ValidationInterceptor.java 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package com.gihon.config.web;
  2. import java.lang.reflect.Method;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.Map;
  6. import java.util.Set;
  7. import java.util.concurrent.ConcurrentHashMap;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import javax.validation.ConstraintViolation;
  11. import javax.validation.ConstraintViolationException;
  12. import org.hibernate.validator.internal.engine.ValidatorImpl;
  13. import org.springframework.beans.factory.InitializingBean;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.core.MethodIntrospector;
  16. import org.springframework.core.MethodParameter;
  17. import org.springframework.util.Assert;
  18. import org.springframework.validation.annotation.Validated;
  19. import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
  20. import org.springframework.web.bind.support.WebDataBinderFactory;
  21. import org.springframework.web.context.request.ServletWebRequest;
  22. import org.springframework.web.method.HandlerMethod;
  23. import org.springframework.web.method.support.HandlerMethodArgumentResolver;
  24. import org.springframework.web.method.support.InvocableHandlerMethod;
  25. import org.springframework.web.method.support.ModelAndViewContainer;
  26. import org.springframework.web.servlet.HandlerInterceptor;
  27. import org.springframework.web.servlet.ModelAndView;
  28. import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
  29. import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory;
  30. import org.springframework.web.servlet.support.RequestContextUtils;
  31. //注意:此处只支持@RequetMapping方式
  32. public class ValidationInterceptor implements HandlerInterceptor, InitializingBean {
  33. @Autowired
  34. private LocalValidatorFactoryBean validatorFactoryBean;
  35. @Autowired
  36. private RequestMappingHandlerAdapter adapter;
  37. private List<HandlerMethodArgumentResolver> argumentResolvers;
  38. @Override
  39. public void afterPropertiesSet() throws Exception {
  40. argumentResolvers = adapter.getArgumentResolvers();
  41. }
  42. private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache = new ConcurrentHashMap<>(256);
  43. private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);
  44. @Override
  45. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  46. // 只处理HandlerMethod方式
  47. if (handler instanceof HandlerMethod) {
  48. HandlerMethod method = (HandlerMethod) handler;
  49. Validated valid = method.getMethodAnnotation(Validated.class); //
  50. if (valid != null) {
  51. // 根据工厂,拿到一个校验器
  52. ValidatorImpl validatorImpl = (ValidatorImpl) validatorFactoryBean.getValidator();
  53. // 拿到该方法所有的参数们~~~ org.springframework.core.MethodParameter
  54. MethodParameter[] parameters = method.getMethodParameters();
  55. Object[] parameterValues = new Object[parameters.length];
  56. //遍历所有的入参:给每个参数做赋值和数据绑定
  57. for (int i = 0; i < parameters.length; i++) {
  58. MethodParameter parameter = parameters[i];
  59. // 找到适合解析这个参数的处理器~
  60. HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
  61. Assert.notNull(resolver, "Unknown parameter type [" + parameter.getParameterType().getName() + "]");
  62. ModelAndViewContainer mavContainer = new ModelAndViewContainer();
  63. mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
  64. WebDataBinderFactory webDataBinderFactory = getDataBinderFactory(method);
  65. Object value = resolver.resolveArgument(parameter, mavContainer, new ServletWebRequest(request, response), webDataBinderFactory);
  66. parameterValues[i] = value; // 赋值
  67. }
  68. // 对入参进行统一校验
  69. Set<ConstraintViolation<Object>> violations = validatorImpl.validateParameters(method.getBean(), method.getMethod(), parameterValues, valid.value());
  70. // 若存在错误消息,此处也做抛出异常处理 javax.validation.ConstraintViolationException
  71. if (!violations.isEmpty()) {
  72. System.err.println("方法入参校验失败~~~~~~~");
  73. throw new ConstraintViolationException(violations);
  74. }
  75. }
  76. }
  77. return true;
  78. }
  79. private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) {
  80. Class<?> handlerType = handlerMethod.getBeanType();
  81. Set<Method> methods = this.initBinderCache.get(handlerType);
  82. if (methods == null) {
  83. // 支持到@InitBinder注解
  84. methods = MethodIntrospector.selectMethods(handlerType, RequestMappingHandlerAdapter.INIT_BINDER_METHODS);
  85. this.initBinderCache.put(handlerType, methods);
  86. }
  87. List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
  88. for (Method method : methods) {
  89. Object bean = handlerMethod.getBean();
  90. initBinderMethods.add(new InvocableHandlerMethod(bean, method));
  91. }
  92. return new ServletRequestDataBinderFactory(initBinderMethods, adapter.getWebBindingInitializer());
  93. }
  94. private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
  95. HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
  96. if (result == null) {
  97. for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
  98. if (methodArgumentResolver.supportsParameter(parameter)) {
  99. result = methodArgumentResolver;
  100. this.argumentResolverCache.put(parameter, result);
  101. break;
  102. }
  103. }
  104. }
  105. return result;
  106. }
  107. @Override
  108. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  109. }
  110. @Override
  111. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  112. }
  113. }