假如在SpringBoot项目中有这么一个 需求,需要对接口返回的某个UserDto对象的手机号phone只显示后四位的处理,那么如何操作?
public class UserDto {
private String name;
private String phone;
private String address;
}
-
方式一
public UserDto getUserInfo() { UserDto user = getUserDto; //在此处处理 user.setPhone(xxxxx); return user; }
在web-api层所有返回UserDto的接口中,在返回之前手动设置USerDto的phone属性只显示后四位。这种方法能实现功能,但是如果有十个接口返回了UserDto呢?或者一百个接口返回了UserDto呢?手动结果肯定是个体力活了
-
方式二
可以在UserDto中进行处理,如果在getter方法中处理会误伤到很多调用此方法的操作,显然不能再getter方法中处理。SpringBoot默认使用的json序列化框架Jackson为我们提供了一种方式:使用
@JsonSerialize
注解指定序列化方式。@JsonSerialize
需要我们实现一个序列化器;public class MyJsonSerializer extends JsonSerializer<String> { //需要提供一个无参构造方法 public MyJsonSerializer() {} @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { //对value操作,使其只显示后四位 //... } }
然后在UserDto中phone字段上为其指定序列化器:
public class UserDto { private String name; @JsonSerialize(using = MyJsonSerializer.class) private String phone; private String address; }
这样操作之后,phone字段就会按照
MyJsonSerializer
中的处理流程进行处理,就能轻松实现功能。那么问题来了,如果现在要求phone字段只显示后三位,又过一段需要显示后五位,怎么办?那这么也好办,我只需要在SpringBoot的配置文件中定一个显示的位数的
phone.showCount
属性,在MyJsonSerializer
中根据该属性进行动态处理,完美解决。但是这样就有一个问题,如何在
MyJsonSerializer
中获取SpringBoot中配置文件中设置的参数呢?也许你又想到了
@Value
注解,可行吗?我们分析一下:首先
JsonSerialize
注解中using
属性需要的一个Class,而@Value
只能在Spring容器管理的对象中才有效,也就是说需要把MyJsonSerializer
实例化一个Bean并注入到Ioc容器中,这样才能使用@Value
注解注入配置文件中的值。但是@JsonSerialize(using = MyJsonSerializer.class)
中只接收一个Class,不接受一个Bean对象,所以如果只简单的通过@Value
向MyJsonSerializer
中注入配置文件中的值是行不通的。那么该如何解决这个问题呢?
因为
@JsonSerialize(using = MyJsonSerializer.class)
接收的是一个Class对象,那我们能把配置文件中的参数作为MyJsonSerializer
的一个静态属性注入进去吗?答案是否定的,@Value
不能向静态成员变量注入属性。现在的问题就变成了如何向未被Spring容器管理的POJO对象中注入属性?
一个曲线救国的方法:
public class MyJsonSerializer extends JsonSerializer<String> { //添加一个静态属性 private static Integer showCount; //添加一个接受一个`Integer showCounc`的构造方法 public MyJsonSerializer(Integer c) { showCount = c; } }
然后只需要在外部主动的将配置文件的参数通过带参构造方法传递进来即可。
@Configuration public class MyConfig { //因为当前类为配置类,所以在这里肯定能够获取到配置文件中的变量的 @Value("${phone.showCount}") private static Integer showCount; //注入此Bean的目的并不是为了使用该Bean,而是为了将showCount变量传递给 MyJsonSerializer 类。 //一个类对象在JVM中只有单独的一份,所以在任何地方使用 MyJsonSerializer 都能获得它的showCount属性。 @Bean public MyJsonSerializer jsonSerializer() { return new MyJsonSerializer(showCount); } }
所以,至此已经成功的将Spring配置文件的值注入到了一个非Ioc容器管理的对象之中去了。
@Autowired
同理。