请求和响应
Servlet最主要的作用就是处理客户端请求,并向客户端做出响应。为此,针对Servlet的每次请求,Web服务器在调用service()方法之前,都会创建两个对象,分别是HttpServletRequest和HttpServletResponse。
其中,HttpServletRequest用于封装HTTP请求消息,简称request对象。
HttpServletResponse用于封装HTTP响应消息,简称response对象。
request对象和response对象在请求Servlet过程中至关重要,接下来,通过一张图来描述浏览器访问Servlet的交互过程,如图所示
需要注意的是,在Web服务器运行阶段,每个Servlet都只会创建一个实例对象。然而,每次HTTP请求,Web服务器都会调用所请求Servlet实例的service(HttpServletRequest request,HttpServletResponse response)方法,重新创建一个request对象和一个response对象。
HttpServletResponse对象
在Servlet API中,定义了一个HttpServletResponse接口,它继承自ServletResponse接口,专门用来封装HTTP响应消息。由于HTTP响应消息分为状态行、响应消息头、消息体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码、响应消息头、响应消息体的方法
发送状态码相关方法
发送响应消息头相关的方法
发送相应消息体相关的方法
由于在HTTP响应消息中,大量的数据都是通过响应消息体传递的,因此,ServletResponse遵循以IO流传递大量数据的设计理念。在发送响应消息体时,定义了两个与输出流相关的方法,具体如下
- 1.getOutputStream()方法(字节流)
该方法所获取的字节输出流对象为ServletOutputStream类型。由于ServletOutputStream是OutputStream的子类,它可以直接输出字节数组中的二进制数据。因此,要想输出二进制格式的响应正文,就需要使用getOutputStream()方法。既然可以返回字节流,就可以返回字符流 - 2.getWriter()方法(字符流)
该方法所获取的字符输出流对象为PrintWriter类型。由于PrintWriter类型的对象可以直接输出字符文本内容,因此,要想输出内容全为字符文本的网页文档,需要使用getWriter()方法。但是图片等二进制文件无法输出
活学活用小案例1
login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>登录页面</h1>
<font color="red">用户或密码错误,请重新输入</font><br />
<form action="#" method="get">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" /></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="pwd" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" name="submit" value="登陆" />
</td>
</tr>
</table>
</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_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Review4</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>PrintServlet</servlet-name>
<servlet-class>PrintServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PrintServlet</servlet-name>
<url-pattern>/ps</url-pattern>
</servlet-mapping>
</web-app>
PrintServlet.java
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class PrintServlet
*/
public class PrintServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// 相应行相关的方法
// hangMethod(response);
// 相应消息头相关的方法
// headerMethod(response);
// 响应体相关方法
// 1.字节流对象
// streamMethod(response);
// 响应体相关方法
// 2.字符流向浏览器输出数据
PrintWriter pWriter = response.getWriter();
String valueString = "Rihood------33";
// pWriter.print(valueString);
pWriter.write(valueString);
}
private void streamMethod(HttpServletResponse response) throws IOException {
ServletOutputStream outputStream = response.getOutputStream();
String valueString = "Rihood";
outputStream.write(valueString.getBytes());
}
private void headerMethod(HttpServletResponse response) {
// 相应消息头相关的方法
// 1.设置状态码
response.setStatus(302);
// 2.设置相应头,完成重定向
response.setHeader("Location", "/Review4/login.html");
}
// 相应行相关的方法
private void hangMethod(HttpServletResponse response) throws IOException {
response.sendError(404, "Not exist!");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
全局配置:
调用行方法(调用发送错误信息的状态码及对应提示说明的文本信息)PrintServlet.java有效代码修改如下:
public class PrintServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// 相应行相关的方法
hangMethod(response);
// 相应消息头相关的方法
// headerMethod(response);
// 响应体相关方法
// 1.字节流对象
// streamMethod(response);
// 响应体相关方法
// 2.字符流向浏览器输出数据
// PrintWriter pWriter = response.getWriter();
// String valueString = "Rihood------33";
// pWriter.print(valueString);
// pWriter.write(valueString);
}
private void streamMethod(HttpServletResponse response) throws IOException {
ServletOutputStream outputStream = response.getOutputStream();
String valueString = "Rihood";
outputStream.write(valueString.getBytes());
}
private void headerMethod(HttpServletResponse response) {
// 相应消息头相关的方法
// 1.设置状态码
response.setStatus(302);
// 2.设置相应头,完成重定向
response.setHeader("Location", "/Review4/login.html");
}
// 相应行相关的方法
private void hangMethod(HttpServletResponse response) throws IOException {
response.sendError(404, "Not exist!");
}
运行结果:
调用消息头方法(设置状态码,设置相应头,完成重定向)PrintServlet.java有效代码修改如下:
public class PrintServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// 相应行相关的方法
// hangMethod(response);
// 相应消息头相关的方法
headerMethod(response);
// 响应体相关方法
// 1.字节流对象
// streamMethod(response);
// 响应体相关方法
// 2.字符流向浏览器输出数据
// PrintWriter pWriter = response.getWriter();
// String valueString = "Rihood------33";
// pWriter.print(valueString);
// pWriter.write(valueString);
}
private void streamMethod(HttpServletResponse response) throws IOException {
ServletOutputStream outputStream = response.getOutputStream();
String valueString = "Rihood";
outputStream.write(valueString.getBytes());
}
private void headerMethod(HttpServletResponse response) {
// 相应消息头相关的方法
// 1.设置状态码
response.setStatus(302);
// 2.设置相应头,完成重定向
response.setHeader("Location", "/Review4/login.html");
}
// 相应行相关的方法
private void hangMethod(HttpServletResponse response) throws IOException {
response.sendError(404, "Not exist!");
}
运行结果:
调用字节流方法,PrintServlet.java有效代码修改如下:
public class PrintServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// 相应行相关的方法
// hangMethod(response);
// 相应消息头相关的方法
// headerMethod(response);
// 响应体相关方法
// 1.字节流对象
streamMethod(response);
// 响应体相关方法
// 2.字符流向浏览器输出数据
// PrintWriter pWriter = response.getWriter();
// String valueString = "Rihood------33";
// pWriter.print(valueString);
// pWriter.write(valueString);
}
private void streamMethod(HttpServletResponse response) throws IOException {
ServletOutputStream outputStream = response.getOutputStream();
String valueString = "Rihood";
outputStream.write(valueString.getBytes());
}
private void headerMethod(HttpServletResponse response) {
// 相应消息头相关的方法
// 1.设置状态码
response.setStatus(302);
// 2.设置相应头,完成重定向
response.setHeader("Location", "/Review4/login.html");
}
// 相应行相关的方法
private void hangMethod(HttpServletResponse response) throws IOException {
response.sendError(404, "Not exist!");
}
运行结果:
调用字符流方法,PrintServlet.java有效代码修改如下:
public class PrintServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// 相应行相关的方法
// hangMethod(response);
// 相应消息头相关的方法
// headerMethod(response);
// 响应体相关方法
// 1.字节流对象
// streamMethod(response);
// 响应体相关方法
// 2.字符流向浏览器输出数据
PrintWriter pWriter = response.getWriter();
String valueString = "Rihood------33";
pWriter.print(valueString);
// pWriter.write(valueString);
}
private void streamMethod(HttpServletResponse response) throws IOException {
ServletOutputStream outputStream = response.getOutputStream();
String valueString = "Rihood";
outputStream.write(valueString.getBytes());
}
private void headerMethod(HttpServletResponse response) {
// 相应消息头相关的方法
// 1.设置状态码
response.setStatus(302);
// 2.设置相应头,完成重定向
response.setHeader("Location", "/Review4/login.html");
}
// 相应行相关的方法
private void hangMethod(HttpServletResponse response) throws IOException {
response.sendError(404, "Not exist!");
}
运行结果:
注:
在字符流方法中,可以调用print方法或者write方法,将想输出的字符文本内容输出到浏览器上
Attention!!!
虽然response对象的getOutputStream()和getWriter()方法都可以发送响应消息体,但是,它们之间互相排斥,不可同时使用,否则会发生IllegalStateException异常
解决中文乱码
字节流处理办法
可能乱码,但是我的没有乱码,所以不需要这个解决办法,但是这个解决办法还是可以了解一下
ChineseServlet.java
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;
/**
* Servlet implementation class ChineseServlet
*/
public class ChineseServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
String dataString = "中国加油";
// 让浏览器端的编码也是utf-8解码
response.setHeader("Content-Type", "text/html;charset=utf-8");
//response.setContentType("text/html;charset=utf-8"); 第二种也可解决
// 让服务器端的中文编码格式为utf-8编码
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(dataString.getBytes("utf-8"));
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
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_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Review4</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>PrintServlet</servlet-name>
<servlet-class>PrintServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PrintServlet</servlet-name>
<url-pattern>/ps</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>ChineseServlet</display-name>
<servlet-name>ChineseServlet</servlet-name>
<servlet-class>ChineseServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ChineseServlet</servlet-name>
<url-pattern>/cs</url-pattern>
</servlet-mapping>
</web-app>
全局配置:
运行结果如下:
字符流处理办法
肯定会有乱码,如下图
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_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Review4</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>PrintServlet</servlet-name>
<servlet-class>PrintServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PrintServlet</servlet-name>
<url-pattern>/ps</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>ChineseServlet</display-name>
<servlet-name>ChineseServlet</servlet-name>
<servlet-class>ChineseServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ChineseServlet</servlet-name>
<url-pattern>/cs</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>ChineseServlet2</display-name>
<servlet-name>ChineseServlet2</servlet-name>
<servlet-class>ChineseServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ChineseServlet2</servlet-name>
<url-pattern>/cs2</url-pattern>
</servlet-mapping>
</web-app>
ChineseServlet2.java
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;
/**
* Servlet implementation class ChineseServlet2
*/
public class ChineseServlet2 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// 处理服务器的编码,支持utf-8编码
response.setCharacterEncoding("utf-8");
// 处理浏览器的编码,支持utf-8解码
response.setHeader("Content-Type", "text/html;charset=utf-8");
//response.setContentType("text/html;charset=utf-8");第二种办法
String dataString = "中国";
PrintWriter pWriter = response.getWriter();
pWriter.print(dataString);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
全局配置:
运行结果:
In conclusion,还是response.setContentType(“text/html;charset=utf-8”);真香!!!
因为它最简单,两种类型的乱码都支持
定时跳转并刷新
核心代码:
response.setHeader("Refresh", "5;URL=/Review4/login.html");
参考文档中关于setHeader的功能介绍
refreshServlet.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class refreshServlet
*/
public class refreshServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
response.setHeader("Refresh", "5;URL=/Review4/login.html");
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
全局配置:
运行流程:
地址栏输入rs
过五秒后,地址跳转到login.html页面
refreshServlet.java
import java.io.IOException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class refreshServlet
*/
public class refreshServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// response.setHeader("Refresh", "5;URL=/Review4/login.html");
response.setHeader("Refresh", "5");
response.getWriter().print(new Date());
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
运行流程:
在地址栏输入rs
每隔五秒刷新一次