- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章ResponseBodyAdvice踩坑及解决由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
通过ResponseBodyAdvice实现Rest接口的日志统一管理 。
ResponseBodyAdvice原理自己百度,代码比较少但是我实践的时候发现有几个坑需要注意一下 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@RestControllerAdvice
(basePackages =
"com.alan.api.controller"
)
public
class
ApiResponseBodyAdvice
implements
ResponseBodyAdvice {
static
org.slf4j.Logger logger = LoggerFactory.getLogger(
"logback_api"
);
@Override
public
boolean
supports(MethodParameter returnType, Class converterType) {
return
(AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.
class
) ||
returnType.hasMethodAnnotation(ResponseBody.
class
));
}
@Override
public
Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class selectedConverterType, ServerHttpRequest serverHttpRequest, ServerHttpResponse response) {
HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
if
(request !=
null
){
Object obj = request.getSession().getAttribute(BaseController.session_user);
String path = request.getServletPath();
if
(StringUtils.isBlank(path)) {
path = request.getPathInfo();
}
if
(obj !=
null
) {
path = request.getPathInfo();
logger.info(
"userId:"
+ ((DataUser) obj).getUserId());
}
logger.info(
"url:"
+ path);
logger.info(
"request:"
+ JSON.toJSONString(request.getParameterMap()));
logger.info(
"response:"
+body);
}
return
body;
}
}
|
生效可能情况 。
1.ApiResponseBodyAdvice bean没有scan,没有什么配置 。
2.如果Controller的注解为@Controller,生效的方法为@ResponseBody 。
3.supports()支持类型返回false,beforeBodyWrite()不调用 。
ResponseBodyAdvice接口属于springMVC 和springBoot框架基础的底层切面接口;实现这个接口的类,可以修改直接作为 ResponseBody类型处理器的返回值,即进行功能增强.
返回值为HpptEntity 。
加了@ResponseBody或@RestController注解, 。
实现了这个接口的类,处理返回的json值在传递给 HttpMessageConverter之前;应用场景在spring项目开发过程中,对controller层返回值进行修改增强处理。比如返回值5,需要封装成 。
{"code":"0","data":5,,"msg":"success"}格式返回前端 。
接口源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public
interface
ResponseBodyAdvice<T> {
/ * *
*该组件是否支持给定的控制器方法返回类型
*和选择的{
@code
HttpMessageConverter}类型。
返回类型
*
@param
converterType选择的转换器类型
*
@return
{
@code
true
}如果{
@link
#beforeBodyWrite}应该被调用;
* {
@code
false
}否则
* /
boolean
supports(MethodParameter returnType, Class<?
extends
HttpMessageConverter<?>> converterType);
/ * *
*在{
@code
HttpMessageConverter}被选中之后和之前调用
*它的write方法被调用。
*
@param
body要写入的主体
控制器方法的返回类型:
*
@param
selectedContentType通过内容协商选择的内容类型
*
@param
selectedConverterType选择写入响应的转换器类型
*
@param
request当前请求
*
@param
response当前响应
*
@return
传入的主体或修改过的(可能是新的)实例
* /
@Nullable
T beforeBodyWrite(
@Nullable
T body, MethodParameter returnType, MediaType selectedContentType,
Class<?
extends
HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response);
}
|
对controller层返回值进行修改增强处理。比如返回值5,需要封装成 。
{"code":"0","data":5,,"msg":"success"} 格式返回前端 。
controller层业务代码:
1
2
3
4
5
6
7
8
9
10
|
@RestController
//此注解包含@ResponseBody注解
@RequestMapping
(
"/nandao"
)
public
class
ResponseBodyAdviceController {
@RequestMapping
(value =
"/hello"
, method = RequestMethod.GET)
public
int
hello() {
//业务代码省略
return
5
;
}
}
|
实现ResponseBodyAdvice接口的切面类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/**
*此注解针对controller层的类做增强功能,即对加了@RestController注解的类进行处理
*/
@ControllerAdvice
(annotations = RestController.
class
)
public
class
RestResultWrapper
implements
ResponseBodyAdvice<Object> {
@Override
public
boolean
supports(MethodParameter returnType, Class<?
extends
HttpMessageConverter<?>> converterType) {
return
true
;
}
@Override
public
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);
}
}
|
返回公共类的创建:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
/**
* @author nandao
* Created on 2021/1/12-21:47.
* 统一返回Rest风格的数据结构
*/
public
class
RestResult<T>
implements
Serializable {
/**
* 成功的code码
*/
private
String code =
"2000"
;
/**
* 成功时返回的数据,失败时返回具体的异常信息
*/
private
T data;
/**
* 请求失败返回的提示信息,给前端进行页面展示的信息
*/
private
String message ;
public
RestResult() {
}
@Override
public
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;
}
public
String getCode() {
return
code;
}
public
void
setCode(String code) {
this
.code = code;
}
public
T getData() {
return
data;
}
public
void
setData(T data) {
this
.data = data;
}
public
String getMessage() {
return
message;
}
public
void
setMessage(String message) {
this
.message = message;
}
}
|
到此切面增强功能就实现了,可以直接在实战项目中使用.
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我.
原文链接:https://blog.csdn.net/zuo_xiaosi/article/details/103520172 。
最后此篇关于ResponseBodyAdvice踩坑及解决的文章就讲到这里了,如果你想了解更多关于ResponseBodyAdvice踩坑及解决的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
前言 每日站会(Daily Standup)是团队统一节奏的、在固定时间发生的、帮助团队内部快速同步进展的敏捷实践活动: 站会的目的是让团队能更好地对齐 Sprint 目标;
jdbcTemplate 中的queryForList,你真的懂吗? 你想象中的queryForList是不是应该长成下面这种模样? String sql = "select *
python是一门清晰简洁的语言,如果你对一些细节不了解的话,就会掉入到那些深不见底的“坑”里,下面,我就来总结一些python里常见的坑。 列表创建和引用 嵌套列表的创建 使用*号来创建一个
如今,在DevOps当中建立安全体系显得比以往任何时候都更加重要。《2021年企业DevOps技能提升报告》指出,56%的受访者表示DevSecOps已经成为自动化工具中的一大必备要素。然而,D
前言 相信看到这个题目,可能大家都觉得是一个老生常谈的月经topic了。一直以来其实把握一个“值传递”基本上就能理解各种情况了,不过最近遇到了更深一点的“小坑”,与大家分享一下。 首先还是从最简
前言 Go 中的for range组合可以和方便的实现对一个数组或切片进行遍历,但是在某些情况下使用for range时很可能就会被"坑",下面用一段代码来模拟下:
大家好,我是明哥。 在开始之前,先考你一个非常 Go 味的经典问题:如何判断一个 interface{} 的值是否为 nil ? 这也是面试有可能会被问到的一个问题,这个问题很 “迷”,平时
ava并发包有很大一部分内容都是关于并发容器的,因此学习和搞懂这部分的内容很有必要。 Java 1.5 之前提供的同步容器虽然也能保证线程安全,但是性能很差,而 Java 1.5 版本之后提供的并发
大家好,我是煎鱼。 前几天在读者交流群里看到一位小伙伴,针对 interface 的使用有了比较大的疑惑。 无独有偶,我也在网上看到有小伙伴在 Go 面试的时候被问到了:
我是一名优秀的程序员,十分优秀!