【问题标题】:Prevent Tomcat from interfering with Jersey/JAX-RS 2 Response Body on HTTP Error Status 4xx or 5xx防止 Tomcat 在 HTTP 错误状态 4xx 或 5xx 上干扰 Jersey/JAX-RS 2 响应正文
【发布时间】:2014-02-03 18:10:16
【问题描述】:

我有以下 REST API 堆栈

  • 泽西 2/JAX RS 2.0
  • Tomcat 7.0.47
  • 杰克逊 2

我的目标是在发生错误时有一个自定义响应正文。我希望能够向客户发送一个解释究竟出了什么问题,以便于调试。

首先我尝试使用@Context HttpServletResponse并在那里设置http状态码,但它被球衣忽略了(这是正常行为,但这超出了我的理解)

然后我尝试像这样使用WebApplicationException

@GET
@Path("/myapi")
public BaseResponse getSomething() {
   BaseResponse b = new BaseResponse();
   if(error) {
      b.setStatusDescription("reason for error");
      throw new WebApplicationException(Response.status(Response.Status.CONFLICT).entity(b).build());
   }
   //add content to BaseReponse
   return b
}

但是 Tomcat 给我的回报是这样的:

<html>
    <head>
        <title>Apache Tomcat/7.0.47 - Error report</title>
        <style>
            <!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22p

这是标准 Tomcat html 输出,由我想要返回的响应正文的 contet-length(.entity(b) - b 的长度)限制。所以它被识别了,但 Tomcat 只是用自己的错误页面覆盖它。

作为旁注,我还尝试返回具有相同结果的响应:

return Response.status(Response.Status.CONFLICT).entity(b).build()

那么我如何告诉 Tomcat 让我一个人呆着,让我自己做出回应?

【问题讨论】:

  • 那个 Jersey 调用 HttpServletResponse.sendError()——并因此调用 servlet 容器的 error-page 机制——似乎违反了 JAX-RS 2.0 的第 3.3.3 节,该节规定返回 Response“导致从Response"的实体属性映射的实体主体。

标签: java rest tomcat7 jax-rs jersey-2.0


【解决方案1】:

问题是我使用的是来自 ehcache 的 GzipServlet,这似乎不适用于球衣。在多个阶段,响应包装器抛出异常。

这是ehcache的依赖:

        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-web</artifactId>
            <version>2.0.4</version>
        </dependency>

以及 web.xml 中有问题的 servlet 定义

<filter>
        <filter-name>GzipFilter</filter-name>
        <filter-class>net.sf.ehcache.constructs.web.filter.GzipFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>GzipFilter</filter-name>
        <url-pattern>/rest/*</url-pattern>
    </filter-mapping>

作为替代方案,我现在使用 Jetty Servlet:http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/servlets/GzipFilter.html

<dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlets</artifactId>
            <version>8.1.0.RC5</version>
        </dependency>

web.xml

<filter>
  <filter-name>GzipFilter</filter-name>
  <filter-class>org.eclipse.jetty.servlets.GzipFilter</filter-class>
  <init-param>
    <param-name>mimeTypes</param-name>
    <param-value>text/html,text/plain,text/xml,application/xhtml+xml,text/css,application/javascript,image/svg+xml</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>GzipFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

作为免责声明:是的,我知道我可以在 tomcat 配置中激活 gzip,但我正在编写一个测试服务器,它必须能够拥有带和不带 gzip 的端点。

【讨论】:

    【解决方案2】:

    只需在 ResourceConfig 类的配置中添加如下代码即可。

    property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true");
    

    jersey.config.server.response.setStatusOverSendError

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-25
      • 2016-09-20
      • 1970-01-01
      • 2023-03-14
      • 2020-06-29
      • 2021-05-21
      • 1970-01-01
      相关资源
      最近更新 更多