程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • SpringMVC

    • SpringMVC 入门
    • Spring MVC 数据接收
    • Spring MVC 数据返回
    • Spring MVC 路径匹配规则
    • Spring MVC 内容协商策略
    • Spring MVC 异步请求处理
    • Spring MVC 静态资源处理
    • Spring MVC 自定义格式化器
    • SpringMVC 自定义拦截器
    • SpringMVC 配置跨域(CORS)
    • Spring MVC 自定义视图控制器
    • Spring MVC 自定义视图解析器
    • Spring MVC 自定义方法参数解析器
    • Spring MVC 自定义返回值处理器
      • 1. 自定义返回值处理器配置
      • 2. 实现自定义返回值处理器
      • 3. 自定义注解 @ResponseData
      • 4. 测试控制器
      • 5. 返回值处理器未生效问题及解决方法
        • 原因分析
        • 解决方案:调整处理器顺序
      • 6. 注意事项
    • Spring MVC 自定义消息转换器
    • Spring MVC 消息转换器扩展
    • Spring MVC 自定义异常处理器
    • Spring MVC 自定义异常处理器扩展
  • SpringMVC
  • SpringMVC
scholar
2024-08-17
目录

Spring MVC 自定义返回值处理器

# Spring MVC 自定义返回值处理器

前言

在 Spring MVC 中,返回值处理器 (HandlerMethodReturnValueHandler) 用于处理控制器方法的返回值,并将结果写入到 HTTP 响应中。通过自定义返回值处理器,我们可以定制返回数据的处理逻辑。

# 1. 自定义返回值处理器配置

首先,通过 addReturnValueHandlers 方法将自定义的返回值处理器添加到 Spring MVC 中:

@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
    // 注册自定义的返回值处理器
    handlers.add(myReturnValueHandler());
}

@Bean
public MyReturnValueHandler myReturnValueHandler() {
    // 创建自定义的返回值处理器实例
    return new MyReturnValueHandler();
}
1
2
3
4
5
6
7
8
9
10
11
  • addReturnValueHandlers 方法:用于将自定义的返回值处理器添加到 Spring MVC 的处理器列表中。
  • MyReturnValueHandler:这是自定义的返回值处理器,用于处理特定注解标记的方法返回值。

# 2. 实现自定义返回值处理器

实现 HandlerMethodReturnValueHandler 接口,并重写其两个核心方法:

public class MyReturnValueHandler implements HandlerMethodReturnValueHandler {

    @Override
    public boolean supportsReturnType(MethodParameter methodParameter) {
        // 判断当前方法是否带有自定义的 @ResponseData 注解
        return methodParameter.hasMethodAnnotation(ResponseData.class);
    }

    @Override
    public void handleReturnValue(Object returnValue, 
                                  MethodParameter methodParameter, 
                                  ModelAndViewContainer mavContainer, 
                                  NativeWebRequest webRequest) throws Exception {
        // 设置请求已处理,避免继续处理
        mavContainer.setRequestHandled(true);
        
        // 处理返回值,并将结果写入 HTTP 响应
        webRequest.getNativeResponse(HttpServletResponse.class)
                  .getWriter()
                  .write("自定义返回内容:" + returnValue.toString());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  • supportsReturnType 方法:判断当前方法是否适用于自定义处理器。这里通过判断方法上是否有自定义的 @ResponseData 注解来决定是否使用此处理器。
  • handleReturnValue 方法:实现自定义的返回值处理逻辑。设置请求为已处理,并将自定义内容写入响应中。

# 3. 自定义注解 @ResponseData

为了让处理器识别特定方法,可以创建一个自定义注解:

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResponseData {
    // 自定义注解,用于标记需要通过自定义返回值处理器处理的方法
}
1
2
3
4
5
6

# 4. 测试控制器

创建一个简单的控制器方法并使用 @ResponseData 注解标记:

@RestController
public class TestController {

    @GetMapping("/test6")
    @ResponseData
    public String test6() {
        return "test6";
    }
}
1
2
3
4
5
6
7
8
9
  • 访问地址:http://localhost:8080/test6
  • 返回结果:自定义返回内容:test6

# 5. 返回值处理器未生效问题及解决方法

如果自定义的返回值处理器未生效,可能是由于默认的返回值处理器(如 RequestResponseBodyMethodProcessor)优先处理了返回值。通常这是因为 @RestController 或 @ResponseBody 注解已经占用了处理顺序。

# 原因分析

在 Spring MVC 的返回值处理流程中,返回值处理器按照注册顺序执行,默认处理器如 RequestResponseBodyMethodProcessor 通常会优先执行。如果自定义处理器排在它之后,则不会生效。

# 解决方案:调整处理器顺序

为了解决这个问题,可以将自定义的返回值处理器放在默认处理器之前。以下是两种实现方式:

方式1:实现 ApplicationContextAware 接口

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    RequestMappingHandlerAdapter adapter = applicationContext.getBean(RequestMappingHandlerAdapter.class);
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();
    handlers.add(myReturnValueHandler()); // 优先添加自定义的处理器
    handlers.addAll(adapter.getReturnValueHandlers()); // 添加其他默认处理器
    adapter.setReturnValueHandlers(handlers);
}
1
2
3
4
5
6
7
8

方式2:通过 @PostConstruct 注解进行初始化

@Autowired
private RequestMappingHandlerAdapter adapter;

@PostConstruct
public void initReturnValueHandlers() {
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();
    handlers.add(myReturnValueHandler()); // 优先添加自定义的处理器
    handlers.addAll(adapter.getReturnValueHandlers()); // 添加其他默认处理器
    adapter.setReturnValueHandlers(handlers);
}
1
2
3
4
5
6
7
8
9
10

# 6. 注意事项

  • 调整返回值处理器顺序可能会影响 Spring MVC 的默认行为,需谨慎操作。
  • 确保自定义处理器不会与已有的处理器冲突,尤其是在处理复杂的返回值类型时。

通过这种配置方式,Spring MVC 可以灵活地支持自定义的返回值处理逻辑,满足复杂的业务需求,同时保持代码的简洁性与可维护性。

编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
Spring MVC 自定义方法参数解析器
Spring MVC 自定义消息转换器

← Spring MVC 自定义方法参数解析器 Spring MVC 自定义消息转换器→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式