zoukankan      html  css  js  c++  java
  • SpringMVC学习指南【笔记4】数据绑定、表单标签库、转换器、格式化、验证器

    表单标签库

    <%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <form:form commandName="book" action="saveBook" method="post">
    </form:form>
    <form:input id="city" path="city" />
    <form:password id="pwd" path="password" cssClass="normal" />
    <form:hidden path="productId" />
    <form:textarea path="note" tabindex="4" rows="5" cols="80" />
    <form:checkbox path="outOfStock" value="out of stock" />
    <form:radiobutton path="newsletter" value="computing now" />
    <form:radiobutton path="newsletter" value="modern health" />
    <form:checkboxes path="category" items="${categoryList}" />
    <form:radiobuttons path="category" items="${categoryList}" />
    <form:select id="category" path="category.id" items="${categories}" itemLabel="name" itemValue="id" >
        <option value="0">-- please select --</option>
    </form:select>
    <form:errors path="*" /><!--显示了所有字段的错误信息-->
    <form:errors path="author" /><!--显示了author属性相关的错误信息-->

    jstl

    <%@taglib prefix="c" uri="http://java.sun.com/jsp/core" %>

    转化器和格式化

    转换器converter,需要实现org.springframework.core.convert.converter.Converter接口

    格式化formatter,需要实现org.springframework.format.Formatter接口

    可以利用转化器和格式化来引导spring mvc应用程序中的数据绑定。Converter是一般工具,可以将任意类型转换成另一种类型,而Formatter只能将String类型转换成另一种Java类型。Formatter更适合于web层。

    验证器

    在spring mvc中,有两种方式可以验证输入,一是利用spring自带的验证框架,二是利用JSR 303实现。

    Converter和Formatter作用于field级,在mvc应用程序中,将String转换或格式化成另一种Java类型;验证器作用于object级,决定某一个对象中的所有field是否均是有效的以及是否遵循某些规则。

    如果一个应用程序中既使用了Formatter又使用了Validator,那么在调用Controller期间,先格式化,格式化完成之后验证器介入。

    验证器要实现org.springframework.validation.Validator接口。

    指定的验证器处理指定的Class文件,supports方法将返回true,validate方法会验证目标对象,并将验证错误填入Errors对象中。

    工具类org.springframework.validation.ValidationUtils有助于编写spring验证器。

    if(firstName==null || firstName.isEmpty()){
        errors.rejectValue("price");
    }
    // 相当于
    ValidationUtils.rejectIfEmpty("price");
    
    if(firstName==null || firstName.trim().isEmpty()){
        errors.rejectValue("price");
    }
    // 相当于
    ValidationUtils.rejectIfEmptyOrWhitespace("price");
    package com.xsl.springmvc;
    
    import org.springframework.validation.Errors;
    import org.springframework.validation.ValidationUtils;
    import org.springframework.validation.Validator;
    
    public class ProductValidator implements Validator {
        @Override
        public boolean supports(Class<?> arg0) {
            return Product.class.isAssignableFrom(arg0);
        }
        @Override
        public void validate(Object arg0, Errors arg1) {
            Product product = (Product) arg0;
            ValidationUtils.rejectIfEmpty(arg1, "name", "productname.required");
            ValidationUtils.rejectIfEmpty(arg1, "price", "price.required");
            Float price = product.getPrice();
            if(price != null && price < 0){
                arg1.rejectValue("price", "price.negative");
            }
        }
    }

    写好验证器类之后,如果想要从某个属性文件中获取错误信息,则需要通过声明messageSource bean,告诉spring要去哪里找这个文件,例如:

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="/WEB-INF/resource/messages" />
    </bean>

    上面代码意思是,错误码和错误信息可以在/WEB-INF/resource目录下的messages.properties文件中找到,例如:

    productname.required=please enter a product name
    price.required=please enter a price
    date.invalid=invalid date

    验证的三种方法:

    方法一:new出验证器类对象,调用validate方法,并在BindingResult中调用hasErrors方法看是否生成错误信息。

    package com.xsl.springmvc;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.validation.BindingResult;
    import org.springframework.validation.FieldError;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class ProductController {
        private static final Log logger = LogFactory.getLog(ProductController.class);
        @RequestMapping(value="/saveProduct")
        public String saveProduct(@ModelAttribute Product product,BindingResult bindingResult,Model model){
            ProductValidator validator = new ProductValidator();
            validator.validate(product, bindingResult);
            if(bindingResult.hasErrors()){
                FieldError fieldError = bindingResult.getFieldError();
                logger.info("code:"+fieldError.getCode()+",field:"+fieldError.getField());
                return "productForm";
            }
            model.addAttribute("product", product);
            return "productDetails";
        }
    }

    方法二:在controller中编写initBinder方法,并将验证器传到WebDataBinder,并调用其validate方法,会使验证器应用于Controller类中所有处理请求的方法。

        @InitBinder
        public void initBinder(WebDataBinder binder){
            // this will apply the validation to all request-handing methods
            binder.setValidator(new ProductValidator());
            binder.validate();
        }

    方法三:利用@javax.validation.Valid对要验证的对象参数进行标注(Valid标注类型是在JSR 303中定义的)。

    实体类上面嵌入约束

    package com.xsl.springmvc;
    import java.io.Serializable;
    import javax.validation.constraints.Min;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    public class Product implements Serializable {
        private static final long serialVersionUID = 748392348L;
        @Size(min=2,max=10)
        private String name;
        @NotNull
        private String description;
        @Min(0)
        private float price;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getDescription() {
            return description;
        }
        public void setDescription(String description) {
            this.description = description;
        }
        public float getPrice() {
            return price;
        }
        public void setPrice(float price) {
            this.price = price;
        }
        
    }

    为了覆盖JSR303的错误信息,可以在属性文件中使用键,例如:

    Size.product.name、NotNull.product.description、Min.product.price

    在controller中,必须要对调用的方法的参数进行标注

        @RequestMapping(value="/saveProduct")
        public String saveProduct(@Valid @ModelAttribute Product product,BindingResult bindingResult,Model model){
            if(bindingResult.hasErrors()){
                FieldError fieldError = bindingResult.getFieldError();
                logger.info("code:"+fieldError.getCode()+",field:"+fieldError.getField());
                return "productForm";
            }
            model.addAttribute("product", product);
            return "productDetails";
        }    

    为了定制来自验证器的错误信息,要在messages.properties文件中使用两个键。

    Size.product.name = name must be 2 to 10 characters long
    NotNull.product.description = description must be not null
    Min.product.price = price must be greater than 0

    JSR303约束

    @AssertFalse  应用于boolean属性,该属性值必须为false

    @AssertTrue  应用于boolean属性,该属性值必须为true

    @DecimalMax  该属性值必须为小于或等于指定值的小数

    @DecimalMin  该属性值必须为大于或等于指定值的小数

    @Digits  该属性值必须在指定范围内,integer属性定义该数值的最大整数部分,fraction属性定义该数值的最大小数部分,例如@Digits(integer=5,fraction=2)

    @Future  该属性值必须是未来的一个日期

    @Max  该属性值必须是一个小于或等于指定值的整数

    @Min  该属性值必须是一个大于或等于指定值的整数

    @NotNull  该属性值不能为null

    @Null  该属性值必须为null

    @Past  该属性值必须是过去的一个日期

    @Pattern  该属性值必须与指定的常规表达式相匹配

    @Size  该属性值必须在指定范围内

  • 相关阅读:
    maven如果正常配置不成功,就按照我的就可以配置成功了
    springmvc中model可以封装的数据类型
    sql中limit使用方法
    bootStrap的使用
    idea中 maven打包时时报错User setting file does not exist C:Userslenevo.m2setting.xml,
    解决方法:CentOS7用yum安装软件显示错误:cannot find a valid baseurl for repo: base/7/x86_64
    centOS 7下无法启动网络(service network start)错误解决办法
    Invalid bound statement (not found)
    AJAX+springmvc遇到的问题
    llegalStateException: getWriter() has already been called for this response
  • 原文地址:https://www.cnblogs.com/xsl1995/p/10169955.html
Copyright © 2011-2022 走看看