拦截器不在Servlet中的方法级别工作

时间:2017-07-05 15:51:59

标签: java wildfly cdi interceptor

我有一个简单的web-app maven项目,其结构如下:

enter image description here

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方法被忽略。

enter image description here

1 个答案:

答案 0 :(得分:1)

CDI提供的服务与拦截一样,通常只发生在业务方法调用上。

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

在您的情况下,该方法来自&#34; outside&#34;豆到了#34;里面&#34; bean不是doGet() - 它是一些其他继承的方法。对doGet()的调用来自bean本身,不能被拦截。

这就是为什么你在课堂级别的拦截似乎被截获一次的原因,虽然你以后尝试直接注释的doGet()上没有。