Json过滤器(基于spring自定义注解的方式,对字段进行过滤,支持嵌套类型,并接口响应体格式统一封装)
发布日期: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数据的输出格式,显著提升前端数据处理的效率和用户体验。

    上一篇:SpringMVC请求过程源码解析
    下一篇:一条SQL查询是如何执行的

    发表评论

    最新留言

    很好
    [***.229.124.182]2025年04月16日 05时01分03秒