한 기사에서는 Maven에 능숙해지고 기존 Java 및 JavaWeb 프로젝트에서 Maven 프로젝트로 빠르게 전환하는 방법과 Maven 실제 사례 자습서를 알려줍니다.

1. 메이븐 개념

1.1 메이븐 소개

Maven은 프로젝트 개체 모델(Project Object Model), 표준 컬렉션 집합, 프로젝트 수명 주기(Project Lifecycle), 종속성 관리 시스템(Dependency Management System)을 포함하는 프로젝트 관리 도구이며 다음에서 정의를 실행하는 데 사용됩니다. 수명 주기 단계에서 플러그인 목표의 논리입니다. Maven을 사용할 때 잘 정의된 프로젝트 개체 모델로 프로젝트를 설명하면 Maven이 공유(또는 사용자 지정) 플러그인 집합에서 교차 절단 논리를 적용할 수 있습니다.

Maven은 "전문가", "전문가"로 번역됩니다. Maven은 Apache에서 순수 Java로 개발된 오픈 소스 프로젝트로, Maven을 사용하여 Java 프로젝트를 빌드하고 관리할 수 있는 프로젝트 관리 도구입니다. 현재 Maven을 사용하는 프로젝트의 수는 계속해서 증가하고 있습니다.

메이븐 공식 홈페이지: https://maven.apache.org/

Maven 기능: 정리, 컴파일, 테스트(직접 단위 테스트 작성), 보고, 패키징(jar, war 내보내기), 배포.

1.2 프로젝트 건설이란

    프로젝트 구성은 소스 코드 작성에서 컴파일, 테스트, 패키징, 배포 및 실행에 이르는 프로젝트 프로세스입니다.

1.2.1 전통적인 프로젝트 건설 과정

Eclipse를 사용하여 프로젝트를 빌드하는 기존 프로세스는 다음과 같습니다.

     구축 과정은 다음과 같습니다.  
        1. Eclipse에서 JavaWeb 프로젝트를 생성합니다.
        2. 프로젝트에 소스 코드 및 구성 파일을 작성합니다.
        3. 소스 코드를 컴파일하고 Java 파일을 클래스 파일로 컴파일합니다.
        4. Junit 단위 테스트를 실행합니다.
        5. 프로젝트를 war 패키지로 만들고 Tomcat에 배포하여 실행합니다.

1.2.2 Maven 프로젝트 구축 과정

    Maven은 프로젝트 구축 프로세스를 표준화합니다. 각 단계는 하나의 명령으로 완료됩니다. 다음 그림은 구축 프로세스의 일부 단계를 보여줍니다. 다음 장에서는 각 단계를 자세히 소개합니다. 일반적인 개요는 다음과 같습니다.

    위 그림의 일부 단계에 해당하는 명령어는 다음과 같다.
        cleanup 단계에 해당하는 Maven 명령어는 clean으로 출력 클래스 파일을 정리한다.
        컴파일 단계에 해당하는 Maven 명령은 java 코드를 클래스 파일로 컴파일하는 compile입니다.
        패키징 단계에 해당하는 Maven 명령은 package, Java 프로젝트는 jar 패키지로, 웹 프로젝트는 war 패키지로 패키징할 수 있습니다.
        Maven 프로젝트(웹 프로젝트)를 실행하려면 tomcat:run 명령이 필요합니다.

    Maven 프로젝트 구축의 장점:
        1. 하나의 명령으로 구축 및 운영이 완료되어 편리하고 빠릅니다.
        2. Maven은 각 구성 단계를 규제하므로 대규모 팀의 공동 개발에 매우 ​​도움이 됩니다.

1.3 종속성 관리란?

    종속성이란 무엇입니까?Java 프로젝트는 실행하기 위해 일부 타사 jar 패키지를 사용해야 할 수 있으므로 이 Java 프로젝트는 이러한 타사 jar 패키지에 종속되어 있습니다. 예를 들어 crm 시스템의 아키텍처는 SSH 프레임워크이고 crm 프로젝트는 SSH 프레임워크에 의존하며 특히 Hibernate, Spring, Struts2 관련 jar 패키지에 의존합니다.

    종속성 관리란 프로젝트의 모든 종속 jar 패키지에 대한 표준화된 관리입니다.

1.3.1 기존 프로젝트의 종속성 관리

    전통적인 프로젝트 엔지니어링이 의존하는 jar 패키지는 완전히 수동으로 관리됩니다.아래 그림과 같이 프로그래머가 인터넷에서 jar 패키지를 다운로드하여 프로젝트 프로젝트에 추가합니다.프로그래머는 Hibernate, Struts2, 그리고 WEB-INF/lib 디렉토리로 Spring.

     jar 패키지를 수동으로 복사하여 프로젝트에 추가하는 문제는 다음과 같습니다.
        1. jar 패키지 버전의 통합 관리가 없기 때문에 버전 충돌이 쉽게 발생할 수 있습니다.
        2. 인터넷에서 jar 패키지를 찾는 것이 매우 불편하고 일부 jar는 찾을 수 없습니다.
        3. jar 패키지가 프로젝트에 추가되고 프로젝트가 너무 큽니다.

1.3.2 Maven 프로젝트의 종속성 관리

    Maven 프로젝트 관리가 의존하는 jar 패키지는 jar 패키지를 프로젝트에 수동으로 추가할 필요가 없으며 jar 패키지의 좌표를 pom에 추가하기만 하면 됩니다.

     Maven 종속성 관리를 사용하여 jar를 추가할 때의 이점:
        1. pom.xml 파일을 통한 jar 패키지 버전의 통합 관리로 버전 충돌을 방지할 수 있습니다.
        2. Maven 팀은 현재 사용되는 jar 패키지를 포함하는 매우 완전한 Maven 창고를 유지 관리합니다.Maven 프로젝트는 Maven 창고에서 jar 패키지를 자동으로 다운로드할 수 있어 매우 편리합니다.

1.4 Maven 개념 모델

    위의 개념에서 다음과 같이 언급했습니다. Maven은 프로젝트 개체 모델(Project Object Model), 표준 컬렉션 집합, 프로젝트 수명 주기(Project Lifecycle), 종속성 관리 시스템(Dependency Management System)을 포함하는 프로젝트 관리 도구입니다. ), 라이프사이클 단계(phase)에서 정의된 플러그인의 목표를 실행하는 데 사용되는 로직.

1.4.1 프로젝트 개체 모델

    작은 설명 정보를 통해 프로젝트 구성, 보고 및 문서화를 관리할 수 있는 프로젝트 관리 도구 소프트웨어인 Maven 프로젝트 개체 모델(POM).

    프로그램 구축 기능 외에도 Maven은 고급 프로젝트 관리 도구를 제공합니다. Maven 기본 빌드 규칙의 높은 재사용성으로 인해 간단한 프로젝트는 종종 2~3줄의 Maven 빌드 스크립트로 빌드할 수 있습니다. 

    Maven 프로젝트에는 pom.xml 파일을 통해 프로젝트 좌표, 프로젝트 종속성, 프로젝트 정보, 플러그인 목표 등을 정의하는 pom.xml 파일이 있습니다.

먼저 pom.xml을 살펴보겠습니다.

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.maven</groupId>
    <artifactId>maven-helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>第一个maven工程</name>
    <description>第一个maven工程</description>

    <!-- 添加依赖: servlet-api,jsp-api,junit单元测试 -->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

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

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <!-- 配置了很多插件 -->
        <plugins>
            <!--jdk编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>utf-8</encoding>
                </configuration>
            </plugin>

            <!--引入tomcat7的插件-->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <!--端口号-->
                    <port>9090</port>
                    <!--path就相当于部署项目时候的ContextPath-->
                    <path>/mgr</path>
                    <uriEncoding>UTF-8</uriEncoding>
                    <server>tomcat7</server>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

파트 1: 프로젝트의 기본 정보

<modelVersion>4.0.0</modelVersion>
<groupId>com.maven</groupId>
<artifactId>maven-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>第一个maven工程</name>
<description>第一个maven工程</description>

두 번째 부분: 종속성으로 둘러싸인 부분은 프로젝트에서 사용해야 하는 jar 패키지입니다.

<!-- 添加依赖: servlet-api,jsp-api,junit单元测试 -->
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

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

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

세 번째 부분: 빌드로 둘러싸인 부분은 프로젝트에서 사용해야 하는 플러그인입니다.

<build>
    <!-- 配置了很多插件 -->
    <plugins>
        <!--jdk编译插件-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>utf-8</encoding>
            </configuration>
        </plugin>

        <!--引入tomcat7的插件-->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <!--端口号-->
                <port>9090</port>
                <!--path就相当于部署项目时候的ContextPath-->
                <path>/mgr</path>
                <uriEncoding>UTF-8</uriEncoding>
                <server>tomcat7</server>
            </configuration>
        </plugin>
    </plugins>
</build>

    위에서 자세히 소개했으며 다음과 같이 세 부분으로 나뉩니다.
        1. 프로젝트 자체에 대한 정보.
        2. 프로젝트 작업이 의존하는 jar 패키지 정보.    
        3. jdk, tomcat 정보와 같은 프로젝트 운영 환경 정보.

1.4.2 종속성 관리 시스템

    Maven의 종속성 관리를 통해 프로젝트가 종속된 jar 패키지를 통합적으로 관리합니다. 프로젝트는 pom.xml에서 종속성을 정의하여 jar 패키지를 관리합니다.

    그림의 중앙은 중앙 창고를 의미하고, b2b는 원격 창고를 의미하며, 로컬은 로컬 창고를 의미합니다.여기서는 종속성을 구성하는 세 부분에 중점을 둡니다. 1.
        회사 조직의 이름.
        2. 프로젝트 이름.
        3. 버전 번호.

특정 종속성을 분석해 보겠습니다.

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

    여기서 javax.servlet은 회사 조직(상위 프로젝트)의 이름이고 javax.servlet-api는 프로젝트 이름이며 3.0.1은 버전 번호입니다.

    왜 의존성 관리인가?
        종속성 관리:
            1. 인터넷에 연결하여 자동으로 다운로드할 수 있습니다.
            2. 자체 개발한 모듈에 대한 종속성 관리를 수행합니다.

1.4.3 프로젝트 라이프사이클

    그림 하단의 Build 생명주기는 Maven의 생명주기를 의미하며, 아래의 Plug-in은 플러그인을 의미합니다. 즉, 각 Maven 명령은 Maven의 기본 플러그인에 해당합니다.

    정리, 컴파일, 테스트, 배포 등 프로젝트 구성은 Maven을 통해 완료됩니다. Maven은 이러한 프로젝트를 수명 주기로 표준화합니다.

     Maven은 몇 가지 간단한 명령을 실행하여 위의 수명 주기 프로세스를 실현할 수 있습니다.

1.4.4 표준 세트 세트

    Maven은 전체 프로젝트 관리 프로세스에 대한 일련의 표준을 정의합니다.예를 들어 Maven 건설 프로젝트에는 표준 디렉토리 구조, 표준 수명 주기 단계 및 종속성 관리를 위한 표준 좌표 정의가 있습니다.
    
    Maven은 서로 다른 개발자의 협업을 용이하게 하고 일부 통합 자동화 스크립트의 구현을 용이하게 하는 공통 표준 디렉토리 구조의 사용을 지지합니다.

    이전에 생성된 Java 프로젝트:
        src -> 소스 코드 디렉터리이지만 이것은 표준이 아니므로 아무렇게나 폴더를 만들어 소스 코드 디렉터리로 만들 수 있습니다.
        libs -> 타사 jar 패키지이지만 디렉터리는 아무 이름이나 가능합니다. 
    
    이전에 만든 웹 프로젝트:
        src -> 소스 코드 디렉터리.
        웹 -> 정적 리소스, 구성 파일 및 타사 jar를 저장하기 위해 IDEA 도구에서 만든 디렉터리입니다.
        WebContent/WebRoot -> 정적 리소스, 구성 파일 및 타사 jar 파일을 저장하기 위해 Eclipse 도구에서 만든 디렉터리입니다.

    이전에 만든 프로젝트에는 표준이 없었습니다.

1.4.5 플러그인 목표

    Maven은 플러그인을 기반으로 프로젝트 수명 주기를 관리합니다.

1.5 메이븐을 사용하는 이유

    1. 프로젝트는 프로젝트입니다.
        프로젝트가 매우 크면 패키지를 사용하여 모듈을 나누는 것이 적합하지 않습니다.각 모듈이 프로젝트에 해당하는 것이 더 좋으며 분업과 협업에 도움이 됩니다. Maven의 도움으로 프로젝트를 여러 프로젝트로 분할할 수 있습니다.

    2. 프로젝트에 사용된 jar 패키지는 프로젝트의 lib에 "복사" 및 "붙여넣기"해야 하므로 관리가 불편합니다. 프로젝트가
        상대적으로 큰 경우 큰 프로젝트를 여러 개의 작은 프로젝트로 분할합니다. 각각의 소규모 프로젝트는 여러 명의 개발자가 담당하며, 예를 들어 전자상거래 프로젝트는 계정 관련 프로젝트, 주문 관련 프로젝트, 상품 관련 프로젝트로 구분되며, 이들 프로젝트의 구조는 유사하며 사용되는 기술은 다음과 같습니다. 동일: SSM(Spring , Springmvc, Mybatis), 각 프로젝트는 이러한 jar의 복사본을 자체 프로젝트 디렉토리에 복사해야 합니다. 지난 10개의 프로젝트는 단지 10개의 jar 복사본만 복사했습니다. 나중에 우리는 프로젝트를 업그레이드해야 합니다. 교체하세요. 이때 항목 10개를 차례로 교체해야 하는데 이 작업도 상당히 고통스럽습니다.
        Maven의 도움으로 jar 패키지를 "웨어하우스"에 저장할 수 있습니다. 어떤 프로젝트에 있든 참조만 사용하면 됩니다.

    3. jar 패키지가 필요한 경우 직접 준비하거나 공식 웹 사이트에서 다운로드해야 합니다.
        예를 들어 프로젝트에서 fastjson을 사용해야 합니다. 이때 Baidu로 이동하여 fastjson 관련 jar를 검색합니다. 패키지를 다운로드하고 프로젝트의 lib 아래에 넣은 다음 프로젝트의 클래스 경로에 추가하고 이를 사용하여 이 jar의 버전이 원하는 버전이 아니라 너무 오래되었는지 확인한 다음 살펴봅니다. 다시 그것을 위해, 그것은 고통 스럽습니다.
        Maven은 각 jar에 대해 고유한 플래그를 정의하며 이를 maven에서 프로젝트의 좌표라고 하며 이를 통해 사용해야 하는 jar 패키지의 모든 버전을 찾을 수 있습니다.

    4. jar 패키지 버전 불일치의 위험
        프로젝트에서 a.jar를 사용하고 c.jar의 버전 1.5에 의존하는 a.jar를 프로젝트에 복사하고 나중에 b.jar를 사용하지만 b.jar도 c.jar 1.0 버전에 의존하는데, 이때 b.jar와 c-1.0.jar을 임포트하면 c.jar 버전이 2개여서 충돌이 나고 에러가 난다. 시작할 때 보고됩니다.이 경우 jar 충돌 문제를 해결하기 시작해야 하며 이 또한 매우 고통스럽습니다.
        Maven은 서로 다른 버전 간의 jar 충돌을 쉽게 해결할 수 있습니다.

    5. jar 패키지는 다른 jar 패키지에 의존하며 프로젝트에 수동으로 추가해야 합니다.
        일반적으로 jar 패키지는 독립적으로 존재하지 않습니다. 일반적으로 일부 jar는 다른 jar도 사용합니다. 예를 들어 spring-aop.jar는 spring을 사용합니다. -core .jar, 이 종속성은 상대적으로 단순할 수 있으며 일부 종속성은 여러 수준을 가질 수 있습니다. , When it comes to a.jar을 사용할 때 나머지 3개를 포함해야 하므로 jar를 사용할 때 이러한 jar가 의존할 jar를 명확하게 알고 모두 가져와야 합니다. 그렇지 않으면 프로젝트가 수행되지 않습니다. 정상적인 운영에서 프로젝트가 많은 jar를 사용하면 어떤 jar가 누락되었는지 판단하기 어렵습니다. 프로젝트 실행 과정에서 오류가 보고될 때만 알 수 있습니다. 이 또한 상당히 고통스럽고 많은 낭비입니다. 시간.
        Maven은 자동으로 jar 종속성 문제를 해결합니다.예를 들어 a-1.0.jar를 사용하고 a-1.0.jar이 b-1.1.jar 및 c-1.5.jar에 의존하는 경우 a-1.0.jar를 도입하면 Maven을 통해 b-1.1.jar 및 c-1.5.jar을 자동으로 가져옵니다.

    6. 통일된 프로젝트 구조
        오래전 이클립스를 이용해 프로젝트를 빌드할 때 자바 소스코드 위치, 리소스 파일 위치, 테스트 파일 위치, 정적 리소스 위치, 컴파일된 클래스 파일의 위치는 모두 마음대로 배치할 수 있으며, 이는 각 회사의 Architect가 프로젝트를 빌드할 때 결정하고 경험에 따라 정의하므로 회사마다 프로젝트 구조가 다를 수 있습니다. 어디에 있는지 아는 사람의 안내가 필요하므로 비용이 눈에 띄게 증가합니다.모든 사람이 특정 사양에 따라 동일한 프로젝트 구조를 채택하면 매우 편리하지 않을까요?모든 사람이 특정 계약을 따르고 프로젝트는 다음과 같은 동일한 구조를 사용합니다.Java 파일, 리소스 파일, 테스트 케이스, 정적 리소스, 컴파일된 클래스, 패키징 후 jar의 위치 등 다양한 파일의 위치, 이런 것들은 Java 개발을 하는 모든 회사가 동의하면 이와 같은 프로젝트를 얻은 후 많은 것을 저장하십시오.
        Maven을 사용하여 구축된 프로젝트 구조는 동일한 구조를 따라야 합니다.Java 소스 파일, 리소스 파일, 테스트 케이스 클래스 파일 및 정적 리소스 파일이 모두 합의됩니다.모두가 이 계약을 따릅니다.프로젝트에서 Created by Maven을 사용하는 경우 새로운 사람을 모집합니다. Maven을 이해하면 교육이 전혀 필요하지 않으며 프로젝트가 떠오를 때 전체 프로젝트의 구조를 이해할 수 있습니다.

    7. 교차 플랫폼
        Maven은 교차 플랫폼이며 Windows 및 Linux에서 사용할 수 있습니다.

2. Maven 설치 및 구성

2.1 JDK 설치 및 JDK 환경 변수 구성

    Maven 설치는 JAVA_HOME 구성의 환경 변수를 기반으로 해야 합니다.

    시스템 변수:
        변수명: JAVA_HOME
        변수값: JDK 설치 루트 경로(C:\Java\jdk1.8.0_311)

    경로 경로 가져오기:
        %JAVA_HOME%\bin

    참고: Maven3.3+ 버전, jdk는 1.7 이상입니다.

2.2 메이븐 설치

2.2.1 메이븐 다운로드

    Maven의 공식 웹 사이트 다운로드 주소: https://maven.apache.org/download.cgi, 최신 버전을 다운로드할 수 있습니다.
        
    참고: Maven에는 최신 버전이 필요하지 않지만 최소한 버전 3.3 이상이 필요합니다.

2.2.2 메이븐 설치

    Maven 자체는 설치할 필요가 없는 그린 버전이므로 압축을 풀기만 하면 됩니다. 중국어와 공백이 포함되지 않은 디렉토리에 Maven 압축을 풉니다.

2.2.3 Maven 환경 변수 설정

    1. 컴퓨터 -> 속성 -> 고급 시스템 설정 -> 고급 탭 -> 환경 변수를 마우스 오른쪽 버튼으로 클릭합니다.    

    2. 새 시스템 변수 생성:
        변수 이름: MAVEN_HOME
        변수 값: D:\Tools\apache-maven-3.8.5(Maven 압축 해제 경로)

     3. Path 시스템 변수에 %MAVEN_HOME%\bin을 추가합니다.

2.2.4 테스트

    cmd 명령줄 창을 열고 mvn -version 명령을 실행하여 구성이 성공했는지 테스트합니다.

2.3 Maven 디렉토리 분석

    bin 디렉토리: Maven이 실행하는 스크립트.
        mvn(실행 모드에서 프로젝트 실행)
        mvnDebug(디버그 모드에서 프로젝트 실행)

    부팅 디렉터리: Maven을 실행하는 데 필요한 클래스 로더입니다.

    conf 디렉토리:
        전체 Maven 도구의 핵심 구성 파일인 settings.xml. 

    lib 디렉토리: Maven은 종속 jar 패키지를 실행합니다.

2.4 전역 설정 및 사용자 설정

    Maven 창고 주소, 사설 서버 및 기타 구성 정보는 전역 구성과 사용자 구성으로 구분되는 settings.xml 파일에서 구성해야 합니다.

    Maven 설치 디렉터리에 conf/settings.xml 파일이 있는데 이 settings.xml 파일은 모든 Maven 프로젝트에 사용되며 Maven의 전역 구성으로 사용됩니다.

    개인화된 구성이 필요한 경우 사용자 구성에서 설정해야 합니다.사용자 구성의 setting.xml 파일의 기본 위치는 ${user.home}/.m2/settings.xml 디렉토리, ${user입니다. home}은 Windows 사용자 디렉터리를 나타냅니다. (개인 추천)

    Maven은 먼저 사용자 구성을 찾습니다. 발견되면 사용자 구성 파일이 우선하고 그렇지 않으면 전역 구성 파일이 사용됩니다.

    역할: Maven의 로컬 웨어하우스 위치, 중앙 웨어하우스 미러링 및 기타 구성.

    Maven 전역 구성 파일 settings.xml에 대한 자세한 설명: https://cloud.tencent.com/developer/article/1014577

2.5 Alibaba Cloud 미러 웨어하우스 구성

    Maven을 사용하여 빌드된 모든 프로젝트는 Maven 창고에서 다운로드되며 두 가지 문제가 있습니다.
        1. 다운로드 속도가 너무 느립니다.
        2. 공식 미러 노드 블랙리스트 메커니즘.
    
    참고: 외부 액세스를 위해 IP 주소 ip138.com을 확인하십시오.

    위의 문제를 기반으로 국내 미러 노드를 구성해야 하며 Alibaba Cloud 미러를 사용하는 것이 좋습니다(기본 미러 노드를 주석 처리해야 함).

    참고: "미러링은 일종의 파일 저장소이자 일종의 중복성입니다. 한 디스크의 데이터는 미러인 다른 디스크에 동일한 복사본을 가집니다."

방법 1: 글로벌 구성

    Maven의 setting.xml 구성에 Alibaba Cloud의 이미지를 추가할 수 있으므로 매번 pom에 미러 웨어하우스 구성을 추가할 필요가 없으며 미러 노드 아래에 하위 노드를 추가할 수 있습니다.

<mirrors>
    <!-- mirror
     | Specifies a repository mirror site to use instead of a given repository. The repository that
     | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
     | for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
     |
    <mirror>
      <id>mirrorId</id>
      <mirrorOf>repositoryId</mirrorOf>
      <name>Human Readable Name for this Mirror.</name>
      <url>http://my.repository.com/repo/path</url>
    </mirror>
     -->

    <!--
    <mirror>
      <id>maven-default-http-blocker</id>
      <mirrorOf>external:http:*</mirrorOf>
      <name>Pseudo repository to mirror external repositories initially using HTTP.</name>
      <url>http://0.0.0.0/</url>
      <blocked>true</blocked>
    </mirror>
 	-->

    <!-- 配置阿里云镜像节点 -->
    <mirror> 
        <id>alimaven</id> 
        <name>aliyun maven</name> 
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url> 
        <mirrorOf>central</mirrorOf>
    </mirror> 
</mirrors>

방법 2: 사용자 구성

    conf/settings.xml을 .m2 폴더에 복사합니다.

    참고: .m2 폴더 생성에 실패하면 명령줄을 사용하여 생성하고 사용자 디렉터리를 입력한 다음 mkdir .m2를 실행할 수 있습니다.

<mirrors>참고: 미러 구성을 아래에 두어야 합니다.

2.6 메이븐 제거

    Maven은 설치 중에 압축을 풀고 환경 변수를 구성하고 로컬 웨어하우스를 설정하기만 하므로 설치 제거도 매우 간단합니다.
        1. 압축 해제된 maven 폴더 삭제
        2. 설정된 환경 변수 MAVEN_HOME 삭제, 경로에 추가된 "%MAVEN_HOME%\bin;" 삭제
        3. 로컬웨어 하우스 삭제

3. 메이븐 계약

Java 프로젝트 및 JavaWeb 프로젝트에서 src는 소스 코드 디렉토리입니다.

    Maven 프로젝트에는 다음과 같은 4개의 소스 코드 디렉토리가 있습니다.
        src/main/java: 프로젝트의 소스 코드(.java) 파일을 저장합니다.
        src/main/resources: Spring, Mybatis 구성 파일 및 db.properties 데이터베이스 리소스 파일과 같은 프로젝트 구성 리소스 파일 및 리소스 파일을 저장합니다.
        src/test/java: Junit 테스트 클래스와 같은 테스트 코드를 저장합니다.
        src/test/resources: 테스트에 사용되는 구성 파일을 저장합니다.

src/main/webapp: Eclipse에서 웹 프로젝트의 WebContent/WebRoot 디렉토리와 유사한 Maven 웹 프로젝트의 디렉토리입니다.

target: 프로젝트 출력 위치, 컴파일된 클래스 파일이 이 디렉터리에 출력됩니다.

pom.xml: 현재 프로젝트의 구성 관리, 종속성 관리 및 플러그인 관리.

구조는 다음과 같습니다.

프로젝트
    |---src
    |----|---main
    |----|----|---java 프로젝트의 .java 파일 저장
    |----|----| -- -resources spring, hibernate 구성 파일과 같은 프로젝트 리소스 파일 저장
    |----|----|---webapp webapp 디렉토리는 웹 프로젝트의 기본 디렉토리입니다.
    |----|-- --|--- |---WEB-INF
    |----|----|---|---web.xml
    |----|---테스트
    |----| ----|- --java는 JUnit 테스트 클래스와 같은 모든 테스트 .java 파일을 저장합니다.
    |----|----|---리소스 테스트 리소스 파일
    |---대상 대상 파일 출력 위치는 다음과 같습니다. .class, .jar, .war 파일
    |---pom.xml 메이븐 프로젝트 코어 구성 파일

4. Maven 프로젝트 구현 수동 빌드

4.1 Maven Java 프로젝트 수동 빌드

    우리는 알아야 합니다. Maven 자체는 플랫폼 독립적인 오픈 소스 프로젝트입니다. 즉, Maven은 모든 개발 플랫폼에서 생성된 Maven 프로젝트에 대한 jar 파일 지원을 제공할 수 있습니다. Eclipse 및 IDEA, Maven을 직접 실행하여 프로젝트에 대한 jar 파일 지원을 제공할 수도 있습니다.

    그런 다음 독립적인 Maven 프로젝트를 수동으로 생성, 컴파일 및 실행하고 이 프로젝트를 통해 Maven 자체에 대한 다른 지식 포인트를 추가해 보겠습니다.

4.1.1 Maven 프로젝트의 폴더 디렉토리 생성

먼저 디렉토리 구조를 살펴보겠습니다.

MavenProjectName:
    |---src
    |----|---main
    |----|----|---java
    |----|----|---resources
    |-- --|---테스트
    |----|----|---자바
    |----|----|---리소스
    |---pom.xml

    그런 다음 먼저 이 가장 간단한 구조를 따르고 Maven 프로젝트 Java 파일 및 테스트 파일을 저장하기 위해 자체 디스크에 폴더 구조를 수동으로 만들고 이 폴더에 코드를 작성하고 POM 파일을 추가하고 이 프로젝트를 점차 설치하여 컴파일 및 실행합니다.

4.1.2 Maven 프로젝트의 pom.xml 파일 구성

    Maven 프로젝트의 pom.xml 파일은 Maven 프로젝트의 영혼입니다.Maven 프로젝트에서 jar 파일에 대한 모든 중요한 정보와 지원은 이 파일을 통해 구성됩니다.pom.xml 파일을 수동으로 구성하겠습니다(인코딩 형식 참고).

1. 프로젝트의 루트 폴더 아래에 pom.xml 구성 파일을 만들고 다음 기본 구조를 만듭니다.

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

</project>

위의 구성은 Maven 프로젝트의 pom.xml 파일의 기본 구성 방법에 속합니다.

    <modelVersion></modelVersion> 태그: 현재 Maven 프로젝트에서 사용하는 설명 사양의 버전 번호를 나타냅니다. 이 레이블에 대해 걱정할 필요가 없습니다.주류 Maven 프로젝트에서 사용하는 설명 사양의 버전 번호는 버전 4.0.0입니다.

2. pom.xml 파일에서 프로젝트 좌표를 구성합니다.

    각 Maven 프로젝트는 pom.xml 파일에 다음 내용을 구성해야 하는데 Maven은 이러한 구성 정보를 기반으로 프로젝트의 특정 위치를 결정하므로 아래에서 구성할 정보를 프로젝트의 프로젝트 좌표라고도 합니다.

    프로젝트 좌표를 이해하는 방법: 실생활에서 좌표 개념은 매우 인기가 있습니다. Yang Guofu Malatang에서 같은 식사를 주문했는데 왜 외국 코드 형제가 다른 사람의 손이 아닌 당신의 부분을 정확하게 전달할 수 있습니까? 좌표를 사용하십시오. 실생활에서 우리는 지방, 도시, 지구, 거리, 지구, 건물, 단위, 층, 집 번호 및 기타 정보와 같은 정보를 사용하여 우리 자신의 좌표를 식별하므로 테이크 아웃 형제는 이에 따라 테이크 아웃을 올바르게 전달할 수 있습니다. "좌표" .

    마찬가지로 우리 컴퓨터 중 하나에 동시에 여러 Java 프로젝트가 있을 수 있는데 Maven은 이러한 프로젝트를 어떻게 구분합니까? 프로젝트 좌표도 사용하므로 프로젝트 좌표는 Maven 소프트웨어에서 Java 프로젝트를 식별하는 데 사용하는 고유 식별자라고 합니다.

    매운탕을 먹을 때 갑오징어를 꼭 넣어야 하고 고수는 절대 먹지 않는 것처럼 Maven 소프트웨어도 프로젝트 좌표에 따라 이 프로젝트에 어떤 jar 파일이 필요한지, 어떤 jar 파일이 필요하지 않은지 구분합니다.

    좋아요! 이제 프로젝트 좌표의 의미를 이해할 수 있을 것입니다. Maven 프로젝트의 프로젝트 좌표를 구성하는 방법을 소개하겠습니다. 먼저 설명하겠습니다. 프로젝트 좌표는 pom.xml 파일의 <project></project> 태그 아래에 직접 구성됩니다.

항목의 좌표를 설명하는 표준 구조는 다음과 같습니다.

<project>
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
    <packaging></packaging>
    <classifier></classifier>
</project>

이러한 레이블의 구성 정보의 의미는 다음과 같습니다.

    <groupId> 태그: 프로젝트 조직의 고유 식별자입니다. 일반적으로 회사나 조직의 이름이거나 대규모 프로젝트의 이름이며, 일반적으로 도메인 이름이 반전되어 창고에 설치된 첫 번째 수준의 디렉토리 구조에 영향을 미칩니다.
        예:
            서블릿 관련 jar, 해당 groupId는 javax.servlet, javax.servlet은 큰 프로젝트의 이름(상위 프로젝트 이름)입니다.
            Mybatis 관련 jar의 groupId는 org.mybatis이고 org.mybatis는 회사 이름 또는 조직 이름입니다.
    
    <artifactId> 태그: 프로젝트의 고유 식별자입니다. 일반적으로 웨어하우스에 설치된 하위 디렉토리 구조와 패키지 이름에 영향을 미치는 프로젝트 이름이나 하위 프로젝트 이름 또는 모듈 이름입니다. <artifactId> 태그의 값은 현재 프로젝트(모듈)의 실제 이름을 사용하는 것이 좋습니다.
    
    groupId와 artifactId는 프로젝트 고유성을 보장하기 위해 통칭하여 "좌표"라고 합니다. 프로젝트를 Maven 로컬 웨어하우스로 가져오려면 이 두 ID에 따라 검색해야 프로젝트를 찾을 수 있습니다. groupId는 일반적으로 여러 섹션으로 나뉩니다. 여기서는 두 섹션만 말합니다. 첫 번째 섹션은 도메인이고 두 번째 섹션은 회사 이름입니다. 도메인은 org, com, cn 등으로 나뉘는데, 그 중 org는 비영리 단체, com은 영리 단체입니다. apache 회사의 tomcat 프로젝트를 예로 들어 보겠습니다. 이 프로젝트의 groupId는 org.apache이고 도메인은 org(tomcat은 비영리 프로젝트이므로), 회사 이름은 apache, artifactId는 tomcat입니다.

    <version> 태그: 웨어하우스에 설치된 최종 디렉토리 구조와 패키지 이름에 영향을 미치는 현재 프로젝트의 버전 번호를 나타냅니다.

    <packaging> 태그: 현재 프로젝트의 패키징 방법을 나타내며 공통 값인 "jar" 외에 현재 프로젝트가 war 파일로 패키징된다는 의미인 "war" 값을 가질 수도 있습니다. 선택적 jar: 패키지가 .jar
        파일 팩으로 패키지됨을 의미합니다.
        선택적 war: 패키지가 .war 파일로 패키징되었음을 나타냅니다.
        선택적 pom: 현재 프로젝트가 관리 프로젝트임을 나타냅니다.
        기본값은 jar입니다.
    
    <classifier> 태그: 현재 프로젝트를 패키징하여 생성할 때 생성되는 일부 첨부 파일을 나타내기 위해 사용합니다.
        더보기:
    
    https://www.cnblogs.com/love-kimi/archive/2012/10/09/2716507.html 어때요, 태그가 많죠? 하지만 실제로 Maven 프로젝트를 생성할 때 그렇게 많은 좌표가 필요하지도 않고 Maven 프로젝트가 가져야 하는 좌표 레이블은 처음 3개뿐!
    
    현재 프로젝트의 좌표를 구성하는 방법을 살펴보겠습니다. 이전에 만든 pom.xml 파일의 <project></project> 태그에 다음 태그 콘텐츠를 복사합니다.

<groupId>com.maven</groupId>
<artifactId>MavenTest</artifactId>
<version>0.0.1-SNAPSHOT</version>

위의 구성을 pom.xml 파일에 복사한 후 이러한 pom.xml 파일의 내용을 가져옵니다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- 当前Maven项目使用的描述规范版本号 -->
    <modelVersion>4.0.0</modelVersion>

    <!-- 配置当前Maven项目的项目坐标 -->
    <!-- 项目组织唯一的标识符 -->
    <groupId>com.maven</groupId>
    <!-- 项目的唯一的标识符 -->
    <artifactId>MavenTest</artifactId>
    <!-- 项目的版本号 -->
    <version>0.0.1-SNAPSHOT</version>
    <!-- 当前项目的打包方式 -->
    <packaging>jar</packaging>

</project>

    지금까지 프로젝트 좌표 구성이 완료되었습니다.

프로젝트 버전 번호에 대한 참고 사항:

    Maven 프로젝트의 <version> 태그에 사용된 버전 번호는 디지털 버전 번호 0.0.1 외에도 버전 유형이 있습니다. SNAPSHOT이라는 단어는 스냅샷 버전을 의미합니다. 그렇다면 프로젝트의 버전 유형은 무엇입니까?
    1. 스냅샷: 스냅샷 버전, 즉 개발 버전 이 버전의 프로젝트는 개발 단계에 있어 기능이 불완전하고 오류가 많기 때문에 사용할 수 없습니다. Eclipse 및 IDEA는 Maven 생성 시 기본적으로 이 버전을 사용합니다. 프로젝트.
    2. 알파: 내부 테스트 버전 이 버전의 프로그램은 권장하지 않습니다. 이 버전의 프로그램은 개발자가 버그를 찾고 변경하기 위한 내부 테스트에 사용됩니다.
    3. 베타: 외부 테스트 버전으로 사용자 그룹을 위해 출시된 테스트 버전으로 사용할 수는 있지만 아직 불안정하고 버그가 많으므로 사용하지 않는 것이 좋습니다.
    4. 릴리스: 공식이 권장하는 릴리스 버전을 의미하며 보다 포괄적인 기능과 안정적인 작동을 제공하지만 일부 버그가 있을 수 있으며 정상적으로 사용할 수 있습니다.
    5. 안정 버전: 릴리스 버전을 기준으로 대부분의 버그를 제거하고 일부 기능을 최적화한 안정적인 버전 사용을 권장합니다.
    6. 현재: 최신 버전, 반드시 안정적인 버전은 아니지만 최신 기능이 포함된 버전 해당 릴리스 또는 안정적인 버전이 있는 경우 처음 두 개를 사용하는 것이 좋습니다.
    7. eval: 1개월 또는 고정 사용 기간이 있는 평가 버전.
    또한 pre, RC, GA 및 기타 버전이 있으며 여기에서 자세히 설명하지 않습니다.

3. pom.xml 파일에 jar 파일 종속성을 추가합니다.

    Maven 학습의 목적은 Maven이 프로젝트에 필요한 jar 파일을 자동으로 추가하고 관리하도록 하는 것입니다.

    현재 Maven 프로젝트의 모든 종속성은 <dependencies> 태그에 구성되며 각 종속성은 종속 jar의 좌표인 <dependency> 태그로 래핑됩니다.

    그리고 프로젝트에 필요한 jar 파일의 종속성 구성을 pom.xml 파일에 추가하는 방법을 소개하기 전에 여기서는 자세히 다루지 않겠습니다.

    현재 프로젝트의 테스트를 용이하게 하기 위해 pom.xml 파일에 junit-4.12 버전의 jar 파일 종속성을 추가합니다.

<!--
    所有jar文件依赖的声明都放在<dependencies>标签下的子标签<dependency>当中
    每一个依赖单独创建一个<dependency>子标签
-->
<dependencies>
    <!-- 对junit-4.12版本的jar文件依赖声明 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

위의 구성 콘텐츠를 pom.xml 파일에 추가한 후 pom.xml 파일의 보다 포괄적인 버전을 얻습니다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<!-- 当前Maven项目使用的描述规范版本号 -->
    <modelVersion>4.0.0</modelVersion>
	
	<!-- 配置当前Maven项目的项目坐标 -->
	<!-- 项目组织唯一的标识符 -->
	<groupId>com.maven</groupId>
	<!-- 项目的唯一的标识符 -->
    <artifactId>MavenTest</artifactId>
	<!-- 项目的版本号 -->
    <version>0.0.1-SNAPSHOT</version>
	<!-- 当前项目的打包方式 -->
    <packaging>jar</packaging>
	
	<!--
    所有jar文件依赖的声明都放在<dependencies>标签下的子标签<dependency>当中
    每一个依赖单独创建一个<dependency>子标签
	-->
	<dependencies>
		<!-- 对junit-4.12版本的jar文件依赖声明 -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

    지금까지 전체 Maven 프로젝트의 pom.xml 구성 파일이 완성되었으므로 Java 코드를 작성해 보겠습니다.

4.1.3 Maven 프로젝트에서 Java 코드 작성

    Maven 프로젝트는 Java 소스 코드와 테스트 코드를 엄격하게 구분합니다.이 코드는 서로 다른 위치에 저장되며 Maven은 컴파일하고 실행하는 과정에서 Java 소스 코드와 테스트 코드를 컴파일하고 컴파일합니다.실행도 상당히 다릅니다. .

1. Java 소스 코드 작성:

    Maven 프로젝트 아래의 모든 Java 소스 코드는 src/main/java 폴더에 저장되므로 이 폴더 아래에 다음과 같은 Java 소스 파일 및 코드를 생성합니다.

HelloMaven.java:

package com.maven;

public class HelloMaven {
	
	private String msg = "Hello Maven!";
	
	public void sayHi() {
		System.out.println(msg);
	}	
	
}

2. 테스트 코드 작성:

    Maven 프로젝트 아래의 모든 테스트 코드는 src/test/java 폴더에 저장되므로 이 폴더에 다음과 같은 테스트 클래스와 테스트 코드를 생성합니다.

HelloMavenTest.java:

package com.maven;

import org.junit.Test;

public class HelloMavenTest {
	
	@Test
	public void test1() {
		HelloMaven hm = new HelloMaven();
		hm.sayHi();
	}	

}

    지금까지 Maven 프로젝트의 Java 코드가 작성되었습니다.위 단계에서 우리가 집중해야 할 것은 Maven 프로젝트의 Java 소스 코드 및 테스트 코드의 저장 경로 위치입니다.

4.1.4 Maven 프로젝트 컴파일 및 실행

    Maven 프로젝트가 생성된 후 프로젝트를 수동으로 컴파일해야 합니다. 또한 Java 원본 코드에서 생성된 HelloMaven 형식을 테스트 코드에 사용하므로 다음과 같은 순서로 프로젝트를 컴파일해야 합니다. 1. 먼저
        src/main/java 폴더에 Java 원본 코드를 컴파일
        합니다. src/test/java 폴더 아래의 코드

    이 순서대로 컴파일해야만 테스트 코드가 정상적으로 실행될 수 있습니다.

1. Java 소스 코드를 컴파일합니다.

    먼저 Maven 프로젝트의 루트 디렉터리에 진입한 후 다음 명령을 통해 Maven 프로젝트의 소스 코드를 컴파일합니다.

mvn compile

    참고: Maven 프로젝트를 처음 컴파일하는 경우 Maven은 원격 중앙 웨어하우스에서 로컬 웨어하우스로 필요한 jar 파일을 다운로드합니다.

    미러를 사용하여 다운로드하도록 구성한 경우 다운로드 프로세스가 훨씬 빨라집니다(시연을 위해 로컬 웨어하우스에서 다운로드한 모든 jar 파일을 삭제했습니다...).

 프로젝트가 성공적으로 컴파일되면 다음과 같은 결과가 나타납니다.

    먼저 명령 콘솔에 다음 결과가 표시됩니다.

     둘째, src 폴더 아래에 현재 컴파일된 모든 Java 파일의 바이트 코드 파일 저장을 담당하는 target이라는 새 폴더가 나타납니다.

 2. 테스트 코드를 컴파일하고 실행합니다.

    동일한 명령이 Maven 프로젝트에서 테스트 코드를 컴파일하고 실행하는 데 사용됩니다.

mvn test

    즉, 위의 명령을 실행할 때 Maven은 다음 세 가지 작업을 동시에 수행합니다.
        1. 중앙 창고로 이동하여 pom에 선언된 jar 파일 종속성에 따라 로컬에 필요한 jar 파일을 다운로드합니다. xml 구성 파일 창고에 있습니다.
        2. 테스트 코드를 컴파일하고 해당 바이트코드 파일을 생성합니다.
        3. 테스트 클래스에서 테스트 메서드를 직접 실행하고 테스트 결과를 인쇄합니다.

jar 파일을 로컬 웨어하우스에 다운로드하는 과정:

 테스트 파일을 컴파일하고 테스트 메서드를 실행하여 실행 결과를 얻습니다.

 3. Maven 프로젝트를 정리합니다.

    컴파일 및 생성된 Java 소스 코드 및 테스트 코드의 바이트 코드 파일을 지워야 하는 경우 다음 명령을 사용할 수 있습니다.

mvn clean

Maven이 프로젝트를 청소하고 있습니다.

 정리 완료:

 이 명령을 실행한 후 Maven은 프로젝트 루트 디렉터리에서 대상 폴더를 자동으로 삭제합니다.

     지금까지 Maven 프로젝트를 수동으로 생성, 구성, 컴파일 및 실행하는 작업이 모두 끝났습니다.

4.2 Maven 웹 프로젝트 수동 빌드

    Maven 웹 프로젝트는 Maven Java 프로젝트보다 구조가 약간 더 많을 뿐이며 Maven 규칙에 따라 빌드할 수 있습니다.

4.2.1 웹 디렉토리 생성

    src/main 디렉토리 아래에 webapp 디렉토리를 생성합니다. webapp 디렉토리는 웹 프로젝트의 기본 디렉토리입니다.

    그 이후는 웹 프로젝트에 따라 운영하기 위한 것이므로 반복하지 않겠습니다. 

4.2.2 HelloServlet 생성

    src/main/java 디렉토리 아래에 com.maven.servlet 패키지를 만들고 그 아래에 HelloServlet 클래스를 정의합니다.

HelloServlet 클래스 코드는 다음과 같습니다.

package com.maven.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().write("Hello.................");
	}

}

4.2.3 구성 종속성 및 운영 환경(자세한 내용은 나중에 설명)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.newcapec</groupId>
  <artifactId>HelloMaven</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
  <build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
	
	<!-- 添加servlet-api,jsp-api -->
	<dependencies>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.0</version>
			<scope>provided</scope>
		</dependency>
		
	</dependencies>
  
</project>

4.2.4 테스트 실행    

    데이터에서 HelloMaven을 열고 테스트를 실행합니다.

    Maven 프로젝트 디렉터리(현재 디렉터리에는 pom.xml 파일이 있음)에 들어가 mvn tomcat:run 명령을 실행합니다.

    위의 프롬프트 정보에 따라 브라우저를 통해 http://localhost:8080/HelloMaven/HelloServlet을 방문하십시오.

4.2.5  Maven 웹 프로젝트 오류 처리

    질문 1: jar 패키지 충돌이 있을 수 있습니다.
        솔루션: jsp 및 서블릿의 종속성에 <scope>provided</scope>를 추가하십시오.

    질문 2: Maven에 내장된 Tomcat은 6.0이며 이 버전은 jdk1.8을 지원하지 않습니다.
        tomcat7 플러그인을 구성하고 maven 컴파일 환경을 1.8로 구성합니다.
        mvn tomcat7:run 명령을 실행하여 서비스를 시작합니다. tomcat:run을 계속 사용하다보면 Maven의 Tomcat6을 계속 쓰게 될 것이고 계속해서 실수를 하게 될 것입니다...

<plugins>
    <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
            <encoding>UTF-8</encoding>
        </configuration>
    </plugin>
</plugins>

4.3 명령어 테스트

cmd 명령줄을 열고 hello 프로젝트의 루트 디렉터리를 입력한 후 다음 명령을 실행하여 루트 디렉터리의 변경 사항을 확인합니다.

#编译:
mvn compile

#清空:
mvn clean

#测试:
mvn test

#打包:在打包之前先执行test命令,经过测试发现,并不会打包测试文件
mvn package

#把项目安装到本地仓库,在安装之前先执行package命令:
mvn install

다섯, Maven 창고 및 좌표

5.1 메이븐 저장소 개요

    Maven 웨어하우스 분류:
        로컬 웨어하우스: 로컬 호스트의 웨어하우스.
        원격 웨어하우스: 로컬에 플러그인 또는 jar 패키지가 필요한데 로컬 웨어하우스에 없는 경우 기본적으로 원격 웨어하우스로 이동하여 다운로드합니다. 원격 창고는 인터넷이나 근거리 통신망에 있을 수 있습니다.

    Maven의 작업은 웨어하우스에서 일부 jar 패키지를 다운로드해야 합니다.아래 그림과 같이 로컬 Maven 프로젝트는 원격 웨어하우스(인터넷상의 웨어하우스로 이해할 수 있음)에서 Maven 소프트웨어 및 스토어를 통해 jar 패키지를 다운로드합니다. 로컬 웨어하우스에 있습니다. 로컬 웨어하우스는 로컬 파일입니다. 폴더, jar 패키지가 두 번째로 필요할 때 로컬 웨어하우스가 이미 존재하고 로컬 웨어하우스는 캐시로 이해 로컬 웨어하우스를 사용하면 매번 원격 웨어하우스에서 다운로드할 필요가 없습니다.

다음 그림은 maven의 창고 유형을 설명합니다.

5.2 중앙 창고

    원래 로컬 웨어하우스가 비어 있으므로 Maven은 Maven 명령을 실행할 때 필요한 빌드를 다운로드하기 위해 사용 가능한 원격 웨어하우스를 하나 이상 알고 있어야 합니다.

    중앙 웨어하우스는 Maven의 기본 원격 웨어하우스로 전체 인터넷에 서비스를 제공합니다. Maven 팀 자체에서 관리하며 세계에서 가장 인기 있는 오픈 소스 프로젝트 구성 요소 대부분을 포함하는 매우 완전한 jar 패키지를 저장합니다.

    중앙 웨어하우스 주소는 https://repo.maven.apache.org/maven2입니다.

    Maven의 설치 파일은 기본적으로 중앙 웨어하우스 구성과 함께 제공되며 MAVEN_HOME/lib/maven-model-builder.jar, org\apache\maven\model\pom-4.0.0.xml에서 찾을 수 있습니다. 중앙 창고 주소로.

<repositories>
    <repository>
        <id>central</id>
        <name>Central Repository</name>
        <url>https://repo.maven.apache.org/maven2</url>
        <layout>default</layout>
        <snapshots>
        <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

5.3 개인 창고

    주로 팀 협업 및 개발을 위해 로컬 영역 네트워크에 설정된 웨어하우스인 특별한 종류의 원격 웨어하우스는 개인 서버라고도 하는 회사의 웨어하우스로 이해할 수 있습니다.

    Alibaba Cloud 미러를 구성하십시오.Alibaba Cloud 미러는 실제로 Ali의 개인 창고이며 모든 사람에게만 공개됩니다.

<mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>
</mirror>

개인 서버 사용의 이점:

    자신의 외부 네트워크 대역폭 절약: 개인 서버를 구축하면 조직 자체 비용을 줄일 수 있으며 외부 원격 창고에 대한 반복 요청이 많을수록 많은 대역폭을 소비합니다.개인 서버를 사용하여 외부 창고를 프록시한 후 외부 반복 구성 요소 다운로드, 즉 외부 네트워크 대역폭 압력을 제거할 수 있습니다.

    Maven 구축 가속화: 외부 웨어하우스를 지속적으로 요청하는 것은 확실히 시간이 많이 걸리는 일이지만 Maven의 일부 내부 메커니즘(예: 스냅샷 감지)은 빌드를 실행할 때 Maven이 원격 웨어하우스의 데이터를 지속적으로 확인해야 합니다. 따라서 많은 원격 창고가 구성되면 구축 속도가 크게 저하됩니다. 사설 서버를 사용하면 이 문제를 아주 잘 해결할 수 있습니다.

    타사 구성 요소 배포: 외부 원격 웨어하우스에서 특정 구성 요소를 다운로드할 수 없는 경우 어떻게 해야 합니까? 예를 들어, 조직 내에서 생성된 전용 구성 요소는 외부 웨어하우스에서 가져오면 안 되며, Oracle의 JDBC 드라이버는 저작권상의 이유로 외부 네트워크의 중앙 웨어하우스에 릴리스할 수 없습니다. 사설 서버가 설정되면 내부 Maven 프로젝트에서 사용할 수 있도록 이러한 구성 요소를 로컬 사설 서버에 배포할 수 있습니다.

    안정성 향상 및 제어 향상: Maven 빌드는 원격 웨어하우스에 의존하므로 인터넷이 불안정하면 Maven 빌드도 불안정해지거나 빌드에 실패합니다.
사설 서버를 사용한 후에는 사설 서버에 많은 구성 요소가 캐시되어 있기 때문에 일시적으로 인터넷 연결이 없어도 Maven이 정상적으로 실행될 수 있습니다. 또한 일부 개인 서버 소프트웨어(예: Nexus)는 권한 관리, RELEASE/SNAPSHOT 구별 등과 같은 많은 추가 기능을 제공하므로 관리자는 웨어하우스에서 고급 제어를 수행할 수 있습니다.

    중앙 창고의 부하 감소: 수백만 건의 요청과 수 테라바이트의 데이터 저장에는 상당한 재정 자원이 필요합니다. 사설 서버를 사용하면 중앙 창고에 대한 많은 반복 요청을 피할 수 있습니다.

5.4 현지 창고

    Maven은 컴파일 또는 테스트를 수행할 때 필요한 경우 항상 좌표를 기반으로 로컬 저장소의 종속성을 사용합니다. 기본적으로 Linux 또는 Windows에 관계없이 각 사용자는 자신의 사용자 디렉터리 아래에 .m2/respository/라는 리포지토리 디렉터리가 있습니다.

    중앙 창고 또는 개인 창고에서 jar 패키지 및 Maven 정보를 다운로드하거나 jar 패키지의 종속 창고를 직접 빌드하십시오.

    기본 위치: ~/.m2/repository

    로컬 웨어하우스 위치 수정: MAVE_HOME/conf/settings.xml 파일에서 로컬 웨어하우스 위치를 구성합니다.

<localRepository>D:\maven\repository</localRepository>

5.4 메이븐 좌표

    Maven 웨어하우스에는 통합 사양을 빌드하기 위해 고유하게 식별해야 하는 수많은 종속 jar 패키지가 있습니다. 통합 사양을 사용하면 Maven 리포지토리에서 필요한 종속성을 정확하게 찾을 수 있습니다.

<dependency>
    <!-- Maven依赖的坐标GAV -->
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
</dependency>

6. 이클립스에서 메이븐 사용하기

6.1 Maven 플러그인 설치

    Eclipse를 열고 도움말 -> 새 소프트웨어 설치 메뉴를 클릭한 다음 추가 버튼을 클릭합니다.
        이름: m2e 
        위치: http://download.eclipse.org/technology/m2e/releases

참고: 새 버전의 eclipse는 Maven을 직접 통합했기 때문에 m2eclipse 플러그인을 설치할 필요가 없습니다.

6.2 Eclipse에서 Maven 구성

    1. Eclipse를 열고 메뉴 Window -> Preferences를 클릭하고 Maven -> Installations를 찾아 기본 Maven을 수정하고 Add를 클릭하여 자신의 Maven을 추가합니다.

    참고: 내장 Maven 버전이 3.3 이상인 경우 이 단계를 생략하고 기본 버전을 사용할 수 있습니다. 물론 직접 설치한 Maven도 사용할 수 있다.

    2. 사용자 설정을 클릭하고 사용자 설정 파일과 로컬 리포지토리 경로를 다시 선택합니다.

    참고: 일반적으로 eclipse는 기본적으로 사용자 디렉토리 아래의 .m2 폴더 아래에 있는 settings/xml을 사용하고 settings.xml 파일의 구성 정보를 자동으로 인식합니다.

     3. jar 패키지의 소스 코드와 설명서를 구성하고 다운로드합니다(필요한 경우).
    
    참고: 다음 두 항목을 체크하면 의존성 다운로드 시 의존성에 해당하는 소스코드와 문서가 함께 다운로드 된다(개인적으로는 확인을 권장하지 않는다).

6.3 Eclipse에서 Maven 프로젝트 생성

6.3.1 메이븐 자바 프로젝트 생성

    1. 파일 -> 새로 만들기 -> 프로젝트를 클릭하고 Maven -> Maven 프로젝트를 찾습니다.

     2. 다음을 클릭하고 Maven 원형(프로토타입)을 선택하십시오.

     3. 카탈로그의 기본 선택은 모든 프로토타입을 의미하는 모든 카탈로그입니다. Catalog에서 Internal을 선택하여 내장된 Maven 유형을 표시합니다(공식 웹 사이트에서 제공).
    
        Maven Java 프로젝트인 경우 maven-archetype-quickstart를 선택합니다.
        Maven 웹 프로젝트인 경우 maven-archetype-webapp을 선택합니다.

     4. Maven 좌표를 입력합니다.
        그룹 ID: 회사 도메인 이름의 반전.
        아티팩트 ID: 프로젝트 이름.
        버전: 버전 번호.
        패키지: 필요에 따라 정의됩니다.

    5. Maven은 프로젝트에 필요한 종속 패키지를 자동으로 다운로드하고 완료 후 프로젝트 구조를 재구성합니다.

    참고: 기본적으로 eclipse에 의해 도입된 junit 종속성 버전은 3.8이며 우리는 이를 4.12로 정의합니다.

     6. 자동으로 생성된 App.java와 AppTest.java를 삭제하고 프로젝트 코드를 작성합니다.

프로젝트 소스 코드 Student.java:

package com.maven;

public class Student {
    private int id;
    private String name;
    private String sex;
    private double score;

    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }

    public Student(int id, String name, String sex, double score) {
        super();
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.score = score;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public double getScore() {
        return score;
    }
    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student [id=" + id + ", name=" + name + ", sex=" + sex + ", score=" + score + "]";
    }

}

프로젝트 테스트 코드 StudentTest.java:

package com.maven;

import org.junit.Test;

public class StudentTest {

	@Test
	public void test1() {
		Student stu = new Student(101, "张三", "男", 22);
		System.out.println(stu);
	}
}

    7. 코드를 작성한 후 Run As 프로젝트를 마우스 오른쪽 버튼으로 클릭하여 실행할 Maven 명령을 선택합니다.

 Maven 테스트 실행:

     참고: Eclipse에는 Maven 패키지 명령이 없는 것으로 나타났습니다. Maven 빌드를 통해 Eclipse에서 명령 구성 인터페이스를 호출하고 이 플러그인에서 실행 대상을 직접 구성할 수 있습니다.

6.3.2 Maven 웹 프로젝트 생성

    1. 이전 단계대로 Maven archetype(prototype) 선택 시 maven-archetype-webapp을 선택하고 Maven 웹 프로젝트를 생성한다.

 Maven 웹 프로젝트가 설정된 후 디렉터리 구조는 다음과 같습니다.

    Maven 프로젝트 빌드 후 프로젝트에 작은 빨간 십자 표시가 나타나는데, JSP 파일에서 오류 위치에 대한 프롬프트 정보를 관찰한 결과 실제로는 우리 프로젝트에서 Java EE의 해당 JAR 파일을 가져오지 않아서 발생한 것임을 알 수 있었습니다. .
    
    다음 작업에는 두 가지 옵션이 있습니다.
        1.1 빌드 경로를 통해 Java EE 관련 Jar 패키지를 수동으로 가져옵니다.
        1.2 Maven의 pom.xml 파일을 통해 이러한 Jar 패키지의 종속성을 구성합니다.

    우리는 Maven 프로젝트를 사용하고 있습니다! Jar 패키지를 수동으로 가져오는 것은 정말 부끄러운 일입니다! Maven을 사용하여 종속성을 구성하도록 적절하게 선택하십시오!

    2. src/main/java, src/test/java, src/test/resources 등의 소스 코드 디렉토리를 수동으로 생성해야 합니다.
    
    참고: src/main/webapp는 WebContent 디렉토리와 유사하게 웹이 저장되는 루트 디렉토리입니다. 단, WEB-INF 디렉토리에 있는 index.jsp와 web.xml은 버전이 너무 이르므로 삭제 후 재구축해야 한다.

     3. Maven의 pom.xml 파일을 통해 이러한 Jar 패키지의 종속성을 구성합니다.
        열기: https://mvnrepository.com, javaee 키워드 검색, 가장 많이 사용되는 옵션 선택:

     다음으로 Java 8 버전을 기반으로 Java EE 클래스 라이브러리를 선택합니다.

     종속성 선언 코드를 프로젝트의 pom.xml 파일에 복사합니다.

또는 개별적으로 구성:

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

<!-- servlet -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
</dependency>

<!-- jstl -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

로컬 Tomcat은 Maven 웹 프로젝트를 배포합니다.

     https://www.cnblogs.com/noyitela/p/10386455.html

Maven 웹 프로젝트를 배포하기 위한 Maven 명령:

    pom.xml에 tomcat7-maven-plugin 플러그인을 추가합니다.
    
    참고: 버전이 tomcat7-maven-plugin 2.0인 경우 jdk 1.8을 지원하지 않으므로 tomcat7-maven-plugin 2.2로 교체하세요.

<build>
    <finalName>maven-web-eclipse</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
        </plugin>
    </plugins>
</build>

    이렇게 하면 구성이 완료됩니다. 목표를 tomcat7:run으로 변경해야 합니다.

6.4 Maven 명령 오류 실행에 대한 솔루션

Maven 명령을 실행하고 오류를 보고합니다.

    오류 원인: Eclipse의 실행 환경은 기본적으로 jre이며 Maven의 실행 환경은 jre 대신 JDK가 필요합니다.

    1. 창 -> 기본 설정 -> Java -> 설치된 JRES -> 추가 -> 표준 VM -> 설치한 JDK를 선택합니다.

     2. 현재 프로젝트 Properties -> Java Build Path -> Libraries -> Add Library -> JRE System Library -> Workspace default JRE를 체크한다.

     기타 솔루션: https://blog.csdn.net/weixin_44405634/article/details/100837978

7. IDEA에서 Maven 사용

7.1 IDEA에는 자체 Maven 플러그인이 있으므로 설치할 필요가 없습니다.

7.2 IDEA에서 Maven 구성

    1. IDEA를 열고 File -> Settings 메뉴를 클릭하고 Build, Execution, Deployment -> Build Tools -> Maven을 찾아 기본 Maven을 수정합니다.

    참고: 내장 Maven 버전이 3.3 이상인 경우 이 단계를 생략하고 기본 버전을 사용할 수 있습니다. 물론 직접 설치한 Maven도 사용할 수 있다.

    2. Build, Execution, Deployment -> Build Tools -> Maven -> Importing에서 자동으로 다운로드할 jar 패키지의 소스 코드, 문서 및 주석을 구성합니다.

    참고: 다음 두 항목을 체크하면 의존성 다운로드 시 의존성에 해당하는 소스코드와 문서가 함께 다운로드 된다(개인적으로는 확인을 권장하지 않는다).

7.3 IDEA에서 메이븐 프로젝트 만들기

7.3.1 메이븐 자바 프로젝트 생성

    1. 파일 -> 새로 만들기 -> 프로젝트를 클릭하고 Maven을 찾은 다음 원형에서 생성을 선택하고 필요한 원형을 선택하면 빠른 시작에서 Java 프로젝트를 빌드하고 webapp에서 JavaWeb 프로젝트를 빌드합니다.

     2. maven 좌표, 그룹 ID: 회사명, artifactID: 프로젝트 이름, 버전: 버전 번호를 입력하고 완료될 때까지 다음 단계를 진행합니다.

     3. Maven은 프로젝트에 필요한 종속 패키지를 자동으로 다운로드하고 완료 후 프로젝트 구조를 재구성합니다.

    4. Maven 계약에 따라 프로젝트 구조를 완성합니다.
        기본 디렉터리 아래에 리소스 폴더를 만들고 디렉터리를 "리소스 루트"로 표시합니다.
        테스트 디렉터리 아래에 리소스 폴더를 만들고 디렉터리를 "테스트 리소스 루트"로 표시합니다.

    참고: 새 버전의 IDEA에서는 리소스를 만들 때 해당 프롬프트가 표시됩니다.

    5. 자동으로 생성된 App.java와 AppTest.java를 삭제하고 프로젝트 코드를 작성합니다.

    6. 코드 작성 후 IDEA 우측의 Maven Projects 창을 접고 Lifecycle 아래의 command를 선택하고 Run 버튼(명령어 더블 클릭)을 클릭하여 실행한다.

    참고: 오른쪽에 Maven Projects 접는 창이 없으면 보기 -> 모양 -> 도구 창 표시줄을 선택하십시오.

7.3.2 Maven의 기본 JDK 컴파일 환경 수정

    Maven에서 생성한 프로젝트의 기본 JDK 컴파일 환경은 1.5이며, pom에서 Maven 컴파일 플러그인을 사용하거나 전역 구성을 통해 프로젝트의 JDK 버전을 변경할 수 있습니다. 버전을 지정하지 않으면 버전 불일치 문제가 발생하기 쉬워 컴파일 실패 문제가 발생할 수 있습니다.

방법 1: 프로젝트 수준 pom.xml 수정

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

    위의 구성은 현재 프로젝트(모듈)에만 적용됩니다.

방법 2: maven의 settings.xml 파일 수정(글로벌)

<profile>    
    <id>jdk-1.8</id>    
    <activation>    
        <activeByDefault>true</activeByDefault>    
        <jdk>1.8</jdk>    
    </activation>    
    <properties>    
        <maven.compiler.source>1.8</maven.compiler.source>    
        <maven.compiler.target>1.8</maven.compiler.target>    
        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>    
    </properties>    
</profile> 

    위 설정은 전역 수준, 즉 현재 maven 환경을 기반으로 생성된 모든 프로젝트(모듈)가 적용됩니다.

7.3.3 Maven 웹 프로젝트 생성

    1. 이전 단계에 따라 Maven 웹 프로젝트를 생성합니다.

 Maven 웹 프로젝트 생성 후 디렉터리 구조는 다음과 같습니다.

    2. src/main/java, src/mian/resources, src/test/java, src/test/resources 등과 같은 소스 코드 디렉토리를 수동으로 생성하고 먼저 디렉토리(일반 디렉토리)를 생성합니다.

    참고: 새 버전의 IDEA가 지정된 이름으로 디렉토리를 생성하면 바로 프롬프트가 표시되므로 사용이 매우 쉽습니다.

     3. 디렉토리를 마우스 오른쪽 버튼으로 클릭하고 Mark Directory as를 선택하여 디렉토리를 해당 소스 코드 디렉토리로 변환합니다. Sources Root는 src/main/java 디렉토리에 해당하고 Test Sources Root는 src/test/java 디렉토리에 해당하고 Resources Root는 src/main/resources 디렉토리에 해당하며 Test Resources Root는 src/test/resources에 해당합니다. 예배 규칙서

     4. src/main/webapp는 WebContent 디렉토리와 유사하게 웹을 저장하기 위한 루트 디렉토리입니다. 단, WEB-INF 디렉토리에 있는 index.jsp와 web.xml은 버전이 너무 이르므로 삭제 후 재구축해야 한다.

jsp 템플릿:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>Hello Maven!</h1>
</body>
</html>

web.xml 템플릿:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>

    5. 배포 및 테스트합니다.
        로컬 Tomcat은 Maven 웹 프로젝트를 배포합니다.
        Maven 웹 프로젝트를 배포하기 위한 Maven 명령.

8. Maven 종속성 범위

    이전에 생성한 Maven 웹 프로젝트를 기반으로 웹 개발에서 일반적으로 사용되는 의존성을 추가합니다.
        1. mysql 드라이버
        2. 서블릿
        3. jsp
        4. jstl
        5. gson 등

디렉토리 구조는 다음과 같습니다.

학생 클래스 코드는 다음과 같습니다.

package com.maven.entity;

/**
 * 学生实体类
 */
public class Student {
    private Integer id;
    private String name;
    private String gender;
    private double score;

    public Student(){}

    public Student(Integer id, String name, String gender, double score) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.score = score;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", score=" + score +
                '}';
    }
}

GsonServlet 클래스 코드는 다음과 같습니다.

package com.maven.servlet;

import com.google.gson.Gson;
import com.maven.entity.Student;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 测试Gson的Servlet
 */
@WebServlet("/gsonServlet")
public class GsonServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建Gson对象(如果没有引入gson的jar包或依赖,肯定会报错)
        Gson gson = new Gson();

        //创建集合来存储学生对象
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student(101,"Tom","boy",89));
        studentList.add(new Student(102,"Jerry","boy",56.2));
        studentList.add(new Student(103,"HanMeiMei","girl",44));
        studentList.add(new Student(104,"LiLei","boy",100));

        //把studentList转换为json字符串响应出去
        String json = gson.toJson(studentList);
        resp.getWriter().write(json);
    }
}

StudentTest 클래스 코드는 다음과 같습니다.

package com.maven.entity;

import org.junit.Test;

/**
 * 学生类单元测试
 */
public class StudentTest {
    @Test
    public void test1() {
        Student student = new Student(101, "张三", "男", 12);
        System.out.println(student);
    }
}

pom.xml 파일은 다음에 따라 다릅니다.

<dependencies>
    <!-- 引入junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

    <!-- 引入mysql驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.49</version>
    </dependency>

    <!-- 引入jsp -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1</version>
        <scope>provided</scope>
    </dependency>

    <!-- 引入servlet -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
        <scope>provided</scope>
    </dependency>

    <!-- 引入jstl -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <!-- 引入gson -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.5</version>
    </dependency>
</dependencies>

    엔터티 클래스, 서블릿 및 테스트 클래스 코드는 설명할 것이 없지만 종속성을 도입할 때 일부 종속성에는 범위 태그가 있고 일부는 그렇지 않음을 알 수 있습니다.

    <scope> 태그는 종속성 요소의 사용 범위를 제어하기 위한 것입니다. 평신도의 용어로 Jar 패키지가 로드되고 사용되는 범위를 제어하는 ​​것입니다.

8.1 종속성 범위 개요

세 가지 클래스 경로에 대한 이해:

    1. 컴파일 클래스 경로: 대상 디렉토리 아래의 클래스 디렉토리에 해당하며 src/main 디렉토리 아래의 컴파일된 내용만 저장됩니다.
        src/main/java: 컴파일 후 생성된 바이트코드 파일은 클래스 디렉토리(패키지 구조 포함)에 배치됩니다.
        src/main/resources: 컴파일되지 않고 클래스 디렉토리에 직접 배치됩니다.

    2. 테스트 클래스 경로: 대상 디렉토리 아래의 test-classes 디렉토리에 해당하며 src/test 디렉토리 아래의 컴파일된 콘텐츠만 저장됩니다.
        src/test/java: 컴파일 후 생성된 바이트코드 파일은 test-classes 디렉토리(패키지 구조 포함)에 배치됩니다.
        src/test/resources: 컴파일되지 않고 test-classes 디렉토리에 직접 배치됩니다.
    
    3. 실행 클래스 경로: 프로젝트 실행 시 바이트코드 파일 저장 디렉터리입니다. 예를 들어 웹 프로젝트 /WEB-INF/classes 디렉토리.
    
    참고:
        1. 리소스 디렉터리 아래에는 패키지를 생성할 수 없으며 폴더만 생성할 수 있으며 com.maven.servlet 폴더를 생성하면 com.maven.servlet이라는 폴더만 생성됩니다.
        2. 리소스 디렉토리 아래에는 메인 디렉토리와 동일한 디렉토리 구조를 정의할 수 있다.
        3. 리소스 디렉토리에는 메인 디렉토리와 동일한 파일을 정의할 수 없습니다.
        4. 자원 디렉토리 아래의 Java 소스 코드는 컴파일되지 않으며 Java 소스 코드를 자원 디렉토리에 두지 않는 것이 좋습니다.

     Maven 프로젝트의 다른 단계에서 클래스 경로에 도입된 종속성은 서로 다릅니다.
        컴파일할 때 Maven은 컴파일 관련 종속성을 클래스 경로에 도입합니다.
        테스트할 때 Maven은 클래스 경로에 테스트 관련 종속성을 도입합니다.
        런타임에 Maven은 클래스 경로에 런타임 관련 종속성을 도입합니다.
    
    종속성의 범위는 클래스 경로 컴파일, 클래스 경로 테스트 및 클래스 경로 실행에 의존하는 세 가지 클래스 경로의 사용을 제어하는 ​​데 사용됩니다.

8.2 범위의 가치에 따라

    Maven의 수명 주기에는 이러한 프로세스의 컴파일, 테스트 및 실행이 포함되므로 junit과 같은 일부 종속성은 테스트용으로만 사용되며 일부 종속성은 컴파일에 사용되지 않고 실행 중일 때만 사용할 수 있습니다. 예를 들어 다음의 드라이버 패키지는 다음과 같습니다. mysql은 컴파일 중에 사용됩니다.(JDBC 인터페이스는 컴파일 타임에 사용됨) 런타임에 컴파일 타임에 사용되는 일부 종속성이 있지만 일부 컨테이너는 이미 일부 컨테이너에 포함되어 있으므로 런타임에 제공할 필요가 없습니다. servlet-api와 같이 tomcat에 이미 제공되어 있으므로 컴파일 시간에 제공하기만 하면 됩니다. 정리하자면, POM 4에서는 <scope>가 <dependency>에도 도입되는데, 주로 의존성의 배포를 관리한다. 크게 컴파일, 제공, 런타임, 테스트, 시스템 등이 있습니다.
        
    컴파일: 종속성 범위를 컴파일합니다.
    테스트: 테스트 종속성 범위입니다.
    제공됨: 종속성 범위가 제공됩니다.
    런타임: 런타임 종속성 범위입니다. (인터페이스와 구현의 분리)
    시스템: 시스템 종속 범위. 로컬이 아닌 창고에서 가져와서 시스템의 특정 경로에 저장되는 항아리. (일반적으로 사용하지 않음)
    import: 종속 범위를 가져옵니다. dependencyManagement를 사용하는 경우 종속성 구성을 가져올 수 있습니다. (추후 설명)

종속성 범위 유효한 컴파일 클래스 경로 테스트 클래스 경로가 유효합니다. 실행 클래스 경로 작동
엮다 와이 와이 와이 스프링크로
시험 N 와이 N 정닛
제공된 와이 와이 N 서블릿 API
실행 시간 N 와이 와이 jdbc

컴파일(기본값)

    의미: compile이 기본값이며 범위 값이 지정되지 않은 경우 이 요소의 기본값은 compile입니다. 종속 프로젝트는 현재 프로젝트의 컴파일, 테스트, 패키징, 실행 및 기타 단계에 참여해야 합니다. 종속 프로젝트는 일반적으로 패키징할 때 포함됩니다.

    데모: gson의 범위 값은 기본 컴파일이며 테스트로 변경하면 컴파일 중에 gson을 찾을 수 없으며 오류가 보고됩니다.

제공된

    의미: 종속 프로젝트는 이론적으로 컴파일, 테스트 및 운영 단계에 참여할 수 있으며 이는 컴파일과 동일하지만 제외 작업은 리패키징 단계에서 수행됩니다. 

    적용 가능한 시나리오: 예를 들어 웹 애플리케이션을 개발하는 경우 컴파일 시간에 servlet-api.jar에 의존해야 하지만 런타임에는 jar 패키지가 필요하지 않습니다. 이 jar 패키지는 애플리케이션에서 제공했기 때문입니다. 서버, 이때 범위 수정을 위해 제공되는 사용이 필요합니다.

    데모: gson의 범위 값을 제공된 것으로 변경합니다. 컴파일 및 테스트에는 문제가 없지만 응용 프로그램 서버에서 gson의 jar 패키지를 제공하지 않기 때문에 실행 시 오류가 보고됩니다.

실행 시간

    의미: 종속 프로젝트가 프로젝트 컴파일에 참여할 필요가 없지만 프로젝트의 테스트 및 실행에 참여할 것임을 나타냅니다. 컴파일과 비교하여 종속 프로젝트는 프로젝트 컴파일에 참여할 필요가 없습니다.

    적용 가능한 시나리오: 예를 들어 컴파일할 때는 JDBC API jar 패키지가 필요하지 않지만 실행할 때는 JDBC 드라이버 패키지만 필요합니다.

시험

    의미: 종속 프로젝트가 테스트 코드의 컴파일 및 실행을 포함하여 테스트 관련 작업에만 참여함을 나타냅니다.

    적용 가능한 시나리오: 예: Junit 테스트.

    데모: src/main/java에서 단위 테스트를 사용할 수 없습니다.

체계

    의미: system 요소는 제공된 요소와 유사하나 종속 항목은 maven 창고에서 검색하지 않고 로컬 시스템에서 가져오며, systemPath 요소는 로컬 시스템에서 jar 파일의 경로를 지정하는 데 사용됩니다. . 예를 들어:

<dependency>
    <groupId>org.open</groupId>
    <artifactId>open-core</artifactId>
    <version>1.5</version>
    <scope>system</scope>
    <systemPath>${basedir}/WebContent/WEB-INF/lib/open-core.jar</systemPath>
</dependency>

수입 (이해)

    <dependencyManagement>에서만 사용되며 이는 예를 들어 다른 pom에서 종속성 구성을 가져오는 것을 의미합니다(B 프로젝트는 A 프로젝트에서 패키지 구성을 가져옵니다).

    아마도 SpringBoot 애플리케이션을 수행할 때 다음 코드가 있을 것입니다.

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

    상위 모듈을 상속한 다음 해당 종속성을 도입합니다.

    상속을 원하지 않거나 둘 이상을 상속하고 싶은 경우 어떻게 해야 합니까? 우리는 Maven의 상속이 Java의 상속과 같이 다중 상속을 달성할 수 없다는 것을 알고 있습니다.10, 20 또는 그 이상의 모듈이 동일한 모듈에서 상속되면 이전 사례에 따르면 이 상위 모듈의 종속성 관리에는 많은 의존이 포함됩니다. 보다 명확한 관리를 위해 이러한 종속성을 분류하려는 경우 불가능하며 가져오기 범위 종속성이 이 문제를 해결할 수 있습니다. 종속성을 관리하는 데 특별히 사용되는 별도의 pom에 종속성 관리를 넣은 다음 종속성을 사용해야 하는 모듈에서 범위 종속성 가져오기를 통해 종속성 관리를 가져올 수 있습니다. 예를 들어 종속성 관리를 위해 다음과 같은 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>

참고: 가져오기 범위는 종속성 관리에서만 사용할 수 있습니다.

    이러한 방식으로 상위 모듈의 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의 모듈을 상속할 필요가 없지만 자신의 프로젝트의 모듈을 상속할 수 있습니다.

9. Maven 의존성 전달

9.1 종속성 이전

모두가 문제를 이해해야 합니다: Maven 웨어하우스의 모든 jar는 실제로 본질적으로 Java 프로젝트이지만 단지 jar 패키지로 패키징되어 Maven 웨어하우스에 배치됩니다. 일부 타사 jar 패키지.

우리가 특정 jar 패키지를 도입할 때 이러한 jar 패키지가 종속된 jar 패키지도 도입되며, 이는 종속성 이전입니다.

    예를 들어 Commons-logging 프로젝트가 있고 Spring-core 프로젝트는 Commons-logging에 의존하고 프로젝트 사용자 서비스는 Spring-core에 의존합니다. 그러면 사용자 서비스도 Commons-logging에 의존한다고 말할 수 있습니다. 즉, 의존관계는 user-service->Spring-core->Commons-logging이다.

    user-service 프로젝트를 실행하면 자동으로 Spring-core 및 Commons-logging을 다운로드하여 user-service 프로젝트의 jar 패키지 폴더로 가져오는데, 이는 종속성의 전이성입니다.

종속성의 전체 구조:

<dependencies>
    <dependency>
        <groupId>组织/父项目名称</groupId>
        <artifactId>项目名称</artifactId>
        <version>项目版本号</version>
        <type>依赖的类型,对应项目的packaging,默认是jar</type>
        <scope>依赖范围</scope>
        <systemPath>配合 scope=system 时使用</systemPath>
        <optional>标记是否为可选依赖</optional>
        <exclusions>
            <!-- 用来排除传递性依赖 -->
            <exclusion>
                <groupId>组织/父项目名称</groupId>
        		<artifactId>项目名称</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

    <optional>true</optional>로 설정하면 종속성이 선택적이며 종속성에 의해 전달되지 않음을 의미합니다.

확인 예:

    종속성 스프링 코어를 소개합니다.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>

결과는 다음과 같습니다.

    주의 깊게 관찰한 결과 현재 "의존성"을 포함하는 더 많은 commons-logging:commons-logging:1.2가 있음을 발견했습니다.

    A jar 패키지가 B jar 패키지의 클래스를 사용해야 하는 경우 A가 B에 종속되어 있다고 말합니다. 현재 프로젝트는 좌표에 따라 종속된 jar 패키지를 찾기 위해 로컬 창고로 이동합니다.

    Maven 창고를 통해 우리는 spring-core가 컴파일할 때 5개의 jar에 의존하지만 선택적 태그가 구성되어 있기 때문에 하나만 의존성으로 전달된다는 것을 알 수 있습니다.

    참고: 선택적 태그는 자신의 프로젝트에서만 설정할 수 있으며 전달되지 않습니다(프로젝트를 jar 패키지로 패키징하면 프로젝트의 일부 종속성이 전달되지 않음). 종속성을 사용하지 않으려는 경우 다른 프로젝트에서 전달한 경우 종속 전이 제외를 사용할 수 있습니다.

9.2 전이 종속성에서 제외

    때로는 프로그램이 올바른지 확인하기 위해 반복될 수 있는 간접 종속성을 제외할 수 있습니다.

    종속성 전송 제외 제외에는 두 가지 유형이 있습니다.
        1. 구성 파일을 통해 종속성을 제외합니다.
        2. Maven은 중복 종속성을 자동으로 제외합니다.

 예: C -> B -> A, C를 실행하고 싶지 않을 때 A를 다운로드하지 않으려면 <exclusions> 태그를 사용할 수 있습니다.

<dependencies>
    <dependency>
        <groupId>B</groupId>
        <artifactId>B</artifactId>
        <version>0.0.1</version>
        <exclusions>
            <exclusion>
                <!--被排除的依赖包坐标-->
                <groupId>A</groupId>
                <artifactId>A</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

    일반적으로 우리는 특별한 상황이 아닌 한 종속성 제외를 직접 작성하지 않습니다.

    junit이 의존하는 hamcrest-core:1.3에 버전 문제가 있고 junit이 의존하는 hamcrest-core:1.3을 원하지 않는 경우 제외를 통해 제외할 수 있습니다.

<!-- 引入junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency></dependency>참고: 원래 종속성을 내보낸 원래 패키지와 동일한 범위에 있어야 합니다 .

    hamcrest-core 제외에 의존한 후 junit에 문제가 있을 것이므로 버전 문제가 없는 hamcrest-core를 찾아서 도입해야 합니다.

<!-- 引入hamcrest-core -->
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-core</artifactId>
    <version>2.2</version>
</dependency>

제외에 의존하는 시나리오:

    1. 프로젝트 A는 프로젝트 B에 의존하지만 프로젝트 A가 프로젝트 B에 완전히 의존하지 않는 경우, 즉 프로젝트 A가 프로젝트 B의 기능 중 일부만 사용하고 이 부분의 프로젝트 기능 실현이 발생합니다. B는 프로젝트 C에 의존할 필요가 없습니다. 이때 프로젝트 A는 프로젝트 C에 대한 의존성을 배제해야 합니다.

    2. 버전 불일치: 전달된 jar 패키지와 실제 사용되는 jar 간에 버전 불일치가 있어 프로젝트가 비정상적으로 실행됩니다.

    3. 공용 모듈 캡슐화: 특정 jar에 API를 사용하고, 이 jar에 불필요한 전이 종속성이 있는 경우 종속성을 제외하여 전달할 수 있습니다.

9.3 종속성 충돌 및 해결

    종속성 충돌: 프로젝트 A는 다른 종속성 전달 경로를 통해 X에 종속됩니다. 다른 경로에 전달된 X의 버전이 다른 경우 A는 어떤 X 패키지 버전을 가져와야 합니까?

    종속된 콘텐츠의 버전이 여러 개 있으므로 특정 POM이 여러 버전에 종속되어 있는 경우 이를 종속성 충돌이라고 합니다.

    종속성 충돌은 두 가지 원칙을 따릅니다.
        1. 단락 우선 순위(종속 콘텐츠, 전송 수가 적을수록 우선 순위가 높음).
        2. 먼저 선언하는 것이 우선합니다(POM.xml에서는 종속 콘텐츠 선언 종속성이 먼저 오는 것이 우선합니다.

확인 예:

    다음 종속성을 소개합니다.

<!-- spring核心包 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- spring beans包 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>
<!-- spring环境包 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>

    우리는 spring-core를 도입했지만 컨텍스트의 bean, context 및 aop는 모두 spring-core에 의존한다는 것을 알게 될 것입니다. 그렇다면 여러 병이 프로젝트에 도입됩니까? 

    대답은 부정적입니다. 실제로 Maven은 스프링 코어만 도입합니다.

 갈등 해결:

    1. 종속 경로의 길이가 다른 경우 최단 경로 원칙이 채택됩니다.
        A—>B—>C—>D—>E—>X(버전 0.0.2)
        A—>F—>X(버전 0.0.1)
        그런 다음 A는 X(버전 0.0.1)에 의존합니다.

    2. 동일한 종속성 경로 길이의 경우 첫 번째 선언 원칙이 채택됩니다.
        A—>E—>X(버전 0.0.1)
        A—>F—>X(버전 0.0.2)
        는 <종속성 > 프로젝트 A의 </dependencies>에서 E와 F 중 어느 것이 먼저 선언되는지, A는 어느 경로의 X에 의존합니다.

10. 메이븐 라이프 사이클

Maven의 수명 주기는 모든 구성 프로세스를 추상화하고 통합하는 것입니다. 여기에는 프로젝트의 청소, 초기화, 컴파일, 테스트, 패키징, 통합 테스트, 검증, 배포 및 사이트 생성과 같은 거의 모든 구성 단계가 포함됩니다.

Maven의 라이프 사이클은 추상적입니다. 즉, 라이프 사이클은 실제 작업을 수행하지 않으며 실제 작업은 플러그인에 의해 완료됩니다. 이는 디자인 패턴의 템플릿 방법과 유사합니다.

10.1 세 가지 수명 주기

    Maven에는 clean, default 및 site의 세 가지 독립 라이프 사이클 세트가 있습니다.
        1. Clean: Clean Lifecycle은 실제 빌드 전에 일부 정리 작업을 수행합니다.

        2. default: Default Lifecycle은 컴파일, 테스트, 패키징, 배포 등과 같은 핵심 부분을 빌드합니다.

        3. 사이트: 사이트 라이프사이클은 프로젝트 보고서, 사이트 및 릴리스 사이트를 생성합니다.

    각 수명 주기에는 몇 가지 단계가 포함되며 이러한 단계는 순차적이며 이후 단계는 이전 단계에 따라 달라지며 사용자와 Maven 간의 가장 직접적인 상호 작용을 이러한 수명 주기 단계라고 합니다.

    수명 주기 단계의 앞 뒤 종속성에 비해 세 가지 수명 주기 자체는 서로 독립적이며 사용자는 클린 수명 주기의 특정 단계만 호출하거나 기본 수명 주기의 특정 단계만 호출할 수 있으며 영향을 주지 않습니다. 다른 라이프 사이클 사이클은 영향을 미칩니다.

10.2 클린 라이프 사이클

    다음 단계를 포함하는 세척 수명 주기:
        1. 사전 세척: 세척 전에 완료해야 하는 일부 작업을 수행합니다.

        2. clean: 이전 빌드에서 생성된 모든 파일을 제거합니다.

        3. 청소 후: 청소 후 즉시 완료해야 하는 일부 작업을 수행합니다.

    mvn clean의 clean은 위의 clean이다.생명주기에서 특정 단계가 실행되면 이전 단계가 모두 실행된다.즉, mvn clean이 실행되면 다음 두 가지 생명주기 단계가 실행된다. :
        pre -clean, clean
        
    mvn post-clean을 실행하면 다음 세 가지 수명 주기 단계를 실행합니다:
        pre-clean, clean, post-clean
        
    이것은 명령의 입력을 크게 단순화할 수 있는 Maven의 매우 중요한 규칙입니다. 선.

10.3 기본 수명 주기

이것은 애플리케이션을 빌드하는 데 사용되는 Maven의 주요 수명 주기이며 다음과 같은 23단계로 구성됩니다.

수명 주기 단계 설명하다
확인하다 (검증하다) 프로젝트가 정확하고 프로젝트의 빌드 프로세스를 완료하는 데 필요한 모든 정보가 있는지 확인하십시오.
초기화하다 (초기화하다) 속성 값 설정과 같은 빌드 상태를 초기화합니다.
generate-sources(소스 코드 생성) 컴파일 단계에 포함된 모든 소스 코드를 생성합니다.
프로세스 소스(프로세스 소스 코드) 예를 들어 소스 코드를 처리하여 임의의 값을 필터링합니다.
generate-resources(리소스 파일 생성) 프로젝트 번들에 포함될 리소스 파일을 생성합니다.
process-resources(프로세스 리소스 파일) 패키징 단계에 가장 잘 준비된 대상 디렉터리에 리소스를 복사하고 처리합니다.
컴파일(컴파일) 프로젝트의 소스 코드를 컴파일합니다.
프로세스 클래스(클래스 파일 처리) Java 클래스 파일의 바이트 코드 개선 및 최적화와 같이 컴파일로 생성된 파일을 처리합니다.
generate-test-sources(테스트 소스 코드 생성) 컴파일 단계에 포함된 모든 테스트 소스 코드를 생성합니다.
process-test-sources(프로세스 테스트 소스) 예를 들어 테스트 소스 코드를 처리하여 임의 값을 필터링합니다.
generate-test-resources(테스트 리소스 파일 생성) 테스트용 리소스 파일을 만듭니다.
process-test-resources(프로세스 테스트 리소스 파일) 테스트 리소스를 대상 디렉터리에 복사하고 처리합니다.
test-compile (테스트 소스 코드 컴파일) 테스트 소스 코드를 테스트 대상 디렉토리로 컴파일합니다.
process-test-classes(프로세스 테스트 클래스 파일) 테스트 소스 코드를 컴파일하여 생성된 파일을 처리합니다.
테스트(테스트) 적절한 단위 테스트 프레임워크를 사용하여 테스트를 실행합니다(Juint는 그 중 하나입니다).
준비-패키지(패키지 준비) 실제 포장하기 전에 필요한 작업을 수행하여 포장을 준비하십시오.
패키지 컴파일된 코드를 JAR, WAR 또는 EAR 파일과 같은 배포 가능한 형식 파일로 패키징합니다.
사전 통합 테스트(통합 테스트 전) 통합 테스트를 실행하기 전에 필요한 조치를 수행하십시오. 예를 들어 필요한 환경을 구축합니다.
통합 테스트(통합 테스트) 통합 테스트를 실행할 수 있는 환경으로 프로젝트를 처리하고 배포합니다.
post-integration-test(통합 테스트 후) 통합 테스트 실행이 완료된 후 필요한 조치를 수행하십시오. 예를 들어 통합 테스트 환경을 정리합니다.
확인하다 (확인하다) 임의 검사를 실행하여 프로젝트 패키지가 유효하고 품질 표준을 충족하는지 확인합니다.
설치하다 프로젝트 패키지를 다른 로컬 프로젝트의 종속성으로 사용할 수 있도록 프로젝트 패키지를 로컬 리포지토리에 설치합니다.
전개하다 최종 프로젝트 패키지를 원격 저장소에 복사하여 다른 개발자 및 프로젝트와 공유합니다.

중요한 단계는 다음과 같습니다.

단계 다루다 설명하다
검증 검증 검증 프로젝트 프로젝트가 올바른지, pom.xml 파일 트리의 유효성 검사를 포함하여 필요한 모든 관련 리소스를 사용할 수 있는지 확인합니다.
컴파일 컴파일 실행 컴파일 소스 코드 컴파일은 이 단계에서 수행됩니다.
테스트 테스트 시험 JUnit과 같은 적절한 단위 테스트 프레임워크를 사용하여 테스트를 실행합니다. 이러한 테스트에는 패키징 및 배포가 필요하지 않습니다.
포장 패키지 언급된 패키지 pom.xml에 정의된 대로 JAR/WAR 패키지를 만듭니다.
확인 확인 조사하다 패키지가 유효하고 품질 표준을 충족하는지 확인하기 위해 모든 검사가 실행됩니다.
설치 설치 설치하다 다른 프로젝트에서 사용할 수 있도록 패키지된 프로젝트를 로컬 리포지토리에 설치합니다.
배포하다 전개하다 최종 프로젝트 패키지를 원격 웨어하우스에 복사하여 다른 개발자 및 프로젝트와 공유합니다.

    모든 단계를 실행할 때 이전의 모든 단계가 실행되므로 mvn install을 실행할 때 코드가 컴파일, 테스트 및 패키징됩니다. 또한 Maven의 플러그인 메커니즘은 Maven의 라이프 사이클에 전적으로 의존하므로 라이프 사이클을 이해하는 것이 매우 중요합니다.

실험:

    Maven Java 프로젝트를 jar 패키지로 패키징하고 다른 Maven 프로젝트로 가져옵니다.

    1. Maven Java 프로젝트에서 설치를 실행하면 Maven Java가 jar 패키지로 패키징되어 로컬 웨어하우스에 설치됩니다.

    2. 프로젝트 좌표를 통해 로컬 창고에 설치된 jar를 가져옵니다.

알아채다:

    두 프로젝트가 프로젝트 수준에 있고 서로 종속되려면 패키징 후 종속성을 통해 가져와야 합니다. 하지만 두 프로젝트의 모듈 레벨을 직접 가져올 수 있다면 나중에 설명하겠습니다.

두 가지 수명 주기 단계를 동시에 실행합니다.

    mvn 새로 설치

    Maven은 먼저 clean 명령을 실행한 다음 install 명령을 실행합니다.

10.4 사이트 수명 주기

    site生命周期的目的是建立和发布项目站点,Maven能够基于POM所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。该生命周期包含如下阶段:
        1、pre-site:执行一些需要在生成站点文档之前完成的工作。

        2、site:生成项目的站点文档。

        3、post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备。

        4、site-deploy:将生成的站点文档部署到特定的服务器上。

十一、Maven项目拆分、继承、聚合

11.1 传统项目开发的问题

    使用Java技术开发的工程项目,无论是数据处理系统还是Web网站,随着项目的不断发展,需求的不断细化与添加,工程项目中的代码越来越多,包结构也越来越复杂这时候工程的进展就会遇到各种问题:

    1、传统的项目中,会将全部的业务都写到一个项目中,用一台Web应用服务器来部署。此时如果某一个业务操作造成服务器宕机,则全部的项目业务都不能访问。

    2、不同方面的代码之间相互耦合,这时候一系统出现问题很难定位到问题的出现原因,即使定位到问题也很难修正问题,可能在修正问题的时候引入更多的问题。

    3、多方面的代码集中在一个整体结构中,新入的开发者很难对整体项目有直观的感受,增加了新手介入开发的成本,需要有一个熟悉整个项目的开发者维护整个项目的结构(通常在项目较大且开发时间较长时这是很难做到的)。

    4、开发者对自己或者他人负责的代码边界很模糊,这是复杂项目中最容易遇到的,导致的结果就是开发者很容易修改了他人负责的代码且代码负责人还不知道,责任追踪很麻烦。

    将一个复杂项目拆分成多个模块是解决上述问题的一个重要方法,多模块的划分可以降低代码之间的耦合性(从类级别的耦合提升到jar包级别的耦合),每个模块都可以是自解释的(通过模块名或者模块文档),模块还规范了代码边界的划分,开发者很容易通过模块确定自己所负责的内容。

11.2 Maven项目拆分

    不知你有没有想过,一个好好的maven工程为什么要进行拆分呢?面对当今互联网+的行业,软件项目变得越来越庞大,复杂程度越来越高,这大大地提高了开发与管理的成本。而工程的拆分可以实现分模块开发与测试,亦可实现多线程开发与管理,在提高工程代码复用度的同时也提高了软件的开发速度与效率。

    例如,一个完整的早期开发好的crm项目,现在要使用maven工程对它进行拆分,这时候就可以将dao层拆解出来,形成一个独立的工程,同样service层以及web层也都进行这样的拆分。
    
    概念讲解和配图原文链接:https://blog.csdn.net/yerenyuan_pku/article/details/103680220

 理解工程拆分的好处:

    从上图可以看出,出现了一个问题,如果crm项目中dao层一旦出现bug需要修复时,erp项目与oa项目中的dao层也要做相应的修改,像这样重复的事情需要做三遍!实在是不可取,那怎么解决呢?

    这时,就可以将crm项目中的dao层拆解出来了,并形成一个独立的工程,然后每个项目都来复用这个独立的工程。

     把工程拆分成一个个独立的工程,将来要用到的时候就把它们的坐标给引进来就行了,这就有点类似于搭积木一样。

     把积木搭建成各种项目:

    对于一个大型的项目,如果我们直接作为一个工程开发,由于相互之间的依赖我们只能从头到尾由一组人开发,否则就会出现一个类好多人开发,相互更改的混乱局面,这个时候我们就将项目进行了横向和纵向的拆分。

    所谓的横向的拆分就是我们平常说的三层架构,将项目分成了web层,service层、dao层(web层也被叫做表现层,service层也被叫做业务层,dao层也被持久层),可以理解为将一个功能模块的不同调用过程进行了水平方向的拆分。

    所谓的纵向拆分就是将一个项目的多个功能模块进行了拆分,横向拆分后,每个功能模块进行了单独的开发之后,项目整合的时候就需要有一个能够整合这些项目或者模块的工程,这就是所谓聚合工程的意义。

11.3 Maven项目聚合

    项目开发通常是分组分模块开发的,每个模块开发完成后,要运行整个工程需要将每个模块聚合在一起运行,比如,dao、service以及web这三个工程最终会打一个独立的war包运行。

    就拿一个完整的早期开发好的crm项目来说,把crm项目拆成多个子模块后,独立运行各个模块是无法完成软件项目的要求的,只有把它们都整合起来,分工合作才能完成工作。因此需要父工程来管理各个子模块,把它们聚合在一起运行,即把crm_dao、crm_service以及crm_web这三个工程打成一个独立的可运行的war包。

     这有点像把汽车的各个零部件组装起来,变成一辆可以行驶的车。以下是一堆的汽车各个零部件。

     将汽车的各个零部件组装起来,可以变成一辆可以行驶的车。

     建立聚合工程需要注意:
        1、该聚合项目本身也做为一个Maven项目,它必须有自己的POM。
        2、它的打包方式必须为:pom。
        3、引入了新的元素:modules---module。
        4、版本:聚合模块的版本和被聚合模块版本一致。
        5、relativePath:每个module的值都是一个当前POM的相对目录。
            指定查找该父项目pom.xml的(相对)路径。默认顺序:relativePath > 本地仓库 > 远程仓库。
            没有relativePath标签等同…/pom.xml, 即默认从当前pom文件的上一级目录找。
        6、目录名称:为了方便的快速定位内容,模块所处的目录应当与其artifactId一致(Maven约定而不是硬性要求),总之,模块所处的目录必须和<module>模块所处的目录</module>相一致。
        7、聚合模块减少的内容:聚合模块的内容仅仅是一个pom.xml文件,它不包含src/main/Java、src/test/java等目录,因为它只是用来帮助其它模块构建的工具,本身并没有实质的内容。
        8、聚合模块和子模块的目录:他们可以是父子类,也可以是平行结构,当然如果使用平行结构,那么聚合模块的POM也需要做出相应的更改。
        9、如果聚合项目的子模块新建完成后进行了删除操作,一定要在聚合项目中pom.xml中的modules选项卡中将这个子模块进行删除

<modules>
    <module>../maven-util</module>
    <module>../maven-entity</module>
    <module>../maven-dao</module>
    <module>../maven-service</module>
    <module>../maven-web</module>
</modules>

总结:

	对于聚合模块来说,它知道有哪些被聚合的模块,而对于被聚合的模块来说,它们不知道被谁聚合了,也不知道它的存在

	对于继承关系的父POM来说,它不知道自己被哪些子模块继承了,对于子POM来说,它必须知道自己的父POM是谁

	在一些最佳实践中我们会发现:一个POM既是聚合POM,又是父POM,这么做主要是为了方便。

11.4 Maven项目的继承

    类似Java中类的继承,都是为了消除重复。子类继承父类,父类里有的方法和属性在子类中就不需要再定义和实现了,使用的时候直接调用父类的就可以了。我们把crm项目拆分后,将会有一个父工程(例如crm)和若干个子工程(例如crm_dao、crm_service、crm_web),子工程中要用到的依赖都可以在父工程的pom.xml文件中进行依赖管理,将来子工程在开发的时候就不需要再定义版本了,这样做的目的是为了方便管理。

    继承除了能够避免重复,还有一个好处就是让项目更加安全。

    继承时需要注意:
        1、说到继承肯定是一个父子结构,那么我们在聚合项目中来创建一个parent project。
        2、<packaging>: 作为父模块的POM,其打包类型也必须为POM。
        3、结构:父模块只是为了帮助我们消除重复,所以它也不需要src/main/java、src/test/java等目录。
        4、新的元素:<parent>,它是被用在子模块中的。
        5.<parent>元素的属性:<relativePath>: 表示父模块POM的相对路径,在构建的时候,Maven会先根据relativePath检查父POM,如果找不到,再从本地仓库查找。
        6、relativePath的默认值:../pom.xml。
        7、子模块省略groupId和version: 使用了继承的子模块中可以不声明groupId和version, 子模块将隐式的继承父模块的这两个元素。

十二、Maven综合案例

    对于一个大型的项目,大部分情况下都是将一个项目的多个功能模块进行了拆分,拆分后,每个功能模块进行了单独的开发之后,项目整合的时候就需要有一个能够整合这些项目或者模块的工程,这就是所谓聚合工程的意义。

    我们现在不写那么多模块,把一个学生模块按照类的功能(三层架构)拆分成一个个模块,然后来体会项目的拆分、继承、聚合。

12.1 搭建项目结构

12.1.1 创建管理父项目

    1、创建管理父项目(maven-student),Maven管理类项目的打包方式为pom。管理类父项目只是用来帮助其它模块构建的工具,本身并没有实质的内容,可以删除src目录。

     2、创建完成之后,做如下配置:
        2.1 修改项目打包方式为pom。
        2.2 依赖版本管理。
        2.3 依赖管理

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.maven</groupId>
    <artifactId>maven-student</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 1、修改为管理项目,packaging为pom -->
    <packaging>pom</packaging>

    <!-- 2、依赖版本管理:对项目中所有的依赖的版本进行管理 -->
    <properties>
        <!-- properties里面可以定义自定义标签 -->
        <servlet.version>3.0.1</servlet.version>
        <jsp.version>2.1</jsp.version>
        <jstl.version>1.2</jstl.version>
        <junit.version>4.12</junit.version>
        <mysql.version>5.1.49</mysql.version>
    </properties>

    <!-- 3、依赖管理:对项目中所有的依赖进行管理 -->
    <!-- 依赖管理不会引入依赖 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <!-- maven表达式获取版本 -->
                <version>${servlet.version}</version>
                <scope>provided</scope>
            </dependency>

            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>${jsp.version}</version>
                <scope>provided</scope>
            </dependency>

            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>${jstl.version}</version>
            </dependency>

            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>

            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>
</project>

12.1.2 创建工具类子项目

    1、创建工具类子项目(maven-student-util)。

    注意:创建子项目的时候,创建的是一个Module。父项目右键 -> New -> Module,Module也是Maven项目。

     2、maven-student-util子模块的pom.xml文件里面会自动添加parent标签,标识当前模块的父项目或父模块。并且父项目的pom.xml文件中会自动添加modules,标识聚合的模块。

<!-- Maven继承:子模块中的parent表示当前模块的父项目或父模块 -->
<parent>
    <artifactId>maven-student</artifactId>
    <groupId>com.maven</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
<!-- 父项目管理的子模块列表:聚合 -->
<modules>
    <module>maven-student-util</module>
    <module>maven-student-entity</module>
</modules>

    3、引入当前模块需要用到的依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- Maven继承:子模块中的parent表示当前模块的父项目或父模块 -->
    <parent>
        <artifactId>maven-student</artifactId>
        <groupId>com.maven</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <!-- 子模块可以继承groupId和version等,但是artifactId不能继承 -->
    <artifactId>maven-student-util</artifactId>

    <!-- 配置当前模块的依赖 -->
    <dependencies>
        <!-- 子模块中配置依赖无需再配置版本,都是参照父项目的版本号 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

12.1.3 创建实体类子项目

    创建实体类子项目(maven-student-entity),并引入当前模块需要用到的依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>maven-student</artifactId>
        <groupId>com.maven</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>maven-student-entity</artifactId>

    <!-- 配置当前模块的依赖 -->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

12.1.4 创建持久层子项目

    创建持久层子项目(maven-student-dao),并引入当前模块需要用到的依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>maven-student</artifactId>
        <groupId>com.maven</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>maven-student-dao</artifactId>

    <!-- 配置当前模块的依赖 -->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 持久层需要用到工具类,那么就需要引入自己的模块,无需安装 -->
        <!-- 这里没有定义版本,是因为在父项目中对自己的模块进行依赖管理了 -->
        <dependency>
            <groupId>com.maven</groupId>
            <artifactId>maven-student-util</artifactId>
        </dependency>
        <dependency>
            <groupId>com.maven</groupId>
            <artifactId>maven-student-entity</artifactId>
        </dependency>
    </dependencies>

</project>

    在父项目中对自己的模块进行依赖管理,子模块中就不需要定义版本。

<dependency>
    <groupId>com.maven</groupId>
    <artifactId>maven-student-util</artifactId>
    <!-- Maven表达式中的对象project -->
    <version>${project.version}</version>
</dependency>

<dependency>
    <groupId>com.maven</groupId>
    <artifactId>maven-student-entity</artifactId>
    <version>${project.version}</version>
</dependency>

12.1.5 创建业务层子项目

    创建业务层子项目(maven-student-service),并引入当前模块需要用到的依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>maven-student</artifactId>
        <groupId>com.maven</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>maven-student-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.maven</groupId>
            <artifactId>maven-student-dao</artifactId>
        </dependency>
    </dependencies>

</project>

12.1.6 创建表现层子项目

    1、创建表现层子项目(maven-student-web),修改项目打包方式为war。

    2、引入当前模块需要用到的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>maven-student</artifactId>
        <groupId>com.maven</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>maven-student-web</artifactId>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>com.maven</groupId>
            <artifactId>maven-student-service</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>

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

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
    </dependencies>

</project>

最后,父项目的pom.xml文件的内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.maven</groupId>
    <artifactId>maven-student</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 父项目管理的子模块列表:聚合 -->
    <modules>
        <module>maven-student-util</module>
        <module>maven-student-entity</module>
        <module>maven-student-dao</module>
        <module>maven-student-service</module>
        <module>maven-student-web</module>
    </modules>
    <!-- 1、修改为管理项目,packaging为pom -->
    <packaging>pom</packaging>

    <!-- 2、依赖版本管理:对项目中所有的依赖的版本进行管理 -->
    <properties>
        <!-- properties里面可以定义自定义标签 -->
        <servlet.version>3.0.1</servlet.version>
        <jsp.version>2.1</jsp.version>
        <jstl.version>1.2</jstl.version>
        <junit.version>4.12</junit.version>
        <mysql.version>5.1.38</mysql.version>
    </properties>

    <!-- 3、依赖管理:对项目中所有的依赖进行管理 -->
    <!-- 依赖管理不会引入依赖 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <!-- maven表达式获取版本 -->
                <version>${servlet.version}</version>
                <scope>provided</scope>
            </dependency>

            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>${jsp.version}</version>
                <scope>provided</scope>
            </dependency>

            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>${jstl.version}</version>
            </dependency>

            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>

            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>

            <dependency>
                <groupId>com.maven</groupId>
                <artifactId>maven-student-util</artifactId>
                <!-- Maven表达式中的对象project -->
                <version>${project.version}</version>
            </dependency>

            <dependency>
                <groupId>com.maven</groupId>
                <artifactId>maven-student-entity</artifactId>
                <version>${project.version}</version>
            </dependency>

            <dependency>
                <groupId>com.maven</groupId>
                <artifactId>maven-student-dao</artifactId>
                <version>${project.version}</version>
            </dependency>

            <dependency>
                <groupId>com.maven</groupId>
                <artifactId>maven-student-service</artifactId>
                <version>${project.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

12.1.7 关于modules

    modules可以加,也可以不加。但是modules有一个好处,当定义modules之后,我们通过父项目执行生命周期,所有的子module都会执行对应的生命周期。

    注意:我们如果模块之间没有依赖,那么按照聚合配置的顺序来执行;如果有了依赖,肯定是被依赖的先构建。

通过父项目执行编译:

12.2 项目后端实现

12.2.1 创建学生表

    在MySQL数据库的test库下创建学生表,学生表字段如下:

12.2.2 DBUtils工具类实现

    在工具类子项目中创建com.maven.util包,创建DBUtils工具类。

DBUtils代码如下:

package com.maven.util;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/*
 * JDBC工具类的高度封装
 * */
public class DBUtils {
    /*
     * private 为了不让外部调用
     * static 因为要在static代码块或方法中使用
     * final 不允许修改
     * */
    private static final String driverName = "com.mysql.jdbc.Driver";
    private static final String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8";
    private static final String userName = "root";
    private static final String userPwd = "root";
    private static Connection connection;
    private static PreparedStatement preparedStatement;
    private static ResultSet resultSet;

    /*
     * 注册数据库驱动,注册驱动只需要执行一次即可
     *   static静态代码块,在类加载的时候有且仅执行一次
     * */
    static {
        try {
            Class.forName(driverName);
        } catch (ClassNotFoundException e) {
            System.out.println("数据库驱动加载失败!");
        }
    }

    /*
     * 获取连接
     * */
    public static Connection getConnection() {
        try {
            connection = DriverManager.getConnection(url, userName, userPwd);
        } catch (SQLException throwables) {
            System.out.println("数据库连接获取失败!");
        }
        return connection;
    }

    /*
     * 查询数据的方法
     *   参数:
     *       String sql,要执行的sql语句
     *       List list,sql的参数
     *   返回值:
     *       不能返回ResultSet,因为资源释放之后,结果集不能在操作
     *       把结果集里面的数据用另外一种形式返回即可 List<Map<String,String>>
     * */
    public static List<Map<String, String>> query(String sql, List list) {
        List<Map<String, String>> resultList = new ArrayList<>();
        // 每次执行查询,都要获取得到连接
        getConnection();

        // 获取执行SQL语句的PrepareStatement对象
        try {
            preparedStatement = connection.prepareStatement(sql);
            // 给sql设置参数
            for (int i = 0; i < list.size(); i++) {
                // 因为不知道参数的类型,所以我们直接使用setObject(占位符索引,值); 占位符索引从1开始
                preparedStatement.setObject(i + 1, list.get(i));
            }

            // 执行查询
            resultSet = preparedStatement.executeQuery();

            // 获取结果集对应的结构
            ResultSetMetaData metaData = resultSet.getMetaData();

            // 把resultSet转换为List<Map<String,String>>
            while (resultSet.next()) {
                // resultSet里面每有一条数据,就创建一个Map集合
                Map<String, String> map = new HashMap<>();
                // map里面的key是列名,value是列对应的值
                // 结果集里面有多少列,就向map里面存储多少对值
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    map.put(metaData.getColumnName(i), resultSet.getString(i));
                }
                // 把map存储到list中
                resultList.add(map);
            }

        } catch (SQLException throwables) {
            System.out.println("SQL语句异常");
        } finally {
            close();
        }
        return resultList;
    }

    /*
     * 增删改的方法
     *   返回值: int类型,表示增、删、改的条目数
     *   参数:
     *       String sql,要执行的sql语句
     *       List list,sql的参数
     * */
    public static int update(String sql, List list) {
        int count = 0;
        // 每次执行更改操作,都要获取得到连接
        getConnection();

        // 获取执行SQL语句的PrepareStatement对象
        try {
            preparedStatement = connection.prepareStatement(sql);
            // 给sql设置参数
            for (int i = 0; i < list.size(); i++) {
                // 因为不知道参数的类型,所以我们直接使用setObject(占位符索引,值); 占位符索引从1开始
                preparedStatement.setObject(i + 1, list.get(i));
            }

            count = preparedStatement.executeUpdate();

        } catch (SQLException throwables) {
            System.out.println("SQL语句异常");
        } finally {
            close();
        }
        return count;
    }


    /*
     * 释放资源
     * */
    public static void close() {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                System.out.println("结果集关闭失败");
            }
        }

        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException throwables) {
                System.out.println("Statement关闭失败");
            }
        }

        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException throwables) {
                System.out.println("连接关闭失败!");
            }
        }
    }
}

12.2.3 学生实体类实现

    在实体类子项目中创建com.maven.entity包,创建StudentEntity实体类。

StudentEntity代码如下:

package com.maven.entity;

/**
 * 学生实体类
 */
public class StudentEntity {
    private Integer id;
    private String name;
    private String sex;
    private String major;

    public StudentEntity() {
    }

    public StudentEntity(Integer id, String name, String sex, String major) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.major = major;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getMajor() {
        return major;
    }

    public void setMajor(String major) {
        this.major = major;
    }

    @Override
    public String toString() {
        return "StudentEntity{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", major='" + major + '\'' +
                '}';
    }
}

12.2.4 学生持久层实现

    在持久层子项目中创建com.maven.dao包,创建StudentDao接口。

    在持久层子项目中创建com.maven.dao.impl包,创建StudentDaoImpl实现类。

    注:我们仅仅实现简单的一套CRUD即可。

StudentDao接口代码如下:

package com.maven.dao;

import com.maven.entity.StudentEntity;

import java.util.List;
import java.util.Map;

/*
 * 学生DAO接口
 */
public interface StudentDao {
    /*
     * 新增学生的方法
     * @param studentEntity 包含新增学生的信息实体类
     * @return int 实际插入的数量
     */
    public abstract int insert(StudentEntity studentEntity);

    /*
     * 删除学生的方法
     * @param id 删除学生的id
     * @return int 实际删除的数量
     */
    public abstract int delete(Integer id);

    /*
     * 修改学生的方法
     * @param studentEntity 包含修改学生的信息实体类
     * @return int
     */
    public abstract int update(StudentEntity studentEntity);

    /*
     * 根据id查询学生的方法
     * @param id 查询学生的id
     * @return StudentEntity 查询到的学生信息
     */
    public abstract List<Map<String, String>> query(Integer id);

    /*
     * 查询所有学生的方法
     * @return List<StudentEntity> 查询到的所有数据
     */
    public abstract List<Map<String, String>> queryAll();
}

StudentDaoImpl实现类代码如下:

package com.maven.dao.impl;

import com.maven.dao.StudentDao;
import com.maven.entity.StudentEntity;
import com.maven.util.DBUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 学生DAO接口实现类
 */
public class StudentDaoImpl implements StudentDao {

    @Override
    public int insert(StudentEntity studentEntity) {
        String sql = "insert into student(name,sex,major) values (?,?,?)";
        List list = Arrays.asList(studentEntity.getName(), studentEntity.getSex(), studentEntity.getMajor());
        return DBUtils.update(sql, list);
    }

    @Override
    public int delete(Integer id) {
        String sql = "delete from student where id = ?";
        List list = Arrays.asList(id);
        return DBUtils.update(sql, list);
    }

    @Override
    public int update(StudentEntity studentEntity) {
        String sql = "update student set name = ?,sex=?,major=? where id = ?";
        List list = Arrays.asList(studentEntity.getName(), studentEntity.getSex(), studentEntity.getMajor(),studentEntity.getId());
        return DBUtils.update(sql, list);
    }

    @Override
    public List<Map<String, String>> query(Integer id) {
        String sql = "select * from student where id = ?";
        List list = Arrays.asList(id);
        return DBUtils.query(sql,list);
    }

    @Override
    public List<Map<String, String>> queryAll() {
        String sql = "select * from student";
        List list = new ArrayList();
        return DBUtils.query(sql,list);
    }
}

12.2.5 学生业务层实现

    在业务层子项目中创建com.maven.service包,创建StudentService类。

StudentService类代码如下:

package com.maven.service;

import com.maven.dao.StudentDao;
import com.maven.dao.impl.StudentDaoImpl;
import com.maven.entity.StudentEntity;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 学生的业务逻辑层
 */
public class StudentService {
    //创建DAO实现类对象
    private StudentDao studentDao = new StudentDaoImpl();

    public int insert(StudentEntity studentEntity) {
        return studentDao.insert(studentEntity);
    }

    public int delete(Integer id) {
        return studentDao.delete(id);
    }

    public int update(StudentEntity studentEntity) {
        return studentDao.update(studentEntity);
    }

    public StudentEntity query(Integer id) {
        StudentEntity studentEntity = null;
        List<Map<String, String>> query = studentDao.query(id);
        if (query.size() > 0) {
            Map<String, String> stringMap = query.get(0);
            studentEntity = new StudentEntity();
            studentEntity.setId(Integer.parseInt(stringMap.get("id")));
            studentEntity.setName(stringMap.get("name"));
            studentEntity.setSex(stringMap.get("sex"));
            studentEntity.setMajor(stringMap.get("major"));
        }

        return studentEntity;
    }

    public List<StudentEntity> queryAll() {
        List<StudentEntity> list = new ArrayList<>();
        List<Map<String, String>> query = studentDao.queryAll();
        for (int i = 0; i < query.size(); i++) {
            Map<String, String> stringMap = query.get(0);
            StudentEntity studentEntity = new StudentEntity();
            studentEntity.setId(Integer.parseInt(stringMap.get("id")));
            studentEntity.setName(stringMap.get("name"));
            studentEntity.setSex(stringMap.get("sex"));
            studentEntity.setMajor(stringMap.get("major"));
            list.add(studentEntity);
        }
        return list;
    }
}

12.2.6 学生表现层Servlet实现

查询所有学生的Servlet:

package com.maven.servlet;

import com.maven.entity.StudentEntity;
import com.maven.service.StudentService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * 查询所有学生的Servlet
 */
@WebServlet("/student/list")
public class StudentQueryAllServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        StudentService studentService = new StudentService();
        List<StudentEntity> list = studentService.queryAll();
        System.out.println(list);
        req.setAttribute("stuList", list);
        System.out.println(req.getServletContext().getContextPath());
        //在请求转发中,/表示项目根目录
        req.getRequestDispatcher("/student/list.jsp").forward(req, resp);

    }
}

根据id查询学生的Servlet:

package com.maven.servlet;

import com.maven.entity.StudentEntity;
import com.maven.service.StudentService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 根据学生id查询学生的Servlet
 */
@WebServlet("/student/query")
public class StudentQueryServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        //获取查询学生的id
        int id = Integer.parseInt(req.getParameter("id"));

        StudentService studentService = new StudentService();
        StudentEntity studentEntity = studentService.query(id);

        req.setAttribute("editStudentInfo", studentEntity);
        req.getRequestDispatcher("/student/edit.jsp").forward(req, resp);

    }
}

添加学生的Servlet:

package com.maven.servlet;

import com.maven.entity.StudentEntity;
import com.maven.service.StudentService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 添加学生的Servlet
 */
@WebServlet("/student/add")
public class StudentAddServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        String name = req.getParameter("name");
        String sex = req.getParameter("sex");
        String major = req.getParameter("major");

        StudentEntity studentEntity = new StudentEntity(null, name, sex, major);

        StudentService studentService = new StudentService();
        int i = studentService.insert(studentEntity);

        if (i > 0) {
            req.setAttribute("msg", "添加成功!");
        } else {
            req.setAttribute("msg", "添加失败!");
        }

        req.getRequestDispatcher("/student/list").forward(req, resp);
    }
}

删除学生的Servlet:

package com.maven.servlet;

import com.maven.entity.StudentEntity;
import com.maven.service.StudentService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 删除学生的Servlet
 */
@WebServlet("/student/delete")
public class StudentDeleteServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        //获取删除学生的id
        int id = Integer.parseInt(req.getParameter("id"));
        System.out.println("删除学生的id:"+id);

        StudentService studentService = new StudentService();
        int i = studentService.delete(id);

        if (i > 0) {
            req.setAttribute("msg", "删除成功!");
        } else {
            req.setAttribute("msg", "删除失败!");
        }

        req.getRequestDispatcher("/student/list").forward(req, resp);
    }
}

修改学生的Servlet:

package com.maven.servlet;

import com.maven.entity.StudentEntity;
import com.maven.service.StudentService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 修改学生的Servlet
 */
@WebServlet("/student/update")
public class StudentUpdateServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        int id = Integer.parseInt(req.getParameter("id"));
        String name = req.getParameter("name");
        String sex = req.getParameter("sex");
        String major = req.getParameter("major");

        StudentEntity studentEntity = new StudentEntity(id, name, sex, major);
        System.out.println(studentEntity);

        StudentService studentService = new StudentService();
        int i = studentService.update(studentEntity);

        if (i > 0) {
            req.setAttribute("msg", "修改成功!");
        } else {
            req.setAttribute("msg", "修改失败!");
        }

        req.getRequestDispatcher("/student/list").forward(req, resp);
    }
}

12.3 项目前端实现

目录结构如下:

12.3.1 项目首页实现

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>这里是项目首页</h1>
    <a href="${pageContext.request.contextPath}/student/list">查询所有学生信息</a>
</body>
</html>

12.3.2 学生列表页实现

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
    <style>
        table, td, th {
            border: 1px solid black;
            border-collapse: collapse;
        }

        table {
            width: 600px;
        }

        tr {
            height: 40px;
        }
    </style>
</head>
<body>
    <h2>所有学生的信息: ${msg}</h2>
    <table>
        <tr>
            <th>学号</th>
            <th>姓名</th>
            <th>性别</th>
            <th>专业</th>
            <th>操作</th>
        </tr>
        <c:forEach items="${stuList}" var="stu">
            <tr>
                <td>${stu.id}</td>
                <td>${stu.name}</td>
                <td>${stu.sex}</td>
                <td>${stu.major}</td>
                <td>
                    <a href="${pageContext.request.contextPath}/student/delete?id=${stu.id}">删除</a>
                        <%--先根据id查询学生信息,然后跳转到修改页面--%>
                    <a href="${pageContext.request.contextPath}/student/query?id=${stu.id}">修改</a>
                </td>
            </tr>
        </c:forEach>
    </table>
</body>
</html>

12.3.3 修改学生页面实现

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h2>修改学生信息</h2>
    <form action="${pageContext.request.contextPath}/student/update" method="post">
        <p>
            学号: <input type="text" name="id" value="${editStudentInfo.id}" readonly>
        </p>
        <p>
            姓名: <input type="text" name="name" value="${editStudentInfo.name}">
        </p>
        <p>
            性别:
            <c:if test="${editStudentInfo.sex == '男'}">
                <input type="radio" name="sex" value="男" checked> 男
                <input type="radio" name="sex" value="女"> 女
            </c:if>
            <c:if test="${editStudentInfo.sex == '女'}">
                <input type="radio" name="sex" value="男"> 男
                <input type="radio" name="sex" value="女" checked> 女
            </c:if>
        </p>
        <p>
            专业: <input type="text" name="major" value="${editStudentInfo.major}">
        </p>
        <p>
            <button type="submit">修改</button>
        </p>
    </form>
</body>
</html>

12.3.4 添加学生页面实现

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h2>添加学生信息</h2>
    <form action="${pageContext.request.contextPath}/student/add" method="post">
        <p>
            姓名: <input type="text" name="name">
        </p>
        <p>
            性别:
            <input type="radio" name="sex" value="男" checked> 男
            <input type="radio" name="sex" value="女"> 女

        </p>
        <p>
            专业: <input type="text" name="major">
        </p>
        <p>
            <button type="submit">新增</button>
        </p>
    </form>
</body>
</html>

추천

출처blog.csdn.net/ligonglanyuan/article/details/123988592