• Maven聚合与继承


    聚合

    考虑这样一个场景,如果我们要开发一个电商系统,按照现在流行的微服务架构,肯定是希望前端和后端独立成两个项目分别进行开发和部署,但前端和后端很多时候有共同的业务。比如,笔者就曾经遇到后端可以帮助用户下单,逻辑与前端用户下单的业务逻辑一致,如果两个项目独立开发,那么下单的代码势必要在两个项目中重复编写,未来如果下单的逻辑有变化,两个项目也要进行修改。Maven的聚合特性能够把不同项目的各个模块聚合在一起构件,让我们避免上面的烦恼。

    我们还是用代码来举例,假设我们有个hello项目,我们在这个项目划分三个层:pojo、service和app。pojo层中有个User对象,用来装载用户的姓名,service层有个HelloService类,提供一个返回String类型的sayHello(User user)业务方法,app层负责调用service层的业务方法。现在我们将通过这个hello项目来实现Maven的聚合。

    我们先创建一个名为hello的空项目:

    然后选择Module,创建quickstart为骨架创建一个名为hello-parent的Maven项目:

    hello-parent项目创建完毕后,我们在pom.xml文件中的坐标处加入<packaging>pom</packaging>:

    <groupId>com.leolin.mvnbook</groupId>
    <artifactId>hello-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    

      

    然后,我们再按照之前的方式创建一个新的Module,名为hello-pojo:

    我们在hello-pojo项目pom.xml文件的坐标处,加入<packaging>jar</packaging>:

    <artifactId>hello-pojo</artifactId>
    <packaging>jar</packaging>
    

    我们对hello-pojo项目进行Maven→Reimport,然后删除com.leolin.mvnbook下的App文件,并创建pojo包,在pojo包下新建User类:

    package com.leolin.mvnbook.pojo;
    
    public class User {
        private String name;
    
        public User(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

      

    我们再建立一个名为hello-service的Module:

    hello-service创建完毕后,我们pom.xml文件中加入packaging元素,并加入对hello-pojo的依赖:

    <artifactId>hello-service</artifactId>
    <packaging>jar</packaging>
    <dependencies>
    	<dependency>
    		<groupId>com.leolin.mvnbook</groupId>
    		<artifactId>hello-pojo</artifactId>
    		<version>1.0-SNAPSHOT</version>
    	</dependency>
    	<dependency>
    		<groupId>junit</groupId>
    		<artifactId>junit</artifactId>
    		<version>4.11</version>
    		<scope>test</scope>
    	</dependency>
    </dependencies>
    

      

    然后对hello-service进行Maven→Reimport,我们删除该项目原先的App.java文件,并创建service目录,在service目录下创建HelloService.java文件:

    package com.leolin.mvnbook.service;
    
    import com.leolin.mvnbook.pojo.User;
    
    public class HelloService {
        public String sayHello(User user) {
            return "hello " + user.getName();
        }
    }
    

      

    我们可以看到,虽然hello-service和hello-pojo都是独立的Maven项目,但hello-service在pom中加入hello-pojo的依赖,就可以引用hello-pojo了。那么按照之前所说的,我们还有个app项目,这个app项目会依赖service,调用service的方法。现在,我们动手创建app:

    在pom.xml文件中加入对packaging和hello-service的依赖:

    <artifactId>hello-app</artifactId>
    <packaging>jar</packaging>
    <dependencies>
    	<dependency>
    		<groupId>com.leolin.mvnbook</groupId>
    		<artifactId>hello-service</artifactId>
    		<version>1.0-SNAPSHOT</version>
    	</dependency>
    	<dependency>
    		<groupId>junit</groupId>
    		<artifactId>junit</artifactId>
    		<version>4.11</version>
    		<scope>test</scope>
    	</dependency>
    </dependencies>
    

      

    对项目Reimport之后,我们可以在App.java文件中尝试调用HelloService中的sayHello(User user)方法:

    package com.leolin.mvnbook;
    
    import com.leolin.mvnbook.pojo.User;
    import com.leolin.mvnbook.service.HelloService;
    
    /**
     * Hello world!
     */
    public class App {
        public static void main(String[] args) {
            User user = new User("Jack");
            HelloService service = new HelloService();
            System.out.println(service.sayHello(user));
        }
    }
    

      

    运行App文件,可以看到控制台打印出:

    hello Jack
    

      

    至此,我们通过Maven的聚合解决了同一个系统,不同模块独立运行部署时产生的代码冗余的问题。

    继承

    现在,让我们在回到开头提的电商系统,如果我们的领导,希望电商系统不仅做到前端后端分离,且前端不同模块,比如:订单模块、商品模块、物流模块,也要独立部署运行。这看上去并不是什么难题,无非就是多建几个Maven项目而已,但我们细细一想,如果我们使用的是Spring Framework框架,那么在订单、商品、物流等模块的pom文件是不是引入相同的groupId和version。也有人说,我们可以在专门在一个Maven项目中存放我们的依赖,然后将那个Maven项目引入进来,这个办法确实可行,但如果有一个项目,它仅依赖spring-core,却因为引入那个Maven项目也间接引入spring-context、spring-beans,这是不是造成没必要的冗余?

    因此,Maven提供的depenencyManagement元素既能让子模块继承到父模块的元素,又能保证子模块的灵活性。代码如下:

        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.7</maven.compiler.source>
            <maven.compiler.target>1.7</maven.compiler.target>
            <junit.version>4.10</junit.version>
            <spring.version>4.1.3.RELEASE</spring.version>
        </properties>
    
    
        <dependencyManagement>
            <dependencies>
                <!-- 单元测试 -->
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>${junit.version}</version>
                    <scope>test</scope>
                </dependency>
                <!-- Spring -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-webmvc</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-jdbc</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aspects</artifactId>
                    <version>${spring.version}</version>
                </dependency>
            </dependencies>
    
    
        </dependencyManagement>
    

      

    这里使用depenencyManagement声明的依赖不会给子模块间接引入依赖,不过这段配置是会被继承的。现在,修改hello-service的pom文件如下:

    <dependencies>
    	<dependency>
    		<groupId>org.springframework</groupId>
    		<artifactId>spring-context</artifactId>
    	</dependency>
    	<dependency>
    		<groupId>junit</groupId>
    		<artifactId>junit</artifactId>
    	</dependency>
    	<dependency>
    		<groupId>com.leolin.mvnbook</groupId>
    		<artifactId>hello-pojo</artifactId>
    		<version>1.0-SNAPSHOT</version>
    	</dependency>
    </dependencies>
    

      

    我们可以看到,spring-context和junit我们都没引入版本号,但Maven会去依赖hello-parent所定义的版本号。

  • 相关阅读:
    浅析[53300] FATAL: remaining connection slots are reserved for non-replication superuser connections
    浅析Web安全漏洞里的X-Frame-Options、X-XSS-Protection、X-Content-Type-Options响应头配置以及如何通过nginx配置避免
    浅析SpringSecurity的方法级安全管控
    浅析mybatis的全局配置文件mybatis-config.xml各配置的意义
    字节序--大端字节序和小端
    【转】go语言中int和byte转换方式
    [转]float32数据在内存中的存储方法
    go语言复制一个struct 对象
    一个table 中 可以有多个tbody. table 可以嵌套
    【转】rpc框架设计
  • 原文地址:https://www.cnblogs.com/beiluowuzheng/p/12771480.html
Copyright © 2020-2023  润新知