栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring MVC组件开发-表单数据校验

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring MVC组件开发-表单数据校验

       在实际工作中,得到数据后的第一步就是校验数据的正确性,如果存在录入上的问题,一般先经过前端js进行验证,但是前端有多种方式可以绕过前端js验证(不是安全有效的),为了数据安全性一般还需要在服务器端做数据校验。这个时候就可以使用spring所提供的验证器(Validator)规则去验证。

        所有的验证都是要先注册验证器,不过验证器也是springmvc自动加载的。我们使用JSR 303校验规范,hibernate提供的数据校验器进行数据校验。

使用JSR 303注解验证输入内容

        Spring  提供了对Bean的功能校验,通过注解@Valid标明哪个Bean需要启用注解式的验证。在javax.validation.constrains.*中定义了一系列的JSR 303规范给出的注解:

限制

说明

@Null

限制只能为null

@NotNull

限制必须不为null

@AssertFalse

限制必须为false

@AssertTrue

限制必须为true

@DecimalMax(value)

限制必须为一个不大于指定值的数字

@DecimalMin(value)

限制必须为一个不小于指定值的数字

@Digits(integer,fraction)

限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction

@Future

限制必须是一个将来的日期

@Max(value)

限制必须为一个不大于指定值的数字

@Min(value)

限制必须为一个不小于指定值的数字

@Past

限制必须是一个过去的日期

@Pattern(value)

限制必须符合指定的正则表达式

@Size(max,min)

限制字符长度必须在min到max之间

@Email

邮箱类型

@NotEmpty

集合,不为空

@NotBlank

不为空字符串

@Positive

数字,正数

@PositiveOrZero

数字,正数或0

@Negative

数字,负数

@NegativeOrZero

数字,负数或0

@PastOrPresent

过去或者现在日期

@FutrueOrPresent

将来或者现在日期

为了使用这些注解,假设要完成一个保存雇员表单:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
  
  
  
  
    添加员工  
  
  
      
            用户名:  
              
            
               密码:
               电子邮箱:
               员工生日:
               薪水:
               联系电话:
                            员工简介:                       
                                  
校验规则:
  • 户名,密码,电子邮箱,入职日期不能为空
  • 入职日期格式为yyyy-MM-dd,且只能大于今日
  • 生日日期格式为yyyy-MM-dd,且只能是一个过去日期
  • 邮箱需要符合格式:
  •  简介内容不得多于256个字符
  • 薪水最小值为2000,最大值为5万
  • 联系方式需为正确的手机号码(使用正则表达式匹配)

建立pojo,确定校验规则:

public class Employee {  
    private Integer id;  
      
    @NotBlank(message = "用户名不能为空")  
    @Size(min = 4,max = 12,message = "{employee.username.valid.size.message}")  
    private String username;  
      
    @NotBlank(message = "密码不能为空")  
    @Size(min = 6,max = 12,message = "密码最低6位")  
    private String password;  
      
      
    @NotNull(message = "邮箱不能为空")  
    @Email(message="邮箱必须满足基本格式")  
    private String email;  
      
    @DateTimeFormat(iso = ISO.DATE)  
    @Past(message = "你不能录用还未出生的员工")  
    private LocalDate bornDate;  
      
      
    @DateTimeFormat(iso = ISO.DATE)  
    @FutureOrPresent  
    private LocalDate entryDate = LocalDate.now();  
      
    @Pattern(regexp = "^1[358]\d{9}$",message = "请输入正确的手机号码")  
    private String phone;  
      
    @Min(value = 2000,message="工资不能低于2000,否则麻烦了")  
    @Max(value=50000,message="工资不能大于50000,否则交奢侈税")  
    private float salary;  
      
      
    @Size(min = 6,max = 12,message = "员工简介不能超过200字")  
    private String intro;  
  
       /  
}  
       这样就定义了一个pojo,用于接收表单的信息。字段上面的注解反映了对每一个字段的验证要求,这样就可以加入对应校验,如果没有指定message属性,会生成默认的错误信息。message配置项用来定义当校验失败后的错误信息,这样就能启动Spring的检验规则来校验表单了。

用控制器验证表单:

@Controller  
@RequestMapping("/control/emp")  
public class EmployeeController {  
    @RequestMapping("/save")  
    public String save(@Validated Employee emp,BindingResult errors) {  
        if(errors.hasErrors()) {  
            return "emp/emp_save";  
        }  
        return "redirect:./list";  
    }  
}  
        使用了注解@Validated 标明这个Bean将会被校验,另外一个类型为BindingResult的参数(或者为Errors)是用于保存校验是否存在错误信息的,也就是当采用JSR 303规范进行校验后,它会将这个错误信息保存到这个参数中,在方法中判断是否有错误信息,如果有错误信息,跳转到填写表单页面告诉用户错误信息。

如何在jsp页面中显示错误信息呢?这时可以使用jsp提供给我们的标签库

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
<%@ taglib prefix="form"  uri="http://www.springframework.org/tags/form"%>  
  
  
  
    添加员工  
  
  
      
            用户名:  
              
            
               密码:
               电子邮箱:
               员工生日:
               薪水:
               联系电话:
                            员工简介:                       
                           
看起来似乎非常不错,但是我们的message错误提示信息是硬编码在pojo身上,为了避免其硬编码而实现可配置,我们在src/main/resource下新建messageSource.properties文件:
employee.username.valid.notnull.message=用户名不能为空  
employee.username.valid.size.message=用户名不能少于4位且不能超过12位 
上面简单罗列了两个错误信息配置,其它道理一样,哪怎么应用(读取)指定的错误信息呢?在pojo验证规则之上:
  
@NotBlank(message = "{employee.username.valid.notnull.message}")  
@Size(min = 4,max = 12,message = "{employee.username.valid.size.message}")  
private String username;  

 可以采用{}表达式对配置文件的key加以读取其对应的value。其它字段同理,到这里还不能读取指定配置文件,需要告诉spring的检验器加载什么样的配置文件,配置代码如下:

@Configuration  
@ComponentScan(basePackages = "com.wise.tiger.web")  
@EnableWebMvc  
public class WebConfig implements WebMvcConfigurer{  
    @Bean  
    public InternalResourceViewResolver viewResolver() {  
        var viewResolver = new InternalResourceViewResolver();  
        viewResolver.setPrefix("/WEB-INF/pages/");  
        viewResolver.setSuffix(".jsp");  
        return viewResolver;  
    }  
  
    @Override //静态资源不被前端控制器拦截  
    public void addResourceHandlers(ResourceHandlerRegistry registry) {  
        registry.addResourceHandler("/static  
    @Override  
    public Validator getValidator() {  
        var validator = new LocalValidatorFactoryBean();  
        validator.setProviderClass(HibernateValidator.class);  
        validator.setValidationMessageSource(messageResource());  
        return validator;  
    }  
}  

 分组校验

1.定义分组:可以采用标识接口来进行分组区分

//分组校验1  
public interface ValidationGroup1 {  
}  
  
//分组校验2  
public interface ValidationGroup2 {  
}

2.在检验规则上添加分组

  
@NotBlank(message = "{employee.username.valid.notnull.message}",groups = ValidationGroup1.class)  
@Size(min = 4,max = 12,message = "{employee.username.valid.size.message}",groups = ValidationGroup2.class)  
private String username;  

3.在conroller中指定使用的分组校验

@Controller  
@RequestMapping("/control/emp")  
public class EmployeeController {  
    @RequestMapping("/save")  
    public String save( @Validated(ValidationGroup2.class) @ModelAttribute Employee emp,BindingResult errors,Model model) {  
        if(errors.hasErrors()) {  
            for (var i = 0; i < errors.getErrorCount();i++) {  
                System.out.println(errors.getObjectName() + ":" + errors.getFieldError().getDefaultMessage());  
            }  
            return "emp/emp_save";  
        }  
        return "redirect:./list";  
    }  
}  

 有时候除了简单的输入格式、非空性等校验,也需要一定的业务校验,Spring提供了Validator接口来实现校验,它将在进入控制器逻辑之前对参数的合法性进行校验。核心代码如下:

public interface Validator {  
      
    @Override  
    public boolean supports(Class clazz) {  
        return false;  
    }  
  
      
    @Override  
    public void validate(Object target, Errors errors) {  
          
    }  
  
}  

Validator接口是SpringMvc校验表单的核心接口,它只是一个验证器,在Spring中最终被注册到验证器的列表中,这样就可以提供给各个控制器去定义,然后通过supports方法判定是否会启用验证器去验证数据。对于校验的过程,则是通过validate方法去实现的。

package com.wise.tiger.pojo;  
  
import org.springframework.validation.Errors;  
import org.springframework.validation.Validator;  
  
  
public class EmployeeValidator implements Validator {  
      
    @Override  
    public boolean supports(Class clazz) {  
        //判断验证是否为Employee,如果是则进行校验  
        return Employee.class.equals(clazz);  
    }  
  
    
    @Override
    public void validate(Object target, Errors errors) {
        var emp = (Employee)target;
        if(emp.getSalary() < emp.getJob().getLowSalary()){
            errors.rejectValue("job",null,String.format("薪水%.2f低于%s的最低薪资水平:%.2f",emp.getSalary(), emp.getJob().getValue(),emp.getJob().getLowSalary()));
        }
    }  
}  

在Employee实体上添加职位属性字段,该字段为枚举类型,定义如下:

@Getter
@RequiredArgsConstructor
public enum JOB {
    CLERK(2000,"业务员"),
    SALESMAN(2000,"销售员"),
    ANALYST(5000,"分析员"),
    SEARCHER(3000,"搜索员"),
    MANAGER(6000,"经理"),;
    @NonNull
    private float lowSalary;
    @NonNull
    private String value;
}
//================================Employee===========================
@NotNull(message = "{employee.job.notnull.message}")
private JOB job;

//================================jsp================================
  职位:
  
    
  
  

需要将该验证器捆绑到对应的控制器中,Spring MVC提供了注解@InitBinder,通过该注解就可以将验证器和控制器捆绑在一起,这样就能对请求表单进行验证了。

@Controller  
@RequestMapping("/control/emp")  
public class EmployeeController {  
    @InitBinder  
    public void initBinder(DataBinder binder){  
        //数据绑定器加入验证器  
        binder.setValidator(new EmployeeValidator());  
    }  
    @RequestMapping("/save")  
    public String save( @Validated(ValidationGroup2.class) @ModelAttribute Employee emp,
BindingResult errors,Model model) {  
        if(errors.hasErrors()) {  
            for (var i = 0; i < errors.getErrorCount();i++) {  
                System.out.println(errors.getObjectName() + ":" + errors.getFieldError().getDefaultMessage());  
            }  
            return "emp/emp_save";  
        }  
        return "redirect:./list";  
    }  
}  

这样就能对比较复杂的逻辑关系进行校验了。@InitBinder的使用还有其它内容,后续讲解。。。。。。

附:依赖列表

dependencies {  
    compile group: 'org.springframework', name: 'spring-context', version: '5.1.7.RELEASE'  
    compile group: 'org.springframework', name: 'spring-webmvc', version: '5.1.7.RELEASE'  
    compile group: 'org.springframework', name: 'spring-test', version: '5.1.7.RELEASE'  
    providedCompile group: 'javax.servlet.jsp', name: 'javax.servlet.jsp-api', version: '2.3.3'  
    providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'  
    compile group: 'taglibs', name: 'standard', version: '1.1.2'  
    compile group: 'javax.servlet', name: 'jstl', version: '1.2'  
    compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'  
    compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'  
    compile group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.1'  
    compile group: 'org.mybatis', name: 'mybatis', version: '3.5.1'  
    compile group: 'com.alibaba', name: 'druid', version: '1.1.16'  
    compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.16'  
    compile group: 'org.springframework', name: 'spring-jdbc', version: '5.1.7.RELEASE'  
    compile group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'  
    compile group: 'org.hibernate', name: 'hibernate-validator', version: '6.0.16.Final'  
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.9'  
}  

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/981489.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号