java过滤器只过滤json请求,利用Jackson的JsonFilter来实现动态过滤数据列(数据列权限控制)...

利用Jackson的JsonFilter来实现动态过滤数据列。

也就是说,同一个实体,你配置了不同的@JsonFilter,通过Jackson展现的结果可以是不一样的。

举个栗子:

AAffA0nNPuCLAAAAAElFTkSuQmCC@lombok.Datapublic class User{

String username;

String password;

Integer age;

String gender;

String blog;

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

默认不做任何配置的话,通过Jackson序列化出来的结果是:

AAffA0nNPuCLAAAAAElFTkSuQmCC{

"username" : "tomcatandjerry",

"password" : "123456",

"age" : 36,

"gender" : "男",

"blog" : "http://www.cnblogs.com/tomcatandjerry/"

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

可是password不应该要展示,方法有多种:

方法1:在不想序列化的字段上加注解JsonProperty:@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)//Jackson

@JSONField(serialize = false)//fastjson

String password;

方法2:

2.1在User类上面加注解JsonFilter:@JsonFilter("non-password")

public class User {

...

}

2.2 配置FilterProvider

测试方法&配置如下:

AAffA0nNPuCLAAAAAElFTkSuQmCCpublic class JsonFilterTest {    private ObjectMapper setupJsonFilter(){

ObjectMapper mapper = new ObjectMapper();

String[] beanProperties = new String[]{"password"};

String nonPasswordFilterName = "non-password";//需要跟User类上的注解@JsonFilter("non-password")里面的一致

FilterProvider filterProvider = new SimpleFilterProvider()

.addFilter(nonPasswordFilterName, SimpleBeanPropertyFilter.serializeAllExcept(beanProperties));                //serializeAllExcept 表示序列化全部,除了指定字段                //filterOutAllExcept 表示过滤掉全部,除了指定的字段        mapper.setFilterProvider(filterProvider);        return mapper;

}

@Test    public void testJsonFilter() throws JsonProcessingException {

User user = new User();

user.setUsername("tomcatandjerry");

user.setPassword("123456");

user.setAge(36);

user.setGender("男");

System.out.println(setupJsonFilter().writeValueAsString(user));

}

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

打印测试结果:

AAffA0nNPuCLAAAAAElFTkSuQmCC{

"username" : "tomcatandjerry",

"age" : 36,

"gender" : "男",

"blog" : "http://www.cnblogs.com/tomcatandjerry/"

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

小结:

看上去似乎使用@JsonProperty更简单。

但是当有一堆字段需要配置,而且整个项目都需要统一处理的时候,后者@JsonFilter是一个不错的选择。

扩展:

同一个API,如果我想不同的人看到不一样的结果呢?

比如同一个用户API,有的展示username+age, 有的展示username+gender等

这个时候JsonFilter就非常适合了。

有人可能会问:不对啊?一个对象只能配置一个JsonFilter,怎么动态切换不同的Filter?

对的,一个对象只能配置一个JsonFilter,但只要稍加修改,就能实现??

思路:

既然一个对象只能配置一个JsonFilter,那么靠一个对象来动态展示不同的属性是不可能的。

我们可以多写几个对象,都继承User对象,不同的子类里面使用不同的JsonFilter

AAffA0nNPuCLAAAAAElFTkSuQmCC@JsonFilter("normal-user")public class UserNormal extends User{ //空class,里面没有任何属性}

@JsonFilter("admin")public class UserAdmin extends User{ //空class,里面没有任何属性}

AAffA0nNPuCLAAAAAElFTkSuQmCC

利用Spring的切点,根据当前用户的角色,替换返回值为不同的子类

AAffA0nNPuCLAAAAAElFTkSuQmCC原本:public class UserService{  

public User get(String id){

}

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

利用切点(可以自定义注解,加到方法上,切在注解上面),替换返回的对象为子类:

具体需要用到的:

1) 扫描并缓存子类

2) @Aspect切点,@Around(value="比如:自定义注解")

3) 利用反射,创建出子类对象,BeanUtils.copyProperties

这样看似调用userService.get("id")返回的是User对象,其实可能已经替换成某一个子类了。

在ObjectMapper配置多个Filter,就实现了动态展示不同属性,且对开发人员透明。

小结:

优点: 对开发透明

缺点:一个对象需要写多个子类,虽然是空class

这也算是一种数据列权限控制的一种解决方案吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值