springBoot中自定义参数类型转换

一、缘起

       由于工作中的项目需要与第三方进行联调,在对方调用我方的接口中请求接受Content-Type 为application/x-www-form-urlencoded,但是针对该请求方式的springBoot中无法封装复杂类型的参数 例如一个VO对象中含有1、Date类型或者2、List对象

本片博文针对其中的两个问题进行解决。

二、解决方式

  1、构造VO对象

  Order对象

/**
 * author  xieqx
 * date   2018/9/7
 * 订单信息
 */
public class Order {

    /**
     * 订单id
     */
    private Long orderId;

    /**
     * 订单编号
     */
    private String orderNo;

    /**
     * 预定时间 默认情况下的日期类型也无法进行封装 需要添加自定义的预定时间
     */
    private Date bookingTime;

    /**
     * 订单详情列表,controller封装的order对象中如果没有自定义的类型转换,默认情况下无法正确的封装
     */
    private List<OrderDetail> orderDetailList;


...省略seter getter方法

OrderDetail对象

/**
 * @author  xieqx
 * date   2018/9/7
 * 订单详情 
 * 使用了lombok框架 简化了bean的创建
 */
@AllArgsConstructor
@Getter
@Setter
public class OrderDetail {

    private Long productId;

    private String productName;

    /**
     * 日期类型
     */
    private Date  buyTime;
}

     2、编写自定义的类型转换器

         2.1 String类型转换为Date类型

          继承Spring提供的org.springframework.core.convert.converter.Converter对象,重写其中的convert()方法 其中是自己的转换逻辑。

/**
 * author  xieqx
 * date   2018/9/4
 * 将String 转换为Date集合
 */
public class StringToDateConverter implements Converter<String, Date> {
    @Nullable
    @Override
    public Date convert(String json) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return simpleDateFormat.parse(json);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;

    }
}

2.2 String类型转换为List集合类型

   与2.1转换Date类型相似 这里使用了jackson框架进行转换

/**
 * author  xieqx
 * date   2018/9/4
 * 将String 转换为list集合
 */
public class StringToListConverter  implements Converter<String, List<OrderDetail>> {

    @Override
    public List<OrderDetail> convert(String json) {
        List<OrderDetail> priceDetails = JsonUtil.str2List(json,OrderDetail.class);
        return  priceDetails;
    }

}

2.3 转换类完成后,还需要将其交由Spring的容器进行处理,这里提供了两种方式 

   1、继承WebMvcConfigurationSupport类并将该对象创建进行添加

@Configuration
public class ApplicationConfig extends WebMvcConfigurationSupport {
    /**
     * 添加静态资源文件
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/img").addResourceLocations("/img/");
        registry.addResourceHandler("/static/css").addResourceLocations("/css/");
        registry.addResourceHandler("/static/js").addResourceLocations("/js/");
        registry.addResourceHandler("/static/swf").addResourceLocations("/swf/");
        registry.addResourceHandler("/static/media").addResourceLocations("/media/");
    }

    /**
     * 添加自定义的Converters和Formatters.
     */
    @Override
    protected void addFormatters(FormatterRegistry registry) {
        //添加字符串转换list的自定义转换器
        registry.addConverter(new StringToListConverter());
        //添加字符串转换Date的自定义转换器
        registry.addConverter(new StringToDateConverter());
    }

}

  使用该方式会破坏SpringBoot默认加载静态文件的默认配置,需要重新进行添加. 切记

  2、第二种方式 

@Configuration
public class SpringDataConvert {

    @Autowired
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;

    /**
     * 增加字符串转换为List集合
     */
    @PostConstruct
    public void addConversionConfig() {
        ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) requestMappingHandlerAdapter.getWebBindingInitializer();
        if (initializer.getConversionService() != null) {
            GenericConversionService genericConversionService = (GenericConversionService)initializer.getConversionService();
            //添加字符串转换为list集合的转换机器
            genericConversionService.addConverter(new StringToListConverter());
            //添加字符串转换为日期类型的字符串
            genericConversionService.addConverter(new StringToDateConverter());

        }
    }
}

   2.4 编写controller进行测试

@Controller
@RequestMapping("/api")
public class DateConvertController {
    private static final Logger logger = LoggerFactory.getLogger(DateConvertController.class);
    /**
     * 
     * @param order 订单信息
     * @return  请求方式为application/x-www-form-urlencoded
     */
    @ResponseBody
    @RequestMapping(value = "test",method = RequestMethod.POST,
consumes = "application/x-www-form-urlencoded",produces = "application/json")
    public Object checkInventoryForm(Order order){
        if(order==null){
            throw new RuntimeException("the hotelOrder is null");
        }
        return order;
    }
}

     

3、启动测试

         3.1、不添加日期类型转换器的post请求

      提示String无法转换为Date类型

  3.2  不添加List类型转换

  提示String无法转换为List

    3.3、自定义的类型转换器都注册上

三、升级

   3.1、 如果我的Order在添加一个Date类型 checkOutTime 格式为yyyy-MM-dd HH:mm:ss(区别于bookingTime yyyy-MM-dd)

如果使用上面的日期类型转换,需要则无法处理怎可以使用@DateFormat注解来针对每一个日期类型的进行定制化的配置

并取消自定义的日期类型的转换器

/**
 * author  xieqx
 * date   2018/9/7
 * 订单信息
 */
public class Order {

    /**
     * 订单id
     */
    private Long orderId;

    /**
     * 订单编号
     */
    private String orderNo;

    /**
     * 预定时间 默认情况下的日期类型也无法进行封装 需要添加自定义的预定时间
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    //@JsonFormat( timezone = "GMT+8",pattern = "yyyy-MM-dd")
    private Date bookingTime;

    /**
     * 离店时间
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date checkOutTime;

    /**
     * 订单详情列表,controller封装的order对象中如果没有自定义的类型转换,默认情况下无法正确的封装
     */
    private List<OrderDetail> orderDetailList;

  postman的请求结果

3.2、对于若干个相同集合的处理

   添加一个用户列表List<User>需要重新构造一个类似于StringToListConverter   去转换User list集合挺麻烦的,我们可以对于StringToListConverter<T>构造成范型,如下代码

/**
 * @author  xieqx
 * date   2018/9/4
 * 将String 转换为list集合 范型的处理
 */
public class StringToListConverter<T>  implements Converter<String, List<T>> {

    @Override
    public List<T> convert(String json) {
        Type type  =  (Class < T > ) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        Class clazz = type.getClass();
        List<T> list = JsonUtil.str2List(json,clazz);
        return  list;
    }

}

需要解析Bean的集合形式只需继承即可

#解析OrderDetail 集合对象
public class StringToOrderDetailListConverter extends StringToListConverter<OrderDetail> {

}


#解析User 集合对象
public class StringToUserListConverter extends StringToListConverter<User> {

}

在spring中进行注册

@Configuration
public class SpringDataConvert {

    @Autowired
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;

    /**
     * 增加字符串转换为List集合
     */
    @PostConstruct
    public void addConversionConfig() {
        ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) requestMappingHandlerAdapter.getWebBindingInitializer();
        if (initializer.getConversionService() != null) {
            GenericConversionService genericConversionService = (GenericConversionService)initializer.getConversionService();
   
   //添加转换OrderDetail 集合         
   genericConversionService.addConverter(new StringToOrderDetailListConverter());
   //添加转换User 集合
   genericConversionService.addConverter(new StringToUserListConverter());            

   //添加字符串转换为日期类型的字符串
   //genericConversionService.addConverter(new StringToDateConverter());

        }
    }
}

github  源码地址:https://github.com/liushangzaibeijing/TypeConvert.git

  • 7
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot 自定义类型转换器(Type Converter)允许你在不修改默认映射规则的情况下,扩展或定制框架对特定数据类型之间的转换过程。这对于处理一些特殊的业务逻辑或第三方库的数据格式转换非常有用。以下是自定义类型转换器的基本步骤: 1. 创建类型转换器接口:实现`org.springframework.core.convert.converter.Converter`接口,这个接口有一个`convert`方法,用于执行转换。 ```java public class CustomConverter implements Converter<String, MyCustomType> { // ... @Override public MyCustomType convert(String source) { // 在这里实现将字符串转换为MyCustomType的具体逻辑 return ...; } // ... } ``` 2. 注册转换器:在Spring Boot应用的配置类使用`@Bean`和`@Configuration`注解来注册你的转换器,并告诉Spring它是如何找到和使用的。 ```java @Configuration public class ConversionConfig { @Bean public Converter<String, MyCustomType> customConverter() { return new CustomConverter(); } @Bean public TypeConverterRegistry typeConverterRegistry(ApplicationContext context) { TypeConverterRegistry registry = new TypeConverterRegistry(context); registry.addConverter(customConverter()); return registry; } } ``` 3. 使用自定义转换器:在需要进行类型转换的地方,Spring会自动调用已注册的转换器。例如,可以在`@RequestMapping`方法的参数上使用`@RequestBody`或`@ModelAttribute`注解来触发转换。 ```java @PostMapping("/my-endpoint") public ResponseEntity<?> handleRequest(@RequestBody String input) { MyCustomType myObject = typeConverter.convert(input); // Spring会自动调用注册的转换器 // ... } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值