• Servlet


    一、Servlet

    1.1 什么是Servlet?

    • Servlet:Server Applet的简称,同Java Applet差不多,Servlet意为服务器上运行的小程序
    • Servlet 就是 Tomcat 这个 HTTP 服务器提供给 Java 的一组 API, 主要用于实现动态页面(什么是动态页面呢?动态页面是相对于静态来说的:

    静态资源是已经写好的,动态资源是即时更新的

    html,css,js一般主要用作静态资源

    对于动态资源:现在开发一般都是前后端分离,前端需要调用后端的结果,因为数据往往是存到数据库中,前端展示的数据是来自于数据库中的,即数据不是写死的

    ps:一般前后端通过json串来互相解析

    • 从我们的角度来说,只要我们遵循Tomcat标准,即实现它的HTTP服务器提供给我们的API(Servlet),就可以使得我们的资源与浏览器进程进行请求与应答的通信活动(所以我们在pom.xml中要引入javax-servlet依赖,引入这个依赖然后实现它,才能够让我们的资源在Tomcat容器中正确的与浏览器通信
    • Tomcat是一个Http服务器,Servlet就是让我们的代码能够和Tomcat的代码完美配合的中间商(一组API)

    1.2 Servlet可以做什么?

    • 解析HTTP请求——把HTTP请求解析为HttpRequest,我们可以获得HttpRequest的请求行信息,请求头们,以及请求体信息
    • 构造HTTP响应——把HttpResponse 对象构造成响应字符串,并通过 Socket 写回给客户端。对于我们而言,只需要通过方法设定HttpResponse 的响应行,响应头们,以及响应体

    1.3 Servlet的生命周期

    首先明确,Servlet是一个接口

    • Servlet的生命周期

      分为5个阶段:加载、创建、初始化、处理客户请求、卸载。

      (1)加载:容器通过类加载器使用servlet类对应的文件加载servlet

      (2)创建:通过调用servlet构造函数创建一个servlet对象

      (3)初始化:调用init方法初始化

      (4)处理客户请求:每当有一个客户请求,容器会创建一个线程来处理客户请求

      (5)卸载:调用destroy方法让servlet自己释放其占用的资源

    • 三个主要方法

      初始化——init(懒汉模式创建的单例对象,初始化时自动调用且只调用一次)

      处理请求响应阶段——service(req,resp)(处理一次调用一次)

      销毁阶段——destroy(只销毁一次)

    在这里插入图片描述

    1.4 如何使用Servlet

    首先明确,Servlet是一个接口,HttpServlet是一个实现这个接口的抽象类,所以我们实现时,可以自定义类,继承这个抽象类,通过覆写doGet,doPost方法对HttpRequest,HttpResponse进行获取和设定,来达到通信

    模板步骤如下:

    • 引入Servlet依赖

          <dependency>
              <groupId>javax.servlet</groupId>
              <artifactId>javax.servlet-api</artifactId>
              <version>3.1.0</version>
              <scope>provided</scope>
          </dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 继承HtttpServlet实现自己的类

      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      
      /**
       * @author sunny
       * @date 2022/06/15 10:07
       **/
      
      @WebServlet("/Model")               
      //通过该注解将url地址/first和这个资源进行绑定,我输入/first就可以请求到这个资源
      public class HttpServletModel extends HttpServlet {
      
          //    重写这个类,表明我们这个类支持Get请求访问
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //        Your code
      //        通过参数req,获取http请求
      //        通过参数resp设置响应内容
          }
      
      
          //    重写这个类,表明我们这个类支持Get请求访问
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //        code
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31

    语法格式:

    (1)注解

    • @WebServlet(“/”)声明是动态资源
    • 必须以”/“开头
    • 路径不能重复
    • 特殊情况:
      • 通配符 * 代表所有,比如(“*.do”),所有以.do结尾的都可以访问到
      • ”/“代表所有的url都可以访问到,只要有这样的,则不可能会出现404
      • ” “代表根目录

    (2)响应体

    • 设置字符集编码+设置Content-type响应头+响应体
    • 标准套路:
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/plain");
            PrintWriter writer = resp.getWriter();
            writer.println("hello");
            writer.println("world");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (3)读取请求参数

    无论是Get请求,还是Post请求,我们都采用相同的方法读取
    在这里插入图片描述

    但要注意:

    GET方法:提交的参数中英文都可正常读取,读取到的内容附在url后,即放在 queryString中:

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**获取用户输入的数据(GET方法提交)
     * @author sunny
     * @date 2022/06/10 21:36
     **/
    @WebServlet("/get")
    public class GetParameter extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            System.out.println(username);
            System.out.println(password);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>表单提交</title>
    </head>
    <body>
    <form method="get" action="/get">
    <input type="text" name="username">
        <input type="password" name="password">
        <button>提交</button>
    </form>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D6fQE0m5-1655862781676)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655260377688.png)]

    点击提交:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G4J3zXnR-1655862781676)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655260403285.png)]

    POST方法:必须req.setCharacterEncoding(“utf-8”)设置编码才可正常读取中文

    以form表单提交,则参数默认是带在请求体中的,并不在url中体现

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**获取用户输入的数据(GET方法提交)
     * @author sunny
     * @date 2022/06/10 21:36
     **/
    @WebServlet("/post")
    public class GetParameter extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //        post方法一定要设置字符集编码
            req.setCharacterEncoding("utf-8");
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            System.out.println(username);
            System.out.println(password);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>表单提交</title>
    </head>
    <body>
    <form method="post" action="/post">
    <input type="text" name="username">
        <input type="password" name="password">
        <button>提交</button>
    </form>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    点击提交:

    在这里插入图片描述

    当然,Post也可以带在url中:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>表单提交</title>
    </head>
    <body>
    <!--以query string的形式post提交,不过这个例子这样写则无论用户的username输入什么,得到的都是aaa-->
    <form method="post" action="/post?username=aaa">
        <input type="text">
        <input type="text" name="password">
        <button>提交</button>
    </form>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    1.5 Servlet获取请求行、请求头们,请求体

    (1)请求行与请求头们

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.Enumeration;
    
    /**
     * @author sunny
     * @date 2022/06/06 21:01
     **/
    @WebServlet("/second")
    public class Second  extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //        请求行信息
            String method = req.getMethod();
            System.out.println("HTTP 方法: " + method);
            System.out.println();
            System.out.println();
    
            String requestURI = req.getRequestURI();
            System.out.println("requestURI: " + requestURI);
            StringBuffer requestURL = req.getRequestURL();
            System.out.println("requestURL: " + requestURL.toString());
            String pathInfo = req.getPathInfo();
            System.out.println("pathInfo: " + pathInfo);
            String contextPath = req.getContextPath();
            System.out.println("contextPath: " + contextPath);
            String servletPath = req.getServletPath();
            System.out.println("servletPath: " + servletPath);
            String pathTranslated = req.getPathTranslated();
            System.out.println("pathTranslated: " + pathTranslated);
            System.out.println();
            System.out.println();
    
            String serverName = req.getServerName();
            System.out.println("serverName: " + serverName);
            int serverPort = req.getServerPort();
            System.out.println("serverPort: " + serverPort);
            String scheme = req.getScheme();
            System.out.println("schema: " + scheme);
            String protocol = req.getProtocol();
            System.out.println("protocol: " + protocol);
            System.out.println();
            System.out.println();
    
    //        请求头们
            Enumeration<String> headerNames = req.getHeaderNames();
            while (headerNames.hasMoreElements()){
                String name = headerNames.nextElement();
                String value = req.getHeader(name);
                System.out.println("name:" + name + " value:" + value);
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    (2)请求体

    import javax.servlet.ServletException;
    import javax.servlet.ServletInputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    
    @WebServlet("/req-body")
    public class ReqBodyServlet extends HttpServlet {
        // 重写了 doPost 方法,所以我们这个资源支持了 POST 方法,但不支持 GET 请求
        // 不能直接在浏览器里直接输入这个 URL 回车,会看到 405 的
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //        方法一
            InputStream inputStream = req.getInputStream();
            byte[] buf = new byte[1024];
            int n = inputStream.read(buf);
    
            // byte[] -> String  字符集解码
            String reqBody = new String(buf, 0, n, "UTF-8");
            System.out.println(reqBody);
    
    //        方法二
    //        BufferedReader reader = req.getReader();
    //        char[] buf = new char[1024];
    //        int n = reader.read(buf);   // n 单位是字符
    //        String reqBody = new String(buf, 0, n);
    //        System.out.println(reqBody);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    【其实实际应用中,只需获取请求参数,用getParameter即可,上面这两种方法是把请求体全部获取到,了解即可】

    1.6 Servlet响应

    其实用1.4中的响应模板即可,这里看看就行:

    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    
    @WebServlet("/set-resp")
    public class SetRespServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 设置响应状态
    //        resp.setStatus(204);
    
            // 设置响应头(header)
            // 响应头的 Name
            // 1. 标准响应头,比如 Content-Type(PS:Content-Length 不需要我们设置)
            // 2. 非标准响应头,填什么都可以(中文不行)
            // 3. Name 不区分大小写
    //        resp.setHeader("Content-Type", "text/plain; charset=gbk");
    //        resp.setHeader("X-My-Class", "Java19");
    
            // 响应体的内容是字符(使用较多的)
    //        resp.setCharacterEncoding("utf-8");
    //        resp.setContentType("text/plain");
    //        PrintWriter writer = resp.getWriter();  // 设置响应字符集要在 getWriter() 之前
    //
    //        writer.print("你好");
    
    
            // 响应体的内容是字节流
            OutputStream outputStream = resp.getOutputStream();
            outputStream.write('H');
            outputStream.write('e');
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    1.7 Get VS Post

    • 语义不同,GET代表获取,POST代表提交

    • GET不应该带有请求体,POST可以带有请求体

    • 对于请求参数,GET方法的参数放在 query string中,POST方法(form表单提交)方法的参数可以直接放在 query string中也可以放在request body中

    • POST比GET稍微安全一点,因为URL一般会记录在日志中,请求体不会记录日志

    • 在这里插入图片描述

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9z3ybhkP-1655862781678)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1654870986868.png)]

    【HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用】

    1.8 Servlet VS CGI

    CGI(Common Gateway Interface)——通用网关接口, 传统技术中,动态的网页建立和显示都是通过CGI来实现

    对于每个请求,都要产生一个新的进程进行处理。因为每个进程都会占有很多服务器的资源和时间,这就导致服务器无法同时处理很多的并发请求, 特别是访问量高的时候),就要消耗系统越多的处理时间,只剩下越来越少的系统资源,对于用户来说,只能是漫长的等待服务器端的返回页面了 。 并且无法克服CGI程序与数据库建立连接时速度慢的瓶颈,从而死机、数据库死锁现象频繁发生

    另外CGI程序都是与操作系统平台相关的,虽然在互联网爆发的初期,CGI为开发互联网应用做出了很大的贡献,但是随着技术的发展,开始逐渐衰落

    Servlet充分发挥了服务器端的资源并高效的利用。 Servlet对每个请求都是单独启动一个线程,而不是进程。这种处理方式大幅度地降低了系统里的进程数量,提高了系统的并发处理能力, 我们的Servlet有连接池的概念,它可以利用多线程的优点,在系统缓存中事先建立好若干与数据库的连接,到时候若想和数据库打交道可以随时跟系统"要"一个连接即可,反应速度可想而知。

    另外因为Java Servlet是运行在虚拟机之上的,也就解决了跨平台问题 。 Servlet具备Java的平台无关性,在系统开发过程中保持了系统的可扩展性、高效性。

    JSP???

    在Servlet出现之后,随着使用范围的扩大,人们发现了它的一个很大的一个弊端。那就是 为了能够输出HTML格式内容,需要编写大量重复代码,造成不必要的重复劳动。

    为了解决这个问题,基于Servlet技术产生了JavaServet Pages技术,也就是JSP。Servlet和JSP两者分工协作,Servlet侧重于解决运算和业务逻辑问题,JSP则侧重于解决展示问题。 Servlet与JSP一起为Web应用开发带来了巨大的贡献,后来出现的众多Java Web应用开发框架都是基于这两种技术的,更确切的说,都是基于Servlet技术的。

    二、前端Http请求的构建

    2.1 Get请求与Post请求

    • 在地址栏输入url是Get请求!!!
    • form表单形式提交通过设定method既可以是Get也可以是Post
    • ajax也既可以构建Get请求也可以构建Post请求
    • 重定向也既可以是Get请求也可以是Post请求

    2.2 地址栏输入url

    先来回顾一下url的格式:

    protocol——本次资源对应的协议(不一定全部是HTTP协议,所以需要标识一下是哪个协议)

    +域名或IP——主机host(资源在哪台主机上)

    +端口——资源在这个主机的哪个进程上获取

    +资源路径——具体定位到是哪个资源

    其中资源路径由两部分组成:Context Path + Servlet Path

    • Tomcat根据Context Path找到具体是哪一个WebApp
    • 然后再根据Servlet Path 找到具体是WebApp中的哪个资源
    • 如果是静态资源如html,找到后响应浏览器
    • 如果是动态资源,则url请求方式为Get

    2.3 form表单提交

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uU9UhRex-1655862781679)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655294128845.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7gXbSga2-1655862781679)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655294244646.png)]

    2.4 ajax——Asynchronous JavaScript and XML

    (1)到底什么是ajax???

    • AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)

    • AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

    • AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

    • 我们这里是ajax的应用之一—— 运用 JavaScript 操作 DOM(Document Object Model)来执行动态效果

    即之前html中都是通过,等标签间接引导浏览器去发送http请求,而ajax则可以自己发送请求

    即我们这里的ajax包含在Javascript中,运用 JavaScript 操作 DOM(Document Object Model)来执行动态效果 ,进而影响用户看到的内容

    (2)ajax的简单使用

    • 创建 XMLHttpRequest 对象

    • 如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open()send() 方法:

      xmlhttp.open("GET","ajax_info.txt",true);
      xmlhttp.send();
      
      • 1
      • 2
    • 如需获得来自服务器的响应,请使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性
      在这里插入图片描述

    如: document.getElementById(“myDiv”).innerHTML=xmlhttp.responseText;

    看下面这个请求的小栗子:

    // 利用这个对象发起 HTTP 请求
    var xhr = new XMLHttpRequest();
    xhr.open("get", "/data/students.json");
    // 以时间驱动的方式,读取响应 —— 当 xhr 完成响应时,执行我们准备好的函数
    xhr.onload = function () {
        console.log(this);      // this 就是 xhr 对象
        console.log(this.responseText); // string 类型
        console.log(xhr.responseText);  // string 类型
    
        // 我们希望把 json 字符串解析成 js 的具体数据类型
        var sts = JSON.parse(this.responseText);
        console.log(sts);
    }
    xhr.send(); // 发送 HTTP 请求
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.5 重定向——Redirect

    (1)什么是重定向?

    • 重定向——请求某个资源,这个资源又定位到了另一个资源

    • 重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。

    (2)重定向方法

    • 永久重定向(状态码:301

    新网址完全继承旧网址, 假如当你访问 a.com时 永久重定向到了 b.com ;那么下一次访问 a.com 时浏览器会直接跳转到 b.com 不会再请求a.com

    • 临时重定向(状态码:302

    对旧网址没有影响, 假如当你访问 a.com 时 临时重定向到了 b.com ; 那么下一次当你请求 a.com
    时浏览器还会先请求 a.com ,然后再重定向到b.com

    临时重定向时没有考虑是否保留原方法,大部分浏览器都实现成不保留的了,就是都退化成GET请求了,所以有了以下两个优化:307和303

    • 保留方法的临时重定向(状态码:307
    • 不保留方法的临时重定向(状态码:303

    以不保留方法的临时重定向为例:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QvUyeZBv-1655862781680)(C:\Users\星\AppData\Roaming\Typora\typora-user-images\1655297729661.png)]

    实际上,一般我们直接用resp带有的sendRedirect();方法即可,这个方法是临时重定向(302)

    resp.sendRedirect("重定向的目标资源");
    
    • 1

    (3) forword VS Redirect

    forward,服务器获取跳转页面内容传给用户,用户地址栏不变

    redirect(重定向),是服务器向用户发送转向的地址,redirect后地址栏变成新的地址

    三、前后端分离——json串交互

    3.1 前后端分离?

    对于一个项目而言,其实如果项目全程都是一个人搞定,也可以使用模板技术(jsp,thymeleaf),对于模板技术,我们不再过多分析

    现在,一般都是前后端分离,下面以前后端分离为重点:

    MVC——Model View Controller

    • 后端数据访问层,我们一般称为dao层,主要就是数据访问控制,现在我们先采用JDBC,来实现对数据库的操作
    • Model模型层,承载数据的对象
    • Controller控制层,将请求分发给具体是服务层的哪个服务来处理
    • Servlet服务层,处理请求,给出响应
    • View视图层,主要是指前端页面

    前后端数据的交互,一般是听过json串来进行数据交互

    ps【】:关于jar包和war包

    Jar包是普通的Java程序打包,里面是.class文件

    War包则是Java Web程序打包,里面除了有.class文件还有其他诸如html的静态资源,也只有被打包成war包,才会被Tomcat识别

    3.2 什么是Json串

    那么,什么是json串呢?

    • JSON: JavaScript Object Notation(JavaScript 对象表示法)
    • Json串实际就是一个字符串,用于交换数据,只不过规定了必须的数据格式
    • JSON 一般内嵌在JavaScript中,可通过 JavaScript 进行解析
    • JSON 数据可使用 AJAX 进行传输

    所以,JavaScript中创建json实例,然后通过ajax进行传输

    • json串是JavaScript的子集?

    3.3 Json串基本语法

    • 大括号 {} 保存对象

    • 中括号 [] 保存数组,数组可以包含多个对象

    • JSON 对象在大括号 {} 中书写:

      {key1 : value1, key2 : value2, ... keyN : valueN }
      
      • 1
    • JSON 数组在中括号 [] 中书写:

      数组可包含多个对象:

      [
          { key1 : value1-1 , key2:value1-2 }, 
          { key1 : value2-1 , key2:value2-2 }, 
          { key1 : value3-1 , key2:value3-2 }, 
          ...
          { key1 : valueN-1 , key2:valueN-2 }, 
      ]
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 通过 JavaScript,您可以创建一个对象数组,并像这样进行赋值:

      实例:

      var sites = [    
          { "name":"runoob" , "url":"www.runoob.com" },     
          { "name":"google" , "url":"www.google.com" },     
          { "name":"微博" , "url":"www.weibo.com" } 
      ];
      //可以像这样访问 JavaScript 对象数组中的第一项(索引从 0 开始):
      
      sites[0].name;
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      返回的内容是:

      runoob

    3.4 Json串的序列化与反序列化

    (1)序列化:JSON.stringify()

    在向服务器发送数据时一般是字符串。,即前端向服务器发送数据,要将前端JS中的数据对象序列化为字符串

    我们可以使用 JSON.stringify() 方法将 JavaScript 对象转换为字符串。

    实例:

    var obj = { "name":"runoob", "alexa":10000, 
                "site":"www.runoob.com"}; 
    var myJSON = JSON.stringify(obj); 
    document.getElementById("demo").innerHTML = myJSON; 
    
    • 1
    • 2
    • 3
    • 4

    (2)反序列化:JSON.parse()

    我们可以使用 JSON.parse() 方法将数据转换为 JavaScript 对象。

    在这里插入图片描述

    XMLHttpRequest.responseText是全部后端的返回数据
    
    • 1
    // 进行 JSON 的反序列
    var students = JSON.parse(this.responseText);
    
    • 1
    • 2

    得到反序列化对象students后,就可以将该对象按我们想要的格式渲染进html中;

    var tbody = document.querySelector('tbody');
    for (var i in students) {    
        var s = students[i];    
        var tr = `<tr><td>${s.姓名}</td><td>${s.成绩}</td></tr>`;    
        tbody.innerHTML = tbody.innerHTML + tr;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (3)Java中将对象变成json串:

    如果我们自己按照json格式,把对象变成json格式的字符串是很麻烦的,如下:

    //    private String getJSON1() {
    //        StringBuilder sb = new StringBuilder();
    //        sb.append("[");
    //        for (Map.Entry<String, Integer> entry : gradeMap.entrySet()) {
    //            String name = entry.getKey();
    //            int value = entry.getValue();
    //            sb.append("{")
    //                    .append("\"姓名\": ")
    //                    .append("\"")
    //                    .append(name)
    //                    .append("\",")
    //                    .append("\"成绩\": ")
    //                    .append(value)
    //                    .append("},");
    //        }
    //        sb.delete(sb.length() - 1, sb.length());
    //        sb.append("]");
    //
    //        return sb.toString();
    //    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    所以,有别人已经实现这个功能了,我们直接借用即可:

    • 引入依赖:
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.12.4</version>
            </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 调用ObjectMapper类对象的writeValueAsString()方法,writerWithDefaultPrettyPrinter()方法是让json串格式好看点儿
    ObjectMapper om = new ObjectMapper();
    om.writerWithDefaultPrettyPrinter().writeValueAsString(list);
    
    • 1
    • 2

    四、简单小栗子——JDBC+Servlet

    源码链接:
    https://gitee.com/serendi-pity/grade_web_separation
    本地存储:D:\JIDEA_code\grade_web_separation

    大体目录结构:
    在这里插入图片描述
    实现内容:
    在这里插入图片描述
    如:输入bb 14,点击提交

    返回成绩列表:
    在这里插入图片描述

    从业务流程角度看逻辑:

    • 首先是save.html,是输入姓名和成绩的页面用户输入后,点击提交提交的数据要保存
    • 所以先去Save类,Save类实现的就是保存到数据库的操作保存完成后,Save类会重定向到index.html页面
    • index.html页面就是要展示给用户的数据列表
    • index.html页面通过ajax想得到数据库中的数据
    • ajax到数据库数据中间经过Servlet,Service,Dao三层封装加工
    • Model层:数据库中的表对应我们的Grade类
    • Dao层:GetGradeList提供从数据库查询数据,返回查询到的数据列表
    • GradeListJsonServlet类中从dao层的GetGradeList类中得到数据对象列表,将数据对象列表转换成json串返还给ajax
    • ajax去向GradeListJsonServlet类也就是路径为(“/data/grade-list.json”)得到json数据串,再将得到的json数据串反序列化,渲染到index.html中

    所以:

    • 用户提交给服务端:一般是form表单的形式提交,一般推荐用Post方法;
      服务端收到数据后,先保存到数据库中,再响应给用户一个新的页面(一般是通过重定向);
    • 服务端响应客户端:重定向的html页面,还需要其他资源共同作业,如css美化,jsp的数据,数据一般是来自于数据库;
    • 那么怎么使数据库中的数据“自动”加载到html页面中呢?
    • jsp这边一般采用ajax,ajax自动发起请求到/data/grade-list.json路径,即GradeListJsonServlet类中的doGet方法进行响应,doGet方法返回的是json格式,内容就是从数据库中获取到数据的json串;
    • 那么如何将数据转化为json串呢,这里我们引入了jackson-databind依赖,引入依赖后,直接通过ObjectMapper类对象的writeValueAsString方法转换为json格式ajax得到响应的Json串后,再将json串反序列化渲染到index.html中
  • 相关阅读:
    nRF52832看门狗WDT使用(SDK17.1.0)
    git容易出问题的命令
    hsql数据库(HyperSQL )(简单了解一下)
    uni-app 使用vscode开发uni-app
    匿名类为什么不可以使用非final变量
    孤僻型性格分析,如何改变孤僻型性格?
    axios的安装使用
    重试框架 Spring-Retry 和 Guava-Retry,你知道该怎么选吗?
    【EMC专题】案例:非接开启后液晶屏闪烁怎么就不是非接的问题?
    【Java基础】第六章 | IO流
  • 原文地址:https://blog.csdn.net/m0_58652786/article/details/125403628