一、响应对象的概述
WEB服务器会针对每一个客户端发出的HTTP请求,分别的创建一个请求对象和一个响应对象。如果需要向客户端发送一些数据,需要使用响应对象。
在之前的文章中,作者介绍了HTTP协议响应的组成,主要包括三个部分:响应行、响应头、响应体。这里不再过多介绍,重点介绍一下响应行中的响应码:
- 1XX:浏览器发送的请求信息不完善,需要浏览器进一步补充资料
- 2XX:响应正常完成
- 3XX:本次请求已经完成,但是需要浏览器进行进一步的操作
- 4XX:请求的资源错误
- 5XX:服务器端错误
二、向客户端发送中文的乱码问题
1、原因
我们在向客户端发送英文时,没有出现任何的问题,但是发送中文时,会出现乱码问题:
response.getWriter().println("你好");
中文乱码问题
为什么会出现这种情况呢?
我们通过调用响应对象的方法查看服务器发送数据的默认编码
String encoding = response.getCharacterEncoding();
response.getWriter().println(encoding);
服务器发送数据默认编码
而浏览器接收数据默认的编码格式为GBK,发送数据和接收数据的编码不一致,导致出现乱码问题。
2、解决方式
(1)字节流传输数据的解决方式
我们可以通过调用响应对象获取字节输出流对象,调用write方法传输数据,由于字节输出流的默认编码就是GBK,所以不会出现乱码问题
package com.demo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Demo4 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletOutputStream os = response.getOutputStream();
os.write("你好".getBytes());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
字节流传输数据
(2)字符流传输数据的解决方式
使用字符流传输数据,我们需要告诉浏览器使用什么方式进行解码。
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Demo4 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("你好");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
字符流传输数据
三、响应头Refresh
我们在访问文字直播网站的时候,经常能够发现网页每隔一段时间就会自动刷新;或者有时候支付宝在完成支付后,会有一个几秒后跳转回商家的提示页面,这些都可以用Refresh来实现。
Refresh的作用:
- 定时自动刷新
response.setHeader("Refresh", 时间);
示例:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Demo7 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("3秒后自动刷新!");
response.setHeader("Refresh", "3");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
定时自动刷新
- 定时自动跳转
跳转外部资源:response.setHeader("Refresh", "3;URL=https://www.baidu.com");
跳转内部资源:response.setHeader("Refresh", "3;URL=/demo/Demo4")
示例:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Demo7 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("3秒后自动跳转到百度首页!");
response.setHeader("Refresh", "3;URL=https://www.baidu.com");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
跳转前
跳转后
跳转与转发的区别:
- 转发:
共享请求和响应对象
只能是内部地址
地址栏不会发生变化 - 跳转:
不共享
内部地址和外部地址都可以
地址栏会发生变化
四、请求重定向
一个WEB资源接收到客户端的请求之后,通知这个客户端去访问(请求)另外的一个WEB资源。
示例:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Demo8 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("/demo/Demo4");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
请求重定向1
请求重定向2
转发和重定向的区别:
- 请求次数:
转发:一次请求一次相应
重定向:两次请求两次响应 - 浏览器的地址:
转发:地址栏保持初值不会改变
重定向:改变为重定向的页面 - 作用范围:
转发:只能是同一个项目的页面
重定向:可以定向任意的页面,内部页面或者外部页面 - URL以“/”开头的含义不同
转发:代表当前web应用的根路径
重定向:代表web服务器的根路径,重定向内部页面必须加上项目名 -
变量的作用域:
转发:request存放的变量不会失效(request域对象)
重定向:request存放的变量失效,进入了一个新的request域。
转发-包含-重定向的区别
五、文件下载案例
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Demo9 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置响应头
response.setHeader("content-disposition", "attachment;filename=tomcat.png");
// 获取字节输出流对象
ServletOutputStream os = response.getOutputStream();
// 创建字节输入流对象
String path = getServletContext().getRealPath("/WEB-INF/tomcat.png");
FileInputStream fis = new FileInputStream(path);
//循环读取并向客户端发送数据
int len = 0;
byte[] bys = new byte[1024];
while((len = fis.read(bys)) != -1){
os.write(bys,0,len);
}
//释放资源
fis.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
下载文件1
下载文件2
注意:
响应头中不能有中文,中文被认为是不安全的字符。如果必须有中文,那么需要将中文转义为UTF-8编码。
String s = URLEncoder.encode("美女.jpg");
response.setHeader("Content-disposition", "attachment;filename=" + s);
网友评论