IDEA创建的web项目Maven改造,使用project/module模式,优化数据库连接池
JavaEE作业管理系统(2)
IDEA创建的web项目Maven改造
Maven是什么?为什么用Maven?或者说它能干什么?
- 简单说它是项目构建管理工具,类似npm、yum那样的包管理,也可以理解为是个框架。
- 如果项目非常庞大,就不适合使用package来划分模块,最好是每一个模块对应一个工程,利于分工协作。
- 普通项目:项目中使用jar包,需要“复制”、“粘贴”项目的lib中; jar包需要的时候每次都要自己准备好或到官网下载; 一个jar包依赖其他的jar包需要自己手动的加入到项目中。
- 借助于maven,可以将jar包保存在“仓库”中,不管在哪个项目只要使用引用即可就行。借助于maven,所有的jar包都放在“仓库”中,所有的项目都使用仓库的一份jar包。借助于maven,它会自动的将依赖的jar包导入进来。
开始行动
- 打开项目,右击项目根目录,选择“添加框架支持”(Add Framework Support),如图,勾选maven,点击确定。
![在这里插入图片描述]()
- 完成后项目多一个pom.xml文件,并且项目目录变成src目录下多了一个main文件夹,它用来放置java源码和web网页文件的源码,这里需要手动把原来web文件夹移动到main目录下,并更名为webapp(这是默认命名),更改后看到上面有个蓝点,代表成功完成,如图。
pom.xml:Project Object Model 项目对象模型。它是maven的核心配置文件,所有的构建的配置都在这里设置。

- 配置pom.xml文件:
<!--公司或组织域名.组织.项目(模块)名,
域名:eg: cn(China),org(非营利组织),com(商业组织)
组织:个人的小项目为 Only
-->
<groupId>cn.Only.JavaEE02</groupId>
<!--project/module-->
<artifactId>JavaEE02</artifactId>
<!--版本号-->
<version>1.0-SNAPSHOT</version>
使用上面的三个向量(也称为坐标)在仓库中唯一的定位一个maven工程。
- 继续配置pom.xml文件:
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>10.0.2</java.version>//符合自己的JDK版本
<maven.compiler.source>10.0.2</maven.compiler.source>
<maven.compiler.target>10.0.2</maven.compiler.target>
</properties>

重要提示:当IDEA右下角弹出弹窗import change 时一定选择该项点击。
- 检查如图所示:

至此我们maven改造完成,接下来我们新建个项目,使用project/module模式,然后将这个改造好的maven项目移植到这个module模式的项目中。
如果你对maven还很迷糊儿,欢迎点击这里Maven最全笔记,大佬一定能解决你99%的疑问。好了,我们休息一会...
使用project/module模式
project和module的关系:

如果你使用过Eclipse,很容易理解,为什么使用project/module模式?
答:因为这样每个module可以独立成我们以前开发的那种小项目,便于管理大项目。
- IntelliJ系中的 Project 相当于Eclipse系中的 Workspace ;
- IntelliJ系中的 Module 相当于Eclipse系中的 Project ;
- IntelliJ中一个 Project 可以包括多个 Module ;
- Eclipse中一个 Workspace 可以包括多个 Project;
开始行动
-
新建一个空的Maven工程,如图:
![在这里插入图片描述]()
-
添加GroupId和ArtifactId,ArtfactId就是整个工程文件(project)名。
![在这里插入图片描述]()
然后下一步,选择项目储存位置,确定即可。 -
创建module,右击工程文件目录:
![在这里插入图片描述]()
勾选Maven,下一步:
![在这里插入图片描述]()
确定Parent,ArtifactId,下一步:
![在这里插入图片描述]()
-
新建完成后删除原有的src文件夹 ,使用同样的方法,创建 Core 及 Database 两个 module。Core: 用来包含一些常用变量;Database:数据层,与数据库连接有关的类。如图所示:
![在这里插入图片描述]()
将上一个改造好的Maven项目,移植到这个JavaEE31(module)中:
![在这里插入图片描述]()
-
配置该module的pom.xml文件:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>10.0.2</java.version>
<maven.compiler.source>10.0.2</maven.compiler.source>
<maven.compiler.target>10.0.2</maven.compiler.target>
</properties>
import changes,别忘了!
- 然后打开Tomcat配置(如果没有添加Tomcat,再添加一下template即可),选择这个要运行的module的exploder。路径设置为“/”。
![在这里插入图片描述]()
- 运行成功!
优化数据库连接池
数据库连接优化的原因
- 之前的JDBC连接不安全,比如同一个用户在两处同时访问一个数据库,这会造成线程不安全。
- 把访问数据库的每一步封装一个函数,生成日志,这样便于事务管理。
开始行动
- 第一步,添加依赖,完善pom.xml文件:
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>Database</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.22</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.22</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.22</version>
</dependency>
</dependencies>
-
数据库连接的用户名密码等放在配置文件中
比如我新建一个db.properties文件,它是HikariConfig类的读取对象。
放在resources文件夹下:
![在这里插入图片描述]()
-
JdbcUtil.java(JDBC连接对象的工具类)
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
/**
*用于获取数据库连接对象的工具类。
*/
public class JdbcUtil {
private static DataSource dataSource;
private static ThreadLocal<Connection> tl = new ThreadLocal<>();
private static final Object obj = new Object();
private static final Logger log = LoggerFactory.getLogger(jdbc.JdbcUtil.class);
static {
init();
}
/**
*获取数据库连接对象的方法,线程安全
*/
public static Connection getConnection() throws SQLException {
// 从当前线程中获取连接对象
Connection connection = tl.get();
// 判断为空的话,创建连接并绑定到当前线程
if(connection == null) {
synchronized(obj) {
if(tl.get() == null) {
connection = createConnection();
tl.set(connection);
}
}
}
return connection;
}
/**
*释放资源
*/
public static void release(Connection conn, Statement statement, ResultSet resultSet) {
if(resultSet != null) {
try {
resultSet.close();
} catch(SQLException e) {
log.error("关闭ResultSet对象异常", e);
}
}
if(statement != null) {
try {
statement.close();
} catch(SQLException e) {
log.error("关闭Statement对象异常", e);
}
}
// 注意:这里不关闭连接
if(conn != null) {
try {
conn.close();
tl.remove();
} catch(SQLException e) {
log.error("关闭Connection对象异常", e);
}
}
}
/**
*开启事务
*/
public static void startTransaction() throws SQLException {
getConnection().setAutoCommit(false);
}
/**
*提交事务
*/
public static void commit() {
Connection connection = tl.get();
if(connection != null) {
try {
connection.commit();
connection.setAutoCommit(true);
} catch(SQLException e) {
log.error("提交事务失败", e);
}
}
}
/**
*回滚事务
*/
public static void rollback() {
Connection connection = tl.get();
if(connection != null) {
try {
connection.rollback();
connection.setAutoCommit(true);
} catch(SQLException e) {
log.error("回滚事务失败", e);
}
}
}
public static DataSource getDataSource() {
return dataSource;
}
public static void setDataSource(DataSource dataSource) {
jdbc.JdbcUtil.dataSource = dataSource;
tl.remove();
}
/**
*创建数据库连接
*/
private static Connection createConnection() throws SQLException {
if(dataSource == null) {
throw new RuntimeException("创建数据源失败");
}
Connection conn = null;
// 获得连接
conn = dataSource.getConnection();
return conn;
}
/**
*根据指定配置文件创建数据源对象
*/
private static void init() {
try {
HikariConfig config = new HikariConfig("/db.properties");
dataSource = new HikariDataSource(config);
} catch(Exception e) {
log.error("创建数据源失败", e);
}
}
}
- 在TeacherJdbc.java和StudentJdbc.java中修改使用方式(提示:可以借助IDEA的查找替换功能,多出代码同时替换),更新和查询操作示例:
public boolean Teacher_login(String sno, String password) {
PreparedStatement stmt = null;
Connection conn = null;
boolean flag=false;
String sql= "SELECT PASSWORD FROM TEACHER WHERE TNO=(?) ";
try {
// 获得连接
conn = jdbc_util.getConnection();
// 开启事务,非自动提交
jdbc_util.startTransaction();
//创建可执行语句
stmt = conn.prepareStatement(sql);
stmt.setString(1, sno);
ResultSet rs = stmt.executeQuery();
if(rs.next()&&rs.getString("password").equals(password)){
flag=true;
}else {
flag=false;
}
} catch (SQLException e) {
jdbc_util.rollback();//事务回退
}finally {
// 释放资源,结果集设置为null
jdbc_util.release(conn, stmt, null);
}
return flag;
}
public void AddTeacher(Teacher teacher) {
PreparedStatement stmt = null;
Connection conn = null;
String sql;
sql = "INSERT INTO TEACHER VALUES (?,?,?)";
try {
// 获得连接
conn = jdbc_util.getConnection();
// 开启事务,非自动提交
jdbc_util.startTransaction();
//创建可执行语句
stmt = conn.prepareStatement(sql);
stmt.setString(1, teacher.getTno());
stmt.setString(2, teacher.getTname());
stmt.setString(3, teacher.getPassword());
stmt.executeUpdate();
} catch (SQLException e) {
jdbc_util.rollback();//事务回退
} finally {
// 释放资源,结果集设置为null
jdbc_util.release(conn, stmt, null);
}
}
主要改动这几处:

- 最后检查服务器依赖是否全部引入,如果没有按箭头所示引入。
![在这里插入图片描述]()












浙公网安备 33010602011771号