欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Boot 2(一):项目搭建

程序员文章站 2022-07-10 18:13:11
...

Spring Boot 简介

Spring Boot 可以帮助我们轻松创建可独立运行的,适用于生产环境的基于 Spring 的应用程序。

Spring Boot 帮我们整合了各种开发包,并解决以往我们在开发 Java Web 项目时所面临的配置繁琐问题,相当于一个“脚手架”。

创建 Spring Boot 项目

要初始创建一个 Spring Boot 项目,最简单的方式就是使用官方的 Spring Initializr

Spring Boot 2(一):项目搭建

因为使用 Spring Initializr 创建实现太简单,没什么好说的。下面我们使用手动创建来学习 Spring Boot 项目,加深理解。

创建 Maven 项目

首先,使用 IntelliJ IDEA 创建一个原始的 Maven 项目,这个太简单了,就不细说了,其中要注意的是我们对 Maven 的配置。我在当前用户主目录的 .m2 目录下,放置如下内容的 Maven 配置文件 settings.xml

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

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

<!--
 | This is the configuration file for Maven. It can be specified at two levels:
 |
 |  1. User Level. This settings.xml file provides configuration for a single user,
 |                 and is normally provided in ${user.home}/.m2/settings.xml.
 |
 |                 NOTE: This location can be overridden with the CLI option:
 |
 |                 -s /path/to/user/settings.xml
 |
 |  2. Global Level. This settings.xml file provides configuration for all Maven
 |                 users on a machine (assuming they're all using the same Maven
 |                 installation). It's normally provided in
 |                 ${maven.conf}/settings.xml.
 |
 |                 NOTE: This location can be overridden with the CLI option:
 |
 |                 -gs /path/to/global/settings.xml
 |
 | The sections in this sample file are intended to give you a running start at
 | getting the most out of your Maven installation. Where appropriate, the default
 | values (values used when the setting is not specified) are provided.
 |
 |-->
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ${user.home}/.m2/repository
  <localRepository>/path/to/local/repo</localRepository>
  -->

  <localRepository>D:\MvnRepository</localRepository>

  <!-- interactiveMode
   | This will determine whether maven prompts you when it needs input. If set to false,
   | maven will use a sensible default value, perhaps based on some other setting, for
   | the parameter in question.
   |
   | Default: true
  <interactiveMode>true</interactiveMode>
  -->

  <!-- offline
   | Determines whether maven should attempt to connect to the network when executing a build.
   | This will have an effect on artifact downloads, artifact deployment, and others.
   |
   | Default: false
  <offline>false</offline>
  -->

  <!-- pluginGroups
   | This is a list of additional group identifiers that will be searched when resolving plugins by their prefix, i.e.
   | when invoking a command line like "mvn prefix:goal". Maven will automatically add the group identifiers
   | "org.apache.maven.plugins" and "org.codehaus.mojo" if these are not already contained in the list.
   |-->
  <pluginGroups>
    <!-- pluginGroup
     | Specifies a further group identifier to use for plugin lookup.
    <pluginGroup>com.your.plugins</pluginGroup>
    -->
  </pluginGroups>

  <!-- proxies
   | This is a list of proxies which can be used on this machine to connect to the network.
   | Unless otherwise specified (by system property or command-line switch), the first proxy
   | specification in this list marked as active will be used.
   |-->
  <proxies>
    <!-- proxy
     | Specification for one proxy, to be used in connecting to the network.
     |
    <proxy>
      <id>optional</id>
      <active>true</active>
      <protocol>http</protocol>
      <username>proxyuser</username>
      <password>proxypass</password>
      <host>proxy.host.net</host>
      <port>80</port>
      <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
    </proxy>
    -->
  </proxies>

  <!-- servers
   | This is a list of authentication profiles, keyed by the server-id used within the system.
   | Authentication profiles can be used whenever maven must make a connection to a remote server.
   |-->
  <servers>
    <!-- server
     | Specifies the authentication information to use when connecting to a particular server, identified by
     | a unique name within the system (referred to by the 'id' attribute below).
     |
     | NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are
     |       used together.
     |
    <server>
      <id>deploymentRepo</id>
      <username>repouser</username>
      <password>repopwd</password>
    </server>
    -->

    <!-- Another sample, using keys to authenticate.
    <server>
      <id>siteServer</id>
      <privateKey>/path/to/private/key</privateKey>
      <passphrase>optional; leave empty if not used.</passphrase>
    </server>
    -->
  </servers>

  <!-- mirrors
   | This is a list of mirrors to be used in downloading artifacts from remote repositories.
   |
   | It works like this: a POM may declare a repository to use in resolving certain artifacts.
   | However, this repository may have problems with heavy traffic at times, so people have mirrored
   | it to several places.
   |
   | That repository definition will have a unique id, so we can create a mirror reference for that
   | repository, to be used as an alternate download site. The mirror site will be the preferred
   | server for that repository.
   |-->
  <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>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
    </mirror>
  </mirrors>

  <!-- profiles
   | This is a list of profiles which can be activated in a variety of ways, and which can modify
   | the build process. Profiles provided in the settings.xml are intended to provide local machine-
   | specific paths and repository locations which allow the build to work in the local environment.
   |
   | For example, if you have an integration testing plugin - like cactus - that needs to know where
   | your Tomcat instance is installed, you can provide a variable here such that the variable is
   | dereferenced during the build process to configure the cactus plugin.
   |
   | As noted above, profiles can be activated in a variety of ways. One way - the activeProfiles
   | section of this document (settings.xml) - will be discussed later. Another way essentially
   | relies on the detection of a system property, either matching a particular value for the property,
   | or merely testing its existence. Profiles can also be activated by JDK version prefix, where a
   | value of '1.4' might activate a profile when the build is executed on a JDK version of '1.4.2_07'.
   | Finally, the list of active profiles can be specified directly from the command line.
   |
   | NOTE: For profiles defined in the settings.xml, you are restricted to specifying only artifact
   |       repositories, plugin repositories, and free-form properties to be used as configuration
   |       variables for plugins in the POM.
   |
   |-->
  <profiles>
    <!-- profile
     | Specifies a set of introductions to the build process, to be activated using one or more of the
     | mechanisms described above. For inheritance purposes, and to activate profiles via <activatedProfiles/>
     | or the command line, profiles have to have an ID that is unique.
     |
     | An encouraged best practice for profile identification is to use a consistent naming convention
     | for profiles, such as 'env-dev', 'env-test', 'env-production', 'user-jdcasey', 'user-brett', etc.
     | This will make it more intuitive to understand what the set of introduced profiles is attempting
     | to accomplish, particularly when you only have a list of profile id's for debug.
     |
     | This profile example uses the JDK version to trigger activation, and provides a JDK-specific repo.
    <profile>
      <id>jdk-1.4</id>

      <activation>
        <jdk>1.4</jdk>
      </activation>

      <repositories>
        <repository>
          <id>jdk14</id>
          <name>Repository for JDK 1.4 builds</name>
          <url>http://www.myhost.com/maven/jdk14</url>
          <layout>default</layout>
          <snapshotPolicy>always</snapshotPolicy>
        </repository>
      </repositories>
    </profile>
    -->

    <!--
     | Here is another profile, activated by the system property 'target-env' with a value of 'dev',
     | which provides a specific path to the Tomcat instance. To use this, your plugin configuration
     | might hypothetically look like:
     |
     | ...
     | <plugin>
     |   <groupId>org.myco.myplugins</groupId>
     |   <artifactId>myplugin</artifactId>
     |
     |   <configuration>
     |     <tomcatLocation>${tomcatPath}</tomcatLocation>
     |   </configuration>
     | </plugin>
     | ...
     |
     | NOTE: If you just wanted to inject this configuration whenever someone set 'target-env' to
     |       anything, you could just leave off the <value/> inside the activation-property.
     |
    <profile>
      <id>env-dev</id>

      <activation>
        <property>
          <name>target-env</name>
          <value>dev</value>
        </property>
      </activation>

      <properties>
        <tomcatPath>/path/to/tomcat/instance</tomcatPath>
      </properties>
    </profile>
    -->
  </profiles>

  <!-- activeProfiles
   | List of profiles that are active for all builds.
   |
  <activeProfiles>
    <activeProfile>alwaysActiveProfile</activeProfile>
    <activeProfile>anotherAlwaysActiveProfile</activeProfile>
  </activeProfiles>
  -->
</settings>

上述配置文件中,我只更改了本地仓库的地址和使用了阿里云 Maven 镜像仓库两个配置。

加入 Maven Wrapper

当我们使用 Spring Initializr 创建 Spring Boot 项目时,会发现在项目根目录下存在 .mvn 文件夹、mvnwmvnw.cmd 文件。这是什么东东?有何作用?

这其实是从 Gradle 借鉴而来的 Maven Wrapper。Maven Wrapper 包含了执行 Maven 项目构建所需要的一切,从而使用户可以在不安装 Maven 的情况下,执行 Maven 项目的构建操作,同时也保证了不同用户之间可使用相同 Maven 版本进行构建。

在项目根目录下执行以下命令,可使用插件(Maven Wrapper plugin)自动创建 Maven Wrapper:

mvn -N io.takari:maven:0.7.6:wrapper -Dmaven=3.6.0

对以上命令作如下两点说明:

  • 选项 -N:代表 –non-recursive,这样 Maven Wrapper 只会应用于当前目录的主项目,而不会应用于任何子模块
  • 参数 maven:用于指定用于构建项目的 Maven 版本。也可以通过对 .mvn/wrapper/maven-wrapper.properties 中的 distributionUrl 属性值进行更改

在执行完上面命令后,即会在项目根目录下生成以下三个文件/文件夹:

  • .mvn 文件夹:
    • wrapper/maven-wrapper.jar:运行脚本时会通过该 jar 执行 Maven 的下载和调用。如果没有找到此 jar,则脚本会从 .mvn/wrapper/maven-wrapper.properties 中的 wrapperUrl 属性值所指定的地址下载,并存放到此处
    • wrapper/maven-wrapper.properties:配置文件。主要涉及以下两个配置项:
      • distributionUrl:指定从何处下载什么版本的 Maven。默认为 distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip。注意,不要使用阿里云 Maven 仓库去下载 zip(distributionUrl=http://maven.aliyun.com/nexus/content/groups/public/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip)。因为通过 Maven Wrapper 从阿里云下载的 zip 文件,都是损坏的
      • wrapperUrl:指定未找到 maven-wrapper.jar 时,应该从何处下载。默认为 wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar。可将此项配置为从阿里云 Maven 仓库下载(wrapperUrl=http://maven.aliyun.com/nexus/content/groups/public/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
    • wrapper/MavenWrapperDownloader.java:如果通过 curlwget 都无法下载 maven-wrapper.jar,则最后会编译该文件,然后执行此生成的类来下载
  • mvnw 文件:Unix 中运行的 Shell 脚本文件
  • mvnw.cmd 文件:Windows 中运行的脚本文件

使用 Maven Wrapper

要使用 Maven Wrapper,只需在项目构建中使用 mvnw 命令代替 mvn 命令即可。如果在 ~/.m2 目录下没有找到 .mvn/wrapper/maven-wrapper.properties 中所指定版本的 Maven,则 Maven Wrapper 首先会下载指定版本的 Maven(存放于 ~/.m2/wrapper),再使用该版本的 Maven 执行相关命令。

主要涉及两个操作系统平台中的操作:

  • Unix 系统:./mvnw dependency:tree
  • Windows 系统:mvnw dependency:tree,在 Windows 中 mvnw.cmd 文件的后缀 .cmd 可以省略

注意:为使 mvnw 使用本地的 Maven 配置,需要将 settings.xml 放置在当前用户主目录的 .m2 目录下

项目编码

关于项目编码部分,除了我认为比较重要的代码片段加了注释外,其它详细请参考 Spring Boot Reference Guide。官方文档写得很详细,很棒!!!

项目结构如下:

Spring Boot 2(一):项目搭建

项目 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.wuxianjiezh</groupId>
  <artifactId>spring-boot-demo</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>spring-boot-demo</name>
  <description>Demo project for Spring Boot</description>

  <!-- Inherit defaults from Spring Boot -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.4.RELEASE</version>
  </parent>

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

  <dependencies>
    <!-- Add typical dependencies for a web application -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Project Lombok -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <!-- Package as an executable jar -->
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

其中应用程序主类 Application.java 源码如下:

package com.wuxianjiezh;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

/**
 * 主应用程序类。通常建议将主应用程序类放在其他类之上的根包中。
 *
 * <p>{@code @EnableAutoConfiguration} 和 {@code @ComponentScan} 注解
 * 可以代替 {@code SpringBootApplication} 注解使用。
 *
 * <ul>
 * <li>{@code @EnableAutoConfiguration} 注解会使 Spring Boot 根据项目添加的 jar 依赖关系来自动配置 Spring。
 * 自动配置是非侵入性的。在任何时候,我们都可以开始定义自己的配置以替换自动配置的特定部分</li>
 * <li>{@code @ComponentScan} 注解会自动获取所有 Spring 组件({@code @Configuration}、{@code @Component}、
 * {@code @Service}、{@code @Controller} 等),都将自动注册为 Spring Beans</li>
 * </ul>
 *
 * @author 吴仙杰
 */
@EnableAutoConfiguration
@ComponentScan({"com.wuxianjiezh", "com.outer"})
public class Application {

    /**
     * 一个遵循 Java 应用程序入口点约定的标准方法。
     * 这里通过调用 {@code run} 将程序委托给 Spring Boot 的 {@code SpringApplication} 类。
     *
     * @param args 将传入 {@link SpringApplication} 中的命令行参数
     */
    public static void main(String[] args) {
        // `SpringApplication` 将引导我们的应用程序,启动 Spring,然后启动自动配置的 Tomcat Web 服务器
        SpringApplication.run(Application.class, args);
    }
}

测试 Controller 类 UserController.java 源码如下:

package com.wuxianjiezh.user;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * {@code @RestController} 注解告诉 Spring 将结果进行字符串序列化后直接呈现给调用者。
 *
 * @author 吴仙杰
 */
@RestController
public class UserController {

    /**
     * {@code @RequestMapping} 注解提供了路由信息。
     * 它告诉 Spring,任何带有 {@code /users} 路径的 HTTP 请求都应该映射到 {@code getUser} 方法。
     *
     * @return <pre>{@code
     * [
     *     {
     *         "username": "吴仙杰",
     *         "email": "aaa@qq.com"
     *     },
     *     {
     *         "username": "Jason",
     *         "email": "aaa@qq.com"
     *     }
     * ]}</pre>
     */
    @GetMapping(value = "/users")
    public List<User> getUser() {
        return new ArrayList<User>() {{
            add(new User("吴仙杰", "aaa@qq.com", "123"));
            add(new User("Jason", "aaa@qq.com", "456"));
        }};
    }
}

其中测试实体源码如下:

package com.wuxianjiezh.user;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 用户实体。
 *
 * @author 吴仙杰
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    private String username;
    private String email;
    /**
     * 密码字段,只在 JSON 反序列化时需要写入,但不在 JSON 序列化时输出。
     */
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String password;
}

其中测试外部包的 NewsController 源码如下:

package com.outer;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 模拟相对 {@code wuxianjiezh} 处于外部包的新闻类。
 *
 * @author 吴仙杰
 */
@RestController
public class NewsController {

    /**
     * 获取新闻信息。
     *
     * @return {@code 我是外部新闻包}
     */
    @GetMapping(value = "/news")
    public String getNews() {
        return "我是外部新闻包";
    }
}

resources 增加配置文件 application.properties

# Server HTTP port
server.port=9090

默认内置的 Tomcat 开放端口为 8080

项目运行

由于我们使用了 spring-boot-starter-parent POM,因此可以在项目根目录中打开 CLI,键入 mvnw spring-boot:run 来启动应用程序。

退出应用程序,请按 ctrl-c

项目打包

执行 mvnw package,即会在项目根目录下生成 target 文件夹,其中主要说明以下两个文件:

  • spring-boot-demo-1.0-SNAPSHOT.jar:经 Spring Boot 打包生成的可执行 jar 文件
  • spring-boot-demo-1.0-SNAPSHOT.jar.original:Maven 在 Spring Boot 重新打包之前创建的原始 jar 文件

如果要查看 jar 的内部文件信息,可执行以下命令:

$ jar tvf spring-boot-demo-1.0-SNAPSHOT.jar

如果要运行程序,可执行以下命令:

$ java -jar spring-boot-demo-1.0-SNAPSHOT.jar

退出应用程序,请按 ctrl-c

项目源码下载

项目源码位于 GitHub wuxianjiezh/spring-boot-demo

点击下载源码