数据前置参数类型转换@InitBinder、Formatter<?>、Converter<?>的使用

前言:在很多时候我们在进行调用接口的时候,传入的参数类型不是指定的特别明确(或者是不能进行自动类型转换),会导致调用接口失败的情况出现,如果我们在调用接口之前进行数据格式化,手动进行数据类型转换,那么就不会出现调用接口失败的情况出现了。这些注解无非也就是做这些工作的。

下面列举工作绝大部分用到的场景

接口中的入参为book,其中book有这几个属性,且提供get、set、tostring方法,如果前端传过来的date的这个属性是一个字符串,但是后端是用Date类型接收的,那么在调用接口的时候会报错。
在这里插入图片描述

 	int id;
    String name;
    Date date;

    @ResponseBody
    @RequestMapping(value = "/bookDo", produces = "application/json"
            , consumes = "application/x-www-form-urlencoded",
            method = RequestMethod.POST)
    public book bookDo(book book) {
        return book;
    }
    @RequestMapping(value = "/date",
            method = RequestMethod.POST)
    public String date(Date date, Model model) {
        model.addAttribute("date", date);
        return "book";
    }

解决办法一(@DateTimeFormat+@JsonFormat)

@DateTimeFormat:指定前端传过来的date的格式化标准(注意前端测试数据别乱写!)
@JsonFormat:指定输出的date格式,由于格式化date是按照国际化标准时间算的,转换成中国时间需要加8


 	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(
            pattern = "yyyy-MM-dd HH:mm:ss",
            timezone = "GMT+8"
    )
    Date date;

缺点:如果有很多个类都需要进行date类型转换,每个实体类都要加这些注解,很麻烦!

解决办法二(@InitBinder+WebDataBinder )

作用:在数据绑定的时候把字符串格式化成Date类型的date,并且不对id绑定,即使前端传了id值也接收不到了哦!(WebDataBinder里面还有一些其他的方法,读者可以自行测试)

/**
 * @author 张子行
 * @class
 */
   @InitBinder
    public void bind(WebDataBinder webDataBinder) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(simpleDateFormat, true));
        webDataBinder.setDisallowedFields("id");
    }

缺点:只能对当前的controller起作用,如果好多controller需要日期格式话呢?每个controller都加上这个东西也是很麻烦!

优化办法二(巧用extends特性 )

让所有需要日期转换的都extends这个类,代码量又小一点了。

/**
 * @author 张子行
 * @class
 */
public class baseController {
    @InitBinder
    public void bind(WebDataBinder webDataBinder) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(simpleDateFormat, true));
        webDataBinder.setDisallowedFields("id");
    }
}

解决办法三(Formatter)

通过实现Formatter接口实现自己的日期格式化逻辑,并且加入到容器内,其中的Locale可以参考国际化解析

/**
 * @author 张子行
 * @class
 */
@Component
public class myDateFormatter implements Formatter<Date> {
    private SimpleDateFormat simpleDateFormat;
    public myDateFormatter() {
        simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    }
    /**
     * @param
     * @method 日期接收格式
     */
    @Override
    public Date parse(String s, Locale locale) throws ParseException {
        return simpleDateFormat.parse(s);
    }
    /**
     * @param
     * @method 日期对外输出格式
     */
    @Override
    public String print(Date date, Locale locale) {
        return simpleDateFormat.format(date);
    }
}

另外添加Formatter的方式有很多,通过实现WebMvcConfigurer 接口进行相关的mvc扩展配置,来添加Formatter也是可以的

/**
 * @author 张子行
 * @class
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    /**
     * @method 添加Formatter
     * @param
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        //registry.addConverter(new myDateConverter());
        registry.addFormatter(new myDateFormatter());

    }
    /**
     * @method 添加视图控制器
     * @param
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {

    }
}

解决办法四(Converter)

和Formatter接口使用上差不多,但是更加强大,可转换的东西也更广。之后加@Component或者注册Converter

/**
 * @author 张子行
 * @class
 */
 @Component
public class myDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date parse = null;
        try {
            parse = simpleDateFormat.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;

    }
}

效果

数据传给后端在做显示给前端
在这里插入图片描述

扩展

如果前端传的是字符串,后端用boolean 接收,咋办呢?同理写Formatter

@RequestMapping(value = "/boolean",
            method = RequestMethod.POST)
    public String date2(boolean b, Model model) {
        model.addAttribute("boolean", b);
        return "book";
    }

只要调用这个接口,传过来的字符串是 {“是”, “嗯”}中的任意一个,那么都为true

@Component
public class myBooleanFormatter implements Formatter<Boolean> {
    private final String[] data = {"是", "嗯"};


    @Override
    public Boolean parse(String s, Locale locale) throws ParseException {
        return Arrays.asList(data).contains(s);
    }

    @Override
    public String print(Boolean aBoolean, Locale locale) {
        return aBoolean ? "true" : "false";
    }
}

测试代码读者觉着不错可以点个星星

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小咸鱼的技术窝

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值