使用 @ControllerAdvice 和 实现ResponseBodyAdvice接口, 拦截Controller方法默认返回参数,统一处理返回值/响应体

使用 @ControllerAdvice 和 实现ResponseBodyAdvice接口, 拦截Controller方法默认返回参数,统一处理返回值/响应体

1、Controller代码
以下是Controller方法源码:

@RestController
@RequestMapping("/manage/user")
public class TestController {private Logger logger = LoggerFactory.getLogger(TestController.class);/*** 通过会员id获取会员信息及详情** @param id 会员id* @return app msg*/@GetMapping("/edit/{id}")public AppMessage edit(@PathVariable Integer id) {if (null == id) {return AppMessage.error(-3, "会员ID不能为空");}// 查询会员对象User user = userService.queryById(id);if (user == null) {return AppMessage.error(-3, "根据会员ID未查询到对应会员");}return AppMessage.success(user);}}

2、拦截处理器
下面已经封装好了一个拦截处理类以供参考:

package com.yclimb.test;import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;/*** 拦截Controller方法默认返回参数,统一处理返回值/响应体*/
@ControllerAdvice
public class TestResponseBodyAdvice implements ResponseBodyAdvice {@Overridepublic Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {System.out.println("TestResponseBodyAdvice==>beforeBodyWrite:" + o.toString() + ","+ methodParameter);return o;}@Overridepublic boolean supports(MethodParameter methodParameter, Class aClass) {return true;}
}

ResponseBodyAdvice

方法讲解

  • supports对你需要进行拦截的response进行判断筛选,返回true则进行拦截反之放行,
  • beforeBodyWrite对supports进行拦截的response进行处理,封装你需要的类型参数,加密等等。

个人理解:

ResponseBodyAdvice 接口是在 Controller 执行 return 之后,在 response 返回给客户端之前,执行的对 response 的一些处理,可以实现对 response 数据的一些统一封装或者加密等操作。

该接口一共有两个方法:

(1)supports —— 判断是否要执行beforeBodyWrite方法,true为执行,false不执行 —— 通过supports方法,我们可以选择哪些类或哪些方法要对response进行处理,其余的则不处理。

(2)beforeBodyWrite —— 对 response 处理的具体执行方法。

package com.abc.demo;import com.github.pagehelper.Page;
import com.abc.pojo.bean.ResponseResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@ControllerAdvice
public class ControllerAdviceHandler implements ResponseBodyAdvice<Object> {@ResponseBody@ExceptionHandler(value = Throwable.class)public ResponseResult catchAllError(HttpServletRequest request, HttpServletResponse response, Throwable error) {return ResponseResult.exception(error);}@Overridepublic boolean supports(MethodParameter method, Class<? extends HttpMessageConverter<?>> clazz) {return method.getContainingClass().getPackage().getName().startsWith("com.abc") &&(method.getContainingClass().getAnnotation(RestController.class) != null ||(method.getMethod() != null && method.getMethod().getAnnotation(ResponseBody.class) != null));}@Overridepublic Object beforeBodyWrite(Object result, MethodParameter methodParameter, MediaType mediaType,Class<? extends HttpMessageConverter<?>> aClass,ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {return result instanceof ResponseResult ? result :result instanceof Page ? ResponseResult.page((Page<?>) result) :ResponseResult.successData(result);}
}

实例

有一个Controller类,返回参数为OutputObject,我们通过ResponseBodyAdvice,对该类的所有方法返回的OutputObject中的部分数据进行统一加密处理。

// 对响应报文统一处理,对bean内容进行加密
@Component
//声明该类要处理的包路径
@ControllerAdvice("com.cmos.edcreg.web.controller")
public class ResponseAdvice implements ResponseBodyAdvice {private final Logger logger = LoggerFactory.getLogger(ResponseAdvice.class);// 对response处理的具体方法@Overridepublic Object beforeBodyWrite(Object arg0, MethodParameter arg1,MediaType arg2, Class arg3, ServerHttpRequest arg4,ServerHttpResponse arg5) {OutputObject out = new OutputObject();try {//arg0转换为OutputObject类型ObjectMapper objectMapper=new ObjectMapper();out = objectMapper.readValue(org.json.JSONObject.valueToString(arg0), OutputObject.class);//获取加密密钥String oldEncryptKey = out.getBean().get("oldEncryptKey");//获取加密字符串DesSpecial des = new DesSpecial();String encryptData = des.strEnc(JSON.toJSONString(out.getBean()), oldEncryptKey, null, null);//封装数据(清除原来数据,放入加密数据)out.getBean().clear();out.getBean().put("data", encryptData);return out;} catch (Exception e) {logger.error("返回报文处理出错", e);out.setReturnCode(ReturnInfoEnums.PROCESS_ERROR.getCode());out.setReturnMessage(ReturnInfoEnums.PROCESS_ERROR.getMessage());return out;}}/* 选择哪些类,或哪些方法需要走beforeBodyWrite* 从arg0中可以获取方法名和类名* arg0.getMethod().getDeclaringClass().getName()为获取方法名*/@Overridepublic boolean supports(MethodParameter arg0, Class arg1) {return "com.cmos.edcreg.web.controller.GdH5AppointmentActiveVideoNewController".equals(arg0.getMethod().getDeclaringClass().getName());}
}

在spring项目开发过程中的应用场景

对controller层返回值进行修改增强处理。比如返回值5,需要封装成:{“code”:“0”,“data”:5,“msg”:“success”} 格式返回前端

1、controller层业务代码

@RestController //此注解包含@ResponseBody注解
@RequestMapping("/mp")
public class ResponseBodyAdviceController {@RequestMapping(value = "/hello", method = RequestMethod.GET)public int hello() {return 5;} 
}

2、实现ResponseBodyAdvice接口的切面类

/**
*此注解针对controller层的类做增强功能,即对加了@RestController注解的类进行处理
*/
@ControllerAdvice(annotations = RestController.class)
public class RestResultWrapper implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,ServerHttpResponse response) {//定义一个统一的返回类RestResult responseResult = new RestResult( "0", body, "success");//如果handler处理类的返回类型是String(即控制层的返回值类型),为了保证一致性,这里需要将ResponseResult转回去if(body instanceof String) {return JSON.toJSONString(responseResult);}//封装后的数据返回到前端页面return JSONObject.toJSON(responseResult);       } 
}

3、返回公共类的创建

// 统一返回Rest风格的数据结构
public class RestResult<T>  implements Serializable {private String code = "2000";// 成功时返回的数据,失败时返回具体的异常信息private T data;// 请求失败返回的提示信息,给前端进行页面展示的信息private String message ; public RestResult() {}@Overridepublic String toString() {return "RestResult{" +"code='" + code + '\'' +", data=" + data +", message=" + message +'}';}public RestResult(String code, T data, String message) {this.code = code;this.data = data;this.message = message;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556745.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言中字符占用的存储单元,C语言知识点第1章.doc

C语言知识点第1章C语言知识点总结(二) 第八节 字符字符常量定义&#xff1a;一对单引号括起来的一个字符。如‘A’、‘a’、‘9’相应字符对应的ASCII编码值(见附录四)字符常量占用一个字节的存储单元(一个字节占8位)重点&#xff1a;表 C语言中常见的转义字符字符形式意义字符…

Spring的@ExceptionHandler注解使用方法

文章目录1&#xff0c;基本使用方法2&#xff0c;注解的参数3&#xff0c;就近原则4&#xff0c;注解方法的返回值5&#xff0c;错误的操作1&#xff0c;基本使用方法 Spring的ExceptionHandler可以用来统一处理方法抛出的异常&#xff0c;比如这样&#xff1a; ExceptionHan…

c语言dfs算法全排列代码,c语言dfs解决全排列问题

如1,2,3三个元素的全排列为&#xff1a;1,2,31,3,22,1,32,3,13,1,23,2,1共3*2*16种代码简单实现n个元素的全排列#include #define N 5int a[100];//存放数字序列int mark[100];//判断数字是否使用过,mark[3]1表示3这个数字能用int count;void dfs(int i,int a[N]);int main(int…

CAS单点登录详细流程

一、CAS简介和整体流程 CAS 是 Yale 大学发起的一个开源项目&#xff0c;旨在为 Web 应用系统提供一种可靠的单点登录方法&#xff0c;CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。CAS 具有以下特点&#xff1a; 【1】开源的企业级单点登录解决方案。 【2】CAS Server 为…

android 图片自动拉伸,解决关于ImageView自适应的问题(拉伸变形,图片模糊)

今天接手一个项目发现有个地方的图片显示非常小&#xff0c;而且还不够清晰&#xff0c;也没办法自适应屏幕的显示&#xff0c;非常的影响美观&#xff0c;于是 就像这优化一下。先看看优化前的效果和优化后的效果。修复后修复前布局文件修复前&#xff1a;修复前布局文件修复后…

redisTemplate.opsForValue()中方法讲解

查看源码可以看到redisTemplate.opsForValue()中的方法都定义在ValueOperations<K, V> 中&#xff0c;该接口中一共有17个方法&#xff1a; public interface ValueOperations<K, V> {void set(K key, V value);void set(K key, V value, long timeout, TimeUnit …

android获取未知字符串,android – 未知的URL内容:// downloads / my_dow...

我正在使用Download Manger下载一些多媒体文件并对其进行分类.我也在使用Crashlytics,这是一个错误,我经常在不同的设备和Android版本上得到它.我正在寻找你的解决方案/建议&#xff01;java.lang.IllegalArgumentException: Unknown URL content://downloads/my_downloadsat a…

spring boot配置dubbo(properties)

spring boot与dubbo配置(properties) dubbo和zookeeper配合使用&#xff0c;具体的它们之间的配置这里不说了。 一、spring boot与dubbo配置有两种方式&#xff1a; 1&#xff09;spring boot在自己的配置文件application.properties 配置dubbo。&#xff08;本篇主要说这个&…

spring boot配置dubbo(XML)

上一篇写的是spring boot在自己的properties配置文件中简单配置dubbo的步骤&#xff0c;那种配置有很多的功能&#xff08;比如超时时间、是否检查&#xff09;等等&#xff0c;配置起来也挺麻烦的&#xff0c;而我们也习惯传统的那种XML形式的dubbo配置。 这一篇写的是spring…

android线程优先级大小,android 设置线程优先级 两种方式

1) android.os.Process.setThreadPriority (int priority)或android.os.Process.setThreadPriority (int tid&#xff0c; int priority)priority&#xff1a;【-20&#xff0c; 19】&#xff0c;高优先级 -> 低优先级.(2)java.lang.Thread.setPriority (int priority)prior…

spring boot配置dubbo注意事项

spring boot配置dubbo注意事项 通过前两篇文章&#xff0c;知道了spring boot配置dubbo有两种方式。具体请回顾前两篇文章吧。 现在主要是说下spring boot在自己的application.properties 文件里配置dubbo内容&#xff0c;这种方式遇到的问题。 问题一&#xff1a;dubbo接口…

spring boot配置mybatis和事务管理

spring boot配置mybatis和事务管理 一、spring boot与mybatis的配置 1.首先,spring boot 配置mybatis需要的全部依赖如下&#xff1a; <!-- Spring Boot 启动父依赖 --> <parent><groupId>org.springframework.boot</groupId><artifactId>spr…

android hud sdk,Android HUD SDK | 百度地图API SDK

简介为了给用户提供更安全优质的服务&#xff0c;LBS开放平台针对Android平台的SDK产品引入Key认证机制&#xff0c;用户在使用之前需要先申请配置Key&#xff0c;并在程序相应位置填写您的Key。Key机制&#xff1a;每个Key仅且唯一对于1个应用验证有效&#xff0c;即对该Key配…

spring boot配置druid(德鲁伊)

spring boot配置druid(德鲁伊) 关于druid的介绍请看 阿里巴巴温少访谈 1.引入相关依赖&#xff0c;全部依赖是上一篇spring bootmybatis依赖的基础上&#xff0c;再加上下边的依赖&#xff0c;如下&#xff1a; <!-- Druid数据库连接池组件 --> <dependency><…

spring boot----简单入门

Spring Boot其实就是spring,为了简便spring框架的搭建&#xff0c;快速开发项目而推出的另一种方式。使用spring boot&#xff0c;搭建框架将变得特别快。可以有更多的时间在代码性能上优化了。 一、Spring Boot个人感觉的优点: ​ 1&#xff09;搭建一个简单运行的框架很快&…

android中给button加图标,Android,如何在我的代码中的TabButton中添加图标

在这里,我制作了5个工作正常的Tab按钮,但现在我想为每个Tab添加图标,如何相对于Tab按钮添加Tab图标….请指导/帮助我.我第一次使用stackOverflow,请告诉我在发布此代码时是否错过了任何步骤…提前致谢package com.vishesh.soapbox;import android.app.TabActivity;import andro…

android js 代码混淆工具,好用的JS(Javascript)混淆加密工具-HDS JSObfuscator 2.14版

好用的JS(Javascript)混淆加密工具-HDS JSObfuscator 2.14版书法字体2017.06.23css压缩分享一款好用的JS混淆加密工具:HDS JSObfuscator 2.14版&#xff0c;HDS JSObfuscator兼顾了JS压缩、JS混淆和JS加密三大功能。js加密工具的主要作用就是为了保护Javascript代码&#xff0c…

Maven 建立父子项目和跨项目调用内容的步骤

使用Maven管理项目&#xff0c;同时我们是做微服务&#xff0c;所以对于微服务项目来说&#xff0c;使用Maven建立起一个父子项目这种关系&#xff0c;很方便管理&#xff08;只是个人感觉&#xff09; 设计层面 &#xff08;1&#xff09;服务端和客户端肯定是分开写的&…

android支付宝运动修改器,一键修改支付宝运动步数-修改支付宝运动步数工具下载不要root手机版-西西软件下载...

修改支付宝运动步数工具是一款支付宝运动步数修改工具和教程,QQ微信也可以修改&#xff0c;最近在支付宝中推出了各种运动活动&#xff0c;很多朋友表示想要直接刷步数&#xff0c;不想去亲自运动来增加步数。那么下面手机乐园水银师小编就为大家介绍了支付宝快速刷步数的方法&…

spring boot配置tomcat部署

spring boot本身默认为jar包运行&#xff0c;可以改为war包&#xff0c;然后运行在tomcat里 具体修改的步骤如下&#xff1a; 1.在pom.xml文件里添加需要的依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>s…