• (Java高级教程)第三章Java网络编程-第七节2:Servlet API和综合案例


    前面说过,Servlet就是Tomcat这个HTTP服务器提供给Java的一组API,来完成构建动态页面等任务。Servlet中涉及的API非常多,这里我们只关注以下三个即可,其余的可在工作中获得遇到具体场景再学习使用

    • HttpServlet
    • HttpServletRequest
    • HttpServletResponse

    一:HttpServlet

    HttpServlet:它提供了处理基于HTTP协议的请求和响应的功能,为开发人员提供了一组用于处理HTTP请求的方法,其中最常用的是doGet()doPost()方法。这些方法可以被子类重写以实现具体的业务逻辑。HttpServlet功能包括

    • 解析HTTP请求:HttpServlet类负责解析来自客户端的HTTP请求,并提供了与请求相关的方法,如获取请求方法、获取请求参数、获取请求头等
    • 处理HTTP请求:HttpServlet类定义了doGet()、doPost()等方法,用于处理GET和POST请求。开发人员可以根据业务需求重写这些方法,并在其中实现相应的业务逻辑
    • 生成HTTP响应:HttpServlet类提供了一组用于生成HTTP响应的方法,如设置响应状态码、设置响应头、写入响应内容等
    • 会话管理:HttpServlet类支持会话管理,可以通过getSession()方法获取会话对象,进行会话跟踪和管理
    • 错误处理:HttpServlet类提供了对HTTP错误的处理机制,可以重写相应的方法来自定义错误页面或错误处理逻辑

    其核心方法如下,常用方法是后三个,前三个经常在相关面试中出现

    方法名称调用时机
    initHttpServlet实例化后被调用一次
    destoryHttpServlet不再使用后被调用一次(正常关闭Tomcat
    service收到HTTP请求时候调用
    doGet收到GET请求的时候调用(由service方法调用)
    doPost收到POST请求的时候调用(由service方法调用)
    doPut/doDelete/doOptions/...收到其他请求的时候调用((由service方法调用))

    这些方法的调用时机就称为“Servlet的生命周期”

    在这里插入图片描述

    二:HttpServletRequest

    (1)介绍

    HttpServletRequest:继承自ServletRequest接口,并提供了访问HTTP请求的方法和属性。HttpServletRequest对象包含了客户端发送到服务器的HTTP请求的信息,开发人员可以使用该对象获取请求的参数、请求头、请求方法等信息

    其核心方法如下(都是get系列)

    方法名称调用时机
    String getProrocol()返回请求协议的名称和版本
    String getMehtod()返回请求方法名称
    String getRequestURI()从协议名称直到HTTP请求的第一行查询字符串中,返回该请求的URL的一部分
    String getContexPath()返回指示请求上下文的URI部分
    Eunmeration getParameterNames()返回一个String对象的美剧,包含在该请求中包含的参数的名称
    String getParameter(String name)以字符串形式返回请求参数的值,如果参数不存在则返回null
    String[] getParameterValues(String name)返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在返回null
    Enumeration getHeaderNames()返回一个枚举,包含在该请求中包含的所有的头名
    String getHeader(String name)以字符串形式返回指定的请求头的值
    String getCharacterEncoding()返回请求主体中使用的字符编码名称
    String getHeader(String name)以字符串形式返回指定的请求头的值
    String getContentType()返回请求主体的MIME类型,如果不知道类型则返回null
    int getContentLength以字节为单位返回请求主体的长度,并提供输入流,如果长度未知则返回-1
    InputStream getInputStream()用于读取去请求的body内容,返回一个InputStream对象

    (2)示例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;  
      
    @WebServlet("/showRequest")  
    public class ShowRequestServlet extends HttpServlet {  
        @Override  
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            //把API执行的结果,放到stringBuilder中  
            StringBuilder stringBuilder=new StringBuilder();  
    
    		// 声明响应boyd是html结构数据  
    		resp.setContentType("text/html");
      
            stringBuilder.append("

    首行部分

    "
    ); stringBuilder.append(req.getProtocol()); stringBuilder.append("
    "
    ); stringBuilder.append(req.getMethod()); stringBuilder.append("
    "
    ); stringBuilder.append(req.getRequestURI()); stringBuilder.append("
    "
    ); stringBuilder.append(req.getContextPath()); stringBuilder.append("
    "
    ); stringBuilder.append(req.getQueryString()); stringBuilder.append("
    "
    ); stringBuilder.append("

    header部分

    "
    ); Enumeration<String> headerNames=req.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName= headerNames.nextElement(); String headerValue=req.getHeader(headerName); stringBuilder.append(headerName+":"+headerValue+"
    "
    ); } resp.setContentType("text/html;charset=utf8"); resp.getWriter().write(stringBuilder.toString()); } }
    • 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

    在浏览器中输入http://localhost:8080/HelloServlet/showRequest?a=10&b=20&c=30,效果如下

    在这里插入图片描述

    (3)示例2:获取Get请求参数

    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;  
      
    @WebServlet("/getparameter")  
    public class GetParameter extends HttpServlet {  
        @Override  
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            // 获取 query string 中的键值对  
            String studentId = req.getParameter("studentId");  
            String studentName = req.getParameter("studentName");  
            System.out.println(studentId);  
            System.out.println(studentName);  
      
            // 告诉浏览器类型和编码,让浏览器正常显示  
            resp.setContentType("text/html; charset=utf-8");  
            resp.getWriter().write("studentId: " + studentId + ", " + "studentName: " + studentName);  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在浏览器中输入http://localhost:8080/GetParameter/getparameter?studentId=22123213&studentName=张三,效果如下

    在这里插入图片描述

    (3)实例3:获取Post请求参数

    A:情况一

    此时请求的bodyx-www-form-urlencoded,也即form表单

    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;  
      
    @WebServlet("/postparameter")  
    public class PostParameter extends HttpServlet {  
        @Override  
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            // 通过发送post请求,获取 body 中的参数  
            // 让Servlet知道如何解析  
            req.setCharacterEncoding("utf-8");  
            String studentId = req.getParameter("studentId");  
            String studentName = req.getParameter("studentName");  
            System.out.println(studentId);  
            System.out.println(studentName);  
      
            // 告诉浏览器类型和编码,让浏览器正常显示  
            resp.setContentType("text/html; charset=utf-8");  
            resp.getWriter().write("studentId: " + studentId + ", " + "studentName: " + studentName);  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    此时并不能在浏览器中直接输入参数,因为那是Get请求,构造Post请求可以有以下两种方法

    • 方法一:利用Html通过form表单发送
    • 方法二:使用软件postman

    先说方法一:需要注意该Html文件必须位于webapp目录之下。复习一下,在HTML中,form标签用于创建一个表单,其中action属性义了表单提交时要发送数据的目标URL或服务器端脚本,当用户提交表单时,浏览器会将表单中的数据发送到action属性指定的URL。有以下两种常见的写法

    • 相对路径(此时基准目录就是Html文件所在目录,也即/PostParameter:例如postparameter
    • 绝对路径:例如/PostParameter.postparameter

    运行PostParameter后,然后在地址栏中输入http://localhost:8080/PostParameter/student.html,即可正确访问到该文件

    • 再次重复:在Java Web应用程序中,通常将静态资源(例如HtmlCSS等)放置在webapp目录下,该目录是Web应用程序的根目录。链接中PostParameter是Servlet类的名称,并不是文件夹或路径

    在这里插入图片描述

    接着向表单输入内容,然后提交

    在这里插入图片描述

    在这里插入图片描述


    再说方法二:postman使用方法非常简单

    在这里插入图片描述

    另外,postman十分方便的一点是可以转换为代码

    在这里插入图片描述

    B:情况二

    这种情况下请求的body是json格式,步骤如下

    • 首先需要读取body中的内容,这里需要借助getInputStream,以此获取到要解析的字符串
    • Servlet并没有内置json解释器,所以需要我们手动实现或者是借助第三方库,这里借助jackson这个库(因为它是SpringBoot御用的)。然后就会得到一组键值对
    • 根据类对象(在Java反射中讲到过)创建一个实例
    • 遍历类对象中的属性的名字,以此作为Key查询对应的Value
    • 返回构造好的对象

    进入Java中央仓库,搜索jackson,选择Jackson Databind

    在这里插入图片描述

    随便选择一个版本后,拷贝Maven至pom.xml中的标签内

    <dependencies>  
          
        <dependency>  
            <groupId>javax.servletgroupId>  
            <artifactId>javax.servlet-apiartifactId>  
            <version>3.1.0version>  
            <scope>providedscope>  
        dependency>  
          
        <dependency>  
            <groupId>com.fasterxml.jackson.coregroupId>  
            <artifactId>jackson-databindartifactId>  
            <version>2.13.4.1version>  
        dependency>  
      
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    jackson会提供一个核心类叫ObjectMapper,其中有两个常用方法:

    • readValue:用于将json数据转换为Java对象
      • 第一个参数:可以是字符串,也可以是输入流
      • 第二个参数:是一个类对象,也就是要解析出来的结果的对象的类
    • writeValueAsString:用于将Java对象转换为json数据

    代码如下

    import com.fasterxml.jackson.databind.ObjectMapper;  
      
    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;  
      
    /*  
    一个Java对象,要想正确解析,必须满足以下条件  
        这个类的属性务必是public或者带有public的getter/setter,否则jackson无法访问到这个对象的属性  
        这个类务必要有无参版本的构造方法(如果不写编译器自动生成无参构造)  
     */class Student {  
        public int studentId;  
        public String studentName;  
    }  
      
    @WebServlet("/json")  
    public class JacksonServlet extends HttpServlet {  
        @Override  
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            // 假设请求的body格式如下  
            // {studentId: 10, studentName: "张三"}  
      
            // 创建Jackson核心类  
            ObjectMapper objectMapper = new ObjectMapper();  
            // 解析json  
            Student s = objectMapper.readValue(req.getInputStream(), Student.class);  
            System.out.println(s.studentId);  
            System.out.println(s.studentName);  
      
            resp.setContentType("text/html; charset=utf-8");  
            resp.getWriter().write("studentId: " + s.studentId + ", " + "studentName: " + s.studentName);  
        }  
    }
    
    • 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

    利用postman发送请求(注意设置正确),可以看到回应

    在这里插入图片描述

    当然我们也可以返回json

    import com.fasterxml.jackson.databind.ObjectMapper;  
      
    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;  
      
    /*  
    一个Java对象,要想正确解析,必须满足以下条件  
        这个类的属性务必是public或者带有public的getter/setter,否则jackson无法访问到这个对象的属性  
        这个类务必要有无参版本的构造方法(如果不写编译器自动生成无参构造)  
     */class Student {  
        public int studentId;  
        public String studentName;  
    }  
      
    @WebServlet("/json")  
    public class JacksonServlet extends HttpServlet {  
        @Override  
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            // 假设请求的body格式如下  
            // {studentId: 10, studentName: "张三"}  
      
            // 创建Jackson核心类  
            ObjectMapper objectMapper = new ObjectMapper();  
            // 解析json  
            Student s = objectMapper.readValue(req.getInputStream(), Student.class);  
            System.out.println(s.studentId);  
            System.out.println(s.studentName);  
      
            // 修改  
            s.studentId=20;  
            s.studentName="李四";  
            // 返回json  
            resp.setContentType("application/json; charset=utf-8");  
            resp.getWriter().write(objectMapper.writeValueAsString(s));  
        }  
    }
    
    • 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

    在这里插入图片描述

    三:HttpServletResponse

    (1)介绍

    HttpServletResponse:用于处理来自客户端的请求并生成响应,其中的方法可以设置和操作HTTP响应的各种属性,包括响应头、状态码、字符编码等等

    其核心方法如下(都是set系列)

    方法描述
    void setStatus(int sc)为该响应设置状态码
    void setHeader(String name, String value)设置一个带有给定的名称和值的header(如果name存在则覆盖)
    void addHeader(String name, Strin value)添加一个带有给定的名称和值的header(如果name存在则并列添加新键值对)
    void setContentType(String type)设置被发送到客户端的响应的内容类型
    void setCharacterEncoding(String charset)设置被发送到客户端的响应的字符编码(MIME字符集),例如utf-8
    void sendRedirect(String location)使用指定的重定向位置URL发送临时重定向响应到客户端
    PrintWriter getWriter()用于向body中写入文本格式数据
    OutputStream getOutputStream()用于向body中写入二进制格式数据

    (2)示例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;  
      
      
    @WebServlet("/status")  
    public class StatusServlet extends HttpServlet {  
        @Override  
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            // 利用 queryString 设置状态码  
           String type = req.getParameter("type");  
      
           if (type.equals("1")) {  
               resp.setStatus(200);  
           } else if (type.equals("2")) {  
               resp.setStatus(404);  
           } else {  
               resp.setStatus(504);  
           }  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在浏览器地址里输入http://localhost:8080/StatusServlet/status?type=2

    在这里插入图片描述

    (3)示例2:自动刷新

    在HTTP响应的头部(Header)中,Refresh属性用于在服务器返回的响应中指示浏览器进行自动刷新或重定向操作。语法如下

    • 延迟时间:表示延迟多少秒后进行属性,默认为0s
    • URL=重定向URL:指定要重定向的URL
    Refresh: [延迟时间]; URL=重定向URL
    
    • 1

    当浏览器接收到带有Refresh属性的响应时,它会根据指定的延迟时间进行等待,并在延迟结束后执行刷新或重定向。如果未指定延迟时间,默认为立即刷新

    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;  
      
    @WebServlet("/refresh")  
    public class AutoRefreshServlet extends HttpServlet {  
        @Override  
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            // 每2s刷新一次  
            resp.setHeader("refresh", "2");  
            // 显示当前时间戳  
            resp.getWriter().write(System.currentTimeMillis() + "");  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    (4)示例3:重定向

    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;  
      
    @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.baidu.com");  
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    四:综合案例之表白墙

    前面介绍的表白墙案例非常简单,它只是一个单纯的HTML页面,如果将浏览器关闭,那么输入的内容将不复存在。所以这里我们可以将其做成服务器版本,这样即使页面关闭,表白墙内容也不会丢失

    • 注意:本案例虽然比较简单,但是会结合到之前很多知识,所以相关内容不再重复,如有需求可以翻看前面的内容

    (1)效果展示

    当加载页面时可以自动从服务器数据库中获取之前的提交内容

    在这里插入图片描述

    点击提交则可以将内容保存到服务器数据库中

    在这里插入图片描述

    在这里插入图片描述

    (2)请求和响应报文格式

    发送数据给服务器

    • 请求报文
      • POST/message HTTP/1.1
      • Content-Type:application/json; charset=utf-8
      • {"who":"我", "whom":"你", "我啊你"}
    • 响应报文
      • HTTP/1.1 200 OK

    从服务器获取数据

    • 请求报文
      • GET/message
    • 响应报文
      • HTTP/1.1 200ok
      • Content-Type:application/json; charset=utf-8

    (3)代码梳理

    在这里插入图片描述

    (4)完整代码

    整个项目概览

    在这里插入图片描述

    Mysql相关语句

    
    show databases;  
    create database confession_wall;  
    use confession_wall;  
    create table message (who varchar(50), whom varchar(50), content varchar(1024));  
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    配置文件

    pom.xml

    <dependencies>  
          
        <dependency>  
            <groupId>javax.servletgroupId>  
            <artifactId>javax.servlet-apiartifactId>  
            <version>3.1.0version>  
            <scope>providedscope>  
        dependency>  
          
        <dependency>  
            <groupId>com.fasterxml.jackson.coregroupId>  
            <artifactId>jackson-databindartifactId>  
            <version>2.13.4.1version>  
        dependency>  
      
          
        <dependency>  
            <groupId>mysqlgroupId>  
            <artifactId>mysql-connector-javaartifactId>  
            <version>5.1.49version>  
        dependency>  
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    web.xml

    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 Applicationdisplay-name>  
    web-app>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    相关类

    Message.java:用于封装消息内容

    public class Message {  
        public String who;  
        public String whom;  
        public String content;  
      
      
        public String getWho() {  
            return who;  
        }  
      
        public String getWhom() {  
            return whom;  
        }  
      
        public String getContent() {  
            return content;  
        }  
      
        public void setWho(String who) {  
            this.who = who;  
        }  
      
        public void setWhom(String whom) {  
            this.whom = whom;  
        }  
      
        public void setContent(String content) {  
            this.content = content;  
        }  
    }
    
    • 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

    MessageServlet.javaServlet服务器

    import com.fasterxml.jackson.databind.ObjectMapper;  
    import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;  
      
    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 javax.sql.DataSource;  
    import java.io.IOException;  
    import java.sql.Connection;  
    import java.sql.PreparedStatement;  
    import java.sql.ResultSet;  
    import java.sql.SQLException;  
    import java.util.ArrayList;  
    import java.util.List;  
      
    
    @WebServlet("/message")  
    public class MessageServlet extends HttpServlet {  
        private ObjectMapper objectMapper = new ObjectMapper();  
        private List<Message> messageList = new ArrayList<>();  
      
        // 让页面获取到数据  
        @Override  
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            // 声明当前的响应数据格式  
            resp.setContentType("application/json; charset=utf-8");  
            // 读取数据库内容返回给页面  
      
            try {  
                messageList = load();  
            } catch (SQLException e) {  
                throw new RuntimeException(e);  
            }  
            resp.getWriter().write(objectMapper.writeValueAsString(messageList));  
        }  
      
        // 浏览器向服务器提交数据  
        @Override  
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
            // 获取到body中的数据并解析  
            Message message = objectMapper.readValue(req.getInputStream(), Message.class);  
            // 向数据库提交内容  
            try {  
                save(message);  
            } catch (SQLException e) {  
                throw new RuntimeException(e);  
            }  
            resp.setStatus(200);  
            System.out.println("成功提交数据:"  
                    + "【" + message.getWho() + "】" + "对【" + message.getWhom() + "】" + "说:" + message.getContent());  
      
        }  
      
        // 从数据库查询数据  
        private List<Message> load() throws SQLException {  
            // 先得有一个数据源  
            DataSource dataSource = DBUtil.getDataSource();  
            // 与服务器建立连接  
            Connection connection = dataSource.getConnection();  
      
      
            // 构造SQL并预处理  
            String sql = "select * from message";  
            PreparedStatement statement = connection.prepareStatement(sql);  
      
      
            // 执行SQL得到结果集合  
            ResultSet resultSet = statement.executeQuery();  
      
            //遍历结果集合  
            // List messageList = new ArrayList<>();  
            while (resultSet.next()) {  
                Message message = new Message();  
                message.setWho(resultSet.getString("who"));  
                message.setWhom(resultSet.getString("whom"));  
                message.setContent(resultSet.getString("content"));  
                messageList.add(message);  
      
            }  
      
            // 关闭连接释放资源  
            statement.close();  
            connection.close();  
      
            return messageList;  
        }  
      
        // 保存数据到数据库  
        private void save(Message message) throws SQLException {  
            // 先得有一个数据源  
            DataSource dataSource = DBUtil.getDataSource();  
      
            // 与服务器建立连接  
            Connection connection = dataSource.getConnection();  
            System.out.println(connection);  
      
            // 构造SQL并进行预处理  
            String sql = "insert into message values(?, ?, ?)";  
            PreparedStatement statement = connection.prepareStatement(sql);  
            System.out.println(sql);  
            statement.setString(1, message.who);  
            statement.setString(2, message.whom);  
            statement.setString(3, message.content);  
      
            // 执行SQL然后插入  
            try {  
                int res = statement.executeUpdate();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            }  
      
            // 关闭连接释放资源  
            statement.close();  
            connection.close();  
      
      
        }  
    }
    
    • 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
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120

    DBUtil.java:用于用于封装DataSource的单例

    import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;   
    import javax.sql.DataSource;  
      
    // 用于封装DataSource的单例(懒汉模式,注意线程安全)  
    public class DBUtil {  
        private static volatile DataSource dataSource = null;  
      
        public static DataSource getDataSource() {  
            if (dataSource == null) {  
                synchronized (DBUtil.class) {  
                    if(dataSource == null) {  
                        dataSource = new MysqlDataSource();  
                        ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/confession_wall?characterEncoding=utf8&useSSL=false&serverTimezone=UTC");  
                        ((MysqlDataSource)dataSource).setUser("root");  
                        ((MysqlDataSource)dataSource).setPassword("123456");  
                    }  
                }  
            }  
      
            return dataSource;  
        }  
      
        // 防止直接new DBUtil  
        private DBUtil() {};  
      
    }
    
    • 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

    webapp

    onfessionalWall.html:网页

    DOCTYPE html>  
    <html lang="en">  
    <head>  
        <meta charset="UTF-8">  
        <title>ConfessionalWalltitle>  
    head>  
    <body>  
      
    <style>  
      .container {  
        width: 400px;  
        /*水平居中*/  
        margin: 0 auto;  
      }  
      
      h1 {  
        text-align: center;  
      }  
      
      p {  
        text-align: center;  
        color: #808080;  
      }  
      
      .row {  
        height: 40px;  
        display: flex;  
        /*  水平居中*/  
        justify-content: center;  
        /*  垂直居中*/  
        align-items: center;  
      }  
      
      .row span {  
        width: 100px;  
      }  
      
      .row input {  
        width: 200px;  
        height: 25px;  
      }  
      
      .row button {  
        width: 310px;  
        height: 40px;  
        color:white;  
        background-color: orange;  
        border: none;  
      
      }  
        
      .row button:active {  
        background-color: #666;  
      }  
      
      
    style>  
      
      
    <div class="container">  
      <h1>表白墙h1>  
      <p>(输入后点击下方按钮提交)p>  
      <div class="row">  
        <span>姓名:span><input type="text">  
      div>  
      
      <div class="row">  
        <span>对谁:span><input type="text">  
      div>  
      
      <div class="row">  
        <span>内容:span><input type="text">  
      div>  
      
      <div class="row">  
        <button>提交button>  
      div>  
      
      
    div>  
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js">script>  
    <script>  
      var container = document.querySelector('.container');  
      var button = document.querySelector('button');  
      button.onclick = function () {  
        // 获取内容  
        var inputs = document.querySelectorAll('input');  
        var who = inputs[0].value;  
        var whom = inputs[1].value;  
        var content = inputs[2].value;  
        console.log(who);  
        console.log(who);  
        console.log(content);  
        if (who === '' || whom === '' || content === '') {  
          alert("有未填写项");  
          return;  
        }  
      
        // 构造出div生成发送内容  
        let newDiv = document.createElement('div');  
        newDiv.className = 'row';  
        newDiv.innerHTML = "【" + who + "】" + "对【" + whom + "】" + "说:" + content;  
        container.appendChild(newDiv);  
      
        // 清空之前输入  
        for (var i = 0; i < inputs.length; i++) {  
          inputs[i].value = '';  
        }  
      
        // 构造对象  
        let data = {  
          who: who,  
          whom, whom,  
          content, content  
        };  
      
        // 利用ajax发送请求  
        $.ajax({  
          type: 'post',  
          url : 'message',  
      
          // 以下是body内容  
          data: JSON.stringify(data),  
          contentType: "application/json; charset=utf-8",  
          success: function(body) {  
            console.log("成功提交数据")  
          }  
        });  
      }  
      
      // 在页面加载时就获取服务器数据  
      function getMessages() {  
        $.ajax({  
          type: 'get',  
          url: 'message',  
          success: function (body) {  
            // body就是响应的body内容,json数组  
            // JQuery可以很智能的我们将json数组解析为js对象数组(但注意设置Content-Type为application/json)  
            let contatiner = document.querySelector('.container')  
            for (let i = 0; i < body.length; i++) {  
              let message = body[i];  
              // 构造元素  
              let newDiv = document.createElement('div');  
              newDiv.className = 'row';  
              newDiv.innerHTML = "【" + message.who + "】" + "对【" + message.whom + "】" + "说:" + message.content;  
              contatiner.appendChild(newDiv);  
            }  
          }  
        })  
      }  
      getMessages();  
      
      
    script>  
      
      
    body>  
    html>
    
    • 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
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
  • 相关阅读:
    RabbitMQ必会的8个知识点
    力扣:130. 被围绕的区域(Python3)
    IPIDEA的使用方式
    【AOP系列】6.缓存处理
    微软出品自动化神器Playwright,不用写一行代码(Playwright+Java)系列
    Lodash的部分用法
    操作系统——处理机调度
    java计算机毕业设计基层党支部建设平台MyBatis+系统+LW文档+源码+调试部署
    微服务架构的可观察性设计模式
    Linux常用命令——clock命令
  • 原文地址:https://blog.csdn.net/qq_39183034/article/details/132833187