|
|
@ -84,10 +84,10 @@ import org.springframework.web.servlet.support.RequestContextUtils; |
|
|
|
public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExceptionResolver { |
|
|
|
public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExceptionResolver { |
|
|
|
|
|
|
|
|
|
|
|
// dummy method placeholder
|
|
|
|
// dummy method placeholder
|
|
|
|
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", null); |
|
|
|
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", (Class<?>[]) null); |
|
|
|
|
|
|
|
|
|
|
|
private final Map<Class<?>, Map<Class<? extends Throwable>, Method>> exceptionHandlerCache = |
|
|
|
private final Map<Class<?>, Map<Class<? extends Throwable>, Method>> exceptionHandlerCache = |
|
|
|
new ConcurrentHashMap<Class<?>, Map<Class<? extends Throwable>, Method>>(); |
|
|
|
new ConcurrentHashMap<Class<?>, Map<Class<? extends Throwable>, Method>>(); |
|
|
|
|
|
|
|
|
|
|
|
private WebArgumentResolver[] customArgumentResolvers; |
|
|
|
private WebArgumentResolver[] customArgumentResolvers; |
|
|
|
|
|
|
|
|
|
|
@ -157,7 +157,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc |
|
|
|
final Class<?> handlerType = ClassUtils.getUserClass(handler); |
|
|
|
final Class<?> handlerType = ClassUtils.getUserClass(handler); |
|
|
|
final Class<? extends Throwable> thrownExceptionType = thrownException.getClass(); |
|
|
|
final Class<? extends Throwable> thrownExceptionType = thrownException.getClass(); |
|
|
|
Method handlerMethod = null; |
|
|
|
Method handlerMethod = null; |
|
|
|
|
|
|
|
|
|
|
|
Map<Class<? extends Throwable>, Method> handlers = exceptionHandlerCache.get(handlerType); |
|
|
|
Map<Class<? extends Throwable>, Method> handlers = exceptionHandlerCache.get(handlerType); |
|
|
|
|
|
|
|
|
|
|
|
if (handlers != null) { |
|
|
|
if (handlers != null) { |
|
|
@ -170,7 +170,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc |
|
|
|
handlers = new ConcurrentHashMap<Class<? extends Throwable>, Method>(); |
|
|
|
handlers = new ConcurrentHashMap<Class<? extends Throwable>, Method>(); |
|
|
|
exceptionHandlerCache.put(handlerType, handlers); |
|
|
|
exceptionHandlerCache.put(handlerType, handlers); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
final Map<Class<? extends Throwable>, Method> resolverMethods = handlers; |
|
|
|
final Map<Class<? extends Throwable>, Method> resolverMethods = handlers; |
|
|
|
|
|
|
|
|
|
|
|
ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() { |
|
|
|
ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() { |
|
|
@ -228,19 +228,19 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the best matching method. Uses the {@link DepthComparator}. |
|
|
|
* Uses the {@link DepthComparator} to find the best matching method |
|
|
|
|
|
|
|
* @return the best matching method or {@code null}. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private Method getBestMatchingMethod( |
|
|
|
private Method getBestMatchingMethod( |
|
|
|
Map<Class<? extends Throwable>, Method> resolverMethods, Exception thrownException) { |
|
|
|
Map<Class<? extends Throwable>, Method> resolverMethods, Exception thrownException) { |
|
|
|
|
|
|
|
|
|
|
|
if (!resolverMethods.isEmpty()) { |
|
|
|
if (resolverMethods.isEmpty()) { |
|
|
|
Class<? extends Throwable> closestMatch = |
|
|
|
|
|
|
|
ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException); |
|
|
|
|
|
|
|
return resolverMethods.get(closestMatch); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
return null; |
|
|
|
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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -249,13 +249,13 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc |
|
|
|
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, |
|
|
|
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, |
|
|
|
NativeWebRequest webRequest, Exception thrownException) throws Exception { |
|
|
|
NativeWebRequest webRequest, Exception thrownException) throws Exception { |
|
|
|
|
|
|
|
|
|
|
|
Class[] paramTypes = handlerMethod.getParameterTypes(); |
|
|
|
Class<?>[] paramTypes = handlerMethod.getParameterTypes(); |
|
|
|
Object[] args = new Object[paramTypes.length]; |
|
|
|
Object[] args = new Object[paramTypes.length]; |
|
|
|
Class<?> handlerType = handler.getClass(); |
|
|
|
Class<?> handlerType = handler.getClass(); |
|
|
|
for (int i = 0; i < args.length; i++) { |
|
|
|
for (int i = 0; i < args.length; i++) { |
|
|
|
MethodParameter methodParam = new MethodParameter(handlerMethod, i); |
|
|
|
MethodParameter methodParam = new MethodParameter(handlerMethod, i); |
|
|
|
GenericTypeResolver.resolveParameterType(methodParam, handlerType); |
|
|
|
GenericTypeResolver.resolveParameterType(methodParam, handlerType); |
|
|
|
Class paramType = methodParam.getParameterType(); |
|
|
|
Class<?> paramType = methodParam.getParameterType(); |
|
|
|
Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException); |
|
|
|
Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException); |
|
|
|
if (argValue != WebArgumentResolver.UNRESOLVED) { |
|
|
|
if (argValue != WebArgumentResolver.UNRESOLVED) { |
|
|
|
args[i] = argValue; |
|
|
|
args[i] = argValue; |
|
|
@ -290,7 +290,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Resolution of standard parameter types...
|
|
|
|
// Resolution of standard parameter types...
|
|
|
|
Class paramType = methodParameter.getParameterType(); |
|
|
|
Class<?> paramType = methodParameter.getParameterType(); |
|
|
|
Object value = resolveStandardArgument(paramType, webRequest, thrownException); |
|
|
|
Object value = resolveStandardArgument(paramType, webRequest, thrownException); |
|
|
|
if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) { |
|
|
|
if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) { |
|
|
|
throw new IllegalStateException( |
|
|
|
throw new IllegalStateException( |
|
|
@ -311,7 +311,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc |
|
|
|
* @param thrownException the exception thrown |
|
|
|
* @param thrownException the exception thrown |
|
|
|
* @return the argument value, or {@link WebArgumentResolver#UNRESOLVED} |
|
|
|
* @return the argument value, or {@link WebArgumentResolver#UNRESOLVED} |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest, |
|
|
|
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest, |
|
|
|
Exception thrownException) throws Exception { |
|
|
|
Exception thrownException) throws Exception { |
|
|
|
|
|
|
|
|
|
|
|
if (parameterType.isInstance(thrownException)) { |
|
|
|
if (parameterType.isInstance(thrownException)) { |
|
|
@ -395,7 +395,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc |
|
|
|
return new ModelAndView().addAllObjects(((Model) returnValue).asMap()); |
|
|
|
return new ModelAndView().addAllObjects(((Model) returnValue).asMap()); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (returnValue instanceof Map) { |
|
|
|
else if (returnValue instanceof Map) { |
|
|
|
return new ModelAndView().addAllObjects((Map) returnValue); |
|
|
|
return new ModelAndView().addAllObjects((Map<String, Object>) returnValue); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (returnValue instanceof View) { |
|
|
|
else if (returnValue instanceof View) { |
|
|
|
return new ModelAndView((View) returnValue); |
|
|
|
return new ModelAndView((View) returnValue); |
|
|
|