HandlerMethodArgumentResolver
springmvc中仅仅加个@Controller @RequestMaping等注解就可以将普通的java方法成为一个Handler处理器。spring通过HandlerMethodArgumentResolver来解析handler处理器参数问题。
HandlerMethodArgumentResolver 接口
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(MethodParameter parameter......
PS:MethodParamter 方法参数信息的封装类,可以通过它获取方法上参数的名称,类型,注解,所在的方法等等
Method showParam = DemoUserSon.class.getMethod("showParam", String.class, Integer.class); Parameter[] parameters = showParam.getParameters(); //识别方法的参数名字 基于ASM DefaultParameterNameDiscoverer defaultParameterNameDiscoverer = new DefaultParameterNameDiscoverer(); for (int i = 0; i < parameters.length; i++) { MethodParameter methodParameter = new MethodParameter(showParam,i); methodParameter.initParameterNameDiscovery(defaultParameterNameDiscoverer); System.out.println("参数类型:"+methodParameter.getParameterType()); System.out.println("参数名称"+methodParameter.getParameterName()); Arrays.stream(methodParameter.getParameterAnnotations()).forEach(x -> System.out.println("参数上的注解:"+x.annotationType())); } 参数类型:class java.lang.String 参数名称name 参数上的注解:interface javax.validation.constraints.NotNull 参数类型:class java.lang.Integer 参数名称age
AbstractNamedValueMethodArgumentResolver
该类主要是用来处理解析Request parameters, request headers, and path variables 的命名值,比如get请求 ?id=110,那么就从id获取这个id值100。
具体都是由子类来实现:为方法参数获取命名值、解析这些命名值到方法参数、适当处理如果参数值没有的(required)的情况。
RequestParamMethodArgumentResolver
这个是最常用的解析器,处理一下三种情况:RequestParam 、RequestPart(MultipartFile,javax.servlet.http.Part)、以及默认兜底处理简单属性。
public boolean supportsParameter(MethodParameter parameter) { if (parameter.hasParameterAnnotation(RequestParam.class)) { if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) { String paramName = parameter.getParameterAnnotation(RequestParam.class).name(); return StringUtils.hasText(paramName); } else { return true; } } else { if (parameter.hasParameterAnnotation(RequestPart.class)) { return false; } parameter = parameter.nestedIfOptional(); if (MultipartResolutionDelegate.isMultipartArgument(parameter)) { return true; } else if (this.useDefaultResolution) { return BeanUtils.isSimpleProperty(parameter.getNestedParameterType()); } else { return false; } } }
public static boolean isSimpleValueType(Class<?> clazz) { return (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() || CharSequence.class.isAssignableFrom(clazz) || Number.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz) || URI.class == clazz || URL.class == clazz || Locale.class == clazz || Class.class == clazz); }
关于请求数组传参问题
@ResponseBody
@GetMapping("/test")
public Object test(@RequestParam List<Object> objects) {
System.out.println(objects);
return objects;
}请求URL:
/test/?objects=1,2,3
。控制台打印:[1,2,3]
传参可以是@RequestParam List<Object> objects 或者@RequestParamObject[] objects , 对于List,@RequestParam必须存在,因为不是简单类型 ,但是String[]objects这样是可以不用注解的,因为它是简单类型,可以走兜底的默认解析RequestParamMethodArgumentResolver。
RequestHeaderMethodArgumentResolver
@ResponseBody
@GetMapping("/test")
public Object test(@RequestHeader("Accept-Encoding") String encoding,
@RequestHeader("Accept-Encoding") List<String> encodingList) {
System.out.println(encoding);
System.out.println(encodingList);
return encoding;
}
逗号隔开,装转成了数组或集合,注解指定的value值是可以不区分大小写的
gzip, deflate, br
[gzip, deflate, br]
类似的像:ServletCookieValueMethodArgumentResolver 的 @CookieValue("JSESSIONID") String cookieValue