java - 在重定向到另一个链接之前打印文本
问题描述
我想在将我的响应重定向到谷歌搜索链接之前打印一些文本..但我无法打印它。我重定向 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>
解决方案
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 标头之前丢弃您的字符串。
推荐阅读
- javascript - 如何使用请求获取 Javascript 页面的完整 HTML 内容?
- python - 如何检查一个元素是否在子列表中,然后打印子列表
- json - Flutter 仅从响应中打印一个值
- cassandra - CassandraCQLUnit 给出空会话
- laravel - Laravel 推送器监听私人事件:错误 403 页面被禁止
- python - 在 TensorFlow2 中结合来自不同“网络”的梯度
- javascript - 如何在整个 div 上进行搜索过滤
- django - 具有唯一值或 null 的 Django MongoDB 模型字段
- reactjs - 使用组件独立地传递一些值和一个处理程序
- typescript - 打字稿泛型 - 声称没有继承属性的子类之一?