热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

springboot利用切面集合@valid注解和BindingResult进行所有controller的参数拦截和校验--R,Go语言社区,Golang程序员人脉社

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;
    }

}

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

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


推荐阅读
author-avatar
吖鸟集团总公司
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有