SpringMVC学习笔记14-----数据绑定与自定义类型转换器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38016931/article/details/82052698

一、问题分析

       在之前的增删改查中,数据都是通过表单传向方法然后转化成相应的数据类型!那么如果我们在java bean中再添加一个日期属性birth时,就会有三个问题:

1.如何将表单中的字符串格式转向日期格式:数据类型转换

2.表单中输入的字符串格式应该是怎么样的:数据类型格式化

3.这是个生日属性,既然是生日属性就应该是当前日期的前面的时间,不能填未来的时间,如何检验:数据校验 

二、数据绑定流程

如尚硅谷视频所说:

1.SpringMVC会把request目标方法的入参传递给WebDataBinderFactory实例,以创建DataBinder实例对象

2.DataBinder调用SpringMVC上下文中的ConversionService组件将request中的数据转换为相应的类型,然后填充到目标方法的入参中。(类型转换和格式化往往是一起的!)

3.调用Validator对已经绑定了的请求消息的入参进行合法性的校验,并将最终生成数据绑定结果BindingData对象!

4.SpringMVC抽取BindingResult中的校验错误信息和入参对象,将他们赋给处理方法中相应的入参!

至此,SpringMVC就将我们上面的三个问题都解决了!

三、源码分析

我们一直在写的那个程序学生类有一个数据类型为整型类型的,即我们可以查看这个由字符串转整型的过程:

因为在最终SpringMVC会调用Student类中的setAge方法,所以我们在这里打个断点:

调试,新增学生信息,填写表单,点击添加,停在这个setter语句!我们在函数栈中翻到这个点击:

可以看出来这个类完成了表单中数据绑定校验等操作,第一行调用WebDataBinderFactory这个工厂类创建了一个WebDataBinder对象,然后第三行进行的是数据绑定,第四行完成校验。

再看Variables,点击属性列表中的Binder属性中的:

这个ConversionService是个DefaultFormattingConversionService对象,其可以完成数据的绑定和格式化工作!

这个组件中有个对象属性里面包含一个有97个转换器的对象的LinkHashMap(age中用的转换器是StringToNumberconverter),SpringMVC就是在这里找到相应的对象并进行数据性转换的!

出来往后翻可以看到一个size为0的validator。我们现在还没有加任何校验!

如果加了校验的话,校验过程中发生错误,就会将错误信息放进bindingResult中。

这就是一个数据绑定的流程!

四、自定义一个类型转换器

SpringMVC内建了很多类型转换器,可以完成大部分的转换工作!

但如果我们遇到特殊情况,自定义转换器还是可以了解下的!

视图层

在input.jsp上加上表单:

<br><br><br><br>
<!--the basic format is "name-gender-age-school.id", such as "Tom-female/male-22-4"-->
<h3>字符串添加学生信息</h3>
<form action="/testDIYConversionService" method="post">
    信息:<input type="text" name="student"/>
    <input type="submit" value="添加信息">
</form>

控制层

新建一个TestConversionServiceHandler类:

@Controller
public class TestConversionServiceHandler {

    @Autowired
    private StudentDao studentDao;

    @RequestMapping(value = "/testDIYConversionService", method = RequestMethod.POST)
    public String testDIYConversionService(Student student){
        System.out.println(student);
        studentDao.saveStudent(student);
        return "redirect:stus";
    }

}

如果只是这样的话,字符串类型和Student类型肯定会报错。

我们现在只需实现一个Converter<S,T>接口将String信息转化为一个student对象:

Converter

public class StudentConverter implements Converter<String, Student> {

    @Autowired
    private SchoolDao schoolDao;

    @Override
    public Student convert(String s) {
        Student student = new Student();
        String parameters[] = s.split("-");
        if (parameters.length == 4) {
            String name = parameters[0];
            boolean gender = "female".equals(parameters[1]);
            int age = Integer.parseInt(parameters[2]);
            int schoolId = Integer.parseInt(parameters[3]);
            student = new Student(0, name, gender, age, schoolDao.getSchoolById(schoolId));
            System.out.println(s + "--convert--" + student);
        }
        return student;
    }
}

springmvc.xml文件的配置

<!--config ConverterService bean-->
    <bean id="studentConverter" class="cn.jxufe.Conversion.StudentConverter"> </bean>

    <!--config ConversionServiceFactoryBean-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="studentConverter"/>
            </set>
        </property>
    </bean>

可以看出来这个converters是个set对象。

然后我们在之前写的mvc:annotation-driven配置使得其能自动注册ConversionServiceFactoryBean对象。

<mvc:annotation-driven conversion-service="conversionService"> </mvc:annotation-driven>

注意: 这个配置写一个就行了,之前因为重定向要用到,获取静态文件也要用到,所以我写了两个,然后写自定义转换器时只在一个mvc:annotation-driven配置了conversion-service,然后运行就一直没有用,String不转换为student,一直报错!

mvc:annotation-driven的功能很多,教学视频的进度还没能覆盖其全部作用(比如其对于json的作用),故后面再做详细总结!

把一个删掉运行就成功了!

猜你喜欢

转载自blog.csdn.net/qq_38016931/article/details/82052698