1.首先在需要校验的参数上加上注解:
@Null 限制只能为null
@NotNull 限制必须不为null
@AssertFalse 限制必须为false
@AssertTrue 限制必须为true
@DecimalMax(value) 限制必须为一个不大于指定值的数字
@DecimalMin(value) 限制必须为一个不小于指定值的数字
@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future 限制必须是一个将来的日期
@Max(value) 限制必须为一个不大于指定值的数字
@Min(value) 限制必须为一个不小于指定值的数字
@Past 限制必须是一个过去的日期
@Pattern(value) 限制必须符合指定的正则表达式
@Size(max,min) 限制字符长度必须在min到max之间
@Past 验证注解的元素值(日期类型)比当前时间早
@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式
2.在controller中加上@valid注解 和BindingResult 对象 另外加上一套restful风格的增删改查:
package com.finance.cmp.ruleEngine.web.controller;
import com.finance.cmp.ruleEngine.common.enums.ResultEnum;
import com.finance.cmp.ruleEngine.common.util.Result;
import com.finance.cmp.ruleEngine.common.util.ResultUtil;
import com.finance.cmp.ruleEngine.common.vo.RuleQueryVo;
import com.finance.cmp.ruleEngine.dao.model.*;
import com.finance.cmp.ruleEngine.dao.vo.RuleVo;
import com.finance.cmp.ruleEngine.service.service.ITRuleFactorService;
import com.finance.cmp.ruleEngine.service.service.ITRuleService;
import com.finance.cmp.ruleEngine.service.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 规则
*/
@SuppressWarnings("all")
@Slf4j
@RestController
@RequestMapping("rule")
public class RuleController extends BaseController {
@Autowired
private ITRuleService itRuleService;
@Autowired
private ITRuleFactorService itRuleFactorService;
//region API
/**
* select all
*
* @param ruleQueryVo
* @return
*/
@GetMapping("list")
public Result selectList(RuleQueryVo ruleQueryVo) {
log.info("入参:" + ruleQueryVo);
Map resultMap = null;
try {
resultMap = itRuleService.selectByList(ruleQueryVo);
} catch (Exception e) {
return ResultUtil.error(ResultEnum.SERVER_ERROR, e.getMessage());
}
return ResultUtil.success(resultMap);
}
/**
* select by id
* GetMapping风格的必须加上@PathVariable 不然获取不到参数
* @param id
* @return
*/
@GetMapping("edit/{id}")
public Result selectById(@PathVariable(value = "id", required = true) Integer id) {
log.info("id:{}" + id);
ModelAndView mv = new ModelAndView();
TRule tRule = itRuleService.selectById(id);
if (tRule == null) {
mv.addObject("msg", "请注意,您正在访问无效资源。操作被禁止。");
mv.setViewName("error/errorPage");
/* return mv;*/
}
return ResultUtil.success(tRule);
}
/**
* add rule
* @PostMapping 这种风格必须加上@RequestBody 不然获取不到参数
* @param tRule
* @param erros
* @return
*/
@Transactional(rollbackFor = Exception.class)
@PostMapping("")
public Result insertRule(@Valid @RequestBody TRule tRule, BindingResult erros) {
log.info("tRule:{}" + tRule);
TRule rule = new TRule();
rule.setRuleName(tRule.getRuleName());
TRule ruleOne= itRuleService.selectByRuleName(rule);
if (ruleOne != null) {
return ResultUtil.error(ResultEnum.RULE_IS_REPEAT);
}
tRule.setCreateTime(new Date());
tRule.setUpdateTime(new Date());
int addRule = itRuleService.insertRule(tRule);
if (addRule > 0) {
TRule tRules = itRuleService.selectByRuleName(rule);
for (TRuleFactor tRuleFactor : tRule.gettRuleFactors()) {
//mabatis的特性 使用引用对象可直接获取到刚新增的id 不受事务影响 不用查一遍
tRuleFactor.setRuleId(tRule.getId());
tRuleFactor.setCreateTime(new Date());
tRuleFactor.setUpdateTime(new Date());
itRuleFactorService.insertRuleFactor(tRuleFactor);
}
} else {
return ResultUtil.error(ResultEnum.INSET_ERROE);
}
return ResultUtil.success();
}
/**
* update rule
*
* @param tRule
* @param erros
* @return
*/
@Transactional(rollbackFor = Exception.class)
@PutMapping
public Result updateRule(@Valid @RequestBody TRule tRule, BindingResult erros) {
log.info("tRule:{}" + tRule);
int ruleIsUse = itRuleService.ruleIsUse(tRule.getId());
if (ruleIsUse > 0) {
return ResultUtil.error(ResultEnum.RULE_ALREADY_USE);
}
int updateRule = itRuleService.updateRule(tRule);
if (updateRule > 0) {
List list = itRuleFactorService.selectFactorByRuleId(tRule.getId());
for (TRuleFactor tRuleFactor : list) {
itRuleFactorService.deleteRuleFactor(tRuleFactor.getId());
}
for (TRuleFactor tRuleFactor : tRule.gettRuleFactors()) {
tRuleFactor.setRuleId(tRule.getId());
tRuleFactor.setCreateTime(new Date());
tRuleFactor.setUpdateTime(new Date());
itRuleFactorService.insertRuleFactor(tRuleFactor);
}
} else {
return ResultUtil.error(ResultEnum.UPDATE_ERROE);
}
return ResultUtil.success();
}
/**
* delete rule
*
* @param id
* @return
*/
@Transactional(rollbackFor = Exception.class)
@DeleteMapping("/{id}")
public Result deleteRule(@PathVariable Integer id) {
log.info("id:{}" + id);
if (id == null) {
return ResultUtil.error(ResultEnum.DATA_IS_NULL, "请传入参数");
}
TRule rule = itRuleService.selectById(id);
if (rule != null) {
if ("invalid".equals(rule.getStatus())) {
int deleteRule = itRuleService.deleteRule(id);
if (deleteRule > 0) {
List ruleFac = itRuleFactorService.selectFactorByRuleId(id);
for (TRuleFactor tRuleFactor : ruleFac) {
itRuleFactorService.deleteRuleFactor(tRuleFactor.getId());
}
} else {
return ResultUtil.error(ResultEnum.DELETE_ERROE);
}
} else {
return ResultUtil.error(ResultEnum.DELETE_ERROE, "该变量为启用状态");
}
} else {
return ResultUtil.error(ResultEnum.DATA_IS_NULL);
}
return ResultUtil.success();
}
//endregion API
}
3.在common项目中定义切面 在进入controller之前进行参数校验 如不通过 直接返回给前端错误信息:
切面类:AutoValidateParam:
package com.zhonguo.zhuboyuan.good.springboot.common.validate;
import com.zhonguo.zhuboyuan.good.springboot.common.enums.ResultEnum;
import com.zhonguo.zhuboyuan.good.springboot.common.util.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
/**
* 自动验证controller层的参数
*
* @author zhangqb
* @date 2019/4/1
*/
@Slf4j
@Aspect
@Component
@Order(2)
public class AutoValidateParam {
/**
* 定义切入点
*/
@Pointcut("execution(public * com.zhonguo.zhuboyuan.good.*.web..*.*(..))")
public void cutService() {
}
/**
* 在切入点开始处切入内容
*
* @param joinPoint
*/
@Around("cutService()")
public Object around(ProceedingJoinPoint joinPoint) {
Object result = null;
// 验证结果
ValidateResult validateResult = new ValidateResult(Boolean.TRUE, "参数合法性校验通过!");
// 获取所有的请求参数
Object[] args = joinPoint.getArgs();
if (null != args && args.length > 0) {
for (Object obj : args) {
if (obj instanceof BindingResult) {
// 参数验证
validateResult = validate((BindingResult) obj);
break;
}
}
}
// 验证通过执行拦截方法,否则不执行
if (validateResult.isValidatePass()) {
try {
// 执行拦截方法
result = joinPoint.proceed();
} catch (Throwable ex) {
log.error("AOP执行拦截方法时异常, {}", ex);
result = ResultUtil.error(ResultEnum.UNKNOWN_ERROR, "AOP执行拦截方法时异常!" + ex.getMessage());
}
} else {
result = ResultUtil.error(ResultEnum.PARAMETER_ERROR, validateResult.getErrorMessage());
}
return result;
}
/**
* 验证
*
* @param bindingResult
* @return
*/
private ValidateResult validate(BindingResult bindingResult) {
// 参数验证结果
ValidateResult validateResult = ParamValidateUtil.validating(bindingResult);
log.info("请求参数验证结果:{}", validateResult);
return validateResult;
}
}
还有两个是返回前端的封装类。
至此就完成了自动检验参数的功能: