本文主要讲述了maven项目创建后进行的一些基础配置及对数据库操作的前置准备工作(pom.xml、DBUtil类、Image类)。
maven项目创建可以看这里:Servlet-day01 这里面有详细介绍
pom.xml中放置了许多外部包
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.bitgroupId>
<artifactId>java_image_servletartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<name>untitled15 Maven Webappname>
<url>http://www.example.comurl>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.7maven.compiler.source>
<maven.compiler.target>1.7maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
<dependency>
<groupId>com.google.code.gsongroupId>
<artifactId>gsonartifactId>
<version>2.10.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.13version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>1.4version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
dependencies>
<build>
<finalName>java_image_servletfinalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-pluginartifactId>
<version>3.1.0version>
plugin>
<plugin>
<artifactId>maven-resources-pluginartifactId>
<version>3.0.2version>
plugin>
<plugin>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.0version>
plugin>
<plugin>
<artifactId>maven-surefire-pluginartifactId>
<version>2.22.1version>
plugin>
<plugin>
<artifactId>maven-war-pluginartifactId>
<version>3.2.2version>
plugin>
<plugin>
<artifactId>maven-install-pluginartifactId>
<version>2.5.2version>
plugin>
<plugin>
<artifactId>maven-deploy-pluginartifactId>
<version>2.8.2version>
plugin>
plugins>
pluginManagement>
build>
project>
这些包中的具体内容以及如何加入的后续都会一一解释,首先我们这里解释一下这几个
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
用于在Java项目中添加JUnit测试框架。JUnit是一个用于编写和运行单元测试的框架,可以帮助开发者确保他们的代码能够按照预期工作。
<dependency>
<groupId>com.google.code.gsongroupId>
<artifactId>gsonartifactId>
<version>2.10.1version>
dependency>
用于在Java项目中添加Google的Gson库。Gson是一个用于处理JSON数据的Java库,可以将Java对象转换为JSON字符串,也可以将JSON字符串转换为Java对象
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.13version>
dependency>
用于在Java项目中添加MySQL的JDBC驱动。这个驱动允许Java程序与MySQL数据库进行交互。
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
用于在Java Web应用程序中添加Servlet API。Servlet API提供了一组接口和类,用于开发基于Java的Web应用程序。
在Java目录下创建dao包(数据访问层,蔚然数据库展开操作),在dao包中创建DBUtil类
JDBC相关操作不清楚可以看这篇文章:0基础速成Java环境下JDBC编程(细节超全,保姆级教程)
package dao;
import com.mysql.cj.jdbc.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.SynchronousQueue;
public class DBUtil {
//获取数据库连接
private static final String URL = "jdbc:mysql://127.0.0.1:3306/image_table?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";
private static final String USERNAME = "root";
private static final String PASSWORD = "123456";
private static volatile DataSource dataSource = null;
//定义了一个私有的、静态的、易变的DataSource类型的变量,并且将其初始化为null
public static DataSource getDataSource(){
if(dataSource == null){
Synchronized(DBUtil.class);{
if(dataSource == null){
dataSource = new MysqlDataSource();
// MysqlDataSource 对象强制转换为 MysqlDataSource 类型,
// 并使用 setURL()、setUser() 和 setPassword() 方法设置数据库连接的相关信息,包括 URL、用户名和密码。
MysqlDataSource tmpDataSour = (MysqlDataSource) dataSource;
tmpDataSour.setURL(URL);
tmpDataSour.setUser(USERNAME);
tmpDataSour.setPassword(PASSWORD);
}
}
}
return dataSource;
}
//建立连接
public static Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
//关闭连接
public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) throws RuntimeException {
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if(preparedStatement != null){
try {
preparedStatement.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (connection != null){
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
private static void Synchronized(Class<DBUtil> dbUtilClass) {
}
}
private static final String URL = "jdbc:mysql://127.0.0.1:3306/image_table?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";
private static final String USERNAME = "root";
private static final String PASSWORD = "123456";
(1)
jdbc:mysql://127.0.0.1:3306/image_table?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";
127.0.0.1:3306/数据库服务器的地址
image_table数据库名,写自己需要对数据库中操作的那个数据库的名字
characterEncoding=utf8:客户端和服务器之间的通信字符编码为UTF-8
useSSL=false:表示不使用SSL进行安全连接
serverTimezone=UTC:设置服务器的时区为UTC
allowPublicKeyRetrieval=true:允许从服务器获取公钥。执行需要公钥认证的操作(如SSL/TLS连接)是必要的(2)
private static final String USERNAME = "root";:表示该数据库的名字为root
(3)private static final String PASSWORD = "123456";:表示该数据库的密码为123456
这是一个单例模式且线程安全的获取数据库连接的代码
单例模式详解:我给面试官讲解了单例模式后,他对我竖起了大拇指!
线程安全详解:多线程中synchronized和volatile-解决线程安全问题
private static DataSource dataSource = null;
public static DataSource getDataSource(){
if(dataSource == null){
dataSource = new MysqlDataSource();
//类型加强,将dataSource 对象强制转换为 MysqlDataSource 类型
MysqlDataSource tmpDataSour = (MysqlDataSource) dataSource;
//使用 setURL()、setUser() 和 setPassword() 方法设置数据库连接的相关信息,包括 URL、用户名和密码
tmpDataSour.setURL(URL);
tmpDataSour.setUser(USERNAME);
tmpDataSour.setPassword(PASSWORD);
}
public static Connection getConnection() throws SQLException {
//从一个数据源(DataSource)对象中获取数据库连接,以便执行SQL语句和操作数据库。
// 数据源可以是配置文件中定义的数据源,也可以是通过编程方式创建的数据源
return getDataSource().getConnection();
}
(1)
dataSource这个对象在一个程序中只用存在一份,且在使用前线判断是否创建了,若没有则创建,若已经创建则将URL,USERNAME,PASSWORD等信息设置进去
(2)if(dataSource == null){ dataSource = new MysqlDataSource(); } return dataSource;判断dataSource是否为空,为空说明还未创建,此时应该创建dataSource对象并调用相关方法设置数据库 URL、数据库名和密码,若不为空则直接返回dataSource
这个判断很明显可以看出来这段代码为单例模式中的懒汉模式(3)上述代码很明显不是一个线程安全的代码,解决方法:
首先:用
volatile让dataSource变量每次读取都会去主存中获取最新值,每次写入都会立即写主存(volatile不能保证原子性,即它不能替代synchronized关键字实现同步操作) 其次:Synchronized(DBUtil.class):同步块,确保在多线程环境下,只有一个线程可以执行这个代码块。锁对象为DBUtil.class 最后:在Synchronized(DBUtil.class)`同步块外加入一个if判断,判断dataSource变量是否为空(4)
return getDataSource().getConnection();调用了getDataSource()方法获取数据源对象,然后调用该对象的getConnection()方法获取数据库连接,并将连接返回。
在java目录下的dao包中创建Image类
package dao;
public class Image {
private int imageId;//图片ID
private String imageName;//图片名字
private int size;//图片大小
private String uploadTime;//图片上传时间
private String contentType;//图片类型
private String path;//图片存储路径
private String md5;//图片md5校验和
}
然后进行自动生成get方法、set方法和toString方法方便在后期直接调用这些方法
(1)自动生成get和set方法:alt+ins 选择Getter and Setter 全选,按下OK
(2)自动生成toString方法:alt+ins 选择toString… 全选,按下OK
最后结果:
package dao;
public class Image {
private int imageId;//图片ID
private String imageName;//图片名字
private int size;//图片大小
private String uploadTime;//图片上传时间
private String contentType;//图片类型
private String path;//图片存储路径
private String md5;//图片md5校验和
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getUploadTime() {
return uploadTime;
}
public void setUploadTime(String uploadTime) {
this.uploadTime = uploadTime;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getImageName() {
return imageName;
}
public void setImageName(String imageName) {
this.imageName = imageName;
}
@Override
public String toString() {
return "Image{" +
"imageId=" + imageId +
", imageName='" + imageName + '\'' +
", size=" + size +
", uploadTime='" + uploadTime + '\'' +
", contentType='" + contentType + '\'' +
", path='" + path + '\'' +
", md5='" + md5 + '\'' +
'}';
}
}
