通过一个含多个包且引用外部jar包的项目实例感受Maven的便利性

embedded/2025/1/11 20:33:59/

目录

1 引言

最近在阅读一本Java Web的书籍1时,手工实现书上的一个含多个Packages的例子,手工进行编译、运行,最终实现了效果。但感觉到整个构建过程非常繁琐,不仅要手写各个源文件的编译命令,还要考虑源文件之间的编译先后顺序;同时还要手工下载本项目所依赖的第三方Jar包。考虑到Maven具有自动化构建、依赖管理的功能,当然考虑到基于Maven重新构建和管理本项目。通过Maven工具重新构建此项目,前后对比之强烈,能让人充分感受到Maven在自动化构建、依赖管理方面的便利性,能让程序员从项目构建中解放出来,更加聚焦于业务的实现。

通过阅读本文,Maven的初学者更能深刻理解Maven存在的必要性及其应用场景;同时,对于那些只会手工编译项目的Java程序员来说,给出了切换到Maven的理由。

接下来,先叙述手工构建项目的详细过程,再叙述基于Maven构建同一项目的详细过程,最后给出二种构建方式的对比。本文所用的环境如下:

名称版本
Java1.8.0_281
MySQL8.0.13
Maven3.8.8

2 手工构建

下面给出一个完整的例子,其划分为6个package,每个package中都放有相关的代码。该例子还需访问MySQL数据库。由此,本例子是一个相对大型的、简单的例子,以能凸显手工编译的不便。

  1. 在MySQL中创建数据库、然后创建表:如下:
mysql> create database testweb;
mysql> use testweb;
mysql> CREATE TABLE product(-> product_id varchar(20) NOT NULL,-> product_name varchar(50) DEFAULT NULL,-> price decimal(6,2) DEFAULT NULL,-> info varchar(100) DEFAULT NULL,-> PRIMARY KEY (product_id)-> )ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected, 1 warning (0.84 sec)
  1. 手工建立文件夹结构。创建一个根目录testDAO,再在其中创建三个子文件夹,如下:
    文件夹结构
  2. 在lib文件夹中放入本项目需要引用的第三方包mysql-connector-java-8.0.13.jar
  3. 在src文件夹中放入如下代码(注意代码所在的packages):

Product.java:

java">package com.rob.pojo;import java.io.Serializable;public class Product implements Serializable {private static final long serialVersionUID = 1L;private String product_id;private String product_name;private double price;private String info;public Product(){super();}public String getProduct_id(){return product_id;}public void setProduct_id(String product_id){this.product_id = product_id;}public String getProduct_name(){return product_name;}public void setProduct_name(String product_name){this.product_name = product_name;}public double getPrice(){return price;}public void setPrice(double price){this.price = price;}public String getInfo(){return info;}public void setInfo(String info){this.info = info;}
}

DBConnection.java:

java">package com.rob.db;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class DBConnection {private static final String Driver = "com.mysql.cj.jdbc.Driver";private static final String URL = "jdbc:mysql://localhost:3306/testweb?serverTimezone=Asia/Shanghai&useSSL=false";private static final String USER = "root";private static final String PASSWORD = "123456";private Connection conn = null;public DBConnection() throws Exception {try {Class.forName(Driver);this.conn = DriverManager.getConnection(URL, USER, PASSWORD);} catch(Exception e) {throw e;}}public Connection getConnection(){return this.conn;}public void close() throws Exception {if (this.conn != null){try {this.conn.close();} catch (Exception e) {throw e;}}}// unit test public static void main(String[] args) throws Exception {DBConnection dbconn = new DBConnection();System.out.println("连接成功");try {dbconn.close();} catch (SQLException e) {e.printStackTrace();}}
}

ProductDao.java:

java">package com.rob.dao;import java.util.List;
import com.rob.pojo.Product;public interface ProductDao {/*** 数据库 新增数据*@param product 要增加的数据对象;*@return 是否增加成功的标记*@throws Exception 如果有异常,直接抛出*/public boolean addProduct(Product product) throws Exception ;/*** 查询全部的Product数据*@param product_name 产品名称*@return 返回全部的查询结果,每一个product对象表示表的一行记录*@throws Exception 如果有异常,直接抛出*/public List<Product> findAll(String product_name) throws Exception;/*** 根据产品编号查询产品*@param product_id 产品编号*@return 产品的vo对象*@throws Exception 如果有异常,直接抛出*/public Product findByProductId(String product_id) throws Exception;
}

ProductDaoImpl.java:

java">package com.rob.dao;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;import com.rob.pojo.Product;public class ProductDaoImpl implements ProductDao {private Connection conn = null;private PreparedStatement pstmt = null; // 数据库操作对象public ProductDaoImpl(Connection conn) {this.conn = conn;}public boolean addProduct(Product product) throws Exception {boolean flag = false;String sql = "insert into product(product_id, product_name, price, info) values(?,?,?,?)";this.pstmt = this.conn.prepareStatement(sql); //实例化PrepareStatement对象this.pstmt.setString(1,product.getProduct_id());this.pstmt.setString(2,product.getProduct_name());this.pstmt.setDouble(3,product.getPrice());this.pstmt.setString(4,product.getInfo());if (this.pstmt.executeUpdate() > 0) {flag = true;}this.pstmt.close();return flag;}public List<Product> findAll(String product_name) throws Exception {List<Product> list = new ArrayList<Product>();String sql = "select product_id, product_name, price, info from product";if (product_name != null && !"".equals(product_name)) {sql = "select product_id, product_name, price, info from product where product_name like?";this.pstmt = this.conn.prepareStatement(sql);this.pstmt.setString(1, "%" + product_name + "%");}else {this.pstmt = this.conn.prepareStatement(sql);}ResultSet rs = this.pstmt.executeQuery(); Product product = null;while (rs.next()){product = new Product();product.setProduct_id(rs.getString(1));product.setProduct_name(rs.getString(2));product.setPrice(rs.getDouble(3));product.setInfo(rs.getString(4));list.add(product);}this.pstmt.close();return list;}public Product findByProductId(String product_id) throws Exception {Product product = null;String sql = "select product_id, product_name, price, info from product where product_id=?";this.pstmt = this.conn.prepareStatement(sql);this.pstmt.setString(1, product_id);ResultSet rs = this.pstmt.executeQuery();if(rs.next()){product = new Product();product.setProduct_id(rs.getString(1));product.setProduct_name(rs.getString(2));product.setPrice(rs.getDouble(3));product.setInfo(rs.getString(4));}this.pstmt.close();return product;}
}

ProductService.java:

java">package com.rob.service;import java.util.List;import com.rob.dao.ProductDao;
import com.rob.dao.ProductDaoImpl;
import com.rob.db.DBConnection;
import com.rob.pojo.Product;public class ProductService implements ProductDao {private DBConnection dbconn = null;private ProductDao dao = null;public ProductService() throws Exception {this.dbconn = new DBConnection();this.dao = new ProductDaoImpl(this.dbconn.getConnection());}public boolean addProduct(Product product) throws Exception {boolean flag = false;try {if(this.dao.findByProductId(product.getProduct_id()) == null) {flag = this.dao.addProduct(product);}} catch (Exception e){throw e;} finally {this.dbconn.close();}return flag;}public List<Product> findAll(String keyWord) throws Exception {List<Product> all = null;try {all = this.dao.findAll(keyWord);} catch( Exception e) {throw e;}finally {this.dbconn.close();}return all;}public Product findByProductId(String product_id) throws Exception {Product product = null;try {product = this.dao.findByProductId(product_id);} catch (Exception e){throw e;} finally {this.dbconn.close();}return product;}
}

DAOFactory.java:

java">package com.rob.factory;import com.rob.dao.ProductDao;
import com.rob.service.ProductService;public class DAOFactory {public static ProductDao getIEmpDAOInstance() throws Exception {return new ProductService();}
}

最后是整个项目的主代码:TestInsertProduct.java:

java">package com.rob.test;import com.rob.factory.DAOFactory;
import com.rob.pojo.Product;public class TestInsertProduct {public static void main(String[] args){Product product = null;try{for(int i=0; i<5; i++){product = new Product();product.setProduct_id("350115001010"+i);product.setProduct_name("水杯"+i);product.setPrice(100+i);product.setInfo("这是一个精美的杯子"+i);DAOFactory.getIEmpDAOInstance().addProduct(product);}} catch (Exception e){e.printStackTrace();}}
}
  1. 编译。要注意不同源文件的编译次序,如果次序不对,会报错。按如下编译脚本:
javac -encoding utf-8 -d classes src\com\rob\pojo\Product.java
javac -classpath lib\mysql-connector-java-8.0.13.jar -d classes src\com\rob\db\DBConnection.java
javac -encoding utf-8 -classpath lib\mysql-connector-java-8.0.13.jar;classes;. -d classes src\com\rob\dao\ProductDao.java
javac -encoding utf-8 -classpath lib\mysql-connector-java-8.0.13.jar;classes;. -d classes src\com\rob\dao\ProductDaoImpl.java
javac -encoding utf-8 -classpath lib\mysql-connector-java-8.0.13.jar;classes;. -d classes src\com\rob\service\productService.java
javac -encoding utf-8 -classpath lib\mysql-connector-java-8.0.13.jar;classes;. -d classes src\com\rob\factory\DAOFactory.java
javac -encoding utf-8 -classpath lib\mysql-connector-java-8.0.13.jar;classes;. -d classes src\com\rob\test\TestInsertProduct.java
  1. 运行。运行也是在根目录下运行,如下脚本:
java  -classpath lib/mysql-connector-java-8.0.13.jar;classes;. com/rob/test/TestInsertProduct

运行成功截图如下:
运行成功截图
在查看数据库表中的内容是否更新:
查询数据库中表的内容
上面是该例子的完整的手工构建过程。可以看出,其中的繁琐点在于编写编译、运行脚本。

3 基于Maven的构建

建议在运行Maven前将镜像设置为国内,我设置的是华为云的镜像。这些提供镜像的企业为广大的软件开发者提供了帮助,做了公益。

  1. 切换到一个新的文件夹,在命令行中输入:mvn archetype:generate,进入对话式创建项目骨架(项目的文件夹结构)过程,截图如下:
    在这里插入图片描述
    在这里插入图片描述
    从上图中可以看出,Maven提供了3514种archetype供用户使用。这里,我们使用编号为2209的骨架,版本选择为1.5,然后再依次输入项目的groupId、artifactId、version等。
  2. 切换到根目录helloworld下,将前面的代码拷贝到src\main\java\com\example\helloworld下,如下图:
    在这里插入图片描述
    注意,由于包名改变,要更改每个源代码的包名位置。此外,对主程序TestInsertProduct.java,也要少许改动,以对数据库中表的更新内容区分,如下:
java">package com.example.helloworld.test;import com.example.helloworld.factory.DAOFactory;
import com.example.helloworld.pojo.Product;public class TestInsertProduct {public static void main(String[] args){Product product = null;try{for(int i=0; i<5; i++){product = new Product();product.setProduct_id("350115001010"+i+5);product.setProduct_name("水杯"+i+5);product.setPrice(100+i+5);product.setInfo("这是一个精美的杯子"+i+5);DAOFactory.getIEmpDAOInstance().addProduct(product);}} catch (Exception e){e.printStackTrace();}}
}
  1. 更改项目的pom.xml文件。改动部分如下:
 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.release>1.8</maven.compiler.release></properties><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.13</version></dependency>
  1. 在cmd console下,将当前目录切换到根目录helloworld,然后执行命令mvn clean compile,如下图:
    在这里插入图片描述
  2. 运行指令mvn exec:java -Dexec.mainClass="com.example.helloworld.test.TestInsertProduct"执行主代码,如下图,
    在这里插入图片描述
    上面出现了警告信息,不用管它。
  3. 查看数据库内容是否更新。如下图:
    在这里插入图片描述
    至此,同一项目的基于Maven的构建讲解完毕。可以清晰地感受到,Maven帮助我们自动下载依赖的包mysql-connector-java-8.0.13.jar;所用的命令较短的情况下,创建了项目骨架、编译和运行,与手工构建形成了鲜明的对比。

4 总结

通过一个相对大型而又简单的例子阐明了手工构建和基于Maven构建的详细过程,经过实操,能感受到如下的对比结论:

注意,对于Java初学者,如果正在学习某本Java书,书中的例子简单,没有划分多个包,只是1到2个源代码文件,则完全可以继续用手工的方式构建。Maven只是针对大型项目来用的,即项目代码划分为多个包,代码量比较大。

通过本文的基于Maven的构建,能帮助我们透彻理解Maven(不基于任何IDE)的构建过程,为我们后续使用集成Maven的IDE提供底层的理解细节,也能更加深刻地理解Maven在软件开发中的地位和作用,即自动化构建、依赖管理等,从而大大提高我们的工作效率。


  1. 刘鑫. JSP从零开始学: 视频教学版. 北京: 清华大学出版社, 2016. 244:252. ↩︎


http://www.ppmy.cn/embedded/153116.html

相关文章

利用 Python 爬虫获取 1688 关键字 API 接口

在当今电商蓬勃发展的时代&#xff0c;掌握市场动态、洞察消费者需求已成为商家制胜的关键。而 1688 作为中国领先的 B2B 电商平台&#xff0c;汇聚了海量商品与交易数据&#xff0c;其关键字 API 接口更是蕴含着丰富的市场信息。本文将详细解读如何借助 Python 爬虫技术&#…

人工智能知识分享第九天-机器学习_集成学习

集成学习 概念 集成学习是机器学习中的一种思想&#xff0c;它通过多个模型的组合形成一个精度更高的模型&#xff0c;参与组合的模型称为弱学习器&#xff08;基学习器&#xff09;。训练时&#xff0c;使用训练集依次训练出这些弱学习器&#xff0c;对未知的样本进行预测时…

Luogu P4688 [Ynoi2016] 掉进兔子洞

很bt的一个题。 题目描述 您正在打 galgame&#xff0c;然后突然发现您今天太颓了&#xff0c;于是想写个数据结构题练练手&#xff1a; 一个长为 n n n 的序列 a a a。 有 m m m 个询问&#xff0c;每次询问三个区间&#xff0c;把三个区间中同时出现的数一个一个删掉&…

[Git] git reset --hard / git reset --soft

git reset --hard 功能&#xff1a;重置索引&#xff08;暂存区&#xff09;和工作目录到指定的提交状态。这意味着它会丢弃所有未提交的更改和已暂存的更改。 适用场景&#xff1a;当你想要完全放弃当前工作目录中的所有更改并回退到某个特定提交状态时&#xff0c;可以使用这…

量子计算遇上人工智能:突破算力瓶颈的关键?

引言&#xff1a;量子计算遇上人工智能——突破算力瓶颈的关键&#xff1f; 在数字化时代的浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的速度改变着我们的生活&#xff0c;从语音助手到自动驾驶&#xff0c;从医学诊断到金融分析&#xff0c;无不彰显其…

#Uniapp: uniapp国际化适配

uniapp国际化适配 插件安装 npm i vue-i18n9.1.9根目录下新建locales文件目录 import Vue from vue; import VueI18n from vue-i18n; import zhCN from ./lang/zh-CN; import enUS from ./lang/en-US;// 获取默认语言 export const defaultLang uni.getStorageSync(language…

基于MATLAB的汽车热管理模型构建

一、引言 汽车热管理系统对汽车性能、部件寿命及驾乘体验至关重要。它能确保发动机、电池等关键部件在适宜温度工作。MATLAB 功能强大&#xff0c;为构建高精度热管理模型提供有效途径&#xff0c;助力优化系统设计与控制策略。 二、汽车热管理系统构成 2.1 发动机冷却系统&…

关于大数据的基础知识(二)——国内大数据产业链分布结构

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于大数据的基础知识&#xff08;二&a…