欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring MVC 数据校验

程序员文章站 2022-07-08 19:25:13
...

Spring MVC

Spring MVC 提供了两种数据校验的⽅式:
1、基于 Validator 接⼝。
基于 Validator 接⼝的⽅式需要⾃定义 Validator 验证器,每⼀条数据的验证规则需要开发者⼿动完成,

2、使⽤ Annotation JSR - 303 标准进⾏校验。
使⽤ Annotation JSR - 303 标准则不需要⾃定义验证器,通过注解的⽅式可以直接在实体类中添加每个属性的验证规则,这种⽅式更加⽅便,实际开发中推荐使⽤。

Annotation JSR - 303 标准

使⽤ Annotation JSR - 303 标准进⾏验证,需要导⼊⽀持这种标准的依赖 jar ⽂件,这⾥我们使⽤
Hibernate Validator。

		  <!--JSR303数据校验支持;tomcat7及以上的服务器,
		tomcat7以下的服务器:el表达式。额外给服务器的lib包中替换新的标准的el
		-->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.1.Final</version>
        </dependency>

给pojo指定校验规则

public class User {
    @NotBlank
    private String username;

    @Length(min = 4,max = 8)
    private String password;

    @Min(22)
    private Integer age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

@valid

增加@Valid注解,验证失败会报错。
Servlet.service() for servlet springDispatcherServlet threw exception
java.lang.NoSuchMethodError:javax.el.ExpressionFactory.newInstance()Ljavax/el/ExpressionFactory;

    @RequestMapping("useradd")
    public String add(@Valid User user, BindingResult bindingResult, Model model){
        Map<String,Object> map=new HashMap<>();
        if(bindingResult.hasErrors()){

            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            for (FieldError fieldError : fieldErrors) {
                System.out.println(fieldError.getField());
                System.out.println(fieldError.getDefaultMessage());
                System.out.println(fieldError);
                map.put(fieldError.getField(),fieldError.getDefaultMessage());
            }
            model.addAttribute("map",map);
            return "user";
        }
        return "success";
    }

BindingResult

public interface BindingResult extends Errors
1.Spring MVC 是通过对处理方法签名的规约来保存校验结果的:前一个表单/命令对象的校验结果保存到随后的入参中,这个保存校验结果的入参必须是 BindingResult 或 Errors 类型,这两个类都位于 org.springframework.validation 包中
2.需校验的 Bean 对象和其绑定结果对象或错误对象是成对出现的,它们之间不允许声明其他的入参
3.Errors 接口提供了获取错误信息的方法,如 getErrorCount() 或 getFieldErrors(String field)
4.BindingResult 扩展了 Errors 接口

在目标方法中获取校验结果

在表单/命令对象类的属性中标注校验注解,在处理方法对应的入参前添加 @Valid,Spring MVC 就会实施校验并将校验结果保存在被校验入参对象之后的 BindingResult 或 Errors 入参中。
常用方法:
FieldError getFieldError(String field)
List getFieldErrors()
Object getFieldValue(String field)
Int getErrorCount()

获取提示信息返回给页面

   @RequestMapping("useradd")
    public String add(@Valid User user, BindingResult bindingResult, Model model){
       Map<String,Object> map=new HashMap<>();
        if(bindingResult.hasErrors()){
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            for (FieldError fieldError : fieldErrors) {
                System.out.println(fieldError.getField());
                System.out.println(fieldError.getDefaultMessage());
                System.out.println(fieldError);
                map.put(fieldError.getField(),fieldError.getDefaultMessage());
            }
            model.addAttribute("map",map);
            return "user";
        }
        return "success";
    }

异常处理

  • ExceptionHandlerExceptionResolver
  1. 主要处理 Handler 中用 @ExceptionHandler 注解定义的方法。
  2. [email protected] 注解定义的方法优先级问题:例如发生的是NullPointerException,但是声明的异常有 RuntimeException 和 Exception,此候会根据异常的最近继承关系找到继承深度最浅的那个 @ExceptionHandler 注解方法,即标记了 RuntimeException 的方法
  3. ExceptionHandlerMethodResolver 内部若找不到@ExceptionHandler 注解的话,会找 @ControllerAdvice 中的@ExceptionHandler 注解方法
  4. @ExceptionHandler
@ExceptionHandler(value={java.lang.ArithmeticException.class})
public ModelAndView handleException(Exception ex){
		System.out.println("出现异常啦:"+ex);
		ModelAndView mv = new ModelAndView("error");
		mv.addObject("exception", ex);
		return mv;
}
  • @ControllerAdvice
@ControllerAdvice
public class ExceptionHandle {

    /**
     *  异常处理
     *  @ExceptionHandler 指定处理异常
     *  要携带的异常信息不能给参数位置写model
     *  可以使用ModelAndView
     *  多个能处理该异常的方法  精确优先 顺序优先
     */
    @ExceptionHandler(Exception.class)
    public ModelAndView excetption(Exception e){
        ModelAndView modelAndView=new ModelAndView();
        System.out.println(e);
        modelAndView.addObject("err",e);
        modelAndView.setViewName("/500.jsp");
        return modelAndView;
    }
}   
  • ResponseStatusExceptionResolver
  1. 在异常及异常父类中找到 @ResponseStatus 注解,然后使用这个注解的属性进行处理。
  2. 定义一个 @ResponseStatus 注解修饰的异常类
  3. 若在处理器方法中抛出了上述异常:若ExceptionHandlerExceptionResolver 不解析上述异常。
  4. 由于触发的异常 UnauthorizedException 带有@ResponseStatus 注解。
  5. 因此会被ResponseStatusExceptionResolver 解析到。
  6. 最后响应HttpStatus.UNAUTHORIZED 代码给客户端。HttpStatus.UNAUTHORIZED 代表响应码401,无权限。 关于其他的响应码请参考 HttpStatus 枚举类型源码。

如果没有异常处理类捕获,那么会交由SpringMVC来处理

/**
 * @author pyc    自定义异常,标注异常的响应状态码,异常拦截器根据异常注解的状态码决定跳转的错误页面
 */
@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {

    public NotFoundException() {
    }

    public NotFoundException(String message) {
        super(message);
    }

    public NotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}
  • 抛出异常
@RequestMapping(value="/testResponseStatusExceptionResolver")
public String testResponseStatusExceptionResolver(@RequestParam("i") int i){
	if(i==13){
	throw new UsernameNotMatchPasswordException();
		}
	System.out.println("testResponseStatusExceptionResolver...");
	return "success";
}
  • 异常处理类捕获异常 判断 是否有ResponseStatus注解
   //  异常处理方法   ModelAndView  不能在参数上注入 ==>
    @ExceptionHandler(Exception.class)
    public ModelAndView exceptionHandler(HttpServletRequest req, Exception e) throws Exception {
        logger.error("Requst URL : {},Exception : {}", req.getRequestURL(),e);

        //  如果异常有ResponseStatus的注解
        if(AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class)!=null){
            //抛出异常    springboot有 指定默认的处理页面 寻找 error文件夹下的对应 400 500异常
            throw  e;
        }        
        // 视图模型
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("url", req.getRequestURL());
        modelAndView.addObject("exception", e);
        modelAndView.setViewName("error/error");
        return modelAndView;
    }

校验规则详解

@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.
@Min(value) 被注解的元素必须是⼀个数字,其值必须⼤于等于指定的最⼩值
@Max(value) 被注解的元素必须是⼀个数字,其值必须⼩于于等于指定的最⼤值
@Email 被注解的元素必须是电⼦邮箱地址
@Pattern 被注解的元素必须符合对应的正则表达式
@Length 被注解的元素的⼤⼩必须在指定的范围内

相关标签: SpringMVC