Spring MVC笔记(五)

数据转换

1. 数据绑定流程

SpringMVC通过反射机制对目标处理方法进行解析,将请求消息绑定到处理方法的入参中。其中,数据绑定的核心部件是DataBinder,运行机制如下

数据绑定的具体流程说明如下
  • SpringMVC主框架将ServletRequest对象和目标方法的入参实例传递给WebDataBinderFactory实例,以创建DataBinder实例对象;
  • DataBinder调用装配在SpringMVC上下文中的ConversionService组件进行数据类型转换与格式化操作,并将Servlet中的请求信息填充到入参对象中;
  • SpringMVC进而调用Validator组件对已经绑定请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData对象;
  • SpringMVC抽取BindingResult中的入参对象和校验错误对象,将其赋给处理方法的响应入参中。
// ModelAttributeMethodProcessor的resolveArgument()方法的核心代码:
WebDataBinder binder = binderFactory.createBinder(request, attribute, name);
if (binder.getTarget() != null) {
    bindRequestParameters(binder, request); //绑定请求数据到入参中
    validateIfApplicable(binder, parameter); //校验入参中数据的合法性
    if (binder.getBindingResult().hasErrors()) {
        if (isBindExceptionRequired(binder, parameter)) {
            throw new BindException(binder.getBindingResult());
        }
    }
}

2. 数据类型转换

SpringMVC上下文中内建了许多数据类型转换器,可完成大多数Java类型的换工作,具体可通过调试模式查看binder的conversionService属性值。

3. 自定义数据类型转换器

  • 明确需求:
<form action="testConversionServiceConverter" method="POST">
    <!-- lastName-email-gender-department.id 例如 : [email protected] -->
    Employee : <input type="text" name="employee">
    <input type="submit" value="submit">
</form>
@Controller
public class SpringMVCTest {

    @Autowired
    private EmployeeDao employeeDao;

    @RequestMapping("/testConversionServiceConverter")
    public String testConverter(@RequestParam("employee") Employee employee) {
        employeeDao.save(employee);
        return "redirect:emps";
    }
}
  • 第一步:自定义实现Converter接口的数据类型转换器类,并添加到Spring的IoC容器中;
// 三种类型的数据转换器接口:Converter<S,T>、ConverterFactory、GenericConverter
@Component
public class EmployeeConverter implements Converter<String, Employee>{
    public Employee convert(String source) {
        if(source != null) {
            String[] strs = source.split("-");
            if(strs != null && strs.length == 4) {
                String name = strs[0];
                String email = strs[1];
                String gender = strs[2];
                Department department = new Department();
                department.setDeptId(Integer.parseInt(strs[3]));
                return new Employee(null, name, email, gender, department);
            }
        }
        return null;
    }

}
  • 第二步:在SpringMVC的配置文件中,通过ConversionServiceFactoryBean的converters属性注册自定义的类型转换器;
<!-- 
    配置数据类型转换器:
    1). ConversionService是SpringMVC类型转换体系的核心接口;
    2). 可以利用ConversionServiceFactoryBean在Spring的IoC容器中定义一个ConversionService;
    3). Spring将自动识别IOC容器中的ConversionService,并在Bean属性配置及SpringMVC处理方法入参绑定等场合使用其进行数据类型转换。
 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <ref bean="employeeConverter"/>
        </set>
    </property>
</bean>
  • 第三步:通过mvc:annotation-driven标签的conversion-service属性,将ConversionServiceFactoryBean注册到SpringMVC的上下文中。
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

4. 关于mvc:annotation-driven

  <mvc:annotation-driven/> 会自动注册 RequestMappingHandlerMapping、
  RequestMappingHandlerAdapter 与 ExceptionHandlerExceptionResolver
  三个bean,其还将提供如下支持:
  • 支持使用ConversionService实例对表单参数进行类型转换;
  • 支持使用@NumberFormat和@DateTimeFormat注解完成数据类型的格式化;
  • 支持使用@Valid注解对JavaBean实例进行JSR 303验证;
  • 支持使用@RequestBody和@ResponseBody注解。

5. @InitBinder注解

由@InitBinder注解标识的方法,可以对 WebDataBinder 对象进行初始化;WebDataBinder是DataBinder的子类,用于完成由表单字段到JavaBean属性的绑定。注意@InitBinder方法不能有返回值,其入参通常是WebDataBinder对象。

/**
 * 在进行数据绑定时,不自动绑定对象中的name属性
 * 注意:其对自定义类型转换器并不起作用
 * @param binder
 */
@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.setDisallowedFields("name");
}

数据格式化

1. FormattingConversionServiceFactroyBean

主要作用:用于在Spring上下文中构造FormattingConversionService。
其中,FormattingConversionServiceFactroyBean工厂类的内部已经注册:

  • NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性使用@NumberFormat注解;
  • JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型的属性使用@DateTimeFormat注解;

2. mvc:annotation-driven

  • mvc:annotation-driven 默认创建的 ConversionService实例即为FormattingConversionServiceFactroyBean;
  • 故配置mvc:annotation-driven后即可在SpringMVC入参绑定及模型数据输出时使用注解驱动,以实现数据类型转换和数据格式化

3. FormattingConversionService

  • 该类是Spring格式化模块中实现了ConversionService接口的实现类;
  • 该类扩展了GenericConversionService,既具有类型转换的功能,又具有格式化的功能。

4. 日期格式化

@DateTimeFormat注解可对java.util.Date、java.util.Calendar和java.long.Long时间 类型的属性进行标注,其具有如下属性:

  • pattern属性:字符串类型,用于指定解析/格式化字段数据的模式,如”yyyy-MM-dd hh:mm:ss”;
  • iso属性:类型为DateTimeFormat.ISO,用于指定解析/格式化字段数据的ISO模式,包括ISO.NONE(不使用,默认)、ISO.DATE(yyyy-MM-dd) 、ISO.TIME(hh:mm:ss.SSSZ)和ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ);
  • style属性:字符串类型,用于指定日期时间的格式,由两位字符组成,第一位表示日期的格式,第二位表示时间的格式;S表示短日期/时间格式、M表示中日期/时间格式、L表示长日期/时间格式、F表示完整日期/时间格式、-表示忽略日期或时间格式。

5. 数值格式化

 @NumberFormat注解可对类似数字类型的属性进行标注,其具有两个互斥的属性:
 

  • pattern属性:字符串类型,用于自定义样式,如”#,###,###.#”;
  • style属性:类型为NumberFormat.Style,用于指定样式类型,包括Style.NUMBER(正常数字类型)、Style.CURRENCY(货币类型)、Style.PERCENT(百分数类型)。
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
@NumberFormat(pattern="###,###,###.##")
private float salary;

数据校验

1 JSR303数据校验

注解           功能说明
@Null          被注释的元素必须为null
@NotNull       被注释的元素必须不为null
@AssertTrue    被注释的元素必须为true
@AssertFalse    被注释的元素必须为false
@Min(value) 被注释的元素必须是一个数字,其值必须大于或等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于或等于指定的最大值
@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于或等于指定的最小值
@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于或等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits(integer, fraction)  被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past   被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式

  Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,还支持一下扩展注解:
  

注解  功能说明
@Email  被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty   被注释的字符串必须非空
@Range  被注释的元素必须在合适的范围内

2 SpringMVC数据校验

2.1 基本概念

  ① 关于所需要的jar包
  Spring4.0拥有独立的数据校验框架,同时支持 JSR 303 标准的校验框架;但其本身并没有提供 JSR 303 的实现,故必须将 JSR 303 的实现者的jar包放到类路径下。

  ② 关于LocalValidatorFactoryBean工厂类
  该工厂类既实现了Spring的Validator接口,也实现了 JSR 303 的Validator接口;故需要在 Spring 容器中定义LocalValidatorFactoryBean,即可将其注入到需要数据校验的Bean中。

  ③ 关于@Valid注解
  会默认装配LocalValidatorFactoryBean,通过在处理方法的入参上标注@Valid注解即可让SpringMVC在进行数据绑定时,同时调用校验框架完成数据校验工作。

扫描二维码关注公众号,回复: 897788 查看本文章

  ④ 关于校验结果
  前一个表单/命令对象的校验结果保存到随后处理方法的入参中,该入参必须是BindingResult或Errors类型;且需注意,需校验的Bean对象和其绑定结果对象或错误对象是成对出现的,其之间不允许声明其他的入参。

2.2 具体实现

  第一步:添加Hibernate Validator验证框架所依赖的jar包,具体如下图所示:

  第二步:在SpringMVC配置文件中添加mvc:annotation-driven标签;
  第三步:在需要校验的JavaBean属性上添加相应的校验注解,以Employee为例:
  

public class Employee {

    @NotNull
    private String name;

    @Email
    private String email;

    @Past
    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date birth;

    // ……
}

第四步:在处理器目标方法的Bean类型的入参前添加@Valid注解,并添加保存校验结果的对象:

@RequestMapping(value="/emp", method=RequestMethod.POST)
public String save(@Valid Employee employee, BindingResult result, Map<String, Object> map) {
    System.out.println(employee);

    if(result.getErrorCount() > 0) {
        for(FieldError error : result.getFieldErrors()) {
            System.out.println(error.getField() + " : " + error.getDefaultMessage());
        }

        // 指定校验错误时所转向的定制页面
        map.put("departments", departmentDao.getDepartments());
        return "input";
    }

    employeeDao.save(employee);
    return "redirect:/emps";
}

猜你喜欢

转载自blog.csdn.net/baidu_37181928/article/details/80338985
今日推荐