太强 ! SpringBoot中出入参增强的5种方法 : 加解密、脱敏、格式转换、时间时区处理

原创 码到三十五 码到三十五 2024年07月27日 20:10 广东

  • 1. 使用@JsonSerialize和@JsonDeserialize注解

  • 2. 全局配置Jackson的ObjectMapper

  • 3. 使用@ControllerAdvice配合@InitBinder

  • 4.  自定义HttpMessageConverter

  • 5. 使用AOP进行切面编程

  • 结语

在Spring Boot中,对接口的请求入参和出参进行自定义的增强或者修改,通常有以下几种方法:

1. 使用@JsonSerialize@JsonDeserialize注解

可以在实体类的字段上使用这两个注解来指定自定义的序列化器和反序列化器。

「使用场景」

  • 当需要对某个特定字段进行自定义的序列化和反序列化时。

  • 当实体类中的某些字段类型不是标准的JSON类型,需要转换成JSON能识别的格式时。

  • 需要在序列化和反序列化过程中添加自定义逻辑,如加密、解密、格式转换等。

首先,定义自定义的序列化器和反序列化器:

public class CustomLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {    @Override    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {        gen.writeString(value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));    }}
public class CustomLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {    @Override    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {        return LocalDateTime.parse(p.getValueAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));    }}

然后,在实体类中使用这些注解:

public class MyEntity {    @JsonSerialize(using = CustomLocalDateTimeSerializer.class)    @JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)    private LocalDateTime dateTime;
    // getters and setters}

2. 全局配置Jackson的ObjectMapper

通过配置ObjectMapper来全局地改变序列化和反序列化的行为,可以添加自定义的模块或配置属性。

「使用场景」

  • 当项目中多个实体类需要应用相同的序列化和反序列化规则时。

  • 需要在全局范围内统一处理日期、时间、枚举等类型的序列化和反序列化。

  • 需要对ObjectMapper进行全局的配置,如设置默认的时区、日期格式等。

创建一个自定义模块,并注册序列化器和反序列化器:

public class CustomJacksonModule extends SimpleModule {    public CustomJacksonModule() {        addSerializer(LocalDateTime.class, new CustomLocalDateTimeSerializer());        addDeserializer(LocalDateTime.class, new CustomLocalDateTimeDeserializer());    }}

然后,配置ObjectMapper

@Beanpublic Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {    return builder -> {        builder.modules(new CustomJacksonModule());    };}

3. 使用@ControllerAdvice配合@InitBinder

要对Spring MVC的控制器进行全局的配置,可以使用@ControllerAdvice注解。然后,在这个类中使用@InitBinder注解的方法来注册自定义的属性编辑器。

「注意」@InitBinder主要用于处理表单数据的绑定,对于JSON数据的序列化和反序列化,它并不是最直接的方法。但如果是处理非JSON格式的请求体(如表单数据),则可以使用此方法。

「使用场景」(对于JSON数据,更偏向于使用其他方法;对于表单数据):

  • 当需要对表单数据的绑定进行自定义处理时。

  • 当需要在多个控制器中复用相同的表单数据绑定逻辑时。

创建一个自定义的属性编辑器:

public class CustomLocalDateTimeEditor extends PropertyEditorSupport {    @Override    public void setAsText(String text) throws IllegalArgumentException {        setValue(LocalDateTime.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));    }
    @Override    public String getAsText() {        LocalDateTime value = (LocalDateTime) getValue();        return value.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));    }}

然后,在@ControllerAdvice类中注册这个属性编辑器:

@ControllerAdvicepublic class CustomControllerAdvice {    @InitBinder    public void initBinder(WebDataBinder binder) {        binder.registerCustomEditor(LocalDateTime.class, new CustomLocalDateTimeEditor());    }}

4.  自定义HttpMessageConverter

可以编写自定义的HttpMessageConverter来处理特定的媒体类型,并在其中实现自定义的序列化和反序列化逻辑。然后,将其注册到Spring MVC的配置中。

「使用场景」

  • 当Spring Boot默认的HttpMessageConverter无法满足自定义的序列化和反序列化需求时。

  • 当需要处理非标准的媒体类型时,如自定义的二进制格式或文本格式。

  • 当需要在序列化和反序列化过程中应用复杂的业务逻辑时。

创建一个自定义的HttpMessageConverter

public class CustomLocalDateTimeConverter extends MappingJackson2HttpMessageConverter {    public CustomLocalDateTimeConverter() {        super();        ObjectMapper customObjectMapper = new ObjectMapper();        customObjectMapper.registerModule(new CustomJacksonModule());        setObjectMapper(customObjectMapper);    }}

然后,在配置类中注册这个转换器:

@Configurationpublic class WebConfig implements WebMvcConfigurer {    @Override    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {        converters.add(0, new CustomLocalDateTimeConverter());    }}

5. 使用AOP进行切面编程

可以使用Spring AOP来对控制器的方法进行切面,从而在方法执行前后进行自定义的序列化和反序列化操作。

「使用场景」

  • 当需要在不修改原有业务代码的情况下,对方法入参和出参进行额外的处理时。

  • 当需要对多个控制器或方法中的入参和出参应用统一的处理逻辑时。

  • 当处理逻辑与业务逻辑相对独立,且需要保持代码结构清晰时。

首先,定义一个切面:

@Aspect@Componentpublic class CustomSerializationAspect {    @Before("execution(* com.example.controller..*.*(..)) && args(..,@RequestParam(..),@RequestBody(..))")    public void beforeControllerMethod(JoinPoint joinPoint) {        // 在这里可以修改入参,但通常不建议这么做,因为这会改变方法的签名        // 更常见的是在处理响应后进行修改    }
    @AfterReturning(pointcut = "execution(* com.example.controller..*.*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", returning = "result")    public void afterControllerMethod(JoinPoint joinPoint, Object result) {        // 在这里可以修改出参,例如将LocalDateTime转换为特定格式的字符串        if (result instanceof MyEntity) {            MyEntity entity = (MyEntity) result;            // 假设你想在这里修改entity的dateTime字段        }    }}

注意:AOP通常用于横切关注点的处理,如日志、事务管理等,而不是用于修改方法的入参和出参。如果你需要修改入参和出参,通常建议使用其他方法,如自定义的HttpMessageConverter@ControllerAdvice。上面的AOP中捕获方法的执行,但实际上修改入参是不推荐的,而出参的修改也通常不是AOP的最佳用途。如确实要在AOP中修改出参,考虑使用@AfterReturning注解。更常见和推荐的做法使用Jackson的序列化特性或@ControllerAdvice来全局处理响应体的格式。

结语

选择哪种方法取决于具体需求。对于简单的自定义需求,使用@JsonSerialize@JsonDeserialize注解是最直接和简单的方式。而对于更复杂的全局配置或跨多个控制器的需求,则可能需要使用ObjectMapper的配置或@ControllerAdvice


关注『 码到三十五 』,日有所获

码到三十五

主要分享正经的开发技术(原理,架构,实践,源码等),以输出驱动输入;当然偶尔会穿插点生活琐碎,顺便吃个瓜,目的嘛,搞点精准流量,看能不能发发广告。

127篇原创内容

公众号

图片

 如对你有帮助, 点赞+转发+在看+收藏 就是最大的支持!

Spring Boot是一个用于创建独立的、基于生产级别的Spring应用程序的框架。MyBatis是一个持久层框架,它可以与Spring Boot集成,用于简化数据库操作。脱敏处理是指在处理敏感数据时,对数据进行加密或者替换等操作,以保护数据的安全性。 在Spring Boot,可以使用MyBatis-Plus来实现脱敏处理。MyBatis-Plus是MyBatis的增强工具,提供了一些方便的功能,包括脱敏处理。 要在Spring Boot实现脱敏处理,可以按照以下步骤进行操作: 1. 添加依赖:在`pom.xml`文件添加MyBatis-Plus的依赖。 ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>最新版本</version> </dependency> ``` 2. 创建实体类:创建对应数据库表的实体类,并在需要脱敏的字段上添加注解。 ```java public class User { private Long id; @SensitiveInfo(type = SensitiveType.NAME) private String name; @SensitiveInfo(type = SensitiveType.PHONE) private String phone; // 其他字段... } ``` 3. 创建脱敏处理器:创建一个脱敏处理器,用于对敏感字段进行脱敏操作。 ```java public class SensitiveInfoHandler { public static String handle(String value, SensitiveType type) { // 根据不同的脱敏类型进行相应的处理 // 例如,对于姓名进行脱敏,可以将姓保留,将名替换为* if (type == SensitiveType.NAME) { return value.substring(0, 1) + "*"; } // 对于手机号进行脱敏,可以将间四位替换为* else if (type == SensitiveType.PHONE) { return value.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"); } // 其他脱敏处理... else { return value; } } } ``` 4. 创建脱敏处理器注解:创建一个注解,用于标记需要脱敏处理的字段。 ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface SensitiveInfo { SensitiveType type(); } ``` 5. 创建脱敏处理器枚举:创建一个枚举类,用于定义脱敏类型。 ```java public enum SensitiveType { NAME, PHONE, // 其他脱敏类型... } ``` 6. 配置MyBatis-Plus:在`application.properties`或`application.yml`文件配置MyBatis-Plus相关信息。 ```yaml mybatis-plus: configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` 7. 编写Mapper和Service:编写对应的Mapper接口和Service类,使用MyBatis-Plus提供的方法进行数据库操作。 ```java public interface UserMapper extends BaseMapper<User> { // 自定义查询方法... } @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { // 自定义服务方法... } ``` 以上就是在Spring Boot使用MyBatis-Plus实现脱敏处理的基本步骤。通过添加注解和自定义脱敏处理器,可以对敏感字段进行相应的脱敏操作,保护数据的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值