0x01 环境搭配
如果还不会搭建jsp环境的可以按照下面的文章跟着搭建
Mac版IDEA创建maven web项目-详细过程: https://www.yuque.com/pmiaowu/gpy1q8/npv0fr
0x02 导入数据库驱动
0x02.1 maven自动添加
打开: https://mvnrepository.com/
搜索: MySQL
点进去: https://mvnrepository.com/artifact/mysql/mysql-connector-java
我这里选择5.1.41
打开: https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.41
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.41</version></dependency>
0x02.2 手动导入
首先介绍如何手动下载jar包
打开: https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.41
下载地址: https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.41/mysql-connector-java-5.1.41.jar
0x03 JDBC链接数据库
// 使用例子# 目录结构├── src│ └── main│ └── webapp│ └── com│ └── Servlet│ ├── ...│ └── DBTest.java│ └── WEB-INF│ └── web.xml│ └── index.jsp
package com.Servlet;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.*;@WebServlet("/DBTest")public class DBTest extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {String DRIVER_NAME = "com.mysql.jdbc.Driver";// jdbc:mysql://[mysql地址]:[mysql端口]/[要连接的数据库名]String URL = "jdbc:mysql://192.168.24.145:3306/mysql";String USER_NAME = "root";String PASSWORD = "123456";Connection connection = null;try {//加载mysql的驱动类Class.forName(DRIVER_NAME);//获取数据库连接connection = DriverManager.getConnection(URL, USER_NAME, PASSWORD);//mysql查询语句String sql = "SELECT * FROM `user`";PreparedStatement prst = connection.prepareStatement(sql);//结果集ResultSet rs = prst.executeQuery();while (rs.next()) {response.getWriter().println(" ");response.getWriter().println("用户名:" + rs.getString("User")+" "+"密码:" + rs.getString("Password"));}rs.close();prst.close();} catch (Exception e) {e.printStackTrace();}finally {if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}}// 执行该文件// 例如: http://127.0.0.1:8081/mavenJspTest_war/DBTest
0x04 问题小结
在开始使用的时候,我一直不理解
为什么第一步需要Class.forName("com.mysql.jdbc.Driver");
不可以删除么?于是删除以后,我发现还是可以正常连接数据库,这让我更加迷惑了
0x04.1 为什么需要Class.forName?
经过查看源码终于理解了
首先我们要知道Class.forName("xxxx")的功能: 除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块
那么Class.forName("com.mysql.jdbc.Driver");干了什么?
先进入com.mysql.jdbc.Driver类
看到这里大致就明白了,也就是说Class.forName("com.mysql.jdbc.Driver");实际上会触发类加载com.mysql.jdbc.Driver类将会被初始化,并且执行类中的static块
实际上这一步就是利用了Java反射+类加载机制往DriverManager中注册了驱动包
0x04.2 删除了Class.forName为什么还可以?
为什么我不加Class.forName("com.mysql.jdbc.Driver");一样可以正常连接数据库?
实际上这里利用了Java的一大特性: Java SPI(Service Provider Interface)DriverManager在初始化时,会调用java.util.ServiceLoader类提供的SPI机制
然后Java自动扫描jar包中的META-INF/services目录下的文件,并且还会自动的Class.forName文件中定义的类
这就是为什么不需要Class.forName也能够成功连接数据库的原因了
怎么判断有没有用SPI?可以考察如下示例
方法一: 查看包的结构,Mysql驱动包示例:
如上图, META-INF/services下面能看到长的很像类的完全限定名,就八九不离十了。
方法二: 通过查看源码
例如: 查看DriverManager类
查找java.util.ServiceLoader.load看看是否有调用
0x05 课外知识补充
如果想反射某个类又不想初始化类方法可以么?
当然可以,解决方案如下:
- 使用
Class.forName("xxxx", false, loader)方法 - 使用
ClassLoader.loadClass("xxxx")0x06 小结
在实际的项目中,通常不会使用原生的JDBC的DriverManager去连接数据库
而是使用javax.sql.DataSource(数据源)来代替DriverManager
因此本文学习如何使用原生来操作数据库,让自己脑子留个底子即可
有关javax.sql.DataSource(数据源)使用的问题,我们后面在一起学习


