Tomcat打包时多项目共享jar和精确指定jar版本

在产品打包发布时一个tomcat中如果存在多个war,部署的一般方式是部署到%TOMCAT_HOME%/webapps目录下,目录结构遵循J2EE规范,把引用的jar放到%TOMCAT_HOME%/webapps/xxxxx.war/WEB-INF/lib下面即可。但是多个项目完全可能引用了相同的jar,如何使多项目共享这个jar呢?项目发布时经常由于jar冲突造成很多问题,如果使打出的包精确指定所需要的jar版本呢?如何不放到%TOMCAT_HOME%/webapps目录,而把war放到特定的位置如何加载呢呢?本文将解决以上几个问题。

1.下载tomcat的zip包并解压,在%TOMCAT_HOME%/conf/Catalina/localhost文件夹下创建一个lkexample.xml文件,内容如下:

[html] view plaincopy

<?xml version="1.0" encoding="UTF-8"?>

<Context docBase="../../apps/lk-example.war">

<Loader className="com.tgb.lk.example.dist.ManifestClasspathWebappLoader"/>

</Context>

2.将待部署的lk-example.war放到../../apps/lk-example.war下,并将lk-example.war/WEB-INF/lib下的所有jar剪接到../lib下,文件结构目录见下图

3.编写com.tgb.lk.example.dist.ManifestClasspathWebappLoader.java类并打包为jar

[java] view plaincopy

package com.tgb.lk.example.dist;

import org.apache.catalina.Container;

import org.apache.catalina.LifecycleException;

import org.apache.catalina.core.StandardContext;

import org.apache.catalina.loader.WebappLoader;

import java.io.*;

import java.util.jar.Attributes;

import java.util.jar.Manifest;

/**

* 从War中的MANIFEST.MF获得类路径并进行额外加载

*/

public class ManifestClasspathWebappLoader extends WebappLoader {

public ManifestClasspathWebappLoader() {

super();

}

public ManifestClasspathWebappLoader(ClassLoader parent) {

super(parent);

}

@Override

protected void startInternal() throws LifecycleException {

final Container container = getContainer();

if (container instanceof StandardContext) {

File baseFile = new File(((StandardContext) container).getRealPath(""));

if (baseFile.exists() && baseFile.canRead()) {  //是否可读

if (baseFile.isDirectory()) {     //目录

final File manifestFile = new File(baseFile, "META-INF/MANIFEST.MF");

if (manifestFile.exists() && manifestFile.canRead() && manifestFile.isFile()) {     //MANIFEST.MF文件可读

System.out.println("[DIST] found MANIFEST.MF" + manifestFile);

try {

FileInputStream fileInputStream = new FileInputStream(manifestFile);

setClasspaths(baseFile, fileInputStream);

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

} else if (baseFile.isFile()) { //文件(war)

}

}

}

super.startInternal();

}

/**

* 设置MANIFEST.MF流中的类路径

*

* @param baseFile

* @param inputStream

*/

private void setClasspaths(File baseFile, InputStream inputStream) {

String classpaths[] = null;

try {

final Manifest manifest = new Manifest(inputStream);

final Attributes attributes = manifest.getMainAttributes();

String classpathValue = attributes.getValue("Class-Path");

if (classpathValue != null) {          //可以不为null说明发现Class-Path

classpathValue = classpathValue.replaceAll("[\r\n]+$", ""); //移除换行

classpaths = classpathValue.split("\\s+");     //拆分类路径字符串

}

} catch (IOException e) {

e.printStackTrace();

}

if (classpaths != null) {   //如果发现类路径则设置类路径

for (String classpath : classpaths) {

addRepository(new File(baseFile.getParent(), classpath).toURI().toString());    //转换相对路径为实际路径并转换为URI

}

System.out.println("[DIST] " + baseFile.getName() + " append " + classpaths.length + " classpaths.");

}

}

}

4.将打出的jar包放到%TOMCAT_HONE%\lib下。

5.修改你的war工程的pom.xml,加入如下配置并运行mvn package命令:

[html] view plaincopy

<build>

<plugins>

<plugin>

<artifactId>maven-war-plugin</artifactId>

<configuration>

<archive>

<manifest>

<addClasspath>true</addClasspath>

<classpathPrefix>../lib/</classpathPrefix>

<useUniqueVersions>false</useUniqueVersions>

</manifest>

</archive>

</configuration>

</plugin>

</plugins>

</build>

观察打出的war包lk-example.war/META-INF/MANIFEST.MF文件,这个文件中打出了war精确引用的jar版本。如下图:

6.将打出的war包解压到apps目录文件下。

7.运行tomcat即可访问http://localhost:8080/lkexample。

总结,修改%TOMCAT_HOME%/conf/Catalina/localhost/lkexample.xml指定了tomcat加载的应用以及加载应用时使用的webapp类加载器,通过自己重写的类加载器ManifestClasspathWebappLoader加载了xxxx.war/META-INF/MANIFEST.MF中精确的jar路径所引用的jar.如果发布的项目有多个war可以同时都指定引用lib下精确版本的jar文件,这样相同的jar就可以被多个项目使用。

时间: 2024-07-29 15:44:27

Tomcat打包时多项目共享jar和精确指定jar版本的相关文章

如何去掉tomcat启动时的项目名

问题需求:tomcat启动项目的时候,一般用localhost:8080/XXXX ,现在想直接用localhost:8080来进入系统 解决办法:在tomcat安装目录中,找到..\apache-tomcat-7.0.75\conf 下的server.xml,打开后找到<Host>标签下的 <Context>标签 设置为:<Context docBase="XXXX" path="" reloadable="true&quo

Eclipse项目中引用第三方jar包时将项目打包成jar文件的两种方式

转载自:http://www.cnblogs.com/lanxuezaipiao/p/3291641.html 方案一:用Eclipse自带的Export功能 步骤1:准备主清单文件 “MANIFEST.MF”, 由于是打包引用了第三方jar包的Java项目,故需要自定义配置文件MANIFEST.MF,在该项目下建立文件MANIFEST.MF,内容如下: Manifest-Version: 1.0 Class-Path: lib/commons-codec.jar lib/commons-htt

tomcat启动时servlet-api.jar not loaded.

今天自己配置一个servlet技术项目,建立的一个网站项目ServletPa,目录结构如下.但是在tomcat启动时,出现servlet-api.jar not loaded. 十月 31, 2015 10:50:43 下午 org.apache.catalina.core.AprLifecycleListener init信息: The APR based Apache Tomcat Native library which allows optimal performance in prod

将本地jar包手动拷贝到Maven库中,在其他电脑上用Maven打包时出错

背景交代:在做图片水印时候引入了两个包文件,这两个包是JDK自带的私有包,不能用Maven库里下载,因此笔者手动将rt和jce两个工具jar文件拷贝到本地的Maven库中,如下图 import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; 然后在pom配置文件里写上下面的配置 将jce和rt拷到如下路径(rt类似) 然后项目在其他电脑上用Maven打包时候报错如下: Fa

maven打包时包含本地jar

项目中需要使用maven的打包工具,生成zip压缩包,使用的插件是assembly-plugin.因为一些特殊的原因,需要使用一些本地的jar进行依赖,加载外部jar后编码过程中没有任何问题,但是打包时一直报"程序包不存在". 思考一下:Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所以虽然在开发过程中项目正常依赖没有任何问题,但是打包的时候肯定就找不到本地的jar了. 这种问题有很多解决方案,比如加入本地仓库.搭建maven私服等,如需这些解决方案自行谷歌百度,

Maven打包时引入本地jar包

<!--pom.xml-->..... <dependencies> <dependency> <groupId>com.xxxxxx</groupId> <artifactId>xxxxxx</artifactId> <version>x.x.x</version><!--版本随意填--> <scope>system</scope> <systemPath

Tomcat启动时项目重复加载,导致资源初始化两次的问题

最近在项目开发测试的时候,发现Tomcat启动时项目重复加载,导致资源初始化两次的问题 导致该问题的原因: 如下图:在Eclipse中将Server Locations设置为"Use Tomcat installation(takes control of Tomcat installation)"时, 就会导致该问题! 根本原因: 解决方法一: 把server.xml中的context删除掉 但这会导致一个问题: 在Web Modules中你将看不到我们的项目 解决方法二: 在Tom

maven 项目打包时无法解析读取properties文件

在做项目时遇见一个问题,无法解析properties文件的 内容 异常为 Could not resolve placeholder ......... 在此之前均有做相关的 配置 但是从未出现过如上异常,困惑了很久,最后把 war包提取出来得知   properties文件未被加载进项目中,因此无法识别. 但这的原因是为什么呢   ,原来此项目采用的是maven配置,但是maven在打包时将丢失properties文件,原因maven执行compile是只会扫描*.class文件. 那么这种请

Tomcat启动时项目重复加载的问题

最近在项目开发测试的时候,发现Tomcat启动时项目重复加载,导致资源初始化两次的问题 导致该问题的原因: 如下图:在Eclipse中将Server Locations设置为"Use Tomcat installation(takes control of Tomcat installation)"时, 就会导致该问题! 根本原因: 解决方法一: 把server.xml中的context删除掉 但这会导致一个问题: 在Web Modules中你将看不到我们的项目 解决方法二: 在Tom