搜索词>>Spring Boot validation 耗时0.0020
  • Spring Boot validation整合hibernate validator实现数据验证

    Spring Boot validation整合hibernate validator实现数据验证,Spring Boot validation使用说明,Spring Boot validation使用教程<h2>引言</h2>     这里主要讲解在Spring  Boot项目中整合hibernate validator框架实现Spring  Boot项目的validation 验证机制。方便后端验证前端或者接口传递过来的数据格式是否正确。 <h2>一.准备环境</h2> <ul> <li>jdk1.8+(Spring Boot项目推荐使用1.8)</li> <li>eclipse(或者你喜欢的IDE)</li> <li>maven 3+</li> </ul> <h2>二.编码实现Spring Boot validation</h2> <h3>2.1创建一个spring boot项目并添web模块和validation模块</h3> 项目结构图如下:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="spring boot项目结果图" src="/assist/images/blog/017be0b2e4e848cb9bc98279929d073a.png" /><br /> 项目的依赖文件: <pre> <code class="language-xml"><?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.xqlee.project.demo</groupId> <artifactId>demo-springboot-hibernate-validator</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-springboot-hibernate-validator</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter- </artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> </code></pre> <h3> </h3> <blockquote> <h3>注意:</h3> <pre> <code class="language-xml"> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency></code></pre> 该模块会自动加载hibernate-validation依赖。不要自己手动配置谨防依赖问题</blockquote> <h3><br /> 2.2编写一个测试的简单对象POJO</h3> <pre> <code class="language-java">package net.xqlee.project.demo.pojo; import javax.validation.constraints.Pattern; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.Range; public class User { @NotBlank(message = "用户名称不能为空。") private String name; @Range(max = 150, min = 1, message = "年龄范围应该在1-150内。") private Integer age; @NotEmpty(message = "密码不能为空") @Length(min = 6, max = 8, message = "密码长度为6-8位。") @Pattern(regexp = "[a-zA-Z]*", message = "密码不合法") private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } </code></pre> 细心的朋友可能已经发现一些属性上的注解。验证框架正是实现了这些注解的具体验证。hibernate在java的JSR-303标准上还添加了一些额外的验证注解实现。这些实现都为我们后端验证数据取得了巨大的方便。 <blockquote> <p>提示:<br /> 验证注解推荐使用</p> <p>javax.validation.constraints包下的注解,不要使用hibernate的<br /> 在2.0中hibernate的很多注解已经弃用,但是</p> <p>javax.validation.constraints包下的注解增多增强<br /> 一种规范性的趋势</p> </blockquote> <h3>2.3编写一个controller用于测试验证机制</h3> <pre> <code class="language-java">package net.xqlee.project.demo.controller; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import net.xqlee.project.demo.pojo.User; @RestController public class ValidatorController { private static final Logger log = LoggerFactory.getLogger(ValidatorController.class); /** * 验证框架使用测试 * * @param user * @param result */ @PostMapping("v/t1.json") public void v1(@Validated User user, BindingResult result) { StringBuilder sBuilder = new StringBuilder(); sBuilder.append("\n"); if (result.hasErrors()) { List<ObjectError> list = result.getAllErrors(); for (ObjectError error : list) { log.info(error.getCode() + "---" + error.getArguments() + "---" + error.getDefaultMessage()); sBuilder.append(error.getDefaultMessage()); sBuilder.append("\n"); } } log.info(sBuilder.toString()); } } </code></pre> <blockquote> <p>提示:<br /> @Validated (org.springframework.validation.annotation)<br /> 或者@Valid(javax.validation)<br /> 验证注解推荐写在方法的参数列表中,例如:<br /> Object   methodName(@Valid Object params){...}<br /> Object   methodName(@Validated Object params){...}<br /> <br />  </p> </blockquote> <h2><br /> 三.演示</h2> <h3>3.1启动spring boot项目</h3> <h3>3.2通过工具postmain进行提交数据验证</h3> <strong>第一组测试:</strong><br /> <br /> 提交全部为空数据:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="spring boot validation测试数据1" src="/assist/images/blog/8d1b26436c0f42b382e4aa7378e4c466.png" /><br /> 观察eclipse的控制台输出:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="Spring Boot validation 控制台输出1" src="/assist/images/blog/6b5e924b8c57446ab125be2043cec0e3.png" /><br /> 可以看到非空验证已经实现。<br /> <br /> <strong>第二组测试:</strong><br /> <br /> 接下来输入一个非空的名称和密码<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="spring boot validation测试数据2" src="/assist/images/blog/d86badcd7bc44cdba5080e8f87406023.png" /><br /> 观察eclipse控制台:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="Spring Boot validation 控制台输出2" src="/assist/images/blog/87f994b3a6eb4bf9a77f3ce652471c11.png" /><br /> 可以看到名称的验证错误信息已经没有说明已经输入正确。但是密码却没有通过正则表达式的验证所以报错不合法,在对象上我们设置的密码只能是大写的字母。所以刚才输入的全数字不合法。<br /> <br /> <strong>第三组测试:</strong><br /> <br /> 接下来输入正常的密码<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="spring boot validation测试数据3" src="/assist/images/blog/40be7f44b6144ade956b3453ae420766.png" />观察控制台:<br /> <br /> <img srcset="" width="" size="" class="img-thumbnail" alt="Spring Boot validation 控制台输出3" src="/assist/images/blog/2be73b7acb544f22845efacbb9c58a6f.png" /><br /> 可以看到已经没有错误信息。验证通过
  • Spring Boot 2.0 hibernate validate List 验证

    Spring Boot 2.0 hibernate validate List 验证Spring Boot 2.0 hibernate validate List 验证
  • spring boot 2.3 hibernate validate框架未引入

    项目升级到springboot之后,参数校验的注解报错,经过与原项目对比,发现spring-boot-starter-web的依赖项已经去除了依赖原版会有如下: <dependency>l; <groupId>l;org.hiberna项目升级到springboot之后,参数校验的注解报错,经过与原项目对比,发现spring-boot-starter-web的依赖项已经去除了依赖原版会有如下: <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.17.Final</version> <scope>compile</scope> </dependency>2.3中已经删除了解决方法手动引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>官网说明链接:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#validation-starter-no-longer-included-in-web-starters
  • Spring Boot 2.0 hibernate validate 版本冲突导致严重失效

    Spring Boot 2.0 hibernate validate 版本冲突导致验证无效,HV000030: No validator could be found for constraint 'javax.validation.constraints.NotEmpty' validating type 'java.lang.String'. Check configuration forHV000030: No validator could be found for constraint 'javax.validation.constraints.NotEmpty' validating type 'java.lang.String'. Check configuration for 'parameter.applyNo'"
  • hibernate validate 手动验证集合/验证树形类结构

    提示:文末提供demo项目下载!!!一、hibernate validate项目创建​ 二、hibernate validate依赖说明$title(pom.xml) <?xml version="1.0" encoding="UTF-8"提示:文末提供demo项目下载!!!一、hibernate validate项目创建​ 二、hibernate validate依赖说明$title(pom.xml) <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo-manual-validate</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo-manual-validate</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate</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.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.4</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 重点配置: <dependency> <groupId>org.hibernate</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.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.4</version> </dependency>三、hibernate validate验证工具编写$title(ValidateUtils.java) package com.example.demomanualvalidate.util; import org.springframework.util.StringUtils; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; import java.util.Iterator; import java.util.Set; public class ValidateUtils { public static String validate(Object obj) { // 用于存储验证后的错误信息 StringBuffer buffer = new StringBuffer(64); Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); if (obj!=null&& obj instanceof Collection){ Collection collection=(Collection)obj; for (Object ob:collection){ String res=validate(ob); if (!StringUtils.isEmpty(res)){ buffer.append(res); buffer.append(","); } } } //对象字段中含有集合的处理 Field[] fields = obj.getClass().getDeclaredFields(); for (Field field:fields){ field.setAccessible(true); Object fv=getFieldValueByName(field.getName(),obj); if (fv!=null&&fv instanceof Collection){ String res=validate(fv); if (!StringUtils.isEmpty(res)){ buffer.append(res); buffer.append(","); } } } // 验证某个对象,其实也可以只验证其中的某一个属性的 Set<ConstraintViolation<Object>> constraintViolations = validator.validate(obj); Iterator<ConstraintViolation<Object>> iter = constraintViolations.iterator(); while (iter.hasNext()) { String message = iter.next().getMessage()+","; buffer.append(message); } if(buffer.length()>0) return buffer.toString().substring(0, buffer.toString().length()-1); return buffer.toString(); } /** * 根据属性名获取属性值 * */ public static Object getFieldValueByName(String fieldName, Object o) { try { String firstLetter = fieldName.substring(0, 1).toUpperCase(); String getter = "get" + firstLetter + fieldName.substring(1); Method method = o.getClass().getMethod(getter, new Class[] {}); Object value = method.invoke(o, new Object[] {}); return value; } catch (NoSuchMethodException e){ // System.out.println("验证字段get方法未找到"); return null; } catch (InvocationTargetException e) { //忽略方法内部错误 return null; } catch (Exception e) { throw new RuntimeException("验证过程获取属性值错误",e); } } } 四、hibernate validate验证数据模型创建$title(DogFood.java) package com.example.demomanualvalidate.model; import javax.validation.constraints.NotEmpty; /** * 狗粮 */ public class DogFood { @NotEmpty(message = "狗粮名称不能为空") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } $title(Dog.java) package com.example.demomanualvalidate.model; import javax.validation.constraints.NotNull; import java.util.List; public class Dog { public Dog(String name) { this.name = name; } @NotNull(message = "宠物名称不能为空") private String name; private List<DogFood> foods; public List<DogFood> getFoods() { return foods; } public void setFoods(List<DogFood> foods) { this.foods = foods; } public String getName() { return name; } public void setName(String name) { this.name = name; } }  $title(Persion.java) package com.example.demomanualvalidate.model; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; public class Persion { public Persion(String name, List<Dog> dogs) { this.name = name; this.dogs = dogs; } @NotEmpty(message = "用户名不能为空") private String name; @NotNull(message = "必须有宠物狗") private List<Dog> dogs;//拥有的宠物狗 public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Dog> getDogs() { return dogs; } public void setDogs(List<Dog> dogs) { this.dogs = dogs; } } 五、hibernate validate验证测试$title(Test.java) package com.example.demomanualvalidate; import com.example.demomanualvalidate.model.Dog; import com.example.demomanualvalidate.model.DogFood; import com.example.demomanualvalidate.model.Persion; import com.example.demomanualvalidate.util.ValidateUtils; import java.util.Arrays; public class Test { public static void main(String[] args) { //-----0 Persion p0=new Persion("", null); String failValue=ValidateUtils.validate(p0); System.out.println("错误信息0:"+failValue); Dog d1=new Dog(null); Persion p1=new Persion("", Arrays.asList(new Dog[]{d1})); failValue=ValidateUtils.validate(p1); System.out.println("错误信息1:"+failValue); //-----2 DogFood df=new DogFood(); d1.setFoods(Arrays.asList(new DogFood[]{df})); Persion p2=new Persion("", Arrays.asList(new Dog[]{d1})); failValue=ValidateUtils.validate(p2); System.out.println("错误信息2:"+failValue); //---GOOD Dog d=new Dog("阿三"); Persion p=new Persion("小左",Arrays.asList(new Dog[]{d})); failValue=ValidateUtils.validate(p); System.out.println("错误信息:"+failValue); } } 执行结果截图:​从输出结果来看,已经实现了hibernate validate树形验证,有任何问题欢迎下方评论区留言讨论。 项目下载地址 :demo-manual-validate.zip
  • Spring Boot 2.0 REST API 接口的数据验证

    1.概要在本Spring boot教程中,我们将学习如何验证发送到PUT/POST API请求的数据BODY1.概要在本Spring boot教程中,我们将学习如何验证发送到PUT/POST API请求的数据BODY。我们还将学习在API响应中添加自定义错误消息以提示错误。在这个演示中,我们将主要看到两个主要的验证案例 -HTTP POST /employees和请求正文不包含有效值或缺少一些字段。它将在响应主体中返回带有适当消息的HTTP状态代码400。/employees/{id}请求中会发送HTTP GET 和INVALID ID。它会在响应主体中返回HTTP状态码404和正确的消息。2.创建REST 模型和API类 EmployeeVO.java@XmlRootElement(name = "employee") @XmlAccessorType(XmlAccessType.FIELD) public class EmployeeVO extends ResourceSupport implements Serializable { private Integer employeeId; private String firstName; private String lastName; private String email; public EmployeeVO(Integer id, String firstName, String lastName, String email) { super(); this.employeeId = id; this.firstName = firstName; this.lastName = lastName; this.email = email; } public EmployeeVO() { } //Removed setter/getter for readability } EmployeeRESTController.java@PostMapping(value = "/employees") public ResponseEntity<EmployeeVO> addEmployee (@RequestBody EmployeeVO employee) { EmployeeDB.addEmployee(employee); return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK); } @GetMapping(value = "/employees/{id}") public ResponseEntity<EmployeeVO> getEmployeeById (@PathVariable("id") int id) { EmployeeVO employee = EmployeeDB.getEmployeeById(id); if(employee == null) { throw new RecordNotFoundException("Invalid employee id : " + id); } return new ResponseEntity<EmployeeVO>(employee, HttpStatus.OK); }3.应用请求验证和异常处理 默认请求支持spring的验证要应用默认验证,您只需在适当的位置添加相关注解。即使用所需的验证特定注释来注释模型类@XmlRootElement(name = "employee") @XmlAccessorType(XmlAccessType.FIELD) public class EmployeeVO extends ResourceSupport implements Serializable { private static final long serialVersionUID = 1L; public EmployeeVO(Integer id, String firstName, String lastName, String email) { super(); this.employeeId = id; this.firstName = firstName; this.lastName = lastName; this.email = email; } public EmployeeVO() { } private Integer employeeId; @NotEmpty(message = "first name must not be empty") private String firstName; @NotEmpty(message = "last name must not be empty") private String lastName; @NotEmpty(message = "email must not be empty") @Email(message = "email should be a valid email") private String email; //Removed setter/getter for readability }通过@Valid注释启用对请求主体的验证自定义验证以添加有意义的信息默认的弹簧验证工作,并提供有关错误的信息超载,这就是为什么你应该根据你的应用程序的需要定制它。您只能提供所需的错误信息,并且语句非常清晰。额外的信息也不建议。建立有意义的例外并且足够好地描述问题始终是一个很好的建议。一种方法是创建单独的类来表示特定的业务用例失败,并在该用例失败时返回它们。 例如,我已经RecordNotFoundException为所有buch场景创建了一个类,在这个场景中,资源被其ID所请求,并且系统中找不到资源。 import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(HttpStatus.NOT_FOUND) public class RecordNotFoundException extends RuntimeException { public RecordNotFoundException(String exception) { super(exception); } } 同样,我写了一个特殊的类,它将被返回所有失败案例。为所有API提供一致的错误消息结构,帮助API消费者编写更健壮的代码import java.util.List; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "error") public class ErrorResponse { public ErrorResponse(String message, List<String> details) { super(); this.message = message; this.details = details; } //General error message about nature of error private String message; //Specific errors in API request processing private List<String> details; //Getter and setters } 现在添加一个类,ResponseEntityExceptionHandler并使用注释对其进行@ControllerAdvice注解。ResponseEntityExceptionHandler是一个方便的基类,@RequestMapping通过@ExceptionHandler方法提供跨所有方法的集中式异常处理。@ControllerAdvice更适用于在应用程序启动时启用自动扫描和配置。CustomExceptionHandler.javaimport java.util.ArrayList; import java.util.List; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; @SuppressWarnings({"unchecked","rawtypes"}) @ControllerAdvice public class CustomExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(Exception.class) public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) { List<String> details = new ArrayList<>(); details.add(ex.getLocalizedMessage()); ErrorResponse error = new ErrorResponse("Server Error", details); return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR); } @ExceptionHandler(RecordNotFoundException.class) public final ResponseEntity<Object> handleUserNotFoundException(RecordNotFoundException ex, WebRequest request) { List<String> details = new ArrayList<>(); details.add(ex.getLocalizedMessage()); ErrorResponse error = new ErrorResponse("Record Not Found", details); return new ResponseEntity(error, HttpStatus.NOT_FOUND); } @Override protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { List<String> details = new ArrayList<>(); for(ObjectError error : ex.getBindingResult().getAllErrors()) { details.add(error.getDefaultMessage()); } ErrorResponse error = new ErrorResponse("Validation Failed", details); return new ResponseEntity(error, HttpStatus.BAD_REQUEST); } } 以上类处理各种异常情况,包括RecordNotFoundException:它还处理@RequestBody注释对象中的请求验证错误。让我们看看它是如何工作的。请求验证演示1)HTTP GET / employees / 1 [有效]HTTP Status : 200 { "employeeId": 1, "firstName": "firstName", "lastName": "lastName", "email": "email@gamil.com", } ​2)HTTP GET / employees / 23 [INVALID]HTTP Status : 404 { "message": "Record Not Found", "details": [ "Invalid employee id : 23" ] } ​3)HTTP POST / employees [INVALID]请求参数: { "lastName": "Bill", "email": "ibill@gmail.com" }响应结果: HTTP Status : 400 { "message": "Validation Failed", "details": [ "first name must not be empty" ] } ​4)HTTP POST / employees [INVALID]请求参数: { "email": "ibill@gmail.com" }响应结果: HTTP Status : 400 { "message": "Validation Failed", "details": [ "last name must not be empty", "first name must not be empty" ] } ​5)HTTP POST / employees [INVALID]请求参数: { "firstName":"Lokesh", "email": "ibill_gmail.com" //invalid email in request }响应内容: HTTP Status : 400 { "message": "Validation Failed", "details": [ "last name must not be empty", "email should be a valid email" ] }​可用的注解在上面的例子中,我们只使用了几个注释,如@NotEmpty和@Email。还有更多这样的注释来验证请求数据。需要时检查出来。注解使用说明@AssertFalse注释的元素必须是false。@AssertTrue注释的元素必须为true。@DecimalMax带注释的元素必须是其值必须小于或等于指定最大值的数字。@DecimalMin带注释的元素必须是其值必须高于或等于指定最小值的数字。@Future注释元素必须是未来的即时,日期或时间。@Max带注释的元素必须是其值必须小于或等于指定最大值的数字。@Min带注释的元素必须是其值必须高于或等于指定最小值的数字。@Negative带注释的元素必须是严格负数。@NotBlank带注释的元素不得null并且必须至少包含一个非空白字符。@NotEmpty带注释的元素不能null也不是空的。@NotNull注释的元素不能是null。@Null注释的元素必须是null。@Pattern注释的CharSequence必须与指定的正则表达式匹配。@Positive带注释的元素必须是严格的正数。@Size注释的元素大小必须在指定的边界之间(包含)。  总结 spring boot REST验证教程中,我们学到了 -通过ID获取资源时验证ID。验证POST / PUT API中的请求主体字段。在API响应中发送一致且结构化的错误响应。提示:项目源码下载demo-springboot2-rest-valid.zip
  • Spring Boot 2.0 绑定属性资源文件 Spring Boot 2.0 读取配置文件值 Spring Boot 2.0获取配置文件值

    Spring Boot 2.0 绑定properties属性资源文件 Spring Boot 2.0 读取properties配置文件值 Spring Boot 2.0获取properties配置文件值Spring Boot 2.0 绑定properties属性资源文件 Spring Boot 2.0 读取配置文件值 Spring Boot 2.0获取配置文件值<br /> 自Spring Boot首次发布以来,就可以使用<code>@ConfigurationProperties</code>注释将属性绑定到类。也可以用不同的形式指定属性名称。 例如,person.first-name,person.firstName和PERSON_FIRSTNAME可以互换使用。 我们称这个功能为“宽松绑定”。<br /> <br /> 不幸的是,在Spring Boot 1.x中,“宽松绑定”实际上有点过于宽松。 确切地定义绑定规则是什么以及什么时候可以使用特定格式是相当困难的。 我们也开始获得有关我们的1.x实施难以解决的问题的报告。 例如,在Spring Boot 1.x中,不可能将项目绑定到java.util.Set。<br /> 所以,在Spring Boot 2.0中,我们已经着手重新设计绑定发生的方式。 我们添加了几个新的抽象,并且我们开发了一个全新的绑定API。 在这篇博文中,我们介绍了一些新的类和接口,并描述了为什么添加了它们,它们做了什么,以及如何在自己的代码中使用它们。 <h2>Property Sources</h2> 如果你一直在使用Spring,你可能很熟悉<code>Environment</code>抽象类。这个接口是一个<code>PropertyResolver</code>,它可以让你从一些底层的<code>PropertySource</code>实现中解析属性。<br /> Spring框架为常见的东西提供<code>PropertySource</code>实现,例如系统属性,命令行标志和属性文件。 Spring Boot 会以对大多数应用程序有意义的方式自动配置这些实现(例如,加载application.properties)。 <h2>Configuration Property Sources</h2> Spring Boot 2.0不是直接使用现有的<code>PropertySource</code>接口进行绑定,而是引入了一个新的<code>ConfigurationPropertySource</code>接口。 我们引入了一个新的接口,为我们提供了一个合理的地方来实施放松绑定规则,这些规则以前是活页夹的一部分<br /> 接口的主要API非常简单: code:>>ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name);<br /> 还有一个<code>IterableConfigurationPropertySource</code>变相的实现了<code>Iterable </code>接口,以便您可以发现源包含的所有名称。<br /> <br /> 通过使用以下代码,可以将Spring <code>Environment</code>调整为<code>ConfigurationPropertySources</code><br /> Iterable sources = ConfigurationPropertySources.get(environment);<br /> 如果您需要它,我们还提供一个简单的<code>MapConfigurationPropertySource</code>实现。 <h2>Configuration Property Names</h2> 事实证明,如果将其限制为一个方向,放宽属性名称的实现更容易实现。 您应该始终使用规范形式访问代码中的属性,而不管它们在基础源中的表示方式如何。<br /> ConfigurationPropertyName类强制执行这些规范的命名规则,这些规则基本归结为“使用小写的kebab-case名称”。<br /> 因此,例如,即使在基础源中使用person.firstName或PERSON_FIRSTNAME,也应该将代码中的属性称为person.first-name。<br /> Origin Support起源支持<br /> 一个Origin是Spring Boot 2.0中引入的一个新接口,可以让您精确定位从某个值加载的确切位置。 有许多Origin实现,可能最有用的是TextResourceOrigin。 这提供了加载的资源的详细信息,以及值的行号和列号。 <pre> <code class="language-html">*************************** APPLICATION FAILED TO START *************************** Description: Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'person' to scratch.PersonProperties failed: Property: person.name Value: Joe Origin: class path resource [application.properties]:1:13 Reason: length must be between 4 and 2147483647 Action: Update your application's configuration </code></pre>   <h2>Binder API</h2> Binder类(在org.springframework.boot.context.properties.bind中)可以让你获取一个或多个ConfigurationPropertySource并从它们中绑定一些东西。 更准确地说,一个Binder采用一个Bindable并返回一个BindResult。<br /> Bindable<br /> Bindable可能是现有的Java bean,类类型或复杂的ResolvableType(如List )。 这里有些例子 <pre> <code class="language-java">Bindable.ofInstance(existingBean); Bindable.of(Integer.class); Bindable.listOf(Person.class); Bindable.of(resovableType);</code></pre> <br /> Bindable也用于携带注释信息,但通常不需要关心这一点。 <h2>BindResult</h2> <br /> 绑定器不是直接返回一个绑定对象,而是返回一个名为BindResult的东西。 类似于Java 8 Streams返回Optional的方式,BinderResult表示可能绑定或可能未绑定的内容。<br /> <br /> 如果您尝试获取未绑定对象的实际结果,则会引发异常。 我们还提供了一些方法,可以让您在没有任何约束或映射到不同类型时提供替代值 <pre> <code class="language-java">var bound = binder.bind("person.date-of-birth",Bindable.of(LocalDate.class)); // Return LocalDate or throws if not bound bound.get(); // Return a formatted date or "No DOB" bound.map(dateFormatter::format).orElse("No DOB"); // Return LocalDate or throws a custom exception bound.orElseThrow(NoDateOfBirthException::new);</code></pre> <h2>Formatting and Conversion </h2> 大多数ConfigurationPropertySource实现将其基础值作为字符串公开。 当Binder需要将源值转换为其他类型时,它将委托给Spring的ConversionService API。<br /> 如果您需要调整值的转换方式,则可以自由使用格式化程序注释(如@NumberFormat或@DateFormat)。<br /> <br /> Spring Boot 2.0还引入了一些对绑定特别有用的新注释和转换器。 例如,您现在可以将诸如4s之类的值转换为持续时间。 有关详细信息,请参阅org.springframework.boot.convert包。 <h2>BindHandler</h2> 有时候,绑定时可能需要实现额外的逻辑,而BindHandler接口提供了一个很好的方法来实现这一点。 每个BindHandler都可以实现onStart,onSuccess,onFailure和onFinish方法来覆盖行为。<br /> <br /> Spring Boot提供了一些处理程序,主要用于支持现有的@ConfigurationProperties绑定。 例如,ValidationBindHandler可用于对绑定对象应用Validator验证。 <h2>@ConfigurationProperties</h2> 正如本文开始时提到的,@ConfigurationProperties从一开始就一直是Spring Boot的特色。 @ConfigurationProperties很可能仍然是大多数人执行绑定的方式。<br /> <br /> 尽管我们重写了整个绑定过程,但大多数人在升级Spring Boot 1.5应用程序时似乎并没有太多问题。 只要您遵循迁移指南中的建议,您应该会发现事情继续良好。<br /> 如果您在升级应用程序时发现问题,请在GitHub问题跟踪器上以小样本向他们报告,以便重现问题。 <h2>Future Work</h2> 我们计划在Spring Boot 2.1中继续开发Binder,我们希望支持的第一个特性是不可变的配置属性。 如果当前需要getter和setter的配置属性可以使用基于构造函数的绑定,那将是非常好的: <pre> <code class="language-java">public class Person { private final String firstName; private final String lastName; private final LocalDateTime dateOfBirth; public Person(String firstName, String lastName, LocalDateTime dateOfBirth) { this.firstName = firstName; this.lastName = lastName; this.dateOfBirth = dateOfBirth; } // getters }</code></pre> 我们认为构造函数绑定也可以很好地处理Kotlin数据类。<br /> <br /> 小结<br /> 我们希望您能够在Spring Boot 2.0中发现新的绑定功能,并且您会考虑升级现有的Spring Boot应用程序。
  • Spring Boot/MVC 日期date参数的获取和Ajax返回日期格式处理

           ​Spring Boot       这里主要对Spring Boot 项目和Spring MVC 相关项目中,日期参数的使用以及Ajax请求日期数据返回格式的处理       ​Spring Boot       这里主要对Spring Boot 项目和Spring MVC 相关项目中,日期参数的使用以及Ajax请求日期数据返回格式的处理。对于Spring Boot日期参数的处理,可以参考上一篇文章Spring boot/spring mvc接受date类型数据处理        本文主要针对Ajax请求返回数据中的的data(日期)字段格式化讲解。对于Spring Boot项目如果要返回date类型字段格式化成指定的日期该如何操作呢? import com.fasterxml.jackson.annotation.JsonFormat; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; import java.io.Serializable; import java.util.Date; public class Message implements Serializable { private Integer id; @NotEmpty(message = "请您填写名称") @Pattern(regexp = "^([\\u4e00-\\u9fa5]{1,20}|[a-zA-Z\\.\\s]{1,20})$",message = "请填写正确的中文名称,20字以内") private String name; // @NotEmpty(message = "请您填写电话") @Pattern(regexp = "1[3456789]\\d{9}",message = "请填写正确的手机号码") private String tel; @Pattern(regexp ="^[\\s\\S]{0,200}$",message = "留言内容应该在0-200字以内") private String content; @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date createTime; private Integer status; private static final long serialVersionUID = 1L; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name == null ? null : name.trim(); } public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel == null ? null : tel.trim(); } public String getContent() { return content; } public void setContent(String content) { this.content = content == null ? null : content.trim(); } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } }​​​​​​​如上代码,请关注createTime字段。在createTime字段我们添加了@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")注解,从而指定了Ajax返回数据的日期格式为 yyyy-MM-dd HH:mm:ss,指定了时区,防止各种其他原因导致时间不对。
  • hibernate validator 正则表达式报错javax.validation.constraints.Pattern

    hibernate validator 正则表达式报错HV000030: No validator could be found for constraint 'javax.validation.constraints.Pattern' validating type 'java.lang.Integer'.HV000030: No validator could be found for constraint 'javax.validation.constraints.Pattern' validating type 'java.lang.Integer'.
  • spring boot mybatis 整合_spring boot mybatis3 事物配置

    引言    通过之前spring boot mybatis 整合的讲解: spring boot mybaties整合  (spring boot mybaties 整合 基于Java注解方式写sql,无需任何得mapper xml文件)s引言    通过之前spring boot mybatis 整合的讲解: spring boot mybaties整合  (spring boot mybaties 整合 基于Java注解方式写sql,无需任何得mapper xml文件)spring boot mybatis 整合_spring boot与mybaties的使用  (spring boot mybaties 整合 xml mapper方式,也是实际应用最多得方式) 我们对于spring boot mybaties 整合有了一个基础的认知。这里主要正对上面得两篇文章中spring boot mybaties整合讲解得一个扩展学习,事物的配置,整合到spring 的事物控制中。一.环境准备 本博客讲沿用上面的项目进行进一步讲解二.实战编码2.1 spring boot 核心配置文件application.properties#==================DataSource Config Start================== #默认采用Tomcat-jdbc-pool性能和并发最好,注意查看maven依赖中是否有tomcat-jdbc #name #spring.datasource.name=test #url #spring.datasource.url=jdbc:sqlserver://192.168.xxx.xxx;instanceName=sql_03;DatabaseName=edu;integratedSecurity=false spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8 #DriverClass #spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver spring.datasource.tomcat.driver-class-name=com.mysql.jdbc.Driver #DB username spring.datasource.tomcat.username=root #DB password spring.datasource.tomcat.password=root #最大连接数量 spring.datasource.tomcat.max-active=150 #最大闲置连接数量 spring.datasource.tomcat.max-idle=20 #最大等待时间 #spring.datasource.tomcat.max-wait=5000 #==================DataSource Config End================== #==================mybaties Config Start================== #ORM Bean Package mybatis.type-aliases-package=com.example.pojo mybatis.mapper-locations=classpath:/mapper/*.xml #打印mybatiesSql语句 logging.level.com.example.mapper=DEBUG #==================mybaties Config End ================== #模板引擎配置缓存为FALSE。开发调试用 spring.thymeleaf.cache=false 这里注意关注数据连接配置和mybaties的xml mapper文件配置。2.2spring boot mybaties 整合 事物关键配置 MyBatiesConfig.javapackage com.example.config; import javax.sql.DataSource; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * mybaties配置扫描mapper路径 * * @author leftso * */ @Configuration @MapperScan(basePackages = { "com.example.mapper" }) /** 注意,这个注解是扫描mapper接口不是xml文件,使用xml模式必须在配置文件中添加xml的配置 **/ @EnableTransactionManagement /** * 启用事物管理 ,在需要事物管理的service类或者方法上使用注解@Transactional **/ public class MyBatiesConfig { @Autowired private DataSource dataSource; /** * 配合注解完成事物管理 * * @return */ @Bean public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } } 注意必须把当前的数据源配置进入spring的注解事物管理器。否则通过spring框架的注解标签@Transactional是不会有事物作用的。提示:spring boot 2.1.4.RELEASE 版本无需配置PlatformTransactionManager 也能起作用,也就说仅需要一个注解@EnableTransactionManagementSpring boot 2.x (Spring 5.0为基础的情况)无需使用@EnableTransactionManagement注解,spring boot 项目内部已经启用三.事物演示3.1编写测试代码package com.example.test; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import com.example.mapper.UserMapper; import com.example.pojo.User; @RunWith(SpringRunner.class) @SpringBootTest public class TransactionalTest { @Autowired private UserMapper userMapper; @Test public void name() { User user=new User("leftso", "男", 1); userMapper.insert(user); int t=1/0; System.out.println(t); } } 执行前查询数据库:​执行测试代码并观察eclipse的控制台和数据库的数据查询结果:​​很明显在报错的情况下,数据还是插入进了数据库。这并不是我们正常业务想要的结果。3.2编辑测试代码,添加spring框架的事物注解package com.example.test; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import com.example.mapper.UserMapper; import com.example.pojo.User; @RunWith(SpringRunner.class) @SpringBootTest public class TransactionalTest { @Autowired private UserMapper userMapper; @Test @Transactional public void name() { User user=new User("测试哈哈", "女", 2); userMapper.insert(user); int t=1/0; System.out.println(t); } } 执行代码并观察eclipse和数据库:​​这次的操作姿势似乎对了。在报错的情况下数据并没有插入数据库。我们仔细观察spring 控制台输出的日志可以发现事物已经在spring的控制下回滚了。​从上图也可以看到回滚的日志