JavaWeb | 数据库的三种连接方式 JDBC、JNDI、c3p0

信息概览

✍️日期:2024.04.21
🙋面向对象:从0开始学JavaWeb,了解并动手实践完成数据库三种连接方式
📖参考书籍源码:《JavaWeb编程技术(第三版)》(沈泽刚)第五章
💫内容概要:① 实现连接所需安装与设置的操作步骤 ② 学习与拓展参考链接 ③ 常见bug的处理方式 ④ 测试与实现连接的源码
🙌使用版本信息 :

  1. IDE : IDEA
  2. tomcat版本:8.5.99
  3. MySQL版本:8.0

方式一:JDBC连接

👉参考链接

【java】Java连接mysql数据库及mysql驱动jar包下载和使用_mysql jar-优快云博客
MySQL官网下载mysql的jar包步骤_mysql jar包下载-优快云博客

1.准备 (以Mysql为例)

1.1 下载 mysql驱动jar包

[ 按照上面参考链接的第二个,有完整的步骤 ]
下载链接:https://dev.mysql.com/downloads/connector/j/

🤔注意
① 版本需要对应 [ 比如MySQL8不能下载5的,否则可能出现java.lung.nullPointerException的报错 ]
②为防止不必要的报错,将下载后将得到的jar包放在三个位置
[ 或者可以一个位置一个位置的添加,不报错即可。因为到后面更新pom.xml 项目结构里面没有不会报错 ]

[ 三个位置 ]
① tomcat的lib目录下(如图)
image.png
② web项目的WEB-INF 的lib目录下(如图)
image.png
③ IDEA左上角项目结构-模块-库-找到驱动包的位置导入(记得点击弹窗右下角的“应用”进行确定与保存)
image.png
image.png

1.2 创建 一个JavaBean对象
step1 . 创建com.model包并创建User实体 类 (该实体类需要与数据库中的表进行对应)
假设我们创建了一个名为test的schema / 数据库,里面有一个名为user 的表,表内有四个字段,
那么 : 创建的实体类User对应的是表user | 创建user的四个属性对应的是 四个字段
而test在后续设置数据库源的url中也有对应关系
image.png
step2 . 完成以下内容:
① 创建属性且访问权限符为 private 类型
② 对应的所有属性都需要设置setter和getter方法
③(非必须步骤) 创建构造函数,一个无参的构造函数和其它自定义的构造函数
image.png

1.3 创建jsp页面作为测试,需要创建如下三个jsp页面(先不管前端的页面是否美观问题)
page1 .查询页面( queryUser.jsp ):

<!--
Date:2024.04.21
description:查询user的jsp页面
-->
<%@ page contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<html>
<body>
<p><a href="user-query-3">查询所有用户</a></p>
<div class="center_user_content">
    <div class="queryForm">
        <form action="user-query-3" method="post">
            <p style="font-weight: bold;color: #797a7a">请输入用户姓名
                <input  type="text" name="username" >
            </p>
            <div class="button">
                <button type="submit" class="confirmButton">确定查询</button>
                <button type="reset" class="cancelButton">取消</button>
            </div>
        </form>
    </div>
</div>
</body>
</html>

page2. 展示单个查询结果(displayUser.jsp)

其中,
<jsp:useBean id="user" type="com.model.User"scope="session"></jsp:useBean>用于声明JavaBean对象 ,type的内容则为刚才创建的实体类所在位置
<td><jsp:getProperty name="user" property="userId"/></td>
property为实体类中定义的属性名
name为jsp:useBean声明的对象名

<%--
date:2024.04.17
description:展示单个查询结果
--%>
<%@ page contentType="text/html; charset=utf-8" %>
<jsp:useBean id="user" type="com.model.User"
             scope="session"></jsp:useBean>
<html>
<head>
    <title>显示单个用户</title>
</head>
<body>
<div>
    <table border="0" class="user-table" width="700" height="100">
        <tr><th>用户ID</th><th>用户名</th><th>用户性别</th><th>电话号码</th>
        </tr>
        <tr>
            <td><jsp:getProperty name="user" property="userId"/></td>
            <td><jsp:getProperty  name="user" property="userName" /></td>
            <td><jsp:getProperty  name="user" property="userSex" /></td>
            <td><jsp:getProperty  name="user" property="phoneNumber" /></td>
        </tr>
    </table>
</div>
</body>
</html>

page3. 展示所有结果(displayAllUser.jsp)

🤔说明:
①此处不用useBean,而是<%@ taglib prefix="c" uri="[http://java.sun.com/jsp/jstl/core"](http://java.sun.com/jsp/jstl/core") %>,使用自定义标签
② 通过遍历servlet传来userList来获取结果

<%@ page contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ page import="java.util.*,com.model.User" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>显示所有用户</title>
</head>
<body>
<table border="1">
    <tr>
        <th>用户ID</th>
        <th>用户名</th>
        <th>电话号码</th>
        <th>性别</th>
    </tr>
    <% ArrayList<User> userList = (ArrayList<User>) session.getAttribute("userList");
        for(User user : userList) { %>
    <tr>
        <td><%= user.getUserId() %></td>
        <td><%=user.getUserName()%>
        <td><%=user.getPhoneNumber() %></td>
        <td><%=user.getUserSex()%></td>
    </tr>
    <%} %>
</table>
</body>
</html>

🐞可能出现的bug:
Bug1. <%@ taglib prefix=“c” uri="[http://java.sun.com/jsp/jstl/core"]%> 句子报红问题
解决:
参考链接:解决idea中http://java.sun.com/jsp/jstl/core“红色异常_idea jsp标红-优快云博客
下载zip链接:Index of /dist/jakarta/taglibs/standard/binaries
安装完成如图:
image.png

Bug2 .无法解析jar文件
org.apache.jasper.JasperException: 无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[[http://java.sun.com/jsp/jstl/]]
解决:
在tomcat/conf / catalina.properties文件下找到语句:
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=*.jar
修改为:
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=<br />**

注:日志可能会显示如下信息,但不影响正常运行
Apr-2024 11:47:13.381 信息 [localhost-startStop-1] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。

Bug3.(非必须步骤,但出现bug可尝试)为防止出现其它bug,最好将standard 和 jst两个jar包放到WEB-INF的lib下和 tomcat的lib下
image.png

page4. 显示查找不到用户的情况(error.jsp)

<%@ page contentType="text/html; charset=UTF-8" %>
<html><body>
查找不到该用户
<a href="queryUser.jsp">返回</a>
</body></html>

2.在servlet进行JDBC连接并设置方法

step1 . JDBC连接

✍️注意事项
① 该类需要继承HttpServlet,否则getServletContext()方法会报错

🌤️实现思路
初始化信息 -> 加载驱动程序 -> 创建连接对象 -> 结束后销毁

package com.demo;
import javafx.scene.layout.HBox;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

@WebServlet("addUser")
public class addUserServlet  extends HttpServlet {
    private static final long serialVersionUID = 1L;
    Connection dbconn = null;
    public void init () {
        // 初始化信息
        // driver:一般用的是这个
        String driver = "com.mysql.cj.jdbc.Driver";
        // xxx是数据库的名称
        // 如jdbc:mysql://localhost:3306/testSystem?serverTimezone=UTC&&useUnicode=true&characterEncoding=utf-8    
        // 后面的是设置时区和字符编码
        String dburl = "jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC&&useUnicode=true&characterEncoding=utf-8";
        // 用户名和密码,在创建数据源的时候可以看到
        String username = "root";
        String password = "123456";
        try {
            // 加载驱动程序
            Class.forName(driver); 
            // 创建连接对象
            dbconn = DriverManager.getConnection(dburl, username, password);
        } catch (ClassNotFoundException e1) {
            // 记录异常到日志
            getServletContext().log("驱动程序类找不到!", e1);
        } catch (SQLException e2) {
            // 记录异常到日志
            getServletContext().log("数据库连接失败!", e2);
        }
    }

    public void destroy () {
        try {
            dbconn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

step2. doPost | doGet 方法 [ 通用于另外两种连接方式,主要方便测试 ]

✍️注意事项 / 易错点
① doPost / doGet 方法request.setCharacterEncoding(“UTF-8”);
语句如果缺失,查询的参数
传入中文时会查询不到结果

② getParameter里面的参数与jsp页面form表单里面对应的name应一致
③为sql语句传入参数的索引从1开始(不是0)
不同类型的sql语句执行语句不同,当执行插入语句时为executeUpdate()
⑤ rst用get方法获取参数,数据类型应与实体类set的对应属性的数据类型一致
⑥ rst.getLong(“user_id”) 括号内的参数名应与数据库表的字段名一致

🌤️实现思路
① 获取查询参数
② 设置sql语句,将需要传入的参数用问号(?)代替,预编译后用setString传入查询参数
③ 查询语句执行:executeQuery()
④ 遍历查询记录
⑤ 将查询结果封装成user(JavaBean对象)传入当前的会话的user属性里面,jsp可以通过user属性来获取到查询结果

  public void doPost (HttpServletRequest request,
                        HttpServletResponse response)
            throws ServletException, IOException {
      // 1. 获取中文的查询参数 
        request.setCharacterEncoding("UTF-8");
        String username = request.getParameter("username");
        response.setContentType("text/html;charset=utf-8");
        try { 
            // 2. 设置sql语句 
            String sql = "SELECT * FROM user WHERE user_name = ?";
            // 2.1 执行预编译
            PreparedStatement pstmt = dbconn.prepareStatement(sql);
            // 2.2 传入参数 
            pstmt.setString(1,username);
            // 3. 执行sql语句
            ResultSet rst = pstmt.executeQuery();
            // 4. 遍历查询记录
            if (rst.next()) {
                User user = new User();
                // 数据类型 与 参数名一致问题 
                user.setUserId(rst.getLong("user_id"));
                user.setUserName(rst.getString("user_name"));
                user.setPhoneNumber(rst.getString("user_phonenumber"));
                user.setUserSex(rst.getString("user_sex"));
                request.getSession().setAttribute("user", user);
                response.sendRedirect("displayUser.jsp");
            } else {
                response.sendRedirect("error.jsp");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

3.测试结果

step1. 准备:在数据库中设置记录
image.png
step2 .打开queryUser.jsp页面
image.png
step3 .输入"张三"后确定查询显示结果
image.png
step4. 点击"查询所有用户"显示结果
image.png

方式二:JNDI连接

🙋前言:此处推荐使用配置全局数据源,其它配置方式与配置属性说明可以参考其它链接
且似乎不同的博文配置的操作可能有一点点差异
👉参考链接:
tomcat服务器配置jndi数据源_tomcat配置jndi需要添加jar包吗-优快云博客

1.全局数据源配置

主要进行操作的是tomcat/conf目录下的server.xml 与 context.xml
image.png
step1 . 在server.xml 的 元素下添加如下内容

🤔注意事项
① name是自定义的(jdbc / xxx格式),但后面与context.xml里面需要对应一致(global 与 name )
② username和password需要根据自身情况进行修改
③ url 与 JDBC连接的dburl一致,xxx为数据库名称

✍️添加内容

    <Resource
            name="jdbc/testlWebDS"
  		scope="Shareable"   
            type="javax.sql.DataSource"
            maxTotal="4"
            maxIdle="2"
     	username="root"
   maxWaitMillis="5000"
            password="123456"
driverClassName="com.mysql.cj.jdbc.Driver"
      url = "jdbc:mysql://127.0.0.1:3306/xxx?useUnicode=true&amp;characterEncoding=utf8&amp;ampzeroDateTimeBehavior=convertToNull&amp;useSSL=true&amp;serverTimezone=GMT%2B8"     
/>

step2.在context.xml 内添加如下内容
🤔注意事项
①global 与 name 和前面的一致
② name是数据源名称, 与前面对应一致

 <ResourceLink
       global = "jdbc/testWebDS"
       name = "jdbc/testWebDS"
       type="javax.sql.DataSource"/>

2.Servlet实现代码

🤔与JDBC的区别
① 对 init 方法进行修改,当没有连接到时,可能会报错:
javax.naming.NameNotFoundException: 名称[testWebDS]未在此上下文中绑定。找不到[testWebDS]。
此时需要检查上面的连接方式与操作位置是否正确
② 没有destroy方法
doGet 与 doPost方法不变

package com.demo;
import com.model.User;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
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.HashMap;
/**
 * 数据源连接方式
 */
@WebServlet("/user-query-2")
public class queryUserServlet2 extends HttpServlet {
    private static final long serialVersionUID = 1L;
    Connection dbconn = null;
    DataSource dataSource = null;
    public  void init(){
        try{
            // 对应需要抛出NamingException
            Context context = new InitialContext();
            dataSource = (DataSource)context.lookup("java:comp/env/jdbc/testWebDS");
            // 对应需要抛出SQLException
            dbconn = dataSource.getConnection();
        }catch (NamingException ne){
            System.out.println("datasource异常:"+ne);
        }catch(SQLException se){
            System.out.println("conn异常:"+se);
        }
    }
}

3.测试结果

基于第一种方法的前提准备(JavaBean对象、数据库表建立、四个jsp页面);
修改queryUser.jsp中的后端映射URL,即将user-query改为user-query-2,结果一致

<!--
Date:2024.04.21
description:查询user的jsp页面(方法2)
-->
<%@ page contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<html>
<body>
<p><a href="user-query-2">查询所有用户</a></p>
<div class="center_user_content">
    <div class="queryForm">
        <form action="user-query-2" method="post">
            <p style="font-weight: bold;color: #797a7a">请输入用户姓名
                <input  type="text" name="username" >
            </p>
            <div class="button">
                <button type="submit" class="confirmButton">确定查询</button>
                <button type="reset" class="cancelButton">取消</button>
            </div>
        </form>
    </div>
</div>
</body>
</html>


方式三:c3p0连接方式

👉参考链接:
c3p0数据库连接池_c3p0 database server running in secondary mode.-优快云博客

1.pom.xml添加信息

在pom.xml中的dependencies元素下添加如下内容,添加完成后更新maven项目( pom.xml内容发生变化时会自动显示该按钮 )
(没有在tomcat-lib 或者 WEB-INF-lib目录下加入jar包,但没有报错;若有报错,可以自行加上)
image.png

<dependency>
  <groupId>com.mchange</groupId>
  <artifactId>c3p0</artifactId>
  <version>0.9.5.2</version>
</dependency>

更新完成后项目结构里面会看到如下内容(第二个与第三个 mchange的内容)
image.png

2.创建c3p0-config.xml文件

在resources的目录下创建c3p0-config.xml文件,放入如下内容
image.png

🤔注意事项
① name是自定义的,但在servlet里面需要对应上
② jdbcUrl 与 前两种方式的url一致
③ user 和 password 根据自身进行修改

3.Servlet实现代码

修改init的内容如下,doPost与doGet内容不变

package com.demo;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.model.User;
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;

@WebServlet("/user-query-3")
public class queryUserServlet3  extends HttpServlet {
    private static DataSource dataSource = null;
    Connection dbconn = null;
    public  void init(){
        try{
            // 输入的参数是named-config name="testApp" 中name属性的值
            ComboPooledDataSource cpds = new ComboPooledDataSource("testApp");
            // Connection 要抛出SQLException
            dbconn = cpds.getConnection();
        }catch (SQLException se){
            System.out.println(se);
        }
    }
}

4.测试结果

queryUser.jsp的修改对应响应
基于第一种方法的前提准备(JavaBean对象、数据库表建立、四个jsp页面);
修改queryUser.jsp中的后端映射URL,即将user-query改为user-query-3,结果一致

<!--
Date:2024.04.21
description:查询user的jsp页面(方法3)
-->
<%@ page contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<html>
<body>
<p><a href="user-query-3">查询所有用户</a></p>
<div class="center_user_content">
    <div class="queryForm">
        <form action="user-query-3" method="post">
            <p style="font-weight: bold;color: #797a7a">请输入用户姓名
                <input  type="text" name="username" >
            </p>
            <div class="button">
                <button type="submit" class="confirmButton">确定查询</button>
                <button type="reset" class="cancelButton">取消</button>
            </div>
        </form>
    </div>
</div>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值