Tomcat And Servlet (1)

文章目录

  • 1. Tomcat
  • 2. 下载安装
  • 3. 启动 Tomcat
  • 4. 运行 Tomcat
  • 5. Servlet
    • 5.1 创建项目
    • 5.2 引入依赖
    • 5.3 创建目录
    • 5.4 编写代码
    • 5.5 打包程序
    • 5.6 部署程序
    • 5.7 验证程序
  • 6. 安装 Smart Tomcat 插件
  • 7. 使用 SmartTomcat 插件
  • 8. 常见错误
    • 8.1 出现 404
    • 8.2 出现 405
    • 8.3 出现 500
    • 8.4 出现空白页面
    • 8.5 出现 无法访问此网站
  • 9. 常用 Servlet API
    • 9.1 HttpServlet
    • 9.2 HttpServletRequest
      • 9.2.1 简单的前后端交互
    • 9.3 HttpServletResponse
  • 10 代码案例
    • 10.1 留言板基本功能实现 (后端)
    • 10.2 补充 : jackson API 使用
    • 10.3 留言板前端部分
    • 10.4 修改为数据库版本
    • 10.5 修改为文件版本

1. Tomcat

谈到 “汤姆猫”, 大家可能更多想到的是大名鼎鼎的这个:

在这里插入图片描述


事实上, Java 世界中的 “汤姆猫” 完全不是一回事, 但是同样大名鼎鼎

在这里插入图片描述


Tomcat 是一个 HTTP 服务器 , HTTP 协议就是 HTTP 客户端 和 HTTP 服务器之间通信使用的协议 , HTTP 客户端就是 浏览器 (当然也有别的) 。

HTTP 服务器 则有很多种实现 ,Tomcat 是 java 圈子中 , 最知名 ,最广泛使用的 http 服务器


下面就来 了解一下 Tomcat ,这里我们先来 安装他

2. 下载安装

图一 :

在这里插入图片描述


图二 :

在这里插入图片描述

3. 启动 Tomcat

在这里插入图片描述

4. 运行 Tomcat


我们使用 tomcat 最大的用途就是把我们写好的网站,给部署上去 , 一个网站 = 前端 + 后端 , 这里 先部署点前端的代码 , 来体验一下.


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


到此我们已经 看完了 Tomcat 安装 , Tomcat 启动 …


但是这只是开胃菜 ,我们学习 Tomcat 的最核心的目标是基于 tomcat 编程 ,做出一个网站来 .


下面就来学习 通过 tomcat 进行 网站 后端开发 , 网站后端 , http 服务器 肯定是需要针对 http 协议进行一系列操作的 , 幸运的是 tomcat

已经把 这些 http 协议相关的底层操作 封装好了 ,我们只需要调用 tomcat 给 提供的 api 即可

这里 tomcatjava 提供的原生进行 webapi 就称为 Servlet , 未来我们 可能还要接触一些框架 (spring 全家桶) Spring MVC 等

也是 进行 web 开发的 api (这组 api 也是基于 servlet 的 ,相当于 对 servlet 的封装)


题外话 :

关于 Servlet ,在企业中已经 几乎不会使用了, 就和 企业中 会不会使用 jdbc 是一样的 .

因为 spring 会比 Servlet 更好用 ,更简单 ,就好比 汽车 自动挡 和 手动挡的区别 ,那么 为啥还要学 Servlet 呢 ,

因为 Servlet 是未来学习框架的基础 , 我们将 基础打扎实了 那么 学习 框架 就会事半功倍 ,

另外 技术是在不停的进步的 ,新的技术体系是层出不穷的 ,这两年流行 spring ,

再过几年 是否有更好的框架代替 spring 是说不定的 。 但是 不管框架 咋样变化 ,

我们想要 使用 java 进行 web 开发 , Servlet 都是恒定不变的。

下面就来学习 Servlet

5. Servlet


Servlet 是 一种实现 动态页面的技术 , 是一组 Tomcat 提供给 程序猿的 API , 帮助程序猿 简单高效开发 一个 web app .


这里稍微说一下 : 动态页面


关于我们的 网页分为两类 :

  1. 静态页面 : 页面内容始终是固定不变的
  2. 动态页面 : 页面内容睡着输入参数的不同而改变

在这里插入图片描述


下面就来 写一个第一个 Servlet 程序 , 还是老规矩 写一个 Hello World .


这里需要 7 个步骤

  1. 创建项目
  2. 引入依赖
  3. 创建目录结构
  4. 编写代码
  5. 打包程序
  6. 部署程序
  7. 验证


看起来很繁琐 ,实际上 ,出来编写代码之外 ,剩下的步骤 都是固定的 (固定的意味着 , 我们多练习几遍就会了) , 正因为这里太麻烦了,后面要学习的 spring MVC 就是简化 这个开发过程的.

5.1 创建项目

这里我们需要创建一个 Maven 项目


Maven 是 个 “工具管理” 工具

  1. 规范目录结构
  2. 管理依赖 (使用了啥第三方库 , 都给处理好)
  3. 构建
  4. 打包
  5. 测试


本文就涉及到 管理依赖 , 和 打包 ,Maven 其他的功能 可以自己 去 了解一下 .


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


项目创建后,来完成第二个步骤 引入依赖

5.2 引入依赖


这里我们需要引入的 依赖 就是 Servlet 对应的 jar 包 .


这里我们可以在 中央仓库 去找 Servlet 对应的 jar 包 , 附上中央仓库 : Maven Repository: Search/Browse/Explore (mvnrepository.com)

在这里插入图片描述


到此第二步就完成了,下面来完成第三步 创建目录

5.3 创建目录


虽然 Maven 已经帮我们自动的创建了一些目录,但是还不够 ,此处是需要使用 Maven 开发一个 web 程序 , 还需要别的 目录 .

在这里插入图片描述

<!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>


提问 : 这里个 web.xml 有啥用 ?


答 :


当前 写的 servlet 程序 和以往写的 代码相比 有一个非常大的 区别, 没有 main 方法

main 方法 可以视为 是 汽车的发送机 ,有发送机才能跑 , r如果现在有辆车 ,没有发送机 ,能不能有办法跑 ?

是有办法的 , 比如 挂一个车头 ,拽着它跑就行了 , 比如 火车 , 有很多车厢 , 只有一个车头 ,当车头开起来的时候就可以拖着 车厢跑了 .

我们写的 servlet 程序 就是车厢 ,tomact 就是车头 , 我们把写好的 servlet 程序 放到 webapps 目录下 ,就相当于 把车厢给挂到车头后面了.

tomcat 如何识别 ,webapps 目录下 ,那些是需要拉着跑的车厢 ? 那些是普通的不需要拉着跑的目录呢 ?


就是靠 目录下的 WEB-INF 里面的 web.xml , 这个文件 就相当于 投名状 . Tomcat 大哥 ,小弟我以后跟着你混了. 此时 tomcat 就把我们写的代码加载并运行起来了 。

在这里插入图片描述

到此 目录就创建好, 下面来完成最核心的一步 编写代码

5.4 编写代码


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


代码编写完,下面来 完成第五步 打包程序

5.5 打包程序


打包程序 : 把程序编译好 (得到一些 .class 文件) , 再把这些 .class 达成 压缩包 .


jar 就是 一种 .class 构成的压缩包 , 但是这里我们需要打的是 war 包 .

jar 只是一个普通的 java 程序 ,war 则是 tomcat 专属的用来描述 webapp 的程序 ,一个 war 就是一个 webapp !!!


这里如何 打 war 包呢 ?

很简单直接通过 Mavne 就可以 打包了

在这里插入图片描述


到此我们的 第五步 打包操作就完成了 , 下面来完成第六步部署程序

5.6 部署程序


部署 : 把刚才打包号的 war 拷贝到 tomcat 的 webapps 目录 中即可 !!!

无论 tomcat 是 在 你的电脑上 还是不同电脑上,都是这样拷贝

在这里插入图片描述


到此 第六步就完成了, 下面来完成最后一步 启动 Tomcat ,验证我们的程序

5.7 验证程序


如果 tomcat 正在运行 ,直接拷贝 ,tomcat 也能识别 (这个识别操作可能存在 bug ,windows , 在 Linux 并不会) ,

实际工作中 ,tomcat 基本都是在 Linux 上运行的 , 所以这个小问题 ,不要太在意 ,如果你的没有识别,那么请重启 Tomcat

在这里插入图片描述


到此我们已经完成了 七步操作 , 别看 步骤很多 ,其实是很简单的, 多操作几遍 很快就熟悉了, 另外 大家有没有一种感觉, 上面的步骤是不是非常繁琐与麻烦 , 下面就来 简化 流程 .

6. 安装 Smart Tomcat 插件


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


安装完 SmartTomcat 后 ,我们就来使用他

7. 使用 SmartTomcat 插件


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


Smart Tomcat 工作原理

不是说自动把 war 包拷贝了 (webapps 里是不变的) , 是通过 另一种方式来启动 Tomcat 的 , Tomcat 支持启动的时候 显示指定一个 特定的 webapp 目录 , 相当于 让 Tomcat 加载 单个 webapp 运行 。

在这里插入图片描述


如果 觉得这一套有一点麻烦 , 没关系,等我们学习了 Spring , Spring Boot , Spring MVC , 后面在实现类似的功能就方便了.


到此 我们已经 基本入门了,下面来看看常见的错误 .

8. 常见错误

8.1 出现 404


404: 标识你要访问的资源在服务上 不存在 / 找不到


这里出现 404 主要 有两个方面

  1. 路径写错了
  2. 你的 webapp 没有被部署


路径写错了

在这里插入图片描述


webapp 没有被部署

在这里插入图片描述

8.2 出现 405


405 : Method Not Allowed 表示 对应的 HTTP 请求方法没有实现

在这里插入图片描述

8.3 出现 500


出现 500 是最好解决的 , 上面的 404 , 405 需要我们的经验 去猜哪里错了,而 500 会直接告诉你哪里错了. 500 本质上是代码抛出了异常 , 出现500 的时候 日志 中会明确的告诉你 异常调用栈,告诉你 哪一行代码出的问题

在这里插入图片描述

8.4 出现空白页面

在这里插入图片描述

8.5 出现 无法访问此网站

在这里插入图片描述


常见错误看完,下面我们来 看看 Servlet 中 常用的 API

9. 常用 Servlet API


关于 Servlet API 当前主要掌握 三个 类即可

  1. HttpServlet
  2. HttpServletRequest
  3. HttpServletResponse

9.1 HttpServlet

HttpServlet 核心方法

方法名称调用时机
init在 HttpServlet 实例化之后被调用一次
destory在 HttpServlet 实例不再使用的时候调用一次
service收到 HTTP 请求的时候调用
doGet收到 GET 请求的时候调用(由 service 方法调用)
doPost收到 POST 请求的时候调用(由 service 方法调用)
doPut/doDelete/doOptions/…收到其他请求的时候调用(由 service 方法调用)

  1. init : tomcat 首次收到了和该类相关联的 请求 的时候 HttpServlet 才会实例化, 而不是 tomcat 一启动就立即实例化 . (类似于之前说过的懒汉模式) , HttpServlet 实例化后才会调用 init 方法

在这里插入图片描述

  1. destory : 在 HttpServlet 实例不在使用的时候调用 一次 (服务器终止的时候,调用) ,这个方法 就可以 做一些清理之类的工作

在这里插入图片描述

  1. service : 收到 http 请求就会触发 (路径匹配的请求) , 其实 我们的 doGet 就在 service 里调用 .

在这里插入图片描述


init , destroy , service 这三个方法 就是 HttpServlet 最关键的 三个方法 (虽然不太会直接用这几个,不会影响他们的重要性)


谈到上面这个 ,就可以引出一个典型的 面试题 : Servlet 的生命周期 是咋回事 ??


生命周期 : 粗浅的说法 ,一个东西啥时候来的, 啥时候没的就是 生命走起 , 进一步的理解 这个东西 什么 阶段,做啥事 , 这就是更加具体的生命走起 .

举个例子 : 一个人的生命周期

  1. 小的时候 , 要做的就是善学

  2. 长大了之后, 参加工作

  3. 再大点 ,要结婚 生娃

  4. 年纪再大 , 娃要上学了

  5. 年纪再大 ,让 娃结婚生娃

  6. 年纪再大 , 帮娃带娃

  7. 年纪再大 驾鹤西去 …


对应的到 Servlet 生命周期

  1. 开始的时候, 执行 init
  2. 每次收到请求执行 service
  3. 销毁之前 ,执行 destroy


如果后面 问到 xxx 的生命周期 , 其实就问你 , 这个东西在 每个 阶段 都在干啥 .


注意 : 一个 Servlet 程序 里面可以包含很多 Servlet ,某个 Servlet 的生死 ,不影响 整个 Servlet 程序

接下来的 几个 ,其实我们已经会用了, 之前使用的 是 doGet 方法来处理请求 , doPost 等方法都是差不多的 。


这里为了省心 ,下面就在来写一些代码看看 :


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


图三 :

在这里插入图片描述


再唠一句 :如果你通过上面的 ajax 发送请求 ,结果 访问 浏览器并没有发送,那么 有可能 是你修改了 type 后,并没有重写启动服务器, 此时服务器运行的还是旧的代码 .


如果你觉得 每次都重启 太麻烦 了 , 也是有办法的 ,只不过我现在不说 , 如果你就是不想那么麻烦, 那么你可以自己去搜索一下 如何开

启 热部署 , 关于 如何开启热部署 ,会在 spring 系列文章中提到 .


到此 HttpServlet 类我们就搞定了, 下面来看看 第二个类 HttpServletRequest

9.2 HttpServletRequest


HttpServletRequest 表示的是 HTTP 请求

在这里插入图片描述


HttpServletRequest 的核心方法

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


注意: 请求对象是服务器收到的内容, 不应该修改. 因此上面的方法也都只是 “读” 方法, 而不是 “写” 方法.


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


这里的 API 使用 其实都比较简单 ,下面来看一个重要的知识点 , 前端给后端传参

9.2.1 简单的前后端交互

前端给后端传参 有两种典型做法 :

  1. 通过 GET 里面的 query string 传给后端
  2. 通过 POST , 借助 form 表单传给后端
  3. 通过 POST , 借助 json 格式表示 body 传给后端

GET , query string


在前端给后端传两个数字 ,一个是同学的 studentId , 一个是 classId 。


比如 : ?studentId=10&classId=20


下面来写一个代码来处理这个请求 :

在这里插入图片描述


2. POST , from


对于前端是 form 表单这样的格式的数据 ,后端还是使用 getParameter 来获取 .


form 表单 也是键值对,和 query string的格式一样,知识这部分内容在 body 中 .


通过 form 表单构造的请求 大致如下 :

首行
POST http://localhost:8080/hello_servlet/postParameter HTTP/1.1

header 部分 :
[
	若干 header
]

body 部分 :
studentId = 10 & classId = 20


下面就来通过 html 的 form 标签来构造 上述的请求

在这里插入图片描述


这里其实就涉及到了前后端交互,如果觉得 有点乱的 话 ,这里可以画个图来帮助大家理解

在这里插入图片描述


POST , json


json 是一种非常主流的数据格式 ,也是键值对结构 .

大概长下面这样子 :

{
	classId:20,
	studentId:10
}


我们请求中的 body 就可以按照 json 的格式来组织.


前端可以通过 ajax 的方式来构造出这个内容 (body 为 json 形式) , 更简单的方式 使用第三方工具 postman 直接构造。


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


图三 :

在这里插入图片描述


图四 :

在这里插入图片描述

9.3 HttpServletResponse

HttpServletResponse : 对应到 HTTP 响应 ,我们 可以通过 这个对象来构造出 HTTP 响应 返回给前端.


HttpServletResponse 核心方法

方法描述
void setStatus(int sc)为该响应设置状态码.
void setHeader(String name, String value)设置一个带有给定的名称和值的 header. 如果 name 已经存在, 则覆盖旧的值.
void addHeader(String name, String 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 中写入二进制格式数据.


响应对象是服务器要返回给浏览器的内容, 这里的重要信息都是程序猿设置的. 因此上面的方
法都是 “写” 方法.


演示几个方法


1. 设置状态码

图一 :

在这里插入图片描述


图二 :

在这里插入图片描述

2. 重定向 : sendRedirect 方法

图一 :

在这里插入图片描述


3. 补充一个字段 : Refresh

再 header 里面 添加一个 Refresh 可以实现 浏览器 “自动刷新” 即 让浏览器每隔几秒自动刷新一次.

在这里插入图片描述


到此 我们的 Servlet 常用 API 就看完了 ,下面我们来写两个代码案例 来熟悉他们 .

10 代码案例


还记得在 学习前端三剑客 (HTML, CSS , javaScript) 的时候 写过一个静态页面 留言版 , 下面就根据它来完成一个前后端交互的小案例.

javaScript-扫盲

10.1 留言板基本功能实现 (后端)


图一 : 约定前后端交互数据格式

在这里插入图片描述


下面就来写代码


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


注意 : 这里多敲了一个变量 from ,可以自己 删改一下 .


图三 :

在这里插入图片描述


图四 :

在这里插入图片描述

附上代码 : MessageServlet

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.jws.WebService;
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.ArrayList;
import java.util.List;


class Message {


    private String to;

    private String message;

    private String form;



    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getForm() {
        return form;
    }

    public void setForm(String form) {
        this.form = form;
    }
}

@WebServlet("/message")
public class MessageServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        deleteServlet.messageList = messageList;
    }

    // 使用这个 List 变量保存所有消息
    private List<Message> messageList = new ArrayList<>();

    // 向服务器提交数据
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // jackson 库中的核心类
        ObjectMapper objectMapper = new ObjectMapper();

        //  将 body 中的内容读取出来 , 解析成 一个 Message 对象
        Message message = objectMapper.readValue(req.getInputStream(), Message.class);

        // 这里先通过简单除暴的方式来完成保存
        messageList.add(message);

        // 此处的设定状态码可以省略 , 不设定默认也是 200
        resp.setStatus(200);

    }


    // 从服务器获取数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ObjectMapper objectMapper = new ObjectMapper();

        resp.setContentType("application/json; charset=utf8");

        // 第一个参数 往那个里面写 , 第二参数 需要转为 json 的数据
        objectMapper.writeValue(resp.getWriter(), messageList);
    }
}

deleteServlet

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;
import java.util.ArrayList;
import java.util.List;

@WebServlet("/delete")
public class deleteServlet extends HttpServlet {


    public static List<Message> messageList = new ArrayList<>();


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ObjectMapper objectMapper = new ObjectMapper();

        int size = messageList.size();

        messageList.remove(size - 1);

        resp.setContentType("text/json; charset=utf8");
        // 将数据返回 :
        objectMapper.writeValue(resp.getWriter(), messageList);

    }
}

这里留言板的 基本功能就完成了 , 如果 对 jackson 这库有点陌生的话, 这里就带着大家 , 写一个代码来认识一下.

10.2 补充 : jackson API 使用


在这里插入图片描述

关于 jackson 的API 后面会经常使用 , 这里 不熟悉没关系 ,后面 用多了 , 就熟悉了, 下面完成 前端部分 .

10.3 留言板前端部分


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


图三 :

在这里插入图片描述

图四 :

在这里插入图片描述


图五 :

在这里插入图片描述


图六 :

在这里插入图片描述


到此就完成了 这个代码案例,但是 存在一个非常严重的问题 , 数据是存储在服务器的内容中 , 如果服务器重启了,那么数据仍然会丢失 。


这里有两种解决办法 :

  1. 将数据存储在数据库中
  2. 将数据存入文件 (通过文件操作 , 将数据 写入到一个文件中).

10.4 修改为数据库版本


这先来完成 通过 数据库 存储数据的版本


图一 :

在这里插入图片描述


DBUtil


// 通过 这个类 ,把数据库连接过程封装一下

// 此处把这个 DBUtil 作为一个 工具类, 提供 static 方法供其他代码来调用

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// DBUtil 本质上是 管理了 单例的 DataSource 的类
public class DBUtil {

    // 这里URL 后面的 只需要改数据名即可
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/lx?characterEncoding=utf8&useSSL=false";

    private static final String USERNAME = "root";

    private static final String PASSWORD = "1234"; // 我们部署到 服务器 , 服务器没有密码所以不填

    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(URL);
                    ((MysqlDataSource) dataSource).setUser(USERNAME);
                    ((MysqlDataSource) dataSource).setPassword(PASSWORD);
                }
            }
        }
        return dataSource;
    }


    public static Connection getConnection() {
        // 通过 getDataSource 来 建立数据库连接
        try {
            return getDataSource().getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.println("数据库连接失败,请检查数据库是否启动正确, url是否正确");
        return null;
    }

    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {
        // 用来关闭

        // 此处的 三个 try catch 分开写更好 , 避免前面的异常导致后面的代码不执行
        if (resultSet == null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement == null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (connection == null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

图二 :

在这里插入图片描述


图三 :

在这里插入图片描述

附上代码 :

deleteServlet

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;
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("/delete")
public class deleteServlet extends HttpServlet {


//    public static List<Message> messageList = new ArrayList<>();


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ObjectMapper objectMapper = new ObjectMapper();


        List<Message> messageList = load();
        int size = messageList.size();


        Message message = messageList.get(size - 1);
        delete(message);


        resp.setContentType("text/json; charset=utf8");
        // 将数据返回 :
//        objectMapper.writeValue(resp.getWriter(), messageList);

    }


    private void delete(Message message) {

        Connection connection = null;

        PreparedStatement statement = null;

        try {
            // 1. 建立连接
            connection = DBUtil.getConnection();

            // 2. 构造 SQL
            String sql = "delete from message where `from` = ? and `to` = ? and message = ?";

            statement = connection.prepareStatement(sql);

            statement.setString(1, message.getForm());

            statement.setString(2, message.getTo());

            statement.setString(3, message.getMessage());

            // 3.  执行 SQL

            statement.executeUpdate();


        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            // 4. 释放资源
            DBUtil.close(connection,statement,null);
        }


    }


    // 从数据库获取数据
    private List<Message> load() {

        Connection connection = null;

        PreparedStatement statement = null;

        List<Message> messageList = new ArrayList<>();

        ResultSet resultSet = null;
        try {
            // 1. 建立连接
            connection = DBUtil.getConnection();

            // 2. 构造SQL
            String sql = "select * from message";

            statement = connection.prepareStatement(sql);

            // 3. 执行 SQL
            resultSet = statement.executeQuery();


            // 4. 遍历 结果集合
            while (resultSet.next()) {

                Message message = new Message();

                message.setForm(resultSet.getString("from"));

                message.setTo(resultSet.getString("to"));

                message.setMessage(resultSet.getString("message"));

                messageList.add(message);
            }


        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 5. 释放资源 ,断开连接
            DBUtil.close(connection, statement, resultSet);
        }

        return messageList;
    }

}


messageServlet

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.jws.WebService;
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.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;


class Message {


    private String to;

    private String message;

    private String form;


    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getForm() {
        return form;
    }

    public void setForm(String form) {
        this.form = form;
    }
}

@WebServlet("/message")
public class MessageServlet extends HttpServlet {

//    @Override
//    public void init() throws ServletException {
//        deleteServlet.messageList = messageList;
//    }

    // 使用这个 List 变量保存所有消息
//    private List<Message> messageList = new ArrayList<>();

    // 向服务器提交数据
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // jackson 库中的核心类
        ObjectMapper objectMapper = new ObjectMapper();

        //  将 body 中的内容读取出来 , 解析成 一个 Message 对象
        Message message = objectMapper.readValue(req.getInputStream(), Message.class);

        // 这里先通过简单除暴的方式来完成保存
//        messageList.add(message);

        save(message);
        // 此处的设定状态码可以省略 , 不设定默认也是 200
        resp.setStatus(200);

    }


    // 从服务器获取数据
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ObjectMapper objectMapper = new ObjectMapper();

        resp.setContentType("application/json; charset=utf8");

        List<Message> messageList = load();
        // 第一个参数 往那个里面写 , 第二参数 需要转为 json 的数据
        objectMapper.writeValue(resp.getWriter(), messageList);
    }


    // JDBC 操作 :

    // 提供一对方法

    // 往数据库中存 一条数据
    private void save(Message message) {

        Connection connection = null;

        PreparedStatement statement = null;

        try {

            // 1. 建立连接 :
            connection = DBUtil.getConnection();

            // 2. 构造 SQL 语句 , ? 表示占位符
            String sql = "insert into message values(?,?,?)";

            statement = connection.prepareStatement(sql);
            statement.setString(1, message.getForm());
            statement.setString(2, message.getTo());
            statement.setString(3, message.getMessage());

            // 3. 执行 sql
            statement.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 4. 关闭连接
            DBUtil.close(connection, statement, null);
        }
    }

    // 从数据库获取数据
    private List<Message> load() {

        Connection connection = null;

        PreparedStatement statement = null;

        List<Message> messageList = new ArrayList<>();

        ResultSet resultSet = null;
        try {
            // 1. 建立连接
            connection = DBUtil.getConnection();

            // 2. 构造SQL
            String sql = "select * from message";

            statement = connection.prepareStatement(sql);

            // 3. 执行 SQL
            resultSet = statement.executeQuery();


            // 4. 遍历 结果集合
            while (resultSet.next()) {

                Message message = new Message();

                message.setForm(resultSet.getString("from"));

                message.setTo(resultSet.getString("to"));

                message.setMessage(resultSet.getString("message"));

                messageList.add(message);
            }


        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 5. 释放资源 ,断开连接
            DBUtil.close(connection, statement, resultSet);
        }

        return messageList;
    }

}


到此 数据库版本就完成了,下面再来写一个 文件版本 ,将数据存入文件中.

10.5 修改为文件版本


图一 :

在这里插入图片描述


图二 :

在这里插入图片描述


这里就不继续写了, 剩余内容放到下一篇文章中 ,防止篇幅过长

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/2617.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在linux上安装配置nodejs工具,设置环境变量,设置npm国内镜像源,提高下载速度。

目录前言1&#xff0c;关于nodejs2&#xff0c;配置环境变量3&#xff0c;总结前言 本文的原文连接是: https://blog.csdn.net/freewebsys/article/details/108971807 未经博主允许不得转载。 博主CSDN地址是&#xff1a;https://blog.csdn.net/freewebsys 博主掘金地址是&…

CSRF漏洞的概念、利用方式、防御方案

CSRF漏洞1.CSRF的概念1.1 什么是CSRF&#xff1f;1.2 基本攻击流程2.CSRF攻击实现2.1 靶场练习2.2 CSRFXSS组合拳2.2.1 攻击页面部署2.2.2 构造恶意xss语句&#xff0c;实现重复生效的CSRF3. CSRF攻击的防御**3.1 只使用JSON API****3.2 验证HTTP Referer字段****3.3 在请求地址…

卫星通信1

偏心率为0&#xff0c;则椭圆变成圆形 偏心率为1 则长轴相比短轴无限长 此时椭圆轨道变成一条直线 半焦距 ae 地球轨道面&#xff0c;称为黄道面 赤道面 中间有个夹角&#xff0c;就是23.5 一般是地心坐标系 沿椭圆轨道探测范围大 在近地点不能提供任何服务,因为覆盖面积太…

【java】笔试强训Day3【在字符串中找出连续最长的数字串与数组中出现次数超过一半的数字】

目录 ⛳选择题 1.以下代码运行输出的是 2.以下程序的输出结果为 3.下面关于构造方法的说法不正确的是 ( ) 4.在异常处理中&#xff0c;以下描述不正确的有&#xff08; &#xff09; 5.下列描述中&#xff0c;错误的是&#xff08; &#xff09; 6.…

Linux下的coredump和kdump

目录前言coredump是什么&#xff1f;运行异常代码查看本地文件多出的core文件gdb调试带上core文件kdump机制前言 在我们之前介绍进程等待的时候&#xff0c;曾经介绍过父进程会等待子进程并且回收子进程的运行结束状态&#xff08;status输出型参数&#xff09;:参考博客 当进…

【Node.js】身份认证,Cookie和Session的认证机制,express中使用session认证和JWT认证

Node.jsWeb开发模式如何选择Web开发模式身份认证什么是身份认证为什么要身份认证不同开发模式的身份认证Session认证机制提高身份认证的安全性Session的工作原理Express中使用Session认证Session认证机制的局限性JWT认证机制JWT的工作原理JWT的组成部分Express中使用JWT在登录成…

Java - 配置中心初体验

目录 前言 配置中心介绍 什么是配置中心 Nacos配置中心 数据结构 命名空间 分组 服务 配置中心添加配置 读取配置 本地添加依赖 本地添加配置 测试 结语 前言 前文讲了ELK&#xff0c;ELK说简单也简单&#xff0c;说复杂也复杂&#xff0c;但说实话&#xff0c;微…

数据库知识总结

数据库知识点总结个人向。 目录第一章 绪论第二章 关系数据库第三章 关系数据库标准语言SQL第四章 数据库安全性第五章 数据库完整性第六章 关系数据理论第七章 数据库设计第十章 数据库恢复技术第十一章 并发控制第一章 绪论 数据(data): 描述事物的符号记录。 数据库(DataB…

基于注解的Spring-AOP应用实例

1、应用场景 需求是&#xff1a;在a系统每次字典数据变更时&#xff0c;都需要给b系统同步一次数据&#xff0c;以保持两个系统字典数据相同。 字典的增、删、改、合并接口&#xff0c;都需要执行数据推送操作&#xff0c;如果不用AOP、这些接口都需要增加推送操作的代码&…

Docker常规安装简介

总体步骤 搜索镜像拉取镜像查看镜像启动镜像,服务端口映射停止容器移除容器 案例 安装tomcat docker hub上面查找tomcat镜像&#xff0c;docker search tomcat从docker hub上拉取tomcat镜像到本地 docker pull tomcatdocker images查看是否有拉取到的tomcat 使用tomcat镜像创…

【带有平移和倾斜头的DIY相机滑块–基于Arduino的项目】

【带有平移和倾斜头的DIY相机滑块–基于Arduino的项目】 1. 前言2. 总体构思3. 构建相机滑块4. 电路图5. 印刷电路板设计6. 组装电子设备7. DIY 相机滑块 Arduino 代码1. 前言 在本教程中,我们将学习如何制作带有平移和倾斜头的电动相机滑块。这个基于 Arduino 的项目是 100%…

【Linux】进程概念二

文章目录进程概念二1. 进程状态2. 进程状态查看3. 僵尸进程3.1 僵尸进程的危害4. 孤儿进程5. 环境变量5.1 常见环境变量5.2 查看环境变量的方法5.3 测试PATH5.4 环境变量相关的命令5.5 环境变量的组织方式5.6 通过代码获取环境变量6. 程序地址空间7. 进程地址空间8. 扩展8.1 为…

如何安装nvm(nvm 安装教程)

如何安装nvm(nvm 安装教程) 一、nvm是什么? nvm是一个node的版本管理工具,可以简单操作node版本的切换、安装、查看等等,与npm不同的是,npm是依赖包的管理工具。 二、安装nvm 1.nvm下载地址 https://github.com/coreybutler/nvm-windows/releases提示:1.nvm-setup.z…

功能测试转型测试开发年薪27W,又一名功能测试摆脱点点点,进了大厂

咱们直接开门见山&#xff0c;没错我的粉丝向我投来了喜报&#xff0c;从功能测试转型测试开发&#xff0c;进入大厂&#xff0c;摆脱最初级的点点点功能测试&#xff0c;拿到高薪&#xff0c;遗憾的是&#xff0c;这名粉丝因为个人原因没有经过指导就去面试了&#xff0c;否则…

CCM调试的理论依据

前言 很久之前在网上看到一些CCM的调试总结&#xff0c;但是没有理论依据&#xff0c;经过我本人的推理&#xff0c;以及和结果比对&#xff0c;这里总结一个我称之为色相环补色原理的调试理论。 CCM理论&#xff1a; CMOS sensor 使用颜色滤波阵列&#xff08;Color Filter…

YOLOV8改进:如何增加注意力模块?(以CBAM模块为例)

YOLOV8改进&#xff1a;如何增加注意力模块&#xff1f;&#xff08;以CBAM模块为例&#xff09;前言YOLOV8nn文件夹modules.pytask.pymodels文件夹总结前言 因为毕设用到了YOLO&#xff0c;鉴于最近V8刚出&#xff0c;因此考虑将注意力机制加入到v8中。 YOLOV8 代码地址&am…

蓝桥杯每日一真题——[蓝桥杯 2021 省 B] 杨辉三角形(二分+规律)

文章目录[蓝桥杯 2021 省 B] 杨辉三角形题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示思路&#xff1a;全部代码&#xff1a;[蓝桥杯 2021 省 B] 杨辉三角形 题目描述 下面的图形是著名的杨辉三角形: 如果我们按从上到下、从左到右的顺序把所有数排成一列&…

配置Maven环境变量

我们现在进行项目开发时&#xff0c;项目中一般都会有依赖包的存在&#xff0c;而这些依赖包一般都是利用Maven进行下载管理的。 一. 下载&安装 下载地址 maven下载地址如下&#xff0c;各位请选择对应系统的maven版本进行下载。 https://maven.apache.org/download.cgi…

做一个前端网页送给女朋友~轮播图+纪念日

文章目录1. 轮播图框架2. 轮播图大盒子实现1. 盒子及图片的可视化2. 将图片重叠起来并放入轮播图盒子中...相对定位与绝对定位3. 添加左右按钮4. 点击按钮跳转图片5. 鼠标离开图片轮播图按钮隐藏6. 添加小圆点按钮7. 点击小圆点跳转图片并且该小圆点变色8. 自动轮播9. 最后一步…

SoC设计流程

此为一个学习记录文&#xff0c;内容可能从书上《SoC设计方法与实现&#xff0c;郭炜等电子工业出版社》来&#xff0c;也可能从网络来。 目录 软、硬件协同设计&#xff1a; 基于标准单元的SoC设计流程&#xff1a; 软、硬件协同设计&#xff1a; SoC 通常被称作系统级芯片…