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

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

 

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

 

<!-- JSR303 Validator定义 -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">  
    <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>  
    <!-- 如果不加下面配置, 默认使用classpath下的 ValidationMessages.properties -->  
    <property name="validationMessageSource" ref="messageSource"/>  
</bean>

 

而上例中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<ObjectError> 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();
	}
	
	/*
	 * 此校验错误信息转化为字符,多个错误信息通过<br>进行分隔
	 */
	private String getErrorsSplitNewLine(BindingResult br) {
		return getErrors(br, "<br>");
	}
}

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

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

 

并在SpringMVC中加入如下配置:

<!--  true表示使用cglib代理技术,false表示使用jdk代理技术 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="paramValidAspect" class="com.hebao.tech.adm.framework.spring.aop.ParamValidAspect"/>

 

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

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

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringAOP 全称为 Spring Aspect-Oriented Programming,是 Spring 框架的一个模块,用于实现面向切面编程。在 SpringAOP ,我们可以通过定义切点和通知来实现对目标对象的增强。 在平台开发,我们可以使用 SpringAOP 来解决平台统一异常处理的问题。具体实现步骤如下: 1. 定义异常处理切面 在 SpringAOP ,我们可以使用 @Aspect 注解来定义切面。在切面类,我们需要定义一个处理异常的方法,并使用 @AfterThrowing 注解来指定这个方法是用于处理异常的。例如: ```java @Aspect public class ExceptionHandlerAspect { @AfterThrowing(pointcut = "execution(* com.example.*.*(..))", throwing = "ex") public void handleException(Exception ex) { // 处理异常的逻辑 } } ``` 在上述代码,我们定义了一个名为 ExceptionHandlerAspect 的切面类,并在其定义了一个名为 handleException 的方法,该方法的参数为 Exception 类型,用于处理异常。我们使用 @AfterThrowing 注解来指定这个方法是用于处理异常的,pointcut 属性用于指定切入点,这里我们使用 execution 表达式来匹配 com.example 包及其子包下的所有方法。 2. 配置 SpringAOPSpring 配置文件,我们需要配置 SpringAOP。具体来说,我们需要定义一个名为 exceptionHandlerAspect 的 bean,并在其指定切面的实现类。例如: ```xml <bean id="exceptionHandlerAspect" class="com.example.ExceptionHandlerAspect"/> <aop:config> <aop:aspect ref="exceptionHandlerAspect"> <aop:after-throwing method="handleException" throwing="ex"/> </aop:aspect> </aop:config> ``` 在上述代码,我们首先定义了一个名为 exceptionHandlerAspect 的 bean,该 bean 的 class 属性指定了切面的实现类。然后,在 aop:config 标签,我们使用 aop:aspect 标签来定义切面,并在其指定切面的实现类。在 aop:aspect 标签,我们使用 aop:after-throwing 标签来指定切面所织入的方法,method 属性用于指定处理异常的方法名,throwing 属性用于指定方法抛出的异常类型。 3. 使用统一异常处理 在业务代码,当发生异常时,SpringAOP 会自动调用我们定义的异常处理方法。在这个方法,我们可以根据具体的业务需求来处理异常。例如: ```java @Service public class UserServiceImpl implements UserService { @Override public void addUser(User user) { // 业务逻辑 try { // 执行业务操作 } catch (Exception e) { throw new RuntimeException("添加用户失败!"); } } } ``` 在上述代码,当执行 addUser 方法时,如果发生异常,SpringAOP 会自动调用我们定义的异常处理方法 handleException,并将异常对象作为参数传入该方法。在 handleException 方法,我们可以根据具体的业务需求来处理异常,例如记录日志、发送邮件等。 通过使用 SpringAOP,我们可以实现平台统一异常处理,避免代码出现大量的 try-catch 代码块,提高代码的可读性和可维护性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值