One article teaches you to be proficient in Maven, quickly switch from traditional Java and JavaWeb projects to Maven projects, and Maven practical case tutorials

1. Maven concept

1.1 Introduction to Maven

Maven is a project management tool that includes a project object model (Project Object Model), a set of standard collections, a project life cycle (Project Lifecycle), a dependency management system (Dependency Management System), and is used to run definitions in The logic of the plugin goal in the lifecycle phase. When you use Maven, you describe your project with a well-defined project object model, and Maven can then apply crosscutting logic from a set of shared (or custom) plugins.

Maven is translated as "expert", "expert". Maven is an open source project developed purely in Java under Apache. It is a project management tool that can use Maven to build and manage Java projects. The number of projects currently using Maven continues to grow.

Maven official website: https://maven.apache.org/

Maven functions: cleaning, compiling, testing (writing unit tests yourself), reporting, packaging (export jar, war), deployment.

1.2 What is project construction

    Project construction is the process of a project from writing source code to compiling, testing, packaging, deploying, and running.

1.2.1 Traditional project construction process

The traditional process of building a project using Eclipse is as follows:

     The construction process is as follows:  
        1. Create a JavaWeb project in Eclipse.
        2. Write source code and configuration files in the project.
        3. Compile the source code, and compile the Java file into a class file.
        4. Execute Junit unit tests.
        5. Make the project into a war package and deploy it to Tomcat to run.

1.2.2 Maven project construction process

    Maven standardizes the process of project construction. Each stage is completed with one command. The following figure shows some stages of the construction process. The following chapters introduce each stage in detail. Here is a general overview:

    The commands corresponding to some stages in the figure above are as follows:
        The Maven command corresponding to the cleanup stage is clean, which cleans up the output class files.
        The Maven command corresponding to the compilation phase is compile, which compiles the Java code into a class file.
        The Maven command corresponding to the packaging phase is package, Java projects can be packaged into jar packages, and web projects can be packaged into war packages.
        Running a Maven project (web project) requires a command: tomcat:run.

    Advantages of Maven project construction:
        1. One command completes construction and operation, which is convenient and fast.
        2. Maven regulates each construction phase, which is very conducive to the collaborative development of large teams.

1.3 What is dependency management

    What is dependency? A Java project may need to use some third-party jar packages to run, so we say that this Java project depends on these third-party jar packages. For example: a crm system, its architecture is the SSH framework, the crm project depends on the SSH framework, specifically it depends on Hibernate, Spring, Struts2 related jar packages.

    What is dependency management? It is the standardized management of all dependent jar packages of the project.

1.3.1 Dependency management of traditional projects

    The jar packages that traditional project engineering depends on are completely managed manually. The programmers download the jar packages from the Internet and add them to the project project, as shown in the figure below: The programmers manually add the jar packages of Hibernate, Struts2, and Spring to the WEB- INF/lib directory.

     The problems of manually copying the jar package and adding it to the project are:
        1. There is no unified management of the version of the jar package, which may easily lead to version conflicts.
        2. It is very inconvenient to find jar packages from the Internet, and some jars cannot be found.
        3. The jar package is added to the project and the project is too large.

1.3.2 Dependency management of Maven project

    The jar package that Maven project management depends on does not need to manually add the jar package to the project. It only needs to add the coordinates of the jar package in pom.

     The benefits of using Maven dependency management to add jars:
        1. Unified management of the version of the jar package through the pom.xml file can avoid version conflicts.
        2. The Maven team maintains a very complete Maven warehouse, which includes the currently used jar packages. Maven projects can automatically download jar packages from the Maven warehouse, which is very convenient.

1.4 Maven Conceptual Model

    In the above concepts, we mentioned: Maven is a project management tool, which includes a project object model (Project Object Model), a set of standard collections, a project life cycle (Project Lifecycle), a dependency management system (Dependency Management System), and the logic used to run the goal of the plugin defined in the lifecycle phase (phase).

1.4.1 Project Object Model

    Maven Project Object Model (POM), a project management tool software that can manage project construction, reporting and documentation through a small piece of description information.

    In addition to featuring program building capabilities, Maven also provides advanced project management tools. Due to the high reusability of Maven's default build rules, simple projects can often be built with two or three lines of Maven build scripts. 

    A Maven project has a pom.xml file, which defines the project coordinates, project dependencies, project information, plug-in goals, etc. through the pom.xml file.

Let's take a look at pom.xml first:

<?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>

Part 1: Basic information of the project

<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>

The second part: surrounded by dependencies is the jar package that needs to be used in the project

<!-- 添加依赖: 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>

The third part: surrounded by build are the plug-ins that need to be used in the project

<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>

    It has been introduced in detail above, and it is divided into three parts, namely:
        1. Information about the project itself.
        2. The jar package information that the project operation depends on.    
        3. Project operating environment information, such as: jdk, tomcat information.

1.4.2 Dependency Management System

    Through Maven's dependency management, the jar packages that the project depends on are managed in a unified manner. The project manages jar packages by defining dependencies in pom.xml.

    The central in the picture refers to the central warehouse, b2b refers to the remote warehouse, and local refers to the local warehouse. Here we focus on the three parts that make up Dependency:
        1. The name of the company organization.
        2. Project name.
        3. Version number.

Let's analyze a specific Dependency:

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

    Where javax.servlet is the name of the company organization (parent project), javax.servlet-api is the project name, and 3.0.1 is the version number.

    Why Dependency Management?
        Dependency management:
            1. It can be connected to the Internet to download automatically.
            2. Do dependency management on the modules developed by ourselves.

1.4.3 Project Lifecycle

    The Build lifecycle in the lower part of the picture refers to the life cycle of Maven, and the Plug-in below refers to the plug-in, that is, each Maven command corresponds to the underlying plug-in of Maven.

    The construction of the project is completed through Maven: cleaning, compiling, testing, deployment, etc. Maven standardizes these projects into a life cycle.

     Maven can realize the above life cycle processes by executing some simple commands.

1.4.4 A set of standard sets

    Maven defines a set of standards for the entire project management process. For example, a Maven construction project has a standard directory structure, a standard life cycle stage, and a standard coordinate definition for dependency management.
    
    Maven advocates the use of a common standard directory structure, which facilitates the collaboration of different developers and facilitates the implementation of some unified automation scripts.

    Previously created java projects:
        src -> source code directory, but this is not a standard, we can create a folder casually and make it a source code directory.
        libs -> third-party jar package, but the directory can be any name. 
    
    Previously created web projects:
        src -> source code directory.
        web -> A directory created by IDEA tools to store static resources, configuration files, and third-party jars.
        WebContent/WebRoot -> A directory created by Eclipse tools to store static resources, configuration files, and third-party jars.

    The projects we created before, there was no standard.

1.4.5 Plug-in goals

    Maven manages the project lifecycle based on plugins.

1.5 Why use Maven

    1. A project is a project.
        If the project is very large, it is not suitable to use packages to divide modules. It is better to have each module correspond to a project, which is conducive to division of labor and collaboration. With the help of Maven, a project can be split into multiple projects.

    2. The jar package used in the project needs to be "copyed" and "pasted" into the lib of the project, which is inconvenient to manage.
        When our project is relatively large, we will divide a large project into many small projects. Each small project Several developers are in charge. For example, an e-commerce project is divided into: account-related projects, order-related projects, and product-related projects. The structures of these projects are similar, and the technologies used are the same: SSM (Spring , Springmvc, Mybatis), and then each project needs to copy a copy of these jars to its own project directory. The last 10 projects only copied 10 copies of jars. Later, we found that some jars in the project needed to be upgraded. Replace it. At this time, we need to replace 10 items in turn, which is also quite painful.
        With the help of Maven, you can save the jar package in the "warehouse", no matter which project you are in, just use the reference.

    3. When the jar package is needed, you must prepare it yourself or download it from the official website.
        For example, we need to use fastjson in our project. At this time, we will go to Baidu to search for the fastjson related jar package, download it, and put it under the lib of the project. , and then add it to the classpath of the project, and use it to find that the version of this jar is too old, not what we want, and then look for it again, which is painful.
        Maven defines a unique flag for each jar, which is called the coordinates of the project in maven, through which you can find any version of the jar package you need to use.

    4. Risk of inconsistent jar package versions
        . a.jar is used in the project, and a.jar depends on version 1.5 of c.jar. Then we copy these two jars into the project, and b.jar is used later, but b .jar also depends on the 1.0 version of c.jar. At this time, if you import b.jar and c-1.0.jar, you will find that there are two versions of c.jar, which conflict, and an error will be reported when starting. In this case, you have to start to solve the jar conflict problem, which is also very painful.
        Maven can easily resolve jar conflicts between different versions.

    5. A jar package depends on other jar packages and needs to be manually added to the project.
        Generally, jar packages do not exist independently. Generally, some jars will also use other jars. For example, spring-aop.jar will use spring-core .jar, this dependency may be relatively simple, and some dependencies may have many levels, such as a.jar depends on b.jar, and b.jar depends on c.jar, and c.jar depends on d.jar, when you use When it comes to a.jar, you need to include the other three, so when you use a jar, you must clearly know which jars these jars will depend on, and import them all, otherwise the project will not be able to In normal operation, when the project uses a lot of jars, it is difficult for us to judge which jars are missing. We only know when an error is reported during the project running process. This is also quite painful and wastes a lot of time.
        Maven will automatically solve the problem of jar dependencies. For example, if you use a-1.0.jar, and a-1.0.jar depends on b-1.1.jar and c-1.5.jar, when we introduce a-1.0.jar through Maven After that, b-1.1.jar and c-1.5.jar will be imported automatically.

    6. Unified project structure
        A long time ago, when we used eclipse to build a project, the location of the Java source code, the location of the resource file, the location of the test file, the location of the static resource, and the location of the compiled class file can all be placed at will , These are determined by the architects of their respective companies when they build the project, and are defined according to their experience. As a result, each company may have a different project structure. Knowing where is where requires human guidance, which invisibly increases the cost. Wouldn’t it be very convenient if everyone adopts the same project structure according to a certain specification? Everyone follows a certain agreement and projects use the same structure, such as: Java Files, resource files, test cases, static resources, compiled classes, the location of jars after packaging, etc. The location of various files, these things, if all companies that do Java development agree, after getting a project like this , you can save a lot of things.
        The project structure built with Maven needs to follow the same structure. Java source files, resource files, test case class files, and static resource files are all agreed upon. Everyone follows this agreement. If your project uses Created by Maven, recruit new people to take over. If they understand Maven, they don't need training at all, and they can understand the structure of the entire project when they come up.

    7. Cross-platform
        Maven is cross-platform and can be used on Windows and Linux.

2. Maven installation and configuration

2.1 Install JDK and configure JDK environment variables

    The installation of Maven must be based on the environment variable of the JAVA_HOME configuration.

    System variable:
        variable name: JAVA_HOME
        variable value: JDK installation root path (C:\Java\jdk1.8.0_311)

    Path path import:
        %JAVA_HOME%\bin

    Note: Maven3.3+ version, jdk is at least 1.7 and above

2.2 Maven installation

2.2.1 Maven download

    Maven's official website download address: https://maven.apache.org/download.cgi, you can download the latest version.
        
    Note: Maven does not require the latest version, but at least version 3.3+.

2.2.2 Maven installation

    Maven itself is a green version that does not need to be installed, just decompress it. Unzip Maven into a directory that does not contain Chinese and spaces.

2.2.3 Configure Maven environment variables

    1. Right click on the computer -> properties -> advanced system settings -> advanced tab -> environment variables.    

    2. Create a new system variable:
        variable name: MAVEN_HOME
        variable value: D:\Tools\apache-maven-3.8.5 (Maven decompression path)

     3. Add %MAVEN_HOME%\bin to the Path system variable

2.2.4 Testing

    Open the cmd command line window and run the mvn -version command to test whether the configuration is successful.

2.3 Maven directory analysis

    bin directory: scripts run by Maven.
        mvn (run the project in run mode)
        mvnDebug (run the project in debug mode)

    Boot directory: The class loader required for Maven to run.

    conf directory:
        settings.xml, the core configuration file of the entire Maven tool. 

    lib directory: Maven runs dependent jar packages.

2.4 Global settings and user settings

    Maven warehouse address, private server and other configuration information need to be configured in the settings.xml file, which is divided into global configuration and user configuration.

    There is a conf/settings.xml file in the Maven installation directory. This settings.xml file is used for all Maven projects, and it is used as Maven's global configuration.

    If you need personalized configuration, you need to set it in the user configuration. The default location of the setting.xml file of the user configuration is: ${user.home}/.m2/settings.xml directory, ${user.home} refers to the Windows user directory. (personal recommendation)

    Maven will first find the user configuration, if found, the user configuration file shall prevail, otherwise the global configuration file shall be used.

    Role: Maven's local warehouse location, central warehouse mirroring and other configurations.

    Detailed explanation of maven global configuration file settings.xml: https://cloud.tencent.com/developer/article/1014577

2.5 Configure Alibaba Cloud Mirror Warehouse

    All projects built using Maven will be downloaded from the Maven warehouse, and there will be two problems:
        1. The download speed is too slow.
        2. Official mirror node blacklist mechanism.
    
    Note: Check the ip address ip138.com for external access.

    Based on the above problems, we need to configure a domestic mirror node, and it is recommended to use Alibaba Cloud mirror (remember to comment out the default mirror node).

    Note: "Mirroring is a form of file storage and a type of redundancy. The data on one disk has an identical copy on another disk, which is a mirror."

Method 1: Global Configuration

    You can add the image of Alibaba Cloud to the setting.xml configuration of maven, so that you don’t need to add the configuration of the mirror warehouse in the pom every time, and add sub-nodes under the mirrors node:

<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>

Method 2: User Configuration

    Copy conf/settings.xml to the .m2 folder.

    Note: If the creation of the .m2 folder fails, you can consider using the command line to create it, enter the user directory, and execute mkdir .m2.

Note: Be sure to put the mirror configuration <mirrors>below

2.6 Maven Uninstall

    Since Maven is only decompressed, configured environment variables, and set up a local warehouse during installation, it is also very simple to uninstall.
        1. Delete the decompressed maven folder;
        2. Delete the set environment variable MAVEN_HOME, delete the "%MAVEN_HOME%\bin;" added in the path;
        3. Delete the local warehouse;

3. Maven agreement

In the Java project and JavaWeb project, src is the source code directory.

    There are four source code directories of the Maven project, which are:
        src/main/java: stores the source code (.java) files of the project.
        src/main/resources: store project configuration resource files and resource files, such as Spring, Mybatis configuration files, and db.properties database resource files.
        src/test/java: store test code, such as Junit test class.
        src/test/resources: Store configuration files used in tests.

src/main/webapp: The directory of the Maven Web project, similar to the WebContent/WebRoot directory of the Web project in eclipse.

target: project output location, the compiled class file will be output to this directory.

pom.xml: Configuration management, dependency management, and plug-in management of the current project.

The structure is as follows:

Project
    |---src
    |----|---main
    |----|----|---java Store the .java file of the project
    |----|----|-- -resources Store project resource files, such as spring, hibernate configuration files
    |----|----|---webapp The webapp directory is the main directory of the web project
    |----|----|--- |---WEB-INF
    |----|----|---|---web.xml
    |----|---test
    |----|----|- --java stores all test .java files, such as JUnit test class
    |----|----|---resources test resource file
    |---target target file output location such as .class, .jar, .war File
    |---pom.xml maven project core configuration file

4. Manually build Maven project implementation

4.1 Manually build the Maven Java project

    We must know: Maven itself is a platform-independent open source project, that is to say: Maven can provide jar file support for Maven projects created on any development platform, that is to say: even if it is separated from development platforms such as Eclipse and IDEA, Maven can also be run directly to provide jar file support for the project.

    Then let's manually create, compile, and run an independent Maven project, and through this project, add some other knowledge points about Maven itself.

4.1.1 Create the folder directory of the Maven project

First, let's look at a directory structure:

MavenProjectName:
    |---src
    |----|---main
    |----|----|---java
    |----|----|---resources
    |----|---test
    |----|----|---java
    |----|----|---resources
    |---pom.xml

    Then we first follow this simplest structure, manually create a folder structure on our own disk for saving the Maven project Java files and test files, and write code in this folder, add POM files, and gradually install this project to compile and run.

4.1.2 Configure the pom.xml file of the Maven project

    The pom.xml file of the Maven project is the soul of the Maven project. All important information and support for jar files under a Maven project are configured through this file. Let’s manually configure the pom.xml file (note the encoding format ).

1. Create a pom.xml configuration file under the root folder of the project, and create the following basic structure:

<?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>

The above configuration belongs to the basic configuration method of the pom.xml file in the Maven project, where:

    <modelVersion></modelVersion> tag: indicates the version number of the description specification used by the current Maven project. You don't have to worry about this label. The version number of the description specification used by the mainstream Maven project is version 4.0.0.

2. Configure the project coordinates in the pom.xml file:

    Each Maven project must configure the following content in the pom.xml file, because Maven determines the specific location of a project based on these configuration information, so the information we will configure below is also called the project coordinates of a project.

    How to understand project coordinates: In real life, the concept of coordinates is very popular: the same meal ordered at Yang Guofu Malatang, why can the foreign code brother accurately deliver your portion to you instead of others hands? Just use coordinates. In real life, we use information such as provinces, cities, districts, streets, districts, buildings, units, floors, house numbers and other information to identify our own coordinates, so the takeaway brother can deliver the takeaway to you correctly according to this "coordinates" .

    Similarly, in one of our computers, there may be multiple Java projects at the same time, so how does Maven distinguish these projects? The project coordinates are also used, so it is said that the project coordinates are the unique identifier used by Maven software to identify a Java project.

    Just like I must add cuttlefish balls when I eat spicy soup, and I never eat coriander, Maven software also distinguishes which jar files are needed for this project and which jar files are not needed according to the project coordinates.

    OK! Now you should be able to understand the meaning of the project coordinates, right? So let's introduce how to configure the project coordinates of a Maven project: First, let's explain: the project coordinates are directly configured under the <project></project> tag of the pom.xml file.

The standard structure for describing the coordinates of an item is as follows:

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

The meanings of the configuration information of these labels are as follows:

    <groupId> tag: the unique identifier of the project organization. Generally, it is the name of the company or organization or the name of a large project. Usually, the domain name is inverted, which affects the first-level directory structure installed in the warehouse.
        For example:
            servlet-related jar, its groupId is javax.servlet, javax.servlet is the name of the big project (parent project name).
            Mybatis related jar, its groupId is org.mybatis, org.mybatis is the company name or organization name.
    
    <artifactId> tag: the unique identifier of the project. Generally, it is the project name or sub-project name or module name, which affects the sub-directory structure installed to the warehouse and the name of the package. For the value in the <artifactId> tag, we recommend using the real name of the current project (module).
    
    groupId and artifactId are collectively referred to as "coordinates" to ensure the uniqueness of the project. If you want to get your project to the maven local warehouse, you must search according to these two ids if you want to find your project. groupId is generally divided into multiple sections, here I only say two sections, the first section is the domain, and the second section is the company name. The domain is divided into org, com, cn, etc., among which org is a non-profit organization, and com is a commercial organization. Take an example of the tomcat project of the apache company: the groupId of this project is org.apache, its domain is org (because tomcat is a non-profit project), the company name is apache, and the artifactId is tomcat.

    <version> tag: Indicates the version number of the current project, which affects the final directory structure installed in the warehouse and the name of the package.

    <packaging> tag: Indicates the packaging method of the current project. In addition to the common value "jar", it can also take the value "war", which means that the current project is packaged as a war file. Optional jar: Indicates that the package is packaged as a .jar
        file Pack.
        Optional war: indicates that the package is packaged as a .war file.
        Optional pom: Indicates that the current project is a management project.
        The default is jar.
    
    <classifier> tag: used to indicate some attachment files generated when the current project is packaged and generated.
        More:
    
    How about https://www.cnblogs.com/love-kimi/archive/2012/10/09/2716507.html, there are many tags on it, right? But when you actually create a Maven project, you don't need so many coordinates at all. The coordinate labels that a Maven project must have are only the first 3!
    
    Let's take a look at how to configure the coordinates of our current project: copy the following tag content to the <project></project> tag of the previously created pom.xml file.

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

After copying the above configuration to the pom.xml file, we get the content of such a pom.xml file:

<?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>

    So far, our configuration of project coordinates is complete.

Note on project version numbers:

    The version number used in the <version> tag of the Maven project, in addition to the digital version number 0.0.1, also has a version type: the word SNAPSHOT means a snapshot version. So what are the version types of the project?
    1. snapshot: The snapshot version, that is, the development version. This version of the project cannot be used because it is in the development stage, with incomplete functions and many errors. Eclipse and IDEA will use this version by default when creating Maven projects.
    2. alpha: Internal testing version. This version of the program is not recommended. This version of the program is used for internal testing by developers to find and change bugs.
    3. beta: external test version, the test version released for the user group, although it can be used, it is still unstable and has many bugs, so it is not recommended to use.
    4. release: release version, which means the version recommended by the official, with more comprehensive functions and stable operation, but there may be some bugs, and it can be used normally.
    5. stable: Stable version, which removes most of the bugs and optimizes some functions on the basis of the release version. It is recommended to use.
    6. current: The latest version, not necessarily a stable version, but with the latest features. If there is a corresponding release or stable version, it is recommended to use the first two.
    7. eval: evaluation version, with a one-month or fixed period of use.
    In addition, there are pre, RC, GA and other versions, which will not be described in detail here.

3. Add jar file dependencies in the pom.xml file:

    The purpose of our learning Maven is to let Maven automatically add and manage the required jar files for our projects.

    All dependencies in the current Maven project are configured in the <dependencies> tag, and each dependency is wrapped in a <dependency> tag, which is the coordinate of the dependent jar.

    And before we have introduced how to add the dependency configuration of the jar file required by the project to the pom.xml file, we will not go into details here.

    In order to facilitate the testing of the current project, we add the jar file dependency of the junit-4.12 version in the pom.xml file:

<!--
    所有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>

After adding the above configuration content to the pom.xml file, we get a more comprehensive version of the pom.xml file:

<?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>

    So far, the pom.xml configuration file of the entire Maven project has been completed, let us write some Java code.

4.1.3 Write Java code in Maven project

    The Maven project strictly distinguishes Java source code and test code. These codes will be stored in different locations, and we will also see that Maven compiles and compiles Java source code and test code in the process of compiling and running. Running is also quite different.

1. Write Java source code:

    All Java source codes under the Maven project are stored in the src/main/java folder, so we create the following Java source files and codes under this folder:

HelloMaven.java:

package com.maven;

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

2. Write test code:

    All test codes under the Maven project are stored in the src/test/java folder, so we create the following test classes and test codes in this folder:

HelloMavenTest.java:

package com.maven;

import org.junit.Test;

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

}

    So far, the Java code in our Maven project has been written. In the above steps, what we need to focus on is: the location of the storage path of Java source code and test code in the Maven project.

4.1.4 Compile and run Maven project

    After the Maven project is created, the project needs to be compiled manually. Moreover, because the HelloMaven type created in the Java original code is used in the test code, we must compile the project in the following order: 1. First compile the
        Java original code under the src/main/java folder
        2. Then compile Test code under the src/test/java folder

    Only by compiling in this order can the test code run normally.

1. Compile the Java source code:

    First, we enter the root directory of the Maven project, and then compile the source code in the Maven project through the following command:

mvn compile

    Note: If it is the first time to compile a Maven project, Maven will download the required jar files from the remote central warehouse to the local warehouse.

    If we have configured to use the mirror to download, the download process will be much faster (for demonstration, I deleted all the downloaded jar files in the local warehouse...).

 After the project is compiled successfully, there will be the following results:

    First, the following results will be displayed in the command console:

     Secondly, under the src folder, a new folder named target will appear, which is responsible for saving the bytecode files of all Java files that have been compiled currently.

 2. Compile and run the test code:

    The same command is used to compile and run the test code under the Maven project:

mvn test

    That is to say, when running the above command, Maven will perform the following three operations at the same time:
        1. Go to the central warehouse to download the required jar files to the local according to the jar file dependencies declared in the pom.xml configuration file. in the warehouse.
        2. Compile the test code and generate its corresponding bytecode file.
        3. Directly execute the test method in the test class and print the test result.

The process of downloading the jar file to the local warehouse:

 Compile the test file and run the test method to get the running result:

 3. Clean up the Maven project:

    If you need to clear the bytecode files of the compiled and generated Java source code and test code, we can use the following command:

mvn clean

Maven is cleaning the project:

 Cleanup complete:

 After running this command, Maven will automatically delete the target folder in the project root directory:

     So far, our operations of manually creating, configuring, compiling, and running a Maven project are all over.

4.2 Manually build the Maven Web project

    The Maven Web project just has some more structures than the Maven Java project, and it can be built according to the Maven convention.

4.2.1 Web directory creation

    Create a webapp directory under the src/main directory. The webapp directory is the main directory of the web project.

    After that, it is to operate according to the Web project, so I won't repeat it. 

4.2.2 Creation of HelloServlet

    Create the com.maven.servlet package under the src/main/java directory, and define the HelloServlet class under it.

The HelloServlet class code is as follows:

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 Configuration dependencies and operating environment (detailed later)

<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 Running tests    

    Open HelloMaven in the data and run the test.

    Enter the Maven project directory (the current directory has a pom.xml file), and run the mvn tomcat:run command.

    According to the prompt information above, visit through a browser: http://localhost:8080/HelloMaven/HelloServlet

4.2.5  Maven Web project error handling

    Question 1: There may be jar package conflicts.
        Solution: Add <scope>provided</scope> in the dependencies of jsp and servlet.

    Question 2: The Tomcat built in Maven is 6.0, and this version does not support jdk1.8.
        Configure the tomcat7 plug-in, and configure the maven compilation environment to 1.8.
        Run the mvn tomcat7:run command to start the service. If you continue to use tomcat:run, you will still use Maven's Tomcat6; you will continue to make mistakes...

<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 Command Test

Open the cmd command line, enter the root directory of the hello project and execute the following command to view the changes in the root directory:

#编译:
mvn compile

#清空:
mvn clean

#测试:
mvn test

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

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

Five, Maven warehouse and coordinates

5.1 Maven warehouse overview

    Maven warehouse classification:
        local warehouse: warehouse on the local host.
        Remote warehouse: If you need a plug-in or jar package locally, but the local warehouse does not have it, you will go to the remote warehouse to download it by default. Remote warehouses can be on the Internet or on a local area network.

    The work of Maven needs to download some jar packages from the warehouse. As shown in the figure below, the local Maven project will download jar packages from the remote warehouse (which can be understood as a warehouse on the Internet) through Maven software and store them in the local warehouse. The local warehouse is the local file. Folder, when the jar package is needed for the second time, it will no longer be downloaded from the remote warehouse, because the local warehouse already exists, and the local warehouse can be understood as a cache. With the local warehouse, there is no need to download from the remote warehouse every time.

The following figure describes the types of warehouses in maven:

5.2 Central Warehouse

    Since the original local warehouse is empty, Maven must know at least one available remote warehouse to download the required build when executing the Maven command.

    The central warehouse is Maven's default remote warehouse, serving the entire Internet. It is maintained by the Maven team itself and stores a very complete jar package, which includes most of the world's popular open source project components.

    The central warehouse address is: https://repo.maven.apache.org/maven2.

    Maven's installation file comes with the configuration of the central warehouse by default, which can be found in MAVEN_HOME/lib/maven-model-builder.jar, org\apache\maven\model\pom-4.0.0.xml, which is configured with the central warehouse address.

<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 Private Warehouse

    A special kind of remote warehouse, which is a warehouse set up in a local area network, mainly for team collaboration and development, it can be understood as the warehouse of your own company, also called a private server.

    Configure the Alibaba Cloud mirror. The Alibaba Cloud mirror is actually Ali's private warehouse, which is only open for everyone to use.

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

Benefits of using private servers:

    Save your own external network bandwidth: Establishing a private server can reduce the organization's own expenses, and a large number of repeated requests for external remote warehouses will consume a lot of bandwidth. After using the private server to proxy external warehouses, the external repeated component downloads can be eliminated, that is, the external network bandwidth pressure.

    Accelerate the construction of Maven: It is undoubtedly time-consuming to continuously request external warehouses, but some internal mechanisms of Maven (such as snapshot detection) require Maven to continuously check the data of remote warehouses when executing builds. Therefore, when many remote warehouses are configured, the speed of the build will be greatly reduced. Using a private server can solve this problem very well.

    Deploying third-party components: What should I do if a certain component cannot be downloaded from an external remote warehouse? There are many such examples. For example, the private components generated within the organization must not be obtained from the external warehouse, and Oracle's JDBC driver cannot be released to the central warehouse on the external network due to copyright reasons. After the private server is established, these components can be deployed to the local private server for use by internal Maven projects.

    Improve stability and enhance control: Maven builds depend on remote warehouses, so when the Internet is unstable, Maven builds will also become unstable, or even fail to build.
After using the private server, Maven can run normally even if there is no Internet connection temporarily, because a large number of components are cached in the private server. In addition, some private server software (such as: Nexus) also provides many additional functions, such as rights management, RELEASE/SNAPSHOT distinction, etc., administrators can perform some more advanced control on the warehouse.

    Reduce the load on the central warehouse: millions of requests and storage of several terabytes of data require considerable financial resources. Using private servers can avoid many repeated requests to the central warehouse.

5.4 Local warehouse

    When Maven performs compilation or testing, it always uses the local repository's dependencies based on coordinates if it needs to use them. By default, regardless of Linux or Windows, each user has a repository directory named .m2/respository/ under their own user directory.

    Download the jar package and Maven information from the central warehouse or private warehouse, or build the dependent warehouse of the jar package yourself.

    Default location: ~/.m2/repository

    Modify the local warehouse location: configure the local warehouse location in the MAVE_HOME/conf/settings.xml file.

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

5.4 Maven coordinates

    There are a large number of dependent jar packages in the Maven warehouse, which need to be uniquely identified to build a unified specification. With a unified specification, you can accurately find the required dependencies from the Maven repository.

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

6. Using Maven in eclipse

6.1 Install Maven plugin

    Open eclipse, click the menu Help -> Install New Software, and click the Add button.
        Name: m2e 
        Location: http://download.eclipse.org/technology/m2e/releases

Note: Since the new version of eclipse has directly integrated Maven, there is no need to install the m2eclipse plug-in.

6.2 Configure Maven in eclipse

    1. Open eclipse, click the menu Window -> Preferences, find Maven -> Installations, modify the default Maven, and click Add to add your own Maven.

    Note: If the built-in Maven version is 3.3+, you can omit this step and use the default one. Of course, you can also use Maven installed by yourself.

    2. Click User Settings, and re-select the User Settings file and the Local Repository path.

    Note: Normally, eclipse will use the settings/xml under the .m2 folder under the user directory by default, and automatically recognize the configuration information of the settings.xml file.

     3. Configure and download the source code and documentation of the jar package (if necessary).
    
    Note: If you check the following two items, when downloading dependencies, the source code and documents corresponding to the dependencies will be downloaded together (personally, it is not recommended to check).

6.3 Create Maven project in eclipse

6.3.1 Create a Maven Java project

    1. Click File -> New -> Project and find Maven -> Maven Project.

     2. Click Next and select Maven archetype (prototype).

     3. The default selection of Catalog is All Catalogs, which means all prototypes. Select Internal in the Catalog to indicate the built-in type of Maven (provided by the official website).
    
        If it is a Maven Java project, choose maven-archetype-quickstart.
        If it is a Maven Web project, select maven-archetype-webapp.

     4. Enter Maven coordinates.
        Group Id: Inversion of the company domain name.
        Artifact Id: project name.
        Version: version number.
        Package: Defined as needed.

    5. Maven will automatically download the dependent packages required by the project, and reconstruct the project structure after completion.

    Note: The junit dependency version introduced by eclipse by default is 3.8, and we define it as 4.12.

     6. Delete the automatically generated App.java and AppTest.java, and write the project code.

Project source code 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 + "]";
    }

}

Project test code 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. After the code is written, right-click the project Run As to select the Maven command to be executed.

 Execute Maven Test:

     Note: We found that there is no Maven package command in eclipse. We can call up the command configuration interface in eclipse through Maven build, and let you configure the execution target yourself on this plug-in.

6.3.2 Create a Maven Web project

    1. According to the previous steps, select maven-archetype-webapp when selecting Maven archetype (prototype), and create a Maven Web project.

 After the Maven Web project is established, the directory structure is as follows:

    After building the Maven project, a small red cross will appear on the project. By observing the prompt information of the error location in the JSP file, we found that it is actually caused by not importing the relevant JAR files of Java EE in our project.
    
    In the next operation, we have two options:
        1.1 Manually import Java EE-related Jar packages through Build Path.
        1.2 Configure the dependencies of these Jar packages through Maven's pom.xml file.

    We are using a Maven project! What a shame to manually import the Jar package! Properly choose to use Maven to configure dependencies!

    2. It is necessary to manually create source code directories such as src/main/java, src/test/java, src/test/resources, etc.
    
    Note: src/main/webapp is the root directory where the web is stored, similar to the WebContent directory. However, the index.jsp and web.xml in the WEB-INF directory need to be deleted and rebuilt because the version is too early.

     3. Configure the dependencies of these Jar packages through Maven's pom.xml file.
        Open: https://mvnrepository.com, and search for javaee keywords, choose the most used option:

     Next, select the Java EE class library based on the Java 8 version:

     Copy the dependency declaration code into the pom.xml file of the project:

Or configure individually:

<!-- 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>

Local tomcat deploys Maven Web project:

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

Maven command to deploy Maven Web project:

    Add the tomcat7-maven-plugin plug-in in pom.xml.
    
    Note: If your version is tomcat7-maven-plugin 2.0, since it does not support jdk 1.8, just replace it with 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>

    In this way, the configuration is complete, remember to change Goals to tomcat7:run.

6.4 Solutions for executing Maven command errors

Execute the Maven command and report an error:

    Cause of error: The execution environment of eclipse is jre by default, and the execution environment of Maven requires JDK instead of jre.

    1. Click Window -> Preferences -> Java -> Installed JRES -> Add -> Standard VM -> choose the JDK you installed.

     2. Right-click the current project Properties -> Java Build Path -> Libraries -> Add Library -> JRE System Library -> check Workspace default JRE.

     Other solutions: https://blog.csdn.net/weixin_44405634/article/details/100837978

7. Using Maven in IDEA

7.1 IDEA has its own Maven plug-in, no need to install

7.2 Configure Maven in IDEA

    1. Open IDEA, click the menu File -> Settings, find Build, Execution, Deployment -> Build Tools -> Maven, and modify the default Maven.

    Note: If the built-in Maven version is 3.3+, you can omit this step and use the default one. Of course, you can also use Maven installed by yourself.

    2. In Build, Execution, Deployment -> Build Tools -> Maven -> Importing, configure the source code, documentation and annotations of the jar package to be automatically downloaded.

    Note: If you check the following two items, when downloading dependencies, the source code and documents corresponding to the dependencies will be downloaded together (personally, it is not recommended to check).

7.3 Create a Maven project in IDEA

7.3.1 Create Maven Java project

    1. Click File -> New -> Project, find Maven, check Create from archetype, select the required archetype, quickstart builds a Java project, and webapp builds a JavaWeb project.

     2. Fill in the maven coordinates, group ID: company name, artifactID: project name, version: version number, the next step until completion.

     3. Maven will automatically download the dependent packages required by the project, and reconstruct the project structure after completion.

    4. Complete the project structure according to the Maven agreement.
        Create a resources folder under the main directory, Mark Directory as "Resources Root".
        Create a resources folder under the test directory, Mark Directory as "Test Resources Root".

    Note: In the new version of IDEA, when we create resources, there will be corresponding prompts.

    5. Delete the automatically generated App.java and AppTest.java, and write the project code.

    6. After writing the code, fold the Maven Projects window on the right side of IDEA, select the command under Lifecycle, and click the Run button (double-click the command) to run it.

    Note: If there is no Maven Projects folding window on the right, click View -> Appearance -> check Tool Window Bars.

7.3.2 Modify Maven's default JDK compilation environment

    The default JDK compilation environment of the project created by Maven is 1.5. You can use the Maven compilation plug-in in the pom or change the JDK version of the project through global configuration. If the version is not specified, it is easy to have a version mismatch problem, which may cause the problem of compilation failure.

Method 1: Modify the project level 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>

    The above configuration only takes effect for the current project (module).

Method 2: Modify maven's settings.xml file (global)

<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> 

    The above configuration is at the global level, that is, any project (module) created based on the current maven environment will take effect.

7.3.3 Create a Maven Web project

    1. Follow the previous steps to create a Maven Web project.

 After creating the Maven web project, the directory structure is as follows:

    2. Manually create source code directories such as src/main/java, src/mian/resources, src/test/java, src/test/resources, etc., and first create a Directory (ordinary directory).

    Note: When the new version of IDEA creates a directory with a specified name, it will directly prompt, which is very easy to use.

     3. Right-click the directory and select Mark Directory as to convert the directory to the corresponding source code directory. Where Sources Root corresponds to the src/main/java directory, Test Sources Root corresponds to the src/test/java directory, Resources Root corresponds to the src/main/resources directory, and Test Resources Root corresponds to the src/test/resources directory

     4. src/main/webapp is the root directory for storing the web, similar to the WebContent directory. However, the index.jsp and web.xml in the WEB-INF directory need to be deleted and rebuilt because the version is too early.

jsp template:

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

web.xml template:

<?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. Deploy and test.
        The local tomcat deploys the Maven Web project.
        Maven command to deploy Maven web projects.

8. Maven dependency scope

    Based on the Maven Web project we created before, add dependencies commonly used in Web development.
        1. mysql driver
        2. servlet
        3. jsp
        4. jstl
        5. gson, etc.

The directory structure is as follows:

The Student class code is as follows:

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 +
                '}';
    }
}

The GsonServlet class code is as follows:

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);
    }
}

The StudentTest class code is as follows:

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);
    }
}

The pom.xml file depends on the following:

<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>

    Entity classes, servlets, and test class codes have nothing to explain, but when we introduce dependencies, we will find that some dependencies have scope tags, and some do not.

    The <scope> tag is to control the scope of use of the dependency element. In layman's terms, it is to control in which scopes the Jar package is loaded and used.

8.1 Overview of Dependency Scope

Understanding of three classpaths:

    1. Compile classpath: corresponding to the classes directory under the target directory, only the compiled content under the src/main directory is stored.
        src/main/java: The bytecode files generated after compilation are placed in the classes directory (with package structure).
        src/main/resources: It will not be compiled and placed directly in the classes directory.

    2. Test classpath: corresponding to the test-classes directory under the target directory, only the compiled content under the src/test directory is stored.
        src/test/java: The bytecode files generated after compilation are placed in the test-classes directory (with package structure).
        src/test/resources: It will not be compiled and placed directly in the test-classes directory.
    
    3. Running classpath: The bytecode file storage directory when the project is running. For example the Web project /WEB-INF/classes directory.
    
    Note:
        1. Packages cannot be created under the resources directory, only folders can be created. If we create the folder com.maven.servlet, only a folder called com.maven.servlet is created.
        2. Under the resources directory, the same directory structure as that under the main directory can be defined.
        3. The same files as those under the main directory cannot be defined under the resources directory.
        4. The Java source code under the resources directory will not be compiled, and it is not recommended to put the Java source code in the resources directory.

     The dependencies introduced into the classpath at different stages of the Maven project are different.
        When compiling, Maven will introduce compilation-related dependencies into the classpath.
        When testing, Maven will introduce test-related dependencies into the classpath.
        At runtime, Maven will introduce runtime-related dependencies into the classpath.
    
    The scope of dependencies is used to control the use of the three classpaths that depend on compiling the classpath, testing the classpath, and running the classpath.

8.2 Depending on the value of the range

    Maven’s life cycle includes compiling, testing, and running these processes, so obviously some dependencies are only used for testing, such as junit; some dependencies are not used for compilation, but can only be used when running. For example, the driver package of mysql is used during compilation. (The JDBC interface is used at compile time), but at run time; there are some dependencies, which are used at compile time, but do not need to be provided at run time, because some containers have already provided them, such as servlet-api in It is already provided in tomcat, all we need is to provide it at compile time. To sum up, in POM 4, <scope> is also introduced in <dependency>, which mainly manages the deployment of dependencies. There are roughly compile, provided, runtime, test, system and so on.
        
    compile: compile dependency scope.
    test: Test dependency scope.
    provided: The dependency scope is provided.
    runtime: Runtime dependency scope. (Separation of interface and implementation)
    system: System dependent scope. A jar imported from a non-local warehouse and stored in a certain path of the system. (Generally not used)
    import: Import dependent scope. When using dependencyManagement, you can import dependency configurations. (later explanation)

Dependency scope compile classpath valid Test classpath is valid Running classpath works example
compile Y Y Y spring-croe
test N Y N junit
provided Y Y N servlet-api
runtime N Y Y jdbc

compile (default)

    Meaning: compile is the default value, if no scope value is specified, the default value of this element is compile. The dependent project needs to participate in the compilation, testing, packaging, running and other stages of the current project. Dependent projects are usually included when packaging.

    Demonstration: The scope value of gson is the default compile, if it is changed to test, then gson will not be found during compilation, and an error will be reported.

provided

    Meaning: The dependent project can theoretically participate in the stages of compilation, testing, and operation, which is equivalent to compile, but the action of exclude is performed in the repackaging stage. 

    Applicable scenarios: For example, if we are developing a web application, we need to rely on servlet-api.jar at compile time, but we don't need the jar package at runtime, because this jar package has been provided by the application server, at this time we need Use provided for range modification.

    Demonstration: Change the scope value of gson to provided, there is no problem in compiling and testing, but an error is reported when running, because the application server does not provide the jar package of gson.

runtime

    Meaning: Indicates that the dependent project does not need to participate in the compilation of the project, but will participate in the testing and running of the project. Compared with compile, the dependent project does not need to participate in the compilation of the project.

    Applicable scenarios: For example, we don't need the JDBC API jar package when compiling, but we only need the JDBC driver package when running.

test

    Meaning: Indicates that the dependent project only participates in test-related work, including compilation and execution of test code.

    Applicable scenarios: For example, Junit testing.

    Demo: Unable to use unit tests in src/main/java.

system

    Meaning: The system element is similar to the provided element, but the dependent item will not be searched from the maven warehouse, but obtained from the local system, and the systemPath element is used to specify the path of the jar file in the local system. For example:

<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>

import (understand)

    It is only used in <dependencyManagement>, which means importing dependency configuration from other pom, for example (B project imports package configuration in A project):

    Presumably, when you are doing SpringBoot applications, you will have the following code:

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

    Inherit a parent module, and then introduce the corresponding dependencies.

    If say, I do not want to inherit, or I want to inherit more than one, how to do? We know that Maven's inheritance, like Java's inheritance, cannot achieve multiple inheritance. If 10, 20 or more modules inherit from the same module, then according to our previous practice, the dependencyManagement of this parent module will contain a large number of rely. If you want to classify these dependencies for clearer management, it is impossible, and import scope dependencies can solve this problem. You can put dependencyManagement in a separate pom specially used to manage dependencies, and then import dependencymanagement through import scope dependencies in modules that need to use dependencies. For example, you can write such a pom for dependency management:

<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>

Then I can introduce this dependency management configuration through non-inheritance:

<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>

Note: import scope can only be used in dependencyManagement;

    In this way, the pom of the parent module will be very clean, and the dependencies are managed by the special packaging as the pom, which also conforms to the principle of single responsibility in object-oriented design. Additionally, we were able to create multiple such dependency management poms to manage dependencies in a more granular way. This practice is also somewhat similar to using composition instead of inheritance in object-oriented design.

    So, how to use this method to solve the inheritance problem of 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>

    With this configuration, your own project does not need to inherit the module of SpringBoot, but can inherit the module of your own project.

9. Maven dependency delivery

9.1 Dependency transfer

Everyone needs to understand a problem: All the jars in the Maven warehouse are actually a Java project in essence, but they are just packaged into a jar package and placed in the Maven warehouse. Since it is a Java project, this project may also use some third-party jar package.

When we introduce certain jar packages, the jar packages that these jar packages depend on will also be introduced, which is dependency transfer.

    For example, there is a Commons-logging project, the project Spring-core depends on Commons-logging, and the project user-service depends on Spring-core. Then we can say that user-service also depends on Commons-logging. In other words, the dependency relationship is: user-service—>Spring-core—>Commons-logging

    When we execute the project user-service, we will automatically download and import Spring-core and Commons-logging into the jar package folder of the user-service project, which is the transitivity of dependencies.

The complete structure of dependency:

<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>

    By setting <optional>true</optional>, it means that the dependency is optional and will not be passed by the dependency.

Example verification:

    Introduce dependency spring-core.

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

The result is as follows:

    After careful observation, it is also found that there are more commons-logging:commons-logging:1.2 at this time, which involves "dependence".

    When the A jar package needs to use the classes in the B jar package, we say that A has a dependency on B. The current project will go to the local warehouse to find the jar packages it depends on according to the coordinates.

    Through the Maven warehouse, we can find that spring-core relies on 5 jars when compiling, but only one is passed in as a dependency, because the optional tag is configured.

    Note: The optional tag can only be set in your own project and not passed down (if we package the project as a jar package, some dependencies in our project will not be passed down), if you don’t want to use the dependencies passed in by other projects , you can use dependent transitive exclusions.

9.2 Exclusions from transitive dependencies

    Sometimes in order to ensure that the program is correct, indirect dependencies that may be repeated can be excluded.

    Exclusion of dependency transfer There are two types of exclusion:
        1. Exclude dependencies through configuration files.
        2. Maven automatically excludes duplicate dependencies.

 For example: C -> B -> A, if you don't want to download A when you don't want to execute C, then we can use the <exclusions> tag

<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>

    In general, we don't write dependency exclusions ourselves, unless there are some special circumstances.

    If: the hamcrest-core:1.3 that junit depends on has a version problem, and we don’t want the hamcrest-core:1.3 that junit depends on, then we can exclude it through exclusion.

<!-- 引入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>

Note: It must be in the same <dependency></dependency>scope as the original package that originally exported the dependency.

    After relying on excluding hamcrest-core, there must be a problem with junit, then we need to find a hamcrest-core without version problems and then introduce it.

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

Scenarios that depend on exclusions:

    1. Project A depends on project B, but when project A does not completely depend on project B, that is, project A only uses part of the functions of project B, and it happens that the realization of this part of the functions of project B does not need to depend on project C. At this time, project A should exclude the dependency on project C.

    2. Version mismatch: There is a version mismatch between the jar package passed in and the jar actually used, causing the project to run abnormally.

    3. Encapsulate public modules: use the API in a certain jar, if there are unnecessary transitive dependencies in this jar, you can pass them by excluding the dependencies.

9.3 Dependency conflict and resolution

    Dependency conflict: A project A depends on X through different dependency delivery paths. If the versions of X delivered under different paths are different, which version of the X package should A import?

    Since there are multiple versions of the dependent content, if a certain POM depends on multiple versions, it is called a dependency conflict.

    Dependency conflicts follow two principles:
        1. Short-circuit priority (dependant content, the smaller the number of transfers, the higher the priority).
        2. Declaring first takes precedence (in POM.xml, whichever dependent content declaration dependency comes first, takes precedence.

Example verification:

    Introduce the following dependencies:

<!-- 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>

    We will find that we have introduced spring-core, but beans, context, and aop in context all rely on spring-core. So will multiple jars be introduced into the project? 

    the answer is negative. Actually Maven only introduces a spring-core.

 Conflict resolution:

    1. If the lengths of the dependent paths are different, the shortest path principle is adopted:
        A—>B—>C—>D—>E—>X(version 0.0.2)
        A—>F—>X(version 0.0.1)
        Then A depends on X (version 0.0.1).

    2. In the case of the same dependency path length, the principle of first declaration is adopted:
        A—>E—>X(version 0.0.1)
        A—>F—>X(version 0.0.2)
        is in <dependencies> of project A In </dependencies>, which one of E and F is declared first, A depends on which path's X.

10. Maven life cycle

Maven's life cycle is to abstract and unify all construction processes. It includes almost all construction steps such as cleaning, initialization, compilation, testing, packaging, integration testing, verification, deployment and site generation of the project.

Maven's life cycle is abstract, that is, the life cycle does not do any actual work, and the actual task is completed by the plug-in, similar to the template method in the design pattern.

10.1 Three life cycles

    Maven has three sets of independent life cycles, namely clean, default and site.
        1. Clean: Clean Lifecycle performs some cleaning work before the real build.

        2. default: Default Lifecycle builds the core parts, such as compilation, testing, packaging, deployment, and so on.

        3. site: Site Lifecycle generates project reports, sites, and release sites.

    Each life cycle contains some phases, these phases are sequential, and the later phases depend on the previous phases, and the most direct interaction between users and Maven calls these life cycle phases.

    Compared with the front and rear dependencies of the life cycle stages, the three life cycles themselves are independent of each other. Users can only call a certain stage of the clean life cycle, or only call a certain stage of the default life cycle without affecting other life cycles. cycle has any effect.

10.2 clean life cycle

    The clean life cycle, which includes the following stages:
        1. Pre-clean: Perform some work that needs to be completed before clean.

        2. clean: Remove all files generated by the previous build.

        3. post-clean: Perform some work that needs to be completed immediately after clean.

    The clean in mvn clean is the clean above. In a life cycle, when a certain stage is run, all the previous stages will be run. That is to say, if mvn clean is executed, the following two life cycle stages will be run:
        pre -clean, clean
        
    If we run mvn post-clean, we run the following three life cycle phases:
        pre-clean, clean, post-clean
        
    This is a very important rule of Maven, which can greatly simplify the input of the command line.

10.3 default life cycle

This is the main life cycle of Maven, which is used to build applications, and consists of the following 23 phases:

life cycle stage describe
validate (validate) Verify that the project is correct and has all the necessary information to complete the project's build process.
initialize (initialize) Initialize build state, such as setting property values.
generate-sources (generate source code) Generate any source code included in the compile phase.
process-sources (process source code) Process source code, say, filter arbitrary values.
generate-resources (generate resource files) Generate resource files that will be included in the project bundle.
process-resources (process resource files) Copy and process resources to the target directory, best prepared for the packaging phase.
compile (compile) Compile the source code of the project.
process-classes (processing class files) Process the files generated by compilation, such as improving and optimizing the bytecode of Java class files.
generate-test-sources (generate test source code) Generate any test source code included in the compile phase.
process-test-sources (process test sources) Handle test source code, for example, to filter arbitrary values.
generate-test-resources (generate test resource files) Create resource files for testing.
process-test-resources (process test resource files) Copy and process test resources to target directory.
test-compile (compile test source code) Compile the test source code into the test target directory.
process-test-classes (process test class files) Process the files generated by compiling the test source code.
test (test) Run the tests using a suitable unit testing framework (Juint is one of them).
prepare-package (prepare to package) Before the actual packaging, perform any necessary operations to prepare for packaging.
package Package the compiled code into a distributable format file, such as a JAR, WAR, or EAR file.
pre-integration-test (before integration testing) Perform necessary actions before executing integration tests. For example, build the required environment.
integration-test (integration test) Process and deploy the project into an environment where integration tests can be run.
post-integration-test (after integration testing) Perform necessary actions after execution of integration tests is complete. For example, clean up the integration test environment.
verify (verify) Run arbitrary checks to verify that the project package is valid and meets quality standards.
install Install the project package to the local repository so that the project package can be used as a dependency of other local projects.
deploy Copy the final project package to a remote repository to share with other developers and projects.

The important stages are as follows:

stage deal with describe
validate validate verification project Verify that the project is correct and that all required related resources are available, which includes validation of the pom.xml file tree.
compile compile execute compile Source code compilation is done at this stage.
Test Test test Run the tests using an appropriate unit testing framework such as JUnit. These tests do not require packaging and deployment.
packaging package Pack Create JAR/WAR package as defined in pom.xml mentioned package.
check verify examine All checks are run to verify that the package is valid and meets quality standards.
install install Install Install the packaged project to the local repository for use by other projects.
deploy deploy deploy Copy the final project package to the remote warehouse to share with other developers and projects.

    When running any stage, all the stages before it will be run, which is why when we run mvn install, the code will be compiled, tested, and packaged. In addition, Maven's plug-in mechanism is completely dependent on Maven's life cycle, so understanding the life cycle is very important.

experiment:

    Package a Maven Java project into a jar package and import it into another Maven project.

    1. Executing install on the Maven Java project will package Maven Java into a jar package and install it in the local warehouse.

    2. Import the jar installed in the local warehouse through the project coordinates.

Notice:

    If both projects are at the Project level and want to depend on each other, they must be imported through dependencies after packaging. But if the Module level of the two projects can be imported directly, we will explain it later.

Executes two lifecycle phases simultaneously:

    mvn clean install

    Maven will execute the clean command first, and then execute the install command.

10.4 site life cycle

    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>

Guess you like

Origin blog.csdn.net/ligonglanyuan/article/details/123988592