在Spring中使用没有端口号的ServletUriComponentsBuilder构建URL

时间:2014-02-01 07:49:46

标签: spring spring-mvc

我在我的服务类中使用ServletUriComponentsBuilder来构建一些URL,但问题是它还包含端口号以及servlet容器运行的位置,当我在生产后面的生产中部署我的应用程序时,这是一个问题代理服务器应该只在端口80上运行

我正在使用的代码是:

String sUri = ServletUriComponentsBuilder.fromCurrentContextPath().path("/student/edit/" + st.getId()).build().toUriString();

虽然我在JSP中使用的c:url工作得非常好,但它不包含端口号。 ServletUriComponentsBuilder是否还有任何方法可以检测是否需要包含端口号。

表示如果应用程序在端口8080上启动,那么它可以包含端口号,但是当从端口80访问应用程序时,则不包括?

发生了什么:如果我的tomcat在端口8080上运行,而我有代理服务器在端口80上提供请求,但由ServletUriComponentsBuilder构建的网址仍然在主机之后附加端口8080,我需要它是80

2 个答案:

答案 0 :(得分:1)

这是此方法的错误:

public static ServletUriComponentsBuilder fromRequest(HttpServletRequest request) {
    String scheme = request.getScheme();
    int port = request.getServerPort();
    String host = request.getServerName();

    String header = request.getHeader("X-Forwarded-Host");

    if (StringUtils.hasText(header)) {
        String[] hosts = StringUtils.commaDelimitedListToStringArray(header);
        String hostToUse = hosts[0];
        if (hostToUse.contains(":")) {
            String[] hostAndPort = StringUtils.split(hostToUse, ":");
            host  = hostAndPort[0];
            port = Integer.parseInt(hostAndPort[1]);
        }
        else {
            host = hostToUse;
        }
    }

    ServletUriComponentsBuilder builder = new ServletUriComponentsBuilder();
    builder.scheme(scheme);
    builder.host(host);
    if ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443)) {
        builder.port(port);
    }
    builder.pathFromRequest(request);
    builder.query(request.getQueryString());
    return builder;
}

如果X-Forwarded-Host被填满,并且没有端口,因为我们在80端口。但是其他

else {
    host = hostToUse;
}

所以这种情况是一种混合的情况,其中主机是从X-Forwarded-Host值中读取的,但是直接从请求中读取端口(并且它是apache用来调用tomcat的请求)。 我们正在这里解决这个问题并且找不到任何替代方法来编写新的UriComponentsBuilder(好吧......也许是juste扩展!)

答案 1 :(得分:0)

看看ServletUriComponentsBuilder#fromRequest

String scheme = request.getScheme();
int port = request.getServerPort();
String host = request.getServerName();

String header = request.getHeader("X-Forwarded-Host");

if (StringUtils.hasText(header)) {
    String[] hosts = StringUtils.commaDelimitedListToStringArray(header);
    String hostToUse = hosts[0];
    if (hostToUse.contains(":")) {
        String[] hostAndPort = StringUtils.split(hostToUse, ":");
        host = hostAndPort[0];
        port = Integer.parseInt(hostAndPort[1]);
    }
    else {
        host = hostToUse;
     }
}
....

特别是

String header = request.getHeader("X-Forwarded-Host");

会做到这一点。您所要做的就是在代理服务器中设置X-Forwarded-Host并开始使用 ServletUriComponentsBuilder#fromRequest 而不是 ServletUriComponentsBuilder#fromCurrentContextPath 。您的网址应包含您的公共代理主机名,不包含端口。