Hey, Nice to meet You. 

必有过人之节.人情有所不能忍者,匹夫见辱,拔剑而起,挺身而斗,此不足为勇也,天下有大勇者,猝然临之而不惊,无故加之而不怒.此其所挟持者甚大,而其志甚远也.          ☆☆☆所谓豪杰之士,

SpringMVC入门学习(五)----SpringMVC自定义类型转换器

1、转换器的概述

实际上在SpringMVC框架中,框架本身就内置了很多类型转换器,这些默认的类型转换器,可以将String类型的数据,自动转换为相应类型的数据。比如在前面的各种演示案例中,表单提交的无论是int还是double类型的请求参数,通过默认转换器均可直接接收到相应类型的相应数据,而非接收到String再手动转换,都是会自动帮你转换。这些默认的转换器就在包 org.springframework.core.convert.converter 下,如图所示:

image

但是有的时候内置的类型转换器不足够满足业务需求,因为默认转换器并不是可以将用户提交的String转换为所有用户需要的类型。此时,就需要自定义类型转换器了。例如,在Spring MVC的默认类型转换器中,没有日期类型的转换器,因为日期的格式太多。若要使表单中提交的日期字符串,被处理器方法形参直接接收为日期类型,则需要自定义类型转换器了,否则肯定会报错。下面就来学习一下怎么操作的。

2、实现Converter接口

依旧使用前面的提交Book举例,首先创建一个实现Converter接口的DateConverter实现类,代码如下:

package com.thr.convert;
 
import org.springframework.core.convert.converter.Converter;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
 
/**
 * 自定义转换器
 */
//@Component
public class DateConverter implements Converter<String, LocalDate> {
    //Java8 的日期格式化器
    DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public LocalDate convert(String source) {
        // 根据格式化器将String类型解析为LocalDate类型
        return LocalDate.parse(source, formatter);
    }
}

上面是在自定义的参数类型转换器中,将一个前台传来的 String 转为 LocalDate 对象。

然后我们在Book类添加一个日期类型的属性,用来表示图书的出版日期,Book实体类代码如下:

public class Book {
    //书的ID
    private Integer id;
    //书名
    private String name;
    //出版社
    private String publisher;
    //图书出版日期
    private LocalDate publishDate;
 
    //getter,setter和toString省略
}

接下来,在 SpringMVC 的配置文件(spring-mvc.xml)中配置相关的 Bean使之生效。

<!-- 注册自定义转换器 -->
<bean id="dateConverter" class="com.thr.convert.DateConverter"/>
<!-- 注册类型转换服务bean -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <ref bean="dateConverter"/>
        </set>
    </property>
</bean>
<!-- 配置MVC注解驱动。-->
<mvc:annotation-driven conversion-service="conversionService"/>

创建用于提交图书信息的index.jsp页面,具体代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>首页</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/book" method="post">
    <table>
        <tr>
            <td>图书ID:</td>
            <td><input type="text" name="id"></td>
        </tr>
        <tr>
            <td>图书名称:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>出版社:</td>
            <td><input type="text" name="publishingHouse"></td>
        </tr>
        <tr>
            <td>图书出版日期:</td>
            <td><input type="date" name="publishDate"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="提交">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

image

image

3、使用@InitBinder注解(推荐)

当然也可以不在XML中配置类型转换服务,而是使用@InitBinder注解来实现,推荐这种方式。在需要日期转换的 Controller 中使用 SpringMVC 的注解 @InitBinder 和 Spring 自带的 WebDateBinder 类来操作,WebDataBinder 是用来绑定请求参数到指定的属性编辑器。由于前端传到 Controller 里的值是 String 类型的,当往 Model 里 Set这个值的时候,如果 set 的这个属性是个对象,Spring 就会去找到对应的 editor 进行转换,然后再 SET 进去。注意:@InitBinder用于在@Controller中标注的方法,表示为当前控制器注册一个属性编辑器,只对当前的Controller有效。这个方法会在控制器中其他方法之前调用,这样就可以预先处理数据。

//@Controller:表示一个Controller实例,该实例由Spring容器管理
@Controller
public class BookController {

    //添加initBinder注解
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        //注册原类型和目标类型的转换格式
        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                System.out.println("-----进入了initBinder()----");
                setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
        });
    }
    //配置请求的地址
    @RequestMapping(value = "book", method = RequestMethod.POST)
    public String getInfo(Book book) {
        System.out.println(book.getId());
        System.out.println(book.getName());
        System.out.println(book.getPublisher());
        System.out.println(book.getPublishDate());
        //成功后跳转的页面
        return "success";
    }
}
posted @ 2021-05-13 08:05  唐浩荣  阅读(759)  评论(0编辑  收藏  举报