2020-01-16 19:03:05 星期四
开发环境版本 jdk1.8
maven3.5.0
spring boot 2.0.2.RELEASE
在java后端项目开发过程中,其实有很多大一部分项目,后端都没有做接口参数校验,或者做了参数校验,但是实现方式都是简单的使用if判断;主要原因在于:API的参数校验目前流行的方案较少、现有方案不适用与自己的项目、项目部署在内网要求不高、或者干脆参数校验这种事情丢给前端来实现
hibernate-validator是Hibernate项目中的一个数据校验框架,是Bean Validation 的参考实现,也算是当前比较流行的框架了;在实体类上添加注解;但对于不同的方法,所应用的校验规则也是不一样的,这样子可能就会需要创建多个实体类或者组,甚至于一些接口根本就没实体类参数;所以hibernate-validator实际应用过程中还是有一定的困难;
基于此,我花费了一点业余时间,借鉴了hibernate-validator的思路,实现了一套基于 注解 + AOP
的方式实现接口参数校验框架
在方法体上使用@CheckParam
或者@CheckParams
注解标注需要校验的参数; 举个栗子:
@RestController
@RequestMapping("/paramCheck")
public class ParamCheckController {
@CheckParam(value = Check.NotEmpty, argName = "userName", msg = "你大爷的,这个是必填参数!")
@PostMapping("/singleCheckNotEmpty")
public Object singleCheckNotNull(String userName) {
return 1;
}
@CheckParam(value = Check.DateTime, argName = "dateTime", msg = "msg可以不写,有默认提示")
@PostMapping("/singleCheckDateTime")
public Object singleCheckDateTime(String dateTime) {
return 1;
}
@CheckParams({
@CheckParam(value = Check.NotNull, argName = "userId", msg = "你大爷的,这个是必填参数!"),
@CheckParam(value = Check.NotEmpty, argName = "userName"),
@CheckParam(value = Check.NotEmpty, argName = "dept.deptName", msg = "实体属性判断"),
@CheckParam(value = Check.Past, argName = "dept.createTime"),
@CheckParam(value = Check.lt, argName = "dept.employees", express = "2") // 对集合的size判断
})
@PostMapping("/entityMultiCheck")
public Object entityMultiCheck(Integer userId, String userName, @RequestBody DeptEntity dept) {
return 1;
}
}
在方法体上使用@CheckParam
或者@CheckParams
注解标注需要校验的参数;
然后使用AOP切入,获取配置的参数校验规则,同时获取对应的入参值
调用CheckUtil工具类,进行判断
Check参数校验枚举类;目前实现了下列校验方法,后续会继续补充
public enum Check {
Null("参数必须为 null", CheckUtil::isNull),
NotNull("参数必须不为 null", CheckUtil::isNotNull),
Empty("参数的必须为空", CheckUtil::isEmpty),
NotEmpty("参数必须非空", CheckUtil::isNotEmpty),
True("参数必须为 true", CheckUtil::isTrue),
False("参数必须为 false", CheckUtil::isFalse),
Date("参数必须是一个日期 yyyy-MM-dd", CheckUtil::isDate),
DateTime("参数必须是一个日期时间 yyyy-MM-dd HH:mm:ss", CheckUtil::isDateTime),
Past("参数必须是一个过去的日期 ", CheckUtil::isPast),
Future("参数必须是一个将来的日期 ", CheckUtil::isFuture),
Today("参数必须今天的日期 ", CheckUtil::isToday),
Enum("参数必须在枚举中 ", CheckUtil::inEnum),
Email("参数必须是Email地址", CheckUtil::isEmail),
Range("参数必须在合适的范围内", CheckUtil::inRange),
NotIn("参数必须不在指定的范围内 ", CheckUtil::outRange),
Length("参数长度必须在指定范围内", CheckUtil::inLength),
gt("参数必须大于指定值", CheckUtil::isGreaterThan),
lt("参数必须小于指定值", CheckUtil::isLessThan),
ge("参数必须大于等于指定值", CheckUtil::isGreaterThanEqual),
le("参数必须小于等于指定值", CheckUtil::isLessThanEqual),
ne("参数必须不等于指定值", CheckUtil::isNotEqual),
Equal("参数必须不等于指定值", CheckUtil::isEqual),
Pattern("参数必须符合指定的正则表达式", CheckUtil::isPattern) ;
public String msg;
public BiFunction<Object, String, Boolean> fun;
Check(String msg, BiFunction<Object, String, Boolean> fun) {
this.msg = msg;
this.fun = fun;
}
}
想深入了解的,可以下载源码细看。
修改Application,添加 @SpringBootApplication(scanBasePackages = {"com.yuxue"})
因为项目中使用了很多注解,需要被扫描到才能生效。
maven项目添加pom依赖,或者添加jar依赖包即可
<dependency>
<groupId>com.yuxue</groupId>
<artifactId>yx-validator</artifactId>
<version>1.0.0</version>
</dependency>
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.yuxue.entity.DeptEntity;
import com.yuxue.entity.EmployeeEntity;
import com.yuxue.validator.annotation.CheckParam;
import com.yuxue.validator.annotation.CheckParams;
import com.yuxue.validator.enumtype.Check;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@Api(tags = {"check"}, description = "参数校验")
@RestController
@RequestMapping("/paramCheck")
public class ParamCheckController {
@ApiImplicitParam(name = "userId", value = "", dataType = "Integer", paramType="query")
@CheckParam(value = Check.NotNull, argName = "userId")
@PostMapping("/singleCheckNotNull")
public Object singleCheckNotNull(Integer userId) {
System.err.println(userId);
return 1;
}
@ApiImplicitParam(name = "userName", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.NotEmpty, argName = "userName", msg = "你大爷的,这个是必填参数!")
@PostMapping("/singleCheckNotEmpty")
public Object singleCheckNotNull(String userName) {
System.err.println(userName);
return 1;
}
@ApiImplicitParam(name = "bl", value = "", dataType = "Boolean", paramType="query")
@CheckParam(value = Check.True, argName = "bl")
@PostMapping("/singleCheckTrue")
public Object singleCheckTrue(Boolean bl) {
System.err.println(bl);
return 1;
}
@ApiImplicitParam(name = "date", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.Date, argName = "date")
@PostMapping("/singleCheckDate")
public Object singleCheckDate(String date) {
System.err.println(date);
return 1;
}
@ApiImplicitParam(name = "dateTime", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.DateTime, argName = "dateTime")
@PostMapping("/singleCheckDateTime")
public Object singleCheckDateTime(String dateTime) {
System.err.println(dateTime);
return 1;
}
@ApiImplicitParam(name = "date", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.Past, argName = "date")
@PostMapping("/singleCheckPast")
public Object singleCheckPast(String date) {
System.err.println(date);
return 1;
}
@ApiImplicitParam(name = "dateTime", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.Future, argName = "dateTime", msg = "参数必须是一个将来的日期或者时间,并且满足 yyyy-MM-dd HH:mm:ss格式")
@PostMapping("/singleCheckFuture")
public Object singleCheckFuture(String dateTime) {
System.err.println(dateTime);
return 1;
}
@ApiImplicitParam(name = "date", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.Today, argName = "date")
@PostMapping("/singleCheckToday")
public Object singleCheckToday(String date) {
System.err.println(date);
return 1;
}
@ApiImplicitParam(name = "gender", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.Enum, argName = "gender", express="男,女,太监")
@PostMapping("/singleCheckStringEnum")
public Object singleCheckStringEnum(String gender) {
System.err.println(gender);
return 1;
}
@ApiImplicitParam(name = "gender", value = "", dataType = "Integer", paramType="query")
@CheckParam(value = Check.Enum, argName = "gender", express="0,1")
@PostMapping("/singleCheckIntegerEnum")
public Object singleCheckIntegerEnum(Integer gender) {
System.err.println(gender);
return 1;
}
@ApiImplicitParam(name = "password", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.Length, argName = "password", express="6,18", msg="密码length必须在6-18位之间!")
@PostMapping("/singleCheckStringLength")
public Object singleCheckStringLength(String password) {
System.err.println(password);
return 1;
}
@ApiImplicitParam(name = "password", value = "", dataType = "String", paramType="query")
@CheckParams({
@CheckParam(value = Check.ge, argName = "password", express = "6"),
@CheckParam(value = Check.le, argName = "password", express = "18")
})
@PostMapping("/singleCheckStringLength1")
public Object singleCheckStringLength1(String password) {
System.err.println(password);
return 1;
}
@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
@CheckParam(value = Check.Range, argName = "age", express="18,50")
@PostMapping("/singleCheckIntegerRange")
public Object singleCheckIntegerRange(Integer age) {
System.err.println(age);
return 1;
}
@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
@CheckParams({
@CheckParam(value = Check.ge, argName = "age", express="18"),
@CheckParam(value = Check.le, argName = "age", express="50")
})
@PostMapping("/singleCheckIntegerRange1")
public Object singleCheckIntegerRange1(Integer age) {
System.err.println(age);
return 1;
}
@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
@CheckParam(value = Check.NotIn, argName = "age", express="18,50")
@PostMapping("/singleCheckIntegerNotIn")
public Object singleCheckIntegerNotIn(Integer age) {
System.err.println(age);
return 1;
}
@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
@CheckParams({
@CheckParam(value = Check.lt, argName = "age", express="18"),
@CheckParam(value = Check.gt, argName = "age", express="50")
})
@PostMapping("/singleCheckIntegerNotIn1")
public Object singleCheckIntegerNotIn1(Integer age) {
System.err.println(age);
return 1;
}
@ApiImplicitParam(name = "email", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.Email, argName = "email", msg="你大爷的,输入个邮箱啊!")
@PostMapping("/singleCheckEmail")
public Object singleCheckEmail(String email) {
System.err.println(email);
return 1;
}
@ApiImplicitParam(name = "age", value = "", dataType = "Integer", paramType="query")
@CheckParam(value = Check.ge, argName = "age", express="18", msg = "必须大于等于18岁") // gt、lt、le、ne、Equal不再举例; 具体看注释
@PostMapping("/singleCheckIntegerGe")
public Object singleCheckIntegerGe(Integer age) {
System.err.println(age);
return 1;
}
@ApiImplicitParam(name = "pattern", value = "", dataType = "String", paramType="query")
@CheckParam(value = Check.Pattern, argName = "pattern", express="^[\u0021-\u007E]{4,16}$")
@PostMapping("/singleCheckPattern")
public Object singleCheckPattern(String pattern) {
System.err.println(pattern);
return 1;
}
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", dataType = "Integer", paramType="query"),
@ApiImplicitParam(name = "userName", dataType = "String", paramType="query")
})
@CheckParams({
@CheckParam(value = Check.NotNull, argName = "userId", msg = "你大爷的,这个是必填参数!"),
@CheckParam(value = Check.NotNull, argName = "userName")
})
@PostMapping("/multiCheckNotNull")
public Object multiCheckNotNull(Integer userId, String userName) {
System.err.println(userId);
System.err.println(userName);
return 1;
}
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", dataType = "Integer", paramType="query"),
@ApiImplicitParam(name = "userName", dataType = "String", paramType="query"),
@ApiImplicitParam(name = "employee", dataType = "entity", paramType="body")
})
@CheckParams({
@CheckParam(value = Check.NotNull, argName = "userId", msg = "你大爷的,这个是必填参数!"),
@CheckParam(value = Check.NotEmpty, argName = "userName"),
@CheckParam(value = Check.NotEmpty, argName = "employee.name")
})
@PostMapping("/entityCheckNotNull")
public Object entityCheckNotNull(Integer userId, String userName, @RequestBody EmployeeEntity employee) {
System.err.println(userId);
System.err.println(userName);
System.err.println(employee.getName());
return 1;
}
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", dataType = "Integer", paramType="query"),
@ApiImplicitParam(name = "userName", dataType = "String", paramType="query"),
@ApiImplicitParam(name = "dept", dataType = "entity", paramType="body")
})
@CheckParams({
@CheckParam(value = Check.NotNull, argName = "userId", msg = "你大爷的,这个是必填参数!"),
@CheckParam(value = Check.NotEmpty, argName = "userName"),
@CheckParam(value = Check.NotEmpty, argName = "dept.deptName"),
@CheckParam(value = Check.Past, argName = "dept.createTime"),
@CheckParam(value = Check.lt, argName = "dept.employees", express = "2") // 对集合的size判断
})
@PostMapping("/entityMultiCheck")
public Object entityMultiCheck(Integer userId, String userName, @RequestBody DeptEntity dept) {
System.err.println(userId);
System.err.println(userName);
System.err.println(dept.getDeptName());
return 1;
}
}
https://blog.csdn.net/weixin_42686388 https://blog.csdn.net/weixin_42686388/article/details/104009771
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
代码活跃度
社区活跃度
团队健康
流行趋势
影响力
:与代码提交频次相关
:与项目和用户的issue、pr互动相关
:与团队成员人数和稳定度相关
:与项目近期受关注度相关
:与项目的star、下载量等社交指标相关