当前位置: 首页 > news >正文

SpringMVC源码分析(九)--返回值解析器

1.返回值解析器介绍

返回值解析器用于解析Hanlder执行方法后的返回结果,例如将方法上标注有@ResponseBody注解的返回值解析成JSON、将方法返回的字符串作为视图名等

SpringMVC中默认的返回值解析器见RequestMappingHandlerAdapter#getDefaultReturnValueHandlers

private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(20);handlers.add(new ModelAndViewMethodReturnValueHandler());handlers.add(new ModelMethodProcessor());handlers.add(new ViewMethodReturnValueHandler());handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));handlers.add(new StreamingResponseBodyReturnValueHandler());handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),this.contentNegotiationManager, this.requestResponseBodyAdvice));handlers.add(new HttpHeadersReturnValueHandler());handlers.add(new CallableMethodReturnValueHandler());handlers.add(new DeferredResultMethodReturnValueHandler());handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));handlers.add(new ModelAttributeMethodProcessor(false));handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),this.contentNegotiationManager, this.requestResponseBodyAdvice));handlers.add(new ViewNameMethodReturnValueHandler());handlers.add(new MapMethodProcessor());// 添加自定义的返回值解析器if (getCustomReturnValueHandlers() != null) {handlers.addAll(getCustomReturnValueHandlers());}// 兜底的解析器if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));}else {handlers.add(new ModelAttributeMethodProcessor(true));}return handlers;
}

这些返回值解析器会被封装到HandlerMethodReturnValueHandlerComposite中,处理返回值时,会按照加入的顺序依次判断每个返回值解析器能否解析此任务,如果其中某个解析器能够解析此参数,则返回解析结果

2.自定义返回值解析器

在某些场景下,我们可以自定义返回值解析器,将响应的返回值转成我们希望的格式,假如我们想要将响应转换为yml格式,这时我们可以自定义注解,然后再自定义返回值解析器实现HandlerMethodReturnValueHandler接口,示例如下:

1)创建自定义注解@Yml及自定义返回值处理器YmlReturnResolver实现HandlerMethodReturnValueHandler接口

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Yml {
}public class YmlReturnResolver implements HandlerMethodReturnValueHandler {// 判断返回值解析器是否支持@Overridepublic boolean supportsReturnType(MethodParameter methodParameter) {Yml yml = methodParameter.getMethodAnnotation(Yml.class);return yml != null;}@Overridepublic void handleReturnValue(Object o, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,NativeWebRequest nativeWebRequest) throws Exception {// 将返回值转换为yamlString str = new Yaml().dump(o);// 设置响应内容HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);response.setContentType("text/plain;charset=utf-8");response.getWriter().print(str);// 设置请求已处理完毕modelAndViewContainer.setRequestHandled(true);}
}

2)配置类中加入自定义返回值解析器

@Configuration
@ComponentScan
public class WebConfig {@Beanpublic ServletWebServerFactory servletWebServerFactory() {return new TomcatServletWebServerFactory();}@Beanpublic DispatcherServlet dispatcherServlet() {return new DispatcherServlet();}@Beanpublic DispatcherServletRegistrationBean servletRegistrationBean(DispatcherServlet dispatcherServlet) {DispatcherServletRegistrationBean dispatcherServletRegistrationBean = new DispatcherServletRegistrationBean(dispatcherServlet, "/");dispatcherServletRegistrationBean.setLoadOnStartup(1);return dispatcherServletRegistrationBean;}@Beanpublic MyRequestMappingHandlerAdapter requestMappingHandlerAdapter() {MyRequestMappingHandlerAdapter handlerAdapter = new MyRequestMappingHandlerAdapter();// 添加自定义返回值解析器handlerAdapter.setCustomReturnValueHandlers(Arrays.asList(new YmlReturnResolver()));return handlerAdapter;}
}

3)创建控制器类及实体类

@Controller
public class Controller01 {@GetMapping("/test")@Ymlpublic User test() {
http://www.lryc.cn/news/330372.html

相关文章:

  • 京西商城——创建订单和获取订单接口
  • 大话设计模式之模板方法模式
  • 新model开发记录
  • ARMday1
  • 【C++风云录】创造视觉奇迹:探索C++图形编程的魅力与可能性
  • 常见的Nginx+Redis+MQ+DB架构设计
  • vue+elementUI搭建动态表头的表格
  • 【ENSP】交换机和交换机之间实现静态路由
  • 2024.2.18力扣每日一题——N叉树的前序遍历
  • Taro活动列表中,对某一个活动添加分享按钮
  • 深入理解计算机系统 家庭作业 2.65
  • Java字节码
  • 深入解析大数据体系中的ETL工作原理及常见组件
  • 条件变量的简易C++实现版
  • 目标检测评价标准
  • C51-- 蓝牙,WIFI模块
  • HN热帖|替换Redis的一场赛跑
  • Kubernetes(k8s):网络插件之Calico安装与详解
  • Chrome base 库详解:工具类和常用类库
  • Nginx开发实战三:替换请求资源中的固定数据
  • 如何在Python中实现多线程和多进程?
  • Redis面试题10道
  • vue3从精通到入门6:v-memo指令
  • 【算法集训】基础算法:双指针
  • 李白打酒加强版(c++实现)
  • 平价运动蓝牙耳机哪个品牌好?必选的5个爆款品牌,超高性价比!
  • Android ImageView以及实现截图
  • 剑指offer--数组中重复的数字
  • 【THM】SQL Injection(SQL注入)-初级渗透测试
  • 数码论坛系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)