本篇概述
在正常的项目开发中,我们常常需要对程序的参数进行校验来保证程序的安全性。参数校验非常简单,说白了就是对参数进行正确性验证,例如非空验证、范围验证、类型验证等等。校验的方式也有很多种。如果架构设计的比较好的话,可能我们都不需要做任何验证,或者写比较少的代码就可以满足验证的需求。如果架构设计的有缺陷,或者说压根就没有架构的话,那么我们对参数进行验证时,就需要我们写大量相对重复的代码进行验证了。
手动参数校验
下面我们还是以上一篇的内容为例,我们首先手动对参数进行校验。下面为Controller源码:
package com.jilinwula.springboot.helloworld.controller;
import com.jilinwula.springboot.helloworld.Repository.UserInfoRepository;
import com.jilinwula.springboot.helloworld.entity.UserInfoEntity;
import com.jilinwula.springboot.helloworld.query.UserInfoQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/userinfo")
public class UserInfoController {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> UserInfoRepository userInfoRepository;
<span class="hljs-meta">@GetMapping(<span class="hljs-meta-string">"/query"</span>)</span>
<span class="hljs-keyword">public</span> Object list(UserInfoQuery userInfo) {
<span class="hljs-keyword">if</span> (StringUtils.isEmpty(userInfo.getUsername())) {
<span class="hljs-keyword">return</span> <span class="hljs-string">"账号不能为空"</span>;
}
<span class="hljs-keyword">if</span> (StringUtils.isEmpty(userInfo.getRoleId()) || userInfo.getRoleId() > <span class="hljs-number">100</span> || userInfo.getRoleId() < <span class="hljs-number">1</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-string">"权限不能为空,并且范围为[1-99]"</span>;
}
UserInfoEntity userInfoEntity = userInfoRepository.findByUsernameAndRoleId(userInfo.getUsername(), userInfo.getRoleId());
<span class="hljs-keyword">return</span> userInfoEntity;
}
}
我们只验证了username和roleId参数,分别验证为空验证及范围验证。下面我们测试一下。启动项目后,访问以下地址:
http://127.0.0.1:8080/springb...
我们看一下程序的运行结果。
因为我们没有写任何参数,所以参数验证一定是不能通过的。所以就返回的上图中的提示信息。下面我们看一下数据库中的数据,然后访问一下正确的地址,看看能不能成功的返回数据库中的数据。下图为数据库中的数据:
下面我们访问一下正确的参数,然后看一下返回的结果。访问地址:
http://127.0.0.1:8080/springb...
访问结果:
我们看上图已经成功的返回数据库中的数据了,这就是简单的参数校验,正是因为简单,所以我们就不做过多的介绍了。下面我们简单分析一下,这样做参数验证好不好。如果我们的项目比较简单,那答案一定是肯定的,因为站在软件设计角度考虑,没必要为了一个简单的功能而设计一个复杂的架构。因为越是复杂的功能,出问题的可能性就越大,程序就越不稳定。但如果站在程序开发角度,那上面的代码一定是有问题的,因为上面的代码根本没办法复用,如果要开发很多这样的项目,要进行参数验证时,那结果一定是代码中有很多相类似的代码,这显然是不合理的。那怎么办呢?那答案就是本篇中的重点内容,也就是SpringBoot对参数的验证,实际上本篇的内容主要是和Spring内容相关和SpringBoot的关系不大。但SpringBoot中基本包括了所有Spring的内容,所以我们还是以SpringBoot项目为例。下面我们看一下,怎么在SpringBoot中的对参数进行校验。
ObjectError参数校验
我们首先看一下代码,然后在详细介绍代码中的新知识。下面为接受的参数类的源码。
修改前:
package com.jilinwula.springboot.helloworld.query;
import lombok.Data;
import org.springframework.stereotype.Component;
@Component
@Data
public class UserInfoQuery{
<span class="hljs-keyword">private</span> String username;
<span class="hljs-keyword">private</span> <span class="hljs-built_in">Long</span> roleId;
}
修改后:
package com.jilinwula.springboot.helloworld.query;
import lombok.Data;
import org.springframework.stereotype.Component;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
@Component
@Data
public class UserInfoQuery{
@<span class="hljs-keyword">NotNull</span>(<span class="hljs-keyword">message</span> = <span class="hljs-string">"账号不能为空"</span>)
private String username;
@<span class="hljs-keyword">NotNull</span>(<span class="hljs-keyword">message</span> = <span class="hljs-string">"权限不能为空"</span>)
@Min(value = <span class="hljs-number">1</span>, message = <span class="hljs-string">"权限范围为[1-99]"</span>)
@Max(value = <span class="hljs-number">99</span>, message = <span class="hljs-string">"权限范围为[1-99]"</span>)
private Long roleId;
}
我们看代码中唯一的区别就是添加了很多的注解。没错,在SpringBoot项目中进行参数校验时,就是使用这些注解来完成的。并且注解的命名很直观,基本上通过名字就可以知道什么含义。唯一需要注意的就是这些注解的包是javax中的,而不是其它第三方引入的包。这一点要特别注意,因为很多第三方的包,也包含这些同名的注解。下面我们继续看Controller中的改动(备注:有关javax中的校验注解相关的使用说明,我们后续在做介绍)。Controller源码:
改动前:
package com.jilinwula.springboot.helloworld.controller;
import com.jilinwula.springboot.helloworld.Repository.UserInfoRepository;
import com.jilinwula.springboot.helloworld.entity.UserInfoEntity;
import com.jilinwula.springboot.helloworld.query.UserInfoQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/userinfo")
public class UserInfoController {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> UserInfoRepository userInfoRepository;
<span class="hljs-meta">@GetMapping(<span class="hljs-meta-string">"/query"</span>)</span>
<span class="hljs-keyword">public</span> Object list(UserInfoQuery userInfo) {
<span class="hljs-keyword">if</span> (StringUtils.isEmpty(userInfo.getUsername())) {
<span class="hljs-keyword">return</span> <span class="hljs-string">"账号不能为空"</span>;
}
<span class="hljs-keyword">if</span> (StringUtils.isEmpty(userInfo.getRoleId()) || userInfo.getRoleId() > <span class="hljs-number">100</span> || userInfo.getRoleId() < <span class="hljs-number">1</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-string">"权限不能为空,并且范围为[1-99]"</span>;
}
UserInfoEntity userInfoEntity = userInfoRepository.findByUsernameAndRoleId(userInfo.getUsername(), userInfo.getRoleId());
<span class="hljs-keyword">return</span> userInfoEntity;
}
}
改动后:
package com.jilinwula.springboot.helloworld.controller;
import com.jilinwula.springboot.helloworld.Repository.UserInfoRepository;
import com.jilinwula.springboot.helloworld.entity.UserInfoEntity;
import com.jilinwula.springboot.helloworld.query.UserInfoQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
@RequestMapping("/userinfo")
public class UserInfoController {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> UserInfoRepository userInfoRepository;
<span class="hljs-meta">@GetMapping(<span class="hljs-meta-string">"/query"</span>)</span>
<span class="hljs-keyword">public</span> Object list(<span class="hljs-meta">@Valid</span> UserInfoQuery userInfo, BindingResult result) {
<span class="hljs-keyword">if</span> (result.hasErrors()) {
<span class="hljs-keyword">for</span> (ObjectError error : result.getAllErrors()) {
<span class="hljs-keyword">return</span> error.getDefaultMessage();
}
}
UserInfoEntity userInfoEntity = userInfoRepository.findByUsernameAndRoleId(userInfo.getUsername(), userInfo.getRoleId());
<span class="hljs-keyword">return</span> userInfoEntity;
}
}
我们看代码改动的还是比较大的首先在入参中添加了@Valid注解。该注解就是标识让SpringBoot对请求参数进行验证。也就是和参数类里的注解是对应的。其次我们修改了直接在Controller中进行参数判断的逻辑,将以前的代码修改成了SpringBoot中指定的校验方式。下面我们启动项目,来验证一下上述代码是否能成功的验证参数的正确性。我们访问下面请求地址:
http://127.0.0.1:8080/springb...
返回结果:
我们看上图成功的验证了为空的校验,下面我们试一下范围的验证。我们访问下面的请求地址:
http://127.0.0.1:8080/springb...
看一下返回结果:
我们看成功的检测到了参数范围不正确。这就是SpringBoot中的参数验证功能。但上面的代码一个问题,就是只是会返回错误的提示信息,而没有提示,是哪个参数不正确。下面我们修改一下代码,来看一下怎么返回是哪个参数不正确。
FieldError参数校验
package com.jilinwula.springboot.helloworld.controller;
import com.jilinwula.springboot.helloworld.Repository.UserInfoRepository;
import com.jilinwula.springboot.helloworld.entity.UserInfoEntity;
import com.jilinwula.springboot.helloworld.query.UserInfoQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
@RequestMapping("/userinfo")
public class UserInfoController {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> UserInfoRepository userInfoRepository;
<span class="hljs-meta">@GetMapping(<span class="hljs-meta-string">"/query"</span>)</span>
<span class="hljs-keyword">public</span> Object list(<span class="hljs-meta">@Valid</span> UserInfoQuery userInfo, BindingResult result) {
<span class="hljs-keyword">if</span> (result.hasErrors()) {
FieldError error = result.getFieldError();
<span class="hljs-keyword">return</span> error.getField() + <span class="hljs-string">"+"</span> + error.getDefaultMessage();
}
UserInfoEntity userInfoEntity = userInfoRepository.findByUsernameAndRoleId(userInfo.getUsername(), userInfo.getRoleId());
<span class="hljs-keyword">return</span> userInfoEntity;
}
}
我们将获取ObjectError的类型修改成了FieldError。因为FieldError类型可以获取到验证错误的字段名字,所以我们将ObjectError修改为FieldError。下面我们看一下请求返回的结果。
我们看这回我们就获取到了验证错误的字段名子了。在实际的项目开发中,我们在返回接口数据时,大部分都会采用json格式的方式返回,下面我们简单封装一个返回的类,使上面的验证返回json格式。下面为封装的返回类的源码:
package com.jilinwula.springboot.helloworld.utils;
import lombok.Data;
@Data
public class Return {
private int code;
private Object data;
private String msg;
<span class="hljs-keyword">public</span> static <span class="hljs-keyword">Return</span> error(Object <span class="hljs-keyword">data</span>, String msg) {
<span class="hljs-keyword">Return</span> r = new <span class="hljs-keyword">Return</span>();
r.setCode(-<span class="hljs-number">1</span>);
r.setData(<span class="hljs-keyword">data</span>);
r.setMsg(msg);
<span class="hljs-keyword">return</span> r;
}
}
Controller修改:
package com.jilinwula.springboot.helloworld.controller;
import com.jilinwula.springboot.helloworld.Repository.UserInfoRepository;
import com.jilinwula.springboot.helloworld.entity.UserInfoEntity;
import com.jilinwula.springboot.helloworld.query.UserInfoQuery;
import com.jilinwula.springboot.helloworld.utils.Return;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
@RequestMapping("/userinfo")
public class UserInfoController {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> UserInfoRepository userInfoRepository;
<span class="hljs-meta">@GetMapping(<span class="hljs-meta-string">"/query"</span>)</span>
<span class="hljs-keyword">public</span> Object list(<span class="hljs-meta">@Valid</span> UserInfoQuery userInfo, BindingResult result) {
<span class="hljs-keyword">if</span> (result.hasErrors()) {
FieldError error = result.getFieldError();
<span class="hljs-keyword">return</span> Return.error(error.getField(), error.getDefaultMessage());
}
UserInfoEntity userInfoEntity = userInfoRepository.findByUsernameAndRoleId(userInfo.getUsername(), userInfo.getRoleId());
<span class="hljs-keyword">return</span> userInfoEntity;
}
}
我们还是启动项目,并访问下面地址看看返回的结果:
http://127.0.0.1:8080/springb...
返回结果:
创建切面
这样我们就返回一个简单的json类型的数据了。虽然我们的校验参数的逻辑没有在Controller里面写,但我们还是在Controller里面写了很多和业务无关的代码,并且这些代码还是重复的,这显然是不合理的。我们可以将上述相同的代码的封装起来,然后统一的处理。这样就避免了有很多重复的代码了。那这代码封装到哪里呢?我们可以使用Spring中的切面功能。因为SpringBoot中基本包括了所有Spring中的技术,所以,我们可以放心大胆的在SpringBoot项目中使用Spring中的技术。我们知道在使用切面技术时,我们可以对方法进行前置增强、后置增强、环绕增强等。这样我们就可以利用切面的技术,在方法之前,也就是请求Controller之前,做参数的校验工作,这样就不会对我们的业务代码产生侵入了。下面我们看一下切面的源码然后在做详细说明:
package com.jilinwula.springboot.helloworld.aspect;
import com.jilinwula.springboot.helloworld.utils.Return;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
@Slf4j
@Aspect
@Component
public class UserAspect {
<span class="hljs-meta">@Before</span>(<span class="hljs-string">"execution(public * com.jilinwula.springboot.helloworld.controller..*(..))"</span>)
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> doBefore(JoinPoint joinPoint) {
<span class="hljs-keyword">for</span> (Object <span class="hljs-string">arg :</span> joinPoint.getArgs()) {
<span class="hljs-keyword">if</span> (arg <span class="hljs-keyword">instanceof</span> BindingResult) {
BindingResult result = (BindingResult) arg;
<span class="hljs-keyword">if</span> (result.hasErrors()) {
FieldError error = result.getFieldError();
Return.error(error.getField(), error.getDefaultMessage());
}
}
}
}
}
我们看上述的代码中我们添加了一个@Aspect注解,这个就是切面的注解,然后我们在方法中又添加了@Before注解,也就是对目标方法进行前置增强,Spring在请求Controller之前会先请求此方法。所以我们可以将校验参数的代码逻辑写在这个方法中。execution参数为切点函数,也就是目标方法的切入点。切点函数包含一些通配符的语法,下面我们简单介绍一下:
- 匹配任意字符,但它可能匹配上下文中的一个元素
- .. 匹配任意字符,可以匹配上下文中的多个元素
- 表示按类型匹配指定类的所有类,必须跟在类名后面,也就是会匹配继承或者扩展指定类的所有类,包括指定类.
创建异常类
我们通过上述代码知道,Spring中的切面功能是没有返回值的。所以我们在使用切面功能时,是没有办法在切面里面做参数返回的。那我们应该怎么办呢?这时异常就派上用场了。我们知道当程序抛出异常时,如果当前方法没有做try catch处理,那么异常就会一直向上抛出,如果程序也一直没有做处理,那么当前异常就会一直抛出,直到被Java虚拟机捕获。但Java虚拟机也不会对异常进行处理,而是直接抛出异常。这也就是程序不做任何处理抛出异常的根本原因。我们正好可以利用异常的这种特性,返回参数验证的结果。因为在Spring中为我们提供了统一捕获异常的方法,我们可以在这个方法中,将我们的异常信息封装成json格式,这样我们就可以返回统一的jons格式了。所以在上述的切面中我们手动了抛出了一个异常。该异常因为我们没有用任何处理,所以上述异常会被SpringBoot中的统一异常拦截处理。这样当SpringBoot检测到参数不正确时,就会抛出一个异常,然后SpringBoot就会检测到程序抛出的异常,然后返回异常中的信息。下面我们看一下异常类的源码:
异常类:
package com.jilinwula.springboot.helloworld.exception;
import com.jilinwula.springboot.helloworld.utils.Return;
import lombok.Data;
@Data
public class UserInfoException extends RuntimeException {
private Return r;
public <span class="hljs-type">UserInfoException</span>(<span class="hljs-type">Return</span> r) {
<span class="hljs-keyword">this</span>.r = r;
}
}
Return源码:
package com.jilinwula.springboot.helloworld.utils;
import com.jilinwula.springboot.helloworld.exception.UserInfoException;
import lombok.Data;
@Data
public class Return {
private int code;
private Object data;
private String msg;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">error</span><span class="hljs-params">(Object data, String msg)</span> </span>{
Return r = <span class="hljs-keyword">new</span> Return();
r.setCode(-<span class="hljs-number">1</span>);
r.setData(data);
r.setMsg(msg);
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UserInfoException(r);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Return <span class="hljs-title">success</span><span class="hljs-params">()</span> </span>{
Return r = <span class="hljs-keyword">new</span> Return();
r.setCode(<span class="hljs-number">0</span>);
<span class="hljs-keyword">return</span> r;
}
}
SpringBoot统一异常拦截
因为该异常类比较简单,我们就不会过多的介绍了,唯一有一点需要注意的是该异常类继承的是RuntimeException异常类,而不是Exception异常类,原因我们已经在上一篇中介绍了,Spring只会回滚RuntimeException异常类及其子类,而不会回滚Exception异常类的。下面我们看一下Spring中统一拦截异常处理,下面为该类的源码:
package com.jilinwula.springboot.helloworld.handler;
import com.jilinwula.springboot.helloworld.exception.UserInfoException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@Slf4j
@RestControllerAdvice
public class UserInfoHandler {
<span class="hljs-comment">/**
* 校验错误拦截处理
*
* @param e 错误信息集合
* @return 错误信息
*/</span>
@ExceptionHandler(UserInfoException.class)
public <span class="hljs-built_in">Object</span> handle(UserInfoException e) {
<span class="hljs-keyword">return</span> e.getR();
}
}
我们在该类添加了@RestControllerAdvice注解。该注解就是为了定义我们统一获取异常拦截的。然后我们又添加了@ExceptionHandler注解,该注解就是用来拦截异常类的注解,并且可以在当前方法中,直接获取到该异常类的对象信息。这样我们直接返回这个异常类的信息就可以了。因为我们在这个自定义异常类中添加了Return参数,所以,我们只要反悔Return对象的信息即可,而不用返回整个异常的信息。下面我们访问一下下面的请求,看看上述代码是否能检测到参数不正确。请求地址:
http://127.0.0.1:8080/springb...
返回结果:
这样我们完成了参数校验的功能了,并且这种方式有很大的复用性,即使我们在写新的Controller,也不需要手动的校验参数了,只要我们的请求参数是UserInfoQuery类就可以了。还有一点要注意,所以我们不用手动验证参数了,但我们的请求参数中还是要写BindingResult参数,这一点要特别注意。
正则表达式校验注解
下面我们更详细的介绍一下参数验证的注解,我们首先看一下正则校验,我们在实体类中添加一个新属性,然后用正则的的方式,验证该参数的正确性。下面为实体类源码:
package com.jilinwula.springboot.helloworld.query;
import lombok.Data;
import org.springframework.stereotype.Component;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
@Component
@Data
public class UserInfoQuery{
@<span class="hljs-keyword">NotNull</span>(<span class="hljs-keyword">message</span> = <span class="hljs-string">"用户编号不能为空"</span>)
@Pattern(regexp = <span class="hljs-string">"^[1-10]$"</span>,message = <span class="hljs-string">"用户编号范围不正确"</span>)
private String id;
@<span class="hljs-keyword">NotNull</span>(<span class="hljs-keyword">message</span> = <span class="hljs-string">"账号不能为空"</span>)
private String username;
@<span class="hljs-keyword">NotNull</span>(<span class="hljs-keyword">message</span> = <span class="hljs-string">"权限不能为空"</span>)
@Min(value = <span class="hljs-number">1</span>, message = <span class="hljs-string">"权限范围为[1-99]"</span>)
@Max(value = <span class="hljs-number">99</span>, message = <span class="hljs-string">"权限范围为[1-99]"</span>)
private Long roleId;
}
下面我们访问以下地址:
http://127.0.0.1:8080/springb...
http文件请求接口
但这回我们不在浏览器里请求,因为浏览器请求不太方便,并且返回的json格式也没有格式化不方便浏览,除非要装一些浏览器插件才可以。实际上在IDEA中我们可以很方便的请求一下接口地址,并且返回的json内容是自动格式化的。下面我们来看一下怎么在IDEA中发起接口请求。在IDEA中请求一个接口很简单,我们只要创建一个.http类型的文件名字就可以。然后我们可以在该文件中,指定我们接口的请求类型,例如GET或者POST。当我们在文件的开口写GET或者POST时,IDEA会自动有相应的提示。下面我们看一下http文件中的内容。
http.http:
GET http://127.0.0.1:8080/springboot/userinfo/query?roleId=3&username=阿里巴巴&id=-1
这时标识GET参数的地方,就会出现绿色剪头,但我们点击这个绿色箭头,IDEA就会就会启动请求GET参数后面的接口。下面我们看一下上述的返回结果。
GET http://127.0.0.1:8080/springboot/userinfo/query?roleId=3&username=%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4&id=-1
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 18 Feb 2019 03:57:29 GMT
{
"code": -1,
"data": "id",
"msg": "用户编号范围不正确"
}
Response code: 200; Time: 24ms; Content length: 41 bytes
这就是.http文件类型的返回结果,用该文件请求接口,相比用浏览器来说,要方便的多。因为我们在实体类中使用正则指定参数范围为1-10,所以请求接口时反悔了id参数有错误。下面我们输入一个正确的值在看一下返回结果。
http.http:
GET http://127.0.0.1:8080/springboot/userinfo/query?roleId=3&username=阿里巴巴&id=1
返回结果:
GET <http://127.0.0.1:8080/springboot/userinfo/query?roleId=3&username=%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4&id=1>
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 18 Feb 2019 05:46:49 GMT
{
"id": 61,
"username": "阿里巴巴",
"password": "alibaba",
"nickname": "阿里巴巴",
"roleId": 3
}
Response code: 200; Time: 25ms; Content length: 77 bytes
常见校验注解
我们看已经正确的返回数据库中的数据了。在Spring中,提供了很多种注解来方便我们进行参数校验,下面是比较常见的注解:
注解 | 作用 | |
---|---|---|
@Null | 参数必须为null | |
@NotNull | 参数必须不为null | |
@NotBlank | 参数必须不为null,并且长度必须大于0 | |
@NotEmpty | 参数必须不为空 | |
@Min | 参数必须大于等于该值 | |
@Max | 参数必须小于等于该值 | |
@Size | 参数必须在指定的范围内 | |
@Past | 参数必须是一个过期的时间 | |
@Future | 参数必须是一个未来的时间 | |
@Pattern | 参数必须满足正则表达式 | |
参数必须为电子邮箱 |
上述内容就是SpringBoot中的参数校验全部内容,如有不正确的欢迎留言,谢谢。
源码地址
https://github.com/jilinwula/...
原文地址
http://jilinwula.com/article/...原文地址:https://segmentfault.com/a/1190000018190090
Table.NestedJoin合并…Join(Power Query 之 M 语言)
Delphi Post登陆Delphi盒子论坛源码
分享一个函数GetStr
用友生产工艺路线导入工具1.1
笔下文学小说下载【3.01】 发布
U6 3.2盘点单管理1.01
防止SQL SERVER的事件探查器跟踪软件
双系统的安装(原创)
2345导航自动登陆签到【1.01】
- 最新文章
-
四大细节疑问(hadoop问题)
《Ruby入门权威经典》(一)
RubyOnRails的安装和eclipse plugin
Eclipse 3.6 插件资源
Win7美化攻略:替换imageres.dll,图标全变样
建立你的RoR学习环境(Windows)之二
区别Ruby的require,load,和include
msn2011 去广告+最小化托盘
【转】美国amazon亚马逊购物教程 包学包会 550人民币买kindle4
建立你的RoR学习环境(Windows)之一
- 热门文章
-
Eclipse反编译工具Jad及插件JadClipse配置
《Ruby入门权威经典》(二)
【转】【海淘菜鸟变高手】超级详细版的美国亚马逊购物教程
[转] 程序员面试、算法研究、编程艺术、红黑树4大系列集锦与总结
[转]和海淘新手分享经验:我就这样开始了海淘
如何使用Ruby中的“split”方法
Table.CombineColumns合并…Combine…(Power Query 之 M 语言)
替换错误Table.ReplaceErrorValues(Power Query 之 M 语言)
Table.RenameColumns重命名…Rename…(Power Query 之 M 语言)
展开Table.Expand…(Power Query 之 M 语言)