拦截器在Servlet的方法级别上不起作用

拦截器在Servlet的方法级别上不起作用

本文介绍了拦截器在Servlet的方法级别上不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有以下结构的简单Web应用程序Maven项目:

I have a simple web-app maven project with the following structure:

SimpleServlet.java 是具有以下代码的servlet:

SimpleServlet.java is a servlet with the following code:

@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 类是具有以下代码的拦截器接口:

And the Logger class is an interceptor interface with the following code:

@InterceptorBinding
@Retention(RUNTIME)
@Target({ METHOD, TYPE })
public @interface Logger {}

MyLogger 类是具有以下代码的拦截器实现:

And the MyLogger class is an interceptor implementation with the following code:

@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 ,我测试并发现它是正确的.

The case is that I read an interceptor only works on CDI beans, which I tested and noticed is correct.

在此示例中,我们谈论的是servlet,因此我向您提出以下问题:

For this example we are talking about a servlet, so I come to you with the following questions:

1)如果我的servlet(示例中的servlet)不被视为CDI bean,为什么在我设置 @Logger 拦截器时起作用?

1) If the my servlet (the one in my example) is not considered a CDI bean, why when I set the @Logger interceptor works?

2)为什么我的servlet中的拦截器 @Logger 在方法级别不起作用,而在类级别却可以正常工作?

2) Why the interceptor @Logger in my servlet does not work at method level and does work fine at class level?

在方法级别使用注释进行调试,我看到servlet被包装了,但是由于某种原因,@ AroundInvoke方法被忽略了.

Debugging with the annotation at method level I see the servlet is wrapped, but for some reason the @AroundInvoke method is ignored.

推荐答案

CDI提供的服务(例如侦听)通常仅在业务方法调用上发生.

Services provided by CDI, like interception, generally only happen on business method invocations.

从本质上讲,这些是通过上下文引用(注入的Bean或在像Servlets一样被视为Bean的组件上对方法的容器调用)对方法的调用.

Essentially, these are invocations of a method through a contextual reference (an injected bean, or the containers invocation of methods on components that are treated as beans like Servlets).

在您的情况下,从bean外部调用到bean内部的方法不是doGet()-这是其他继承的方法.对doGet()的调用来自Bean本身,无法被拦截.

In your case, the method called from "outside" the bean to "inside" the bean is not doGet() -- it's some other inherited method. The call to doGet() comes from within the bean itself and cannot be intercepted.

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

That's why your interception at the class level seems to be intercepted once, although it's not on the doGet() that you later try to annotate directly.

这篇关于拦截器在Servlet的方法级别上不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 23:11