【问题标题】:Use Spring Aop on Spring mvc controller在 Spring mvc 控制器上使用 Spring Aop
【发布时间】:2017-01-18 22:21:39
【问题描述】:

我有一个 Spring MVC 控制器抛出两种异常:

@RequestMapping(value = "forwardRefundApply",method = RequestMethod.GET)
public ModelAndView forwardRefundApply1(String ticketNbr)throws Exception {
    if(true)
        throw new Exception();
    else
        throw new ApplicationException("test");
}

然后我编写一个 AOP 类来处理异常,然后像这样返回模型:

  @Pointcut("execution(public * ..*(..))")
public void getRefundPointCut() {
}

@AfterThrowing(pointcut="getRefundPointCut()", throwing="e")
public ModelAndView throwException(Exception e){
    ModelAndView mav = null;
    if(e instanceof ApplicationException)
    {

        e.printStackTrace();
        mav = new ModelAndView(CommonConstants.ERRORPAGE);
        mav.addObject("errorMsg", "application error");
        return mav;
    }
    else{
        e.printStackTrace();

        mav  = new ModelAndView(CommonConstants.ERRORPAGE);
        mav.addObject("errorMsg", "system error");
        return mav;
    }
}

aop 是工作。但结果是错误的。系统错误:

org.springframework.web.util.NestedServletException:处理程序处理失败;嵌套异常是 java.lang.NoSuchMethodError

Aspect 类是否无法将 ModelAndView 返回给 Controller?

【问题讨论】:

  • 发布完整的堆栈跟踪。

标签: java spring-mvc aop


【解决方案1】:

为什么在这种情况下使用 AOP? Spring 提供了你需要的一切:

【讨论】:

  • +1 这些是此用例的合适替代方案。
【解决方案2】:

NoSuchMethodError 与您的问题无关,是由您未向我们展示的内容引起的。

至于问题

Aspect 类是否无法将 ModelAndView 返回给 Controller?

我在Spring's AOP documentation 的任何地方都找不到对它的任何引用,但是您可以在实现中看到它。

当您声明 @AfterThrowing 通知时,Spring 使用 AspectJAfterThrowingAdvice 来处理它。其invoke(..) 方法实现为

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        return mi.proceed();
    }
    catch (Throwable t) {
        if (shouldInvokeOnThrowing(t)) {
            invokeAdviceMethod(getJoinPointMatch(), null, t);
        }
        throw t;
    }
}

mi.proceed() 调用您的建议方法,invokeAdviceMethod(..) 调用您的@AfterThrowing 建议方法。请注意,它对返回值没有任何作用。因此,您可以从 @AfterThrowing 通知方法返回一个 ModelAndView 对象,但它没有任何用途,它只会被丢弃。

一种可能的替代方法是声明@Around 建议。在其中,您包装正在进行的调用并捕获可能的异常,并适当地处理它们

@Around(value = "getRefundPointCut()")
public ModelAndView throwException(ProceedingJoinPoint joinPoint) throws Throwable {
    ModelAndView mav = null;
    try {
        return (ModelAndView) joinPoint.proceed(); // might want to make sure that it is a ModelAndView
    } catch(ApplicationException e) {
        e.printStackTrace();
        mav = new ModelAndView("home");
        mav.addObject("errorMsg", "application error");
        return mav;
    } catch (Exception e) {
        e.printStackTrace();
        mav = new ModelAndView("home");
        mav.addObject("errorMsg", "system error");
        return mav;
    }
}

如果返回正确,则在此处返回建议方法的值。或者你抓住任何抛出的Exception,然后通过返回一个不同的ModelAndView再次适当地处理它。

【讨论】:

    【解决方案3】:

    我自己还没有测试过,但是 Spring AOP 使用代理对象而不是实际对象。所以 e 实际上是代理的一个实例,而不是 ApplicationException 的一个实例。所以下面的条件永远不会执行为真。

    if(e instanceof ApplicationException)
    

    处理此问题的最简单方法是在 Spring 配置文件中使用 proxy-target-class="true" 标记您的 aop 设置。

    <aop:aspectj-autoproxy proxy-target-class="true"/>
    

    HTH

    【讨论】:

      猜你喜欢
      • 2017-03-21
      • 1970-01-01
      • 2015-06-04
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      • 1970-01-01
      • 2018-07-22
      • 1970-01-01
      相关资源
      最近更新 更多