TL;DR:

我怎么才能在ServletRequestListener.requestDestroyed期间拿到ServletResponse美元?

Short Version

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

  • 当请求启动时
  • 当请求结束时

并且能够判断requestresponse个物体.

Long Version

在ASP.net世界中,如果您想知道请求何时开始和结束,您可以编写一个100:

public class ExampleModuleForThisQuestion : IHttpModule
{
}

然后在Web XML配置文件中注册您的"module":

web.config:

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

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

  • BeginRequest个活动
  • EndRequest个活动

然后,Web服务器基础设施调用您的100方法.这是您注册希望在请求启动和请求结束时接收通知的机会:

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
   }
}

现在我们有了回调,当request starts分:

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"]);
}

request ends分的时候,我们有回拨:

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 Almost-Equivalent is ServletRequestListener

在Java apparently中,相应的技术是创建实现101接口的对象:

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

}

并将我们的listener注册到应用服务器,方法是将其包含在我们的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());
   }
}

But how to get the response?

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

  • 我需要http状态代码(例如424)
  • 我需要http状态描述(例如Failed Dependency)
  • 我需要判断响应头
  • 我需要修改响应头

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

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

我不知道如何获得response;这就是为什么我问Stackoverflow.

推荐答案

您可以创建Filter而不是监听程序. 筛选器允许您围绕请求处理创建包装器.请参见the documentation on that topic.

对于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);//calls other filters and processes request
        //after request processing
        //you can use res here
    }
}

如果不调用chain.doFilter,则不会执行其他过滤器和Servlet.

如果您喜欢在部署描述符(web.xml)中声明筛选器,您可以:

<filter>
  <filter-name>yourFilter</filter-name>
  <filter-class>your.FilterClass</filter-class>
</filter>
<filter-mapping>
  <filter-name>yourFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Java相关问答推荐

如何从片段请求数据到活动?在主要活动中单击按钮请求数据?

编译期间错误(Java 0000)Android .Net MAUI

如果给定层次 struct 级别,如何从其预序穿越构造n元树

查找最大子数组的和

如何在Javascript中设置文本区域圆角的样式

在spring—data中自动发现native—sql查询期间遇到重复的SQL别名[id]

@org.springframework.beans.factory.annotation.Autowired(required=true)-注入点有以下注释:-SpringBoot

我找不到&Quot;配置&的位置

Spark上下文在向Spark提交数据集时具有内容,但Spark在实际构建它时发现它为空

Mapstruct不能正确/完全映射属性

PDFBox未加载内容

SpringBoot Kafka自动配置-适用于SASL_PLAYTEXT的SSLBundle 包,带SCRAM-SHA-512

JNI:将代码打包成自包含的二进制文件

将关闭拍卖的TimerService

STREAMS减少部分结果的问题

JavaFX:无论何时显示应用程序,如何更改组件/ node 位置?

记录是类的语法糖吗?

Java KeyListener不工作或被添加

javax.crypto-密码对象-提供者服务是如何工作的?

错误:JOIN/ON的参数必须是boolean类型,而不是bigint类型.Java Spring启动应用程序