有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在SpringMVC控制器上使用SpringAOP

我有一个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是工作。但结果是错误的。系统错误:

组织。springframework。网状物util。NestedServletException:处理程序处理失败;嵌套的异常是java。lang.NoSuchMethodError

方面类是否无法将ModelAndView返回给控制器


共 (3) 个答案

  1. # 1 楼答案

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

    if(e instanceof ApplicationException)
    

    最简单的处理方法是在Spring配置文件中用proxy target class=“true”标记aop设置

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

  2. # 2 楼答案

    为什么要在这种情况下使用AOP?春天带来了你需要的一切:

    • ^{}是异常处理的全局入口点
    • ^{}允许您在控制器中定义处理程序
    • ^{}允许您在全局级别上定义@ExceptionHandler
  3. # 3 楼答案

    这个NoSuchMethodError与你的问题无关,是由你没有向我们展示的东西引起的

    至于这个问题

    is Aspect class cannot return ModelAndView to 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建议的方法。请注意,它对返回值没有任何影响。因此,您可以从@AfterThrowingadvice方法返回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来适当地处理它