项目简介
一个轻量级的 Java 字段过滤工具,只需两个注解即可优雅地控制接口返回字段。
为何开发这个项目?
Java 在平时开发中,我们难免会遇到不想返回某些字段的情况,又或者某些字段的值过于敏感不方便展示,这种情况我们通常会新建一个类,包装成一个视图对象。那么随着业务的增长,视图对象会越来越多,所以开发了这个项目。
会不会有使用成本?
不会,仅需配置 2 个注解即可完成所有功能。并且可以将粒度细分到方法,返回同一对象,A 方法返回所有字段,B 方法返回需要的字段。
GitHub 地址:sensitive-field-filter
快速开始
引入依赖
目前仅支持 Spring Boot 项目,引入依赖
1 2 3 4 5
| <dependency> <groupId>io.github.soora33</groupId> <artifactId>sft</artifactId> <version>1.0.0</version> </dependency>
|
注解说明
注解共有三个,其中 @SftFilter
加在需要过滤的实体类字段上,@SftObjectFilter
和 @SftResponseFilter
根据方法的返回值选择其中一个。注解详情如下:
@SftFilter:配置在实体类上需要过滤的字段
可配置项:
value:过滤后的字段值,默认为 null
@SftObjectFilter: 配置在方法上,适用于直接返回对象,配置后会对该方法的返回值按照 SftFilter
配置的字段进行过滤
可配置项:
entity:方法的返回值类型
preserveField:是否需要保留字段,默认为 true
@SftResponseFilter:配置在方法上,适用于封装格式对象,配置后会对该方法的返回值按照 SftFilter
配置的字段进行过滤(默认获取封装对象中 data
中的对象)
可配置项:
entity:方法的返回值类型
key:封装数据体中存储数据的字段名,默认为 data
preserveField:是否需要保留字段,默认为 true
对于 @SftObjectFilter
:用在直接返回视图对象的方法
对于 @SftResponseFilter
:用在返回经过统一格式封装的对象,如 Result.success (data),AjaxResult.success (data) 等等
⚠️⚠️⚠️ 注意:如果配置 preserveField
为 false,则会将返回值中的实体类对象转为 LinkedHashMap
。因为去除过滤字段的实现方式是通过将非过滤字段加入到 Map 内实现的。如果对业务有影响,请不要使用!!!
如果看不明白没关系,下面提供了示例,结合示例更容易明白。
使用示例
实体类说明:
以下面 Person
举例说明,并设置 name 字段为 null,email 为 Nah
1 2 3 4 5 6 7 8 9 10
| @Data @AllArgsConstructor @NoArgsConstructor public class Person { private String id; @SftFilter private String name; @SftFilter(value = "Nah") private String email; }
|
SftObjectFilter
SftObjectFilter
注解用于对象的过滤,可配置的参数有 2 个:
entity:方法的返回值类型
preserveField:是否需要保留字段,默认为 true
下面介绍常见的两种场景
1. 返回单个对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @SftObjectFilter(entity = Person.class) public Person getPerson() { Person person = new Person("1","azki","azki@email.com"); return person; }
class com.sora.domain.Person Person(id=1, name=null, email=Nah)
@SftObjectFilter(entity = Person.class, preserveField = false) public Person getPerson() { Person person = new Person("1","azki","azki@email.com"); return person; }
class java.util.LinkedHashMap {id=1}
|
2. 返回集合类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @SftObjectFilter(entity = Person.class) public List<Person> getPerson() { Person person = new Person("1","azki","azki@email.com"); Person person2 = new Person("2","nayuta","nayuta@email.com"); Person person3 = new Person("3","aznayu","aznayu@email.com"); ArrayList<Person> list = Lists.newArrayList(person, person2, person3); return list; }
class java.util.ArrayList [Person(id=1, name=null, email=Nah), Person(id=2, name=null, email=Nah), Person(id=3, name=null, email=Nah)]
@SftObjectFilter(entity = Person.class, preserveField = false) public List<Person> getPerson() { Person person = new Person("1","azki","azki@email.com"); Person person2 = new Person("2","nayuta","nayuta@email.com"); Person person3 = new Person("3","aznayu","aznayu@email.com"); ArrayList<Person> list = Lists.newArrayList(person, person2, person3); return list; }
class java.util.ArrayList [{id=1}, {id=2}, {id=3}]
|
SftResponseFilter
在使用 SftResponseFilter
之前,我先来介绍一下目前 Java 项目的统一返回值格式,大体上分为两种:
第一种是以对象的形式,通过字段存储数据,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class AjaxResult implements Serializable { @Serial private static final long serialVersionUID = -7126327333321005351L; private String msg; private Integer code; private Object data;
private static AjaxResult rest(Object object) { AjaxResult ajaxResult = new AjaxResult(); ajaxResult.setMsg("success"); ajaxResult.setData(object); ajaxResult.setCode(200); return ajaxResult; }
public static AjaxResult success(Object object) { return rest(object); } }
|
第二种则是 Map 的形式存储数据,内部通过 put 的方式存储数据,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class AjaxResultMap extends HashMap<Object,Object> implements Serializable { @Serial private static final long serialVersionUID = -7127333321005351L; private static String msg; private Integer code; private Object data;
private AjaxResultMap(Object object) { super.put("msg", "success"); super.put("data", object); super.put("code", 200); }
public static AjaxResultMap success(Object object) { return new AjaxResultMap(object); } }
|
无论你使用的是哪种格式包装数据,项目内部都对其进行了实现,使用方法上是完全一样的!这里仅使用其中一种进行演示。下面是具体的使用方法。
SftResponseFilter
注解用于被封装格式封装的数据,可配置的参数有 3 个:
entity:方法的返回值类型
key:封装数据体中存储数据的字段名,默认为 data
preserveField:是否需要保留字段,默认为 true
1. 返回单个对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @SftResponseFilter(entity = AjaxResult.class) public AjaxResult getPerson() { Person person = new Person("1","azki","azki@email.com"); return AjaxResult.success(person); }
class com.sora.result.AjaxResult AjaxResult(code=200, msg=success, data=Person(id=1, name=null, email=Nah))
@SftResponseFilter(entity = AjaxResult.class, preserveField = false) public AjaxResult getPerson() { Person person = new Person("1","azki","azki@email.com"); return AjaxResult.success(person); }
class com.sora.result.AjaxResult AjaxResult(code=200, msg=success, data={id=1})
|
2. 返回集合类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| @SftResponseFilter(entity = AjaxResult.class) public AjaxResult getPerson() { Person person = new Person("1","azki","azki@email.com"); Person person2 = new Person("2","nayuta","nayuta@email.com"); Person person3 = new Person("3","aznayu","aznayu@email.com"); ArrayList<Person> list = Lists.newArrayList(person, person2, person3); return AjaxResult.success(list); }
class com.sora.result.AjaxResult AjaxResult(code=200, msg=success, data=[Person(id=1, name=null, email=Nah), Person(id=2, name=null, email=Nah), Person(id=3, name=null, email=Nah)]) @SftResponseFilter(entity = AjaxResult.class, preserveField = false) public AjaxResult getPerson() { Person person = new Person("1","azki","azki@email.com"); Person person2 = new Person("2","nayuta","nayuta@email.com"); Person person3 = new Person("3","aznayu","aznayu@email.com"); ArrayList<Person> list = Lists.newArrayList(person, person2, person3); return AjaxResult.success(list); }
class com.sora.result.Result Result(code=200, msg=操作成功, data=[{id=1}, {id=2}, {id=3}])
|
3. 自定义 key 演示
如果说你存储数据的字段不叫 data
,那么使用 key
配置正确的字段名就可以,例如小明的项目使用类名为 Result
作为封装对象,并且使用 body
字段存储数据,那么可以这么写:
1 2 3 4 5 6 7 8
| @SftResponseFilter(entity = Result.class, key = "body") public Result getPerson() { Person person = new Person("1","azki","azki@email.com"); Person person2 = new Person("2","nayuta","nayuta@email.com"); Person person3 = new Person("3","aznayu","aznayu@email.com"); ArrayList<Person> list = Lists.newArrayList(person, person2, person3); return Result.success(list); }
|
结束语
欢迎各位提出建议,后续也会优化性能不断扩展新功能