暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

JSR380输入验证(Base Spring)

Coding On Road 2019-06-06
725

   JSR 303 输入验证是 Javax.validation 1.0 

   JSR 349 输入验证是 Javax.validation 1.1

   目前Spring默认支持到JSR 349。

   JSR 380 输入验证是 javax.Validation 2.0 ,通过添加Hiberante validator 6.x 默认将使用JSR S80验证。

   根据Spring官网说明,对JSR 380 从Spring 5.x以后开始支持。但并不全面。经过测试,可以使用。   


10.1JSR380验证

以下使用最新的JSR380做为本次的验证,需要spring5以上版本。

1:可以使用@ExceptionHandler只用于验证一个Controller中的异常。

2@ControllerAdvice可以用于系统全局异常。

3BindingResult为错误的具体信息,可以被注入的任意的方法中用于设置错误或是读取错误信息。

4:建议根据不同的请求类型返回不同的响应信息,如,如果Acceptjson则应该响应JSON数据。

JSR380的验证包括:



1、添加验证依赖

<!-- 验证用的包以下是JSR380验证即javax.validation-2.0 -->

<dependency>  

 <groupId>org.hibernate.validator</groupId>

   <artifactId>hibernate-validator</artifactId> 

  <version>6.0.16.Final</version></dependency><dependency>   

<groupId>javax.el</groupId>

   <artifactId>javax.el-api</artifactId> 

  <version>3.0.0</version></dependency>

<dependency> 

  <groupId>org.glassfish</groupId>  

 <artifactId>javax.el</artifactId> 

  <version>3.0.0</version>

</dependency>


2、在spring配置文件中添加validator

   <!-- 定义验证器 -->

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">

       <!--以下属性如果不设置,将默认使用javax.validator-->       

<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/></bean>


  <!--方法上基本类型参数的验证-->   

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">       <property name="validator" ref="validator"/>   

</bean>

<!--用于识别@RequestMapping,并指定验证规则-->

<mvc:annotation-driven validator="validator"/>

 

1:注意上面的配置中,在annotation-driven中通过validator指定使用LocalValiatorFactoryBean,而LocalValidatorFactoryBean默认将使用 javax.validator

(见 API源代码)

2:注意上面包含两种不同的验证,其中LocalValidatorFactoryBeaan用于验证JavaBean,而MethodValidationPostProcessor用于验证方法上的其中类型和String.


3JavaBean验证

分为两步:

1:给javaBean添加注解。

2:在Controller的参数上添加@Valid注解。

 

JavaBean添加以下注解:

public class StudSaveForm {    

private Long id;    

@NotBlank(message = "姓名不能为空(name)")    

private String name;    

@NotNull(message = "年龄不能为空(age)")    

private Integer age;

}

 

Controller的参数上,添加以下注解:@Valid()

@PostMapping("/save")

@ResponseBody

public Stud save(@Valid()StudSaveForm form) {    

log.info("接收到的数据:"+form);    

Stud stud = studService.save(form);    

return stud;

}

 

如果验证不成功,将会抛出400 BadRequest 状态码,异常类型:BindException


4、方法上接收参数验证(基本类型和 String等包装类型 )

即以下方式:

@RequestMapping("/save2")

@ResponseBody

public Stud save2(@NotBlank(message = "用户名必须输入")String name,@NotNull(message = "年龄必须输入")Integer age){

    Stud stud  = new Stud();    

stud.setName(name);   

 stud.setAge(age);    

return stud;

}

 

这需要在方法的参数上添加@NotBlank等等注解。然后还需要在类上添加:@Vaidate注解:

@Controller@Slf4j@Validated  //注意这个注解

@RequestMapping("example/stud")public class StudController {

..

}

 

上面的已经添加了,如下的配置,上面的配置才会有效:【 支持方法上的验证

<!--方法上基本类型参数的验证-->

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">    <property name="validator" ref="validator"/></bean>

 

 

然后,测试,如果没有输入name,age的值,请求对应地址,则将抛出异常:ConstraintViolationException


5、开发异常处理中心

使用@ControllerAdvice可以统一处理异常,以下是具体统一处理的类,它同时根据用户的请求的是ajax还是网页,返回了不同的内容,以下代码主要是两个核心注解:

@ControllerAvice

@ExceptionHandler+[@ResponseStatus 可选]

 

 

package cn.ssm.core.controller;

import com.fasterxml.jackson.databind.ObjectMapper;


import lombok.extern.slf4j.Slf4j;


import org.springframework.stereotype.Controller;

import org.springframework.validation.BindException;

import org.springframework.validation.FieldError;

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.context.request.RequestContextHolder;

import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.validation.ConstraintViolation;

import javax.validation.ConstraintViolationException;

import java.util.*;

@Slf4j@ControllerAdvice

public class ExceptionController {    

public ExceptionController() {        

log.info("异常处理类启动成功..." + this);    

}    

//这儿所有没有匹配到的异常,在开始时,建议删除    

@ExceptionHandler(value = Exception.class)    

public String exception(Exception e) {        

log.info("异常:" + e.getMessage() + ",异常类型:" + e.getMessage());        e.printStackTrace();        

return "abc";    }    

/**     * 

JavaBean验证失败用于处理JavaBean验证失败     

*/    

@ExceptionHandler(value = org.springframework.validation.BindException.class)    

public String bindException(BindException bindException, HttpServletRequest request) throws Exception {

        List<FieldError> list = bindException.getFieldErrors();        

log.info("数据绑定异常:" + bindException.getMessage() + "," + bindException.getCause());        

log.info("请求类型为:" + request.getHeader("Accept"));        

bindException.printStackTrace();        

String accept = request.getHeader("Accept");        

if (accept.toLowerCase().contains("/json")) {

//如果包含json            

ServletRequestAttributes sra = 

(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();            

HttpServletResponse response = sra.getResponse();            

response.setContentType("application/json;charset=UTF-8");            

Map<String, Object> map = new HashMap<>();            

map.put("result", 1);//错误            

for (FieldError fe : list) {                

map.put(fe.getField(), fe.getDefaultMessage());           

 }

            ObjectMapper objectMapper = new ObjectMapper();

String json = objectMapper.writeValueAsString(map);

            response.getWriter().print(json);

            return null;

        }

        StringBuilder sb = new StringBuilder();

        for (FieldError fe : list) {

            sb.append("错误-字段:" + fe.getField() + ",错误:" + fe.getDefaultMessage() + "<br>");

        }

        request.setAttribute("errorMsg", sb.toString());

        return "error/error";

    }

    /**

     * 方法上的基本类型验证失败用于处理参数验证失败

     */

    @ExceptionHandler(value = ConstraintViolationException.class)    public String methodValidation(ConstraintViolationException e,HttpServletRequest request) throws Exception{

        Set<ConstraintViolation<?>>

 sets =  e.getConstraintViolations();

        String accept = request.getHeader("Accept");

        if (accept.toLowerCase().contains("/json")) {//如果包含json

            ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

            HttpServletResponse response = sra.getResponse();

            response.setContentType("application/json;charset=UTF-8");

            Map<String, Object> map = new HashMap<>();

            map.put("result", 1);//错误

            for (ConstraintViolation fe : sets) {


                String msg = fe.getMessage();

                if(map.containsKey("error")){//只有错误信息,没有key

                    map.put("error",map.get("error")+","+msg);

                }else{

                    map.put("error",msg);

                }

            }

            ObjectMapper objectMapper = new ObjectMapper();

            String json = objectMapper.writeValueAsString(map);

            response.getWriter().print(json);

            return null;

        }

        StringBuilder sb = new StringBuilder();

        for (ConstraintViolation fe : sets) {

            sb.append("错误-字段:" + fe.getMessage()+"<br>");

        }

        request.setAttribute("errorMsg", sb.toString());

        return "error/error";

    }}

6、网页测试结果

Ajax测试结果:


10.2、输入验证的更多细节

1ResponseStatus验证错误状态码

可以添加 ResponseStatus注解,确定错误的状态码,如下所示:

 @ResponseStatus(code = HttpStatus.BAD_REQUEST)

     @ExceptionHandler(value = org.springframework.validation.BindException.class)

     public String bindException(BindException bindException, HttpServletRequest request) throws Exception {

2、在一个Controller中进行验证

@Controller@Slf4j@Validated@RequestMapping("example/stud")

public class StudController {

@PostMapping("/save")

@ResponseBody

public Stud save(@Valid()StudSaveForm form) {

    log.info("接收到的数据:"+form);    Stud stud = studService.save(form);

    return stud;

}

 

    

@ResponseStatus(value = HttpStatus.BAD_REQUEST)

    @ExceptionHandler(BindException.class)

    public String exception(Exception e, BindingResult errors, HttpServletRequest request){

        log.info("验证错误:"+e.getMessage());

        log.info("类型:"+e.getClass());

        e.printStackTrace();

        int errorCont =  errors.getErrorCount();

        log.info("错误的数量:"+errorCont);

        List<FieldError> list =  errors.getFieldErrors();

        for(FieldError

 error:list){

            log.info(error.getField()+","+error.getDefaultMessage()+","+error.getRejectedValue());

        }

       return "error/error"; 

   }}


10.3、自定义验证器

  后续

 




文章转载自Coding On Road,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论