Jersey 如何确定应用程序的基本 URI?

How does Jersey determine the base URI of an application?

我在 tomcat 中有一个 java 应用程序 运行。在应用程序的一个端点中,我想 return 类型为 See-Other 的 HTTP 响应。

@GET
@Path("logout")
@Produces(MediaType.TEXT_HTML)
public Response logOut(@Context HttpServletRequest request) throws URISyntaxException {
    // logout logic omitted
    Response.ResponseBuilder response = Response.seeOther(new URI("../jsp/login.jsp"));
    return response.build();
}

当我在本地机器上测试时,一切正常。然而,在生产系统上,jersey 似乎无法从相对路径“../jsp/login.jsp”解析正确的主机名。尽管主机名为 myhost,但相对路径被解析为 http://localhost:7080/myapplication/jsp/login.jsp.

new URI("../jsp/login.jsp") returns 一个对象,其中所有字段都是空的,只有 path="../jsp/login。 jsp”。因此,行为的根源必须在响应 class 中。我检查了文档并发现 Response.seeOther 调用了 Response.location 方法。文档指出

If a relative URI is supplied it will be converted into an absolute URI by resolving it relative to the base URI of the application

有谁知道 Jersey 如何确定应用程序的基本 URI?是不是tomcat里面有什么配置文件或者是我设置的环境变量错了?

应用程序的基本 URI 是使用 HttpServletRequest object 的属性计算的,其形式为:

<scheme>://<serverName>:<serverPort>/<contextPath><servletPath>/

<serverName><serverPort> 通常由 HTTP 客户端提供,其余由 Tomcat 或您的应用程序配置修复:

  • <scheme>使用<Connector>的同名属性配置(参见Tomcat's documentation) or can be set by the RemoteIpValve (cf. documentation),
  • <serverName> 由 HTTP 客户端提供,但可以使用连接器的 proxyName 属性覆盖,
  • <serverPort> 由 HTTP 客户端提供,但可以使用连接器的 proxyPort 属性或 RemoteIpValve
  • 覆盖
  • <contextPath> 取决于您部署应用程序的方式(例如,它取决于 webapps 目录中 WAR 文件的名称),
  • <servletPath>web.xml描述符或通过@ApplicationPath注解配置。

您的生产环境中可能发生的情况是 Tomcat 在 反向代理 后面。要在这种情况下正确配置基本 URI,您有两种选择:

  1. <Connector>
  2. 上静态配置 schemesecureproxyNameproxyPort 的正确值
  3. 使用RemoteIpValve并配置代理服务器发送原Hostheader并添加X-Forwarded-ForX-Forwarded-Protoheader s.

如果您的代理将不同类型的请求转发给 Tomcat(例如 HTTP 和 HTTPS 请求),RemoteIpValve 是您唯一的选择。

备注:如果将ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231属性设置为true,base URI也可以基于请求URI:cf . this question.