123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- package com.gihon.config.web;
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import java.util.concurrent.ConcurrentHashMap;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.validation.ConstraintViolation;
- import javax.validation.ConstraintViolationException;
- import org.hibernate.validator.internal.engine.ValidatorImpl;
- import org.springframework.beans.factory.InitializingBean;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.core.MethodIntrospector;
- import org.springframework.core.MethodParameter;
- import org.springframework.util.Assert;
- import org.springframework.validation.annotation.Validated;
- import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
- import org.springframework.web.bind.support.WebDataBinderFactory;
- import org.springframework.web.context.request.ServletWebRequest;
- import org.springframework.web.method.HandlerMethod;
- import org.springframework.web.method.support.HandlerMethodArgumentResolver;
- import org.springframework.web.method.support.InvocableHandlerMethod;
- import org.springframework.web.method.support.ModelAndViewContainer;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
- import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
- import org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory;
- import org.springframework.web.servlet.support.RequestContextUtils;
- //注意:此处只支持@RequetMapping方式
- public class ValidationInterceptor implements HandlerInterceptor, InitializingBean {
- @Autowired
- private LocalValidatorFactoryBean validatorFactoryBean;
- @Autowired
- private RequestMappingHandlerAdapter adapter;
- private List<HandlerMethodArgumentResolver> argumentResolvers;
-
- @Override
- public void afterPropertiesSet() throws Exception {
- argumentResolvers = adapter.getArgumentResolvers();
- }
- private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache = new ConcurrentHashMap<>(256);
- private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- // 只处理HandlerMethod方式
- if (handler instanceof HandlerMethod) {
- HandlerMethod method = (HandlerMethod) handler;
- Validated valid = method.getMethodAnnotation(Validated.class); //
- if (valid != null) {
- // 根据工厂,拿到一个校验器
- ValidatorImpl validatorImpl = (ValidatorImpl) validatorFactoryBean.getValidator();
- // 拿到该方法所有的参数们~~~ org.springframework.core.MethodParameter
- MethodParameter[] parameters = method.getMethodParameters();
- Object[] parameterValues = new Object[parameters.length];
- //遍历所有的入参:给每个参数做赋值和数据绑定
- for (int i = 0; i < parameters.length; i++) {
- MethodParameter parameter = parameters[i];
- // 找到适合解析这个参数的处理器~
- HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
- Assert.notNull(resolver, "Unknown parameter type [" + parameter.getParameterType().getName() + "]");
- ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
- WebDataBinderFactory webDataBinderFactory = getDataBinderFactory(method);
- Object value = resolver.resolveArgument(parameter, mavContainer, new ServletWebRequest(request, response), webDataBinderFactory);
- parameterValues[i] = value; // 赋值
- }
- // 对入参进行统一校验
- Set<ConstraintViolation<Object>> violations = validatorImpl.validateParameters(method.getBean(), method.getMethod(), parameterValues, valid.value());
- // 若存在错误消息,此处也做抛出异常处理 javax.validation.ConstraintViolationException
- if (!violations.isEmpty()) {
- System.err.println("方法入参校验失败~~~~~~~");
- throw new ConstraintViolationException(violations);
- }
- }
- }
- return true;
- }
- private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) {
- Class<?> handlerType = handlerMethod.getBeanType();
- Set<Method> methods = this.initBinderCache.get(handlerType);
- if (methods == null) {
- // 支持到@InitBinder注解
- methods = MethodIntrospector.selectMethods(handlerType, RequestMappingHandlerAdapter.INIT_BINDER_METHODS);
- this.initBinderCache.put(handlerType, methods);
- }
- List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();
- for (Method method : methods) {
- Object bean = handlerMethod.getBean();
- initBinderMethods.add(new InvocableHandlerMethod(bean, method));
- }
- return new ServletRequestDataBinderFactory(initBinderMethods, adapter.getWebBindingInitializer());
- }
- private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
- HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
- if (result == null) {
- for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
- if (methodArgumentResolver.supportsParameter(parameter)) {
- result = methodArgumentResolver;
- this.argumentResolverCache.put(parameter, result);
- break;
- }
- }
- }
- return result;
- }
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- }
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- }
- }
|