前言
项目中,有许多需要初始化的数据脚本在其它项目中使用,需要一个初始化数据库脚本的插件,可以必然数据库环境或人员手动执行带来的影响。
Maven 插件
Mojo 工程
Mojo 就是 Maven Plain Old Java Object。是对 Pojo 的一种改进。
每一个 Mojo 都是 Maven 中的一个执行目标(executable goal),Maven plugin 就是对多个 Mojo 的封装。
创建 Mojo 工程
1、创建一个 Maven 项目
2、添加依赖
这里直接放完整依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| <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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.gt.boot</groupId> <artifactId>sql-init-maven-plugin</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>maven-plugin</packaging> <name>1-plugin-sql-init</name> <url>https://github.com/maxzhao-it/sql-init-maven-plugin</url> <developers> <developer> <name>maxzhao</name> <email>1441439636@qq.com</email> </developer> </developers> <licenses> <license> <name>Apache License Version 2.0</name> <url>http://www.apache.org/licenses/LICENSE-2.0</url> </license> </licenses> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven-plugin-api.version>3.8.4</maven-plugin-api.version> <maven-plugin-annotations.version>3.6.4</maven-plugin-annotations.version> <log4j2.version>2.17.1</log4j2.version> <commons-lang3.version>3.11</commons-lang3.version> <fastjson.version>1.2.79</fastjson.version> <lombok.version>1.18.22</lombok.version> </properties>
<dependencies> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>${maven-plugin-api.version}</version> </dependency> <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> <version>${maven-plugin-annotations.version}</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> </dependencies> <build> <sourceDirectory>src/main/java</sourceDirectory> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugin-plugin</artifactId> <version>${maven-plugin-annotations.version}</version> <configuration> <goalPrefix>gt-boot</goalPrefix> <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> <skip>true</skip> </configuration> </plugin> </plugins> </build> </project>
|
3、设置打包方式
1 2
| <packaging>maven-plugin</packaging>
|
4、创建一个继承 AbstractMojo
的类
创建一个 InitTableMojo
类,继承 AbstractMojo
,其中 execute()
方法就是需要自定义实现的业务。
Mojo
标记方法,需要 @Mojo
注解或Javadoc
包里含@goal
注解的类来当做一个 Mojo
类。
使用 @Mojo
需要引入
1 2 3 4 5 6
| <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> <version>3.6.2</version> </dependency>
|
引入自定义plugin
下面引入的是 MySQL
依赖,数据库连接 MySQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <plugin> <groupId>com.gt.boot</groupId> <artifactId>sql-init-maven-plugin</artifactId> <version>${gt-base.version}</version> <configuration> <sqlFile>${project.basedir}/src/http/sql.sql</sqlFile> <sqlFileEncoding>UTF-8</sqlFileEncoding> <dataSource> <driverClassName>com.mysql.cj.jdbc.Driver</driverClassName> <url>jdbc:mysql://xxxx:3306/xxxx?charset=utf8mb4&useUnicode=true&useSSL=false</url> <username>xxxx</username> <password>xxx..</password> </dataSource> </configuration> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> </dependencies> </plugin>
|
调试
IDEA 直接调试
创建一个自定义的Mojo 类 InitTableMojo.java
命令行启动
1 2
| mvnDebug com.gt.boot:sql-init-maven-plugin:1.0.0-SNAPSHOT:touch mvnDebug com.gt.boot:sql-init-maven-plugin:1.0.0-SNAPSHOT:initTable
|
然后使用 Remote JVM Debug
连接,运行后就可以 Debug 调试代码了。
附
InitTableMojo.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
| package com.gt.boot.plugin.sqlInit;
import com.gt.boot.plugin.sqlInit.config.DataSourceConfig; import com.gt.boot.plugin.sqlInit.dao.DBDao; import lombok.extern.slf4j.Slf4j; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter;
import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.ArrayList; import java.util.List;
@Slf4j @Mojo(name = "initTable", threadSafe = true) public class InitTableMojo extends AbstractMojo {
@Parameter(required = true) private DataSourceConfig dataSource; @Parameter(required = true) private File sqlFile; @Parameter private String sqlFileEncoding = StandardCharsets.UTF_8.toString();
static final String DEFAULT_DELIMITER = ";";
protected DBDao config;
@Override public void execute() throws MojoExecutionException, MojoFailureException { log.info("====================== 开始 连接数据库 ======================"); config = new DBDao(dataSource); log.info("====================== 开始解析SQL脚本 ======================"); List<String> sqlList = readSQLs(sqlFile); if (sqlList.isEmpty()) { log.warn("====================== SQL脚本不存在 ======================"); return; } log.info("====================== 开始执行SQL脚本 ======================"); if (config.executeSqls(sqlList)) { log.info("====================== 执行SQL脚本成功 ======================"); } }
public String read(File sqlFile) { if (sqlFile == null || !sqlFile.exists() || sqlFile.isDirectory()) { return null; } if (!sqlFile.getName().endsWith(".sql") && !sqlFile.getName().endsWith(".txt")) { log.warn("SQL脚本 文件只能为 .sql 或 .txt "); return null; } StringBuilder sql = new StringBuilder(); InputStreamReader isr = null; BufferedReader reader = null; try { isr = new InputStreamReader(Files.newInputStream(sqlFile.toPath()), sqlFileEncoding); reader = new BufferedReader(isr); char[] buf = new char[50]; int len; while ((len = reader.read(buf)) != -1) { sql.append(buf, 0, len); } } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { throw new RuntimeException(e); } } if (isr != null) { try { isr.close(); } catch (IOException e) { throw new RuntimeException(e); } } } return sql.toString(); }
public List<String> readSQLs(File sqlFile) { List<String> sqlList = new ArrayList<>(); if (sqlFile == null || !sqlFile.exists() || sqlFile.isDirectory()) { return sqlList; } if (!sqlFile.getName().endsWith(".sql") && !sqlFile.getName().endsWith(".txt")) { log.warn("SQL脚本 文件只能为 .sql 或 .txt "); return sqlList; } StringBuilder sqlTemp = new StringBuilder(); InputStreamReader isr = null; BufferedReader reader = null; try { isr = new InputStreamReader(Files.newInputStream(sqlFile.toPath()), sqlFileEncoding); reader = new BufferedReader(isr); String sqlLine; while ((sqlLine = reader.readLine()) != null) { sqlTemp.append(sqlLine); sqlLine = sqlLine.trim(); if (sqlLine.isEmpty() || sqlLine.startsWith("--") || sqlLine.startsWith("//")) { } else if (sqlLine.endsWith(DEFAULT_DELIMITER)) { sqlList.add(sqlTemp.substring(0, sqlTemp.length() - 1)); sqlTemp = new StringBuilder(); } } } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { throw new RuntimeException(e); } } if (isr != null) { try { isr.close(); } catch (IOException e) { throw new RuntimeException(e); } } } return sqlList; } }
|
DBDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| package com.gt.boot.plugin.sqlInit.dao;
import com.gt.boot.plugin.sqlInit.config.DataSourceConfig; import jdk.nashorn.internal.runtime.ScriptRuntime; import lombok.extern.slf4j.Slf4j; import org.codehaus.plexus.util.StringUtils;
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.List;
@Slf4j public class DBDao {
private Connection connection;
private DataSourceConfig dataSourceConfig;
public DBDao(DataSourceConfig dataSourceConfig) { this.dataSourceConfig = dataSourceConfig; }
public boolean executeSql(String sql) { Statement ps = null; connection = dataSourceConfig.getConn(); try { ps = connection.createStatement();
return ps.execute(sql); } catch (SQLException e) { log.error("====================== 执行SQL脚本失败 ======================"); log.error("执行失败SQL脚本:\n{}\n", sql); log.error("SQL 执行失败 ", e); } finally { try { if (ps != null) { ps.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } return false; }
public boolean executeSqls(List<String> sqlList) { Statement ps = null; connection = dataSourceConfig.getConn(); try { ps = connection.createStatement(); for (String sql : sqlList) { if (StringUtils.isBlank(sql)) { continue; } ps.addBatch(sql); } int[] ints = ps.executeBatch(); log.info("执行成功数据量:{}", ints.length); return true; } catch (SQLException e) { log.error("====================== 执行SQL脚本失败 ======================"); log.error("执行失败SQL脚本:\n{}\n", Arrays.toString(sqlList.toArray())); log.error("SQL 执行失败 ", e); } finally { try { if (ps != null) { ps.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } return false; }
}
|
DataSourceConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| package com.gt.boot.plugin.sqlInit.config;
import lombok.extern.slf4j.Slf4j; import org.apache.maven.plugins.annotations.Parameter;
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;
@Slf4j public class DataSourceConfig {
@Parameter(required = true) private String url;
@Parameter(required = true) private String driverClassName;
@Parameter(required = true) private String username;
@Parameter(required = true) private String password;
public Connection getConn() { Connection conn = null; try { Class.forName(driverClassName); conn = DriverManager.getConnection(url, username, password); } catch (ClassNotFoundException e) { log.error("请添加数据库依赖:比如:\n{}\n", "<dependency>\n" + " <groupId>mysql</groupId>\n" + " <artifactId>mysql-connector-java</artifactId>\n" + "</dependency>", e); } catch (SQLException e) { e.printStackTrace(); return null; } return conn; } }
|
本文地址: https://github.com/maxzhao-it/blog/post/5570fc49/