什么是Servlet
Servlet=Server+applet
Server:服务器
applet:小程序
Servlet含义是服务器端的小程序。
Tomcat和Servlet的关系
Tomcat 是Web应用服务器,是一个Servlet/JSP容器。Tomcat 作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户。而Servlet是一种运行在支持Java语言的服务器上的组件。Servlet最常见的用途是扩展Java Web服务器功能。
- Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读可以通过request对象调用对应的方法查询到
- Tomcat同时会要响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器
Servlet开发流程
Servlet的开发流程
狭义上讲,servlet是servlet是java语言实现的一个类,所以我们就要根据这个类进行相应的扩展开发.
开发流程如下:
- 编写一个java类,继承HttpServlet类
- 重写HttpServlet类的doGet方法和doPost方法
配置web.xml文件,或者使用注解对servlet进行配置
在IDEA里面编写Servlet
1.搭建Tomcat环境与前端文件
具体怎么做的看这片文章
Tomcat
最终目录结构向这样
2.添加Servlet依赖(在Tomcat里面)
点击

- 添加依赖


- 添加完依赖以后,这里就会出现刚才的依赖
3. 编写Servlet
- 在模块里面的src下新建一个包,在包里面创建一个java文件

package lyd.servlet;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/*** @author liyadong* @create 2022-03-22-16:25*/public class demo01servlet extends HttpServlet { //继承HttpServlet类@Overridepublic void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做get请求的处理System.out.println("GET");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做post请求的处理System.out.println("POST");}}
3.1.运行逻辑
- 前段发送请求到demo01servlet这个方法
- req就是前段发送过来的全部东西,包括请求头,数据
- 重写HttpServlet里面的do类方法,如果这个请求是post,就会执行doPost方法,如果请求是get,就会执行doGet方法
- 如果请求是get,没有重写doGet方法,就会去父类里面执行doGet方法,而父类里面的do类方法都是提醒你错误的,所以要重写,没重写就给你返回错误4xx状态
- 这个方法执行完了,resp就会被Tomcat返回给前端,所以在这个方法里面可以对resp进行一系列的操作,比如携带一些值返回
4.在web.xml中配置servlet

目的是让浏览器发出的请求知道到达哪个servlet,也就是让tomcat将封装好的request找到对应的servlet让其使用。
写在web-app标签里面
<servlet><servlet-name>demo01servlet</servlet-name><servlet-class>lyd.servlet.demo01servlet</servlet-class></servlet><servlet-mapping><servlet-name>demo01servlet</servlet-name><url-pattern>/demo01api</url-pattern></servlet-mapping>
- servlet-name:给servlet取个名字,这个无所谓取什么,一般跟我们写的servlet类名相同
- servlet-class:servlet的全限定类名,也就是servlet的位置
- 首先在浏览器输入
http://localhost:8080/demo01/demo01api - 根据url来找到
- 然后根据
里面的名字找到对应的 标签 - 最后找到servlet的位置
- 最终运行程序,在浏览器输入url按回车,IDEA控制台会打印GET,因为浏览器url访问是get方法
4.2多个url
上面的一个
标签可以对应多个 标签, 里面的 和 里面的对上, 可以不同,也就是说可以通过不同的url访问同一个servlet
5. HttpServletRequest取值
Request Payload
前端发送请求的数据是在Payload里面的,是Json格式
请求头是的Content-Type是application/json
package lyd.servlet;import javax.servlet.ServletException;import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.Part;import java.io.BufferedReader;import java.io.IOException;import java.util.Collection;/*** @author liyadong* @create 2022-03-22-16:25*/public class demo01servlet extends HttpServlet { //继承HttpServlet类@Overridepublic void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做get请求的处理System.out.println("GET");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做post请求的处理System.out.println("POST");//得到Request Payload形式的数据,json字符串(还要经过转换成json)String jsonstr = getStringFromStream(req);}/*** 从流中获取Request Payload的数据。调用了req.getInputStream()方法后,这个request就不再是json传参了*/private String getStringFromStream(HttpServletRequest req) {ServletInputStream is;try {is = req.getInputStream();int nRead = 1;int nTotalRead = 0;byte[] bytes = new byte[10240];while (nRead > 0) {nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);if (nRead > 0)nTotalRead = nTotalRead + nRead;}String str = new String(bytes, 0, nTotalRead, "utf-8");return str;} catch (IOException e) {e.printStackTrace();return "";}}}
QueryString
get方式带参数,请求如http://localhost:8080/demo01/demo01api?name=%E5%BC%A0%E4%B8%89&age=23&score99
package lyd.servlet;import javax.servlet.ServletException;import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.Part;import java.io.BufferedReader;import java.io.IOException;import java.util.Collection;/*** @author liyadong* @create 2022-03-22-16:25*/public class demo01servlet extends HttpServlet { //继承HttpServlet类@Overridepublic void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做get请求的处理System.out.println("GET");String qs = req.getQueryString();}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做post请求的处理System.out.println("POST");}}
Form Data
这是请求的数据
注意:这里用的

这是请求头
package lyd.servlet;import javax.servlet.ServletException;import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.Part;import java.io.BufferedReader;import java.io.IOException;import java.util.Collection;/*** @author liyadong* @create 2022-03-22-16:25*/public class demo01servlet extends HttpServlet { //继承HttpServlet类@Overridepublic void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做get请求的处理System.out.println("GET");String qs = req.getQueryString();}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做post请求的处理System.out.println("POST");req.setCharacterEncoding("UTF-8"); //有中文记得设置编码String name = req.getParameter("Name");String age =req.getParameter("Age");String score=req.getParameter("Score");}}
6.Servlet生命周期
Servlet生命周期对应三个方法:init()service()destroy()
默认情况下。第一次请求的时候,这个Servlet会进行,实例化(构造方法),初始化(调用init),服务(调用service)
从第二次请求开始,每一次都是服务(service)。
Servlet实例只会创建一个,所有请求都是这个实例去响应。
当容器关闭时,其中的所有servlet实例会被销毁,调用destroy。
第一次请求要实例化,初始化等,可能比较慢,在web.xml里面的<load-on-startup>1</load-on-startup>,就会在容器启动的时候就加载servlet。第一次请求就不用初始化了。
Servlet是单例的,线程不安全的
7.Session
package lyd.servlet;import javax.servlet.ServletException;import javax.servlet.ServletInputStream;import javax.servlet.http.*;import java.io.BufferedReader;import java.io.IOException;import java.util.Collection;/*** @author liyadong* @create 2022-03-22-16:25*/public class demo01servlet extends HttpServlet { //继承HttpServlet类@Overridepublic void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做get请求的处理System.out.println("GET");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//做post请求的处理System.out.println("POST");//得到session或者生成新的session,新session会在响应头里面Set-Cookie自动发给前端HttpSession session =req.getSession();//参数传入false表示有就获取,没有就null,不创建新的,默认为truesession.setMaxInactiveInterval(18000);//设置非激活的最大间隔时间,默认1800秒,半个小时不操作,Session就过期了,可以每29分钟操作一次Session,一直在session.invalidate();//强制性的让会话立即失效//设置和得到session的值session.setAttribute("pwd","123456");session.getAttribute("pwd");System.out.println(session.getId());}}
7.1.逻辑流程
第一次发请求的时候并没有带有SessionID
getSession()会自动生成一个Session
响应头会带有一个Set-Cookie
再次刷新页面的时候,网站就保存了这个Sessionid到Cookie里面
而再次发送请求,它会自动携带
带有这个SessionId的请求访问,getSession()就会得到对应的Session,而不是新建一个Session。通过这个SessionId就能区分开不同的客户端了。
8.服务端转发和客户端重定向
8.1.服务端转发
package lyd.servlet;import javax.servlet.ServletException;import javax.servlet.ServletInputStream;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.*;import java.io.BufferedReader;import java.io.IOException;import java.util.Collection;/*** @author liyadong* @create 2022-03-22-16:25*/public class demo01servlet extends HttpServlet { //继承HttpServlet类@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("执行了demo01");req.getRequestDispatcher("demo02api").forward(req,res);//转发给demo02api来处理,这个要在web.xml里面配置好}}
package lyd.servlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServlet;import java.io.IOException;/*** @author liyadong* @create 2022-03-22-22:09*/public class demo02servlet extends HttpServlet {@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("执行了demo02");}}
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><servlet><servlet-name>demo01servlet</servlet-name><servlet-class>lyd.servlet.demo01servlet</servlet-class></servlet><servlet-mapping><servlet-name>demo01servlet</servlet-name><url-pattern>/demo01api</url-pattern></servlet-mapping><servlet><servlet-name>demo02servlet</servlet-name><servlet-class>lyd.servlet.demo02servlet</servlet-class></servlet><servlet-mapping><servlet-name>demo02servlet</servlet-name><url-pattern>/demo02api</url-pattern></servlet-mapping></web-app>
8.2.客户端重定向
package lyd.servlet;import javax.servlet.ServletException;import javax.servlet.ServletInputStream;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.*;import java.io.BufferedReader;import java.io.IOException;import java.util.Collection;/*** @author liyadong* @create 2022-03-22-16:25*/public class demo01servlet extends HttpServlet { //继承HttpServlet类@Overridepublic void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {System.out.println("执行了demo01");res.sendRedirect("demo02api");//客户端重定向,重新发送请求到demo02api}}



