在重定向到另一个之前打印文本 link

Printing Text before redirecting to another link

我想在将我的响应重定向到 google 搜索 link 之前打印一些文本。但是我无法打印 it.My 重定向 servlet 的代码如下:

package sendredirect;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SendRedirectServlet extends HttpServlet {

    
    private static final long serialVersionUID = 1L;
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


        resp.setContentType("text/html");
        
        PrintWriter out = resp.getWriter();
        out.println("Hello World");
        
        try {
            
            Thread.sleep(5000);
            
        } catch (InterruptedException e) {
            
            e.printStackTrace();
            
        }
        
        String textToSearch = req.getParameter("textToGoogle");
        
        resp.sendRedirect("https://www.google.com/search?q="+ textToSearch);  
        
        out.close();
        
    }
    

}

为什么我无法在重定向到 google 搜索之前在浏览器中获取代码 out.println("Hello World"); 的输出。

我的index.html文件如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Send Redirect Example</title>
</head>
<body>
<form action="sr" method="GET">
    <input type="text" name="textToGoogle"><br>
    <input type="submit" value="Google It!">
</form>
</body>
</html>

我的 web.xml 文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>ServletSendRedirect</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
        <servlet-name>SR</servlet-name>
        <servlet-class>sendredirect.SendRedirectServlet</servlet-class>
  </servlet>
  
  
  <servlet-mapping>
        <servlet-name>SR</servlet-name>
        <url-pattern>/sr</url-pattern>
  </servlet-mapping>
  
  
</web-app>

sendRedirect 正在向浏览器发送响应代码,例如 302 或 304(我假设是 302 临时重定向),并且 Location header 告诉客户端去哪里。然后由浏览器透明地处理,而无需显示任何内容。

要亲自查看 HTTP 响应,请使用 curl -v http://yourendpoint,或者如果您更喜欢基于浏览器的工具,请使用 Postman。或者您可以查看浏览器开发工具中的 request/response,在网络选项卡下(您可能必须找到一个不会在页面加载时清除检查器历史记录的选项)。

或者,您可以将重定向 url 传递给页面,稍后使用 javascript 进行重定向。

您可以用这样的方式响应,显示页面并在 3 秒后重定向:

<html>
  <body>
    Hello there, redirecting soon
    <script type="application/javascript">
      setTimeout(function() {
        window.location.href = "https://www.google.com/search?q=dogs";
      }, 3000); 
    </script>
  </body>
</html>

Why couldn't I print, If i close the PrintWriter after redirecting it to google link?

我会先从另一个方向开始,flushing/closing 然后调用 sendRedirect

当您调用 out.println("Hello World"); 时,tomcat 将“Hello World”写入 OutputBuffer here,它存储在内存中直到被刷新。此时您仍然可以使用 resp.setStatus(201); 之类的方式更改响应代码,因为尚未将任何内容发送回客户端。

一旦您使用 out.flush()out.close() 刷新 Writer,Tomcat 必须选择 Headers 写入 HTTP 响应,因为它们必须来在 body 之前。像这样:

HTTP/1.1 200 
Content-Type: text/html;charset=ISO-8859-1
Date: Mon, 14 Jun 2021 02:05:46 GMT

Hello World

参见 here, on the first flush of the output buffer. It sends headers, which then sets the response to committed

这是在您的堆栈跟踪中响应为 committed 的时候。此时您无法更改 header 或状态代码。所以没有回头更改为 302。

当您在第一次刷新后调用 sendRedirect 时,如果由于上述原因提交响应,则它 fails with error

如果你走另一条路打印到 in-memory 缓冲区,不要刷新然后调用 sendRedirect,它做的第一件事就是 reset the output buffer. Discarding your string before it proceeds to send the status code and Location header.