《Java Web程序设计任务教程》简要复盘:第四章 请求与响应
作者:氯磷Rolin
目录:
- 第一章:网页开发基础(无)
- 第二章:Java Web概述
- 第三章:Servlet基础
- 第四章:请求与响应
- 第五章:会话及其会话技术
- 第六章:JSP技术
- 第七章:EL表达式和JSTL
- 第八章:Servlet的高级特性
- 第九章:JDBC
- 第十章:数据库连接池与DBUtils工具
- 第十一章:JSP开发模型
- 第十二章:文件的上传和下载
第四章:请求与响应
Servlet最主要的作用就是处理客户端请求,并向客户端做出响应。
为此,针对Servlet的每次请求,Web服务器在调用service()之前都会先创建请求(HttpServletRequest)和响应(HttpServletRespone)两个对象,用于封装HTTP请求和响应消息
上图则描述了浏览器访问Servlet的交互过程
需要注意的是,在Web服务器运行阶段,每个Servlet只会创建一个实例对象。
然而针对每次HTTP请求,Web服务器都会调用所请求的Servlet实例的service(HttpServletRequest request ,HttpServletResponse response)
,重新创建一个request对象和一个response对象。
易混:
Servlet只有一个实例,init()和destroy()也都只能调用一次
但是中间的service()却能调用多次,每调用一次就会新建一对request && response对象
HttpServletResponse
在Servlet API中,定义了一个HttpServletResponse接口,专门用来封装HTTP消息。
由于HTTP消息分为状态行,响应消息头和消息体三部分,因此该接口分别定义了三种对应的方法
对象
状态码相关方法
当Servlet向客户端回送响应消息时,需要在响应消息中设置状态码。为此,在HttpServletResponse接口中,定义了两个发送状态码的方法
- setStatus(int status)方法
- 只要通过setStatus(int status)方法设置状态码即可
- 正常情况下,Web服务器会默认产生一个状态码为200的状态行
- sendError(int sc)方法
- 该方法用于发送表示错误信息的状态码。例如:404状态码表示找不到客户端所请求的资源
- 在response对象中提供了如下两个重载的sendError(int sc)方法,第一个方法只是发送错误信息的状态码,而第二个方法可以附带一条说明的文本信息,该文本信息将出现在发送给客户端的正文内容中
public void sendError(int code) throws java.io.IOException
public void sendError(int code,String message) throws java.io.IOException
响应头相关方法
当Servlet向客户端发送响应消息时,由于HTTP协议的响应头字段有很多种,为此在HttpServletResponse接口中,定义了一些设置HTTP响应头字段的方法
方法声明 | 功能描述 |
---|---|
void addHeader(String name , String value) | 增加同名的响应头字段参数 |
void setHeader(String name , String value) | 覆盖同名的响应头字段参数 |
void addIntHeader(String name , int value) | 用于设置包含整数值的响应头,增加同名的响应头字段参数 |
void setIntHeader(String name , int value) | 用于设置包含整数值的响应头,覆盖同名的响应头字段参数 |
void setContentLength(int len) | 用于设置响应消息的实体内容大小,具体通过设置Content-Length响应头字段的值实现 |
void setContentType(String type) | 设置Servlet输出内容的MIME类型,如果内容为文本,则还可以附带字符编码,如text/html;charset=UTF-8 |
void setLocale(Locale loc) | 用于设置响应消息本地化信息,指定了Content-Length和Content-Type的字符集编码 |
void setCharacterEncoding(String charset) | 用于设置输出内容的字符编码,优先权比上述可设置字符编码的优先级高,他的结果将覆盖上述字符编码 |
响应消息体的相关方法
由于在HTTP响应消息中,大量的数据都是通过响应消息体传递的,因此ServletResponse遵循以IO流传递大量数据的设计理念。
- getOutputStream()方法
该方法所获取的字节输出流对象为ServletOutputStream类型,属于OutputStream的子类,它可以直接输出字节数组中的二进制数据,所以想要输出二进制格式的响应正文,就需要使用该方法 - getWriter()方法
该方法获取的字符输出流对象为PrintWriter类型。因此想要输出内容全为字符文本的网页文档,则需要使用该方法
※虽然 response 对象的 getOutputStream()和 getWriter()都可以发送响应消息体,但是它们两个相互排斥,不可同时使用,否则会发生IllegalStateException异常。
- 例如下图则是在Servlet中调用response.getWriter()之前已经调用了response.getOutputStream()方法
package com.Rolin.ttt;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/abc")
public class Servlet extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
doGet(request,response);
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
response.getOutputStream();
response.getWriter();
}
}
应用
1. 解决中文输出乱码问题
由于浏览器默认使用UTF-8码表进行编码,而servlet使用ISO-8859-1码表进行编码,传输和接收方编码不一致导致乱码的产生。
- 解决方法:
response.setHeader("content-type", "text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
第一句目的是为了指定浏览器以UTF-8码表打开服务器发出的数据
第二句目的是设置response使用的码表,控制response以UTF-8码表向浏览器写入数据(必须写在方法中第一行)
- 亦或者:使代码更加简洁
//包含第一种方式的两个功能
response.setContentType("text/html;charset=utf-8")
- 再或者:通过字节流向浏览器写入meta标签控制浏览器使用的码表
OutputStream out=response.getOutputStream();
out.write("<metahttp-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());
2.网页定时刷新并跳转
在web开发中,有时候会遇到定时跳转页面的需求。在HTTP协议中,定义了一个Refresh头字段,它可以通知浏览器在指定的时间内自动刷新并跳转到其他页面。
只需要将Refresh写入响应的头字段中即可实现
- 实现方式:
//5秒后刷新当前页面
response.setHeader("Refresh","5");
//2秒后刷新并跳转至B站首页
response.setHeader("Refresh","2;URL=http://www.bilibili.com");
3.实现请求重定向
在某些情况下,针对客户端的请求,一个Servlet类可能无法完成全部工作,这时可以使用请求重定向来完成。
请求重定向,指的就是Web服务器接收到客户端的请求后,可能由于某些条件的限制,服务器指定了一个新的资源路径,让客户端重新发送请求
- sendRedirect()方法声明如下:
public void sendRedirect(String location) throws IOException
其中参数location可以使用相对路径,也可以使用绝对路径,Web服务器会自动将相对URL翻译成绝对URL,再生成Location头字段
- sendRedirect()的工作原理
- 具体实现:
public void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");