我有一个简单的web-app maven项目,其结构如下:
SimpleServlet.java
是一个servlet,代码如下:
@Logger
public class SimpleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("hello");
}
}
Logger
类是一个拦截器接口,代码如下:
@InterceptorBinding
@Retention(RUNTIME)
@Target({ METHOD, TYPE })
public @interface Logger {}
MyLogger
类是一个拦截器实现,具有以下代码:
@Interceptor
@Logger
public class MyLogger {
@AroundInvoke
public Object veQuePedo(InvocationContext ctx) throws Exception {
System.out.println("Logged");
return ctx.proceed();
}
}
我的web.xml
:
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>ThaServlet</servlet-name>
<servlet-class>com.SimpleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ThaServlet</servlet-name>
<url-pattern>/hola</url-pattern>
</servlet-mapping>
</web-app>
我的beans.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1"
bean-discovery-mode="all">
<interceptors>
<class>com.MyLogger</class>
</interceptors>
</beans>
案例是我读的拦截器仅适用于 CDI bean ,我测试过并且注意到它是正确的。
对于这个例子,我们讨论的是一个servlet,所以我带着以下问题来找你:
1)如果我的servlet(我的例子中的那个)不被认为是CDI bean,那么为什么我设置@Logger
拦截器时会起作用?
2)为什么我的servlet中的拦截器@Logger
在方法级别不起作用并且在类级别上工作正常?
使用方法级别的注释进行调试我看到servlet已被包装,但由于某种原因,@ AroundInvoke方法被忽略。
答案 0 :(得分:1)
CDI提供的服务与拦截一样,通常只发生在业务方法调用上。
本质上,这些是通过上下文引用(一个注入的bean,或者被视为像Servlets一样被视为bean的组件上的方法的容器调用)对方法的调用。
在您的情况下,该方法来自&#34; outside&#34;豆到了#34;里面&#34; bean不是doGet() - 它是一些其他继承的方法。对doGet()的调用来自bean本身,不能被拦截。
这就是为什么你在课堂级别的拦截似乎被截获一次的原因,虽然你以后尝试直接注释的doGet()上没有。