Рубрики
Без рубрики

Maven – Как создать многомодульный проект

– Maven – Как создать многомодульный проект

В этом уроке мы покажем вам, как использовать Maven для управления многомодульным проектом, содержащим четыре модуля:

  1. Модуль паролей – только интерфейс.
  2. Модуль пароля md5 – Реализация модуля пароля, хэширование пароля MD5.
  3. Модуль sha паролей – Реализация модуля паролей, хэширование паролей SHA.
  4. Веб–модуль – Простое веб-приложение MVC для хэширования входных данных с помощью алгоритма MD5 или SHA.

Зависимость от модуля.

$ password 

$ password <-- password-md5

$ password <-- password-sha

$ web <-- (password-md5 | password-sha) <-- password

Некоторые команды для построения многомодульного проекта, например:

$ mvn -pl password compile	# compile password module only	

$ mvn -pl password-sha compile	# compile password-sha module, also dependency - password

$ mvn -pl web compile		# compile web module only	

$ mvn -am -pl web compile	# compile web module, also dependency - password-sha or password-md5, password

$ mvn -pl web jetty:run 	# run web module with Jetty

$ mvn compile 			# compile everything

Используемые технологии:

  1. Мавен 3.5.3
  2. JDK 8
  3. Весна 5.1.0.ВЫПУСК
  4. thymeleaf 3.0.10.ВЫПУСК

1. Структура каталогов

В макете многомодульного проекта родительский проект содержит родительский pom.xml и каждый подмодуль (подпроект) также содержит собственный и каждый подмодуль (подпроект) также содержит собственный

2. Мавен ПОМ

Давайте рассмотрим многомодульные POM-файлы Maven.

2.1 Родительский файл POM, упаковка – pom .



    4.0.0

	
    com.mkyong.multi
    java-multi-modules
    pom
	1.0

	
	
        web
        password
        password-sha
        password-md5
    
	

2.2 В модуле пароля.




	
    
        java-multi-modules
        com.mkyong.multi
        1.0
    
    4.0.0

	
    com.mkyong.password
    password
    1.0
    jar
	

2.3 В модуле пароль-md5.



		 
    
        java-multi-modules
        com.mkyong.multi
        1.0
    
    4.0.0

	
    com.mkyong.password
    password-md5
    1.0
    jar

    
        
            com.mkyong.password
            password
            1.0
        
    


2.4 В модуле password-sha.



		 
    
        java-multi-modules
        com.mkyong.multi
        1.0
    
    4.0.0

	
    com.mkyong.password
    password-sha
    1.0
    jar

    
        
            com.mkyong.password
            password
            1.0
        
    


2.4 В веб-модуле.




    
    
        com.mkyong.multi
        java-multi-modules
        1.0
    
    4.0.0

    
    com.mkyong
    web
    1.0
    war

    

		
		
        

        
        
            com.mkyong.password
            password-sha
            1.0
        

    


3. Родительский проект

3.1 Родительский pom, эти свойства и зависимости (JDK 8, блок 5, Весна 5) являются общими для всех подмодулей.



    4.0.0

    com.mkyong.multi
    java-multi-modules
    pom
    1.0

    
        
        UTF-8
        1.8
        1.8
        5.3.1
        5.1.0.RELEASE
    

    
        web
        password
        password-sha
        password-md5
    

    

        
        
            org.springframework
            spring-context
            ${spring.version}
        

        
        
            org.junit.jupiter
            junit-jupiter-engine
            ${junit.version}
            test
        
		
        
            org.junit.jupiter
            junit-jupiter-params
            ${junit.version}
            test
        

    

    
        
            
                org.apache.maven.plugins
                maven-surefire-plugin
                2.22.0
            
            
                org.apache.maven.plugins
                maven-dependency-plugin
                3.1.1
            
        
    

4. Модуль Паролей

4.1 Модуль, содержащий только один интерфейс.

4.2 Файл POM.



    
        java-multi-modules
        com.mkyong.multi
        1.0
    
    4.0.0

    com.mkyong.password
    password
    1.0
    jar


4.3 Интерфейс.

package com.mkyong.password;

public interface PasswordService {

    String hash(String input);

    String algorithm();

}

5. Пароль-Модуль md5

5.1 Реализация модуля паролей.

5.2 Файл POM.



    
        java-multi-modules
        com.mkyong.multi
        1.0
    
    4.0.0

    
    com.mkyong.password
    password-md5
    1.0
    jar

    
        
            com.mkyong.password
            password
            1.0
        
    


5.3 Хеширование MD5.

package com.mkyong.password;

import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

@Service
public class PasswordServiceImpl implements PasswordService {

    @Override
    public String hash(String input) {
        return md5(input);
    }

    @Override
    public String algorithm() {
        return "md5";
    }

    private String md5(String input) {

        StringBuilder result = new StringBuilder();
        MessageDigest md;

        try {
            md = MessageDigest.getInstance("MD5");
            byte[] hashInBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));

            for (byte b : hashInBytes) {
                result.append(String.format("%02x", b));
            }
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException(e);
        }

        return result.toString();
    }
}

5.4 Модульный тест.

package com.mkyong.password;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class TestPasswordService {

    PasswordService passwordService;

    @BeforeEach
    void init() {
        passwordService = new PasswordServiceImpl();
    }

    @DisplayName("md5 -> hex")
    @ParameterizedTest
    @CsvSource({
            "123456, e10adc3949ba59abbe56e057f20f883e",
            "hello world, 5eb63bbbe01eeed093cb22bb8f5acdc3"
    })
    void testMd5hex(String input, String expected) {
        assertEquals(expected, passwordService.hash(input));
    }

}

6. Модуль ввода пароля-sha

6.1 Реализация модуля паролей.

6.2 Файл POM.



    
        java-multi-modules
        com.mkyong.multi
        1.0
    
    4.0.0

    com.mkyong.password
    password-sha
    1.0
    jar

    
        1.11
    

    

        
            commons-codec
            commons-codec
            ${commos.codec.version}
        

        
            com.mkyong.password
            password
            1.0
        

    


6.3 Хеширование SHA с помощью общей библиотеки кодеков Apache

package com.mkyong.password;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Service;

@Service
public class PasswordServiceImpl implements PasswordService {

    @Override
    public String hash(String input) {
        return DigestUtils.sha256Hex(input);
    }

    @Override
    public String algorithm() {
        return "sha256";
    }

}

6.4 Модульный тест.

package com.mkyong.password;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class TestPasswordService {

    PasswordService passwordService;

    @BeforeEach
    void init() {
        passwordService = new PasswordServiceImpl();
    }

    @DisplayName("sha256 -> hex")
    @ParameterizedTest
    @CsvSource({
            "123456, 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92",
            "hello world, b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
    })
    void testSha256hex(String input, String expected) {
        assertEquals(expected, passwordService.hash(input));
    }

}

7. Веб-Модуль

7.1 Веб-приложение Spring MCV + thymeleaf, хэширует входные данные с помощью алгоритма md5 или sha.

7.2 Файл POM.




    
    
        com.mkyong.multi
        java-multi-modules
        1.0
    
    4.0.0

    
    com.mkyong
    web
    1.0
    war

    
        3.0.10.RELEASE
    

    

        

        
        
            com.mkyong.password
            password-sha
            1.0
        

        
            org.springframework
            spring-webmvc
            ${spring.version}
        

        
            org.springframework
            spring-test
            ${spring.version}
        

        
        
            ch.qos.logback
            logback-classic
            1.2.3
        

        
        
            org.hamcrest
            hamcrest-library
            1.3
            test
        

        
        
            javax.servlet
            javax.servlet-api
            3.1.0
            provided
        

        
        
            org.thymeleaf
            thymeleaf
            ${thymeleaf.version}
        

        
            org.thymeleaf
            thymeleaf-spring5
            ${thymeleaf.version}
        

    

    
        java-web-project
        

            
                org.eclipse.jetty
                jetty-maven-plugin
                9.4.12.v20180830
            

            
                org.apache.maven.plugins
                maven-war-plugin
                3.2.2
            

        
    


7.3 Зависимость от веб-модуля

$ mvn -pl web dependency:tree

[INFO] com.mkyong:web:war:1.0
[INFO] +- com.mkyong.password:password-sha:jar:1.0:compile
[INFO] |  +- commons-codec:commons-codec:jar:1.11:compile
[INFO] |  \- com.mkyong.password:password:jar:1.0:compile
[INFO] +- org.springframework:spring-webmvc:jar:5.1.0.RELEASE:compile
[INFO] |  +- org.springframework:spring-aop:jar:5.1.0.RELEASE:compile
[INFO] |  +- org.springframework:spring-beans:jar:5.1.0.RELEASE:compile
[INFO] |  +- org.springframework:spring-core:jar:5.1.0.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-jcl:jar:5.1.0.RELEASE:compile
[INFO] |  +- org.springframework:spring-expression:jar:5.1.0.RELEASE:compile
[INFO] |  \- org.springframework:spring-web:jar:5.1.0.RELEASE:compile
[INFO] +- org.springframework:spring-test:jar:5.1.0.RELEASE:compile
[INFO] +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] |  +- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO] +- org.hamcrest:hamcrest-library:jar:1.3:test
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] +- org.thymeleaf:thymeleaf:jar:3.0.10.RELEASE:compile
[INFO] |  +- ognl:ognl:jar:3.1.12:compile
[INFO] |  |  \- org.javassist:javassist:jar:3.20.0-GA:compile
[INFO] |  +- org.attoparser:attoparser:jar:2.0.5.RELEASE:compile
[INFO] |  \- org.unbescape:unbescape:jar:1.1.6.RELEASE:compile
[INFO] +- org.thymeleaf:thymeleaf-spring5:jar:3.0.10.RELEASE:compile
[INFO] +- org.springframework:spring-context:jar:5.1.0.RELEASE:compile
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.3.1:test
[INFO] |  +- org.apiguardian:apiguardian-api:jar:1.0.0:test
[INFO] |  +- org.junit.platform:junit-platform-engine:jar:1.3.1:test
[INFO] |  |  +- org.junit.platform:junit-platform-commons:jar:1.3.1:test
[INFO] |  |  \- org.opentest4j:opentest4j:jar:1.1.1:test
[INFO] |  \- org.junit.jupiter:junit-jupiter-api:jar:5.3.1:test
[INFO] \- org.junit.jupiter:junit-jupiter-params:jar:5.3.1:test
[INFO] ------------------------------------------------------------------------

7.4 Пружинный материал, интегрируйте thymeleaf и конфигурацию.

package com.mkyong.web.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;

@EnableWebMvc
@Configuration
@ComponentScan({"com.mkyong"})
public class SpringConfig implements WebMvcConfigurer {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/resources/");
    }

    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(this.applicationContext);
        templateResolver.setPrefix("/WEB-INF/views/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCacheable(true);
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        templateEngine.setEnableSpringELCompiler(true);
        return templateEngine;
    }

    @Bean
    public ThymeleafViewResolver viewResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        return viewResolver;
    }

}
package com.mkyong.web;

import com.mkyong.web.config.SpringConfig;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class[] getServletConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}
package com.mkyong.web.controller;

import com.mkyong.password.PasswordService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class WelcomeController {

    private final Logger logger = LoggerFactory.getLogger(WelcomeController.class);

    @Autowired
    private PasswordService passwordService;

    @GetMapping("/")
    public String welcome(@RequestParam(name = "query",
            required = false, defaultValue = "123456") String query, Model model) {

        logger.debug("Welcome to mkyong.com... Query : {}", query);

        model.addAttribute("query", query);
        model.addAttribute("hash", passwordService.hash(query));
        model.addAttribute("algorithm", passwordService.algorithm());

        return "index";
    }

}

7.5 Модульный тест для Spring MVC.

package com.mkyong.web;

import com.mkyong.web.config.SpringConfig;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringJUnitWebConfig(SpringConfig.class)
@DisplayName("Test Spring MVC default view")
public class TestWelcome {

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webAppContext;

    @BeforeEach
    public void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();
    }

    @Test
    public void testDefault() throws Exception {

        this.mockMvc.perform(
                get("/"))
                .andExpect(status().isOk())
                .andExpect(view().name("index"))
                .andExpect(model().attribute("query", "123456"));
        //.andExpect(model().attribute("sha256", "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92"))
        //.andExpect(model().attribute("md5", "e10adc3949ba59abbe56e057f20f883e"));

    }

}

7.6 Вид на лист Тимьяна.





Сделано.

8. Демонстрация

8.1 В родительском проекте используется стандартная компиляция mvn для компиляции всех модулей, Maven определит порядок сборки.

$ mvn compile 

[INFO] Reactor Summary:
[INFO]
[INFO] java-multi-modules 1.0 ............................. SUCCESS [  0.007 s]
[INFO] password ........................................... SUCCESS [  0.539 s]
[INFO] password-sha ....................................... SUCCESS [  0.038 s]
[INFO] web ................................................ SUCCESS [  0.080 s]
[INFO] password-md5 1.0 ................................... SUCCESS [  0.035 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.822 s
[INFO] Finished at: 2018-10-23T15:32:21+08:00
[INFO] ------------------------------------------------------------------------

8.2 Установите все модули в локальное хранилище.

$ mvn install 

8.3 Компилирует только веб-модуль (Maven найдет зависимость модуля паролей от локального репозитория, поэтому нам нужно установка mvn

$ mvn -pl web compile 

8.4 В качестве альтернативы добавьте -am для компиляции веб-модуля, а также его модулей зависимостей (пароль-sha и пароль).

$ mvn -am -pl web compile

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] java-multi-modules                                                 [pom]
[INFO] password                                                           [jar]
[INFO] password-sha                                                       [jar]
[INFO] web                                                                [war]

......

[INFO] Reactor Summary:
[INFO]
[INFO] java-multi-modules 1.0 ............................. SUCCESS [  0.009 s]
[INFO] password ........................................... SUCCESS [  0.534 s]
[INFO] password-sha ....................................... SUCCESS [  0.036 s]
[INFO] web 1.0 ............................................ SUCCESS [  0.077 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.780 s
[INFO] Finished at: 2018-10-23T15:36:16+08:00
[INFO] ------------------------------------------------------------------------

8.5 Протестируйте веб-модуль с помощью веб-причала mvn-pl: выполните команду .

$ mvn install

$ mvn -pl web jetty:run

//...
[INFO] 1 Spring WebApplicationInitializers detected on classpath
[INFO] DefaultSessionIdManager workerName=node0
[INFO] No SessionScavenger set, using defaults
[INFO] node0 Scavenging every 600000ms
[INFO] Started ServerConnector@40a8a26f{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
[INFO] Started @6398ms
[INFO] Started Jetty Server

8.6 http://localhost:8080

8.7 http://localhost:8080/?query = мкенг

8.8 Обновление алгоритма md5. Перезапустите сервер причала.

		
        
            com.mkyong.password
            password-md5
            1.0
        
        
        

8.9 http://localhost:8080/?query = мкенг

Скачать Исходный Код

Рекомендации

  1. Учебное пособие: Лист Тимьяна + Весна
  2. Обслуживание веб-контента с помощью Spring MVC
  3. Многомодульный Проект
  4. Spring IO – Создание многомодульного проекта
  5. Многомодульные сборки проектов с использованием Maven и Gradle
  6. Maven – Как создать проект Java
  7. Maven – Как создать проект веб-приложения Java

Оригинал: “https://mkyong.com/maven/maven-how-to-create-a-multi-module-project/”