天天看点

基于spring aop + validator实现接口请求参数校验

目录

1. 概述

2. 基于AOP在执行convert方法前进行参数校验

3. 定义参数校验定义切面类和切点

4. 参考链接

1. 概述

可以参考以前做过的项目mwp模块中的查询接口,json转ReqBean时根据reqbean中的校验注解进行参数校验

在基于springboot项目时,可以借助于springboot + validator在controller层实现请求参数的自动校验功能。如下controller类中的请求方法:

/**
* 在controller层,自动实现接口参数校验功能
*/
@RequestMapping(method = {RequestMethod.POST}, value = "/personDetailInfoQuery")
public RspBean<R> npfList(@RequestBody @Validated ReqBean<PersonReqBean> reqBean, HttpServletRequest request) throws Exception {
    PageUtils page = service.queryPage(reqBean);
    RspBean<R> rspBean = new RspBean<>();
    rspBean.setMsgBody(R.ok().put("page", page));
    rspBean.setMsgHead(MsgHead.defaultMsgHeaderInstance());
    return rspBean;
}
           

在实际项目中,遇到先将请求参数json接收,然后在后面逻辑转为不同reqBean时进行参数校验,这样就需要手动实现上面的校验逻辑,可借助于如下工具类,实现参数校验

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

/**
 * hibernate-validator校验工具类
 * 参考文档:http://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/
 */
public class ValidatorUtils {
    private static Validator validator;

    static {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    /**
     * 校验对象
     * @param object        待校验对象
     * @param groups        待校验的组
     * @throws RRException  校验不通过,则报RRException异常
     */
    public static void validateEntity(Object object, Class<?>... groups)
            throws RRException {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty()) {
        	ConstraintViolation<Object> constraint = (ConstraintViolation<Object>)constraintViolations.iterator().next();
            throw new RRException(constraint.getMessage());
        }
    }
}
           

2. 基于AOP在执行convert方法前进行参数校验

刚开始想在抽象类中的convert()方法做为切点的,但是最后没有成功,AOP对抽象类、抽象方法加切点有特殊要求,以后有时间了再研究。因此就临时选择了另外一种途径。如下抽象类:

public abstract class AbstractQueryService<M extends BaseMapper<T>, T, REQ extends BaseBean> extends ServiceImpl<M,T> implements QueryService {

    public PageUtils queryPage(String rawMsg) {
        return doQueryPage(convert(rawMsg));
    }

    /**
     * 查询数据
     * @param reqBean
     * @return
     */
    protected PageUtils doQueryPage(ReqBean<REQ> reqBean) {
        PageUtils pageUtils = new PageUtils(page);
        return pageUtils;
    }

    /**
     * 请求报文转为 reqBean,并校验查询参数是否满足
     * @param rawMsg
     * @return
     */
    public abstract ReqBean<REQ> convert(String rawMsg);
}	
           

如下抽象类的具体实现类:

public class MwpServiceImpl extends AbstractQueryService<ABCDao, ABCEntity, ABCReqBean> {

    @Override
    public ReqBean<ABCReqBean> convert(String rawMsg) {
        ReqBean<ABCReqBean> reqBean = JSONObject.toJavaObject(JSONObject.parseObject(rawMsg), new ReqBean<>().getClass());
        reqBean.setMsgBody(JSONObject.toJavaObject(JSONObject.parseObject(rawMsg).getJSONObject("msgBody"), ABCReqBean.class));  
        return reqBean;
    }
}
           

3. 定义参数校验定义切面类和切点

/**
* 参数校验切面
*/
@Slf4j
@Aspect
@Configuration
public class ParamValidatorAspect {

    @Pointcut("execution(* com.xxx.service.QueryService.queryPage(java.lang.String))")
    public void validateParam() {
        log.info("Pointcut validateParam");
    }

    /**
     * 校验查询参数
     */
    @Before("validateParam()")
    public void doBefore(JoinPoint pjp) throws Throwable {

        Object[] paramValues = pjp.getArgs();
        String type = JSONObject.parseObject(String.valueOf(paramValues[0])).getJSONObject(MSG_HEAD).getString(MSG_HEAD_TYPE);
        ReqRouterUtil.isAvailableService(type);

        Class<?> parameterizedTypeClass = Class.forName((((ParameterizedType)QueryService.queryServerMap.get(type).getClass().getDeclaredMethod(CONVERT_METHOD_NAME, String.class).getGenericReturnType()).getActualTypeArguments()[0]).getTypeName());
        String msgBody = JSONObject.parseObject(String.valueOf(paramValues[0])).getString(MSG_BODY);
        ObjectMapper mapper = new ObjectMapper();
        ValidatorUtils.validateEntity(mapper.readValue(msgBody, parameterizedTypeClass));
        log.info("param validate successful");
    }
}	
           
/**
*	切点类,进入下一步前,对raw转换为reqbean时做参数校验
*/
@Service("QueryService")
public class MwpQueryService {

    public PageUtils queryPage(String rawMsg) {
        ReqBean reqBean = JSONObject.toJavaObject(JSONObject.parseObject(rawMsg), new ReqBean<>().getClass());
        return QueryService.queryServerMap.get(reqBean.getMsgHead().getType()).queryPage(rawMsg);
    }
}
           

4. 参考链接

获取(泛型)方法返回类型  https://blog.csdn.net/doctor_who2004/article/details/101780509

https://blog.csdn.net/qq_35387940/article/details/106232146

https://blog.csdn.net/qq_28033239/article/details/86740861

https://www.jb51.net/article/110461.htm

https://blog.csdn.net/qq_18769269/article/details/80841734

https://blog.csdn.net/weixin_45627031/article/details/107567577