IDEA创建的web项目Maven改造,使用project/module模式,优化数据库连接池

JavaEE作业管理系统(2)


github源码地址

IDEA创建的web项目Maven改造


Maven是什么?为什么用Maven?或者说它能干什么?

  1. 简单说它是项目构建管理工具,类似npm、yum那样的包管理,也可以理解为是个框架。
  2. 如果项目非常庞大,就不适合使用package来划分模块,最好是每一个模块对应一个工程,利于分工协作。
  3. 普通项目:项目中使用jar包,需要“复制”、“粘贴”项目的lib中; jar包需要的时候每次都要自己准备好或到官网下载; 一个jar包依赖其他的jar包需要自己手动的加入到项目中。
  4. 借助于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。路径设置为“/”。
    在这里插入图片描述
  • 运行成功!

优化数据库连接池


数据库连接优化的原因

  1. 之前的JDBC连接不安全,比如同一个用户在两处同时访问一个数据库,这会造成线程不安全。
  2. 把访问数据库的每一步封装一个函数,生成日志,这样便于事务管理。

开始行动

  • 第一步,添加依赖,完善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);
        }
    }

主要改动这几处:
在这里插入图片描述

  • 最后检查服务器依赖是否全部引入,如果没有按箭头所示引入。
    在这里插入图片描述
posted @ 2020-05-04 15:43  King_MoYang  阅读(512)  评论(0)    收藏  举报