SpringMVC 实现数据绑定

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

SpringMVC 会根据请求方法签名不同,将请求消息的消息以一定的方式转换并绑定到请求的参数中。在请求消息到达真正处理方法之前的这一段时间内,SpringMVC需要完成请求消息转换,数据转换,格式化,数据校验等

1.数据绑定流程

SpringMVC 框架将ServletRequest 对象(HttpServletRequest 为其子类)以及处理方法的参数对象实例传递给DataBinder,DataBinder 调用Spring web 上下文的ConversionService 数据组件进行数据转换,并将ServletRequest 中消息填充到参数对象中,然后调用Validator组件进行数据合法性验证,最总生成的BindingResult 对象包含已完成转换的参数对象和校验错误对象。

2.数据转换

1.在Spring上下文中定义一个ConversionService,Spring 将自动识别上下文中的Conversion Service,并在SpringMVC 处理方法的参数绑定中使用它进行数据转换。

<!-- 装配自定义类型转换器 -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!--自定义类型转换器-->
<bean id="conversionService" 
    class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name ="converters">
        <list>
            <!--自己编写的转换器类-->
            <bean class="org...StringtoDataConverter" 
            p:dataPattern="yyyy-MM-dd"></bean>
        </list>
    </property>
</bean>

2.在控制器的任何处理方法中使用这个转换器

@RequestMapping(value='/register',method = RequstMethod.POST)
public String registe(
    @ModelAtrribute User user,model model)
    {}

数据校验

输入校验分为客户端校验和服务端校验,客户端校验主要是过来正常用户的误操作,服务器端校验组织非法数据

SpringMVC 提供强大的数据校验功能,一个是利用Spirng 自带的Validation 校验框架;另一种是利用JSR303 实现校验功能

1.validation 校验框架
位于org.Springframework.validation ,重要接口和类定义如下

  • Validator 接口:提供两个方法
    Boolean supports(Class< ?> clazz):对clazz 类型的对象进行校验
    void validate(Object targe,Errors errors):对目标类target 进行校验
  • Error接口:存放错误信息
  • LocalValidatorFactoryBean:该类实现了Spring的Validator 接口,也实现了JSR303 的Validator接口,只要在容器中定义一个LcoalValidatorFactorybean ,既可以注册到数据校验的Bean 中。< mvc:annotation-driven/> 默认装配好LocalValidatorFactoryBean.
@Repository("userValidator")
public class UserValidator implements validator{
    public boolean supports(Class<?> clazz){
    ...}
    public void validate(Object target,Error errors){
        ValidationUtils.rejectIfEmpty(errors,"loginname",null,"登陆名不能为空")

通过@Repository(“userValidator”)注解将该对象注释为Spring容器中一个bean,名字为”userValidator”

@Autowired
@Qualifier("uservalidator")
private UserValidator userValidator;

@requestmapping(value="/login")
public static login(
    @ModelAttribute User user,
    Model model,
    Errors errors){
    userValidator.validate(user,errors);
    ...
    }

2.JSR303 是Java 为Bean数据合法性校验提供一个标准规范,用于对java Bean 中字段值进行校验,通过在Bean 属性上标注类似@NotNull 指定校验规则,通过校验接口实现对bean 校验(可以自定义注解)

< mvc:annotation-driven/>会默认装配一个LocalValidatorFactoryBean ,通过在处理方法的入参上标注@Valid注解,即可让SpringMVC在完成数据绑定后执行数据校验工作。

//constraint 注解
@Documented
@Target({ ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface Constraint {
    Class<? extends ConstraintValidator<?, ?>>[] validatedBy();

一个 constraint 通常由 annotation 和相应的 constraintValidator(约束验证器) 组成,它们是一对多的关系。也就是说可以有多个 constraintValidator 对应一个 annotation。在运行时,Bean Validation 框架本身会根据被注释元素的类型来选择合适的 constraint validator 对数据进行验证。

//ConstraintValidator 接口
public interface ConstraintValidator<A extends Annotation, T> {
    void initialize(A constraintAnnotation);
    boolean isValid(T value, ConstraintValidatorContext context);

第一个是我们的注解,也就是我们自己定义的注解,第二个是参数的值
ConstraintValidator是一个接口,也就是我们自己定义的校验类要实现这个接口

例如 我们 校验手机号,可以写一个 @Mobile的注解

import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

import miaosha.validator.MobileValidator;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;

/**
 * 做一个mobile的注解 注意我们使用的静态导入
 * 
 * @author kaifeng1
 *
 */
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { MobileValidator.class })
public @interface Mobile {
    boolean required() default true;

    String message() default "手机号码格式错误";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

需要自定义一个校验器 MobileValidator,它使用 ValidatorUtil来完成校验的具体逻辑

MobileValidator.java

package miaosha.validator;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.apache.commons.lang3.StringUtils;

import miaosha.annotation.Mobile;
import miaosha.util.ValidatorUtil;

public class MobileValidator implements ConstraintValidator<Mobile, String> {
    private boolean required = false;
    /**
     * 初始化
     */
    public void initialize(Mobile constraintAnnotation) {
        required = constraintAnnotation.required();
    }

    /**
     * 校验
     */
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (required) {
            return ValidatorUtil.isMobile(value);
        } else {
            if (StringUtils.isEmpty(value)) {
                return true;
            } else {
                return ValidatorUtil.isMobile(value);
            }
        }
    }

}

ValidatorUtil.java


package miaosha.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

/**
 * 校验
 * 
 * @author 
 *
 */
public class ValidatorUtil {

    private static final Pattern mobile_pattern = Pattern.compile("1\\d{10}");

    public static boolean isMobile(String src) {
        if (StringUtils.isEmpty(src)) {
            return false;
        }
        Matcher m = mobile_pattern.matcher(src);
        return m.matches();
    }
}

我们使用该注解的时候:

    @Mobile
    private String mobile;

猜你喜欢

转载自blog.csdn.net/jcsyl_mshot/article/details/81638761