欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring MVC 统一处理异常值AOP

程序员文章站 2022-04-25 21:19:06
...

* 思想

       下班后,站在熙熙攘攘的地铁上,看到一个帖子,技术和思想的重要性。一位楼主的话让我感受很深刻:论技术和思想的重要性,他说到他的开发水平不是很高,但是他认为他所具有的思想是很不错的,他谈到对自己手下的员工的高要求,让他们在写出来的代码不至于那样的笨重,他说他很严格,但是还是有人愿意跟着他,为什么呢?因为可以收获很多。然后开始制定接口,约束大家如何写代码。

       看着文章,不由得想到了我的领导,顺手写下评论:“感恩我有一个和您很像的领导”。前两周做了一个开发demo,以便让后续的开发更加的高效,项目经理审代码的时候提了一个要求,我们的异常处理可以不在controller中处理吗,boss提了这么个建议,我便去落实,我知道答案肯定是可以的。


* 代码分析

       我们用的框架有SpringMVC,给大家分享一下controller中的代码:

/**
     * 根据id查找Foo
     *
     * @param id 主键id
     * @return ItooResult Foo集合
     * @author viola
     * @since 1.0.0 2018-10-18 14:35:27
     */
    @ApiOperation(value = "根据id查询Foo", notes = "请输入主键id进行查询")
    @GetMapping(value = {"/findFooModelById/{id}"})
    public ItooResult findFooModelById(@ApiParam(value = "主键id", required = true) @PathVariable String id) {

        FooModel fooModel = null;
        try {
            fooModel = fooService.queryFooModelById(id);
        } catch (Exception e) {
            return ItooResult.build(ItooResult.SUCCESS, "查询成功", fooModel);
        }
        return ItooResult.build(ItooResult.SUCCESS, "查询成功", fooModel);
    }

       当然上面的代码大家看着已经很不错了,大家看到经过已经是被封装过的了。但是我们的每个方法中都要进行异常的捕获和处理,是不是显得很麻烦,这样也不符合我们开发的过程中多关注业务实现。下面是优化后的代码:

/**
     * 根据id查找Foo
     *
     * @param id 主键id
     * @return ItooResult Foo集合
     * @author viola
     * @since 1.0.0 2018-10-18 14:35:27
     */
    @ApiOperation(value = "根据id查询Foo", notes = "请输入主键id进行查询")
    @GetMapping(value = {"/findFooModelById/{id}"})
    public ItooResult findFooModelById(@ApiParam(value = "主键id", required = true) @PathVariable String id) {
        FooModel fooModel = fooService.queryFooModelById(id);
        return ItooResult.build(ItooResult.SUCCESS, "查询成功", fooModel);
    }

       给人的感觉是不是简单了很多,这便是一个团队整体素质的体现。


* @Around

       我的实现方式是通过横切处理的,@Around增强处理是较为强大的处理,它近似等于Before和AfterReturning的总和。@Around既可在执行目标方法之前织入增强动作,也可在执行目标方法之后织入增强动作。@Around甚至可以绝地目标方法什么时候执行,如何执行,更甚这可以完全阻止目标方法的执行。

       @Around功能虽然强大,但通常在线程安全的环境下使用,因此,如果可以用Before和AfterReturning就能解决问题的,就没有必要使用Around。但是我们拦截controller需要改变目标返回值,因此需要用Around。

       当定义一个Around增强处理时,需要的一个形参必须是ProceedingJopinPoint类型,在增强处理方法体内,调用ProceedingJoinPoint的proceed方法才会执行目标方法------这就是@Around增强处理可以完全控制目标方法执行时机、如何执行的关键;如果程序没有调用ProceedingJoinPoint的proceed方法,则目标方法不会执行。

       如下是拦截异常的方法实现:

@Aspect
public class ExceptionIntercept {
    private static final Logger logger = LoggerFactory.getLogger(AfterReturningAspect.class);
    
    //配置切面
    @Pointcut("execution(* com.dmsdbj.itoo.*.provider.controller.*.*(..))")
    public void declareJoinPointExpression() {
    }

   //增强方法
    @Around("declareJoinPointExpression()")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) {
        try {
            ItooResult itooResult = (ItooResult)pjp.proceed(pjp.getArgs());
            return itooResult;
        } catch (Throwable var4) {
            if("true".equals(this.clazzMap.get("aop.printexception.enable"))) {
                logger.info("执行Controller异常: " + pjp.getSignature() + ", 异常信息:" + var4);
                throw new ItooRuntimeException(var4);
            } else {
                return ItooResult.build("1111", "异常");
            }
        }
    }
}

       spring.xml中进行如下配置:

 <!-- 启动对@AspectJ注解的支持 -->
    <aop:aspectj-autoproxy/>
 <!--统一处理controller的异常-->
  <bean class="com.dmsdbj.itoo.tool.aspect.ExceptionIntercept"/>
相关标签: AOP