- 初步了解 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();
- 解析参数依赖的就是各种参数解析器,它们都有两个重要方法
- 常见参数的解析
点击查看代码
//解析 @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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。