繁体   English   中英

如何在 JavaEE 中挂钩 HTTP 请求的开始和结束?

[英]How to hook begin and end of HTTP requests in JavaEE?

tl;博士:

如何在ServletRequestListener.requestDestroyed期间获得ServletResponse

精简版

在 JavaEE 中,我想知道什么时候:

  • 当请求开始时
  • 当请求结束时

并能够检查请求响应对象。

长版

在 ASP.net 世界中,如果您想知道请求何时开始和结束,请编写IHttpModule

public class ExampleModuleForThisQuestion : IHttpModule
{
}

然后在 web xml 配置文件中注册您的“模块”

web.config

    <system.webServer>
        <modules>
            <add name="DoesntMatter" type="ExampleModuleForThisQuestion "/>
        </modules>
    </system.webServer> 

在您的模块中,您可以为以下内容注册回调处理程序:

  • 开始请求事件
  • 结束请求事件

然后,Web 服务器基础架构会调用您的Init方法。 这是您注册希望在请求开始和请求结束时接收通知的机会:

public class ExampleModuleForThisQuestion : IHttpModule
{
   public void Init(HttpApplication application)
   {
      application.BeginRequest += new EventHandler(beginRequest); //register the "BeginRequet" event
      application.EndRequest += new EventHandler(endRequest); //register the "EndRequest" event
   }
}

现在我们有了请求开始时的回调:

private void beginRequest(object sender, EventArgs e)
{
   HttpApplication application = (HttpApplication)sender;

   //Record the time the request started
   application.Context.Items["RequestStartTime"] = DateTime.Now;

   //We can even access the Request and Response objects
   application.ContenxtLog(application.Context.Request.Headers["User-Agent"]);
}

请求结束时我们有回调:

private void endRequest(object sender, EventArgs e)
{
   HttpApplication application = (HttpApplication)sender;

   //We can even access the Request and Response objects

   //Get the response status code (e.g. 418 I'm a teapot)
   int statusCode = application.Context.Response.StatusCode;

   //Get the request method (e.g. GET, POST, BREW)
   String method = application.context.Request.RequestType;

   //Get the path from the request (e.g. /ViewCustomer)
   String path = application.context.Request.AppRelativeCurrentExecutionFilePath'
   
   //Get when the request started - that we recorded during "Begin Request"
   DateTime requestStartTime = (DateTime)application.Context.Items["RequestStartTime"];

   //And we can modify the response
   if ((DateTime.Now - requestStartTime).TotalSeconds = 17)
       application.Context.Response.StatusCode = 451;
}

Java 几乎等价于 ServletRequestListener

在 Java 中,显然相应的技术是创建和实现ServletRequestListener接口的 object:

@WebListener
public class ExampleListenerForThisQuestion 
      implements javax.servlet.ServletRequestListener {

}

并将我们的侦听器注册到应用程序服务器,方法是将其包含在我们的 web xml 配置文件中:

web.xml

<listener>
    <listener-class>ExampleListenerForThisQuestion</listener-class>
</listener>

现在我们可以实现requestInitializedrequestDestroyed方法来获取请求何时开始和结束:

public class ExampleListenerForThisQuestion 
      implements javax.servlet.ServletRequestListener {

   @Override
   public void requestInitialized(ServletRequestEvent sre) {
      ServletRequest sr = sre.getServletRequest();
      sr.setAttribute("requestStartTicks", getCurrentTickCount());

      HttpServletRequest request = (HttpServletRequest) sr;

      // e.g. "PUT /Customers/1234"
      System.out.printf("%s %s\r\n", request.getMethod());
   }

   @Override
   public void requestDestroyed(ServletRequestEvent sre) {
      ServletRequest sr = sre.getServletRequest();
      long requestStartTicks = (long)sr.getAttribute("requestStartTicks");

      HttpServletResponse response = (HttpServletRequest)...nothing, because i don't know how...

      // e.g. "226 IM Used"
      System.out.printf("%d %s\r\n", response.getStatus(), response.getStatusDescription());
   }
}

但是如何得到响应呢?

现在我在响应结束时收到通知,我需要该请求的结果:

  • 我需要 http 状态码(例如424
  • 我需要 http 状态描述(例如Failed Dependency
  • 我需要检查响应标头
  • 我需要修改响应头

您注意到我上面的代码中的行:

HttpServletResponse response = (HttpServletRequest)...nothing, because i don't know how...

我不知道如何得到回应 这就是为什么我要问 Stackoverflow。

您可以创建过滤器而不是侦听器。

过滤器允许您围绕请求处理创建包装器。

对于 HTTP,您可以使用HTTPFilter 这可能如下所示:

@WebFilter("")//or via deployment descriptor
public class YourFilter extends HttpFilter{ //or just Filter for general (non-HTTP) processing
    @Override
    public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) {//for generic filters, use ServletRequest/ServletResponse instead
        //before request processing 
        chain.doFilter(req, res, chain);//calls other filters and processes request
        //after request processing
        //you can use res here
    }
}

如果不调用chain.doFilter ,其他过滤器和 servlet 将不会被执行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM