我使用在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
類,所以爲什麼它與我的切入點匹配?因爲HandlerInterceptorAdapter
在servlet.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)
您是否檢查了截取哪種方法? ClassCastException發生在哪裏? –
@PredragMaric它匹配控制器的'handleRequest'方法(它是一個'AbstractController')。因此,我的控制器擴展了'AbstractController'並實現了'handleRequestInternal'方法。因此,如果我調用'proceed()',我會匹配'handleRequest'方法,該方法會調用我的'handleRequestInternal'方法,否則我想要返回一個新的'ModelAndView'以重定向用戶。關於例外情況,它被拋在'return test;'上。我將在我的文章中包含整個堆棧跟蹤。 – HyperZ