1. 什么是Servlet
Servlet是TomCat提供给程序员的一组API,帮助程序员简单高效的开发一个Web app.
Servlet 主要做的工作:
- 允许程序猿注册一个类, 在 Tomcat 收到某个特定的 HTTP 请求的时候, 执行这个类中的一些代码.
- 帮助程序猿解析 HTTP 请求, 把 HTTP 请求从一个字符串解析成一个 HttpRequest 对象.
- 帮助程序猿构造 HTTP 响应. 程序猿只要给指定的 HttpResponse 对象填写一些属性字段, Servlet 就会自动的安装 HTTP 协议的方式构造出一个 HTTP 响应字符串, 并通过 Socket 写回给客户端.
2. 创建一个Servlet程序
1. 创建项目 (Maven)
new project ——> 选择Maven ,即可创建一个Maven项目
项目的目录结构:
2. 引入依赖
这里引入的依赖就是写Servlet程序需要的依赖(Servlet的 jar 包)。
之前在JDBC变成时,引入mysql的驱动包时手动导入,这里我们依赖maven来实现自动导入
- 在 https://mvnrepository.com/ 找到servlet,然后选择3.1.0版本
- 选中这一串1内容,将其拷贝到pom.xml文件中
注意:第一次使用会有如下标红
一般会自动下载,如果没有自动下载,那就点击如下刷新按钮:
3. 创建一些新目录
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
4. 编写代码
- 创建HelloServlet,继承HttpServlet
- 构造响应
- 注意:
5. 打包
此时打成的包是一个jar包,但是Tomcat只能识别war包,所以要打成war包。此时就得修改pom.xml,让打成的包是一个war包
<packaging>war</packaging>//打成war包
<build>
<finalName>hello_servlet</finalName>//打成的包名叫做hello_servlet
</build>
此时就会形成一个war包:
6. 部署
将刚才打成的war包拷贝到Tomcat的webapp当中
- 打开war目录复制war
- 粘贴到Tomcat的webapp,然后启动Tomcat
7. 验证程序
执行结果:
URL分析:
3. 简化创建Servlet的步骤
上述的7个步骤中,1 ~ 3在一个项目中操作一次就行了,而5 ~ 7在每次修改代码之后,都得进行一遍。所以,我们就从5 ~ 7入手进行简化。
1. 安装plugin插件——Smart Tomcat
Smart Tomcat的功能就是在idea中调用Tomcat。
安装之后,启动Tomcat就不需要找到Tomcat脚本来启动,直接在idea中就直接可以启动。
安装后进行重启。
2. Smart Tomcat的使用
4. Servlet API详解
1. HttpServlet
我们写 Servlet 代码的时候, 首先第一步就是先创建类, 继承自 HttpServlet, 并重写其中的某些方法.
我们实际开发的时候主要重写 doXXX 方法, 很少会重写 init / destory / service
1. 如何构造一个post请求
在前面,我们王浏览器中之家输入一个URL构造的都是get请求,下面我们看看怎么构造一个post请求:
- form表单(只支持get和post)
- ajax
这里我们采用ajax构造一个get请求:
- 创建一个html文件(注意文件目录的位置)
- 写html代码
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<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>
<div>
</div>
<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
<script>
$.ajax({
type:'post',
url:'hello',
success:function(body){
console.log(body);
}
});
</script>
</body>>
</html>
- 测试请求
2. 利用Postman构造请求
【面试】谈谈HttpServlet的生命周期
这个主要考查的就是啥时机调用啥方法
- 首次使用,先调用一次init
- 每次收到请求,调用service,在service内部通过方法来决定调用哪个doXXX
- 销毁之前调用destroy
2. HttpServletRequest
当 Tomcat 通过 Socket API 读取 HTTP 请求(字符串), 并且按照 HTTP 协议的格式把字符串解析成HttpServletRequest 对象.
1. 核心方法
2. 测试代码:
@WebServlet("/showRequest")
public class ShowRequestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//调用一下RequestServlet里面的常用方法
//把调用的结果显示到页面上
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(req.getProtocol());
stringBuilder.append("<br>");
stringBuilder.append(req.getMethod());
stringBuilder.append("<br>");
stringBuilder.append(req.getRequestURI());
stringBuilder.append("<br>");
stringBuilder.append(req.getContextPath());
stringBuilder.append("<br>");
stringBuilder.append(req.getQueryString());
stringBuilder.append("<br>");
Enumeration<String> headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements()){
String name=headerNames.nextElement();
stringBuilder.append(name+":"+req.getHeader(name));
stringBuilder.append("<br>");
}
resp.setContentType("text/html; charset=utf-8");//让浏览器知道body的数据格式是啥
resp.getWriter().write(stringBuilder.toString());
}
}
运行结果:
3. 注意事项:
2.
两者之间的先后顺序不能乱
3. 传参的方式
1. 通过query string传参
@WebServlet("/studentInfo")
public class StudentInfoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//假设客户端发来的请求形如:/studentInfo?studentId=104&studentId=20
//就可以通过getParameter方法拿到两个Id的值
String queryString = req.getQueryString();
System.out.println(queryString);
//getParameter方法的效果就是拿到queryString中的键值对
String classId=req.getParameter("classId");
String studentId=req.getParameter("studentId");
System.out.println("classId: "+classId + " studentId: "+studentId);
resp.getWriter().write("classId: "+classId + " studentId: "+studentId);
}
}
运行结果:
2. 通过post请求的body传参(格式为x-www-from-urlencoded)
代码:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
//获取到body中的参数
//约定 body 使用 application/x-www-from-urlencoded 这种格式来传参
//这个格式就相当于calssId=104&studentId=20
//这个格式和query string相同,只是数据在body中
String classId = req.getParameter("calssId");
String studentId = req.getParameter("studentId");
System.out.println("classId: "+classId + " studentId: "+studentId);
resp.getWriter().write("classId: "+classId + " studentId: "+studentId);
}
postman构造post请求:
运行结果:
3. 利用form标签
创建文件:
代码展示:
<!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>通过form构造请求</title>
</head>
<body>
<form action="studentInfo" method="post">
<input type="text" name="classId">
<input type="text" name="studentId">
<input type="submit" name="提交">
</form>
</body>
</html>
浏览器访问:
利用fiddler抓包:
4. 构造JSON格式的HttpServletResponse
问题分析:
Jackson下载安装:
将下面得代码复制到pom.xml并刷新:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.4.1</version>
</dependency>
核心代码(将json转换成字符串):
//这里属性得名字,应该与 json 的key保持一致
//这里的属性是public或者提供的public的getter方法
class Student{
public int classId;
public int studentId;
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理JSON格式的请求
ObjectMapper objectMapper = new ObjectMapper();
//从请求的body中进行读取,并解析
//使用 readValue 来吧json字符串转称java对象
//第一个参数是一个 String 或者是一个InputStream
//第二个参数是转换的结果对应得 Java类对象
Student student=objectMapper.readValue(req.getInputStream(),Student.class);
System.out.println(student.classId+","+student.studentId);
resp.getWriter().write(student.classId+","+student.studentId);
}
运行结果:
方法总结:
objectMapper.readValue()——把json字符串转成java对象
objectMapper.writeValue()——把java对象转成json字符串
3. HttpServletResponse
0. HttpServletResponse的核心方法
1. 设置状态码
以404为例
@WebServlet("/status")
public class StatusCodeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setStatus(404);
}
}
运行结果:
抓包结果:
2. 自动刷新
自动刷新就是给报文header设置Refresh属性,设置的value值就是N秒之后刷新。
@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Refresh","1");
resp.getWriter().write(System.currentTimeMillis()+"");
}
}
运行结果:
抓包结果:
3. 重定向
@WebServlet("/rediret")
public class RediretServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//约定跳转到搜狗主页
resp.setStatus(302);
resp.setHeader("Location","http://www.sogou.com");
}
}
运行结果:在浏览器输入127.0.0.1:8080/hello_servlet/rediret
抓包结果:
提示,也可以这样,效果一样: