当前位置: 代码网 > it编程>编程语言>Java > springboot如何根据配置屏蔽接口返回字段

springboot如何根据配置屏蔽接口返回字段

2024年08月09日 Java 我要评论
springboot根据配置屏蔽接口返回字段很多时候就是为了偷懒,swagger可以屏蔽接口文档中的字段,却不能屏蔽真实返回的数据,故而需要再controller返回的时候再做处理参考了,做了一些改动

springboot根据配置屏蔽接口返回字段

很多时候就是为了偷懒,swagger可以屏蔽接口文档中的字段,却不能屏蔽真实返回的数据,故而需要再controller返回的时候再做处理

参考了,做了一些改动

经验证对简单接口,还可以,稍微复杂的嵌套就不行,可以使用@jsonignore,路径为

com.fasterxml.jackson.annotation.jsonignore
<dependency>
            <groupid>org.aspectj</groupid>
            <artifactid>aspectjweaver</artifactid>
            <version>1.9.6</version>
        </dependency>

1.类的数据域

import lombok.allargsconstructor;
import lombok.data;
import lombok.noargsconstructor;

@noargsconstructor
@allargsconstructor
@data
public class jsonfields {

    boolean include = true;

    string[] fields = {};

}

2.开启的注解

写在controller的方法上

import java.lang.annotation.*;

@target({ elementtype.parameter, elementtype.method})
@retention(retentionpolicy.runtime)
@documented
public @interface jsoninclude {
    /**
     * 排除
     * @return
     */
    boolean include() default true;

    /**
     * 字段类型
     * @return
     */
    class clazz();

    /**
     * 过滤的字段名
     * @return
     */
    string[] fields() default {};
}

3.json过滤器

import com.fasterxml.jackson.core.jsongenerator;
import com.fasterxml.jackson.databind.serializerprovider;
import com.fasterxml.jackson.databind.ser.beanpropertyfilter;
import com.fasterxml.jackson.databind.ser.filterprovider;
import com.fasterxml.jackson.databind.ser.propertywriter;
import com.fasterxml.jackson.databind.ser.propertyfilter;
import com.fasterxml.jackson.databind.ser.impl.simplebeanpropertyfilter;

import java.util.hashmap;
import java.util.map;

public class jsonfilter extends filterprovider {

    /**
     * 对于规则我们采用 threadlocal 封装,防止出现线程安全问题
     */
    private static final threadlocal<map<class<?>, jsonfields>> include = new threadlocal<>();

    /**
     * 清空规则
     */
    public static void clear() {
        include.remove();
    }


    /**
     * 设置过滤规则
     * @param clazz 规则
     */
    public static void add(boolean isinclude, class<?> clazz, string... fields) {
        map<class<?>, jsonfields> map = include.get();
        if (map == null) {
            map = new hashmap<>();
            include.set(map);
        }
        jsonfields jsonfields = new jsonfields(isinclude,fields);
        map.put(clazz, jsonfields);
    }

    /**
     * 重写规律规则
     */
    @override
    public propertyfilter findpropertyfilter(object filterid, object valuetofilter) {
        return new simplebeanpropertyfilter() {
            @override
            public void serializeasfield(
                    object pojo,
                    jsongenerator jg,
                    serializerprovider sp,
                    propertywriter pw
            ) throws exception {
                if (apply(pojo.getclass(), pw.getname())) {
                    pw.serializeasfield(pojo, jg, sp);
                } else if (!jg.canomitfields()) {
                    pw.serializeasomittedfield(pojo, jg, sp);
                }
            }
        };
    }

    @deprecated
    @override
    public beanpropertyfilter findfilter(object filterid) {
        throw new unsupportedoperationexception("不支持访问即将过期的过滤器");
    }

    /**
     * 判断该字段是否需要,返回 true 序列化,返回 false 则过滤
     * @param type 实体类类型
     * @param name 字段名
     */
    public boolean apply(class<?> type, string name) {
        map<class<?>, jsonfields> map = include.get();
        if (map == null) {
            return true;
        }
        jsonfields jsonfields = map.get(type);
        string[] fields = jsonfields.getfields();
        if (jsonfields.isinclude()){
            for (string field : fields) {
                if (field.equals(name)) {
                    return true;
                }
            }
            return false;
        } else{
            for (string field : fields) {
                if (field.equals(name)) {
                    return false;
                }
            }
            return true;
        }
    }
}

4.过滤器切面

jsonfilter.clear();解决多线程下面的并发的问题

import lombok.extern.slf4j.slf4j;
import org.aspectj.lang.joinpoint;
import org.aspectj.lang.annotation.aspect;
import org.aspectj.lang.annotation.before;
import org.aspectj.lang.annotation.pointcut;
import org.aspectj.lang.reflect.methodsignature;
import org.springframework.stereotype.component;

import java.lang.reflect.method;

@slf4j
@component
@aspect
public class jsonfilteraop {

    @pointcut("@annotation(com.tt.framework.web.filter.jsoninclude)")
    public void controlleraspect(){}


    /**
     * (1)@annotation:用来拦截所有被某个注解修饰的方法
     * (2)@within:用来拦截所有被某个注解修饰的类
     * (3)within:用来指定扫描的包的范围
     */
    @before("controlleraspect()")
    public void dobefore(joinpoint joinpoint) throws throwable{
        jsonfilter.clear();
        //从切面织入点处通过反射机制获取织入点处的方法
        methodsignature signature = (methodsignature) joinpoint.getsignature();
        //获取切入点所在的方法
        method method = signature.getmethod();
        jsoninclude jsoninclude = method.getannotation(jsoninclude.class);
        jsonfilter.add(jsoninclude.include(),jsoninclude.clazz(),jsoninclude.fields());
    }


}

5.如何使用

启动类增加此过滤器

@slf4j
@springbootapplication
public class fayserverapplication {

    public static void main(string[] args) {
        try {
            configurableapplicationcontext context = springapplication.run(fayserverapplication.class, args);
            objectmapper objectmapper = context.getbean(objectmapper.class);
            objectmapper.setfilterprovider(new jsonfilter());

        } finally {
            log.info("server start finish");
        }
    }
}

include = true包含则表示仅显示包含的数据,include = false则排除这配置的fields,显示没有配置的字段。

没有此注解的则不受影响

 @jsoninclude(include = true,clazz = lxrjbhysth.class,fields = {"dg","mz"})
    @apioperation("金不换规则")
    @getmapping("jbhrule")
    public responseresult<list<lxrjbhysth>> jbhrule(string dg){
        list<lxrjbhysth> lxrjbhysths = extlxrjbhysthservice.selectbydg(dg);
        responseresult<list<lxrjbhysth>> resp = new responseresult<>(true);
        resp.setdata(lxrjbhysths);
        return resp;
    }

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com