Java 行为古怪的人
我在Spring中使用了基于XML的AOP,我有以下切入点:Java 行为古怪的人,java,spring,aop,Java,Spring,Aop,我在Spring中使用了基于XML的AOP,我有以下切入点: <aop:aspect id=".." ref=".."> <aop:pointcut id="interceptController" expression="execution(ModelAndView org.springframework.web.servlet.mvc.Controller+.handleRequest(HttpServletRequest, ..))" /> <
<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>
上面代码的问题是,如果我们进入if表达式的true子句,一切都可以正常工作,但是,如果进入else子句,程序会因错误而崩溃:
SEVERE: Servlet.service() for servlet ... threw exception
java.lang.ClassCastException: org.springframework.web.servlet.ModelAndView cannot be cast to java.lang.Boolean
因此,我在objecttest=jp.procedue
行上放置了一个断点,我注意到jp.procedue()
返回布尔值true
。因此,在else子句中,当我返回一个新的ModelAndView
时,它崩溃了,因为它期望从通知返回一个布尔值
究竟为什么这个建议会返回布尔值??在切入点表达式中,我指定要匹配的方法执行的返回类型为ModelAndView
,因此,procedure()
以及我的建议应该返回ModelAndView
我错过了什么
更新:如前所述,我尝试打印连接点。因此,我打印了joinpoint及其目标:
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 : my.packages.etc.LoginInterceptor@5b181df3
jp is : org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(postHandle)
target is : my.packages.etc.LoginInterceptor@5b181df3
jp is : org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(afterCompletion)
target is : my.packages.etc.LoginInterceptor@5b181df3
请注意,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)
我认为你的切入点并没有截取你所认为的。出于某种原因,它似乎截获了返回布尔值的方法。试着在控制台上打印jp
,看看你截取了哪种方法
切入点本身看起来基本上没有问题,但有一点让我印象深刻:ModelAndView
不是一个完全限定的类名。也许你想改变这一点。你有没有检查到底截获了哪个方法?ClassCastException
发生在哪里?@prefragmaric它匹配控制器的handleRequest
方法(这是一个AbstractController
)。因此,我的控制器扩展了AbstractController
,并实现了handleRequestInternal
方法。因此,我正在匹配handleRequest
方法,如果我调用procedure()
的话,该方法将调用我的handleRequestInternal
方法,否则我想返回一个新的ModelAndView
,以便重定向用户。关于异常,在返回测试时抛出代码>。我将在我的帖子中包含整个stacktrace。你说得对,我打印了jp.getTarget().toString()
,它在我的项目中打印了一些类LoginInterceptor
。它似乎截取了LoginInterceptor
类的preHandle
方法,该方法确实返回布尔值。然而,这个LoginInterceptor
类扩展了org.springframework.web.servlet.handler.HandlerInterceptorAdapter
,所以我不明白为什么会截取这个方法,因为我的切入点应该只截取servlet.mvc.Controller+
类中的HandleRequest
,当此方法位于servlet.handler
中时。。。请注意,我已将model和view
更改为其完全限定名称。我假设还有另一个切入点与同一个通知方法关联,因为您在问题中显示的切入点不会截取preHandle
、postHandle
或afterCompletion
等方法。请参考方法myAroundAdvice
,检查您的方面代码以及其他地方的配置。对,我也是这么想的,但是,最初的项目没有集成AOP。我的工作是集成AOP来做各种事情。我注释掉了所有其他切入点,因此这确实是唯一的切入点,但是问题仍然存在。为了100%确定,我更改了通知的名称,并在xml文件中引用了该新名称,但是,相同的行为仍然存在,因此,我确定没有其他切入点意外地指向相同的通知。这真的很奇怪。。我也把它给我的助教看了,他也被绊倒了。我设法解决了这个问题,使用基于注释的AOP而不是基于XML的AOP,并重写了建议。谢谢你的帮助!
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)