zoukankan      html  css  js  c++  java
  • 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("[ ]+$", ""); //移除换行  
                    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就可以被多个项目使用。
  • 相关阅读:
    C# 利用Autofac批量接口注入依赖【学习记录】
    c# Quartzs定时器的简单使用
    Web Api 宿主的搭建
    教你如何搭建自己的直播服务器简易
    自用电脑+外网开放+SSL认证(纯免费)
    sql 获取主键表和主键的方法
    sql 分裂字符串函数
    Sql 将一个整型数字转换成带前导零的固定长度数字字符串
    sql 根据外键表和外键列得到主键表和主键列的方法
    定位div
  • 原文地址:https://www.cnblogs.com/jym-sunshine/p/4859248.html
Copyright © 2011-2022 走看看