目录
一、HttpServlet
1、HttpServlet核心方法
2、Servlet的生命周期
二、HttpRequest
1、HttpRequest核心方法
2、代码示例
示例1:打印请求信息
示例2:获取GET请求中的query string
示例3:获取POST请求中的query string(form表单形式)
示例4:获取POST请求中的query string(json格式)
三、HttpResponse
1、HttpResponse核心方法
2、代码示例
示例1:自动刷新
示例2:重定向
一、HttpServlet
HttpServlet是我们写Servlet代码创建类时需要继承的父类。
1、HttpServlet核心方法
方法名称 | 调用时机 |
init | HttpServlet被实例化时调用一次 |
destroy | HttpServlet对象被销毁前调用一次 |
service | 每收到一个HTTP请求时调用一次 |
doGet | 收到GET请求时调用(由service方法调用) |
doPost | 收到POST请求时调用(由service方法调用) |
doPut/doDelete/doOptions…… | 收到其他对应请求时调用(由service方法调用) |
2、Servlet的生命周期
Servley的声明周期指的是Servlet从创建到销毁的过程:
(1) 当一个请求从HTTP服务器转发给Servlet容器时,容器会检查对应的Servley是否创建,如果没有创建就实例化该Servlet,并调用init()方法,inint()方法只调用一次,后续的请求都从第二步开始;
(2) Servlet每收到一个请求,就会调用一次service()方法,根据请求类型调用对应的方法,doGet、doPost等;
(3) Servlet销毁前调用一次destroy()方法进行清理操作,该方法只调用一次,随后JVM回收资源。
二、HttpRequest
Tomcat会把收到的HTTP请求按照HTTP协议的格式解析成一个HttpRequest对象。
1、HttpRequest核心方法
方法 | 描述 |
String getProtocol() | 返回请求协议的名称和版本 |
String getMethod() | 返回请求的HTTP方法名称 |
String getURI() | 返回URL中端口之后的部分 |
String getContextPath() | 返回请求的ContextPath |
String getQueryString() | 返回请求中的查询字符串(query string) |
Enumeration getParameterNames() | 返回query string中所有key的名称, 返回值类型是一个String对象的枚举 |
String getParameter(String name) | 返回query string中指定的key所对应的一个value, 如果key不存在则返回null |
String[] getParameterValues(String name) | 返回query string中指定的key所对应的所有value, 如果key不存在则返回null |
Enumeration getHeaderNames() | 返回HTTP请求头中所有的key, 返回值类型是一个String对象的枚举 |
String getHeader(String name) | 返回请求头中指定的key所对应的value |
String getCharacterEncoding() | 返回请求主体中使用的字符编码名称 |
String getContentType() | 返回请求主体中使用的数据类型, 如果不知道类型则返回null |
int getContentLength() | 以字节为单位返回请求主体的长度, 如果长度未知则返回-1 |
InputStream getInputStream() | 返回一个InputStream对象,用于读取请求的body内容 |
2、代码示例
示例1:打印请求信息
@WebServlet("/request")
public class RequestDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//指定响应的数据格式以及使用的字符集
resp.setContentType("text/html;charset=utf8");
StringBuilder sb = new StringBuilder();
//获取请求协议的名称和版本号
sb.append(req.getProtocol());
sb.append("<br>");//html的换行
//获取请求的方法名称
sb.append(req.getMethod());
sb.append("<br>");
//获取请求的URI和ContextPath
sb.append(req.getRequestURI());
sb.append("<br>");
sb.append(req.getContextPath());
sb.append("<br>");
//获取query string
sb.append(req.getQueryString());
sb.append("<br>");
//获取请求头中的键值对
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()){
//获取请求头中的key
String name = headerNames.nextElement();
//获取请求头中的value
String value = req.getHeader(name);
sb.append(name+": "+value);
sb.append("<br>");
}
resp.getWriter().write(sb.toString());
}
}
代码运行结果:
示例2:获取GET请求中的query string
@WebServlet("/getParameter")
public class GetParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//假设请求中有两个参数:id和name
String id = req.getParameter("id");
String name = req.getParameter("name");
System.out.println(id);
System.out.println(name);
resp.getWriter().write(id + ", " + name);
}
}
代码运行结果:
注意:要在服务器中显示指定响应的数据格式和字符集,否则浏览器可能无法正确识别响应内容。
resp.setContentType("text/html;charset=utf8");
设置好响应的数据格式和字符集后,再次查看代码运行结果:
示例3:获取POST请求中的query string(form表单形式)
@WebServlet("/getParameter")
public class GetParameterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//假设请求中有两个参数:id和name
String id = req.getParameter("id");
String name = req.getParameter("name");
System.out.println(id);
System.out.println(name);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write(id + ", " + name);
}
}
通过form表单构造一个POST请求:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="getParameter" method="post">
<input type="text" name="id">
<input type="text" name="name">
<input type="submit" value="提交">
</form>
</body>
</html>
代码运行结果:
可以看到,服务器这里打印的响应数据已经乱码了,说明服务器对请求的解析方式不正确,所以我们要给请求也设置字符集,告诉Servlet按照哪种编码来解析请求的body:
req.setCharacterEncoding("utf8");
再次查看代码运行结果:
示例4:获取POST请求中的query string(json格式)
为了能够解析JSON格式的数据,我们需要借助第三方库:jackson。
(1) 在Java中央仓库搜索jackson:
(2) 任意选择一个版本:
(3) 复制maven中的内容到pom.xml文件中的<dependencies>标签中:
jackson中最核心的类:ObjectMapper;
ObjectMapper中的核心方法:
方法 | 说明 |
readValue() | 把json格式数据转换为Java的对象 |
writeVauleAsString() | 把Java对象转换为json格式的字符串 |
获取json格式的数据:
class Parameter{
//1.用来接收json格式数据的类中的属性必须是public修饰的
// 或者必须提供public修饰的getter和setter方法
// 否则jackson无法访问这个类的属性
//2.必须要有一个无参版本的构造方法
//3.属性的类型和名称必须要和json中key的类型和名称一致
public int id;
public String name;
}
@WebServlet("/json")
public class GetJsonParameter extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//假设请求的body为:{"id": 10,"name": 张三}
//1.创建一个ObjectMapper对象
ObjectMapper objectMapper = new ObjectMapper();
//2.读取json格式的数据并转换为要解析的类的对象
//readValue第一个参数可以是字符串,也可以是输入流
//第二个参数是要解析的类的类对象
Parameter parameter = objectMapper.readValue(req.getInputStream(),Parameter.class);
System.out.println(parameter.id);
System.out.println(parameter.name);
//以json格式返回
resp.setContentType("application/json;charset=utf8");
resp.getWriter().write(objectMapper.writeValueAsString(parameter));
}
}
readValue的工作过程:
(1) 读取输入流,获取到要解析的字符串;
(2) 把字符串按照json格式解析为一组键值对;
(3) 根据类对象创建一个对应的实例;
(4) 遍历类对象的属性名,根据属性名(key)在刚才解析的键值对中寻找对应的值(value),并赋值给对应的属性;
(5) 返回构造完成的对象。
通过postman构造一个POST请求查看代码运行结果:
三、HttpResponse
Servlet中的doXXX方法会根据请求计算响应,并把响应的数据设置到HttpResponse对象中,然后Tomcat就会把这个HttpResponse对象按照HTTP协议的格式,转成一个字符串,并通过Socket写回给浏览器。
1、HttpResponse核心方法
方法 | 描述 |
void setStatus(int sc) | 设置响应的状态码 |
void setHeader(String name,String value) | 设置一个指定名称和值的响应头,如果name已存在, 则覆盖旧的值 |
void addHeader(String name,String value) | 设置一个指定名称和值的响应头,如果name已存在, 不会覆盖旧的值,添加新的键值对 |
void setContentType(String type) | 设置被发送的客户端的响应的数据格式 |
void setCharacterEncoding(String charset) | 设置被发送到客户端的响应的字符编码 |
void sendRedirect(String location) | 使用指定的重定向位置URL发送临时重定向响应到客户端 |
PrintWriter getWriter() | 用于往body中写入文本格式数据 |
OutPutStream getOutPutStream() | 用于往body中写入二进制格式数据 |
2、代码示例
示例1:自动刷新
实现一个程序,让浏览器每2s自动刷新一次,并显示时间戳:
@WebServlet("/autoRefresh")
public class AutoRefreshServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通过设置HTTP响应报头中的refresh字段,可以控制浏览器自动刷新的时机
resp.setHeader("refresh","2");
//返回当前的时间戳
resp.getWriter().write(System.currentTimeMillis()+"");
}
}
抓包结果:
示例2:重定向
实现一个程序,返回一个重定向HTTP响应,自动跳转到搜狗主页:
方式一:通过设置状态码和响应头中的Location字段:
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//收到请求时跳转到搜狗主页
resp.setStatus(302);
resp.setHeader("Location","https://www.sogou.com");
}
}
抓包结果:
方式二:通过调用sendRedict方法重定向
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//收到请求时跳转到搜狗主页
// resp.setStatus(302);
// resp.setHeader("Location","https://www.sogou.com");
resp.sendRedirect("https://www.sogou.com");
}
}
抓包结果: