spring 20 参数解析器
作者:互联网
- 初步了解 RequestMappingHandlerAdapter 的调用过程
- 控制器方法被封装为 HandlerMethod
- 准备对象绑定与类型转换
- 准备 ModelAndViewContainer 用来存储中间 Model 结果
- 解析每个参数值
点击查看代码
private static void test1() throws NoSuchMethodException {
//初步了解 RequestMappingHandlerAdapter 的调用过程
//设置控制器对象
S20Controller controller = new S20Controller();
//设置控制器方法,控制器方法被封装为 HandlerMethod 对象
HandlerMethod method = new HandlerMethod(controller, controller.getClass().getMethod("testParamsResolver", String.class, String.class, int.class, String.class, MultipartFile.class, int.class, String.class, String.class, String.class, HttpServletRequest.class, User.class, User.class, User.class));
//准备对象绑定与参数的类型转换
for (MethodParameter methodParameter : method.getMethodParameters()) {
//设置参数名解析
methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
Annotation[] parameterAnnotations = methodParameter.getParameterAnnotations();
String annotation = parameterAnnotations.length > 0 ? Arrays.stream(parameterAnnotations).map(a -> a.annotationType().getSimpleName()).collect(Collectors.joining()) : null;
System.out.println("[" + methodParameter.getParameterIndex() + "] " + annotation + " " + methodParameter.getParameterType().getSimpleName() + " " + methodParameter.getParameterName());
}
//ModelAndViewContainer ,用来存储中间生成的 Model 结果
// new ModelAndView();
- 解析参数依赖的就是各种参数解析器,它们都有两个重要方法
- supportsParameter 判断是否支持方法参数
- resolveArgument 解析方法参数
- 常见参数的解析
- @RequestParam
- 省略 @RequestParam
- @RequestParam(defaultValue)
点击查看代码
//解析 @RequestParam 注解的参数,增加 context ,为了解析环境变量。${JAVA_HOME}
private static void test2(AnnotationConfigApplicationContext context, HttpServletRequest request) throws Exception {
//创建解析 @RequestParam 注解的参数解析器
RequestParamMethodArgumentResolver requestParamMethodArgumentResolver = new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(),true);
//设置控制器方法,控制器方法被封装为 HandlerMethod 对象
HandlerMethod method = new HandlerMethod(new S20Controller(), S20Controller.class.getMethod("testParamsResolver", String.class, String.class, int.class, String.class, MultipartFile.class, int.class, String.class, String.class, String.class, HttpServletRequest.class, User.class, User.class, User.class));
//准备对象绑定与参数的类型转换
DefaultDataBinderFactory factory = new DefaultDataBinderFactory(null);
//ModelAndViewContainer ,用来存储中间生成的 Model 结果
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
for (MethodParameter methodParameter : method.getMethodParameters()) {
//设置解析参数名字解析器
methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
//判断是否可以解析此参数
if (requestParamMethodArgumentResolver.supportsParameter(methodParameter)) {
//可以,获得解析得到的参数
Object resolveArgument = requestParamMethodArgumentResolver.resolveArgument(methodParameter, modelAndViewContainer, new ServletWebRequest(request), factory);
System.out.println(methodParameter.getParameterName() + "参数值是:" + resolveArgument + "类型是:" + resolveArgument.getClass().getSimpleName());
}
}
}
点击查看代码
//组合器 将所以参数解析器组合,统一调用
HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();
composite.addResolvers(
//@RequestParam
requestParamMethodArgumentResolver,
//@PathVariable
new PathVariableMethodArgumentResolver(),
//@RequestHeader
new RequestHeaderMethodArgumentResolver(context.getDefaultListableBeanFactory()),
//@CookieValue
new ServletCookieValueMethodArgumentResolver(context.getDefaultListableBeanFactory()),
//@Value
new ExpressionValueMethodArgumentResolver(context.getDefaultListableBeanFactory())
);
for (MethodParameter methodParameter : method.getMethodParameters()) {
//设置解析参数名字解析器
methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
//判断是否可以解析此参数
if (composite.supportsParameter(methodParameter)) {
//可以,获得解析得到的参数
Object resolveArgument = composite.resolveArgument(methodParameter, modelAndViewContainer, new ServletWebRequest(request), factory);
System.out.println(methodParameter.getParameterName() + "参数值是:" + resolveArgument + "类型是:" + resolveArgument.getClass().getSimpleName());
}
- HttpServletRequest 等
- @ModelAttribute
- 省略 @ModelAttribute
- @RequestBody
点击查看代码
private static void test5(AnnotationConfigApplicationContext context, HttpServletRequest request) {
//设置控制器方法,控制器方法被封装为 HandlerMethod 对象
HandlerMethod method = new HandlerMethod(new S20Controller(), S20Controller.class.getMethod("testParamsResolver", String.class, String.class, int.class, String.class, MultipartFile.class, int.class, String.class, String.class, String.class, HttpServletRequest.class, User.class, User.class, User.class));
//准备对象绑定与参数的类型转换
ServletRequestDataBinderFactory factory = new ServletRequestDataBinderFactory(null,null);
//ModelAndViewContainer ,用来存储中间生成的 Model 结果
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
//组合器 将所以参数解析器组合,统一调用
HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();
composite.addResolvers(
//@RequestParam false 必须要有 @RequestParam 注解
new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(), false),
//@PathVariable
new PathVariableMethodArgumentResolver(),
//@RequestHeader
new RequestHeaderMethodArgumentResolver(context.getDefaultListableBeanFactory()),
//@CookieValue
new ServletCookieValueMethodArgumentResolver(context.getDefaultListableBeanFactory()),
//@Value spring 获取数据 ${} #{}
new ExpressionValueMethodArgumentResolver(context.getDefaultListableBeanFactory()),
// request, response, session ...
new ServletRequestMethodArgumentResolver(),
// @ModelAttribute
new ServletModelAttributeMethodProcessor(false),
// @RequestBody
new RequestResponseBodyMethodProcessor(Collections.singletonList(new MappingJackson2HttpMessageConverter())),
// 无 @ModelAttribute 修饰的
new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(),true),
//无 @RequestParam 修饰的
new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(),true)
);
for (MethodParameter methodParameter : method.getMethodParameters()) {
//设置解析参数名字解析器
methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer());
//判断是否可以解析此参数
if (composite.supportsParameter(methodParameter)) {
//可以,获得解析得到的参数
Object resolveArgument = composite.resolveArgument(methodParameter, modelAndViewContainer, new ServletWebRequest(request), factory);
System.out.println(methodParameter.getParameterName() + "参数值是:" + resolveArgument + "类型是:" + resolveArgument.getClass().getSimpleName());
//模型数据
System.out.println(modelAndViewContainer.getModel());
}
}
}
- 组合模式在 Spring 中的体现
- @RequestParam, @CookieValue 等注解中的参数名、默认值, 都可以写成活的, 即从 ${ } #{ }中获取
- 此处 @RequestBody 解析 类型转换报错 java.lang.IllegalArgumentException: not support type
标签:解析器,context,20,String,spring,methodParameter,resolveArgument,new,class 来源: https://www.cnblogs.com/xy7112/p/16436066.html