什么是Servlet

Servlet=Server+applet
Server:服务器
applet:小程序
Servlet含义是服务器端的小程序。
Servlet - 图1

Tomcat和Servlet的关系

Tomcat 是Web应用服务器,是一个Servlet/JSP容器。Tomcat 作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户。而Servlet是一种运行在支持Java语言的服务器上的组件。Servlet最常见的用途是扩展Java Web服务器功能。

  1. Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读可以通过request对象调用对应的方法查询到
  2. Tomcat同时会要响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器

Servlet - 图2

Servlet开发流程

Servlet的开发流程
狭义上讲,servlet是servlet是java语言实现的一个类,所以我们就要根据这个类进行相应的扩展开发.
开发流程如下:

  1. 编写一个java类,继承HttpServlet类
  2. 重写HttpServlet类的doGet方法和doPost方法
  3. 配置web.xml文件,或者使用注解对servlet进行配置

    在IDEA里面编写Servlet

    1.搭建Tomcat环境与前端文件

    具体怎么做的看这片文章
    Tomcat
    最终目录结构向这样
    image.png

    2.添加Servlet依赖(在Tomcat里面)

  4. 点击

image.png

  1. 添加依赖

image.png
image.png

  1. 添加完依赖以后,这里就会出现刚才的依赖

image.png

3. 编写Servlet

  1. 在模块里面的src下新建一个包,在包里面创建一个java文件

image.png

  1. package lyd.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.http.HttpServlet;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.io.IOException;
  7. /**
  8. * @author liyadong
  9. * @create 2022-03-22-16:25
  10. */
  11. public class demo01servlet extends HttpServlet { //继承HttpServlet类
  12. @Override
  13. public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  14. //做get请求的处理
  15. System.out.println("GET");
  16. }
  17. @Override
  18. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  19. //做post请求的处理
  20. System.out.println("POST");
  21. }
  22. }

3.1.运行逻辑

  1. 前段发送请求到demo01servlet这个方法
  2. req就是前段发送过来的全部东西,包括请求头,数据
  3. 重写HttpServlet里面的do类方法,如果这个请求是post,就会执行doPost方法,如果请求是get,就会执行doGet方法
  4. 如果请求是get,没有重写doGet方法,就会去父类里面执行doGet方法,而父类里面的do类方法都是提醒你错误的,所以要重写,没重写就给你返回错误4xx状态
  5. 这个方法执行完了,resp就会被Tomcat返回给前端,所以在这个方法里面可以对resp进行一系列的操作,比如携带一些值返回

    4.在web.xml中配置servlet

    image.png
    目的是让浏览器发出的请求知道到达哪个servlet,也就是让tomcat将封装好的request找到对应的servlet让其使用。

写在web-app标签里面

  1. <servlet>
  2. <servlet-name>demo01servlet</servlet-name>
  3. <servlet-class>lyd.servlet.demo01servlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>demo01servlet</servlet-name>
  7. <url-pattern>/demo01api</url-pattern>
  8. </servlet-mapping>
    • servlet-name:给servlet取个名字,这个无所谓取什么,一般跟我们写的servlet类名相同
    • servlet-class:servlet的全限定类名,也就是servlet的位置
    • servlet-name:跟上面取的名字要相同
    • url-pattern:浏览器通过该url找到请求的servlet,/一定要加,名字也是随意

      4.1运行逻辑

  1. 首先在浏览器输入http://localhost:8080/demo01/demo01api
  2. 根据url来找到
  3. 然后根据里面的名字找到对应的标签
  4. 最后找到servlet的位置
  5. 最终运行程序,在浏览器输入url按回车,IDEA控制台会打印GET,因为浏览器url访问是get方法

image.png

4.2多个url

上面的一个标签可以对应多个标签,里面的里面的对上,可以不同,也就是说可以通过不同的url访问同一个servlet

5. HttpServletRequest取值

Request Payload

前端发送请求的数据是在Payload里面的,是Json格式
image.png
请求头是的Content-Type是application/json
image.png

  1. package lyd.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletInputStream;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import javax.servlet.http.Part;
  8. import java.io.BufferedReader;
  9. import java.io.IOException;
  10. import java.util.Collection;
  11. /**
  12. * @author liyadong
  13. * @create 2022-03-22-16:25
  14. */
  15. public class demo01servlet extends HttpServlet { //继承HttpServlet类
  16. @Override
  17. public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  18. //做get请求的处理
  19. System.out.println("GET");
  20. }
  21. @Override
  22. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  23. //做post请求的处理
  24. System.out.println("POST");
  25. //得到Request Payload形式的数据,json字符串(还要经过转换成json)
  26. String jsonstr = getStringFromStream(req);
  27. }
  28. /**
  29. * 从流中获取Request Payload的数据。调用了req.getInputStream()方法后,这个request就不再是json传参了
  30. */
  31. private String getStringFromStream(HttpServletRequest req) {
  32. ServletInputStream is;
  33. try {
  34. is = req.getInputStream();
  35. int nRead = 1;
  36. int nTotalRead = 0;
  37. byte[] bytes = new byte[10240];
  38. while (nRead > 0) {
  39. nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);
  40. if (nRead > 0)
  41. nTotalRead = nTotalRead + nRead;
  42. }
  43. String str = new String(bytes, 0, nTotalRead, "utf-8");
  44. return str;
  45. } catch (IOException e) {
  46. e.printStackTrace();
  47. return "";
  48. }
  49. }
  50. }

image.png

QueryString

get方式带参数,请求如http://localhost:8080/demo01/demo01api?name=%E5%BC%A0%E4%B8%89&age=23&score99

  1. package lyd.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletInputStream;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import javax.servlet.http.Part;
  8. import java.io.BufferedReader;
  9. import java.io.IOException;
  10. import java.util.Collection;
  11. /**
  12. * @author liyadong
  13. * @create 2022-03-22-16:25
  14. */
  15. public class demo01servlet extends HttpServlet { //继承HttpServlet类
  16. @Override
  17. public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  18. //做get请求的处理
  19. System.out.println("GET");
  20. String qs = req.getQueryString();
  21. }
  22. @Override
  23. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  24. //做post请求的处理
  25. System.out.println("POST");
  26. }
  27. }

image.png

Form Data

这是请求的数据

注意:这里用的

表单发的能用getParameter读取数据,用axios改成from data发送都读不出数据,得用Request Payload的读取流的方法

image.png
这是请求头
image.png

  1. package lyd.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletInputStream;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import javax.servlet.http.Part;
  8. import java.io.BufferedReader;
  9. import java.io.IOException;
  10. import java.util.Collection;
  11. /**
  12. * @author liyadong
  13. * @create 2022-03-22-16:25
  14. */
  15. public class demo01servlet extends HttpServlet { //继承HttpServlet类
  16. @Override
  17. public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  18. //做get请求的处理
  19. System.out.println("GET");
  20. String qs = req.getQueryString();
  21. }
  22. @Override
  23. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  24. //做post请求的处理
  25. System.out.println("POST");
  26. req.setCharacterEncoding("UTF-8"); //有中文记得设置编码
  27. String name = req.getParameter("Name");
  28. String age =req.getParameter("Age");
  29. String score=req.getParameter("Score");
  30. }
  31. }

image.png

6.Servlet生命周期

Servlet生命周期对应三个方法:
init()
service()
destroy()
默认情况下。第一次请求的时候,这个Servlet会进行,实例化(构造方法),初始化(调用init),服务(调用service)
从第二次请求开始,每一次都是服务(service)。
Servlet实例只会创建一个,所有请求都是这个实例去响应。
当容器关闭时,其中的所有servlet实例会被销毁,调用destroy。
第一次请求要实例化,初始化等,可能比较慢,在web.xml里面的里面加入<load-on-startup>1</load-on-startup>,就会在容器启动的时候就加载servlet。第一次请求就不用初始化了。

Servlet是单例的,线程不安全的

Servlet - 图18

7.Session

  1. package lyd.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletInputStream;
  4. import javax.servlet.http.*;
  5. import java.io.BufferedReader;
  6. import java.io.IOException;
  7. import java.util.Collection;
  8. /**
  9. * @author liyadong
  10. * @create 2022-03-22-16:25
  11. */
  12. public class demo01servlet extends HttpServlet { //继承HttpServlet类
  13. @Override
  14. public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  15. //做get请求的处理
  16. System.out.println("GET");
  17. }
  18. @Override
  19. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  20. //做post请求的处理
  21. System.out.println("POST");
  22. //得到session或者生成新的session,新session会在响应头里面Set-Cookie自动发给前端
  23. HttpSession session =req.getSession();//参数传入false表示有就获取,没有就null,不创建新的,默认为true
  24. session.setMaxInactiveInterval(18000);//设置非激活的最大间隔时间,默认1800秒,半个小时不操作,Session就过期了,可以每29分钟操作一次Session,一直在
  25. session.invalidate();//强制性的让会话立即失效
  26. //设置和得到session的值
  27. session.setAttribute("pwd","123456");
  28. session.getAttribute("pwd");
  29. System.out.println(session.getId());
  30. }
  31. }

7.1.逻辑流程

第一次发请求的时候并没有带有SessionID
image.png
getSession()会自动生成一个Session
image.png
响应头会带有一个Set-Cookie
image.png
再次刷新页面的时候,网站就保存了这个Sessionid到Cookie里面
image.png
而再次发送请求,它会自动携带
image.png
带有这个SessionId的请求访问,getSession()就会得到对应的Session,而不是新建一个Session。通过这个SessionId就能区分开不同的客户端了。

8.服务端转发和客户端重定向

8.1.服务端转发

  1. package lyd.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletInputStream;
  4. import javax.servlet.ServletRequest;
  5. import javax.servlet.ServletResponse;
  6. import javax.servlet.http.*;
  7. import java.io.BufferedReader;
  8. import java.io.IOException;
  9. import java.util.Collection;
  10. /**
  11. * @author liyadong
  12. * @create 2022-03-22-16:25
  13. */
  14. public class demo01servlet extends HttpServlet { //继承HttpServlet类
  15. @Override
  16. public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
  17. System.out.println("执行了demo01");
  18. req.getRequestDispatcher("demo02api").forward(req,res);//转发给demo02api来处理,这个要在web.xml里面配置好
  19. }
  20. }
  1. package lyd.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletRequest;
  4. import javax.servlet.ServletResponse;
  5. import javax.servlet.http.HttpServlet;
  6. import java.io.IOException;
  7. /**
  8. * @author liyadong
  9. * @create 2022-03-22-22:09
  10. */
  11. public class demo02servlet extends HttpServlet {
  12. @Override
  13. public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
  14. System.out.println("执行了demo02");
  15. }
  16. }
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5. version="4.0">
  6. <servlet>
  7. <servlet-name>demo01servlet</servlet-name>
  8. <servlet-class>lyd.servlet.demo01servlet</servlet-class>
  9. </servlet>
  10. <servlet-mapping>
  11. <servlet-name>demo01servlet</servlet-name>
  12. <url-pattern>/demo01api</url-pattern>
  13. </servlet-mapping>
  14. <servlet>
  15. <servlet-name>demo02servlet</servlet-name>
  16. <servlet-class>lyd.servlet.demo02servlet</servlet-class>
  17. </servlet>
  18. <servlet-mapping>
  19. <servlet-name>demo02servlet</servlet-name>
  20. <url-pattern>/demo02api</url-pattern>
  21. </servlet-mapping>
  22. </web-app>

image.png

8.2.客户端重定向

  1. package lyd.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletInputStream;
  4. import javax.servlet.ServletRequest;
  5. import javax.servlet.ServletResponse;
  6. import javax.servlet.http.*;
  7. import java.io.BufferedReader;
  8. import java.io.IOException;
  9. import java.util.Collection;
  10. /**
  11. * @author liyadong
  12. * @create 2022-03-22-16:25
  13. */
  14. public class demo01servlet extends HttpServlet { //继承HttpServlet类
  15. @Override
  16. public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
  17. System.out.println("执行了demo01");
  18. res.sendRedirect("demo02api");//客户端重定向,重新发送请求到demo02api
  19. }
  20. }

image.png
image.png
image.png