首页 > 解决方案 > 在重定向到另一个链接之前打印文本

问题描述

我想在将我的响应重定向到谷歌搜索链接之前打印一些文本..但我无法打印它。我重定向 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();
        
    }
    

}

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>

标签: javaservlets

解决方案


sendRedirect正在向浏览器发送像 302 或 304 (我假设是 302 临时重定向)这样的响应代码,以及一个Location告诉客户端去哪里的标头。然后由浏览器透明地处理,而无需显示任何内容。

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

或者,您可以将重定向 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>

为什么我不能打印,如果我在将 PrintWriter 重定向到谷歌链接后关闭它?

我将首先从另一个方向开始,在调用之前冲洗/关闭sendRedirect

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

一旦您使用 刷新 Writer out.flush(),或者out.close()Tomcat 必须选择要写入 HTTP 响应的标头,因为它们必须位于正文之前。像这样:

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

Hello World

请参阅此处,在输出缓冲区的第一次刷新时。它发送标头,然后将响应设置为 commit

这是响应committed与您的堆栈跟踪一样的情况。此时您无法更改标题或状态代码。因此,没有回头路并更改为 302。

当您sendRedirect在第一次刷新之后调用时,如果由于上述原因提交了响应,则会失败并出现错误。

如果您采用另一种方式并打印到内存缓冲区,请不要刷新然后调用sendRedirect,它所做的第一件事就是重置输出缓冲区。在继续发送状态代码和 Location 标头之前丢弃您的字符串。


推荐阅读