Springmvc核心技术之类型转换器(九)

一、类型转换器

1.1、日期类型转换

1、index.jsp添加下列表单

   <form action="/my/date" method="post">
       年龄:<input type="text" name="age"/><br>
       出生日期:<input type="text" name="birthday"/><br>
       <button type="submit">登录</button>
   </form>

2、MyController处理类

 @RequestMapping("/date")
    public ModelAndView doDate(int age, Date birthday){
        ModelAndView andView = new ModelAndView();
        andView.addObject("age",age);
        andView.addObject("birthday",birthday);
        andView.setViewName("/WEB-INF/jsp/home.jsp");
        return andView;
    }

3、home.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>年龄:${age}</h1>
    <h1>出生日期:${birthday}</h1>
</body>
</html>

4、测试

在这里插入图片描述

5、结果

在这里插入图片描述

经过多次测试发现:springmvc默认只支持2019/01/22这种字符串格式的日期类型转换。

1.2、自定义类型转换器 —— 自定义日期转换的格式

1、自定义类型转换器

public class MyConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        Date date = null;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
             date = format.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

注意ParseException 异常必须处理,不能抛出;自定义的类型转换器必须实现org.springframework.core.convert.converter.Converter接口。

2、spring.xml注册自定义类型转换器

<!--注册自定义类型转换器-->
    <bean id="myConverter" class="com.chuan.core.config.MyConverter"/>

    <!--注册类型转换器工厂bean-->
    <bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
               <set>
                   <ref bean="myConverter"/>
               </set>
        </property>
    </bean>

    <!--配置类型转换器工厂bean注解扫描-->
    <mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>

3、测试

在这里插入图片描述

4、结果

在这里插入图片描述

  • 自定义日期格式类型yyyy-MM-dd生效,springmvc原来默认的日期解析格式作废。

1.3、配置多个日期格式

  • 自定义类型转换器添加如下代码
public class MyConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        Date date = null;
        SimpleDateFormat format = getSimpleDateFormat(s);
        try {
             date = format.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    private SimpleDateFormat getSimpleDateFormat(String source){
        SimpleDateFormat format = new SimpleDateFormat();
        if(Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$",source)){
            format = new SimpleDateFormat("yyyy-MM-dd");
        }else if(Pattern.matches("^\\d{4}.\\d{2}.\\d{2}$",source)){
            format = new SimpleDateFormat("yyyy.MM.dd");
        }else if(Pattern.matches("^\\d{4}\\d{2}\\d{2}$",source)){
            format = new SimpleDateFormat("yyyyMMdd");
        }
        return format;
    }
  • 测试结果显示上述符合上述三种日期格式的字符串参数都能正常请求目标视图

二、数据回显

  • 应用场景:登录/注册失败后跳转回登录/注册页面并显示错误信息,提高用户体验

2.1、age信息错误时index.jsp页面回显

1、解决方案

  • 需求:表单中 /my/date 请求数据格式有误时跳转回index.jsp页面
  • 解决方案:1)获取参数错误是的错误Exception;2)使用@ExceptionHandler处理该异常并在其标记方法中回显至index.jsp页面。

2、测试“age”的异常类型

在这里插入图片描述

控制台打印的异常:org.springframework.web.method.annotation.MethodArgumentTypeMismatchException,必须要注册自定义类型处理器,后台才会打印显示这个错误。

3、修改MyController

    @RequestMapping("/date")
    public ModelAndView doDate(int age, Date birthday){
        ModelAndView andView = new ModelAndView();
        andView.addObject("age",age);
        andView.addObject("birthday",birthday);
        andView.setViewName("/WEB-INF/jsp/home.jsp");
        return andView;
    }

    @ExceptionHandler(TypeMismatchException.class)
    public ModelAndView initException(){
        return new ModelAndView("/index.jsp");
    }

加入一个异常处理使页面跳转至index.jsp即可;注意@ExceptionHandler(TypeMismatchException.class) 只能在 Mycontroller 中使用,如果再上一篇定义的MyExceptionController 中使用会没有效果,具体原因未知。

4、测试成功:age输入错误是会回显至index.jsp页面

2.2、出生日期错误时页面回显

  • 解决思路:与2.1思路相同,处理date数据的异常即可

1、捕获出生日期date类型的异常

  try {
             date = format.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
  • 异常信息就是ParseException

2、修改MyController:添加下列代码

  @ExceptionHandler(ParseException.class)
    public ModelAndView parseException(){
        return new ModelAndView("/index.jsp");
    }

3、测试结果失败:无法跳转到/index.jsp页面

  • 原因分析:ParseException 异常是已经在自定义类型转换器MyConverter中处理了并没有抛出,所有**@ExceptionHandler**并不能捕获到该异常,也就无法处理该方法体的业务逻辑。

4、解决方案

  • 修改MyConvertergetSimpleDateFormat方法
    private SimpleDateFormat getSimpleDateFormat(String source){
        SimpleDateFormat format = new SimpleDateFormat();
        if(Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$",source)){
            format = new SimpleDateFormat("yyyy-MM-dd");
        }else if(Pattern.matches("^\\d{4}.\\d{2}.\\d{2}$",source)){
            format = new SimpleDateFormat("yyyy.MM.dd");
        }else if(Pattern.matches("^\\d{4}\\d{2}\\d{2}$",source)){
            format = new SimpleDateFormat("yyyyMMdd");
        }
        else{
        //在上述三个日期格式时都不符合时,抛出TypeMismatchException异常
             throw new TypeMismatchException("12a",Date.class);
        }
        return format;
    }

如上:在上述三个日期格式时都不符合时,抛出TypeMismatchException异常;TypeMismatchException的值设置为**(“12a”,Date.class))**,则这个异常必定会被抛出且抛出的是 date数据相关的异常

5、重新测试:当日期错误时也能回显至index.jsp页面

2.3、错误信息提示

  • 需求:当我们成功回显至页面时,我们还需要将具体的错误信息显示到前端页面,提升用户体验

1、修改MyController的initException方法

 @ExceptionHandler(TypeMismatchException.class)
    public ModelAndView initException(HttpServletRequest request,Exception ex){
        ModelAndView view = new ModelAndView();
        //1、获取age和birthday 的请求参数
        String age = request.getParameter("age");
        String birthday = request.getParameter("birthday");
        view.addObject("ex",ex);
        String exMessage = ex.getMessage();
        //2、校验ex.getMessage()是否包含了age和birthday的值,即判断异常属于哪一个异常
        if (exMessage.contains(age)){
            view.addObject("error_age","年龄格式有误。。。");
        }
        if (exMessage.contains(birthday)){
            view.addObject("error_birthday","出生日期格式有误。。。");
        }
        view.setViewName("/index.jsp");
        return view;
    }

2、测试

在这里插入图片描述

年龄和日期均出现错误

3、结果

在这里插入图片描述

  • 如上图:只会显示一个数据的错误

三、注解式实现日期类型转换

3.1、实现一种日期格式

  • MyController:直接应用springMVC的注解@initbinder和spring自带的WebDataBinder类和操作
@InitBinder
    public void initBinder(WebDataBinder binder) {
             
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
         binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
     }

3.2、实现多种日期

  • 思路:我们不使用springmvc给我们提供的CustomDateEditor,我们注册自定义的Editor属性编辑器来进行多种日期格式的规范,该编辑器需要继承org.springframework.beans.propertyeditors.PropertiesEditor接口。

1、MyPropertiesEditor属性编辑器类

  • 先将自定义的类型解析器删除、以免产生冲突,删除以后**@ExceptionHandler**(TypeMismatchException.class)标记的方法体将会失效。

public class MyPropertiesEditor extends PropertiesEditor {

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        SimpleDateFormat format = getSimpleDateFormat(text);
        try {
            Date date = format.parse(text);
            setValue(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    private  SimpleDateFormat getSimpleDateFormat(String source){
        SimpleDateFormat format = new SimpleDateFormat();
        if(Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$",source)){
            format = new SimpleDateFormat("yyyy-MM-dd");
        }else if(Pattern.matches("^\\d{4}.\\d{2}.\\d{2}$",source)){
            format = new SimpleDateFormat("yyyy.MM.dd");
        }else if(Pattern.matches("^\\d{4}\\d{2}\\d{2}$",source)){
            format = new SimpleDateFormat("yyyyMMdd");
        }
        return format;
    }

setAsText:将日期格式注册到属性编辑器当中去。

2、修改MyController类中的initBinder()方法

  • 即注册自定义的日期属性编辑器
    @InitBinder
    public void initBinder(WebDataBinder binder) {
         binder.registerCustomEditor(Date.class,new MyPropertiesEditor());
    }

四、springmvc中数据类型转换过程

4.1、原理图

在这里插入图片描述
从上图可以看到,Spring在解析请求参数时,会根据请求格式进入到不同的转换流程:

  • 如果是非raw请求(即包含参数数组),则交由ModelAttributeMethodProcessor处理,ModelAttributeMethodProcessor再调用Spring Converter SPI对请求参数逐个进行转换。
  • 如果是raw请求,则交由RequestResponseBodyMethodProcessor处理,对于JSON格式的请求体,会再调用MappingJackson2HttpMessageConverter,最终通过ObjectMapper完成转换。

4.2、Spring Boot注册自定义Converter

1、实现org.springframework.core.convert.converter.Converter接口生成一个自定义Converter

public class OffsetDateTimeConverter implements Converter<String, OffsetDateTime> {

    @Override
    public OffsetDateTime convert(String source) {
        if (!NumberUtils.isNumber(source)) {
            return null;
        }

        Long milli = NumberUtils.createLong(source);
        return OffsetDateTime.ofInstant(Instant.ofEpochMilli(milli), systemDefault());
    }
}

2、选择一个标注@Configuration注解的配置类,继承org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter,然后覆盖addFormatters方法,注册自定义Converter。

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new OffsetDateTimeConverter());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring MVC中,您可以使用自定义类型转换来处理特定类型之间的转换。要设置自定义类型转换,您需要执行以下步骤: 1. 创建一个实现了 `Converter<S, T>` 接口的自定义类型转换类。其中,S 是源类型,T 是目标类型。该接口要求实现 `convert()` 方法,用于执行实际的类型转换逻辑。 ```java public class CustomConverter implements Converter<String, Date> { @Override public Date convert(String source) { // 实现自定义的类型转换逻辑 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { return dateFormat.parse(source); } catch (ParseException e) { throw new IllegalArgumentException("Invalid date format"); } } } ``` 2. 在Spring MVC配置中注册自定义类型转换。可以通过编程方式或者使用XML配置进行注册。 a. 编程方式: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new CustomConverter()); } } ``` b. XML配置方式: ```xml <mvc:annotation-driven conversion-service="conversionService" /> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="com.example.CustomConverter" /> </set> </property> </bean> ``` 3. 在您的控制方法中使用目标类型作为参数。Spring MVC会自动调用适当的类型转换将请求参数转换为目标类型。 ```java @Controller public class MyController { @RequestMapping("/example") public String handleRequest(@RequestParam("date") Date date) { // 处理转换后的日期对象 return "example"; } } ``` 通过以上步骤,您就可以设置自定义的类型转换来处理Spring MVC中的类型转换。希望对您有所帮助!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值