信息概览
✍️日期:2024.04.21
🙋面向对象:从0开始学JavaWeb,了解并动手实践完成数据库三种连接方式
📖参考书籍源码:《JavaWeb编程技术(第三版)》(沈泽刚)第五章
💫内容概要:① 实现连接所需安装与设置的操作步骤 ② 学习与拓展参考链接 ③ 常见bug的处理方式 ④ 测试与实现连接的源码
🙌使用版本信息 :
- IDE : IDEA
- tomcat版本:8.5.99
- 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目录下(如图)
② web项目的WEB-INF 的lib目录下(如图)
③ IDEA左上角项目结构-模块-库-找到驱动包的位置导入(记得点击弹窗右下角的“应用”进行确定与保存)
1.2 创建 一个JavaBean对象
step1 . 创建com.model包并创建User实体 类 (该实体类需要与数据库中的表进行对应)
假设我们创建了一个名为test的schema / 数据库,里面有一个名为user 的表,表内有四个字段,
那么 : 创建的实体类User对应的是表user | 创建user的四个属性对应的是 四个字段
而test在后续设置数据库源的url中也有对应关系
step2 . 完成以下内容:
① 创建属性且访问权限符为 private 类型
② 对应的所有属性都需要设置setter和getter方法
③(非必须步骤) 创建构造函数,一个无参的构造函数和其它自定义的构造函数
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
安装完成如图:
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下
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. 准备:在数据库中设置记录
step2 .打开queryUser.jsp页面
step3 .输入"张三"后确定查询显示结果
step4. 点击"查询所有用户"显示结果
方式二:JNDI连接
🙋前言:此处推荐使用配置全局数据源,其它配置方式与配置属性说明可以参考其它链接
且似乎不同的博文配置的操作可能有一点点差异
👉参考链接:
tomcat服务器配置jndi数据源_tomcat配置jndi需要添加jar包吗-优快云博客
1.全局数据源配置
主要进行操作的是tomcat/conf目录下的server.xml 与 context.xml
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&characterEncoding=utf8&ampzeroDateTimeBehavior=convertToNull&useSSL=true&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包,但没有报错;若有报错,可以自行加上)
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
更新完成后项目结构里面会看到如下内容(第二个与第三个 mchange的内容)
2.创建c3p0-config.xml文件
在resources的目录下创建c3p0-config.xml文件,放入如下内容
🤔注意事项
① 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>