Drop Portlet MVC support
This commit also removes the corresponding deprecated Servlet MVC variant and updates DispatcherServlet.properties to point to RequestMappingHandlerMapping/Adapter by default. Issue: SPR-14129
This commit is contained in:
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.web.util.NestedServletException;
|
||||
|
||||
/**
|
||||
* ViewRendererServlet is a bridge servlet, mainly for the Portlet MVC support.
|
||||
*
|
||||
* <p>For usage with Portlets, this Servlet is necessary to force the portlet container
|
||||
* to convert the PortletRequest to a ServletRequest, which it has to do when
|
||||
* including a resource via the PortletRequestDispatcher. This allows for reuse
|
||||
* of the entire Servlet-based View support even in a Portlet environment.
|
||||
*
|
||||
* <p>The actual mapping of the bridge servlet is configurable in the DispatcherPortlet,
|
||||
* via a "viewRendererUrl" property. The default is "/WEB-INF/servlet/view", which is
|
||||
* just available for internal resource dispatching.
|
||||
*
|
||||
* @author William G. Thompson, Jr.
|
||||
* @author John A. Lewis
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ViewRendererServlet extends HttpServlet {
|
||||
|
||||
/**
|
||||
* Request attribute to hold current web application context.
|
||||
* Otherwise only the global web app context is obtainable by tags etc.
|
||||
* @see org.springframework.web.servlet.support.RequestContextUtils#findWebApplicationContext
|
||||
*/
|
||||
public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE;
|
||||
|
||||
/** Name of request attribute that holds the View object */
|
||||
public static final String VIEW_ATTRIBUTE = ViewRendererServlet.class.getName() + ".VIEW";
|
||||
|
||||
/** Name of request attribute that holds the model Map */
|
||||
public static final String MODEL_ATTRIBUTE = ViewRendererServlet.class.getName() + ".MODEL";
|
||||
|
||||
|
||||
@Override
|
||||
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
processRequest(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
processRequest(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process this request, handling exceptions.
|
||||
* The actually event handling is performed by the abstract
|
||||
* {@code renderView()} template method.
|
||||
* @see #renderView
|
||||
*/
|
||||
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
try {
|
||||
renderView(request, response);
|
||||
}
|
||||
catch (ServletException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new NestedServletException("View rendering failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the View instance and model Map to render
|
||||
* and trigger actual rendering.
|
||||
* @param request current HTTP request
|
||||
* @param response current HTTP response
|
||||
* @throws Exception in case of any kind of processing failure
|
||||
* @see org.springframework.web.servlet.View#render
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void renderView(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
View view = (View) request.getAttribute(VIEW_ATTRIBUTE);
|
||||
if (view == null) {
|
||||
throw new ServletException("Could not complete render request: View is null");
|
||||
}
|
||||
Map<String, Object> model = (Map<String, Object>) request.getAttribute(MODEL_ATTRIBUTE);
|
||||
view.render(model, request, response);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,452 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
import org.springframework.core.ExceptionDepthComparator;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.support.WebArgumentResolver;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link org.springframework.web.servlet.HandlerExceptionResolver} interface that handles
|
||||
* exceptions through the {@link ExceptionHandler} annotation.
|
||||
*
|
||||
* <p>This exception resolver is enabled by default in the {@link org.springframework.web.servlet.DispatcherServlet}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @deprecated as of Spring 3.2, in favor of
|
||||
* {@link org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver ExceptionHandlerExceptionResolver}
|
||||
*/
|
||||
@Deprecated
|
||||
public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
|
||||
|
||||
/**
|
||||
* Arbitrary {@link Method} reference, indicating no method found in the cache.
|
||||
*/
|
||||
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis");
|
||||
|
||||
|
||||
private final Map<Class<?>, Map<Class<? extends Throwable>, Method>> exceptionHandlerCache =
|
||||
new ConcurrentHashMap<Class<?>, Map<Class<? extends Throwable>, Method>>(64);
|
||||
|
||||
private WebArgumentResolver[] customArgumentResolvers;
|
||||
|
||||
private HttpMessageConverter<?>[] messageConverters =
|
||||
new HttpMessageConverter<?>[] {new ByteArrayHttpMessageConverter(), new StringHttpMessageConverter(),
|
||||
new SourceHttpMessageConverter<Source>(),
|
||||
new org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter()};
|
||||
|
||||
|
||||
/**
|
||||
* Set a custom ArgumentResolvers to use for special method parameter types.
|
||||
* <p>Such a custom ArgumentResolver will kick in first, having a chance to resolve
|
||||
* an argument value before the standard argument handling kicks in.
|
||||
*/
|
||||
public void setCustomArgumentResolver(WebArgumentResolver argumentResolver) {
|
||||
this.customArgumentResolvers = new WebArgumentResolver[]{argumentResolver};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set one or more custom ArgumentResolvers to use for special method parameter types.
|
||||
* <p>Any such custom ArgumentResolver will kick in first, having a chance to resolve
|
||||
* an argument value before the standard argument handling kicks in.
|
||||
*/
|
||||
public void setCustomArgumentResolvers(WebArgumentResolver[] argumentResolvers) {
|
||||
this.customArgumentResolvers = argumentResolvers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the message body converters to use.
|
||||
* <p>These converters are used to convert from and to HTTP requests and responses.
|
||||
*/
|
||||
public void setMessageConverters(HttpMessageConverter<?>[] messageConverters) {
|
||||
this.messageConverters = messageConverters;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected ModelAndView doResolveException(
|
||||
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
||||
|
||||
if (handler != null) {
|
||||
Method handlerMethod = findBestExceptionHandlerMethod(handler, ex);
|
||||
if (handlerMethod != null) {
|
||||
ServletWebRequest webRequest = new ServletWebRequest(request, response);
|
||||
try {
|
||||
Object[] args = resolveHandlerArguments(handlerMethod, handler, webRequest, ex);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Invoking request handler method: " + handlerMethod);
|
||||
}
|
||||
Object retVal = doInvokeMethod(handlerMethod, handler, args);
|
||||
return getModelAndView(handlerMethod, retVal, webRequest);
|
||||
}
|
||||
catch (Exception invocationEx) {
|
||||
logger.error("Invoking request method resulted in exception : " + handlerMethod, invocationEx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the handler method that matches the thrown exception best.
|
||||
* @param handler the handler object
|
||||
* @param thrownException the exception to be handled
|
||||
* @return the best matching method; or {@code null} if none is found
|
||||
*/
|
||||
private Method findBestExceptionHandlerMethod(Object handler, final Exception thrownException) {
|
||||
final Class<?> handlerType = ClassUtils.getUserClass(handler);
|
||||
final Class<? extends Throwable> thrownExceptionType = thrownException.getClass();
|
||||
Method handlerMethod = null;
|
||||
|
||||
Map<Class<? extends Throwable>, Method> handlers = this.exceptionHandlerCache.get(handlerType);
|
||||
if (handlers != null) {
|
||||
handlerMethod = handlers.get(thrownExceptionType);
|
||||
if (handlerMethod != null) {
|
||||
return (handlerMethod == NO_METHOD_FOUND ? null : handlerMethod);
|
||||
}
|
||||
}
|
||||
else {
|
||||
handlers = new ConcurrentHashMap<Class<? extends Throwable>, Method>(16);
|
||||
this.exceptionHandlerCache.put(handlerType, handlers);
|
||||
}
|
||||
|
||||
final Map<Class<? extends Throwable>, Method> matchedHandlers = new HashMap<Class<? extends Throwable>, Method>();
|
||||
|
||||
ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) {
|
||||
method = ClassUtils.getMostSpecificMethod(method, handlerType);
|
||||
List<Class<? extends Throwable>> handledExceptions = getHandledExceptions(method);
|
||||
for (Class<? extends Throwable> handledException : handledExceptions) {
|
||||
if (handledException.isAssignableFrom(thrownExceptionType)) {
|
||||
if (!matchedHandlers.containsKey(handledException)) {
|
||||
matchedHandlers.put(handledException, method);
|
||||
}
|
||||
else {
|
||||
Method oldMappedMethod = matchedHandlers.get(handledException);
|
||||
if (!oldMappedMethod.equals(method)) {
|
||||
throw new IllegalStateException(
|
||||
"Ambiguous exception handler mapped for " + handledException + "]: {" +
|
||||
oldMappedMethod + ", " + method + "}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
handlerMethod = getBestMatchingMethod(matchedHandlers, thrownException);
|
||||
handlers.put(thrownExceptionType, (handlerMethod == null ? NO_METHOD_FOUND : handlerMethod));
|
||||
return handlerMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the exception classes handled by the given method.
|
||||
* <p>The default implementation looks for exceptions in the annotation,
|
||||
* or - if that annotation element is empty - any exceptions listed in the method parameters if the method
|
||||
* is annotated with {@code @ExceptionHandler}.
|
||||
* @param method the method
|
||||
* @return the handled exceptions
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Class<? extends Throwable>> getHandledExceptions(Method method) {
|
||||
List<Class<? extends Throwable>> result = new ArrayList<Class<? extends Throwable>>();
|
||||
ExceptionHandler exceptionHandler = AnnotationUtils.findAnnotation(method, ExceptionHandler.class);
|
||||
if (exceptionHandler != null) {
|
||||
if (!ObjectUtils.isEmpty(exceptionHandler.value())) {
|
||||
result.addAll(Arrays.asList(exceptionHandler.value()));
|
||||
}
|
||||
else {
|
||||
for (Class<?> param : method.getParameterTypes()) {
|
||||
if (Throwable.class.isAssignableFrom(param)) {
|
||||
result.add((Class<? extends Throwable>) param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the {@link ExceptionDepthComparator} to find the best matching method.
|
||||
* @return the best matching method, or {@code null} if none found
|
||||
*/
|
||||
private Method getBestMatchingMethod(
|
||||
Map<Class<? extends Throwable>, Method> resolverMethods, Exception thrownException) {
|
||||
|
||||
if (resolverMethods.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Class<? extends Throwable> closestMatch =
|
||||
ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException);
|
||||
Method method = resolverMethods.get(closestMatch);
|
||||
return ((method == null) || (NO_METHOD_FOUND == method)) ? null : method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the arguments for the given method. Delegates to {@link #resolveCommonArgument}.
|
||||
*/
|
||||
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
|
||||
NativeWebRequest webRequest, Exception thrownException) throws Exception {
|
||||
|
||||
Class<?>[] paramTypes = handlerMethod.getParameterTypes();
|
||||
Object[] args = new Object[paramTypes.length];
|
||||
Class<?> handlerType = handler.getClass();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
MethodParameter methodParam = new SynthesizingMethodParameter(handlerMethod, i);
|
||||
GenericTypeResolver.resolveParameterType(methodParam, handlerType);
|
||||
Class<?> paramType = methodParam.getParameterType();
|
||||
Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException);
|
||||
if (argValue != WebArgumentResolver.UNRESOLVED) {
|
||||
args[i] = argValue;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unsupported argument [" + paramType.getName() +
|
||||
"] for @ExceptionHandler method: " + handlerMethod);
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves common method arguments. Delegates to registered {@link #setCustomArgumentResolver(WebArgumentResolver)
|
||||
* argumentResolvers} first, then checking {@link #resolveStandardArgument}.
|
||||
* @param methodParameter the method parameter
|
||||
* @param webRequest the request
|
||||
* @param thrownException the exception thrown
|
||||
* @return the argument value, or {@link WebArgumentResolver#UNRESOLVED}
|
||||
*/
|
||||
protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest,
|
||||
Exception thrownException) throws Exception {
|
||||
|
||||
// Invoke custom argument resolvers if present...
|
||||
if (this.customArgumentResolvers != null) {
|
||||
for (WebArgumentResolver argumentResolver : this.customArgumentResolvers) {
|
||||
Object value = argumentResolver.resolveArgument(methodParameter, webRequest);
|
||||
if (value != WebArgumentResolver.UNRESOLVED) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resolution of standard parameter types...
|
||||
Class<?> paramType = methodParameter.getParameterType();
|
||||
Object value = resolveStandardArgument(paramType, webRequest, thrownException);
|
||||
if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) {
|
||||
throw new IllegalStateException(
|
||||
"Standard argument type [" + paramType.getName() + "] resolved to incompatible value of type [" +
|
||||
(value != null ? value.getClass() : null) +
|
||||
"]. Consider declaring the argument type in a less specific fashion.");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves standard method arguments. The default implementation handles {@link NativeWebRequest},
|
||||
* {@link ServletRequest}, {@link ServletResponse}, {@link HttpSession}, {@link Principal},
|
||||
* {@link Locale}, request {@link InputStream}, request {@link Reader}, response {@link OutputStream},
|
||||
* response {@link Writer}, and the given {@code thrownException}.
|
||||
* @param parameterType the method parameter type
|
||||
* @param webRequest the request
|
||||
* @param thrownException the exception thrown
|
||||
* @return the argument value, or {@link WebArgumentResolver#UNRESOLVED}
|
||||
*/
|
||||
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest,
|
||||
Exception thrownException) throws Exception {
|
||||
|
||||
if (parameterType.isInstance(thrownException)) {
|
||||
return thrownException;
|
||||
}
|
||||
else if (WebRequest.class.isAssignableFrom(parameterType)) {
|
||||
return webRequest;
|
||||
}
|
||||
|
||||
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
|
||||
|
||||
if (ServletRequest.class.isAssignableFrom(parameterType)) {
|
||||
return request;
|
||||
}
|
||||
else if (ServletResponse.class.isAssignableFrom(parameterType)) {
|
||||
return response;
|
||||
}
|
||||
else if (HttpSession.class.isAssignableFrom(parameterType)) {
|
||||
return request.getSession();
|
||||
}
|
||||
else if (Principal.class.isAssignableFrom(parameterType)) {
|
||||
return request.getUserPrincipal();
|
||||
}
|
||||
else if (Locale.class == parameterType) {
|
||||
return RequestContextUtils.getLocale(request);
|
||||
}
|
||||
else if (InputStream.class.isAssignableFrom(parameterType)) {
|
||||
return request.getInputStream();
|
||||
}
|
||||
else if (Reader.class.isAssignableFrom(parameterType)) {
|
||||
return request.getReader();
|
||||
}
|
||||
else if (OutputStream.class.isAssignableFrom(parameterType)) {
|
||||
return response.getOutputStream();
|
||||
}
|
||||
else if (Writer.class.isAssignableFrom(parameterType)) {
|
||||
return response.getWriter();
|
||||
}
|
||||
else {
|
||||
return WebArgumentResolver.UNRESOLVED;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Object doInvokeMethod(Method method, Object target, Object[] args) throws Exception {
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
try {
|
||||
return method.invoke(target, args);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
ReflectionUtils.rethrowException(ex.getTargetException());
|
||||
}
|
||||
throw new IllegalStateException("Should never get here");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ModelAndView getModelAndView(Method handlerMethod, Object returnValue, ServletWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
ResponseStatus responseStatus = AnnotatedElementUtils.findMergedAnnotation(handlerMethod, ResponseStatus.class);
|
||||
if (responseStatus != null) {
|
||||
HttpStatus statusCode = responseStatus.code();
|
||||
String reason = responseStatus.reason();
|
||||
if (!StringUtils.hasText(reason)) {
|
||||
webRequest.getResponse().setStatus(statusCode.value());
|
||||
}
|
||||
else {
|
||||
webRequest.getResponse().sendError(statusCode.value(), reason);
|
||||
}
|
||||
}
|
||||
|
||||
if (returnValue != null && AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
|
||||
return handleResponseBody(returnValue, webRequest);
|
||||
}
|
||||
|
||||
if (returnValue instanceof ModelAndView) {
|
||||
return (ModelAndView) returnValue;
|
||||
}
|
||||
else if (returnValue instanceof Model) {
|
||||
return new ModelAndView().addAllObjects(((Model) returnValue).asMap());
|
||||
}
|
||||
else if (returnValue instanceof Map) {
|
||||
return new ModelAndView().addAllObjects((Map<String, Object>) returnValue);
|
||||
}
|
||||
else if (returnValue instanceof View) {
|
||||
return new ModelAndView((View) returnValue);
|
||||
}
|
||||
else if (returnValue instanceof String) {
|
||||
return new ModelAndView((String) returnValue);
|
||||
}
|
||||
else if (returnValue == null) {
|
||||
return new ModelAndView();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Invalid handler method return value: " + returnValue);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes", "resource" })
|
||||
private ModelAndView handleResponseBody(Object returnValue, ServletWebRequest webRequest)
|
||||
throws ServletException, IOException {
|
||||
|
||||
HttpInputMessage inputMessage = new ServletServerHttpRequest(webRequest.getRequest());
|
||||
List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();
|
||||
if (acceptedMediaTypes.isEmpty()) {
|
||||
acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
|
||||
}
|
||||
MediaType.sortByQualityValue(acceptedMediaTypes);
|
||||
HttpOutputMessage outputMessage = new ServletServerHttpResponse(webRequest.getResponse());
|
||||
Class<?> returnValueType = returnValue.getClass();
|
||||
if (this.messageConverters != null) {
|
||||
for (MediaType acceptedMediaType : acceptedMediaTypes) {
|
||||
for (HttpMessageConverter messageConverter : this.messageConverters) {
|
||||
if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
|
||||
messageConverter.write(returnValue, acceptedMediaType, outputMessage);
|
||||
return new ModelAndView();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Could not find HttpMessageConverter that supports return type [" + returnValueType + "] and " +
|
||||
acceptedMediaTypes);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,275 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.ServletRequestBindingException;
|
||||
import org.springframework.web.bind.UnsatisfiedServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link org.springframework.web.servlet.HandlerMapping}
|
||||
* interface that maps handlers based on HTTP paths expressed through the
|
||||
* {@link RequestMapping} annotation at the type or method level.
|
||||
*
|
||||
* <p>Registered by default in {@link org.springframework.web.servlet.DispatcherServlet}
|
||||
* on Java 5+. <b>NOTE:</b> If you define custom HandlerMapping beans in your
|
||||
* DispatcherServlet context, you need to add a DefaultAnnotationHandlerMapping bean
|
||||
* explicitly, since custom HandlerMapping beans replace the default mapping strategies.
|
||||
* Defining a DefaultAnnotationHandlerMapping also allows for registering custom
|
||||
* interceptors:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
|
||||
* <property name="interceptors">
|
||||
* ...
|
||||
* </property>
|
||||
* </bean></pre>
|
||||
*
|
||||
* Annotated controllers are usually marked with the {@link Controller} stereotype
|
||||
* at the type level. This is not strictly necessary when {@link RequestMapping} is
|
||||
* applied at the type level (since such a handler usually implements the
|
||||
* {@link org.springframework.web.servlet.mvc.Controller} interface). However,
|
||||
* {@link Controller} is required for detecting {@link RequestMapping} annotations
|
||||
* at the method level if {@link RequestMapping} is not present at the type level.
|
||||
*
|
||||
* <p><b>NOTE:</b> Method-level mappings are only allowed to narrow the mapping
|
||||
* expressed at the class level (if any). HTTP paths need to uniquely map onto
|
||||
* specific handler beans, with any given HTTP path only allowed to be mapped
|
||||
* onto one specific handler bean (not spread across multiple handler beans).
|
||||
* It is strongly recommended to co-locate related handler methods into the same bean.
|
||||
*
|
||||
* <p>The {@link AnnotationMethodHandlerAdapter} is responsible for processing
|
||||
* annotated handler methods, as mapped by this HandlerMapping. For
|
||||
* {@link RequestMapping} at the type level, specific HandlerAdapters such as
|
||||
* {@link org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter} apply.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.5
|
||||
* @see RequestMapping
|
||||
* @see AnnotationMethodHandlerAdapter
|
||||
* @deprecated as of Spring 3.2, in favor of
|
||||
* {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping RequestMappingHandlerMapping}
|
||||
*/
|
||||
@Deprecated
|
||||
public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping {
|
||||
|
||||
static final String USE_DEFAULT_SUFFIX_PATTERN = DefaultAnnotationHandlerMapping.class.getName() + ".useDefaultSuffixPattern";
|
||||
|
||||
private boolean useDefaultSuffixPattern = true;
|
||||
|
||||
private final Map<Class<?>, RequestMapping> cachedMappings = new HashMap<Class<?>, RequestMapping>();
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to register paths using the default suffix pattern as well:
|
||||
* i.e. whether "/users" should be registered as "/users.*" and "/users/" too.
|
||||
* <p>Default is "true". Turn this convention off if you intend to interpret
|
||||
* your {@code @RequestMapping} paths strictly.
|
||||
* <p>Note that paths which include a ".xxx" suffix or end with "/" already will not be
|
||||
* transformed using the default suffix pattern in any case.
|
||||
*/
|
||||
public void setUseDefaultSuffixPattern(boolean useDefaultSuffixPattern) {
|
||||
this.useDefaultSuffixPattern = useDefaultSuffixPattern;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks for presence of the {@link org.springframework.web.bind.annotation.RequestMapping}
|
||||
* annotation on the handler class and on any of its methods.
|
||||
*/
|
||||
@Override
|
||||
protected String[] determineUrlsForHandler(String beanName) {
|
||||
ApplicationContext context = getApplicationContext();
|
||||
Class<?> handlerType = context.getType(beanName);
|
||||
RequestMapping mapping = context.findAnnotationOnBean(beanName, RequestMapping.class);
|
||||
if (mapping != null) {
|
||||
// @RequestMapping found at type level
|
||||
this.cachedMappings.put(handlerType, mapping);
|
||||
Set<String> urls = new LinkedHashSet<String>();
|
||||
String[] typeLevelPatterns = mapping.value();
|
||||
if (typeLevelPatterns.length > 0) {
|
||||
// @RequestMapping specifies paths at type level
|
||||
String[] methodLevelPatterns = determineUrlsForHandlerMethods(handlerType, true);
|
||||
for (String typeLevelPattern : typeLevelPatterns) {
|
||||
if (!typeLevelPattern.startsWith("/")) {
|
||||
typeLevelPattern = "/" + typeLevelPattern;
|
||||
}
|
||||
boolean hasEmptyMethodLevelMappings = false;
|
||||
for (String methodLevelPattern : methodLevelPatterns) {
|
||||
if (methodLevelPattern == null) {
|
||||
hasEmptyMethodLevelMappings = true;
|
||||
}
|
||||
else {
|
||||
String combinedPattern = getPathMatcher().combine(typeLevelPattern, methodLevelPattern);
|
||||
addUrlsForPath(urls, combinedPattern);
|
||||
}
|
||||
}
|
||||
if (hasEmptyMethodLevelMappings ||
|
||||
org.springframework.web.servlet.mvc.Controller.class.isAssignableFrom(handlerType)) {
|
||||
addUrlsForPath(urls, typeLevelPattern);
|
||||
}
|
||||
}
|
||||
return StringUtils.toStringArray(urls);
|
||||
}
|
||||
else {
|
||||
// actual paths specified by @RequestMapping at method level
|
||||
return determineUrlsForHandlerMethods(handlerType, false);
|
||||
}
|
||||
}
|
||||
else if (AnnotationUtils.findAnnotation(handlerType, Controller.class) != null) {
|
||||
// @RequestMapping to be introspected at method level
|
||||
return determineUrlsForHandlerMethods(handlerType, false);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive URL mappings from the handler's method-level mappings.
|
||||
* @param handlerType the handler type to introspect
|
||||
* @param hasTypeLevelMapping whether the method-level mappings are nested
|
||||
* within a type-level mapping
|
||||
* @return the array of mapped URLs
|
||||
*/
|
||||
protected String[] determineUrlsForHandlerMethods(Class<?> handlerType, final boolean hasTypeLevelMapping) {
|
||||
String[] subclassResult = determineUrlsForHandlerMethods(handlerType);
|
||||
if (subclassResult != null) {
|
||||
return subclassResult;
|
||||
}
|
||||
|
||||
final Set<String> urls = new LinkedHashSet<String>();
|
||||
Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>();
|
||||
handlerTypes.add(handlerType);
|
||||
handlerTypes.addAll(Arrays.asList(handlerType.getInterfaces()));
|
||||
for (Class<?> currentHandlerType : handlerTypes) {
|
||||
ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) {
|
||||
RequestMapping mapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
|
||||
if (mapping != null) {
|
||||
String[] mappedPatterns = mapping.value();
|
||||
if (mappedPatterns.length > 0) {
|
||||
for (String mappedPattern : mappedPatterns) {
|
||||
if (!hasTypeLevelMapping && !mappedPattern.startsWith("/")) {
|
||||
mappedPattern = "/" + mappedPattern;
|
||||
}
|
||||
addUrlsForPath(urls, mappedPattern);
|
||||
}
|
||||
}
|
||||
else if (hasTypeLevelMapping) {
|
||||
// empty method-level RequestMapping
|
||||
urls.add(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, ReflectionUtils.USER_DECLARED_METHODS);
|
||||
}
|
||||
return StringUtils.toStringArray(urls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive URL mappings from the handler's method-level mappings.
|
||||
* @param handlerType the handler type to introspect
|
||||
* @return the array of mapped URLs
|
||||
*/
|
||||
protected String[] determineUrlsForHandlerMethods(Class<?> handlerType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add URLs and/or URL patterns for the given path.
|
||||
* @param urls the Set of URLs for the current bean
|
||||
* @param path the currently introspected path
|
||||
*/
|
||||
protected void addUrlsForPath(Set<String> urls, String path) {
|
||||
urls.add(path);
|
||||
if (this.useDefaultSuffixPattern && path.indexOf('.') == -1 && !path.endsWith("/")) {
|
||||
urls.add(path + ".*");
|
||||
urls.add(path + "/");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate the given annotated handler against the current request.
|
||||
* @see #validateMapping
|
||||
*/
|
||||
@Override
|
||||
protected void validateHandler(Object handler, HttpServletRequest request) throws Exception {
|
||||
RequestMapping mapping = this.cachedMappings.get(handler.getClass());
|
||||
if (mapping == null) {
|
||||
mapping = AnnotationUtils.findAnnotation(handler.getClass(), RequestMapping.class);
|
||||
}
|
||||
if (mapping != null) {
|
||||
validateMapping(mapping, request);
|
||||
}
|
||||
request.setAttribute(USE_DEFAULT_SUFFIX_PATTERN, this.useDefaultSuffixPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the given type-level mapping metadata against the current request,
|
||||
* checking HTTP request method and parameter conditions.
|
||||
* @param mapping the mapping metadata to validate
|
||||
* @param request current HTTP request
|
||||
* @throws Exception if validation failed
|
||||
*/
|
||||
protected void validateMapping(RequestMapping mapping, HttpServletRequest request) throws Exception {
|
||||
RequestMethod[] mappedMethods = mapping.method();
|
||||
if (!ServletAnnotationMappingUtils.checkRequestMethod(mappedMethods, request)) {
|
||||
String[] supportedMethods = new String[mappedMethods.length];
|
||||
for (int i = 0; i < mappedMethods.length; i++) {
|
||||
supportedMethods[i] = mappedMethods[i].name();
|
||||
}
|
||||
throw new HttpRequestMethodNotSupportedException(request.getMethod(), supportedMethods);
|
||||
}
|
||||
|
||||
String[] mappedParams = mapping.params();
|
||||
if (!ServletAnnotationMappingUtils.checkParameters(mappedParams, request)) {
|
||||
throw new UnsatisfiedServletRequestParameterException(mappedParams, request.getParameterMap());
|
||||
}
|
||||
|
||||
String[] mappedHeaders = mapping.headers();
|
||||
if (!ServletAnnotationMappingUtils.checkHeaders(mappedHeaders, request)) {
|
||||
throw new ServletRequestBindingException("Header conditions \"" +
|
||||
StringUtils.arrayToDelimitedString(mappedHeaders, ", ") +
|
||||
"\" not met for actual request");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsTypeLevelMappings() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Helper class for annotation-based request mapping.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.5.2
|
||||
* @deprecated as of Spring 3.2, together with {@link DefaultAnnotationHandlerMapping},
|
||||
* {@link AnnotationMethodHandlerAdapter}, and {@link AnnotationMethodHandlerExceptionResolver}.
|
||||
*/
|
||||
@Deprecated
|
||||
abstract class ServletAnnotationMappingUtils {
|
||||
|
||||
/**
|
||||
* Check whether the given request matches the specified request methods.
|
||||
* @param methods the HTTP request methods to check against
|
||||
* @param request the current HTTP request to check
|
||||
*/
|
||||
public static boolean checkRequestMethod(RequestMethod[] methods, HttpServletRequest request) {
|
||||
String inputMethod = request.getMethod();
|
||||
if (ObjectUtils.isEmpty(methods) && !RequestMethod.OPTIONS.name().equals(inputMethod)) {
|
||||
return true;
|
||||
}
|
||||
for (RequestMethod method : methods) {
|
||||
if (method.name().equals(inputMethod)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given request matches the specified parameter conditions.
|
||||
* @param params the parameter conditions, following
|
||||
* {@link org.springframework.web.bind.annotation.RequestMapping#params() RequestMapping.#params()}
|
||||
* @param request the current HTTP request to check
|
||||
*/
|
||||
public static boolean checkParameters(String[] params, HttpServletRequest request) {
|
||||
if (!ObjectUtils.isEmpty(params)) {
|
||||
for (String param : params) {
|
||||
int separator = param.indexOf('=');
|
||||
if (separator == -1) {
|
||||
if (param.startsWith("!")) {
|
||||
if (WebUtils.hasSubmitParameter(request, param.substring(1))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!WebUtils.hasSubmitParameter(request, param)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
boolean negated = separator > 0 && param.charAt(separator - 1) == '!';
|
||||
String key = !negated ? param.substring(0, separator) : param.substring(0, separator - 1);
|
||||
String value = param.substring(separator + 1);
|
||||
boolean match = value.equals(request.getParameter(key));
|
||||
if (negated) {
|
||||
match = !match;
|
||||
}
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given request matches the specified header conditions.
|
||||
* @param headers the header conditions, following
|
||||
* {@link org.springframework.web.bind.annotation.RequestMapping#headers() RequestMapping.headers()}
|
||||
* @param request the current HTTP request to check
|
||||
*/
|
||||
public static boolean checkHeaders(String[] headers, HttpServletRequest request) {
|
||||
if (!ObjectUtils.isEmpty(headers)) {
|
||||
for (String header : headers) {
|
||||
int separator = header.indexOf('=');
|
||||
if (separator == -1) {
|
||||
if (header.startsWith("!")) {
|
||||
if (request.getHeader(header.substring(1)) != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (request.getHeader(header) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
boolean negated = (separator > 0 && header.charAt(separator - 1) == '!');
|
||||
String key = !negated ? header.substring(0, separator) : header.substring(0, separator - 1);
|
||||
String value = header.substring(separator + 1);
|
||||
if (isMediaTypeHeader(key)) {
|
||||
List<MediaType> requestMediaTypes = MediaType.parseMediaTypes(request.getHeader(key));
|
||||
List<MediaType> valueMediaTypes = MediaType.parseMediaTypes(value);
|
||||
boolean found = false;
|
||||
for (Iterator<MediaType> valIter = valueMediaTypes.iterator(); valIter.hasNext() && !found;) {
|
||||
MediaType valueMediaType = valIter.next();
|
||||
for (Iterator<MediaType> reqIter = requestMediaTypes.iterator();
|
||||
reqIter.hasNext() && !found;) {
|
||||
MediaType requestMediaType = reqIter.next();
|
||||
if (valueMediaType.includes(requestMediaType)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (negated) {
|
||||
found = !found;
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
boolean match = value.equals(request.getHeader(key));
|
||||
if (negated) {
|
||||
match = !match;
|
||||
}
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isMediaTypeHeader(String headerName) {
|
||||
return ("Accept".equalsIgnoreCase(headerName) || "Content-Type".equalsIgnoreCase(headerName));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,13 +7,13 @@ org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i
|
||||
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
|
||||
|
||||
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
|
||||
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
|
||||
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
|
||||
|
||||
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
|
||||
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
|
||||
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
|
||||
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
|
||||
|
||||
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
|
||||
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
|
||||
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
|
||||
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
|
||||
|
||||
|
||||
@@ -88,8 +88,7 @@ public class HandlerMappingIntrospectorTests {
|
||||
List<HandlerMapping> actual = new HandlerMappingIntrospector(cxt).getHandlerMappings();
|
||||
assertEquals(2, actual.size());
|
||||
assertEquals(BeanNameUrlHandlerMapping.class, actual.get(0).getClass());
|
||||
assertEquals(org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping.class,
|
||||
actual.get(1).getClass());
|
||||
assertEquals(RequestMappingHandlerMapping.class, actual.get(1).getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.net.BindException;
|
||||
import java.net.SocketException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@Deprecated
|
||||
public class AnnotationMethodHandlerExceptionResolverTests {
|
||||
|
||||
private final AnnotationMethodHandlerExceptionResolver exceptionResolver = new AnnotationMethodHandlerExceptionResolver();
|
||||
|
||||
private final MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||
|
||||
private final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
|
||||
@Test
|
||||
public void simpleWithIOException() {
|
||||
IOException ex = new IOException();
|
||||
SimpleController controller = new SimpleController();
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, controller, ex);
|
||||
assertNotNull("No ModelAndView returned", mav);
|
||||
assertEquals("Invalid view name returned", "X:IOException", mav.getViewName());
|
||||
assertEquals("Invalid status code returned", 500, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleWithSocketException() {
|
||||
SocketException ex = new SocketException();
|
||||
SimpleController controller = new SimpleController();
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, controller, ex);
|
||||
assertNotNull("No ModelAndView returned", mav);
|
||||
assertEquals("Invalid view name returned", "Y:SocketException", mav.getViewName());
|
||||
assertEquals("Invalid status code returned", 406, response.getStatus());
|
||||
assertEquals("Invalid status reason returned", "This is simply unacceptable!", response.getErrorMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleWithFileNotFoundException() {
|
||||
FileNotFoundException ex = new FileNotFoundException();
|
||||
SimpleController controller = new SimpleController();
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, controller, ex);
|
||||
assertNotNull("No ModelAndView returned", mav);
|
||||
assertEquals("Invalid view name returned", "X:FileNotFoundException", mav.getViewName());
|
||||
assertEquals("Invalid status code returned", 500, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleWithBindException() {
|
||||
BindException ex = new BindException();
|
||||
SimpleController controller = new SimpleController();
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, controller, ex);
|
||||
assertNotNull("No ModelAndView returned", mav);
|
||||
assertEquals("Invalid view name returned", "Y:BindException", mav.getViewName());
|
||||
assertEquals("Invalid status code returned", 406, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleWithNumberFormatExceptionAndComposedResponseStatusAnnotation() {
|
||||
NumberFormatException ex = new NumberFormatException();
|
||||
SimpleController controller = new SimpleController();
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, controller, ex);
|
||||
assertNotNull("No ModelAndView returned", mav);
|
||||
assertEquals("Invalid view name returned", "X:NumberFormatException", mav.getViewName());
|
||||
assertEquals("Invalid status code returned", 400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inherited() {
|
||||
IOException ex = new IOException();
|
||||
InheritedController controller = new InheritedController();
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, controller, ex);
|
||||
assertNotNull("No ModelAndView returned", mav);
|
||||
assertEquals("Invalid view name returned", "GenericError", mav.getViewName());
|
||||
assertEquals("Invalid status code returned", 500, response.getStatus());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void ambiguous() {
|
||||
IllegalArgumentException ex = new IllegalArgumentException();
|
||||
AmbiguousController controller = new AmbiguousController();
|
||||
exceptionResolver.resolveException(request, response, controller, ex);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noModelAndView() throws UnsupportedEncodingException {
|
||||
IllegalArgumentException ex = new IllegalArgumentException();
|
||||
NoMAVReturningController controller = new NoMAVReturningController();
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, controller, ex);
|
||||
assertNotNull("No ModelAndView returned", mav);
|
||||
assertTrue("ModelAndView not empty", mav.isEmpty());
|
||||
assertEquals("Invalid response written", "IllegalArgumentException", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseBody() throws UnsupportedEncodingException {
|
||||
IllegalArgumentException ex = new IllegalArgumentException();
|
||||
ResponseBodyController controller = new ResponseBodyController();
|
||||
request.addHeader("Accept", "text/plain");
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, controller, ex);
|
||||
assertNotNull("No ModelAndView returned", mav);
|
||||
assertTrue("ModelAndView not empty", mav.isEmpty());
|
||||
assertEquals("Invalid response written", "IllegalArgumentException", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-9209
|
||||
|
||||
@Test
|
||||
public void cachingSideEffect() {
|
||||
IllegalArgumentException ex = new IllegalArgumentException();
|
||||
SimpleController controller = new SimpleController();
|
||||
|
||||
ModelAndView mav = exceptionResolver.resolveException(request, response, controller, ex);
|
||||
assertNotNull("No ModelAndView returned", mav);
|
||||
|
||||
mav = exceptionResolver.resolveException(request, response, controller, new NullPointerException());
|
||||
assertNull(mav);
|
||||
}
|
||||
|
||||
@ResponseStatus
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface ComposedResponseStatus {
|
||||
|
||||
@AliasFor(annotation = ResponseStatus.class, attribute = "code")
|
||||
HttpStatus responseStatus() default HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
@Controller
|
||||
private static class SimpleController {
|
||||
|
||||
@ExceptionHandler(IOException.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public String handleIOException(IOException ex, HttpServletRequest request) {
|
||||
return "X:" + ex.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@ExceptionHandler(SocketException.class)
|
||||
@ResponseStatus(code = HttpStatus.NOT_ACCEPTABLE, reason = "This is simply unacceptable!")
|
||||
public String handleSocketException(Exception ex, HttpServletResponse response) {
|
||||
return "Y:" + ex.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public String handleIllegalArgumentException(Exception ex) {
|
||||
return ex.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@ExceptionHandler(NumberFormatException.class)
|
||||
@ComposedResponseStatus(responseStatus = HttpStatus.BAD_REQUEST)
|
||||
public String handleNumberFormatException(NumberFormatException ex) {
|
||||
return "X:" + ex.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class InheritedController extends SimpleController {
|
||||
|
||||
@Override
|
||||
public String handleIOException(IOException ex, HttpServletRequest request) {
|
||||
return "GenericError";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class AmbiguousController {
|
||||
|
||||
@ExceptionHandler({BindException.class, IllegalArgumentException.class})
|
||||
public String handle1(Exception ex, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
return ex.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
public String handle2(IllegalArgumentException ex) {
|
||||
return ex.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class NoMAVReturningController {
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public void handle(Exception ex, Writer writer) throws IOException {
|
||||
writer.write(ex.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class ResponseBodyController {
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseBody
|
||||
public String handle(Exception ex) {
|
||||
return ex.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Deprecated
|
||||
public class RequestSpecificMappingInfoComparatorTests {
|
||||
|
||||
private AnnotationMethodHandlerAdapter.RequestSpecificMappingInfoComparator comparator;
|
||||
|
||||
private AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo emptyInfo;
|
||||
|
||||
private AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo oneMethodInfo;
|
||||
|
||||
private AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo twoMethodsInfo;
|
||||
|
||||
private AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo oneMethodOneParamInfo;
|
||||
|
||||
private AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo oneMethodTwoParamsInfo;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws NoSuchMethodException {
|
||||
comparator = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfoComparator(new MockComparator(), new MockHttpServletRequest());
|
||||
|
||||
emptyInfo = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo(null, new RequestMethod[0],null, null);
|
||||
|
||||
oneMethodInfo = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo(null, new RequestMethod[]{RequestMethod.GET}, null, null);
|
||||
|
||||
twoMethodsInfo = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo(null, new RequestMethod[]{RequestMethod.GET, RequestMethod.POST}, null, null);
|
||||
|
||||
oneMethodOneParamInfo = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo(null, new RequestMethod[]{RequestMethod.GET}, new String[]{"param"}, null);
|
||||
|
||||
oneMethodTwoParamsInfo = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo(null, new RequestMethod[]{RequestMethod.GET}, new String[]{"param1", "param2"}, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sort() {
|
||||
List<AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo> infos = new ArrayList<AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo>();
|
||||
infos.add(emptyInfo);
|
||||
infos.add(oneMethodInfo);
|
||||
infos.add(twoMethodsInfo);
|
||||
infos.add(oneMethodOneParamInfo);
|
||||
infos.add(oneMethodTwoParamsInfo);
|
||||
|
||||
Collections.shuffle(infos);
|
||||
Collections.sort(infos, comparator);
|
||||
|
||||
assertEquals(oneMethodTwoParamsInfo, infos.get(0));
|
||||
assertEquals(oneMethodOneParamInfo, infos.get(1));
|
||||
assertEquals(oneMethodInfo, infos.get(2));
|
||||
assertEquals(twoMethodsInfo, infos.get(3));
|
||||
assertEquals(emptyInfo, infos.get(4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acceptHeaders() {
|
||||
AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo html = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo(null, null, null, new String[] {"accept=text/html"});
|
||||
|
||||
AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo xml = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo(null, null, null, new String[] {"accept=application/xml"});
|
||||
|
||||
AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo none = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo(null, null, null, null);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "application/xml, text/html");
|
||||
comparator = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfoComparator(new MockComparator(), request);
|
||||
|
||||
assertTrue(comparator.compare(html, xml) > 0);
|
||||
assertTrue(comparator.compare(xml, html) < 0);
|
||||
assertTrue(comparator.compare(xml, none) < 0);
|
||||
assertTrue(comparator.compare(none, xml) > 0);
|
||||
assertTrue(comparator.compare(html, none) < 0);
|
||||
assertTrue(comparator.compare(none, html) > 0);
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "application/xml, text/*");
|
||||
comparator = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfoComparator(new MockComparator(), request);
|
||||
|
||||
assertTrue(comparator.compare(html, xml) > 0);
|
||||
assertTrue(comparator.compare(xml, html) < 0);
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "application/pdf");
|
||||
comparator = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfoComparator(new MockComparator(), request);
|
||||
|
||||
assertTrue(comparator.compare(html, xml) == 0);
|
||||
assertTrue(comparator.compare(xml, html) == 0);
|
||||
|
||||
// See SPR-7000
|
||||
request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "text/html;q=0.9,application/xml");
|
||||
comparator = new AnnotationMethodHandlerAdapter.RequestSpecificMappingInfoComparator(new MockComparator(), request);
|
||||
|
||||
assertTrue(comparator.compare(html, xml) > 0);
|
||||
assertTrue(comparator.compare(xml, html) < 0);
|
||||
}
|
||||
|
||||
private static class MockComparator implements Comparator<String> {
|
||||
|
||||
@Override
|
||||
public int compare(String s1, String s2) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@Deprecated
|
||||
public class ServletAnnotationMappingUtilsTests {
|
||||
|
||||
@Test
|
||||
public void checkRequestMethodMatch() {
|
||||
RequestMethod[] methods = new RequestMethod[]{RequestMethod.GET, RequestMethod.POST};
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
boolean result = ServletAnnotationMappingUtils.checkRequestMethod(methods, request);
|
||||
assertTrue("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkRequestMethodNoMatch() {
|
||||
RequestMethod[] methods = new RequestMethod[]{RequestMethod.GET, RequestMethod.POST};
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/");
|
||||
boolean result = ServletAnnotationMappingUtils.checkRequestMethod(methods, request);
|
||||
assertFalse("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkParametersSimpleMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addParameter("param1", "value1");
|
||||
String[] params = new String[]{"param1", "!param2"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkParameters(params, request);
|
||||
assertTrue("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkParametersSimpleNoMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addParameter("param1", "value1");
|
||||
request.addParameter("param2", "value2");
|
||||
String[] params = new String[]{"param1", "!param2"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkParameters(params, request);
|
||||
assertFalse("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkParametersKeyValueMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addParameter("param1", "value1");
|
||||
String[] params = new String[]{"param1=value1"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkParameters(params, request);
|
||||
assertTrue("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkParametersKeyValueNoMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addParameter("param1", "value1");
|
||||
String[] params = new String[]{"param1=foo"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkParameters(params, request);
|
||||
assertFalse("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkParametersNegatedValueMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addParameter("param1", "value1");
|
||||
String[] params = new String[]{"param1!=foo"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkParameters(params, request);
|
||||
assertTrue("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkParametersNegatedValueNoMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addParameter("param1", "foo");
|
||||
String[] params = new String[]{"param1!=foo"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkParameters(params, request);
|
||||
assertFalse("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkParametersCompositeNoMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addParameter("param1", "foo");
|
||||
request.addParameter("param2", "foo");
|
||||
String[] params = new String[]{"param1=foo", "param2!=foo"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkParameters(params, request);
|
||||
assertFalse("[SPR-8059] Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkHeadersSimpleMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("header1", "value1");
|
||||
String[] headers = new String[]{"header1", "!header2"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkHeaders(headers, request);
|
||||
assertTrue("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkHeadersSimpleNoMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("header1", "value1");
|
||||
request.addHeader("header2", "value2");
|
||||
String[] headers = new String[]{"header1", "!header2"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkHeaders(headers, request);
|
||||
assertFalse("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkHeadersKeyValueMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("header1", "value1");
|
||||
String[] headers = new String[]{"header1=value1"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkHeaders(headers, request);
|
||||
assertTrue("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkHeadersKeyValueNoMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("header1", "value1");
|
||||
String[] headers = new String[]{"header1=foo"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkHeaders(headers, request);
|
||||
assertFalse("Invalid request method result", result);
|
||||
}
|
||||
|
||||
// SPR-8862
|
||||
|
||||
@Test
|
||||
public void checkHeadersKeyValueNoMatchWithNegation() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("Accept-Encoding", "gzip");
|
||||
String[] headers1 = new String[]{"Accept-Encoding!=gzip"};
|
||||
String[] headers2 = new String[]{"Accept-Encoding=gzip"};
|
||||
assertFalse(ServletAnnotationMappingUtils.checkHeaders(headers1, request));
|
||||
assertTrue(ServletAnnotationMappingUtils.checkHeaders(headers2, request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkHeadersAcceptMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("Accept", "application/pdf, text/html");
|
||||
String[] headers = new String[]{"accept=text/html, application/*"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkHeaders(headers, request);
|
||||
assertTrue("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkHeadersAcceptNoMatch() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("Accept", "application/pdf, text/html");
|
||||
String[] headers = new String[]{"accept=audio/basic, application/xml"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkHeaders(headers, request);
|
||||
assertFalse("Invalid request method result", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkHeadersAcceptNoMatchWithNegation() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||
request.addHeader("Accept", "application/pdf");
|
||||
String[] headers = new String[]{"accept!=application/pdf"};
|
||||
boolean result = ServletAnnotationMappingUtils.checkHeaders(headers, request);
|
||||
assertFalse("Invalid request method result", result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@Controller
|
||||
public class Spr7766Controller {
|
||||
|
||||
@RequestMapping("/colors")
|
||||
public void handler(@RequestParam List<Color> colors) {
|
||||
Assert.isTrue(colors.size() == 2);
|
||||
Assert.isTrue(colors.get(0).equals(Color.WHITE));
|
||||
Assert.isTrue(colors.get(1).equals(Color.BLACK));
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
|
||||
public class Spr7766Tests {
|
||||
|
||||
@Test
|
||||
@Deprecated
|
||||
public void test() throws Exception {
|
||||
AnnotationMethodHandlerAdapter adapter = new AnnotationMethodHandlerAdapter();
|
||||
ConfigurableWebBindingInitializer binder = new ConfigurableWebBindingInitializer();
|
||||
GenericConversionService service = new DefaultConversionService();
|
||||
service.addConverter(new ColorConverter());
|
||||
binder.setConversionService(service);
|
||||
adapter.setWebBindingInitializer(binder);
|
||||
Spr7766Controller controller = new Spr7766Controller();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/colors");
|
||||
request.setPathInfo("/colors");
|
||||
request.addParameter("colors", "#ffffff,000000");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
public class ColorConverter implements Converter<String, Color> {
|
||||
@Override
|
||||
public Color convert(String source) { if (!source.startsWith("#")) source = "#" + source; return Color.decode(source); }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@Deprecated
|
||||
public class Spr7839Tests {
|
||||
|
||||
AnnotationMethodHandlerAdapter adapter = new AnnotationMethodHandlerAdapter();
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
Spr7839Controller controller = new Spr7839Controller();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ConfigurableWebBindingInitializer binder = new ConfigurableWebBindingInitializer();
|
||||
GenericConversionService service = new DefaultConversionService();
|
||||
service.addConverter(new Converter<String, NestedBean>() {
|
||||
@Override
|
||||
public NestedBean convert(String source) {
|
||||
return new NestedBean(source);
|
||||
}
|
||||
});
|
||||
binder.setConversionService(service);
|
||||
adapter.setWebBindingInitializer(binder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void object() throws Exception {
|
||||
request.setRequestURI("/nested");
|
||||
request.addParameter("nested", "Nested");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void list() throws Exception {
|
||||
request.setRequestURI("/nested/list");
|
||||
request.addParameter("nested.list", "Nested1,Nested2");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listElement() throws Exception {
|
||||
request.setRequestURI("/nested/listElement");
|
||||
request.addParameter("nested.list[0]", "Nested");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listElementAutogrowObject() throws Exception {
|
||||
request.setRequestURI("/nested/listElement");
|
||||
request.addParameter("nested.list[0].foo", "Nested");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void listElementAutogrowOutOfMemory() throws Exception {
|
||||
request.setRequestURI("/nested/listElement");
|
||||
request.addParameter("nested.list[1000000000].foo", "Nested");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listOfLists() throws Exception {
|
||||
request.setRequestURI("/nested/listOfLists");
|
||||
request.addParameter("nested.listOfLists[0]", "Nested1,Nested2");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listOfListsElement() throws Exception {
|
||||
request.setRequestURI("/nested/listOfListsElement");
|
||||
request.addParameter("nested.listOfLists[0][0]", "Nested");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listOfListsElementAutogrowObject() throws Exception {
|
||||
request.setRequestURI("/nested/listOfListsElement");
|
||||
request.addParameter("nested.listOfLists[0][0].foo", "Nested");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void arrayOfLists() throws Exception {
|
||||
// TODO TypeDescriptor not capable of accessing nested element type for arrays
|
||||
request.setRequestURI("/nested/arrayOfLists");
|
||||
request.addParameter("nested.arrayOfLists[0]", "Nested1,Nested2");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void map() throws Exception {
|
||||
request.setRequestURI("/nested/map");
|
||||
request.addParameter("nested.map['apple'].foo", "bar");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapOfLists() throws Exception {
|
||||
request.setRequestURI("/nested/mapOfLists");
|
||||
request.addParameter("nested.mapOfLists['apples'][0]", "1");
|
||||
adapter.handle(request, response, controller);
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class Spr7839Controller {
|
||||
|
||||
@RequestMapping("/nested")
|
||||
public void handler(JavaBean bean) {
|
||||
assertEquals("Nested", bean.nested.foo);
|
||||
}
|
||||
|
||||
@RequestMapping("/nested/list")
|
||||
public void handlerList(JavaBean bean) {
|
||||
assertEquals("Nested2", bean.nested.list.get(1).foo);
|
||||
}
|
||||
|
||||
@RequestMapping("/nested/listElement")
|
||||
public void handlerListElement(JavaBean bean) {
|
||||
assertEquals("Nested", bean.nested.list.get(0).foo);
|
||||
}
|
||||
|
||||
@RequestMapping("/nested/listOfLists")
|
||||
public void handlerListOfLists(JavaBean bean) {
|
||||
assertEquals("Nested2", bean.nested.listOfLists.get(0).get(1).foo);
|
||||
}
|
||||
|
||||
@RequestMapping("/nested/listOfListsElement")
|
||||
public void handlerListOfListsElement(JavaBean bean) {
|
||||
assertEquals("Nested", bean.nested.listOfLists.get(0).get(0).foo);
|
||||
}
|
||||
|
||||
@RequestMapping("/nested/arrayOfLists")
|
||||
public void handlerArrayOfLists(JavaBean bean) {
|
||||
assertEquals("Nested2", bean.nested.arrayOfLists[0].get(1).foo);
|
||||
}
|
||||
|
||||
@RequestMapping("/nested/map")
|
||||
public void handlerMap(JavaBean bean) {
|
||||
assertEquals("bar", bean.nested.map.get("apple").foo);
|
||||
}
|
||||
|
||||
@RequestMapping("/nested/mapOfLists")
|
||||
public void handlerMapOfLists(JavaBean bean) {
|
||||
assertEquals(new Integer(1), bean.nested.mapOfLists.get("apples").get(0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class JavaBean {
|
||||
|
||||
private NestedBean nested;
|
||||
|
||||
public NestedBean getNested() {
|
||||
return nested;
|
||||
}
|
||||
|
||||
public void setNested(NestedBean nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static class NestedBean {
|
||||
|
||||
private String foo;
|
||||
|
||||
private List<NestedBean> list;
|
||||
|
||||
private List<List<NestedBean>> listOfLists;
|
||||
|
||||
private List<NestedBean>[] arrayOfLists;
|
||||
|
||||
private Map<String, NestedBean> map;
|
||||
|
||||
private Map<String, List<Integer>> mapOfLists;
|
||||
|
||||
public NestedBean() {
|
||||
|
||||
}
|
||||
|
||||
public NestedBean(String foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public String getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(String foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public List<NestedBean> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List<NestedBean> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public Map<String, NestedBean> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public void setMap(Map<String, NestedBean> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public List<List<NestedBean>> getListOfLists() {
|
||||
return listOfLists;
|
||||
}
|
||||
|
||||
public void setListOfLists(List<List<NestedBean>> listOfLists) {
|
||||
this.listOfLists = listOfLists;
|
||||
}
|
||||
|
||||
public List<NestedBean>[] getArrayOfLists() {
|
||||
return arrayOfLists;
|
||||
}
|
||||
|
||||
public void setArrayOfLists(List<NestedBean>[] arrayOfLists) {
|
||||
this.arrayOfLists = arrayOfLists;
|
||||
}
|
||||
|
||||
public Map<String, List<Integer>> getMapOfLists() {
|
||||
return mapOfLists;
|
||||
}
|
||||
|
||||
public void setMapOfLists(Map<String, List<Integer>> mapOfLists) {
|
||||
this.mapOfLists = mapOfLists;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,713 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.servlet.mvc.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.test.MockServletConfig;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class UriTemplateServletAnnotationControllerTests {
|
||||
|
||||
private DispatcherServlet servlet;
|
||||
|
||||
@Test
|
||||
public void simple() throws Exception {
|
||||
initServlet(SimpleUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiple() throws Exception {
|
||||
initServlet(MultipleUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21-other");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-42-21-other", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void binding() throws Exception {
|
||||
initServlet(BindingUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-11-18");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-foo-bar");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals(400, response.getStatus());
|
||||
|
||||
initServlet(NonBindingUriTemplateController.class);
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42/dates/2008-foo-bar");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals(500, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
public void doubles() throws Exception {
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
|
||||
throws BeansException {
|
||||
GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(DoubleController.class));
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(DefaultAnnotationHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useDefaultSuffixPattern", false);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
};
|
||||
servlet.init(new MockServletConfig());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/lat/1.2/long/3.4");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
|
||||
assertEquals("latitude-1.2-longitude-3.4", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ambiguous() throws Exception {
|
||||
initServlet(AmbiguousUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/new");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("specific", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void relative() throws Exception {
|
||||
initServlet(RelativePathUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-42-21", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21.html");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-42-21", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extension() throws Exception {
|
||||
initServlet(SimpleUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42.xml");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeConversionError() throws Exception {
|
||||
initServlet(SimpleUriTemplateController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.xml");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("Invalid response status code", HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void explicitSubPath() throws Exception {
|
||||
initServlet(ExplicitSubPathController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void implicitSubPath() throws Exception {
|
||||
initServlet(ImplicitSubPathController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void crud() throws Exception {
|
||||
initServlet(CrudController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("list", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("list", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/hotels");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("create", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("show-42", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels/42/");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("show-42", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("PUT", "/hotels/42");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("createOrUpdate-42", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("DELETE", "/hotels/42");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("remove-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodNotSupported() throws Exception {
|
||||
initServlet(MethodNotAllowedController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/1");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/hotels/1");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals(405, response.getStatus());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/hotels");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/hotels");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals(405, response.getStatus());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiPaths() throws Exception {
|
||||
initServlet(MultiPathController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/category/page/5");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("handle4-page-5", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/category/page/5.html");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("handle4-page-5", response.getContentAsString());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private void initServlet(final Class<?> controllerclass) throws ServletException {
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
|
||||
throws BeansException {
|
||||
GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(controllerclass));
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
};
|
||||
servlet.init(new MockServletConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
public void noDefaultSuffixPattern() throws Exception {
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
|
||||
throws BeansException {
|
||||
GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(ImplicitSubPathController.class));
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(DefaultAnnotationHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useDefaultSuffixPattern", false);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
};
|
||||
servlet.init(new MockServletConfig());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/hotel.with.dot");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-hotel.with.dot", response.getContentAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customRegex() throws Exception {
|
||||
initServlet(CustomRegexController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("test-42", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-6640
|
||||
@Test
|
||||
public void menuTree() throws Exception {
|
||||
initServlet(MenuTreeController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/book/menu/type/M5");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("M5", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-6876
|
||||
@Test
|
||||
public void variableNames() throws Exception {
|
||||
initServlet(VariableNamesController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("foo-foo", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("DELETE", "/test/bar");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("bar-bar", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-8543
|
||||
@Test
|
||||
public void variableNamesWithUrlExtension() throws Exception {
|
||||
initServlet(VariableNamesController.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo.json");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("foo-foo", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-9333
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
public void suppressDefaultSuffixPattern() throws Exception {
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
|
||||
throws BeansException {
|
||||
GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(VariableNamesController.class));
|
||||
RootBeanDefinition mappingDef = new RootBeanDefinition(DefaultAnnotationHandlerMapping.class);
|
||||
mappingDef.getPropertyValues().add("useDefaultSuffixPattern", false);
|
||||
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
};
|
||||
servlet.init(new MockServletConfig());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/jsmith@mail.com");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("foo-jsmith@mail.com", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-6906
|
||||
@Test
|
||||
@SuppressWarnings("serial")
|
||||
public void controllerClassName() throws Exception {
|
||||
servlet = new DispatcherServlet() {
|
||||
@Override
|
||||
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
|
||||
throws BeansException {
|
||||
GenericWebApplicationContext wac = new GenericWebApplicationContext();
|
||||
wac.registerBeanDefinition("controller", new RootBeanDefinition(ControllerClassNameController.class));
|
||||
RootBeanDefinition mapping = new RootBeanDefinition(ControllerClassNameHandlerMapping.class);
|
||||
mapping.getPropertyValues().add("excludedPackages", null);
|
||||
wac.registerBeanDefinition("handlerMapping", mapping);
|
||||
wac.refresh();
|
||||
return wac;
|
||||
}
|
||||
};
|
||||
servlet.init(new MockServletConfig());
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/controllerclassname/bar");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("plain-bar", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/controllerclassname/bar.pdf");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("pdf-bar", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/controllerclassname/bar.do");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("plain-bar", response.getContentAsString());
|
||||
}
|
||||
|
||||
// SPR-6978
|
||||
@Test
|
||||
public void doIt() throws Exception {
|
||||
initServlet(Spr6978Controller.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/100");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("loadEntity:foo:100", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/foo/100");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("publish:foo:100", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("GET", "/module/100");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("loadModule:100", response.getContentAsString());
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/module/100");
|
||||
response = new MockHttpServletResponse();
|
||||
servlet.service(request, response);
|
||||
assertEquals("publish:module:100", response.getContentAsString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Controllers
|
||||
|
||||
@Controller
|
||||
public static class SimpleUriTemplateController {
|
||||
|
||||
@RequestMapping("/{root}")
|
||||
public void handle(@PathVariable("root") int root, Writer writer) throws IOException {
|
||||
assertEquals("Invalid path variable value", 42, root);
|
||||
writer.write("test-" + root);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class MultipleUriTemplateController {
|
||||
|
||||
@RequestMapping("/hotels/{hotel}/bookings/{booking}-{other}")
|
||||
public void handle(@PathVariable("hotel") String hotel,
|
||||
@PathVariable int booking,
|
||||
@PathVariable String other,
|
||||
Writer writer) throws IOException {
|
||||
assertEquals("Invalid path variable value", "42", hotel);
|
||||
assertEquals("Invalid path variable value", 21, booking);
|
||||
writer.write("test-" + hotel + "-" + booking + "-" + other);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class BindingUriTemplateController {
|
||||
|
||||
@InitBinder
|
||||
public void initBinder(WebDataBinder binder, @PathVariable("hotel") String hotel) {
|
||||
assertEquals("Invalid path variable value", "42", hotel);
|
||||
binder.initBeanPropertyAccess();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
dateFormat.setLenient(false);
|
||||
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
|
||||
}
|
||||
|
||||
@RequestMapping("/hotels/{hotel}/dates/{date}")
|
||||
public void handle(@PathVariable("hotel") String hotel, @PathVariable Date date, Writer writer)
|
||||
throws IOException {
|
||||
assertEquals("Invalid path variable value", "42", hotel);
|
||||
assertEquals("Invalid path variable value", new GregorianCalendar(2008, 10, 18).getTime(), date);
|
||||
writer.write("test-" + hotel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class NonBindingUriTemplateController {
|
||||
|
||||
@RequestMapping("/hotels/{hotel}/dates/{date}")
|
||||
public void handle(@PathVariable("hotel") String hotel, @PathVariable Date date, Writer writer)
|
||||
throws IOException {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/hotels/{hotel}")
|
||||
public static class RelativePathUriTemplateController {
|
||||
|
||||
@RequestMapping("bookings/{booking}")
|
||||
public void handle(@PathVariable("hotel") String hotel, @PathVariable int booking, Writer writer)
|
||||
throws IOException {
|
||||
assertEquals("Invalid path variable value", "42", hotel);
|
||||
assertEquals("Invalid path variable value", 21, booking);
|
||||
writer.write("test-" + hotel + "-" + booking);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/hotels")
|
||||
public static class AmbiguousUriTemplateController {
|
||||
|
||||
@RequestMapping("/{hotel}")
|
||||
public void handleVars(@PathVariable("hotel") String hotel, Writer writer) throws IOException {
|
||||
assertEquals("Invalid path variable value", "42", hotel);
|
||||
writer.write("variables");
|
||||
}
|
||||
|
||||
@RequestMapping("/new")
|
||||
public void handleSpecific(Writer writer) throws IOException {
|
||||
writer.write("specific");
|
||||
}
|
||||
|
||||
@RequestMapping("/*")
|
||||
public void handleWildCard(Writer writer) throws IOException {
|
||||
writer.write("wildcard");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/hotels/*")
|
||||
public static class ExplicitSubPathController {
|
||||
|
||||
@RequestMapping("{hotel}")
|
||||
public void handleHotel(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("test-" + hotel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("hotels")
|
||||
public static class ImplicitSubPathController {
|
||||
|
||||
@RequestMapping("{hotel}")
|
||||
public void handleHotel(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("test-" + hotel);
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class CustomRegexController {
|
||||
|
||||
@RequestMapping("/{root:\\d+}")
|
||||
public void handle(@PathVariable("root") int root, Writer writer) throws IOException {
|
||||
assertEquals("Invalid path variable value", 42, root);
|
||||
writer.write("test-" + root);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class DoubleController {
|
||||
|
||||
@RequestMapping("/lat/{latitude}/long/{longitude}")
|
||||
public void testLatLong(@PathVariable Double latitude, @PathVariable Double longitude, Writer writer)
|
||||
throws IOException {
|
||||
writer.write("latitude-" + latitude + "-longitude-" + longitude);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("hotels")
|
||||
public static class CrudController {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public void list(Writer writer) throws IOException {
|
||||
writer.write("list");
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
public void create(Writer writer) throws IOException {
|
||||
writer.write("create");
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{hotel}", method = RequestMethod.GET)
|
||||
public void show(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("show-" + hotel);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "{hotel}", method = RequestMethod.PUT)
|
||||
public void createOrUpdate(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("createOrUpdate-" + hotel);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "{hotel}", method = RequestMethod.DELETE)
|
||||
public void remove(@PathVariable String hotel, Writer writer) throws IOException {
|
||||
writer.write("remove-" + hotel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/hotels")
|
||||
public static class MethodNotAllowedController {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public void list(Writer writer) {
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "{hotelId}")
|
||||
public void show(@PathVariable long hotelId, Writer writer) {
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.PUT, value = "{hotelId}")
|
||||
public void createOrUpdate(@PathVariable long hotelId, Writer writer) {
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{hotelId}")
|
||||
public void remove(@PathVariable long hotelId, Writer writer) {
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/category")
|
||||
public static class MultiPathController {
|
||||
|
||||
@RequestMapping(value = {"/{category}/page/{page}", "/**/{category}/page/{page}"})
|
||||
public void category(@PathVariable String category, @PathVariable int page, Writer writer) throws IOException {
|
||||
writer.write("handle1-");
|
||||
writer.write("category-" + category);
|
||||
writer.write("page-" + page);
|
||||
}
|
||||
|
||||
@RequestMapping(value = {"/{category}", "/**/{category}"})
|
||||
public void category(@PathVariable String category, Writer writer) throws IOException {
|
||||
writer.write("handle2-");
|
||||
writer.write("category-" + category);
|
||||
}
|
||||
|
||||
@RequestMapping(value = {""})
|
||||
public void category(Writer writer) throws IOException {
|
||||
writer.write("handle3");
|
||||
}
|
||||
|
||||
@RequestMapping(value = {"/page/{page}"})
|
||||
public void category(@PathVariable int page, Writer writer) throws IOException {
|
||||
writer.write("handle4-");
|
||||
writer.write("page-" + page);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RequestMapping("/*/menu/**")
|
||||
public static class MenuTreeController {
|
||||
|
||||
@RequestMapping("type/{var}")
|
||||
public void getFirstLevelFunctionNodes(@PathVariable("var") String var, Writer writer) throws IOException {
|
||||
writer.write(var);
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/test")
|
||||
public static class VariableNamesController {
|
||||
|
||||
@RequestMapping(value = "/{foo}", method=RequestMethod.GET)
|
||||
public void foo(@PathVariable String foo, Writer writer) throws IOException {
|
||||
writer.write("foo-" + foo);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{bar}", method=RequestMethod.DELETE)
|
||||
public void bar(@PathVariable String bar, Writer writer) throws IOException {
|
||||
writer.write("bar-" + bar);
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
public static class Spr6978Controller {
|
||||
|
||||
@RequestMapping(value = "/{type}/{id}", method = RequestMethod.GET)
|
||||
public void loadEntity(@PathVariable final String type, @PathVariable final long id, Writer writer)
|
||||
throws IOException {
|
||||
writer.write("loadEntity:" + type + ":" + id);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/module/{id}", method = RequestMethod.GET)
|
||||
public void loadModule(@PathVariable final long id, Writer writer) throws IOException {
|
||||
writer.write("loadModule:" + id);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{type}/{id}", method = RequestMethod.POST)
|
||||
public void publish(@PathVariable final String type, @PathVariable final long id, Writer writer)
|
||||
throws IOException {
|
||||
writer.write("publish:" + type + ":" + id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -49,14 +49,11 @@ import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
import org.springframework.web.servlet.mvc.annotation.UriTemplateServletAnnotationControllerTests;
|
||||
import org.springframework.web.servlet.view.AbstractView;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* The origin of this test class is {@link UriTemplateServletAnnotationControllerTests}.
|
||||
*
|
||||
* Tests in this class run against the {@link HandlerMethod} infrastructure:
|
||||
* <ul>
|
||||
* <li>RequestMappingHandlerMapping
|
||||
|
||||
Reference in New Issue
Block a user