springboot利用切面集合@valid注解和BindingResult 进行所有controller的参数拦截和校验--R

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<String, Object> 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<TRuleFactor> 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<TRuleFactor> 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;
    }

}

还有两个是返回前端的封装类。

至此就完成了自动检验参数的功能:
在这里插入图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: @Valid注解和@Validated注解都是用于校验数据的注解,但是它们的使用场景略有不同。 @Valid注解是JSR-303规范中定义的注解,用于校验JavaBean中的属性值是否符合规范。它可以用在方法参数、方法返回值、方法参数中的属性、方法返回值中的属性等位置上。在Spring Boot中,我们可以在Controller中使用@Valid注解校验请求参数是否符合规范。 @Validated注解是Spring框架中提供的注解,它可以用于校验方法参数是否符合规范。它支持分组校验,可以根据不同的场景对参数进行不同的校验。在Spring Boot中,我们可以在Service或者Controller中使用@Validated注解校验方法参数是否符合规范。 总的来说,@Valid注解用于校验JavaBean中的属性值,而@Validated注解用于校验方法参数。两者都可以用于校验数据,但是使用场景略有不同。 ### 回答2: @Valid注解和@Validated注解都用于校验数据的有效性,但是它们有所不同。 @Valid注解是来自于javax.validation规范中的注解,是用于Bean Validation校验的,它可以用于校验Java Bean对象中的字段。@Valid注解只能加在某个目标类型参数上,并且该参数类型需要是一个对象,它可以递归验证对象中的所有字段和对象。 @Validated注解则是Spring框架提供的注解,是用于Spring校验的,它可以用于校验方法和参数。@Validated注解用于验证参数和返回值,通常放在接口方法上。@Validated注解描述的约束条件必须是JSR303支持的约束条件的JavaBean,而@Valid注解不支持约束条件。 总的来说,@Valid注解是制定了JSR303规范而来的,属于Bean Validation更多的是参数校验,而@Validated注解是Spring框架专门提供的注解,用于控制校验,其作用与@Valid注解类似,但更加灵活,能进行更多的分组约束、级联验证等。 ### 回答3: @Valid注解和@Validated注解是Java中用于数据校验的两个注解。它们都是基于Bean Validation规范的,提供了对Java Bean属性进行校验的功能。 @Valid注解用于进行简单的数据校验,它可以在Controller的方法参数中对参数进行校验。它的作用是告诉Spring框架对该参数进行数据校验,如果校验失败,则会抛出ConstraintViolationException异常。该注解使用时需要配合bindingResult参数一起使用,bindingResult参数用于接收校验结果。 @Validated注解更加强大,除了提供了@Valid注解的功能外,它还可以在Service和Dao对方法参数进行校验。它支持Spring Expression Language(SpEL)表达式,并提供了基于分组校验的功能。基于分组校验可以根据不同的校验场景,对同一个实体进行不同的校验,增强了数据校验的灵活性。 除了以上的差异,还有一个重要区别:@Valid注解是标准的Java注解,而@Validated注解是Spring提供的注解。因此,如果项目中只使用了Spring框架,那么可以直接使用@Validated注解。但如果使用的是标准的Java环境,则需要使用@Valid注解

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值