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文件,内容如下:

<?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
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命令:
<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就可以被多个项目使用。


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值