Maven管理(一)
Maven管理(一)
背景描述:
工作中经常维护一些比较老的项目,技术体系十分陈旧。一次两次按照升级需求针对性地改动少量代码完成任务还凑活,当频繁进行改动时就非常令人头大了。许多冗余操作类似:导入额外jar包、根据不同环境改写配置文件等,不但操作繁琐,而且每次部署都需要手动改写7、8个不同配置文件中的若干配置项,很容易出错(线上出了好几次问题-_-I|)。
为了彻底解决这些问题,我决定升级这些代码,其中最核心的操作就是:使用maven管理项目。关于maven的基础知识我再不在赘述了,直接根据我的项目进程总结maven应用。
1.将普通项目转为maven项目
1.1转换项目
在指定文件夹下命令行输入以下内容(也可以使用IDE创建一个空的maven项目):
#自行填入groupId和artifactId
mvn -B archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DgroupId=xxxx \
-DartifactId=xxxx
生成的目录包含一个src
文件夹,一个pom.xml
。
这个路径是普通maven项目的路径,如果是web项目还需要创建resources
存放配置文件,创建webapp
存放web资源。创建完成后后,将所有配置文件放到/resources
下,将web资源(没使用的maven管理的java web项目一般存放在webContent中)复制到web下。然后将项目导入到你的IDE中进行后续处理。excipse导入这样的项目可能会出现一些问题,请注意配置Peoject Facets
和Devlepment Assembly
。
以上操作都可以通过直接创建maven项目然后复制代码完成
1.2修改配置文件路径
- 一般使用tomcat启动web项目需要web.xml,xml中定义了spring相关框架的监听器,注意修改这些路径。
- 一些spring相关框架中可能需要引入property,注意修改路径。
- 使用mybatis或hibernate等持久层框架的项目,注意修改数据映射文件的路径。
2.导入本地jar包
未使用maven管理的web项目一般会把额外jar包放到WEB-INF/lib路径下,我们可以使用maven插件将这些jar包在编译打包的时候直接复制到指定位置,省的你再一个个去写dependency
。
pom.xml配置如下:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
<!--打包本地 jar包 -->
<compilerArguments>
<extdirs>${project.basedir}/src/main/webapp/WEB-INF/lib</extdirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}\classes\lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
3.利用profile
针对不同环境打包
我们十分头疼根据开发、测试、生产不同的环境不停的修改配置文件,这不但非常麻烦而且很容易出错。传统的web项目我们没有什么比较好的解决方法,只能提前准备好不同环境的配置文件不停地去替换,这样就带来保持不同配置文件版本同步的困难。现在我们使用maven的profile
参数进行帮助我们避免这个问题。
在/src/resources
目录下新建test
、product
两个文件夹,把原来/src/resources
下的配置文件复制到这俩目录下各一份,并根据环境的不同改好配置文件。
并在pom.xml
中添加插件:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>compile</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<!-- 覆盖原有文件 -->
<overwrite>true</overwrite>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<!-- 待处理的资源定义 -->
<resources>
<resource>
<!-- 指定resources插件处理哪个目录下的资源文件 -->
<directory>src/main/resources/${package.environment}</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
<inherited></inherited>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<warName>${project.artifactId}</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
添加参数:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<package.environment>dev</package.environment>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<package.environment>test</package.environment>
</properties>
</profile>
<profile>
<id>product</id>
<properties>
<package.environment>product</package.environment>
</properties>
</profile>
</profiles>
这个配置的含义是:
pom定义三个参数dev
、test
、product
。在打包时,根据输入的命令参数不同,将相应目录下的配置文件复制并替换/src/resources
下的配置文件。
例如,使用:
mvn package -Pproduct
打包时,maven会将/src/resources/product
路径下的配置文件辅助并替换掉/src/respurces
中的配置文件。这样,生成的war包的/src/resources
中包含的就是生产环境的配置文件了。
4.本地jar包生成pom文件中的dependency
有时候,你不得不把/WEB-INF/lib
下的jar包全部使用maven管理(比如你的领导要求如此)。你不必着急一个个jar包的去查询,我这有个代码拿去抄吧(就是调用接口查询dependency的写法):
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import org.dom4j.Element;
import org.dom4j.dom.DOMElement;
import org.jsoup.Jsoup;
import com.alibaba.fastjson.JSONObject;
/**
* @author chen_xi_yuan
* @vsersion 2019年11月15日 下午8:34:15
*/
public class TestStatic {
public static void main(String[] args) throws Exception {
genDependicies();
}
public static void genDependicies() throws FileNotFoundException, IOException {
Element dependencys = new DOMElement("dependencys");
// 需生成pom.xml文件的lib路径
File dir = new File("D:/xxx/src/main/webapp/WEB-INF/lib");
for (File jar : dir.listFiles()) {
JarInputStream jis = new JarInputStream(new FileInputStream(jar));
Manifest mainmanifest = jis.getManifest();
jis.close();
if (mainmanifest == null) {
continue;
}
String bundleName = mainmanifest.getMainAttributes().getValue("Bundle-Name");
String bundleVersion = mainmanifest.getMainAttributes().getValue("Bundle-Version");
Element ele = null;
StringBuffer sb = new StringBuffer(jar.getName());
if (bundleName != null) {
bundleName = bundleName.toLowerCase().replace(" ", "-");
sb.append(bundleName + "\t").append(bundleVersion);
ele = getDependices(bundleName, bundleVersion);
}
if (ele == null || ele.elements().size() == 0) {
bundleName = "";
bundleVersion = "";
String[] ns = jar.getName().replace(".jar", "").split("-");
for (String s : ns) {
if (Character.isDigit(s.charAt(0))) {
bundleVersion += s + "-";
} else {
bundleName += s + "-";
}
}
if (bundleVersion.endsWith("-")) {
bundleVersion = bundleVersion.substring(0, bundleVersion.length() - 1);
}
if (bundleName.endsWith("-")) {
bundleName = bundleName.substring(0, bundleName.length() - 1);
}
ele = getDependices(bundleName, bundleVersion);
sb.setLength(0);
sb.append(bundleName + "\t").append(bundleVersion);
// System.out.println(sb.toString());
System.out.println(ele.asXML());
}
ele = getDependices(bundleName, bundleVersion);
if (ele.elements().size() == 0) {
ele.add(new DOMElement("groupId").addText("not find"));
ele.add(new DOMElement("artifactId").addText(bundleName));
ele.add(new DOMElement("version").addText(bundleVersion));
}
dependencys.add(ele);
System.out.println();
}
System.out.println(dependencys.asXML());
}
public static Element getDependices(String key, String ver) {
Element dependency = new DOMElement("dependency");
try {
String url = "http://search.maven.org/solrsearch/select?q=a%3A%22" + key + "%22%20AND%20v%3A%22" + ver
+ "%22&rows=3&wt=json";
org.jsoup.nodes.Document doc = Jsoup.connect(url).ignoreContentType(true).timeout(30000).get();
String elem = doc.body().text();
JSONObject response = JSONObject.parseObject(elem).getJSONObject("response");
if (response.containsKey("docs") && response.getJSONArray("docs").size() > 0) {
JSONObject docJson = response.getJSONArray("docs").getJSONObject(0);
Element groupId = new DOMElement("groupId");
Element artifactId = new DOMElement("artifactId");
Element version = new DOMElement("version");
groupId.addText(docJson.getString("g"));
artifactId.addText(docJson.getString("a"));
version.addText(docJson.getString("v"));
dependency.add(groupId);
dependency.add(artifactId);
dependency.add(version);
}
} catch (Exception e) {
e.printStackTrace();
}
return dependency;
}
}
目前正在尝试maven自动测试,以及持续集成方案。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· 几个技巧,教你去除文章的 AI 味!
· 对象命名为何需要避免'-er'和'-or'后缀
· JDK 24 发布,新特性解读!
· .NET Core奇技淫巧之WinForm使用Python.NET并打包
· .NET 10 Preview 2 增强了 Blazor 和.NET MAUI