【问题标题】:Interceptor not working at method level in a Servlet拦截器在 Servlet 中的方法级别不起作用
【发布时间】:2017-12-09 09:33:03
【问题描述】:

我有一个简单的 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 方法被忽略了。

【问题讨论】:

  • 您确定 doGet() 在您的注释处于类级别时被拦截,还是像构造函数一样被拦截?您应该从调用上下文中记录更多信息或签入调试器。
  • 是的,在方法级别拦截,我确认一下

标签: java wildfly cdi interceptor


【解决方案1】:

CDI 提供的服务,如拦截,一般只发生在业务方法调用上。

本质上,这些是通过上下文引用(注入的 bean,或容器对组件上的方法调用,这些组件像 Servlet 一样被视为 bean)。

在您的情况下,从 bean 的“外部”调用到 bean 的“内部”的方法不是 doGet() - 它是其他一些继承的方法。对 doGet() 的调用来自 bean 本身,不能被拦截。

这就是为什么您在类级别的拦截似乎被拦截了一次,尽管它不在您稍后尝试直接注释的 doGet() 上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-07
    • 2017-09-26
    相关资源
    最近更新 更多