springBoot

SpringBoot入门实践(六)-JSR-349实现请求参数验

2020-01-25  本文已影响0人  _兰陵笑笑生

 我的博客:兰陵笑笑生,欢迎浏览博客!

 上一章 SpringBoot入门实践(五)-开源日志框架介绍当中,我们介绍了常用的开源日志框架。本期总结我在项目中是如何使用JSR实现请求参数的验证的。

前言

 从Spring4开始,已经实现了对JSR-349(Bean Validation,是JSR303的升级 )的全面支持,Bean Validation API在javax。validation.CONSTRAINTS 中以JAVA注解的形式定义了一组可应用于域对象的约束,另外可以使用注解开发和应用自定义验证器,如类级验证器。

一、Spring中配置Bean Validation的支持

使用方式:

public class Singer {  
    @NotNull(message = "名称不能为空")  
    @Size(min = 2, max = 5)   
    private String fistName;  
    private String lastName;   
    @NotNull(message = "性别不能为空")  
    private Genre genre;
    ....
}
package com.miroservice.chapter2.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;@Configuration@ComponentScan("com.miroservice")
public class AppConfig { 
    /**     * 默认会在类路径下搜索Hibernate validator的库     * @return     */  
    @Bean  
    LocalValidatorFactoryBean validator(){     
        return new LocalValidatorFactoryBean();  
    }
}
import com.miroservice.chapter2.pojo.Singer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.validation.ConstraintViolation;import javax.validation.Validator;import java.util.Set;
@Component
public class ValidateComponent {  
    /**     * 注入一个javax.validation.Validator 实例     */  
    @Autowired    
    private Validator validator;   
    
    public Set<ConstraintViolation<Singer>> validatorSinger(Singer singer) { 
        return validator.validate(singer);  
    }
}
package com.miroservice.chapter2.web;
import com.miroservice.chapter2.config.AppConfig;
import com.miroservice.chapter2.pojo.Singer;
importorg.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import javax.validation.ConstraintViolation;
import java.util.Set;

public class JSR349Demo { 
public static void main(String[] args) {   
GenericApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);   
ValidateComponent validateController = ctx.getBean(ValidateComponent.class);        Singer singer = new Singer();      
    singer.setFistName("j");    
    singer.setLastName("l");     
    singer.setGenre(null);      
    validatorSinger(singer, validateController);  
}    
    private static void validatorSinger(Singer singer, 
                                        ValidateComponent validateController) {  
        
        final Set<ConstraintViolation<Singer>> constraintViolations = validateController.validatorSinger(singer);    
        listVidlations(constraintViolations);    
    }  
    
    private static void listVidlations(Set<ConstraintViolation<Singer>> set) {     
        for (ConstraintViolation<Singer> v : set) {  
            System.out.print("property:" + v.getPropertyPath() + ",value:" 
                             + v.getInvalidValue() + ";error:" + v.getMessage());  
        } 
    }
}
file

二、常用的注解解释

Hibernate Validator参考实现 http://hibernate.org/validator/

三、springBoot中web请求的POJO验证

使用方式:

import javax.validation.constraints.NotNull;import javax.validation.constraints.Size;
public class Singer { 
    
    @NotNull(message = "名称不能为空")    
    @Size(min = 2, max = 5)  
    private String fistName;   
    
    private String lastName; 
    
    @NotNull(message = "性别不能为空")   
    private Genre genre;
   ...   
}
import com.miroservice.chapter2.common.HttpResponse;
import com.miroservice.chapter2.pojo.Singer;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;

@RestController
public class SingerController { 
    /**    
    * 添加@Valid 注解    
    * @param singer    
    * @return   
    */ 
    @PostMapping("/singer")    
    private String validator(@Valid @RequestBody Singer singer) {      
        System.out.print(singer);     
        return "ok"; 
}
{
    "fistName":null,
    "genre":"FEMALE"    
}
{
    "timestamp": "2020-01-11T15:16:22.851+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "NotNull.singer.fistName",
                "NotNull.fistName",
                "NotNull.java.lang.String",
                "NotNull"
            ],
            "arguments": [
                {
                    "codes": [
                        "singer.fistName",
                        "fistName"
                    ],
                    "arguments": null,
                    "defaultMessage": "fistName",
                    "code": "fistName"
                }
            ],
            "defaultMessage": "名称不能为空",
            "objectName": "singer",
            "field": "fistName",
            "rejectedValue": null,
            "bindingFailure": false,
            "code": "NotNull"
        }
    ],
    "message": "Validation failed for object='singer'. Error count: 1",
    "path": "/singer"
}
@PostMapping("/singer") 
private HttpResponse validator(@Valid @RequestBody Singer singer, BindingResult result) 
{   
    if (result.hasErrors()) {    
    return HttpResponse.error(result.getFieldError().getDefaultMessage());    
    }     return HttpResponse.ok();
    
}
{
    "code": 500,
    "message": "名称不能为空",
    "requestid": "eebb0bf86dc24aabb9051bf832542828"
}

四、创建自定义注解验证器

 对于一些复杂的验证,比如说手机号码的验证,需要多个条件,或者一个验证的POJO中包含了另一个类,出现了这样的需求也是常有的,这就需要我们自定义创建验证器了,以手机的长度为例,我们自定义一个手机号的验证。

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
//使用的验证器,自定义验证器
@Constraint(validatedBy = PhoneValidator.class)
//注解的使用级别是方法、属性上
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Phone {  
    //如果 验证经过PhoneValidator的验证返回false ,则默认返回的信息  
    String message() default "长度必须大于11";   
    /**  
    *   
    * @return 
    */  
    Class<?>[] groups() default {};  
    Class<? extends Payload>[] payload() 
        default {}
    ;

}
package com.miroservice.chapter2.pojo;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/** 
* 
自定义实现对phone的验证逻辑
*/
public class PhoneValidator implements ConstraintValidator<Phone,String> {   
    /** 
    *  value就是属性
    *   
    */ 
    @Override  
    public boolean isValid(String value, ConstraintValidatorContext context) { 
        if(value==null||value.trim().length()<12){       
            return false;   
        }else {         
            return true;     
        }   
    }
}
public class Singer { 
    
@NotNull(message = "名称不能为空")  
@Size(min = 2, max = 5)  
    
private String fistName; 
    
private String lastName;  
@NotNull(message = "性别不能为空") 
    
private Genre genre;   
    
@Phone()  
private String phone;
...
}
{
    "phone" : 1,
    "fistName": "zhang",
    "genre":"MALE"
}

 请求结果

{
  "code": 500,
  "message": "长度必须大于11",
  "requestid": "38cc357c07144d098e7c5730cc8f4c08"
}

五、总结

 以上就是本期的分享,你还可以关注本博客的#Spring Boot入门实践系列!#

本文由博客一文多发平台 OpenWrite 发布!

上一篇 下一篇

猜你喜欢

热点阅读