代码的行为是正确的,因为您说您的重定向视图url在上下文上是相对的,但是它是一个有效的url,因此spring将它构建为一个url,/my/page.html不是一个有效的url。说的问题是,你应该配置全双工方式重写的url,并在反向代理中解决这个问题,事实上,对于代码来说,如果它运行在一个服务于80端口的服务器上,那么代码会将你的url映射到80上,否则你应该像下面这样手工编写url:
@RequestMapping(method = RequestMethod.GET, value = "/")
public RedirectView localRedirect()
{
final RedirectView redirectView = new RedirectView();
redirectView.setUrl("http://localhost:8080/my/index.html");
redirectView.setHosts();
return redirectView;
}
我试图在我的PC上运行两个应用程序实例,一个在80上运行,另一个在8080上运行,重定向工作正常
更新:
当您使用redirectview时,重定向会在服务器端与httpservletresponse.sendrirect调用一起发生,当然,如果您的服务器位于反向代理之后,您的服务器端应用程序将无法知道它。
当您在控制器中使用set location header时,它是一个普通字符串,不会从您的servlet环境中传递。重定向发生在浏览器中,在这种情况下会收到一个相对url,因为在控制器中设置了一个纯字符串,而浏览器已经知道已经被代理的服务器。
更新2
RedirectView类的核心逻辑是一个名为sendRedirect(…)的受保护方法。
/**
* Send a redirect back to the HTTP client
* @param request current HTTP request (allows for reacting to request method)
* @param response current HTTP response (for sending response headers)
* @param targetUrl the target URL to redirect to
* @param http10Compatible whether to stay compatible with HTTP 1.0 clients
* @throws IOException if thrown by response methods
*/
protected void sendRedirect(HttpServletRequest request, HttpServletResponse response,
String targetUrl, boolean http10Compatible) throws IOException {
String encodedURL = (isRemoteHost(targetUrl) ? targetUrl : response.encodeRedirectURL(targetUrl));
if (http10Compatible) {
HttpStatus attributeStatusCode = (HttpStatus) request.getAttribute(View.RESPONSE_STATUS_ATTRIBUTE);
if (this.statusCode != null) {
response.setStatus(this.statusCode.value());
response.setHeader("Location", encodedURL);
}
else if (attributeStatusCode != null) {
response.setStatus(attributeStatusCode.value());
response.setHeader("Location", encodedURL);
}
else {
// Send status code 302 by default.
response.sendRedirect(encodedURL);
}
}
else {
HttpStatus statusCode = getHttp11StatusCode(request, response, targetUrl);
response.setStatus(statusCode.value());
response.setHeader("Location", encodedURL);
}
}
方法首先检索url,然后如果http10compatible为true,则最终将使用response.sendRedirect(encodeDurl);否则只需将相对url放在location头中,而不传递ServletAPI。在您的代码中,您没有为active the if条件提供数据,该条件阻止了servlet api的sendRedirect。这可以解释为什么在代码中有问题。当然,在任何其他代码分支中:http10compatible at false等等,您的代码只需在location header中放置一个字符串,它就可以工作,因为在您的浏览器中,执行重定向的会到达一个相对的url。
如果这是一个Servlet API的错误,我可以把官方接口代码:
httpservletresponse.java:
/**
* Sends a temporary redirect response to the client using the specified
* redirect location URL. This method can accept relative URLs; the servlet
* container must convert the relative URL to an absolute URL before sending
* the response to the client. If the location is relative without a leading
* '/' the container interprets it as relative to the current request URI.
* If the location is relative with a leading '/' the container interprets
* it as relative to the servlet container root.
* <p>
* If the response has already been committed, this method throws an
* IllegalStateException. After using this method, the response should be
* considered to be committed and should not be written to.
*
* @param location
* the redirect location URL
* @exception IOException
* If an input or output exception occurs
* @exception IllegalStateException
* If the response was committed or if a partial URL is given
* and cannot be converted into a valid URL
*/
public void sendRedirect(String location) throws IOException;
您可以阅读评论片段:
This method can accept relative URLs; the servlet
* container must convert the relative URL to an absolute URL before sending
* the response to the client
阅读本文,我可以说这不是一个bug,而是ServletAPI的一个特性,但是它把唯一知道自身的服务器主机放在了这里,因此它不能与反向代理一起工作。
我希望这能很好地解释这个问题。