提交 04fa5d4b 编写于 作者: A Arjen Poutsma

SPR-6093 - MVC Annotation Inheritance

上级 d8245c80
......@@ -341,7 +341,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (handler.getClass().getAnnotation(SessionAttributes.class) != null) {
if (AnnotationUtils.findAnnotation(handler.getClass(), SessionAttributes.class) != null) {
// Always prevent caching in case of session attribute management.
checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
// Prepare cached set of session attributes names.
......@@ -707,8 +707,8 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
ExtendedModelMap implicitModel,
ServletWebRequest webRequest) throws Exception {
if (handlerMethod.isAnnotationPresent(ResponseStatus.class)) {
ResponseStatus responseStatus = handlerMethod.getAnnotation(ResponseStatus.class);
ResponseStatus responseStatus = AnnotationUtils.findAnnotation(handlerMethod, ResponseStatus.class);
if (responseStatus != null) {
HttpServletResponse response = webRequest.getResponse();
response.setStatus(responseStatus.value().value());
responseArgumentUsed = true;
......@@ -725,8 +725,8 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
}
if (returnValue != null && handlerMethod.isAnnotationPresent(ResponseBody.class)) {
handleRequestBody(returnValue, webRequest);
if (returnValue != null && AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
handleResponseBody(returnValue, webRequest);
}
if (returnValue instanceof ModelAndView) {
......@@ -740,7 +740,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
else if (returnValue instanceof View) {
return new ModelAndView((View) returnValue).addAllObjects(implicitModel);
}
else if (handlerMethod.isAnnotationPresent(ModelAttribute.class)) {
else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) {
addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
return new ModelAndView().addAllObjects(implicitModel);
}
......@@ -771,7 +771,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator implemen
}
@SuppressWarnings("unchecked")
private void handleRequestBody(Object returnValue, ServletWebRequest webRequest) throws ServletException, IOException {
private void handleResponseBody(Object returnValue, ServletWebRequest webRequest) throws ServletException, IOException {
HttpInputMessage inputMessage = new ServletServerHttpRequest(webRequest.getRequest());
List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();
HttpOutputMessage outputMessage = new ServletServerHttpResponse(webRequest.getResponse());
......
......@@ -39,6 +39,7 @@ import javax.servlet.http.HttpSession;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.ui.Model;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
......@@ -56,8 +57,8 @@ 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}.
* 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
* @since 3.0
......@@ -132,23 +133,25 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
}
else {
Method oldMappedMethod = resolverMethods.get(handledException);
if (!oldMappedMethod.equals(method)) {
throw new IllegalStateException(
"Ambiguous exception handler mapped for " + handledException + "]: {" +
oldMappedMethod + ", " + method + "}.");
}
}
}
}
}
});
return getBestMatchingMethod(thrownException, resolverMethods);
}
/**
* Returns all the exception classes handled by the given method.
* <p>Default implementation looks for exceptions in the {@linkplain ExceptionHandler#value() annotation}, or -
* if that annotation element is empty - any exceptions listed in the method parameters if the method is annotated
* with {@code @ExceptionHandler}.
* Returns all the exception classes handled by the given method. <p>Default implementation looks for exceptions in the
* {@linkplain ExceptionHandler#value() 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
......@@ -156,7 +159,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
@SuppressWarnings("unchecked")
protected List<Class<? extends Throwable>> getHandledExceptions(Method method) {
List<Class<? extends Throwable>> result = new ArrayList<Class<? extends Throwable>>();
ExceptionHandler exceptionHandler = method.getAnnotation(ExceptionHandler.class);
ExceptionHandler exceptionHandler = AnnotationUtils.findAnnotation(method, ExceptionHandler.class);
if (exceptionHandler != null) {
if (!ObjectUtils.isEmpty(exceptionHandler.value())) {
result.addAll(Arrays.asList(exceptionHandler.value()));
......@@ -172,9 +175,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
return result;
}
/**
* Returns the best matching method. Uses the {@link DepthComparator}.
*/
/** Returns the best matching method. Uses the {@link DepthComparator}. */
private Method getBestMatchingMethod(Exception thrownException,
Map<Class<? extends Throwable>, Method> resolverMethods) {
if (!resolverMethods.isEmpty()) {
......@@ -189,9 +190,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
}
}
/**
* Resolves the arguments for the given method. Delegates to {@link #resolveCommonArgument}.
*/
/** Resolves the arguments for the given method. Delegates to {@link #resolveCommonArgument}. */
private Object[] resolveHandlerArguments(Method handlerMethod,
Object handler,
NativeWebRequest webRequest,
......@@ -222,8 +221,8 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
}
/**
* Resolves common method arguments. Delegates to registered {@link #setCustomArgumentResolver(WebArgumentResolver) argumentResolvers} first,
* then checking {@link #resolveStandardArgument}.
* 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
......@@ -256,10 +255,10 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
}
/**
* Resolves standard method arguments. 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}.
* Resolves standard method arguments. 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
......@@ -327,8 +326,8 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
private ModelAndView getModelAndView(Method handlerMethod, Object returnValue, ServletWebRequest webRequest)
throws Exception {
if (handlerMethod.isAnnotationPresent(ResponseStatus.class)) {
ResponseStatus responseStatus = handlerMethod.getAnnotation(ResponseStatus.class);
ResponseStatus responseStatus = AnnotationUtils.findAnnotation(handlerMethod, ResponseStatus.class);
if (responseStatus != null) {
HttpServletResponse response = webRequest.getResponse();
response.setStatus(responseStatus.value().value());
}
......@@ -355,9 +354,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
}
}
/**
* Comparator capable of sorting exceptions based on their depth from the thrown exception type.
*/
/** Comparator capable of sorting exceptions based on their depth from the thrown exception type. */
private static class DepthComparator implements Comparator<Class<? extends Throwable>> {
private final Class<? extends Throwable> handlerExceptionType;
......
......@@ -65,6 +65,16 @@ public class AnnotationMethodHandlerExceptionResolverTests {
assertEquals("Invalid status code returned", 406, 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();
......@@ -86,6 +96,7 @@ public class AnnotationMethodHandlerExceptionResolverTests {
private static class SimpleController {
@ExceptionHandler(IOException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleIOException(IOException ex, HttpServletRequest request) {
return ClassUtils.getShortName(ex.getClass());
}
......@@ -103,6 +114,15 @@ public class AnnotationMethodHandlerExceptionResolverTests {
}
@Controller
private static class InheritedController extends SimpleController
{
@Override
public String handleIOException(IOException ex, HttpServletRequest request) {
return "GenericError";
}
}
@Controller
private static class AmbiguousController {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册