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; }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论