我有一个简单的 Web 应用程序 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
类是一个拦截器接口(interface),代码如下:
@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 beans,我测试并注意到这是正确的。
在本示例中,我们讨论的是 servlet,因此我向您提出以下问题:
1) 如果我的 servlet(我的示例中的那个)不被视为 CDI bean,为什么当我设置 @Logger
拦截器时会起作用?
2) 为什么我的 servlet 中的拦截器 @Logger
在方法级别不起作用,而在类级别却工作正常?
在方法级别使用注释进行调试时,我看到 servlet 已被包装,但由于某种原因,@AroundInvoke 方法被忽略。
最佳答案
CDI 提供的服务(如拦截)通常仅发生在业务方法调用上。
本质上,这些是通过上下文引用(注入(inject)的 bean,或者容器调用被视为 Servlet 等 bean 的组件上的方法)来调用方法。
在你的例子中,从bean“外部”到bean“内部”调用的方法不是 doGet() —— 它是其他一些继承的方法。对 doGet() 的调用来自 bean 本身,无法被拦截。
这就是为什么您在类级别的拦截似乎被拦截了一次,尽管它不在您稍后尝试直接注释的 doGet() 上。
关于java - 拦截器在 Servlet 中的方法级别不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44930897/