美文网首页
IntelliJ Idea14 创建Maven多模块项目,多继承

IntelliJ Idea14 创建Maven多模块项目,多继承

作者: _双眸 | 来源:发表于2019-06-03 01:43 被阅读0次

    接着上文【IntelliJ Idea14 创建Maven多模块项目,多继承,热部署配置总结(一)】,总结下项目热部署和pom文件结构的一些要点:

    一,依赖包的热部署

    上文中项目如果改了依赖包core模块中的service服务代码,重启web服务是看不到改动效果的,这是因为依赖的core已经打成jar包给web模块使用了,重启并不会重新打jar包,所以只能重新package打包才能看到效果。
    【解决方案】:把依赖的core模块,编译到web模块里面去,在web下生成core的class文件,这样重启编译就会实时更新界面了。
    【未处理之前】:

    在这里插入图片描述
    配置模块的output layout下的class,选中对应的依赖右键,点击put into output root
    在这里插入图片描述
    【处理之后,重新打包,启动】:
    在这里插入图片描述
    有了class文件之后,重启就能看到service的改动了。

    此外Project Stucture里面还有一些其他要注意的点:
    1,【Modules】当项目的JDK是1.8的时候,配置每个module的Language Level为对应的JDK的level;

    2,【Facets】
    检查Facets右边的【Deplyment Descriptors】,必须是指向web.xml
    检查Facets右边的【Web Resource Directories】,必须是选中webapp的目录,类似普通非maven的项目需要指向WebRoot或者WebContent目录

    3,【Artifacts】就是上面的热部署配置。


    二,pom配置要点

    2.1 pom的继承

    1,项目模块可以一层一层的继承下去,比如多层级的module方式:

    module-test
    --- module-test-common
    --- module-test-platform
    --- --- module-test-platform-A
    --- --- module-test-platform-B
    

    由上可知:

    1. module-test-platform-A和module-test-platform-B的parent是module-test-platform
    2. module-test-platform和module-test-common的parent是module-test

    上面配置要实现的话,也很简单,只需要将module-test-platform的pom.xml里面配置成<packaging>pom</packaging>,然后module-test-platform-A和module-test-platform-B的parent都以来module-test-platform的GAV(maven三要素:groupId/artifactId/version)就行了。

    <packaging>不写的话默认是jar,意思就是打成jar包;
    写pom的意思就是做父模块,给子模块继承或者引用;
    写war的意思就是打成war包给tomcat启动;

    在Maven 中除了用继承parent来做版本控制以外, 还可以通过 scope=import 来做版本控制.

    Maven 2.0.9 添加了一个新特性: scope = import 也就是从外部导入依赖管理的依赖配置. 使用过 DependencyManagement都知道, 多模块构建项目的时候, 为了解决各模块依赖版本一致, 统一在父pom.xml文件中统一定义各个依赖jar文件的版本, 然后子模块通过引用的方式添加需要的依赖jar, 但随着项目工程越来越大, 添加的依赖文件也越来也多, 父pom.xml的 DependencyManagement 也会越来越长, 不便于管理. 另外, 因为pom.xml 是单继承的, 如果已经有一个父pom.xml了, 想要再引用外部的pom.xml, 就只能复制到父pom.xml中了. 因此采用在 DependencyManagement 中使用scope = import的方式可以分类引入更多的管理配置, 也摆脱了单继承的限制.


    使用import scope解决maven继承(单)问题

    想必大家在做SpringBoot应用的时候,都会有如下代码:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>
    

    继承一个父模块,然后再引入相应的依赖

    假如说,我不想继承,或者我想继承多个,怎么做?

    我们知道Maven的继承和Java的继承一样,是无法实现多重继承的,如果10个、20个甚至更多模块继承自同一个模块,那么按照我们之前的做法,这个父模块的dependencyManagement会包含大量的依赖。如果你想把这些依赖分类以更清晰的管理,那就不可能了,import scope依赖能解决这个问题。你可以把dependencyManagement放到单独的专门用来管理依赖的pom中,然后在需要使用依赖的模块中通过import scope依赖,就可以引入dependencyManagement。例如可以写这样一个用于依赖管理的pom:

    <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.test.sample</groupId>
        <artifactId>base-parent1</artifactId>
        <packaging>pom</packaging>
        <version>1.0.0-SNAPSHOT</version>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactid>junit</artifactId>
                    <version>4.8.2</version>
                </dependency>
                <dependency>
                    <groupId>log4j</groupId>
                    <artifactid>log4j</artifactId>
                    <version>1.2.16</version>
                </dependency>
            </dependencies>
        </dependencyManagement>
    </project>
    

    然后我就可以通过非继承的方式来引入这段依赖管理配置

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.test.sample</groupId>
                <artifactid>base-parent1</artifactId>
                <version>1.0.0-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
     
    <dependency>
        <groupId>junit</groupId>
        <artifactid>junit</artifactId>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactid>log4j</artifactId>
    </dependency>
    

    注意:import scope只能用在dependencyManagement里面

    这样,父模块的pom就会非常干净,由专门的packaging为pom来管理依赖,也契合的面向对象设计中的单一职责原则。此外,我们还能够创建多个这样的依赖管理pom,以更细化的方式管理依赖。这种做法与面向对象设计中使用组合而非继承也有点相似的味道。

    那么,如何用这个方法来解决SpringBoot的那个继承问题呢?

    配置如下:

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.3.3.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
     
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    

    这样配置的话,自己的项目里面就不需要继承SpringBoot的module了,而可以继承自己项目的module了。

    参考:https://blog.csdn.net/mn960mn/article/details/50894022


    2.2 dependencies与dependencyManagement的区别

    在我们项目顶层的POM文件中,我们会看到dependencyManagement元素。通过它元素来管理jar包的版本,让子项目中引用一个依赖而不用显示的列出版本号。Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用在这个dependencyManagement元素中指定的版本号。

    这样做的好处:统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,才能保证测试的和发布的是相同的成果,因此,在顶层pom中定义共同的依赖关系。同时可以避免在每个使用的子项目中都声明一个版本号,这样想升级或者切换到另一个版本时,只需要在父类容器里更新,不需要任何一个子项目的修改;如果某个子项目需要另外一个版本号时,只需要在dependencies中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。

    区别:

    dependencies即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)

    dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。


    2.3 Maven依赖Scope选项详解

    在一个maven项目中,如果存在编译需要而发布不需要的jar包,可以用scope标签,值设为provided。

    如下:

    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.3</version>
      <scope>provided</scope>      
    </dependency>
    

    Scope的其他参数如下:

    compile:默认的scope,表示 dependency 都可以在生命周期中使用。
    而且,这些dependencies 会传递到依赖的项目中。适用于所有阶段,会随着项目一起发布

    provided:跟compile相似,但是表明了dependency 由JDK或者容器提供,例如Servlet AP和一些Java EE APIs。这个scope 只能作用在编译和测试时,同时没有传递性,即:child module无法引用。

    runtime:表示dependency不作用在编译时,但会作用在运行和测试时,如JDBC驱动,适用运行和测试阶段,与provided相反。

    test:表示dependency作用在测试时,不作用在运行时。 只在测试时使用,用于编译和运行测试代码。不会随项目发布。

    system:跟provided 相似,但是在系统中要以外部JAR包的形式提供,maven不会在repository查找它。


    2.4 Maven的classifier作用

    classifier可以是任意的字符串,用于拼接在GAV之后来确定指定的文件。
    可用于区分不同jdk版本所生成的jar包

    <dependency>  
        <groupId>net.sf.json-lib</groupId>   
        <artifactId>json-lib</artifactId>   
        <version>2.2.2</version>  
        <classifier>jdk15</classifier>    
    </dependency>
    
    <dependency>  
        <groupId>net.sf.json-lib</groupId>   
        <artifactId>json-lib</artifactId>   
        <version>2.2.2</version>  
        <classifier>jdk13</classifier>    
    </dependency>
    

    实际上对应的jar包是json-lib-2.2.2-jdk15.jarjson-lib-2.2.2-jdk13.jar

    区分项目的不同组成部分,例如:源代码、javadoc、类文件等。

    <dependency>  
        <groupId>net.sf.json-lib</groupId>   
        <artifactId>json-lib</artifactId>   
        <version>2.2.2</version>  
        <classifier>jdk15-javadoc</classifier>    
    </dependency> 
    

    对应的是json-lib-2.2.2-jdk15-javadoc.jar

    需要注意classifier的位置

    <dependency>  
        <groupId>net.sf.json-lib</groupId>   
        <artifactId>json-lib</artifactId>   
        <classifier>jdk15-javadoc</classifier>  
        <version>2.2.2</version>   
    </dependency> 
    

    对应的是json-lib-jdk15-javadoc-2.2.2.jar。可能会出现找不到jar包的情况。

    相关文章

      网友评论

          本文标题:IntelliJ Idea14 创建Maven多模块项目,多继承

          本文链接:https://www.haomeiwen.com/subject/buqqxctx.html