赞
踩
很多时候就是为了偷懒,swagger可以屏蔽接口文档中的字段,却不能屏蔽真实返回的数据,故而需要再controller返回的时候再做处理
参考了springboot2 jackson 实现动态返回类字段,做了一些改动
经验证对简单接口,还可以,稍微复杂的嵌套就不行,可以使用@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;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。