使用AOP对Spring @Valid的校验结果做统一处理

@ResponseBody
@RequestMapping(value = "add", method = RequestMethod.POST)
public ResponseModel add(@Valid User user, BindingResult br, HttpServletResponse response) {
		
    if(br.hasErrors()) {
        //将所有的校验错误封装成一个带
换行的字符串返回给前端页面进行展示。         return ResponseModel.validFail(getErrorsSplitNewLine(br));     }     accountService.addUser(user);     return ResponseModel.success("保存用户成功"); }

 

如上面代码所示,我们一般做表单提交数据校验的时候一般使用@Valid对 Bean对象进行校验,而要使用@Valid对对象进行校验需要引入实现JSR303标准的HibernateValidator实现,如下所示:

 


  
      
      
      

 

而上例中add方法的 BindingResult参数对象会绑定校验的结果。所以要求BindingResult对象参数要紧跟在@Valid的对象参数后面,然后代码中通过判定是否存在校验错误。而代码中通过判断是否存在校验错误,来决定是调回表单页进行重新录入还是继续执行业务逻辑。如上例所示,通过if...else...来判断,

 

if(br.hasErrors()) {

} else {

}

所以这种代码逻辑就散布在很多Controller里面,丑陋无比。所以本文就使用aop方式来解决这个问题。

 

@Aspect
public class ParamValidAspect {
@Around("execution(* com.hebao.tech.adm.web.controller.*.*(..)) && args(..,bindingResult)")
    public Object validateParam(ProceedingJoinPoint pjp, BindingResult bindingResult) throws Throwable {
        Object retVal;
        logger.debug("进入AOP-ParamValidAspect-validateParam进行参数有效性校验....");
        if (bindingResult.hasErrors()) {
            String errorInfo = getErrorsSplitNewLine(bindingResult);
            logger.info("AOP-ParamValidAspect-validateParam进行参数校验出错, 出错信息如下:{}", errorInfo);
      
            retVal = ResponseModel.validFail(errorInfo);
        } else {
            //执行目标方法
            retVal = pjp.proceed();
        }
        return retVal;
    }
        /*
	 * 此校验错误信息转化为字符,多个错误信息通过参数[splitChars]进行分隔
	 */
	private String getErrors(BindingResult br, String splitChars) {
		if(splitChars == null) {
			splitChars = "";
		}
		StringBuilder result = new StringBuilder();
		List errors = br.getAllErrors();
		for (ObjectError vError : errors) {
			result.append(vError.getDefaultMessage());
			result.append(splitChars);
		}
		if(result.length() > 0) {
			result.delete(result.length() - splitChars.length(), result.length());
		}
		return result.toString();
	}
	
	/*
	 * 此校验错误信息转化为字符,多个错误信息通过
进行分隔 */ private String getErrorsSplitNewLine(BindingResult br) { return getErrors(br, "
"); } }

@Around("execution(* com.hebao.tech.adm.web.controller.*.*(..)) && args(..,bindingResult)")

使用切点符合运算,表示切入 ...controller的包以及子包,并且方法的最后一个参数为bindingResult,并将实例直接传递给validateParam方法。

 

并在SpringMVC中加入如下配置:



 

不使用@Component,的原因已经在上一篇博客文章中说过了:

Spring与SpringMVC是2个不同的父子容器, @Aspect如果被spring容器加载的话,而@Controller注解的这些类的实例化以及注入却是由SpringMVC来完成。 @Aspect如果被spring容器加载的时候,可能Spring MVC容器还未初始化, Controller类还未初始化,所以无法正常织入。。

 

你可能感兴趣的:(web后端)