大数跨境
0
0

强大!Spring Boot自定义数据绑定,搞定任意数据类型

强大!Spring Boot自定义数据绑定,搞定任意数据类型 Spring全家桶实战案例
2025-03-25
1
导读:强大!Spring Boot自定义数据绑定,搞定任意数据类型
Spring Boot 3实战案例锦集PDF电子书已更新至100篇精华案例!

🎉🎉《Spring Boot实战案例合集》目前已更新109个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

现在就订阅合集




环境:SpringBoot3.4.2



1. 简介

本篇文章将介绍如何利用Spring的数据绑定机制,通过实现自动将基本类型到对象的转换,从而提升代码的清晰度和可读性。

在默认情况下,Spring仅具备转换简单类型数据的能力。也就是说,当我们向Controller提交诸如int、String或boolean等类型的数据时,Spring能够自动地将这些数据绑定到相应的Java类型上。然而,在实际的项目开发中,这简单的能力往往无法满足我们的需求,因为我们经常需要绑定更为复杂的对象类型。

接下来,我将通过多个实例,从不同维度深入讲解各类复杂数据绑定的实现方法。

2. 实战案例

2.1 单对象绑定请求参数

首先,我们定义如下接口,在默认情况下该接口是会报错:

@RestController@RequestMapping("/api")public class ApiController {  @GetMapping("/{date}")  public ResponseEntity<?> findByDate(@PathVariable("date") LocalDateTime date) {    return ResponseEntity.ok(date);  }}

解决该问题,我们可以使用下面的注解:

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")

该注解标注在参数上后能得到正确的处理。我们还可以自定义Converter接口

@Componentpublic class StringToLocalDateTimeConverter     implements Converter<StringLocalDateTime> {  @Override  public LocalDateTime convert(String source) {    return LocalDateTime.parse(source,         DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")) ;  }}

如何进行转换由我们自己实现。

接下来,我们在来一个字符串到枚举值的绑定

@GetMapping("/pay")public ResponseEntity<Objectpay(Payment payment) {  return ResponseEntity.ok(payment) ;}public enum Payment {    ALIWX;}

默认情况,该接口会报错,无法进行转换。

自定义类型转换器

public class StringToEnumConverter implements Converter<StringPayment> {  public Payment convert(String from) {    return Payment.valueOf(from.toUpperCase());  }}

注册方式我们还可以通过如下的方式:

@Componentpublic class WebConfig implements WebMvcConfigurer {  public void addFormatters(FormatterRegistry registry) {    registry.addConverter(new StringToEnumConverter()) ;  }}

关于枚举类型的更多应用请查看下面文章:

超赞!Java枚举的高级实战技巧

高级开发!Spring Boot处理枚举类型,支持JPA、MyBatis、Jackson

2.2 层次对象绑定

有时我们需要转换对象层次结构的整个树,此时使用一个更加集中的绑定而非一组单独的转换器更有意义。在这个例子中,我们有一个基类 BaseEntity

public abstract class BaseEntity {  private long id;  public BaseEntity(long id) {    this.id = id;  }  // getters,setters}public class User extends BaseEntity {  private String name ;  public User(long id) {    super(id) ;  }}

接口定义如下:

@GetMapping("/obj/{user}")public ResponseEntity<ObjectgetStringToFoo(@PathVariable User user) {  return ResponseEntity.ok(user);}

定义类型转换工厂

public class StringToBaseEntityConverterFactory implements ConverterFactory<StringBaseEntity> {  @Override  public <T extends BaseEntityConverter<String, T> getConverter(Class<T> targetClass) {    return new StringToBaseEntityConverter<>(targetClass);  }  private static class StringToBaseEntityConverter<T extends BaseEntityimplements Converter<String, T> {    private Class<T> targetClass;    public StringToBaseEntityConverter(Class<T> targetClass) {      this.targetClass = targetClass;    }    public T convert(String source) {      String[] tmps = source.split(",") ;      long id = 0 ;      if (tmps.length > 1) {        id = Long.parseLong(tmps[0]);      }      if (this.targetClass == User.class) {        User user = new User(id);        user.setName(tmps[1]) ;        return (T) user;      } else {        return null ;      }    }  }}

注册转换器工厂

public void addFormatters(FormatterRegistry registry) {  registry.addConverterFactory(new StringToBaseEntityConverterFactory()) ;}

运行结果

2.3 自定义参数解析器进行绑定

接下来,我们将通过一个注解完成数据的绑定功能。使用该注解的参数将自动从请求header中读取数据进行绑定。

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.PARAMETER)public @interface Version {}

自定义参数解析器

public class HeaderVersionArgumentResolver implements HandlerMethodArgumentResolver {  public boolean supportsParameter(MethodParameter methodParameter) {    return methodParameter.getParameterAnnotation(Version.class) != null;  }  public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,      NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {    HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest() ;    // 读取请求header中的x-version进行绑定    return request.getHeader("x-version") ;  }}

注册参数解析器

public void addArgumentResolvers(    List<HandlerMethodArgumentResolver> argumentResolvers) {  argumentResolvers.add(new HeaderVersionArgumentResolver()) ;}

请求接口

@GetMapping("/version/{id}")public ResponseEntity<?> findByVersion(    @PathVariable Long id, @Version String version) {  return ResponseEntity.ok(id + "@" + version);}

测试结果

当然了,这里我们也可以使用SpringMVC自带的注解:

@RequestHeader("x-version"String version

不过,这里我们要向大家介绍的是,如何利用这种方式来自定义数据绑定过程。



以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

告别内存溢出!Spring StreamingResponseBody 三大实战案例,性能提升100%

优雅!Spring 基于 Plugin 插件开发(官方推荐)

Spring Cloud Gateway 网关非常实用的8个开发技巧,你知道吗?太实用了

强大!基于Spring Boot动态注册 / 删除Controller接口(支持动态上传)

Controller 接口支持多达26种参数解析方式

性能优化!3种方法优化@Transactional长事务问题,方法三性能提升4倍(不修改业务代码)

Spring Boot中记录JDBC、JPA及MyBatis执行SQL及参数的正确姿势

强大!JSON解析神器,再复杂也不怕了

API接口优化!基于Spring Boot 实现Deflate压缩技术

SpringBoot这3个高级技能太强!非常实用

基于Spring Boot给所有Controller接口添加统一前缀的5种方式

超赞!Java枚举的高级实战技巧

9种技巧优化if-else

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读38
粉丝0
内容832