在产品打包发布时一个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就可以被多个项目使用。

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

  1. tomcat中设置多项目共享jar;类包

    随着服务器上的tomcat部署的项目越来越多,最近在部署一个新的项目的时候出现内存溢出的错误 Exception in thread "main" java.lang.OutOfM ...

  2. Maven打包时去掉项目版本号

    Maven打包后,jar或war文件名里带有版本号信息,如projectname0.0.1-SNAPSHOT.jar等,怎么去掉呢? 解决办法: 打开项目pom.xml文件,在<build> ...

  3. eclipse java项目中明明引入了jar包 为什么项目启动的时候不能找到jar包 项目中已经 引入了 com.branchitech.app 包 ,但时tomcat启动的时候还是报错? java.lang.ClassNotFoundException: com.branchitech.app.startup.AppStartupContextListener java.lang.ClassN

    eclipse java项目中明明引入了jar包 为什么项目启动的时候不能找到jar包 项目中已经 引入了 com.branchitech.app 包 ,但时tomcat启动的时候还是报错?java. ...

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

    转载自:http://www.cnblogs.com/lanxuezaipiao/p/3291641.html 方案一:用Eclipse自带的Export功能 步骤1:准备主清单文件 “MANIFES ...

  5. [JAR包] android引入JAR包,打包成JAR包,打包成Library项目,导入Library项目

    (1)项目导入JAR包:1.在项目目录里建立一个libs目录,将外部jar包拷贝在里面.2.右键点击项目,Bulid Path->Configure Build Path3.在设置Libraie ...

  6. spring boot (2):spring boot 打包tomcat、tomcat 部署多个项目、服务器部署项目SSL 设置(阿里云)

    一.spring boot 内置tomcat配置https: 关于自签名证书可以看下上一篇 spring boot1 更详细的可以看转载 https://www.jianshu.com/p/8d4ab ...

  7. maven打包时包含本地jar

    项目中需要使用maven的打包工具,生成zip压缩包,使用的插件是assembly-plugin.因为一些特殊的原因,需要使用一些本地的jar进行依赖,加载外部jar后编码过程中没有任何问题,但是打包 ...

  8. 通过idea 打包 spring maven项目打包为可执行jar包

    用assembly打包一直报错: shangyanshuodeMacBook-Pro:target shangyanshuo$ java -jar jobscrawler-1.0-SNAPSHOT-j ...

  9. maven打包时无法加载lib下的jar

    © 版权声明:本文为博主原创文章,转载请注明出处 问题描述: 项目在本地部署没有问题,但是使用maven打包时报错: ***(引用jar中某个类的的路径) 不存在 ***(某个java类中的某行某列) ...

随机推荐

  1. am,pm时间转换

    写在前面 最近遇到的一个问题,在英文操作系统上,获取到的时间是带am或者pm的.但是数据库是datetime类型,存储的时候竟然都变成0000-00-00 00:00:00.但是在中文操作系统上又是正 ...

  2. 第四十四课:jQuery UI和jQuery easy UI

    jQuery UI是jQuery官方提供的功能效果和UI样式.作为官方出的东西,它一直没有被人们看重,一是它没有datagrid,tree等UI库必备的东西,二是它修改太过频繁,体积庞大.其实它所有以 ...

  3. 百度地图整合功能分享修正版[ZMap.js] 实例源码!

    ZMap 功能说明 ZMap 是学习百度地图 api 接口,开发基本功能后整的一个脚本类,本类方法功能大多使用 prototype 原型 实现: 包含的功能有:轨迹回放,圈画区域可编辑,判断几个坐标是 ...

  4. AngularJS - 服务简介

    服务是AngularJS中非常重要的一个概念,虽然我们有了控制器,但考虑到其生命实在脆弱,我们需要用到服务. 起初用service时,我便把service和factory()理所当然地关联起来了. 确 ...

  5. Redis——分布式简单使用

    Redis简介:Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. Redis安装:参考博客http://www ...

  6. Moqui学习之数据与资源

    资源位置: 资源门面位置的字符串类似于URL的构成方式:协议,主机,可选端口和文件名.它支持标准的java URL协议(http https ftp jar file).同样也支持一些扩展的协议: c ...

  7. js获取url查询参数

    function getURLParamInfo(key) { if (location.search == "") { return undefined; } var a = l ...

  8. JSP中<base href="<%=basePath%>">的作用

    来源于:http://fanshuyao.iteye.com/blog/2097229 首先了解是什么是<base href=""> <base href=&qu ...

  9. Qt *.pro编写一般规则

    qmake 之 CONFIG 与 QT 乱谈 看qtcn论坛中经常有人忘记 QT+=network 等语句.随便写写吧,或许对他人有帮助. 写来写去,发现越写越乱,就这样吧,反正主要的内容很简单. d ...

  10. Java-transient

    transient的作用及使用方法 都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这 ...