
Json过滤器(基于spring自定义注解的方式,对字段进行过滤,支持嵌套类型,并接口响应体格式统一封装)
拦截响应体:通过 自定义消息转换器:开发一个自定义的 注解定义:使用自定义注解 2. 实现
统一响应格式:可以将接口的返回格式统一封装到一个规范模板中。 支持多级嵌套结构:针对包含容器或其他复杂对象的场景进行二次过滤。 缓存机制:优化性能,避免重复计算。
发布日期:2021-05-07 13:36:03
浏览次数:23
分类:精选文章
本文共 3471 字,大约阅读时间需要 11 分钟。
在实际的开发过程中,经常会遇到后台需要返回给前端的JSON数据中包含不必要属性的问题。为了实现对返回数据的精确控制,可以通过自定义注解和Spring的消息转换器来实现字段过滤。以下是具体实现方法和优化思路。
整体思路
ResponseBodyAdvice
在响应体写入之前对数据进行处理,获取相关参数并配置过滤规则。HttpMessageConverter
,用于处理过滤后的数据转换。@SerializeField
来指定需要保留的字段,支持包含和排除字段功能。实现步骤
1. 定义自定义注解
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface SerializeField { Class clazz(); String[] includes() default {}; String[] excludes() default {};}
2. 实现ResponseBodyAdvice
@ControllerAdvicepublic class JsonFilterResponseBodyAdvice implements ResponseBodyAdvice { @Override public Object beforeBodyWrite(Object object, MethodParameter methodParameter, MediaType mediaType, Class > converterType, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { if (methodParameter.getMethod().isAnnotationPresent(SerializeField.class)) { JsonFilterObject jsonFilterObject = new JsonFilterObject(); handleAnnotation(methodParameter.getMethod().getAnnotation(SerializeField.class), jsonFilterObject); jsonFilterObject.setObject(object); return jsonFilterObject; } return object; } private void handleAnnotation(SerializeField serializeField, JsonFilterObject jsonFilterObject) { // 提取注解参数进行处理 // 具体实现逻辑可根据需求扩展 }}
3. 实现自定义消息转换器
public class JsonFilterHttpMessageConverter extends FastJsonHttpMessageConverter { // 其他配置可参考FastJsonHttpMessageConverter的实现 @Override protected void writeInternal(Object obj, HttpOutputMessage outputMessage) throws IOException { if (obj instanceof JsonFilterObject) { JsonFilterObject jsonFilterObject = (JsonFilterObject) obj; // 使用SimpleSerializerFilter进行字段过滤 String text = JSON.toJSONString(jsonFilterObject.getObject(), new SimpleSerializerFilter( jsonFilterObject.getIncludes(), jsonFilterObject.getExcludes() ), this.features); OutputStream out = outputMessage.getBody(); out.write(text.getBytes(this.charset)); } else { // 未声明注解直接序列化 OutputStream out = outputMessage.getBody(); String text = JSON.toJSONString(obj, this.features); out.write(text.getBytes(this.charset)); } }}
使用示例
1. 控制层
@RestControllerpublic class DemoController { @GetMapping("user") @SerializeField(clazz = User.class, includes = {"name", "id"}) public User getUser() { User user = new User(1L, "jjc", "123456"); return user; }}
2. 返回结果示例
{ "id": 1, "name": "jjc"}
3. 复杂对象处理
@GetMapping("userMulti")@MultiSerializeField(clazz = User.class, includes = {"name", "id", "addresses"})public User getUserMulti() { User user = new User(1L, "jjc", "123456"); List addresses = new ArrayList<>(); addresses.add(new Address("liuyis's home", "liuyis's school", user)); addresses.add(new Address("liuyis's home2", "liuyis's school2", user)); user.setAddresses(addresses); return user;}
4. 返回结果
{ "addresses": [ { "home": "liuyis's home", "school": "liuyis's school" }, { "home": "liuyis's home2", "school": "liuyis's school2" } ], "id": 1, "name": "jjc"}
优化与扩展
通过以上方法,开发者可以灵活控制JSON数据的输出格式,显著提升前端数据处理的效率和用户体验。
发表评论
最新留言
很好
[***.229.124.182]2025年04月16日 05时01分03秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
windows消息机制(转)
2019-03-06
STL笔试面试题总结(干货)(转)
2019-03-06
XML 和 HTML 之间的差异
2019-03-06
qt中moc的作用
2019-03-06
阿里钉钉面试题
2019-03-06
华为社招笔试
2019-03-06
MFC的Dlg和App什么区别?应用程序类与对话框类
2019-03-06
C\C++下获取系统进程或线程ID(转)
2019-03-06
VS环境变量(转)
2019-03-06
C++中找资源或者函数的方法
2019-03-06
一些留给自己的思考题(只求回过头来能够有所获)
2019-03-06
SQL函数返回表的写法
2019-03-06
delete对象时会自动调用类的析构函数
2019-03-06
C++ 子类对象直接赋值给父类对象可行,反过来不行
2019-03-06
WMWare下安装centOS7,并使用xshell进行连接记录.
2019-03-06
linux下同一个动态库名为何辣么多的.so文件
2019-03-06
SQL联表的方式(逗号, Left Join, Right Join)
2019-03-06
牛客网输入输出举例
2019-03-06
字符串初始化时的注意点
2019-03-06
dll路径加载顺序
2019-03-06