2016-11-18 63 views
2

我使用在Spring基於XML的AOP,和我有下面的切入點:環繞通知舉止奇怪

<aop:aspect id=".." ref=".."> 
    <aop:pointcut id="interceptController" expression="execution(ModelAndView org.springframework.web.servlet.mvc.Controller+.handleRequest(HttpServletRequest, ..))" /> 
    <aop:around method="myAroundAdvice" pointcut-ref="interceptController" /> 
</aop:aspect> 

我的建議如下:

public Object myAroundAdvice(ProceedingJoinPoint jp) throws Throwable { 
    if (someCondition) { 
     Object test = jp.proceed(); 
     return test; 
    } 
    else { 
     return new ModelAndView("redirect:index.htm"); 
    } 
} 

的與上面的代碼問題如果我們進入if表達式的真正子句,那麼一切正常,但是,如果我們進入else子句,程序崩潰,並出現錯誤:

SEVERE: Servlet.service() for servlet ... threw exception 
java.lang.ClassCastException: org.springframework.web.servlet.ModelAndView cannot be cast to java.lang.Boolean 

所以我把一個斷點Object test = jp.proceed,我注意到jp.proceed();返回布爾true。因此,在else子句中,當我返回一個新的ModelAndView時,它會崩潰,因爲它預計從建議中返回一個布爾值。

爲什麼地球上有一個布爾值會從此建議中返回?在切入點表達式我指定的方法執行我很匹配的返回類型爲ModelAndView,因此,proceed()以及我的意見應該返回ModelAndView ..

缺少什麼我在這裏?


UPDATE:正如指出的那樣,我試着打印連接點。因此我打印的連接點以及它的目標:

System.out.println("jp is : " + jp.toString()); 
System.out.println("target is : " + jp.getTarget().toString()); 

此打印訪問的網頁時,以下幾點:

jp is : org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(preHandle) 
target is : [email protected] 

jp is : org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(postHandle) 
target is : [email protected] 

jp is : org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(afterCompletion) 
target is : [email protected] 

注意LoginInterceptor擴展HandlerInterceptorAdapter類,所以爲什麼它與我的切入點匹配?因爲HandlerInterceptorAdapterservlet.handler而我匹配servlet.mvc.Controller+.handleRequest


整個stracktrace:

18-nov-2016 14:52:26 org.apache.catalina.core.StandardWrapperValve invoke 
SEVERE: Servlet.service() for servlet ... threw exception 
java.lang.ClassCastException: org.springframework.web.servlet.ModelAndView cannot be cast to java.lang.Boolean 
    at com.sun.proxy.$Proxy32.preHandle(Unknown Source) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:865) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571) 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:723) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:112) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861) 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:612) 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503) 
    at java.lang.Thread.run(Thread.java:695) 
+0

您是否檢查了截取哪種方法? ClassCastException發生在哪裏? –

+0

@PredragMaric它匹配控制器的'handleRequest'方法(它是一個'AbstractController')。因此,我的控制器擴展了'AbstractController'並實現了'handleRequestInternal'方法。因此,如果我調用'proceed()',我會匹配'handleRequest'方法,該方法會調用我的'handleRequestInternal'方法,否則我想要返回一個新的'ModelAndView'以重定向用戶。關於例外情況,它被拋在'return test;'上。我將在我的文章中包含整個堆棧跟蹤。 – HyperZ

回答

1

我覺得你的切入點不攔截你認爲它。由於某種原因,它似乎攔截返回布爾值的方法。嘗試在控制檯上打印jp並查看您截取了哪種方法。

這樣的切入點看起來基本上沒問題,但有一點讓我感到震驚:ModelAndView不是完全合格的類名。也許你想改變它。

+0

你說得對,我打印了'jp.getTarget()。toString()',它在我的項目中打印了一些類'LoginInterceptor'。它似乎攔截了'LoginInterceptor'類的'preHandle'方法,它確實返回一個布爾值。然而,這個'LoginInterceptor'類擴展了'org.springframework.web.servlet.handler.HandlerInterceptorAdapter',所以我不明白爲什麼這個方法被攔截,因爲我的切入點應該只攔截來自'servlet.mvc的'HandleRequest'。 Controller +'類,而此方法在'servlet.handler'中...請注意,我將'ModelAndView'更改爲完全限定名稱。 – HyperZ

+0

我假設有另一個切入點與相同的建議方法相關聯,因爲你在問題中顯示的那個切入點不會攔截諸如'preHandle','postHandle'或'afterCompletion'之類的方法。請檢查您的方面代碼以及您引用方法myAroundAdvice的其他地方的配置。 – kriegaex

+0

對,這正是我的想法,但是,原來的項目沒有集成AOP。我的工作是整合AOP來做各種各樣的東西。我評論了所有其他切入點,以至於這確實是唯一的切入點,但問題仍然存在。爲了100%確定,我改變了建議的名稱,並在我的xml文件中提到了這個新名字,但是,相同的行爲仍然存在,因此,我確信沒有其他意外指出相同的切入點諮詢。這真的很奇怪,我也向我的助教展示過,而且他也陷入了困境。 – HyperZ