Spring Boot - 快速指南



Spring Boot - 简介

Spring Boot 是一个开源的基于 Java 的框架,用于创建微服务。它由 Pivotal 团队开发,用于构建独立且可用于生产环境的 Spring 应用程序。本章将向您介绍 Spring Boot,并使您熟悉其基本概念。

什么是微服务?

微服务是一种架构,它允许开发人员独立地开发和部署服务。每个运行的服务都有自己的进程,从而实现了轻量级模型来支持业务应用程序。

优势

微服务为其开发人员提供了以下优势:

  • 易于部署
  • 简单的可扩展性
  • 兼容容器
  • 最小配置
  • 缩短生产时间

什么是 Spring Boot?

Spring Boot 为 Java 开发人员提供了一个良好的平台来开发独立且可用于生产环境的 Spring 应用程序,您可以直接运行。您可以以最少的配置开始,而无需进行完整的 Spring 配置设置。

优势

Spring Boot 为其开发人员提供了以下优势:

  • 易于理解和开发 Spring 应用程序
  • 提高生产力
  • 缩短开发时间

目标

Spring Boot 的设计目标如下:

  • 避免在 Spring 中使用复杂的 XML 配置
  • 以更简单的方式开发可用于生产环境的 Spring 应用程序
  • 减少开发时间并独立运行应用程序
  • 提供一种更简单的应用程序入门方式

为什么选择 Spring Boot?

您可以选择 Spring Boot,因为它提供了以下功能和优势:

  • 它提供了一种灵活的方式来配置 Java Bean、XML 配置和数据库事务。

  • 它提供强大的批处理功能并管理 REST 端点。

  • 在 Spring Boot 中,所有内容都自动配置;无需手动配置。

  • 它提供基于注解的 Spring 应用程序

  • 简化依赖管理

  • 它包含嵌入式 Servlet 容器

它是如何工作的?

Spring Boot 通过使用@EnableAutoConfiguration注解根据您添加到项目中的依赖项自动配置您的应用程序。例如,如果 MySQL 数据库位于您的类路径中,但您没有配置任何数据库连接,则 Spring Boot 会自动配置一个内存数据库。

Spring Boot 应用程序的入口点是包含@SpringBootApplication注解和 main 方法的类。

Spring Boot 通过使用@ComponentScan注解自动扫描项目中包含的所有组件。

Spring Boot 启动器

对于大型项目,处理依赖管理是一项艰巨的任务。Spring Boot 通过为开发人员提供一组依赖项来解决此问题。

例如,如果您想使用 Spring 和 JPA 进行数据库访问,只需在您的项目中包含spring-boot-starter-data-jpa依赖项即可。

请注意,所有 Spring Boot 启动器都遵循相同的命名模式spring-boot-starter- *,其中 * 表示应用程序的类型。

示例

为了更好地理解,请查看以下 Spring Boot 启动器的说明:

Spring Boot Starter Actuator 依赖项用于监控和管理您的应用程序。其代码如下所示:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Spring Boot Starter Security 依赖项用于 Spring Security。其代码如下所示:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Spring Boot Starter Web 依赖项用于编写 Rest 端点。其代码如下所示:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot Starter Thyme Leaf 依赖项用于创建 Web 应用程序。其代码如下所示:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Spring Boot Starter Test 依赖项用于编写测试用例。其代码如下所示:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
</dependency>

自动配置

Spring Boot 自动配置根据您在项目中添加的 JAR 依赖项自动配置您的 Spring 应用程序。例如,如果 MySQL 数据库位于您的类路径中,但您没有配置任何数据库连接,则 Spring Boot 会自动配置一个内存数据库。

为此,您需要在主类文件中添加@EnableAutoConfiguration注解或@SpringBootApplication注解。然后,您的 Spring Boot 应用程序将自动配置。

观察以下代码以更好地理解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;

@EnableAutoConfiguration
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

Spring Boot 应用程序

Spring Boot 应用程序的入口点是包含@SpringBootApplication注解的类。此类应具有 main 方法以运行 Spring Boot 应用程序。@SpringBootApplication注解包括自动配置、组件扫描和 Spring Boot 配置。

如果您在类中添加了@SpringBootApplication注解,则无需添加@EnableAutoConfiguration、@ComponentScan@SpringBootConfiguration注解。@SpringBootApplication注解包含所有其他注解。

观察以下代码以更好地理解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

组件扫描

Spring Boot 应用程序在应用程序初始化时扫描所有 bean 和包声明。您需要为您的类文件添加@ComponentScan注解以扫描您添加到项目中的组件。

观察以下代码以更好地理解:

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

@ComponentScan
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

Spring Boot - 快速入门

本章将教您如何使用 Maven 和 Gradle 创建 Spring Boot 应用程序。

先决条件

您的系统需要满足以下最低要求才能创建 Spring Boot 应用程序:

  • Java 7
  • Maven 3.2
  • Gradle 2.5

Spring Boot CLI

Spring Boot CLI 是一个命令行工具,它允许我们运行 Groovy 脚本。这是使用 Spring Boot 命令行界面创建 Spring Boot 应用程序的最简单方法。您可以在命令提示符本身创建、运行和测试应用程序。

本节说明 Spring Boot CLI 手动安装的步骤。如需更多帮助,您可以使用以下链接:https://docs.springframework.org.cn/springboot/ docs/current-SNAPSHOT/reference/htmlsingle/#getting-started-installing-springboot

您也可以从 Spring 软件存储库下载 Spring CLI 发行版:https://docs.springframework.org.cn/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#getting-started-manual-cli-installation

对于手动安装,您需要使用以下两个文件夹:

  • spring-boot-cli-2.0.0.BUILD-SNAPSHOT-bin.zip

  • spring-boot-cli-2.0.0.BUILD-SNAPSHOT-bin.tar.gz

下载后,解压缩存档文件并按照 install.txt 文件中的步骤操作。请注意,它不需要任何环境设置。

在 Windows 中,转到命令提示符中的 Spring Boot CLI bin 目录并运行命令spring –-version以确保 Spring CLI 正确安装。执行该命令后,您可以看到 Spring CLI 版本,如下所示:

Spring CLI Version

使用 Groovy 运行 Hello World

创建一个简单的 Groovy 文件,其中包含 Rest 端点脚本,并使用 Spring Boot CLI 运行该 Groovy 文件。为此,请观察此处显示的代码:

@Controller
class Example {
   @RequestMapping("/")
   @ResponseBody
   public String hello() {
      "Hello Spring Boot"
   }
}

现在,将 Groovy 文件保存为hello.groovy。请注意,在此示例中,我们将 Groovy 文件保存在 Spring Boot CLI bin 目录中。现在,使用命令spring run hello.groovy运行应用程序,如下面的屏幕截图所示:

Run Hello World with Groovy

运行 Groovy 文件后,所需的依赖项将自动下载,它将在 Tomcat 8080 端口启动应用程序,如下面的屏幕截图所示:

Run Groovy File Tomcat Port

Tomcat 启动后,转到 Web 浏览器并访问 URL https://127.0.0.1:8080/,您将看到输出,如下所示。

Hello Spring Boot

Spring Boot - 引导

本章将解释如何在 Spring Boot 应用程序上执行引导。

Spring Initializer

启动 Spring Boot 应用程序的一种方法是使用 Spring Initializer。为此,您需要访问 Spring Initializer 网页 www.start.spring.io 并选择您的构建、Spring Boot 版本和平台。此外,您需要提供一个 Group、Artifact 和运行应用程序所需的依赖项。

观察以下屏幕截图,其中显示了一个示例,我们添加了spring-boot-starter-web依赖项来编写 REST 端点。

Spring Initializer

提供 Group、Artifact、依赖项、构建项目、平台和版本后,单击生成项目按钮。zip 文件将下载并解压缩文件。

本节将通过 Maven 和 Gradle 两种方式向您解释示例。

Maven

下载项目后,解压缩文件。现在,您的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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>demo</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.8.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle

下载项目后,解压缩文件。现在,您的build.gradle文件如下所示:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

类路径依赖项

Spring Boot 提供了许多启动器来将 jar 添加到我们的类路径中。例如,要编写 Rest 端点,我们需要在我们的类路径中添加spring-boot-starter-web依赖项。观察下面显示的代码以更好地理解:

Maven 依赖项

<dependencies>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
</dependencies>   

Gradle 依赖项

dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
}

主方法

主方法应该写入 Spring Boot 应用程序类。此类应该用@SpringBootApplication进行注释。这是 spring boot 应用程序的入口点以启动。您可以在src/java/main目录下的默认包中找到主类文件。

在本例中,主类文件位于src/java/main目录下的默认包com.tutorialspoint.demo中。观察此处显示的代码以更好地理解:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

编写 REST 端点

要在 Spring Boot 应用程序主类文件中编写简单的 Hello World REST 端点,请按照以下步骤操作:

  • 首先,在类的顶部添加@RestController注释。

  • 现在,使用@RequestMapping注释编写一个请求 URI 方法。

  • 然后,请求 URI 方法应返回Hello World字符串。

现在,您的主 Spring Boot 应用程序类文件将如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController

public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @RequestMapping(value = "/")
   public String hello() {
      return "Hello World";
   }
}

创建可执行 JAR

让我们创建一个可执行 JAR 文件,以使用命令提示符中的 Maven 和 Gradle 命令运行 Spring Boot 应用程序,如下所示:

使用 Maven 命令 mvn clean install,如下所示:

Command MVN Clean Install

执行该命令后,您可以在命令提示符下看到BUILD SUCCESS消息,如下所示:

BUILD SUCCESS Message

使用 Gradle 命令gradle clean build,如下所示:

Gradle Clean Build

执行该命令后,您可以在命令提示符下看到BUILD SUCCESSFUL消息,如下所示:

BUILD SUCCESSFUL Message in Command Prompt

使用 Java 运行 Hello World

创建可执行 JAR 文件后,您可以在以下目录中找到它。

对于 Maven,您可以在 target 目录下找到 JAR 文件,如下所示:

Maven JAR File Target Directory

对于 Gradle,您可以在build/libs目录下找到 JAR 文件,如下所示:

JAR File Under Build Libs Directory

现在,使用命令java –jar <JARFILE>运行 JAR 文件。请注意,在上面的示例中,JAR 文件名为demo-0.0.1-SNAPSHOT.jar

JAR File Named Demo SNAPSHOT

运行 jar 文件后,您可以在控制台窗口中看到输出,如下所示:

Output in Console Window

现在,查看控制台,Tomcat 在端口 8080 (http) 上启动。现在,转到 Web 浏览器并点击 URLhttps://127.0.0.1:8080/,您将看到如下所示的输出:

Tomcat Started on Port 8080 (http).

Spring Boot - Tomcat 部署

使用 Spring Boot 应用程序,我们可以创建一个 war 文件以部署到 Web 服务器。在本章中,您将学习如何创建 WAR 文件并在 Tomcat Web 服务器中部署 Spring Boot 应用程序。

Spring Boot Servlet 初始化器

传统的部署方式是使 Spring Boot 应用程序@SpringBootApplication类扩展SpringBootServletInitializer类。Spring Boot Servlet 初始化器类文件允许您在使用 Servlet 容器启动应用程序时配置应用程序。

JAR 文件部署的 Spring Boot 应用程序类文件的代码如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

我们需要扩展类SpringBootServletInitializer以支持 WAR 文件部署。Spring Boot 应用程序类文件的代码如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class DemoApplication  extends SpringBootServletInitializer {
   @Override
   protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(DemoApplication.class);
   }
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

设置主类

在 Spring Boot 中,我们需要提到应该在构建文件中启动的主类。为此,您可以使用以下代码段:

对于 Maven,在pom.xml属性中添加启动类,如下所示:

<start-class>com.tutorialspoint.demo.DemoApplication</start-class>

对于 Gradle,在 build.gradle 中添加主类名称,如下所示:

mainClassName="com.tutorialspoint.demo.DemoApplication"

将打包 JAR 更新为 WAR

我们必须使用以下代码段将打包 JAR 更新为 WAR:

对于 Maven,在pom.xml中将打包添加为 WAR,如下所示:

<packaging>war</packaging>

对于 Gradle,在build.gradle中添加应用程序插件和 war 插件,如下所示:

apply plugin: ‘war’
apply plugin: ‘application’

现在,让我们编写一个简单的 REST 端点来返回字符串“Hello World from Tomcat”。要编写 REST 端点,我们需要将 Spring Boot web 启动器依赖项添加到我们的构建文件中。

对于 Maven,使用如下所示的代码在 pom.xml 中添加 Spring Boot 启动器依赖项:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

对于 Gradle,使用如下所示的代码在build.gradle中添加 Spring Boot 启动器依赖项:

dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
}

现在,在 Spring Boot 应用程序类文件中使用如下所示的代码编写一个简单的 REST 端点:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication  extends SpringBootServletInitializer {
   @Override
   protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(DemoApplication.class);
   }
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   
   @RequestMapping(value = "/")
   public String hello() {
      return "Hello World from Tomcat";
   }
}

打包您的应用程序

现在,使用 Maven 和 Gradle 命令创建 WAR 文件以部署到 Tomcat 服务器,以打包您的应用程序,如下所示:

对于 Maven,使用命令mvn package打包您的应用程序。然后,将创建 WAR 文件,您可以在 target 目录中找到它,如下面的屏幕截图所示:

Maven MVN Package

Maven Packaging Application Target Directory

对于 Gradle,使用命令gradle clean build打包您的应用程序。然后,将创建您的 WAR 文件,您可以在build/libs目录下找到它。观察此处提供的屏幕截图以更好地理解:

Gradle Clean Build Command

Maven Packaging Application Target Directory

部署到 Tomcat

现在,运行 Tomcat 服务器,并将 WAR 文件部署到webapps目录下。观察此处显示的屏幕截图以更好地理解:

Tomcat Web Application Maneger

webApps Directory

部署成功后,在 Web 浏览器中点击 URLhttps://127.0.0.1:8080/demo-0.0.1-SNAPSHOT/,并观察输出将如下面的屏幕截图所示:

Successful Deployment Screenshot

此目的的完整代码如下所示。

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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>war</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>
   
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.8.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <start-class>com.tutorialspoint.demo.DemoApplication</start-class>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'
apply plugin: 'application'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
mainClassName = "com.tutorialspoint.demo.DemoApplication"

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

主 Spring Boot 应用程序类文件的代码如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication  extends SpringBootServletInitializer {
   @Override
   protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(DemoApplication.class);
   }
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   
   @RequestMapping(value = "/")
   public String hello() {
      return "Hello World from Tomcat";
   }
}

Spring Boot - 构建系统

在 Spring Boot 中,选择构建系统是一项重要的任务。我们推荐使用 Maven 或 Gradle,因为它们为依赖项管理提供了良好的支持。Spring 不太支持其他构建系统。

依赖项管理

Spring Boot 团队提供了一系列依赖项来支持其每个版本的 Spring Boot 版本。您无需在构建配置文件中提供依赖项的版本。Spring Boot 会根据版本自动配置依赖项版本。请记住,当您升级 Spring Boot 版本时,依赖项也会自动升级。

注意 - 如果您想为依赖项指定版本,您可以在配置文件中指定它。但是,Spring Boot 团队强烈建议无需为依赖项指定版本。

Maven 依赖项

对于 Maven 配置,我们应该继承 Spring Boot Starter 父项目来管理 Spring Boot Starters 依赖项。为此,我们只需在pom.xml文件中继承启动器父级,如下所示。

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

我们应该为 Spring Boot Parent Starter 依赖项指定版本号。然后对于其他启动器依赖项,我们不需要指定 Spring Boot 版本号。观察下面给出的代码:

<dependencies>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
</dependencies>

Gradle 依赖项

我们可以直接将 Spring Boot Starters 依赖项导入build.gradle文件。我们不需要像 Maven 那样为 Gradle 使用 Spring Boot 启动父依赖项。观察下面给出的代码:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

同样,在 Gradle 中,我们不需要为依赖项指定 Spring Boot 版本号。Spring Boot 会根据版本自动配置依赖项。

dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
}

Spring Boot - 代码结构

Spring Boot 没有任何代码布局可以一起使用。但是,有一些最佳实践可以帮助我们。本章将详细讨论它们。

默认包

没有包声明的类被认为是默认包。请注意,通常不建议使用默认包声明。当您使用默认包时,Spring Boot 会导致自动配置或组件扫描等问题。

注意 - Java 建议的包声明命名约定是反向域名。例如 - com.tutorialspoint.myproject

典型布局

Spring Boot 应用程序的典型布局如下面的图像所示:

Typical Layout of Spring Boot Application

Application.java 文件应声明主方法以及 @SpringBootApplication。观察下面给出的代码以更好地理解:

package com.tutorialspoint.myproject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
   public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

Bean 和依赖注入

在 Spring Boot 中,我们可以使用 Spring Framework 来定义我们的 Bean 及其依赖注入。@ComponentScan注释用于查找 Bean,并使用@Autowired注释进行相应的注入。

如果您遵循 Spring Boot 典型布局,则无需为@ComponentScan注释指定任何参数。所有组件类文件都将自动注册到 Spring Bean 中。

以下示例提供了有关自动连接 Rest Template 对象和为其创建 Bean 的想法:

@Bean
public RestTemplate getRestTemplate() {
   return new RestTemplate();
}

以下代码显示了在主 Spring Boot 应用程序类文件中自动连接 Rest Template 对象和 Bean 创建对象的代码:

package com.tutorialspoint.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class DemoApplication {
@Autowired
   RestTemplate restTemplate;
   
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @Bean
   public RestTemplate getRestTemplate() {
      return new RestTemplate();   
   }
}

Spring Boot - 运行器

Application Runner 和 Command Line Runner 接口允许您在 Spring Boot 应用程序启动后执行代码。您可以使用这些接口在应用程序启动后立即执行任何操作。本章将详细讨论它们。

Application Runner

Application Runner 是一个用于在 Spring Boot 应用程序启动后执行代码的接口。以下示例显示了如何在主类文件上实现 Application Runner 接口。

package com.tutorialspoint.demo;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication implements ApplicationRunner {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @Override
   public void run(ApplicationArguments arg0) throws Exception {
      System.out.println("Hello World from Application Runner");
   }
}

现在,如果您观察控制台窗口,在Hello World from Application Runner下方,println 语句在 Tomcat 启动后执行。以下屏幕截图是否相关?

Hello World From Application Runner

Command Line Runner

Command Line Runner 是一个接口。它用于在 Spring Boot 应用程序启动后执行代码。以下示例显示了如何在主类文件上实现 Command Line Runner 接口。

package com.tutorialspoint.demo;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @Override
   public void run(String... arg0) throws Exception {
      System.out.println("Hello world from Command Line Runner");
   }
}

查看控制台窗口,在“Hello world from Command Line Runner”println 语句在 Tomcat 启动后执行。

Command Line Runner

Spring Boot - 应用属性

Application Properties 支持我们在不同的环境中工作。在本章中,您将学习如何将属性配置和指定到 Spring Boot 应用程序。

命令行属性

Spring Boot 应用程序将命令行属性转换为 Spring Boot 环境属性。命令行属性优先于其他属性源。默认情况下,Spring Boot 使用 8080 端口号启动 Tomcat。让我们学习如何使用命令行属性更改端口号。

步骤 1 - 创建可执行 JAR 文件后,使用命令java –jar <JARFILE>运行它。

步骤 2 - 使用下面给出的屏幕截图中给出的命令,使用命令行属性更改 Spring Boot 应用程序的端口号。

Command Line Properties JARFILE

注意 - 您可以使用分隔符 - 提供多个应用程序属性。

属性文件

属性文件用于在一个文件中保留“N”个属性,以便在不同的环境中运行应用程序。在 Spring Boot 中,属性保存在类路径下的application.properties文件中。

application.properties 文件位于src/main/resources目录中。示例application.properties文件的代码如下所示:

server.port = 9090
spring.application.name = demoservice

请注意,在上面显示的代码中,Spring Boot应用程序demoservice在端口9090上启动。

YAML文件

Spring Boot支持基于YAML的属性配置来运行应用程序。我们可以使用application.yml文件,而不是application.properties文件。此YAML文件也应保存在类路径中。下面给出了示例application.yml文件:

spring:
   application:
      name: demoservice
   server:
port: 9090

外部化属性

我们可以将属性文件保存在不同的位置或路径中,而不是将其保存在类路径下。在运行JAR文件时,我们可以指定属性文件路径。您可以使用以下命令在运行JAR时指定属性文件的位置:

-Dspring.config.location = C:\application.properties

Externalized Properties

使用@Value注解

@Value注解用于在Java代码中读取环境或应用程序属性值。读取属性值的语法如下所示:

@Value("${property_key_name}")

请查看以下示例,该示例显示了使用@Value注解在Java变量中读取spring.application.name属性值的语法。

@Value("${spring.application.name}")

请观察以下代码以更好地理解:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {
   @Value("${spring.application.name}")
   private String name;
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @RequestMapping(value = "/")
   public String name() {
      return name;
   }
}   

注意 - 如果在运行应用程序时找不到该属性,则Spring Boot会抛出IllegalArgument异常,例如Could not resolve placeholder 'spring.application.name' in value "${spring.application.name}"

为了解决占位符问题,我们可以使用以下语法设置属性的默认值:

@Value("${property_key_name:default_value}")

@Value("${spring.application.name:demoservice}")

Spring Boot活动配置文件

Spring Boot根据Spring活动配置文件支持不同的属性。例如,我们可以为开发和生产环境保留两个单独的文件来运行Spring Boot应用程序。

application.properties中的Spring活动配置文件

让我们了解如何在application.properties中使用Spring活动配置文件。默认情况下,将使用application.properties来运行Spring Boot应用程序。如果要使用基于配置文件的属性,我们可以为每个配置文件保留单独的属性文件,如下所示:

application.properties

server.port = 8080
spring.application.name = demoservice

application-dev.properties

server.port = 9090
spring.application.name = demoservice

application-prod.properties

server.port = 4431
spring.application.name = demoservice

在运行JAR文件时,我们需要根据每个属性文件指定Spring活动配置文件。默认情况下,Spring Boot应用程序使用application.properties文件。设置Spring活动配置文件的命令如下所示:

Prod.Properties Active Dev

您可以在控制台日志中看到活动配置文件名称,如下所示:

2017-11-26 08:13:16.322  INFO 14028 --- [           
   main] com.tutorialspoint.demo.DemoApplication  :
   The following profiles are active: dev

现在,Tomcat已在端口9090(http)上启动,如下所示:

2017-11-26 08:13:20.185  INFO 14028 --- [           
   main] s.b.c.e.t.TomcatEmbeddedServletContainer : 
   Tomcat started on port(s): 9090 (http)

您可以设置生产活动配置文件,如下所示:

Production Active Profile

您可以在控制台日志中看到活动配置文件名称,如下所示:

2017-11-26 08:13:16.322  INFO 14028 --- [           
   main] com.tutorialspoint.demo.DemoApplication  :
   The following profiles are active: prod

现在,Tomcat已在端口4431(http)上启动,如下所示:

2017-11-26 08:13:20.185  INFO 14028 --- [          
   main] s.b.c.e.t.TomcatEmbeddedServletContainer :
   Tomcat started on port(s): 4431 (http)

application.yml的Spring活动配置文件

让我们了解如何在application.yml中保留Spring活动配置文件。我们可以在单个application.yml文件中保留Spring活动配置文件属性。无需像application.properties那样使用单独的文件。

以下是在application.yml文件中保留Spring活动配置文件的示例代码。请注意,分隔符(---)用于分隔application.yml文件中每个配置文件。

spring:
   application:
      name: demoservice
server:
   port: 8080

---
spring:
   profiles: dev
   application:
      name: demoservice
server:
   port: 9090

---
spring: 
   profiles: prod
   application:
      name: demoservice
server: 
   port: 4431

设置开发活动配置文件的命令如下所示:

Prod.Properties Active Dev

您可以在控制台日志中看到活动配置文件名称,如下所示:

2017-11-26 08:41:37.202  INFO 14104 --- [           
   main] com.tutorialspoint.demo.DemoApplication  : 
   The following profiles are active: dev

现在,Tomcat已在端口9090(http)上启动,如下所示:

2017-11-26 08:41:46.650  INFO 14104 --- [           
   main] s.b.c.e.t.TomcatEmbeddedServletContainer : 
   Tomcat started on port(s): 9090 (http)

设置生产活动配置文件的命令如下所示:

Production Active Profile

您可以在控制台日志中看到活动配置文件名称,如下所示:

2017-11-26 08:43:10.743  INFO 13400 --- [    
   main] com.tutorialspoint.demo.DemoApplication  : 
   The following profiles are active: prod

这将启动Tomcat在端口4431(http)上,如下所示

2017-11-26 08:43:14.473  INFO 13400 --- [     
   main] s.b.c.e.t.TomcatEmbeddedServletContainer : 
   Tomcat started on port(s): 4431 (http)

Spring Boot - 日志

Spring Boot使用Apache Commons logging进行所有内部日志记录。Spring Boot的默认配置提供了对使用Java Util Logging、Log4j2和Logback的支持。使用这些,我们可以配置控制台日志记录以及文件日志记录。

如果您使用的是Spring Boot Starters,则Logback将为日志记录提供良好的支持。此外,Logback还提供了对Common Logging、Util Logging、Log4J和SLF4J的良好支持。

日志格式

默认的Spring Boot日志格式显示在下面给出的屏幕截图中。

Spring Boot Log Format

它为您提供以下信息:

  • 日期时间,提供日志的日期和时间

  • 日志级别显示INFO、ERROR或WARN

  • 进程ID

  • ---,这是一个分隔符

  • 线程名称用方括号[]括起来

  • 日志记录器名称,显示源类名

  • 日志消息

控制台日志输出

默认的日志消息将打印到控制台窗口。默认情况下,“INFO”、“ERROR”和“WARN”日志消息将打印到日志文件中。

如果必须启用调试级别日志,请在启动应用程序时添加调试标志,使用以下命令:

java –jar demo.jar --debug

您还可以将调试模式添加到application.properties文件中,如下所示:

debug = true

文件日志输出

默认情况下,所有日志都将打印到控制台窗口,而不是文件中。如果要将日志打印到文件中,则需要在application.properties文件中设置logging.filelogging.path属性。

您可以使用以下属性指定日志文件路径。请注意,日志文件名是spring.log。

logging.path = /var/tmp/

您可以使用以下属性指定自己的日志文件名:

logging.file = /var/tmp/mylog.log

注意 - 文件在达到10 MB大小时会自动轮换。

日志级别

Spring Boot支持所有日志记录器级别,例如“TRACE”、“DEBUG”、“INFO”、“WARN”、“ERROR”、“FATAL”、“OFF”。您可以在application.properties文件中定义根日志记录器,如下所示:

logging.level.root = WARN

注意 - Logback不支持“FATAL”级别日志。它映射到“ERROR”级别日志。

配置Logback

Logback支持基于XML的配置来处理Spring Boot日志配置。日志配置详细信息在logback.xml文件中配置。logback.xml文件应放在类路径下。

您可以使用以下代码在Logback.xml文件中配置ROOT级别日志:

<?xml version = "1.0" encoding = "UTF-8"?>
<configuration>
   <root level = "INFO">
   </root>
</configuration>

您可以在下面给出的Logback.xml文件中配置控制台附加程序。

<?xml version = "1.0" encoding = "UTF-8"?>
<configuration>
   <appender name = "STDOUT" class = "ch.qos.logback.core.ConsoleAppender"></appender>
   <root level = "INFO">
      <appender-ref ref = "STDOUT"/> 
   </root>
</configuration>

您可以使用以下代码在Logback.xml文件中配置文件附加程序。请注意,您需要在文件附加程序中指定日志文件路径。

<?xml version = "1.0" encoding = "UTF-8"?>
<configuration>
   <appender name = "FILE" class = "ch.qos.logback.core.FileAppender">
      <File>/var/tmp/mylog.log</File>
   </appender>   
   <root level = "INFO">
      <appender-ref ref = "FILE"/>
   </root>
</configuration>

您可以在logback.xml文件中使用以下代码定义日志模式。您还可以使用以下代码在控制台或文件日志附加程序中定义一组支持的日志模式:

<pattern>[%d{yyyy-MM-dd'T'HH:mm:ss.sss'Z'}] [%C] [%t] [%L] [%-5p] %m%n</pattern>

完整logback.xml文件的代码如下所示。您必须将其放在类路径中。

<?xml version = "1.0" encoding = "UTF-8"?>
<configuration>
   <appender name = "STDOUT" class = "ch.qos.logback.core.ConsoleAppender">
      <encoder>
         <pattern>[%d{yyyy-MM-dd'T'HH:mm:ss.sss'Z'}] [%C] [%t] [%L] [%-5p] %m%n</pattern>
      </encoder>
   </appender>
   
   <appender name = "FILE" class = "ch.qos.logback.core.FileAppender">
      <File>/var/tmp/mylog.log</File>
      <encoder>
         <pattern>[%d{yyyy-MM-dd'T'HH:mm:ss.sss'Z'}] [%C] [%t] [%L] [%-5p] %m%n</pattern>
      </encoder>
   </appender>
   
   <root level = "INFO">
      <appender-ref ref = "FILE"/>
      <appender-ref ref = "STDOUT"/> 
   </root>
</configuration>

以下代码显示了如何在Spring Boot主类文件中添加slf4j日志记录器。

package com.tutorialspoint.demo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   private static final Logger logger = LoggerFactory.getLogger(DemoApplication.class);
   
   public static void main(String[] args) {
      logger.info("this is a info message");
      logger.warn("this is a warn message");
      logger.error("this is a error message");
      SpringApplication.run(DemoApplication.class, args);
   }
}

您可以在控制台窗口中看到的输出显示在此处:

Logger Console Window

您可以在日志文件中看到的输出显示在此处:

Log Output

Spring Boot - 构建RESTful Web服务

Spring Boot为企业应用程序构建RESTful Web服务提供了非常好的支持。本章将详细解释如何使用Spring Boot构建RESTful Web服务。

注意 - 为了构建RESTful Web服务,我们需要将Spring Boot Starter Web依赖项添加到构建配置文件中。

如果您是Maven用户,请使用以下代码将以下依赖项添加到您的pom.xml文件中:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>    
</dependency>

如果您是Gradle用户,请使用以下代码将以下依赖项添加到您的build.gradle文件中。

compile('org.springframework.boot:spring-boot-starter-web')

完整构建配置文件Maven构建 – 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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>
   
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.8.RELEASE</version>
      <relativePath/> 
   </parent>
   
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>
   
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

完整构建配置文件Gradle构建 – build.gradle的代码如下所示:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

在继续构建RESTful Web服务之前,建议您了解以下注解:

Rest控制器

@RestController注解用于定义RESTful Web服务。它提供JSON、XML和自定义响应。其语法如下所示:

@RestController
public class ProductServiceController { 
}

请求映射

@RequestMapping注解用于定义访问REST端点的请求URI。我们可以定义请求方法来使用和生成对象。默认请求方法是GET。

@RequestMapping(value = "/products")
public ResponseEntity<Object> getProducts() { }

请求体

@RequestBody注解用于定义请求体内容类型。

public ResponseEntity<Object> createProduct(@RequestBody Product product) {
}

路径变量

@PathVariable注解用于定义自定义或动态请求URI。请求URI中的路径变量定义为花括号{},如下所示:

public ResponseEntity<Object> updateProduct(@PathVariable("id") String id) {
}

请求参数

@RequestParam注解用于从请求URL读取请求参数。默认情况下,它是一个必需的参数。我们也可以为请求参数设置默认值,如下所示:

public ResponseEntity<Object> getProduct(
   @RequestParam(value = "name", required = false, defaultValue = "honey") String name) {
}

GET API

默认的HTTP请求方法是GET。此方法不需要任何请求体。您可以发送请求参数和路径变量来定义自定义或动态URL。

下面显示了定义HTTP GET请求方法的示例代码。在此示例中,我们使用HashMap存储Product。请注意,我们使用POJO类作为要存储的产品。

此处,请求URI为/products,它将从HashMap存储库返回产品列表。以下是包含GET方法REST端点的控制器类文件。

package com.tutorialspoint.demo.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tutorialspoint.demo.model.Product;

@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();
   static {
      Product honey = new Product();
      honey.setId("1");
      honey.setName("Honey");
      productRepo.put(honey.getId(), honey);
      
      Product almond = new Product();
      almond.setId("2");
      almond.setName("Almond");
      productRepo.put(almond.getId(), almond);
   }
   @RequestMapping(value = "/products")
   public ResponseEntity<Object> getProduct() {
      return new ResponseEntity<>(productRepo.values(), HttpStatus.OK);
   }
}

POST API

HTTP POST请求用于创建资源。此方法包含请求体。我们可以发送请求参数和路径变量来定义自定义或动态URL。

以下示例显示了定义HTTP POST请求方法的示例代码。在此示例中,我们使用HashMap存储Product,其中Product是POJO类。

此处,请求URI为/products,它将在将产品存储到HashMap存储库后返回字符串。

package com.tutorialspoint.demo.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.tutorialspoint.demo.model.Product;

@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();
   
   @RequestMapping(value = "/products", method = RequestMethod.POST)
   public ResponseEntity<Object> createProduct(@RequestBody Product product) {
      productRepo.put(product.getId(), product);
      return new ResponseEntity<>("Product is created successfully", HttpStatus.CREATED);
   }
}

PUT API

HTTP PUT请求用于更新现有资源。此方法包含请求体。我们可以发送请求参数和路径变量来定义自定义或动态URL。

以下示例显示了如何定义HTTP PUT请求方法。在此示例中,我们使用HashMap更新现有的Product,其中Product是POJO类。

此处,请求URI为/products/{id},它将在将产品添加到HashMap存储库后返回字符串。请注意,我们使用了路径变量{id},它定义了需要更新的产品ID。

package com.tutorialspoint.demo.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.tutorialspoint.demo.model.Product;

@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();
   
   @RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
   public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody Product product) { 
      productRepo.remove(id);
      product.setId(id);
      productRepo.put(id, product);
      return new ResponseEntity<>("Product is updated successsfully", HttpStatus.OK);
   }   
}

DELETE API

HTTP Delete请求用于删除现有资源。此方法不包含任何请求体。我们可以发送请求参数和路径变量来定义自定义或动态URL。

以下示例显示了如何定义HTTP DELETE请求方法。在此示例中,我们使用HashMap删除现有的产品,它是一个POJO类。

请求URI为/products/{id},它将在从HashMap存储库删除产品后返回字符串。我们使用了路径变量{id},它定义了需要删除的产品ID。

package com.tutorialspoint.demo.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.tutorialspoint.demo.model.Product;

@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();
   
   @RequestMapping(value = "/products/{id}", method = RequestMethod.DELETE)
   public ResponseEntity<Object> delete(@PathVariable("id") String id) { 
      productRepo.remove(id);
      return new ResponseEntity<>("Product is deleted successsfully", HttpStatus.OK);
   }
}

本节为您提供了完整的源代码集。请观察以下代码及其各自的功能:

Spring Boot主应用程序类 – DemoApplication.java

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

POJO类 – Product.java

package com.tutorialspoint.demo.model;

public class Product {
   private String id;
   private String name;

   public String getId() {
      return id;
   }
   public void setId(String id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

Rest控制器类 – ProductServiceController.java

package com.tutorialspoint.demo.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.tutorialspoint.demo.model.Product;

@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();
   static {
      Product honey = new Product();
      honey.setId("1");
      honey.setName("Honey");
      productRepo.put(honey.getId(), honey);
      
      Product almond = new Product();
      almond.setId("2");
      almond.setName("Almond");
      productRepo.put(almond.getId(), almond);
   }
   
   @RequestMapping(value = "/products/{id}", method = RequestMethod.DELETE)
   public ResponseEntity<Object> delete(@PathVariable("id") String id) { 
      productRepo.remove(id);
      return new ResponseEntity<>("Product is deleted successsfully", HttpStatus.OK);
   }
   
   @RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
   public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody Product product) { 
      productRepo.remove(id);
      product.setId(id);
      productRepo.put(id, product);
      return new ResponseEntity<>("Product is updated successsfully", HttpStatus.OK);
   }
   
   @RequestMapping(value = "/products", method = RequestMethod.POST)
   public ResponseEntity<Object> createProduct(@RequestBody Product product) {
      productRepo.put(product.getId(), product);
      return new ResponseEntity<>("Product is created successfully", HttpStatus.CREATED);
   }
   
   @RequestMapping(value = "/products")
   public ResponseEntity<Object> getProduct() {
      return new ResponseEntity<>(productRepo.values(), HttpStatus.OK);
   }
}

您可以创建一个可执行的JAR文件,并使用以下Maven或Gradle命令运行Spring Boot应用程序,如下所示:

对于Maven,请使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于Gradle,请使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

您可以使用以下命令运行JAR文件:

java –jar <JARFILE> 

这将在Tomcat端口8080上启动应用程序,如下所示:

Started Application on Tomcat Port8080

现在在POSTMAN应用程序中点击以下URL并查看输出。

GET API URL为:https://127.0.0.1:8080/products

POSTMAN Application Get API URL

POST API URL为:https://127.0.0.1:8080/products

POSTMAN Application Post API URL

PUT API URL为:https://127.0.0.1:8080/products/3

POSTMAN Application Put API URL

DELETE API URL为:https://127.0.0.1:8080/products/3

POSTMAN Application Delete API URL

Spring Boot - 异常处理

在API中处理异常和错误并向客户端发送正确的响应对于企业应用程序来说非常重要。在本章中,我们将学习如何在Spring Boot中处理异常。

在继续进行异常处理之前,让我们了解以下注解。

控制器建议

@ControllerAdvice 是一个注解,用于全局处理异常。

异常处理器

@ExceptionHandler 是一个注解,用于处理特定的异常并向客户端发送自定义响应。

您可以使用以下代码创建 @ControllerAdvice 类来全局处理异常:

package com.tutorialspoint.demo.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;

@ControllerAdvice
   public class ProductExceptionController {
}

定义一个扩展 RuntimeException 类的类。

package com.tutorialspoint.demo.exception;

public class ProductNotfoundException extends RuntimeException {
   private static final long serialVersionUID = 1L;
}

您可以定义 @ExceptionHandler 方法来处理异常,如所示。此方法应用于编写 Controller Advice 类文件。

@ExceptionHandler(value = ProductNotfoundException.class)

public ResponseEntity<Object> exception(ProductNotfoundException exception) {
}

现在,使用下面给出的代码从 API 中抛出异常。

@RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
public ResponseEntity<Object> updateProduct() { 
   throw new ProductNotfoundException();
}

处理异常的完整代码如下所示。在此示例中,我们使用 PUT API 更新产品。在此,在更新产品时,如果找不到产品,则返回响应错误消息“产品未找到”。请注意,**ProductNotFoundException** 异常类应扩展 **RuntimeException**。

package com.tutorialspoint.demo.exception;
public class ProductNotfoundException extends RuntimeException {
   private static final long serialVersionUID = 1L;
}

全局处理异常的 Controller Advice 类如下所示。我们可以在此类文件中定义任何异常处理程序方法。

package com.tutorialspoint.demo.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class ProductExceptionController {
   @ExceptionHandler(value = ProductNotfoundException.class)
   public ResponseEntity<Object> exception(ProductNotfoundException exception) {
      return new ResponseEntity<>("Product not found", HttpStatus.NOT_FOUND);
   }
}

产品服务 API 控制器文件如下所示,用于更新产品。如果找不到产品,则会抛出 **ProductNotFoundException** 类。

package com.tutorialspoint.demo.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.tutorialspoint.demo.exception.ProductNotfoundException;
import com.tutorialspoint.demo.model.Product;

@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();
   static {
      Product honey = new Product();
      honey.setId("1");
      honey.setName("Honey");
      productRepo.put(honey.getId(), honey);
      
      Product almond = new Product();
      almond.setId("2");
      almond.setName("Almond");
      productRepo.put(almond.getId(), almond);
   }
   
   @RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
   public ResponseEntity<Object> updateProduct(@PathVariable("id") String id, @RequestBody Product product) { 
      if(!productRepo.containsKey(id))throw new ProductNotfoundException();
      productRepo.remove(id);
      product.setId(id);
      productRepo.put(id, product);
      return new ResponseEntity<>("Product is updated successfully", HttpStatus.OK);
   }
}

主 Spring Boot 应用程序类文件的代码如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

产品 POJO 类的代码如下所示:

package com.tutorialspoint.demo.model;
public class Product {
   private String id;
   private String name;

   public String getId() {
      return id;
   }
   public void setId(String id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

Maven 构建 - 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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

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

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle 构建 - build.gradle 的代码如下所示:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

您可以创建一个可执行的 JAR 文件,并使用 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,您可以使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

您可以使用以下命令运行 JAR 文件:

java –jar <JARFILE>

这将在Tomcat端口8080上启动应用程序,如下所示:

Exception Handling Tomcat Application Startded

现在在 POSTMAN 应用程序中点击以下 URL,您可以看到如下所示的输出:

更新 URL:https://127.0.0.1:8080/products/3

Postman Application Update URL

Spring Boot - 拦截器

您可以在 Spring Boot 中使用拦截器在以下情况下执行操作:

  • 在将请求发送到控制器之前

  • 在将响应发送到客户端之前

例如,您可以使用拦截器在将请求发送到控制器之前添加请求头,并在将响应发送到客户端之前添加响应头。

要使用拦截器,您需要创建一个支持它的 **@Component** 类,并且它应该实现 **HandlerInterceptor** 接口。

以下是在使用拦截器时您应该了解的三个方法:

  • **preHandle()** 方法 - 用于在将请求发送到控制器之前执行操作。此方法应返回 true 以将响应返回给客户端。

  • **postHandle()** 方法 - 用于在将响应发送到客户端之前执行操作。

  • **afterCompletion()** 方法 - 用于在完成请求和响应后执行操作。

观察以下代码以更好地理解:

@Component
public class ProductServiceInterceptor implements HandlerInterceptor {
   @Override
   public boolean preHandle(
      HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      
      return true;
   }
   @Override
   public void postHandle(
      HttpServletRequest request, HttpServletResponse response, Object handler, 
      ModelAndView modelAndView) throws Exception {}
   
   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
      Object handler, Exception exception) throws Exception {}
}

您需要使用 **WebMvcConfigurerAdapter** 将此拦截器注册到 **InterceptorRegistry**,如下所示:

@Component
public class ProductServiceInterceptorAppConfig extends WebMvcConfigurerAdapter {
   @Autowired
   ProductServiceInterceptor productServiceInterceptor;

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(productServiceInterceptor);
   }
}

在下面给出的示例中,我们将点击 GET 产品 API,它会给出如下所示的输出:

拦截器类 ProductServiceInterceptor.java 的代码如下所示:

package com.tutorialspoint.demo.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class ProductServiceInterceptor implements HandlerInterceptor {
   @Override
   public boolean preHandle
      (HttpServletRequest request, HttpServletResponse response, Object handler) 
      throws Exception {
      
      System.out.println("Pre Handle method is Calling");
      return true;
   }
   @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, 
      Object handler, ModelAndView modelAndView) throws Exception {
      
      System.out.println("Post Handle method is Calling");
   }
   @Override
   public void afterCompletion
      (HttpServletRequest request, HttpServletResponse response, Object 
      handler, Exception exception) throws Exception {
      
      System.out.println("Request and Response is completed");
   }
}

将拦截器注册到拦截器注册表 - ProductServiceInterceptorAppConfig.java 的应用程序配置类文件的代码如下所示:

package com.tutorialspoint.demo.interceptor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Component
public class ProductServiceInterceptorAppConfig extends WebMvcConfigurerAdapter {
   @Autowired
   ProductServiceInterceptor productServiceInterceptor;

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(productServiceInterceptor);
   }
}

控制器类文件 ProductServiceController.java 的代码如下所示:

package com.tutorialspoint.demo.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.tutorialspoint.demo.exception.ProductNotfoundException;
import com.tutorialspoint.demo.model.Product;

@RestController
public class ProductServiceController {
   private static Map<String, Product> productRepo = new HashMap<>();   
   static {      
      Product honey = new Product();
      honey.setId("1");
      honey.setName("Honey");
      productRepo.put(honey.getId(), honey);      
      Product almond = new Product();
      almond.setId("2");
      almond.setName("Almond");
      productRepo.put(almond.getId(), almond);      
   }
   @RequestMapping(value = "/products")
   public ResponseEntity<Object> getProduct() {
      return new ResponseEntity<>(productRepo.values(), HttpStatus.OK);
   }
}

产品 Product.java 的 POJO 类的代码如下所示:

package com.tutorialspoint.demo.model;

public class Product {
   private String id;
   private String name;

   public String getId() {
      return id;
   }
   public void setId(String id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

主 Spring Boot 应用程序类文件 **DemoApplication.java** 的代码如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);   
   }
}

Maven 构建 - **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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

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

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle 构建 **build.gradle** 的代码如下所示:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,请使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,请使用如下所示的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

您可以使用以下命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8080 上启动,如下所示:

Started Application on Tomcat Port 8080

现在在 POSTMAN 应用程序中点击以下 URL,您可以看到如下所示的输出:

GET API:**https://127.0.0.1:8080/products**

POSTMAN Application Get API URL

在控制台窗口中,您可以看到在拦截器中添加的 System.out.println 语句,如下面的屏幕截图所示:

Interceptor Output Console Window

Spring Boot - Servlet 过滤器

过滤器是一个用于拦截应用程序的 HTTP 请求和响应的对象。通过使用过滤器,我们可以在两个实例中执行两个操作:

  • 在将请求发送到控制器之前
  • 在将响应发送到客户端之前。

以下代码显示了带有 @Component 注解的 Servlet Filter 实现类的示例代码。

@Component
public class SimpleFilter implements Filter {
   @Override
   public void destroy() {}

   @Override
   public void doFilter
      (ServletRequest request, ServletResponse response, FilterChain filterchain) 
      throws IOException, ServletException {}

   @Override
   public void init(FilterConfig filterconfig) throws ServletException {}
}

以下示例显示了在将请求发送到控制器之前从 ServletRequest 对象读取远程主机和远程地址的代码。

在 doFilter() 方法中,我们添加了 System.out.println 语句以打印远程主机和远程地址。

package com.tutorialspoint.demo;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.springframework.stereotype.Component;

@Component
public class SimpleFilter implements Filter {
   @Override
   public void destroy() {}

   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain) 
      throws IOException, ServletException {
      
      System.out.println("Remote Host:"+request.getRemoteHost());
      System.out.println("Remote Address:"+request.getRemoteAddr());
      filterchain.doFilter(request, response);
   }

   @Override
   public void init(FilterConfig filterconfig) throws ServletException {}
}

在 Spring Boot 主应用程序类文件中,我们添加了返回“Hello World”字符串的简单 REST 端点。

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @RequestMapping(value = "/")
   public String hello() {
      return "Hello World";
   }
}

Maven 构建 - **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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

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

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle 构建 - build.gradle 的代码如下所示:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

您可以创建一个可执行的 JAR 文件,并使用以下所示的 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,请使用如下所示的命令:

mvn clean install

构建成功后,您可以在 target 目录下找到 JAR 文件。

对于 Gradle,请使用如下所示的命令:

gradle clean build

构建成功后,您可以在 build/libs 目录下找到 JAR 文件。

现在,使用以下命令运行 JAR 文件

java –jar <JARFILE> 

您可以看到应用程序已在 Tomcat 端口 8080 上启动。

现在点击 URL **https://127.0.0.1:8080/** 并查看输出 Hello World。它应该如下所示:

Tomcat Started on Port 8080 HTTP

然后,您可以在控制台日志中看到远程主机和远程地址,如下所示:

Remote Host Remote Address on Console Log

Spring Boot - Tomcat 端口号

Spring Boot 允许您在不同的端口号上多次运行相同的应用程序。在本章中,您将详细了解这一点。请注意,默认端口号为 8080。

自定义端口

在 **application.properties** 文件中,我们可以为属性 server.port 设置自定义端口号

server.port = 9090

在 **application.yml** 文件中,您可以找到如下内容:

server: 
   port: 9090

随机端口

在 **application.properties** 文件中,我们可以为属性 server.port 设置随机端口号

server.port = 0

在 **application.yml** 文件中,您可以找到如下内容:

server: 
   port: 0

**注意** - 如果在启动 Spring Boot 应用程序时 **server.port** 号为 0,则 Tomcat 会使用随机端口号。

Spring Boot - Rest 模板

Rest Template 用于创建使用 RESTful Web 服务的应用程序。您可以使用 **exchange()** 方法使用所有 HTTP 方法使用 Web 服务。下面给出的代码显示了如何创建 Rest Template 的 Bean 以自动连接 Rest Template 对象。

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @Bean
   public RestTemplate getRestTemplate() {
      return new RestTemplate();
   }
}

GET

使用 RestTemplate - exchange() 方法使用 GET API

假设此 URL **https://127.0.0.1:8080/products** 返回以下 JSON,我们将使用以下代码使用 Rest Template 使用此 API 响应:

[
   {
      "id": "1",
      "name": "Honey"
   },
   {
      "id": "2",
      "name": "Almond"
   }
]

您需要遵循以下几点来使用 API:

  • 自动连接 Rest Template 对象。
  • 使用 HttpHeaders 设置请求头。
  • 使用 HttpEntity 包装请求对象。
  • 为 Exchange() 方法提供 URL、HttpMethod 和返回类型。
@RestController
public class ConsumeWebService {
   @Autowired
   RestTemplate restTemplate;

   @RequestMapping(value = "/template/products")
   public String getProductList() {
      HttpHeaders headers = new HttpHeaders();
      headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      HttpEntity <String> entity = new HttpEntity<String>(headers);
      
      return restTemplate.exchange("
         https://127.0.0.1:8080/products", HttpMethod.GET, entity, String.class).getBody();
   }
}

POST

使用 RestTemplate - exchange() 方法使用 POST API

假设此 URL **https://127.0.0.1:8080/products** 返回如下所示的响应,我们将使用 Rest Template 使用此 API 响应。

下面给出的代码是请求体:

{
   "id":"3",
   "name":"Ginger"
}

下面给出的代码是响应体:

Product is created successfully

您需要遵循以下几点来使用 API:

  • 自动连接 Rest Template 对象。

  • 使用 HttpHeaders 设置请求头。

  • 使用 HttpEntity 包装请求对象。在这里,我们包装 Product 对象以将其发送到请求体。

  • 为 exchange() 方法提供 URL、HttpMethod 和返回类型。

@RestController
public class ConsumeWebService {
   @Autowired
   RestTemplate restTemplate;

   @RequestMapping(value = "/template/products", method = RequestMethod.POST)
   public String createProducts(@RequestBody Product product) {
      HttpHeaders headers = new HttpHeaders();
      headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      HttpEntity<Product> entity = new HttpEntity<Product>(product,headers);
      
      return restTemplate.exchange(
         "https://127.0.0.1:8080/products", HttpMethod.POST, entity, String.class).getBody();
   }
}

PUT

使用 RestTemplate - exchange() 方法使用 PUT API

假设此 URL **https://127.0.0.1:8080/products/3** 返回以下响应,我们将使用 Rest Template 使用此 API 响应。

下面给出的代码是请求体:

{
   "name":"Indian Ginger"
}

下面给出的代码是响应体:

Product is updated successfully

您需要遵循以下几点来使用 API:

  • 自动连接 Rest Template 对象。

  • 使用 HttpHeaders 设置请求头。

  • 使用 HttpEntity 包装请求对象。在这里,我们包装 Product 对象以将其发送到请求体。

  • 为 exchange() 方法提供 URL、HttpMethod 和返回类型。

@RestController
public class ConsumeWebService {
   @Autowired
   RestTemplate restTemplate;

   @RequestMapping(value = "/template/products/{id}", method = RequestMethod.PUT)
   public String updateProduct(@PathVariable("id") String id, @RequestBody Product product) {
      HttpHeaders headers = new HttpHeaders();
      headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      HttpEntity<Product> entity = new HttpEntity<Product>(product,headers);
      
      return restTemplate.exchange(
         "https://127.0.0.1:8080/products/"+id, HttpMethod.PUT, entity, String.class).getBody();
   }
}

DELETE

使用 RestTemplate - exchange() 方法使用 DELETE API

假设此 URL **https://127.0.0.1:8080/products/3** 返回以下响应,我们将使用 Rest Template 使用此 API 响应。

下面显示的代码行是响应体:

Product is deleted successfully

您需要遵循以下几点来使用 API:

  • 自动连接 Rest Template 对象。

  • 使用 HttpHeaders 设置请求头。

  • 使用 HttpEntity 包装请求对象。

  • 为 exchange() 方法提供 URL、HttpMethod 和返回类型。

@RestController
public class ConsumeWebService {
   @Autowired
   RestTemplate restTemplate;

   @RequestMapping(value = "/template/products/{id}", method = RequestMethod.DELETE)
   public String deleteProduct(@PathVariable("id") String id) {
      HttpHeaders headers = new HttpHeaders();
      headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      HttpEntity<Product> entity = new HttpEntity<Product>(headers);
      
      return restTemplate.exchange(
         "https://127.0.0.1:8080/products/"+id, HttpMethod.DELETE, entity, String.class).getBody();
   }
}

完整的 Rest Template 控制器类文件如下所示:

package com.tutorialspoint.demo.controller;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.tutorialspoint.demo.model.Product;

@RestController
public class ConsumeWebService {
   @Autowired
   RestTemplate restTemplate;

   @RequestMapping(value = "/template/products")
   public String getProductList() {
      HttpHeaders headers = new HttpHeaders();
      headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      HttpEntity<String> entity = new HttpEntity<String>(headers);
      
      return restTemplate.exchange(
         "https://127.0.0.1:8080/products", HttpMethod.GET, entity, String.class).getBody();
   }
   @RequestMapping(value = "/template/products", method = RequestMethod.POST)
   public String createProducts(@RequestBody Product product) {
      HttpHeaders headers = new HttpHeaders();
      headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      HttpEntity<Product> entity = new HttpEntity<Product>(product,headers);
      
      return restTemplate.exchange(
         "https://127.0.0.1:8080/products", HttpMethod.POST, entity, String.class).getBody();
   }
   @RequestMapping(value = "/template/products/{id}", method = RequestMethod.PUT)
   public String updateProduct(@PathVariable("id") String id, @RequestBody Product product) {
      HttpHeaders headers = new HttpHeaders();
      headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      HttpEntity<Product> entity = new HttpEntity<Product>(product,headers);
      
      return restTemplate.exchange(
         "https://127.0.0.1:8080/products/"+id, HttpMethod.PUT, entity, String.class).getBody();
   }
   @RequestMapping(value = "/template/products/{id}", method = RequestMethod.DELETE)
   public String deleteProduct(@PathVariable("id") String id) {
      HttpHeaders headers = new HttpHeaders();
      headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      HttpEntity<Product> entity = new HttpEntity<Product>(headers);
      
      return restTemplate.exchange(
         "https://127.0.0.1:8080/products/"+id, HttpMethod.DELETE, entity, String.class).getBody();
   }
}

Spring Boot 应用程序类 - DemoApplication.java 的代码如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

Maven 构建 - 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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

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

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle 构建 - build.gradle 的代码如下所示:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,您可以使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

“构建成功”后,您可以在 build/libs 目录下找到 JAR 文件。

现在,使用以下命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8080 上启动。

Started Application on Tomcat Port_8080

现在在 POSTMAN 应用程序中点击以下 URL,您可以看到输出。

通过 Rest Template 获取产品 - **https://127.0.0.1:8080/template/products**

GET Products by Rest Template

创建产品 POST - **https://127.0.0.1:8080/template/products**

Create Products POST

更新产品 PUT - **https://127.0.0.1:8080/template/products/3**

Update Products POST

删除产品 - **https://127.0.0.1:8080/template/products/3**

Delete Products POST

Spring Boot - 文件处理

在本章中,您将学习如何使用 Web 服务上传和下载文件。

文件上传

要上传文件,您可以使用 **MultipartFile** 作为请求参数,并且此 API 应使用多部分表单数据值。观察下面给出的代码:

@RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)

public String fileUpload(@RequestParam("file") MultipartFile file) {
   return null;
}

完整的代码如下所示:

package com.tutorialspoint.demo.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class FileUploadController {
   @RequestMapping(value = "/upload", method = RequestMethod.POST, 
      consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
   
   public String fileUpload(@RequestParam("file") MultipartFile file) throws IOException {
      File convertFile = new File("/var/tmp/"+file.getOriginalFilename());
      convertFile.createNewFile();
      FileOutputStream fout = new FileOutputStream(convertFile);
      fout.write(file.getBytes());
      fout.close();
      return "File is upload successfully";
   }
}

文件下载

对于文件下载,您应该使用 InputStreamResource 下载文件。我们需要在响应中设置 HttpHeader **Content-Disposition**,并需要指定应用程序的响应媒体类型。

**注意** - 在以下示例中,文件应在应用程序运行的指定路径上可用。

@RequestMapping(value = "/download", method = RequestMethod.GET) 
public ResponseEntity<Object> downloadFile() throws IOException  {
   String filename = "/var/tmp/mysql.png";
   File file = new File(filename);
   InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
   HttpHeaders headers = new HttpHeaders();
      
   headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));
   headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
   headers.add("Pragma", "no-cache");
   headers.add("Expires", "0");
      
   ResponseEntity<Object> 
   responseEntity = ResponseEntity.ok().headers(headers).contentLength(file.length()).contentType(
      MediaType.parseMediaType("application/txt")).body(resource);
      
   return responseEntity;
}

完整的代码如下所示:

package com.tutorialspoint.demo.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FileDownloadController {
   @RequestMapping(value = "/download", method = RequestMethod.GET) 
   public ResponseEntity<Object> downloadFile() throws IOException  {
      String filename = "/var/tmp/mysql.png";
      File file = new File(filename);
      InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
      HttpHeaders headers = new HttpHeaders();
      
      headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", file.getName()));
      headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
      headers.add("Pragma", "no-cache");
      headers.add("Expires", "0");
      
      ResponseEntity<Object> 
      responseEntity = ResponseEntity.ok().headers(headers).contentLength(
         file.length()).contentType(MediaType.parseMediaType("application/txt")).body(resource);
      
      return responseEntity;
   }
}

主 Spring Boot 应用程序如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

Maven 构建 - 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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

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

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle 构建 - build.gradle 的代码如下所示:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

现在您可以创建一个可执行的 JAR 文件,并使用下面给出的 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在 target 目录下找到 JAR 文件。

对于 Gradle,您可以使用以下命令:

sgradle clean build

“构建成功”后,您可以在 build/libs 目录下找到 JAR 文件。

现在,使用以下命令运行 JAR 文件:

java –jar <JARFILE> 

这将在Tomcat端口8080上启动应用程序,如下所示:

POSTMAN Application

现在在 POSTMAN 应用程序中访问以下 URL,您将看到以下输出:

文件上传 - https://127.0.0.1:8080/upload

POSTMAN application File Upload

文件下载 - https://127.0.0.1:8080/upload

Spring Boot - 服务组件

服务组件是包含 @Service 注解的类文件。这些类文件用于在不同的层编写业务逻辑,与 @RestController 类文件分离。创建服务组件类文件的逻辑如下所示:

public interface ProductService {
}

实现带有 @Service 注解的接口的类如下所示:

@Service
public class ProductServiceImpl implements ProductService {
}

请注意,在本教程中,我们使用 产品服务 API 来存储、检索、更新和删除产品。我们在 @RestController 类文件中本身编写了业务逻辑。现在,我们将业务逻辑代码从控制器移到服务组件。

您可以创建一个包含添加、编辑、获取和删除方法的接口,使用以下代码所示:

package com.tutorialspoint.demo.service;

import java.util.Collection;
import com.tutorialspoint.demo.model.Product;

public interface ProductService {
   public abstract void createProduct(Product product);
   public abstract void updateProduct(String id, Product product);
   public abstract void deleteProduct(String id);
   public abstract Collection<Product> getProducts();
}

以下代码将允许您创建一个实现 ProductService 接口并带有 @Service 注解的类,并编写存储、检索、删除和更新产品的业务逻辑。

package com.tutorialspoint.demo.service;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.tutorialspoint.demo.model.Product;

@Service
public class ProductServiceImpl implements ProductService {
   private static Map<String, Product> productRepo = new HashMap<>();
   static {
      Product honey = new Product();
      honey.setId("1");
      honey.setName("Honey");
      productRepo.put(honey.getId(), honey);

      Product almond = new Product();
      almond.setId("2");
      almond.setName("Almond");
      productRepo.put(almond.getId(), almond);
   }
   @Override
   public void createProduct(Product product) {
      productRepo.put(product.getId(), product);
   }
   @Override
   public void updateProduct(String id, Product product) {
      productRepo.remove(id);
      product.setId(id);
      productRepo.put(id, product);
   }
   @Override
   public void deleteProduct(String id) {
      productRepo.remove(id);

   }
   @Override
   public Collection<Product> getProducts() {
      return productRepo.values();
   }
}

此处的代码显示了 Rest Controller 类文件,这里我们 @Autowired 了 ProductService 接口并调用了其方法。

package com.tutorialspoint.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.tutorialspoint.demo.model.Product;
import com.tutorialspoint.demo.service.ProductService;

@RestController
public class ProductServiceController {
   @Autowired
   ProductService productService;

   @RequestMapping(value = "/products")
   public ResponseEntity<Object> getProduct() {
      return new ResponseEntity<>(productService.getProducts(), HttpStatus.OK);
   }
   @RequestMapping(value = "/products/{id}", method = RequestMethod.PUT)
   public ResponseEntity<Object> 
      updateProduct(@PathVariable("id") String id, @RequestBody Product product) {
      
      productService.updateProduct(id, product);
      return new ResponseEntity<>("Product is updated successsfully", HttpStatus.OK);
   }
   @RequestMapping(value = "/products/{id}", method = RequestMethod.DELETE)
   public ResponseEntity<Object> delete(@PathVariable("id") String id) {
      productService.deleteProduct(id);
      return new ResponseEntity<>("Product is deleted successsfully", HttpStatus.OK);
   }
   @RequestMapping(value = "/products", method = RequestMethod.POST)
   public ResponseEntity<Object> createProduct(@RequestBody Product product) {
      productService.createProduct(product);
      return new ResponseEntity<>("Product is created successfully", HttpStatus.CREATED);
   }
}

此处显示了 POJO 类 – Product.java 的代码:

package com.tutorialspoint.demo.model;

public class Product {
   private String id;
   private String name;

   public String getId() {
      return id;
   }
   public void setId(String id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

下面给出一个主要的 Spring Boot 应用程序:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

下面显示了 Maven 构建 - 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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

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

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>

</project>

下面显示了 Gradle 构建 - build.gradle 的代码:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

您可以创建一个可执行的 JAR 文件,并使用下面给出的 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,请使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

“构建成功”后,您可以在 build/libs 目录下找到 JAR 文件。

使用以下命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8080 上启动,如下图所示:

BUILD SUCCESSFUL

现在在 POSTMAN 应用程序中访问以下 URL,您将看到以下输出:

GET API URL 为 - https://127.0.0.1:8080/products

Postman Application GET API URL

POST API URL 为 - https://127.0.0.1:8080/products

Postman Application POST API URL

PUT API URL 为 - https://127.0.0.1:8080/products/3

Postman Application PUT API URL

DELETE API URL 为 - https://127.0.0.1:8080/products/3

Postman Application DELETE API URL

Spring Boot - Thymeleaf

Thymeleaf 是一个基于 Java 的库,用于创建 Web 应用程序。它为在 Web 应用程序中提供 XHTML/HTML5 提供了良好的支持。在本章中,您将详细了解 Thymeleaf。

Thymeleaf 模板

Thymeleaf 将您的文件转换为格式良好的 XML 文件。它包含以下 6 种类型的模板:

  • XML
  • 有效 XML
  • XHTML
  • 有效 XHTML
  • HTML5
  • 传统 HTML5

除了传统 HTML5 之外的所有模板都指的是格式良好的有效 XML 文件。传统 HTML5 允许我们在网页中呈现 HTML5 标签,包括未关闭的标签。

Web 应用程序

您可以使用 Thymeleaf 模板在 Spring Boot 中创建 Web 应用程序。您需要按照以下步骤使用 Thymeleaf 在 Spring Boot 中创建 Web 应用程序。

使用以下代码创建一个 @Controller 类文件,将请求 URI 重定向到 HTML 文件:

package com.tutorialspoint.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class WebController {
   @RequestMapping(value = "/index")
   public String index() {
      return "index";
   }
}

在上面的示例中,请求 URI 为 /index,并将控制权重定向到 index.html 文件。请注意,index.html 文件应放置在 templates 目录下,所有 JS 和 CSS 文件应放置在类路径中的 static 目录下。在所示的示例中,我们使用 CSS 文件来更改文本的颜色。

您可以使用以下代码并在单独的文件夹 css 中创建一个 CSS 文件,并将文件命名为 styles.css:

h4 {
   color: red;
}

下面给出了 index.html 文件的代码:

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "ISO-8859-1" />
      <link href = "css/styles.css" rel = "stylesheet"/>
      <title>Spring Boot Application</title>
   </head>
   <body>
      <h4>Welcome to Thymeleaf Spring Boot web application</h4>
   </body>
</html>

下面给出了项目资源管理器的屏幕截图:

Project Explorer Screenshot

现在,我们需要在构建配置文件中添加 Spring Boot Starter Thymeleaf 依赖项。

Maven 用户可以将以下依赖项添加到 pom.xml 文件中:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项:

compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'

主 Spring Boot 应用程序类文件的代码如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

下面给出了 Maven - 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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

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

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

下面给出了 Gradle - build.gradle 的代码:

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 spring boot 应用程序:

对于 Maven,请使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,请使用如下所示的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

使用此处给出的命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8080 上启动,如下所示:

Started Application on Tomcat Port_8080

现在在您的 Web 浏览器中访问该 URL,您将看到以下输出:

https://127.0.0.1:8080/index

Spring Boot Thymleaf web Application

使用 RESTful Web 服务

本章将详细讨论如何使用 jQuery AJAX 使用 RESTful Web 服务。

创建一个简单的 Spring Boot Web 应用程序,并编写一个控制器类文件,该文件用于重定向到 HTML 文件以使用 RESTful Web 服务。

我们需要在构建配置文件中添加 Spring Boot starter Thymeleaf 和 Web 依赖项。

对于 Maven 用户,请在您的 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

对于 Gradle 用户,请在您的 build.gradle 文件中添加以下依赖项:

compile group: ‘org.springframework.boot’, name: ‘spring-boot-starter-thymeleaf’
compile(‘org.springframework.boot:spring-boot-starter-web’)

下面给出了 @Controller 类文件的代码:

@Controller
public class ViewController {
}

您可以定义请求 URI 方法以重定向到 HTML 文件,如下所示:

@RequestMapping(“/view-products”)
public String viewProducts() {
   return “view-products”;
}
@RequestMapping(“/add-products”)
public String addProducts() {
   return “add-products”;
}

此 API https://127.0.0.1:9090/products 应在响应中返回以下 JSON,如下所示:

[
   {
      "id": "1",
      "name": "Honey"
   },
   {
      "id": "2",
      "name": "Almond"
   }
]

现在,在类路径中的 templates 目录下创建一个 view-products.html 文件。

在 HTML 文件中,我们添加了 jQuery 库并编写了在页面加载时使用 RESTful Web 服务的代码。

<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<script>
$(document).ready(function(){
   $.getJSON("https://127.0.0.1:9090/products", function(result){
      $.each(result, function(key,value) {
         $("#productsJson").append(value.id+" "+value.name+" ");
      }); 
   });
});
</script>

POST 方法和此 URL https://127.0.0.1:9090/products 应包含以下请求正文和响应正文。

下面给出了请求正文的代码:

{
   "id":"3",
   "name":"Ginger"
}

下面给出了响应正文的代码:

Product is created successfully

现在,在类路径中的 templates 目录下创建 add-products.html 文件。

在 HTML 文件中,我们添加了 jQuery 库并编写了在单击按钮时将表单提交到 RESTful Web 服务的代码。

<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
   $(document).ready(function() {
      $("button").click(function() {
         var productmodel = {
            id : "3",
            name : "Ginger"
         };
         var requestJSON = JSON.stringify(productmodel);
         $.ajax({
            type : "POST",
            url : "https://127.0.0.1:9090/products",
            headers : {
               "Content-Type" : "application/json"
            },
            data : requestJSON,
            success : function(data) {
               alert(data);
            },
            error : function(data) {
            }
         });
      });
   });
</script>

下面给出了完整的代码。

Maven - 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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

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

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

下面给出了 Gradle - build.gradle 的代码:

buildscript {
   ext {
      springBootVersion = ‘1.5.8.RELEASE’
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: ‘java’
apply plugin: ‘eclipse’
apply plugin: ‘org.springframework.boot’

group = ‘com.tutorialspoint’
version = ‘0.0.1-SNAPSHOT’
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}

dependencies {
   compile(‘org.springframework.boot:spring-boot-starter-web’)
   compile group: ‘org.springframework.boot’, name: ‘spring-boot-starter-thymeleaf’
   testCompile(‘org.springframework.boot:spring-boot-starter-test’)
}

下面给出了控制器类文件 - ViewController.java:

package com.tutorialspoint.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ViewController {
   @RequestMapping(“/view-products”)
   public String viewProducts() {
      return “view-products”;
   }
   @RequestMapping(“/add-products”)
   public String addProducts() {
      return “add-products”;   
   }   
}

下面给出了 view-products.html 文件:

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "ISO-8859-1"/>
      <title>View Products</title>
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
      
      <script>
         $(document).ready(function(){
            $.getJSON("https://127.0.0.1:9090/products", function(result){
               $.each(result, function(key,value) {
                  $("#productsJson").append(value.id+" "+value.name+" ");
               }); 
            });
         });
      </script>
   </head>
   
   <body>
      <div id = "productsJson"> </div>
   </body>
</html>

下面给出了 add-products.html 文件:

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "ISO-8859-1" />
      <title>Add Products</title>
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
      
      <script>
         $(document).ready(function() {
            $("button").click(function() {
               var productmodel = {
                  id : "3",
                  name : "Ginger"
               };
               var requestJSON = JSON.stringify(productmodel);
               $.ajax({
                  type : "POST",
                  url : "https://127.0.0.1:9090/products",
                  headers : {
                     "Content-Type" : "application/json"
                  },
                  data : requestJSON,
                  success : function(data) {
                     alert(data);
                  },
                  error : function(data) {
                  }
               });
            });
         });
      </script>
   </head>
   
   <body>
      <button>Click here to submit the form</button>
   </body>
</html>

下面给出了主 Spring Boot 应用程序类文件:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

现在,您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,请使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,请使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

使用以下命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8080 上启动。

Started Application on Tomcat Port_8080

现在在您的 Web 浏览器中访问该 URL,您将看到以下输出:

https://127.0.0.1:8080/view-products

1Honey_2Almond

https://127.0.0.1:8080/add-products

Submit Form Spring Boot

现在,单击 点击此处提交表单 按钮,您将看到以下结果:

Submit Form Spring Boot Output Window

现在,访问查看产品 URL 并查看创建的产品。

https://127.0.0.1:8080/view-products

1Honey 2Almond 3Ginger

Angular JS

要使用 Angular JS 使用 API,您可以使用以下示例:

使用以下代码创建 Angular JS 控制器以使用 GET API - https://127.0.0.1:9090/products

angular.module('demo', [])
.controller('Hello', function($scope, $http) {
   $http.get('https://127.0.0.1:9090/products').
   then(function(response) {
      $scope.products = response.data;
   });
});

使用以下代码创建 Angular JS 控制器以使用 POST API - https://127.0.0.1:9090/products

angular.module('demo', [])
.controller('Hello', function($scope, $http) {
   $http.post('https://127.0.0.1:9090/products',data).
   then(function(response) {
      console.log("Product created successfully");
   });
});

注意 - Post 方法数据表示以 JSON 格式创建产品的请求正文。

Spring Boot - CORS 支持

跨源资源共享 (CORS) 是一种安全概念,允许限制在 Web 浏览器中实现的资源。它可以防止 JavaScript 代码针对不同来源生成或使用请求。

例如,您的 Web 应用程序正在 8080 端口上运行,并且您正在使用 JavaScript 尝试从 9090 端口使用 RESTful Web 服务。在这种情况下,您将在 Web 浏览器上遇到跨源资源共享安全问题。

解决此问题需要两个要求:

  • RESTful Web 服务应支持跨源资源共享。

  • RESTful Web 服务应用程序应允许从 8080 端口访问 API。

在本章中,我们将详细了解如何为 RESTful Web 服务应用程序启用跨源请求。

在控制器方法中启用 CORS

我们需要使用 @CrossOrigin 注解为控制器方法设置 RESTful Web 服务的来源。此 @CrossOrigin 注解支持特定的 REST API,而不是整个应用程序。

@RequestMapping(value = "/products")
@CrossOrigin(origins = "https://127.0.0.1:8080")

public ResponseEntity<Object> getProduct() {
   return null;
}

全局 CORS 配置

我们需要定义所示的 @Bean 配置以全局地将 CORS 配置支持设置为您的 Spring Boot 应用程序。

@Bean
public WebMvcConfigurer corsConfigurer() {
   return new WebMvcConfigurerAdapter() {
      @Override
      public void addCorsMappings(CorsRegistry registry) {
         registry.addMapping("/products").allowedOrigins("https://127.0.0.1:9000");
      }    
   };
}

下面给出了在主 Spring Boot 应用程序中全局设置 CORS 配置的代码。

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @Bean
   public WebMvcConfigurer corsConfigurer() {
      return new WebMvcConfigurerAdapter() {
         @Override
         public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/products").allowedOrigins("https://127.0.0.1:8080");
         }
      };
   }
}

现在,您可以创建一个在 8080 端口上运行的 Spring Boot Web 应用程序,以及可以在 9090 端口上运行的 RESTful Web 服务应用程序。有关 RESTful Web 服务实现的更多详细信息,您可以参考本教程中标题为 使用 RESTful Web 服务 的章节。

Spring Boot - 国际化

国际化是一个使您的应用程序能够适应不同的语言和地区而无需对源代码进行工程更改的过程。换句话说,国际化是本地化的准备。

在本章中,我们将详细了解如何在 Spring Boot 中实现国际化。

依赖项

我们需要 Spring Boot Starter Web 和 Spring Boot Starter Thymeleaf 依赖项才能在 Spring Boot 中开发 Web 应用程序。

Maven

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Gradle

compile('org.springframework.boot:spring-boot-starter-web')
compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'

LocaleResolver

我们需要确定应用程序的默认语言环境。我们需要在 Spring Boot 应用程序中添加 LocaleResolver bean。

@Bean
public LocaleResolver localeResolver() {
   SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
   sessionLocaleResolver.setDefaultLocale(Locale.US);
   return sessionLocaleResolver;
}

LocaleChangeInterceptor

LocaleChangeInterceptor 用于根据添加到请求中的语言参数的值更改新的语言环境。

@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
   LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
   localeChangeInterceptor.setParamName("language");
   return localeChangeInterceptor;
}

为了实现此效果,我们需要将 LocaleChangeInterceptor 添加到应用程序的注册拦截器中。配置类应扩展 WebMvcConfigurerAdapter 类并覆盖 addInterceptors() 方法。

@Override
public void addInterceptors(InterceptorRegistry registry) {
   registry.addInterceptor(localeChangeInterceptor());
}

消息源

Spring Boot 应用程序默认从类路径下的src/main/resources文件夹获取消息源。默认语言环境的消息文件名应为message.properties,每个语言环境的文件应命名为messages_XX.properties。“XX”表示语言环境代码。

所有消息属性都应作为键值对使用。如果在语言环境中找不到任何属性,则应用程序使用 messages.properties 文件中的默认属性。

默认的 messages.properties 将如下所示:

welcome.text=Hi Welcome to Everyone

法语 messages_fr.properties 将如下所示:

welcome.text=Salut Bienvenue à tous

注意 - 消息源文件应保存为“UTF-8”文件格式。

HTML 文件

在 HTML 文件中,使用语法#{key}显示属性文件中的消息。

<h1 th:text = "#{welcome.text}"></h1>

完整的代码如下所示

Maven – 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.tutorialspoint</groupId>
   <artifactId>demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>demo</name>
   <description>Demo project for Spring Boot</description>

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

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

主要的 Spring Boot 应用程序类文件如下所示:

package com.tutorialspoint.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

控制器类文件如下所示:

package com.tutorialspoint.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ViewController {
   @RequestMapping("/locale")
   public String locale() {
      return "locale";
   }
}

支持国际化的配置类

package com.tutorialspoint.demo;

import java.util.Locale;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;

@Configuration
public class Internationalization extends WebMvcConfigurerAdapter {
   @Bean
   public LocaleResolver localeResolver() {
      SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
      sessionLocaleResolver.setDefaultLocale(Locale.US);
      return sessionLocaleResolver;
   }
   @Bean
   public LocaleChangeInterceptor localeChangeInterceptor() {
      LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
      localeChangeInterceptor.setParamName("language");
      return localeChangeInterceptor;
   }
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(localeChangeInterceptor());
   }
}

消息源 – messages.properties 如下所示:

welcome.text = Hi Welcome to Everyone

消息源 – message_fr.properties 如下所示:

welcome.text = Salut Bienvenue à tous

HTML 文件 locale.html 应放置在类路径下的 templates 目录下,如下所示:

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "ISO-8859-1"/>
      <title>Internationalization</title>
   </head>
   <body>
      <h1 th:text = "#{welcome.text}"></h1>
   </body>
</html>

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用如下所示的命令运行 JAR 文件:

java –jar <JARFILE> 

您会发现应用程序已在 Tomcat 端口 8080 上启动。

Started Application on Tomcat Port_8080

现在在您的 Web 浏览器中访问 URL https://127.0.0.1:8080/locale,您将看到以下输出:

Output Web Browser

URL https://127.0.0.1:8080/locale?language=fr 将为您提供如下所示的输出:

Output Web Browser Salut Bienvenue

Spring Boot - 调度

调度是按特定时间段执行任务的过程。Spring Boot 为在 Spring 应用程序上编写调度程序提供了良好的支持。

Java Cron 表达式

Java Cron 表达式用于配置 CronTrigger 的实例,CronTrigger 是 org.quartz.Trigger 的子类。有关 Java cron 表达式的更多信息,您可以参考此链接:

https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm

@EnableScheduling 注解用于为您的应用程序启用调度程序。此注解应添加到主 Spring Boot 应用程序类文件中。

@SpringBootApplication
@EnableScheduling

public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

@Scheduled 注解用于在特定时间段内触发调度程序。

@Scheduled(cron = "0 * 9 * * ?")
public void cronJobSch() throws Exception {
}

以下是一个示例代码,它演示了如何每天从上午 9:00 开始到上午 9:59 结束,每分钟执行一次任务

package com.tutorialspoint.demo.scheduler;

import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class Scheduler {
   @Scheduled(cron = "0 * 9 * * ?")
   public void cronJobSch() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
      Date now = new Date();
      String strDate = sdf.format(now);
      System.out.println("Java cron job expression:: " + strDate);
   }
}

以下屏幕截图显示了应用程序如何在 09:03:23 启动,以及从那时起每分钟执行一次 cron 作业调度程序任务。

cron job scheduler

固定速率

固定速率调度程序用于在特定时间执行任务。它不会等待上一个任务完成。值应以毫秒为单位。示例代码如下所示:

@Scheduled(fixedRate = 1000)
public void fixedRateSch() { 
}

这里有一个示例代码,用于从应用程序启动开始每秒执行一次任务:

package com.tutorialspoint.demo.scheduler;

import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class Scheduler {
   @Scheduled(fixedRate = 1000)
   public void fixedRateSch() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

      Date now = new Date();
      String strDate = sdf.format(now);
      System.out.println("Fixed Rate scheduler:: " + strDate);
   }
}

观察以下屏幕截图,它显示了应用程序在 09:12:00 启动,之后每秒执行一次固定速率调度程序任务。

Fixed Rate Scheduler Task Executed

固定延迟

固定延迟调度程序用于在特定时间执行任务。它应该等待上一个任务完成。值应以毫秒为单位。示例代码如下所示:

@Scheduled(fixedDelay = 1000, initialDelay = 1000)
public void fixedDelaySch() {
}

这里,initialDelay 是应用程序启动后第一次执行任务之前需要等待的时间(以毫秒为单位)。

以下是一个示例,演示如何在应用程序启动完成后 3 秒后每秒执行一次任务:

package com.tutorialspoint.demo.scheduler;

import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class Scheduler {
   @Scheduled(fixedDelay = 1000, initialDelay = 3000)
   public void fixedDelaySch() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
      Date now = new Date();
      String strDate = sdf.format(now);
      System.out.println("Fixed Delay scheduler:: " + strDate);
   }
}

观察以下屏幕截图,它显示了应用程序在 09:18:39 启动,并且每 3 秒后,固定延迟调度程序任务每秒执行一次。

Fixed Delay Scheduler Task Executed

Spring Boot - 启用 HTTPS

默认情况下,Spring Boot 应用程序在启动时使用 HTTP 8080 端口。

Started Application on Tomcat port_8080

您需要按照以下步骤在 Spring Boot 应用程序中配置 HTTPS 和端口 443:

  • 获取 SSL 证书 - 创建自签名证书或从证书颁发机构获取证书

  • 启用 HTTPS 和 443 端口

自签名证书

要创建自签名证书,Java 运行时环境附带证书管理实用程序 keytool。此实用程序用于创建自签名证书。它在以下代码中显示:

keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
Enter keystore password:
   Re-enter new password:
   What is your first and last name?
   [Unknown]:
   What is the name of your organizational unit?
   [Unknown]:
   What is the name of your organization?
   [Unknown]:
   What is the name of your City or Locality?
   [Unknown]:
   What is the name of your State or Province?
   [Unknown]:
   What is the two-letter country code for this unit?
   [Unknown]:
   Is CN = Unknown, OU=Unknown, O = Unknown, L = Unknown, ST = Unknown, C = Unknown correct?
   [no]: yes

此代码将生成一个名为 keystore.p12 的 PKCS12 密钥库文件,证书别名名为 tomcat。

配置 HTTPS

我们需要将服务器端口设置为 443,并将密钥库文件路径、密钥库密码、密钥库类型和密钥别名提供给 application.properties 文件。请观察以下代码:

server.port: 443
server.ssl.key-store: keystore.p12
server.ssl.key-store-password: springboot
server.ssl.keyStoreType: PKCS12
server.ssl.keyAlias: tomcat

如果您使用 YAML 属性,则可以使用以下 application.yml:

server:
   port: 443
   ssl:
      key-store: keystore.p12
      key-store-password: springboot
      keyStoreType: PKCS12
      keyAlias: tomcat

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用以下命令运行 JAR 文件:

java –jar <JARFILE>

现在,应用程序已在 Tomcat 端口 443 上启动,并使用 https,如下所示:

Started Application on Tomcat Port 443

Spring Boot - Eureka 服务器

Eureka Server 是一个应用程序,它保存有关所有客户端服务应用程序的信息。每个微服务都将注册到 Eureka 服务器,并且 Eureka 服务器知道在每个端口和 IP 地址上运行的所有客户端应用程序。Eureka Server 也称为发现服务器。

在本章中,我们将详细了解如何构建 Eureka 服务器。

构建 Eureka 服务器

Eureka Server 与 Spring Cloud 捆绑在一起。为此,我们需要开发 Eureka 服务器并在默认端口 8761 上运行它。

访问 Spring Initializer 主页 https://start.spring.io/ 并下载带有 Eureka 服务器依赖项的 Spring Boot 项目。它在下面的屏幕截图中显示:

Build Eureka Server

在主 Spring Boot 应用程序类文件中下载项目后,我们需要添加 @EnableEurekaServer 注解。@EnableEurekaServer 注解用于使您的 Spring Boot 应用程序充当 Eureka 服务器。

主 Spring Boot 应用程序类文件的代码如下所示:

package com.tutorialspoint.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaserverApplication {
   public static void main(String[] args) {
      SpringApplication.run(EurekaserverApplication.class, args);
   }
}

确保在您的构建配置文件中添加了 Spring Cloud Eureka Server 依赖项。

Maven 用户依赖项的代码如下所示:

<dependency>
<groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>

Gradle 用户依赖项的代码如下所示:

compile('org.springframework.cloud:spring-cloud-starter-eureka-server')

完整的构建配置文件如下所示:

Maven 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.tutorialspoint</groupId>
   <artifactId>eurekaserver</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>eurekaserver</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-eureka-server</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
ext {
   springCloudVersion = 'Edgware.RELEASE'
}
dependencies {
   compile('org.springframework.cloud:spring-cloud-starter-eureka-server')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
   }
}

默认情况下,Eureka Server 将自身注册到发现中。您应该将以下给定的配置添加到您的 application.properties 文件或 application.yml 文件中。

application.properties 文件如下所示:

eureka.client.registerWithEureka = false
eureka.client.fetchRegistry = false
server.port = 8761

application.yml 文件如下所示:

eureka:
   client:
      registerWithEureka: false
      fetchRegistry: false
server:
   port: 8761

现在,您可以创建一个可执行的 JAR 文件,并使用以下所示的 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,请使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用以下命令运行 JAR 文件:

 java –jar <JARFILE> 

您会发现应用程序已在 Tomcat 端口 8761 上启动,如下所示:

Application Started on  Tomcat Port 8761

现在,在您的 Web 浏览器中访问 URL https://127.0.0.1:8761/,您会发现 Eureka Server 在端口 8761 上运行,如下所示:

Eureka Server Running on port 8761

使用 Eureka 注册服务

在本章中,您将详细了解如何将 Spring Boot 微服务应用程序注册到 Eureka Server。在注册应用程序之前,请确保 Eureka Server 在端口 8761 上运行,或者先构建 Eureka Server 并运行它。有关构建 Eureka 服务器的更多信息,您可以参考上一章。

首先,您需要在我们的构建配置文件中添加以下依赖项,以便将微服务注册到 Eureka 服务器。

Maven 用户可以将以下依赖项添加到pom.xml文件中:

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

Gradle 用户可以将以下依赖项添加到build.gradle文件中:

compile('org.springframework.cloud:spring-cloud-starter-eureka')

现在,我们需要在主 Spring Boot 应用程序类文件中添加 @EnableEurekaClient 注解。@EnableEurekaClient 注解使您的 Spring Boot 应用程序充当 Eureka 客户端。

主 Spring Boot 应用程序如下所示:

package com.tutorialspoint.eurekaclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class EurekaclientApplication {
   public static void main(String[] args) {
      SpringApplication.run(EurekaclientApplication.class, args);
   }
}

要将 Spring Boot 应用程序注册到 Eureka Server,我们需要在我们的 application.properties 文件或 application.yml 文件中添加以下配置,并在我们的配置中指定 Eureka Server URL。

application.yml 文件的代码如下所示:

eureka:
   client:
      serviceUrl:
         defaultZone: https://127.0.0.1:8761/eureka
      instance:
      preferIpAddress: true
spring:
   application:
      name: eurekaclient

application.properties 文件的代码如下所示:

eureka.client.serviceUrl.defaultZone  = https://127.0.0.1:8761/eureka
eureka.client.instance.preferIpAddress = true
spring.application.name = eurekaclient

现在,添加 Rest 端点以在主 Spring Boot 应用程序中返回字符串,并在构建配置文件中添加 Spring Boot Starter Web 依赖项。请观察以下代码:

package com.tutorialspoint.eurekaclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableEurekaClient
@RestController
public class EurekaclientApplication {
   public static void main(String[] args) {
      SpringApplication.run(EurekaclientApplication.class, args);
   }
   @RequestMapping(value = "/")
   public String home() {
      return "Eureka Client application";
   }
}

整个配置文件如下所示。

对于 Maven 用户 - 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.tutorialspoint</groupId>
   <artifactId>eurekaclient</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>eurekaclient</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-eureka</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>
   
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>   
   </build>
   
</projecta>

对于 Gradle 用户 – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
ext {
   springCloudVersion = 'Edgware.RELEASE'
}
dependencies {
   compile('org.springframework.cloud:spring-cloud-starter-eureka')
   testCompile('org.springframework.boot:spring-boot-starter-test')
   compile('org.springframework.boot:spring-boot-starter-web')   
}
dependencyManagement {
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
   }
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,您可以使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用如下所示的命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8080 上启动,并且 Eureka Client 应用程序已注册到 Eureka Server,如下所示:

Started Application on Tomcat Port

在您的 Web 浏览器中访问 URL https://127.0.0.1:8761/,您会看到 Eureka Client 应用程序已注册到 Eureka Server。

Eureka Client Application

现在在您的 Web 浏览器中访问 URL https://127.0.0.1:8080/,并查看 Rest 端点的输出。

Eureka Client Application Output

Spring Boot - Zuul 代理服务器和路由

Zuul Server 是一个网关应用程序,它处理所有请求并执行微服务应用程序的动态路由。Zuul Server 也称为边缘服务器。

例如,/api/user 映射到用户服务,/api/products 映射到产品服务,Zuul Server 会动态地将请求路由到相应的后端应用程序。

在本章中,我们将详细了解如何在 Spring Boot 中创建 Zuul Server 应用程序。

创建 Zuul Server 应用程序

Zuul 服务器与 Spring Cloud 依赖项捆绑在一起。您可以从 Spring Initializer 页面https://start.spring.io/下载 Spring Boot 项目,并选择 Zuul Server 依赖项。

Creating Zuul Server Application

在您的主 Spring Boot 应用程序上添加 @EnableZuulProxy 注解。@EnableZuulProxy 注解用于使您的 Spring Boot 应用程序充当 Zuul 代理服务器。

package com.tutorialspoint.zuulserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
public class ZuulserverApplication {
   public static void main(String[] args) {
      SpringApplication.run(ZuulserverApplication.class, args);
   }
}

您需要在构建配置文件中添加 Spring Cloud Starter Zuul 依赖项。

Maven 用户需要在您的 pom.xml 文件中添加以下依赖项:

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

对于 Gradle 用户,请在您的 build.gradle 文件中添加以下依赖项:

compile('org.springframework.cloud:spring-cloud-starter-zuul')

对于 Zuul 路由,请在您的 application.properties 文件或 application.yml 文件中添加以下属性。

spring.application.name = zuulserver
zuul.routes.products.path = /api/demo/**
zuul.routes.products.url = https://127.0.0.1:8080/
server.port = 8111

这意味着对 /api/demo/ 的 http 调用将转发到产品服务。例如,/api/demo/products 将转发到 /products

yaml 文件用户可以使用以下所示的 application.yml 文件:

server:
   port: 8111
spring:
   application:  
      name: zuulserver
zuul:

routes:
   products:
      path: /api/demo/**
      url: https://127.0.0.1:8080/

注意 - 在通过 Zuul 代理进行路由之前,https://127.0.0.1:8080/ 应用程序应已在运行。

完整的构建配置文件如下所示。

Maven 用户可以使用以下提供的 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.tutorialspoint</groupId>
   <artifactId>zuulserver</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>zuulserver</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-zuul</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>

Gradle 用户可以使用以下提供的 build.gradle 文件:

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
ext {
   springCloudVersion = 'Edgware.RELEASE'
}
dependencies {
   compile('org.springframework.cloud:spring-cloud-starter-zuul')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
   }
}

您可以创建一个可执行的 JAR 文件,并使用下面给出的 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下提供的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用以下显示的命令运行 JAR 文件:

java –jar <JARFILE> 

您会发现应用程序已在 Tomcat 端口 8111 上启动,如下所示。

Started Application on Tomcat Port_8111

现在,在您的 Web 浏览器中访问 URL https://127.0.0.1:8111/api/demo/products,您可以看到 /products REST 端点的输出,如下所示:

Products REST Endpoint

Spring Boot - 云配置服务器

Spring Cloud Configuration Server 是一个集中式应用程序,用于管理所有与应用程序相关的配置属性。在本节中,您将详细了解如何创建 Spring Cloud Configuration 服务器。

创建 Spring Cloud Configuration 服务器

首先,从 Spring Initializer 页面下载 Spring Boot 项目,并选择 Spring Cloud Config Server 依赖项。请观察以下屏幕截图:

Creating Spring Cloud Configuration Server

现在,在您的构建配置文件中添加 Spring Cloud Config 服务器依赖项,如下所述:

Maven 用户可以将以下依赖项添加到 pom.xml 文件中。

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-config-server</artifactId>
</dependency>

Gradle 用户可以在您的 build.gradle 文件中添加以下依赖项。

compile('org.springframework.cloud:spring-cloud-config-server')

现在,在您的主 Spring Boot 应用程序类文件中添加 @EnableConfigServer 注解。@EnableConfigServer 注解使您的 Spring Boot 应用程序充当配置服务器。

主要的 Spring Boot 应用程序类文件如下所示:

package com.tutorialspoint.configserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class ConfigserverApplication {
   public static void main(String[] args) {
      SpringApplication.run(ConfigserverApplication.class, args);
   }
}

现在,将以下配置添加到您的属性文件中,并将 application.properties 文件替换为 bootstrap.properties 文件。请观察以下代码:

server.port = 8888
spring.cloud.config.server.native.searchLocations=file:///C:/configprop/
SPRING_PROFILES_ACTIVE=native

配置服务器在 Tomcat 端口 8888 上运行,并且应用程序配置属性从本机搜索位置加载。

现在,在 file:///C:/configprop/ 中,放置您的客户端应用程序 - application.properties 文件。例如,您的客户端应用程序名称为 config-client,则将您的 application.properties 文件重命名为 config-client.properties 并将属性文件放置在路径 file:///C:/configprop/ 上。

config-client 属性文件的代码如下所示:

welcome.message = Welcome to Spring cloud config server

完整的构建配置文件如下所示:

Maven 用户可以使用以下提供的 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.tutorialspoint</groupId>
   <artifactId>configserver</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>configserver</name>
   <description>Demo project for Spring Boot</description>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-config-server</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle 用户可以使用以下提供的 build.gradle 文件:

<scope>import</scope>
</dependency>
</dependencies>
buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
ext {
   springCloudVersion = 'Edgware.RELEASE'
}
dependencies {
   compile('org.springframework.cloud:spring-cloud-config-server')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
   }
}

现在,创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,请使用以下提供的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

使用以下命令运行 JAR 文件:

 java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8888 上启动,如下所示:

Tomcat Port 8888 Output

现在,在您的 Web 浏览器中访问 URL https://127.0.0.1:8888/config-client/default/master,您可以看到您的 config-client 应用程序配置属性,如下所示。

Config-Client Application

Spring Boot - 云配置客户端

某些应用程序可能需要配置属性,这些属性可能需要更改,开发人员可能需要将其关闭或重新启动应用程序才能执行此操作。但是,这可能会导致生产环境中的停机时间,并且需要重新启动应用程序。Spring Cloud Configuration Server 允许开发人员加载新的配置属性,而无需重新启动应用程序且无需任何停机时间。

使用 Spring Cloud Configuration 服务器

首先,从 https://start.spring.io/下载 Spring Boot 项目,并选择 Spring Cloud Config Client 依赖项。现在,在您的构建配置文件中添加 Spring Cloud Starter Config 依赖项。

Maven 用户可以将以下依赖项添加到 pom.xml 文件中。

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

Gradle 用户可以将以下依赖项添加到 build.gradle 文件中。

compile('org.springframework.cloud:spring-cloud-starter-config')

现在,您需要将 @RefreshScope 注解添加到您的主 Spring Boot 应用程序中。@RefreshScope 注解用于从配置服务器加载配置属性值。

package com.example.configclient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;

@SpringBootApplication
@RefreshScope
public class ConfigclientApplication {
   public static void main(String[] args) {
      SpringApplication.run(ConfigclientApplication.class, args);
   }
}

现在,在您的 application.properties 文件中添加配置服务器 URL 并提供您的应用程序名称。

注意 - 在启动配置客户端应用程序之前,应运行 https://127.0.0.1:8888 配置服务器。

spring.application.name = config-client
spring.cloud.config.uri = https://127.0.0.1:8888

以下代码用于编写一个简单的 REST 端点,以从配置服务器读取欢迎消息:

package com.example.configclient;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RefreshScope
@RestController
public class ConfigclientApplication {
   @Value("${welcome.message}")
   String welcomeText;
   
   public static void main(String[] args) {
      SpringApplication.run(ConfigclientApplication.class, args);
   }
   @RequestMapping(value = "/")
   public String welcomeText() {
      return welcomeText;
   }
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,您可以使用以下显示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用此处显示的命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8080 上启动,如下所示:

Started Application on Tomcat Port 8080

您可以在控制台窗口中看到日志;config-client 应用程序正在从 https://127.0.0.1:8888 获取配置。

2017-12-08 12:41:57.682  INFO 1104 --- [           
   main] c.c.c.ConfigServicePropertySourceLocator : 
   Fetching config from server at: https://127.0.0.1:8888

现在访问 URL https://127.0.0.1:8080/,欢迎消息将从配置服务器加载。

Spring Cloud Config Server

现在,转到配置服务器上更改属性值,然后访问执行器端点 POST URL https://127.0.0.1:8080/refresh,并在 URL https://127.0.0.1:8080/ 中查看新的配置属性值。

Spring Boot - Actuator

Spring Boot Actuator 提供安全的端点,用于监控和管理您的 Spring Boot 应用程序。默认情况下,所有执行器端点都是安全的。在本节中,您将详细了解如何为您的应用程序启用 Spring Boot 执行器。

启用 Spring Boot 执行器

要为您的 Spring Boot 应用程序启用 Spring Boot 执行器端点,我们需要在构建配置文件中添加 Spring Boot Starter Actuator 依赖项。

Maven 用户可以在您的 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Gradle 用户可以在您的 build.gradle 文件中添加以下依赖项。

compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'

在 application.properties 文件中,我们需要禁用执行器端点的安全性。

management.security.enabled = false

YAML 文件用户可以在您的 application.yml 文件中添加以下属性。

management:
   security:
      enabled: false

如果要使用单独的端口号来访问 Spring Boot 执行器端点,请在 application.properties 文件中添加管理端口号。

management.port = 9000

YAML 文件用户可以在您的 application.yml 文件中添加以下属性。

management:
   port: 9000

现在,您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,您可以使用以下命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8080 上启动。请注意,如果您指定了管理端口号,则同一应用程序将在两个不同的端口号上运行。

Startedc Application on Tomcat Port

以下是一些重要的 Spring Boot 执行器端点。您可以在 Web 浏览器中输入它们并监控应用程序的行为。

端点 用法
/metrics 查看应用程序指标,例如使用的内存、空闲内存、线程、类、系统正常运行时间等。
/env 查看应用程序中使用的环境变量列表。
/beans 查看 Spring Bean 及其类型、作用域和依赖项。
/health 查看应用程序健康状况。
/info 查看有关 Spring Boot 应用程序的信息。
/trace 查看 REST 端点跟踪列表。

Spring Boot - Admin 服务器

使用 Spring Boot Actuator 端点监控应用程序稍微有些困难。因为,如果您有“n”个应用程序,每个应用程序都有单独的执行器端点,从而使监控变得困难。Spring Boot Admin Server 是一个用于管理和监控微服务应用程序的应用程序。

为了处理这种情况,CodeCentric 团队提供了一个 Spring Boot Admin UI,用于在一个地方管理和监控所有 Spring Boot 应用程序执行器端点。

要构建 Spring Boot Admin Server,我们需要在构建配置文件中添加以下依赖项。

Maven 用户可以在您的 pom.xml 文件中添加以下依赖项:

<dependency>
   <groupId>de.codecentric</groupId>
   <artifactId>spring-boot-admin-server</artifactId>
   <version>1.5.5</version>
</dependency>
<dependency>
   <groupId>de.codecentric</groupId>
   <artifactId>spring-boot-admin-server-ui</artifactId>
   <version>1.5.5</version>
</dependency>

Gradle 用户可以在您的 build.gradle 文件中添加以下依赖项:

compile group: 'de.codecentric', name: 'spring-boot-admin-server', version: '1.5.5'
compile group: 'de.codecentric', name: 'spring-boot-admin-server-ui', version: '1.5.5'

在您的主 Spring Boot 应用程序类文件中添加 @EnableAdminServer 注解。@EnableAdminServer 注解用于使您的应用程序成为 Admin Server 以监控所有其他微服务。

package com.tutorialspoint.adminserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import de.codecentric.boot.admin.config.EnableAdminServer;

@SpringBootApplication
@EnableAdminServer
public class AdminserverApplication {   
   public static void main(String[] args) {
      SpringApplication.run(AdminserverApplication.class, args);
   }
}

现在,在 application.properties 文件中定义服务器端口和应用程序名称,如下所示:

server.port = 9090
spring.application.name = adminserver

对于 YAML 用户,请使用以下属性在 application.yml 文件中定义端口号和应用程序名称。

server:
   port: 9090
spring:
   application:
      name: adminserver

构建配置文件如下所示。

对于 Maven 用户 - 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.tutorialspoint</groupId>
   <artifactId>adminserver</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>adminserver</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath /> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>

      <dependency>
         <groupId>de.codecentric</groupId>
         <artifactId>spring-boot-admin-server</artifactId>
         <version>1.5.5</version>
      </dependency>
      
      <dependency>
         <groupId>de.codecentric</groupId>
         <artifactId>spring-boot-admin-server-ui</artifactId>
         <version>1.5.5</version>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

对于 Gradle 用户 - build.gradle 文件

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {   
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter')
   compile group: 'de.codecentric', name: 'spring-boot-admin-server', version: '1.5.5'
   compile group: 'de.codecentric', name: 'spring-boot-admin-server-ui', version: '1.5.5'   
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,请使用此处显示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在 target 目录下找到 JAR 文件。

对于 Gradle,请使用此处显示的命令:

gradle clean build

“构建成功”后,您可以在 build/libs 目录下找到 JAR 文件。

现在,使用以下提供的命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 9090 上启动,如下所示:

Tomcat Port 9090 Output

现在,从您的 Web 浏览器访问以下 URL 并查看 Admin Server UI。

https://127.0.0.1:9090/

Web Browser Admin Server UI

Spring Boot - Admin 客户端

要通过 Spring Boot Admin Server 监控和管理您的微服务应用程序,您应该添加 Spring Boot Admin 启动器客户端依赖项,并在应用程序属性文件中指出 Admin Server URI。

注意 - 为了监控应用程序,您应该为您的微服务应用程序启用 Spring Boot Actuator 端点。

首先,在构建配置文件中添加以下 Spring Boot Admin 启动器客户端依赖项和 Spring Boot 启动器执行器依赖项。

Maven 用户可以在您的 pom.xml 文件中添加以下依赖项:

<dependency>
   <groupId>de.codecentric</groupId>
   <artifactId>spring-boot-admin-starter-client</artifactId>
   <version>1.5.5</version>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Gradle 用户可以在您的 build.gradle 文件中添加以下依赖项。

compile group: 'de.codecentric', name: 'spring-boot-admin-starter-client', version: '1.5.5'
compile('org.springframework.boot:spring-boot-starter-actuator')

现在,将 Spring Boot Admin Server URL 添加到您的 application.properties 文件中。

对于属性文件用户,请在 application.properties 文件中添加以下属性。

spring.boot.admin.url = https://127.0.0.1:9090/

对于 YAML 用户,请在 application.yml 文件中添加以下属性。

spring:
   boot:
      admin:
         url: https://127.0.0.1:9000/

现在,创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用以下命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 9090 上启动,如下所示:

Tomcat Port 9090 Output

现在,从您的 Web 浏览器访问以下 URL,查看您的 Spring Boot 应用程序是否已注册到 Spring Boot Admin Server。

https://127.0.0.1:9090/

Spring Boot Admin Server

现在,点击详细信息按钮,并在 Admin Server UI 中查看执行器端点。

Actuator Endpoints in Admin Server UI

Spring Boot - 启用 Swagger2

Swagger2 是一个开源项目,用于为 RESTful Web 服务生成 REST API 文档。它提供了一个用户界面,可以通过 Web 浏览器访问我们的 RESTful Web 服务。

要在 Spring Boot 应用程序中启用 Swagger2,您需要在构建配置文件中添加以下依赖项。

<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.7.0</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.7.0</version>
</dependency>

对于 Gradle 用户,请在您的 build.gradle 文件中添加以下依赖项。

compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.7.0'
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.7.0'

现在,在您的主 Spring Boot 应用程序中添加 @EnableSwagger2 注解。@EnableSwagger2 注解用于为您的 Spring Boot 应用程序启用 Swagger2。

主 Spring Boot 应用程序的代码如下所示:

package com.tutorialspoint.swaggerdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@EnableSwagger2
public class SwaggerDemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(SwaggerDemoApplication.class, args);
   }
}

接下来,创建 Docket Bean 以配置 Spring Boot 应用程序的 Swagger2。我们需要定义基本包以配置 Swagger2 的 REST API。

@Bean
   public Docket productApi() {
      return new Docket(DocumentationType.SWAGGER_2).select()
         .apis(RequestHandlerSelectors.basePackage("com.tutorialspoint.swaggerdemo")).build();
   }

现在,将此 Bean 添加到主 Spring Boot 应用程序类文件本身,您的主 Spring Boot 应用程序类将如下所示:

package com.tutorialspoint.swaggerdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@EnableSwagger2
public class SwaggerDemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(SwaggerDemoApplication.class, args);
   }
   @Bean
   public Docket productApi() {
      return new Docket(DocumentationType.SWAGGER_2).select()
         .apis(RequestHandlerSelectors.basePackage("com.tutorialspoint.swaggerdemo")).build();
   }
}

现在,在您的构建配置文件中添加以下 Spring Boot Starter Web 依赖项以编写 REST 端点,如下所示:

Maven 用户可以在您的 pom.xml 文件中添加以下依赖项:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项:

compile('org.springframework.boot:spring-boot-starter-web')

现在,此处显示了在 Rest Controller 文件中构建两个简单的 RESTful Web 服务 GET 和 POST 的代码:

package com.tutorialspoint.swaggerdemo;

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

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SwaggerAPIController {
   @RequestMapping(value = "/products", method = RequestMethod.GET)
   public List<String> getProducts() {
      List<String> productsList = new ArrayList<>();
      productsList.add("Honey");
      productsList.add("Almond");
      return productsList;
   }
   @RequestMapping(value = "/products", method = RequestMethod.POST)
   public String createProduct() {
      return "Product is saved successfully";
   }
}

完整的构建配置文件如下所示:

Maven – 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.tutorialspoint</groupId>
   <artifactId>swagger-demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>swagger-demo</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath /> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      
      <dependency>
         <groupId>io.springfox</groupId>
         <artifactId>springfox-swagger2</artifactId>
         <version>2.7.0</version>
      </dependency>

      <dependency>
         <groupId>io.springfox</groupId>
         <artifactId>springfox-swagger-ui</artifactId>
         <version>2.7.0</version>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
} dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
   compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.7.0'
   compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.7.0'
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用此处显示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用此处显示的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用此处显示的命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序将在 Tomcat 端口 8080 上启动,如下所示:

Started Application on Tomcat Port 8080

现在,在您的 Web 浏览器中访问 URL,查看 Swagger API 功能。

https://127.0.0.1:8080/swagger-ui.html

Swagger API functionalities

Spring Boot - 创建 Docker 镜像

Docker 是一种容器管理服务,可以简化构建和部署。如果您是 Docker 初学者,可以通过此链接详细了解它:https://tutorialspoint.com/docker/index.htm

在本章中,我们将了解如何使用 Maven 和 Gradle 依赖项为您的 Spring Boot 应用程序创建 Docker 镜像。

创建 Dockerfile

首先,在src/main/docker目录下创建一个名为Dockerfile的文件,内容如下所示。请注意,此文件对于创建 Docker 镜像至关重要。

FROM java:8
VOLUME /tmp
ADD dockerapp-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

Maven

对于 Maven,将 Docker Maven 插件添加到您的构建配置文件pom.xml中。

<properties>
   <docker.image.prefix>spring-boot-tutorialspoint</docker.image.prefix>
</properties>

<build>
   <plugins>
      <plugin>
         <groupId>com.spotify</groupId>
         <artifactId>docker-maven-plugin</artifactId>
         <version>1.0.0</version>
         
         <configuration>
            <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
            <dockerDirectory>src/main/docker</dockerDirectory>
            <resources>
               <resource>
                  <directory>${project.build.directory}</directory>
                  <include>${project.build.finalName}.jar</include>
               </resource>
            </resources>
         </configuration>
      </plugin>
      
      <plugin>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
   </plugins>
   
</build>

完整的 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.tutorialspoint</groupId>
   <artifactId>dockerapp</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>dockerapp</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath /> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <docker.image.prefix>spring-boot-tutorialspoint</docker.image.prefix>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>1.0.0</version>
            
            <configuration>
               <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
               <dockerDirectory>src/main/docker</dockerDirectory>
               <resources>
                  <resource>
                     <directory>${project.build.directory}</directory>
                     <include>${project.build.finalName}.jar</include>
                  </resource>
               </resources>
            </configuration>
         </plugin>
         
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

现在,您可以使用 Maven 命令mvn package docker:build运行您的应用程序。

MVN Package Docker Build

注意 - 在tcp://127.0.0.1:2375上启用 Expose 守护程序,无需 TLS。

构建成功后,您可以在控制台上看到如下所示的输出:

MVN Package Docker Output

现在,使用 docker images 命令查看 Docker 镜像,并在控制台上查看镜像信息。

Docker Images Command

Gradle

要使用 Gradle 构建配置构建 Docker 镜像,我们需要添加docker插件,并需要编写一个任务buildDocker来创建 Docker 镜像。

Gradle Docker 配置代码如下所示。

buildscript {
   .....
   dependencies {
      .....
      classpath('se.transmode.gradle:gradle-docker:1.2')
   }
}

group = 'spring-boot-tutorialspoint'

.....
apply plugin: 'docker'

task buildDocker(type: Docker, dependsOn: build) {
   applicationName = jar.baseName
   dockerfile = file('src/main/docker/Dockerfile')
   doFirst {
      copy {
         from jar
         into stageDir
      }
   }
}

完整的 build.gradle 文件如下所示。

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
      classpath('se.transmode.gradle:gradle-docker:1.2')
   }
}

group = 'spring-boot-tutorialspoint'

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'docker'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}
task buildDocker(type: Docker, dependsOn: build) {
   applicationName = jar.baseName
   dockerfile = file('src/main/docker/Dockerfile')
   doFirst {
      copy {
         from jar
         into stageDir
      }
   }
}

现在,使用以下命令创建 Docker 镜像:

gradle build buildDocker

Gradle Build Docker

执行命令后,您可以在控制台窗口中看到 BUILD SUCCESSFUL 日志。

Docker Build Successful

现在,使用docker images命令查看 Docker 镜像,并在控制台上查看镜像信息。

Get Image Info Using DockerImages

Spring Boot - 追踪微服务日志

如果出现任何问题,大多数开发人员都会遇到追踪日志的困难。这可以通过 Spring Cloud Sleuth 和 ZipKin 服务器解决 Spring Boot 应用程序。

Spring Cloud Sleuth

Spring cloud Sleuth 日志以以下格式打印:

[application-name,traceid,spanid,zipkin-export]

其中,

  • Application-name = 应用程序的名称

  • Traceid = 调用相同服务或一个服务到另一个服务时,每个请求和响应的 traceid 都相同。

  • Spanid = Span Id 与 Trace Id 一起打印。Span Id 在每个请求和响应中都不同,从一个服务调用到另一个服务。

  • Zipkin-export = 默认情况下为 false。如果为 true,日志将导出到 Zipkin 服务器。

现在,在您的构建配置文件中添加 Spring Cloud Starter Sleuth 依赖项,如下所示:

Maven 用户可以在您的 pom.xml 文件中添加以下依赖项:

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

Gradle 用户可以在您的 build.gradle 文件中添加以下依赖项:

compile('org.springframework.cloud:spring-cloud-starter-sleuth')

现在,将日志添加到您的 Spring Boot 应用程序 Rest Controller 类文件,如下所示:

package com.tutorialspoint.sleuthapp;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class SleuthappApplication {
   private static final Logger LOG = Logger.getLogger(SleuthappApplication.class.getName());
   public static void main(String[] args) {
      SpringApplication.run(SleuthappApplication.class, args);
   }
   @RequestMapping("/")
   public String index() {
      LOG.log(Level.INFO, "Index API is calling");
      return "Welcome Sleuth!";
   }
}

现在,在 application.properties 文件中添加应用程序名称,如下所示:

spring.application.name = tracinglogs

构建配置文件的完整代码如下所示:

Maven – 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.tutorialspoint</groupId>
   <artifactId>sleuthapp</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>sleuthapp</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-sleuth</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
ext {
   springCloudVersion = 'Edgware.RELEASE'
}
dependencies {
   compile('org.springframework.cloud:spring-cloud-starter-sleuth')
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
   }
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用此处显示的命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 8080 上启动。

Started Application on Tomcat Port 8080

现在,在您的 Web 浏览器中访问 URL,查看控制台日志中的输出。

https://127.0.0.1:8080/

Output Welcome Sleuth

您可以在控制台窗口中看到以下日志。观察日志以以下格式打印 [应用程序名称、traceid、spanid、zipkin-export]

Log is Printed

Zipkin 服务器

Zipkin 是一款应用程序,用于监控和管理 Spring Boot 应用程序的 Spring Cloud Sleuth 日志。要构建 Zipkin 服务器,我们需要在构建配置文件中添加 Zipkin UI 和 Zipkin Server 依赖项。

Maven 用户可以在您的 pom.xml 文件中添加以下依赖项:

<dependency>
   <groupId>io.zipkin.java</groupId>
   <artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
   <groupId>io.zipkin.java</groupId>
   <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>

Gradle 用户可以在您的 build.gradle 文件中添加以下依赖项:

compile('io.zipkin.java:zipkin-autoconfigure-ui')
compile('io.zipkin.java:zipkin-server')

现在,在 application 属性文件中配置 server.port = 9411。

对于属性文件用户,请在 application.properties 文件中添加以下属性。

server.port = 9411

对于 YAML 用户,请在 application.yml 文件中添加以下属性。

server:
   port: 9411

在您的主 Spring Boot 应用程序类文件中添加 @EnableZipkinServer 注解。@EnableZipkinServer 注解用于启用您的应用程序充当 Zipkin 服务器。

package com.tutorialspoint.zipkinapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import zipkin.server.EnableZipkinServer;

@SpringBootApplication
@EnableZipkinServer
public class ZipkinappApplication {
   public static void main(String[] args) {
      SpringApplication.run(ZipkinappApplication.class, args);
   }
}

完整构建配置文件的代码如下所示。

Maven – 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.tutorialspoint</groupId>
   <artifactId>zipkinapp</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>zipkinapp</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath /> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>io.zipkin.java</groupId>
         <artifactId>zipkin-server</artifactId>
      </dependency>
      <dependency>
         <groupId>io.zipkin.java</groupId>
         <artifactId>zipkin-autoconfigure-ui</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
ext {
   springCloudVersion = 'Edgware.RELEASE'
}
dependencies {
   compile('io.zipkin.java:zipkin-autoconfigure-ui')
   compile('io.zipkin.java:zipkin-server')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
   }
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,请使用以下提供的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

使用以下命令运行 JAR 文件:

java –jar <JARFILE> 

现在,应用程序已在 Tomcat 端口 9411 上启动,如下所示:

Output Tomcat Port 9411

现在,访问以下 URL 并查看 Zipkin 服务器 UI。

https://127.0.0.1:9411/zipkin/

Zipkin server UI

然后,在您的客户端服务应用程序中添加以下依赖项,并指出 Zipkin Server URL 以通过 Zipkin UI 追踪微服务日志。

现在,在您的构建配置文件中添加 Spring Cloud Starter Zipkin 依赖项,如下所示:

Maven 用户可以在 pom.xml 文件中添加以下依赖项:

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项:

compile('org.springframework.cloud:spring-cloud-sleuth-zipkin')

现在,在您的 Spring Boot 应用程序中添加Always Sampler Bean以将日志导出到 Zipkin 服务器。

@Bean
public AlwaysSampler defaultSampler() {
   return new AlwaysSampler();
}

如果您添加 AlwaysSampler Bean,则 Spring Sleuth Zipkin 导出选项将自动从 false 更改为 true。

接下来,在客户端服务 application.properties 文件中配置您的 Zipkin Server 基本 URL。

spring.zipkin.baseUrl = https://127.0.0.1:9411/zipkin/ 

然后,提供 trace id 并找到 Zipkin UI 中的跟踪。

https://127.0.0.1:9411/zipkin/traces/{traceid}/

Spring Boot - Flyway 数据库

Flyway 是一款版本控制应用程序,可以轻松可靠地在所有实例中演变您的数据库模式。要了解更多关于 Flyway 的信息,您可以使用此链接:www.flywaydb.org

许多软件项目使用关系数据库。这需要处理数据库迁移,也常称为模式迁移。

在本章中,您将详细了解如何在 Spring Boot 应用程序中配置 Flyway 数据库。

配置 Flyway 数据库

首先,从 Spring Initializer 页面下载 Spring Boot 项目www.start.spring.io并选择以下依赖项:

  • Spring Boot Starter Web
  • Flyway
  • MySQL
  • JDBC

Maven 用户可以在 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.flywaydb</groupId>
   <artifactId>flyway-core</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项。

compile('org.flywaydb:flyway-core')
compile('org.springframework.boot:spring-boot-starter-jdbc')
compile('org.springframework.boot:spring-boot-starter-web')
compile('mysql:mysql-connector-java')

在 application 属性中,我们需要配置数据库属性以创建 DataSource,还需要在 application 属性中配置 flyway 属性。

对于属性文件用户,请在 application.properties 文件中添加以下属性。

spring.application.name = flywayapp  

spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/USERSERVICE?autoreconnect=true
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.testOnBorrow = true
spring.datasource.testWhileIdle = true
spring.datasource.timeBetweenEvictionRunsMillis = 60000
spring.datasource.minEvictableIdleTimeMillis = 30000
spring.datasource.validationQuery = SELECT 1
spring.datasource.max-active = 15
spring.datasource.max-idle = 10
spring.datasource.max-wait = 8000

flyway.url = jdbc:mysql://127.0.0.1:3306/mysql
flyway.schemas = USERSERVICE
flyway.user = root
flyway.password = root

YAML 用户可以在 application.yml 文件中添加以下属性。

spring:
   application:
      name: flywayapp  
   datasource: 
      driverClassName: com.mysql.jdbc.Driver
      url: "jdbc:mysql://127.0.0.1:3306/USERSERVICE?autoreconnect=true"
      password: "root"
      username: "root"
      testOnBorrow: true
      testWhileIdle: true
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 30000
      validationQuery: SELECT 1
      max-active: 15
      max-idle: 10
      max-wait: 8000
flyway:
   url: jdbc:mysql://127.0.0.1:3306/mysql
   schemas: USERSERVICE
   user: "root"
   password: "root"

现在,在src/main/resources/db/migration目录下创建一个 SQL 文件。将 SQL 文件命名为“V1__Initial.sql”。

CREATE TABLE USERS (ID INT AUTO_INCREMENT PRIMARY KEY, USERID VARCHAR(45));
INSERT INTO USERS (ID, USERID) VALUES (1, 'tutorialspoint.com');

主 Spring Boot 应用程序类文件的代码如下所示:

package com.tutorialspoint.flywayapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FlywayappApplication {
   public static void main(String[] args) {
      SpringApplication.run(FlywayappApplication.class, args);
   }
}

完整的构建配置文件如下所示。

Maven – 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.tutorialspoint</groupId>
   <artifactId>flywayapp</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>flywayapp</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.flywaydb</groupId>
         <artifactId>flyway-core</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-jdbc</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.flywaydb:flyway-core')
   compile('org.springframework.boot:spring-boot-starter-jdbc')
   compile('org.springframework.boot:spring-boot-starter-web')
   compile('mysql:mysql-connector-java')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

您可以创建一个可执行的 JAR 文件,并使用下面给出的 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用此处显示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用此处显示的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用以下命令运行 JAR 文件:

 java –jar <JARFILE> 

现在,Tomcat 在端口 8080 上启动,您可以在控制台窗口中看到 flyway 数据库日志,如下所示。

Flyway Database Logs

您现在可以转到数据库并执行 select 查询。

Database and Select the Queries

Spring Boot - 发送邮件

通过使用 Spring Boot RESTful Web 服务,您可以使用 Gmail 传输层安全性发送电子邮件。在本章中,让我们详细了解如何使用此功能。

首先,我们需要在构建配置文件中添加 Spring Boot Starter Mail 依赖项。

Maven 用户可以将以下依赖项添加到 pom.xml 文件中。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

Gradle 用户可以在您的 build.gradle 文件中添加以下依赖项。

 compile('org.springframework.boot:spring-boot-starter-mail')

主 Spring Boot 应用程序类文件的代码如下所示:

package com.tutorialspoint.emailapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class EmailappApplication {
   public static void main(String[] args) {
      SpringApplication.run(EmailappApplication.class, args);
   }
}

您可以在 Rest Controller 类文件中编写一个简单的 Rest API 以发送电子邮件,如下所示。

package com.tutorialspoint.emailapp;

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

@RestController
public class EmailController {
   @RequestMapping(value = "/sendemail")
   public String sendEmail() {
      return "Email sent successfully";
   }   
}

您可以编写一个方法来发送带附件的电子邮件。定义 mail.smtp 属性并使用 PasswordAuthentication。

private void sendmail() throws AddressException, MessagingException, IOException {
   Properties props = new Properties();
   props.put("mail.smtp.auth", "true");
   props.put("mail.smtp.starttls.enable", "true");
   props.put("mail.smtp.host", "smtp.gmail.com");
   props.put("mail.smtp.port", "587");
   
   Session session = Session.getInstance(props, new javax.mail.Authenticator() {
      protected PasswordAuthentication getPasswordAuthentication() {
         return new PasswordAuthentication("[email protected]", "<your password>");
      }
   });
   Message msg = new MimeMessage(session);
   msg.setFrom(new InternetAddress("[email protected]", false));

   msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("[email protected]"));
   msg.setSubject("Tutorials point email");
   msg.setContent("Tutorials point email", "text/html");
   msg.setSentDate(new Date());

   MimeBodyPart messageBodyPart = new MimeBodyPart();
   messageBodyPart.setContent("Tutorials point email", "text/html");

   Multipart multipart = new MimeMultipart();
   multipart.addBodyPart(messageBodyPart);
   MimeBodyPart attachPart = new MimeBodyPart();

   attachPart.attachFile("/var/tmp/image19.png");
   multipart.addBodyPart(attachPart);
   msg.setContent(multipart);
   Transport.send(msg);   
}

现在,从 Rest API 调用上述 sendmail() 方法,如下所示:

@RequestMapping(value = "/sendemail")
public String sendEmail() throws AddressException, MessagingException, IOException {
   sendmail();
   return "Email sent successfully";   
}

注意 - 在发送电子邮件之前,请在您的 Gmail 帐户设置中启用允许安全性较低的应用。

完整的构建配置文件如下所示。

Maven – 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.tutorialspoint</groupId>
   <artifactId>emailapp</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>emailapp</name>
   <description>Demo project for Spring Boot</description>
   
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
   
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
   <java.version>1.8</java.version>
   </properties>
   
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-mail</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build> 
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   compile('org.springframework.boot:spring-boot-starter-mail')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

现在,您可以创建一个可执行的 JAR 文件,并使用以下所示的 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,您可以使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用以下提供的命令运行 JAR 文件:

java –jar <JARFILE> 

您可以看到应用程序已在 Tomcat 端口 8080 上启动。

Tomcat Port 8080 Application Output

现在,从您的 Web 浏览器访问以下 URL,您将收到一封电子邮件。

https://127.0.0.1:8080/sendemail

Email Sent Successfully Browser Window

Email Sent Successfully

Spring Boot - Hystrix

Hystrix 是来自 Netflix 的一个库。Hystrix 隔离服务之间的访问点,阻止它们之间出现级联故障,并提供回退选项。

例如,当您调用第三方应用程序时,发送响应需要更多时间。因此,此时,控制权将转到回退方法,并将自定义响应返回到您的应用程序。

在本章中,您将了解如何在 Spring Boot 应用程序中实现 Hystrix。

首先,我们需要在构建配置文件中添加 Spring Cloud Starter Hystrix 依赖项。

Maven 用户可以在 pom.xml 文件中添加以下依赖项:

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项:

compile('org.springframework.cloud:spring-cloud-starter-hystrix')

现在,将 @EnableHystrix 注解添加到您的主 Spring Boot 应用程序类文件。@EnableHystrix 注解用于在您的 Spring Boot 应用程序中启用 Hystrix 功能。

主 Spring Boot 应用程序类文件的代码如下所示:

package com.tutorialspoint.hystrixapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

@SpringBootApplication
@EnableHystrix
public class HystrixappApplication {
   public static void main(String[] args) {
      SpringApplication.run(HystrixappApplication.class, args);
   }
}

现在编写一个简单的 Rest Controller,使其在请求时间 3 秒后返回字符串。

@RequestMapping(value = "/")
public String hello() throws InterruptedException {
   Thread.sleep(3000);
   return "Welcome Hystrix";
}

现在,为 Rest API 添加 @Hystrix 命令和 @HystrixProperty,并定义以毫秒为单位的超时值。

@HystrixCommand(fallbackMethod = "fallback_hello", commandProperties = {
   @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
})

接下来,如果请求响应时间过长,则定义回退方法 fallback_hello()。

private String fallback_hello() {
   return "Request fails. It takes long time to response";
}

包含 REST API 和 Hystrix 属性的完整 Rest Controller 类文件如下所示:

@RequestMapping(value = "/")
@HystrixCommand(fallbackMethod = "fallback_hello", commandProperties = {
   @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
})
public String hello() throws InterruptedException {
   Thread.sleep(3000);
   return "Welcome Hystrix";
}
private String fallback_hello() {
   return "Request fails. It takes long time to response";
}

在此示例中,REST API 编写在主 Spring Boot 应用程序类文件本身中。

package com.tutorialspoint.hystrixapp;

import org.springframework.boot.SpringApplication;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@SpringBootApplication
@EnableHystrix
@RestController
public class HystrixappApplication {
   public static void main(String[] args) {
      SpringApplication.run(HystrixappApplication.class, args);
   }
   @RequestMapping(value = "/")
   @HystrixCommand(fallbackMethod = "fallback_hello", commandProperties = {
      @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
   })
   public String hello() throws InterruptedException {
      Thread.sleep(3000);
      return "Welcome Hystrix";
   }
   private String fallback_hello() {
      return "Request fails. It takes long time to response";
   }
}

完整的构建配置文件如下所示。

Maven - 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.tutorialspoint</groupId>
   <artifactId>hystrixapp</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>hystrixapp</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Edgware.RELEASE</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-hystrix</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
ext {
   springCloudVersion = 'Edgware.RELEASE'
}
dependencies {
   compile('org.springframework.cloud:spring-cloud-starter-hystrix')
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
   }
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序:

对于 Maven,使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,使用如下所示的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用以下提供的命令运行 JAR 文件:

java –jar <JARFILE> 

这将在Tomcat端口8080上启动应用程序,如下所示:

Tomcat Application Command Prompt

现在,从您的 Web 浏览器中访问 URL https://127.0.0.1:8080/,并查看 Hystrix 响应。API 需要 3 秒才能响应,但 Hystrix 超时时间为 1 秒。

Request Fail Hystrix Timeout

Spring Boot - WebSocket

在本章中,让我们了解如何使用 Spring Boot 和 WebSockets 构建交互式 Web 应用程序。

要在 Spring Boot 中使用 Web Socket 构建交互式 Web 应用程序,您需要添加以下依赖项。

Maven 用户应在 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
   <groupId>org.webjars</groupId>
   <artifactId>webjars-locator</artifactId>
</dependency>
<dependency>
   <groupId>org.webjars</groupId>
   <artifactId>sockjs-client</artifactId>
   <version>1.0.2</version>
</dependency>

<dependency>
   <groupId>org.webjars</groupId>
   <artifactId>stomp-websocket</artifactId>
   <version>2.3.3</version>
</dependency>
<dependency>
   <groupId>org.webjars</groupId>
   <artifactId>bootstrap</artifactId>
   <version>3.3.7</version>        </dependency>
<dependency>
   <groupId>org.webjars</groupId>
   <artifactId>jquery</artifactId>
   <version>3.1.0</version>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项:

compile("org.springframework.boot:spring-boot-starter-websocket")
compile("org.webjars:webjars-locator")
compile("org.webjars:sockjs-client:1.0.2")
compile("org.webjars:stomp-websocket:2.3.3")
compile("org.webjars:bootstrap:3.3.7")
compile("org.webjars:jquery:3.1.0")

让我们创建一个消息处理控制器来处理 STOMP 消息。STOMP 消息可以路由到 @Controller 类文件。例如,GreetingController 映射到处理目标为“/hello”的消息。

package com.tutorialspoint.websocketapp;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class GreetingController {
   @MessageMapping("/hello")
   @SendTo("/topic/greetings")
   public Greeting greeting(HelloMessage message) throws Exception {
      Thread.sleep(1000); // simulated delay
      return new Greeting("Hello, " + message.getName() + "!");
   }
}

现在,为 STOMP 消息配置 Spring。编写一个 WebSocketConfig 类文件,该文件扩展 AbstractWebSocketMessageBrokerConfigurer 类,如下所示。

package com.tutorialspoint.websocketapp;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
   @Override
   public void configureMessageBroker(MessageBrokerRegistry config) {
      config.enableSimpleBroker("/topic");
      config.setApplicationDestinationPrefixes("/app");
   }
   @Override
   public void registerStompEndpoints(StompEndpointRegistry registry) {
      registry.addEndpoint("/tutorialspoint-websocket").withSockJS();
   }
}

@EnableWebSocketMessageBroker 注解用于配置 Web Socket 消息代理以创建 STOMP 端点。

您可以在 src/main/resources/static/index.html 下创建一个浏览器客户端文件,如下所示:

<!DOCTYPE html>
<html>
   <head>
      <title>Hello WebSocket</title>
      <link href = "/webjars/bootstrap/css/bootstrap.min.css" rel = "stylesheet">
      <link href = "/main.css" rel = "stylesheet">
      <script src = "/webjars/jquery/jquery.min.js"></script>
      <script src = "/webjars/sockjs-client/sockjs.min.js"></script>
      <script src = "/webjars/stomp-websocket/stomp.min.js"></script>
      <script src = "/app.js"></script>
   </head>
   
   <body>
      <noscript>
         <h2 style = "color: #ff0000">
            Seems your browser doesn't support Javascript! Websocket relies on Javascript being
            enabled. Please enable Javascript and reload this page!
         </h2>
      </noscript>
      <div id = "main-content" class = "container">
         <div class = "row">
            <div class = "col-md-6">
               <form class = "form-inline">
                  <div class = "form-group">
                     <label for = "connect">WebSocket connection:</label>
                     <button id = "connect" class = "btn btn-default" type = "submit">Connect</button>
                     <button id = "disconnect" class = "btn btn-default" type = "submit" disabled = "disabled">Disconnect
                     </button>
                  </div>
               </form>
            </div>
            
            <div class = "col-md-6">
               <form class = "form-inline">
                  <div class = "form-group">
                     <label for = "name">What is your name?</label>
                     <input type = "text" id = "name" class = "form-control" placeholder = "Your name here...">
                  </div>
                  <button id = "send" class = "btn btn-default" type = "submit">Send</button>
               </form>
            </div>
         </div>
         
         <div class  =  "row">
            <div class  =  "col-md-12">
               <table id  =  "conversation" class = "table table-striped">
                  <thead>
                     <tr>
                        <th>Greetings</th>
                     </tr>
                  </thead>
                  <tbody id  =  "greetings"></tbody>
               </table>
            </div>
         </div>
      </div>
   </body>
</html>

让我们创建一个 app.js 文件,使用 STOMP 消费和生成消息。

var stompClient = null;

function setConnected(connected) {
   $("#connect").prop("disabled", connected);
   $("#disconnect").prop("disabled", !connected);
   
   if (connected) {
      $("#conversation").show();
   } else {
      $("#conversation").hide();
   }
   $("#greetings").html("");
}

function connect() {
   var socket = new SockJS('/tutorialspoint-websocket');
   stompClient = Stomp.over(socket);
   stompClient.connect({}, function (frame) {
      setConnected(true);
      console.log('Connected: ' + frame);
      stompClient.subscribe('/topic/greetings', function (greeting) {
         showGreeting(JSON.parse(greeting.body).content);
      });
   });
}
function disconnect() {
   if (stompClient !== null) {
      stompClient.disconnect();
   }
   setConnected(false);
   console.log("Disconnected");
}
function sendName() {
   stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
}
function showGreeting(message) {
   $("#greetings").append("<tr><td>" + message + "</td></tr>");
}
$(function () {
   $( "form" ).on('submit', function (e) {e.preventDefault();});
   $( "#connect" ).click(function() { connect(); });
   $( "#disconnect" ).click(function() { disconnect(); });
   $( "#send" ).click(function() { sendName(); });
});

主 Spring Boot 应用程序的代码如下所示。

package com.tutorialspoint.websocketapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebsocketappApplication {
   public static void main(String[] args) {
      SpringApplication.run(WebsocketappApplication.class, args);
   }  
}

完整的构建配置文件如下所示。

Maven – 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.tutorialspoint</groupId>
   <artifactId>websocketapp</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>websocketapp</name>
   <description>Demo project for Spring Boot</description>

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

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-websocket</artifactId>
      </dependency>
      <dependency>
         <groupId>org.webjars</groupId>
         <artifactId>webjars-locator</artifactId>
      </dependency>
      <dependency>
         <groupId>org.webjars</groupId>
         <artifactId>sockjs-client</artifactId>
         <version>1.0.2</version>
      </dependency>
      
      <dependency>
         <groupId>org.webjars</groupId>
         <artifactId>stomp-websocket</artifactId>
         <version>2.3.3</version>
      </dependency>
      <dependency>
         <groupId>org.webjars</groupId>
         <artifactId>bootstrap</artifactId>
         <version>3.3.7</version>
      </dependency>
      
      <dependency>
         <groupId>org.webjars</groupId>
         <artifactId>jquery</artifactId>
         <version>3.1.0</version>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   
   <properties>
      <java.version>1.8</java.version>
   </properties>
   
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.9.RELEASE")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

jar {
   baseName = 'websocketapp'
   version =  '0.1.0'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile("org.springframework.boot:spring-boot-starter-websocket")
   compile("org.webjars:webjars-locator")
   compile("org.webjars:sockjs-client:1.0.2")
   compile("org.webjars:stomp-websocket:2.3.3")
   compile("org.webjars:bootstrap:3.3.7")
   compile("org.webjars:jquery:3.1.0")

   testCompile("org.springframework.boot:spring-boot-starter-test")
}

Spring Boot - 批处理服务

您可以创建一个可执行的 JAR 文件,并使用 Maven 或 Gradle 命令运行 Spring Boot 应用程序,如下所示:

对于 Maven,您可以使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

使用此处给出的命令运行 JAR 文件:

java –jar <JARFILE>

现在,应用程序已在 Tomcat 端口 8080 上启动,如下所示。

Batch Service application started on Tomcat port

现在,在您的 Web 浏览器中访问 URL https://127.0.0.1:8080/,连接 Web Socket 并发送问候语并接收消息。

Web Socket Send and Receive Message

批处理服务是一个在单个任务中执行多个命令的过程。在本章中,您将学习如何在 Spring Boot 应用程序中创建批处理服务。

让我们考虑一个将 CSV 文件内容保存到 HSQLDB 的示例。

要创建批处理服务程序,我们需要在构建配置文件中添加 Spring Boot Starter Batch 依赖项和 HSQLDB 依赖项。

Maven 用户可以在 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
   <groupId>org.hsqldb</groupId>
   <artifactId>hsqldb</artifactId>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项。

compile("org.springframework.boot:spring-boot-starter-batch")
compile("org.hsqldb:hsqldb")

现在,在类路径资源 - src/main/resources 下添加简单的 CSV 数据文件,并将文件命名为 file.csv,如下所示:

William,John
Mike, Sebastian
Lawarance, Lime

接下来,为 HSQLDB 编写 SQL 脚本 - 在类路径资源目录下 - request_fail_hystrix_timeout

DROP TABLE USERS IF EXISTS;
CREATE TABLE USERS  (
   user_id BIGINT IDENTITY NOT NULL PRIMARY KEY,
   first_name VARCHAR(20),
   last_name VARCHAR(20)
);

为 USERS 模型创建一个 POJO 类,如下所示:

package com.tutorialspoint.batchservicedemo;
public class User {
   private String lastName;
   private String firstName;

   public User() {
   }
   public User(String firstName, String lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
   }
   public void setFirstName(String firstName) {
      this.firstName = firstName;
   }
   public String getFirstName() {
      return firstName;
   }
   public String getLastName() {
      return lastName;
   }
   public void setLastName(String lastName) {
      this.lastName = lastName;
   }

   @Override
   public String toString() {
      return "firstName: " + firstName + ", lastName: " + lastName;
   }   
}

现在,创建一个中间处理器,在从 CSV 文件读取数据和将数据写入 SQL 之前执行操作。

package com.tutorialspoint.batchservicedemo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;

public class UserItemProcessor implements ItemProcessor<User, User> {
   private static final Logger log = LoggerFactory.getLogger(UserItemProcessor.class);

   @Override
   public User process(final User user) throws Exception {
      final String firstName = user.getFirstName().toUpperCase();
      final String lastName = user.getLastName().toUpperCase();
      final User transformedPerson = new User(firstName, lastName);

      log.info("Converting (" + user + ") into (" + transformedPerson + ")");
      return transformedPerson;
   }
}

让我们创建一个批处理配置文件,从 CSV 读取数据并写入 SQL 文件,如下所示。我们需要在配置类文件中添加 @EnableBatchProcessing 注解。@EnableBatchProcessing 注解用于为您的 Spring Boot 应用程序启用批处理操作。

package com.tutorialspoint.batchservicedemo;

import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;

import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
   @Autowired
   public JobBuilderFactory jobBuilderFactory;

   @Autowired
   public StepBuilderFactory stepBuilderFactory;

   @Autowired
   public DataSource dataSource;

   @Bean
   public FlatFileItemReader<User> reader() {
      FlatFileItemReader<User> reader = new FlatFileItemReader<User>();
      reader.setResource(new ClassPathResource("file.csv"));
      reader.setLineMapper(new DefaultLineMapper<User>() {
         {
            setLineTokenizer(new DelimitedLineTokenizer() {
               {
                  setNames(new String[] { "firstName", "lastName" });
               }
            });
            setFieldSetMapper(new BeanWrapperFieldSetMapper<User>() {
               {
                  setTargetType(User.class);
               }
            });
         }
      });
      return reader;
   }
   @Bean
   public UserItemProcessor processor() {
      return new UserItemProcessor();
   }
   @Bean
   public JdbcBatchItemWriter<User> writer() {
      JdbcBatchItemWriter<User> writer = new JdbcBatchItemWriter<User>();
      writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<User>());
      writer.setSql("INSERT INTO USERS (first_name, last_name) VALUES (:firstName, :lastName)");
      writer.setDataSource(dataSource);
      return writer;
   }
   @Bean
   public Job importUserJob(JobCompletionNotificationListener listener) {
      return jobBuilderFactory.get("importUserJob").incrementer(
         new RunIdIncrementer()).listener(listener).flow(step1()).end().build();
   }
   @Bean
   public Step step1() {
      return stepBuilderFactory.get("step1").<User, User>chunk(10).reader(reader()).processor(processor()).writer(writer()).build();
   }
}

reader() 方法用于从 CSV 文件读取数据,而 writer() 方法用于将数据写入 SQL。

接下来,我们将不得不编写一个作业完成通知侦听器类 - 用于在作业完成之后发出通知。

package com.tutorialspoint.batchservicedemo;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.listener.JobExecutionListenerSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

@Component
public class JobCompletionNotificationListener extends JobExecutionListenerSupport {
   private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class);
   private final JdbcTemplate jdbcTemplate;

   @Autowired
   public JobCompletionNotificationListener(JdbcTemplate jdbcTemplate) {
      this.jdbcTemplate = jdbcTemplate;
   }
   @Override
   public void afterJob(JobExecution jobExecution) {
      if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
         log.info("!!! JOB FINISHED !! It's time to verify the results!!");

         List<User> results = jdbcTemplate.query(
            "SELECT first_name, last_name FROM USERS", new RowMapper<User>() {
            
            @Override
            public User mapRow(ResultSet rs, int row) throws SQLException {
               return new User(rs.getString(1), rs.getString(2));
            }
         });

         for (User person : results) {
            log.info("Found <" + person + "> in the database.");
         }
      }
   }
}

现在,创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

使用此处给出的命令运行 JAR 文件:

java –jar <JARFILE>

您可以在控制台窗口中看到输出,如下所示:

Batch Service Otput in Console Window

Spring Boot - Apache Kafka

Apache Kafka 是一个开源项目,用于基于容错消息系统发布和订阅消息。它速度快、可扩展且分布式设计。如果您是 Kafka 的初学者,或者希望对其有更深入的了解,请参考此链接:www.tutorialspoint.com/apache_kafka/

在本章中,我们将了解如何在 Spring Boot 应用程序中实现 Apache Kafka。

首先,我们需要在构建配置文件中添加 Spring Kafka 依赖项。

Maven 用户可以在 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.kafka</groupId>
   <artifactId>spring-kafka</artifactId>
   <version>2.1.0.RELEASE</version>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项。

compile group: 'org.springframework.kafka', name: 'spring-kafka', version: '2.1.0.RELEASE'

生成消息

要将消息生成到 Apache Kafka,我们需要为生产者配置定义配置类,如下所示:

package com.tutorialspoint.kafkademo;

import java.util.HashMap;
import java.util.Map;

import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory;

@Configuration
public class KafkaProducerConfig {
   @Bean
   public ProducerFactory<String, String> producerFactory() {
      Map<String, Object> configProps = new HashMap<>();
      configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
      configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
      configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
      return new DefaultKafkaProducerFactory<>(configProps);
   }
   @Bean
   public KafkaTemplate<String, String> kafkaTemplate() {
      return new KafkaTemplate<>(producerFactory());
   }
}

要发布消息,自动装配 Kafka Template 对象并生成消息,如下所示。

@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
 
public void sendMessage(String msg) {
   kafkaTemplate.send(topicName, msg);
}   

消费消息

要消费消息,我们需要编写一个消费者配置类文件,如下所示。

package com.tutorialspoint.kafkademo;

import java.util.HashMap;
import java.util.Map;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;

@EnableKafka
@Configuration
public class KafkaConsumerConfig {
   @Bean
   public ConsumerFactory<String, String> consumerFactory() {
      Map<String, Object> props = new HashMap<>();
      props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:2181");
      props.put(ConsumerConfig.GROUP_ID_CONFIG, "group-id");
      props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
      props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
      return new DefaultKafkaConsumerFactory<>(props);
   }
   @Bean
   public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
      ConcurrentKafkaListenerContainerFactory<String, String> 
      factory = new ConcurrentKafkaListenerContainerFactory<>();
      factory.setConsumerFactory(consumerFactory());
      return factory;
   }
}      

接下来,编写一个侦听器来侦听消息。

@KafkaListener(topics = "tutorialspoint", groupId = "group-id")
public void listen(String message) {
   System.out.println("Received Messasge in group - group-id: " + message);
}

让我们从主 Spring Boot 应用程序类文件的 ApplicationRunner 类 run 方法中调用 sendMessage() 方法,并从同一个类文件中消费消息。

您的主 Spring Boot 应用程序类文件代码如下所示:

package com.tutorialspoint.kafkademo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.KafkaTemplate;

@SpringBootApplication
public class KafkaDemoApplication implements ApplicationRunner {
   @Autowired
   private KafkaTemplate<String, String> kafkaTemplate;

   public void sendMessage(String msg) {
      kafkaTemplate.send("tutorialspoint", msg);
   }
   public static void main(String[] args) {
      SpringApplication.run(KafkaDemoApplication.class, args);
   }
   @KafkaListener(topics = "tutorialspoint", groupId = "group-id")
   public void listen(String message) {
      System.out.println("Received Messasge in group - group-id: " + message);
   }
   @Override
   public void run(ApplicationArguments args) throws Exception {
      sendMessage("Hi Welcome to Spring For Apache Kafka");
   }
}

完整构建配置文件的代码如下所示。

Maven – 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.tutorialspoint</groupId>
   <artifactId>kafka-demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>kafka-demo</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath /> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.kafka</groupId>
         <artifactId>spring-kafka</artifactId>
         <version>2.1.0.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter')
   compile group: 'org.springframework.kafka', name: 'spring-kafka', version: '2.1.0.RELEASE'
   testCompile('org.springframework.boot:spring-boot-starter-test')
}   

现在,创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序,如下所示:

对于 Maven,使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,使用如下所示的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

使用此处给出的命令运行 JAR 文件:

java –jar <JARFILE> 

您可以在控制台窗口中看到输出。

Spring Boot - Twilio

Twilio 是一个第三方应用程序,用于从我们的应用程序发送短信和拨打电话。它允许我们以编程方式发送短信和拨打电话。

在本章中,您将学习如何使用 Spring Boot 和 Twilio 实现发送短信和拨打电话。

注意:我们使用 Twilio 中的试用账户发送短信和拨打电话。您可以在 www.twilio.com 了解更多关于 Twilio 的信息。

首先,我们需要在构建配置文件中添加 Twilio 依赖项。

Maven 用户可以在 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>com.twilio.sdk</groupId>
   <artifactId>twilio</artifactId>
   <version>7.16.1</version>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项。

compile group: "com.twilio.sdk", name:"twilio", version: "7.16.1"   

现在,在静态块中使用 ACCOUNT_SID 和 AUTH_ID 初始化 Twilio 账户,如下所示:

static {
   Twilio.init(ACCOUNT_SID, AUTH_ID);
}

发送短信

要发送短信,我们需要向 Message.create() 方法提供发件号码和收件号码。我们还需要为 Message.creator() 方法提供消息正文内容,如下所示:

Message.creator(new PhoneNumber("to-number"), new PhoneNumber("from-number"),
   "Message from Spring Boot Application").create();

主 Spring Boot 应用程序类文件如下所示。

package com.tutorialspoint.smsdemo;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Message;
import com.twilio.type.PhoneNumber;

@SpringBootApplication
public class SmsdemoApplication implements ApplicationRunner {
   private final static String ACCOUNT_SID = "<your-account-sid>";
   private final static String AUTH_ID = "<your-auth-id>";

   static {
      Twilio.init(ACCOUNT_SID, AUTH_ID);
   }
   public static void main(String[] args) {
      SpringApplication.run(SmsdemoApplication.class, args);
   }
   @Override
   public void run(ApplicationArguments arg0) throws Exception {
      Message.creator(new PhoneNumber("to-number"), new PhoneNumber("from-number"),
         "Message from Spring Boot Application").create();
   }
}

构建配置文件的完整代码如下所示:

Maven – 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.tutorialspoint</groupId>
   <artifactId>smsdemo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>smsdemo</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath /> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>com.twilio.sdk</groupId>
         <artifactId>twilio</artifactId>
         <version>7.16.1</version>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter')
   testCompile('org.springframework.boot:spring-boot-starter-test')
   compile group: "com.twilio.sdk", name:"twilio", version: "7.11.+"   
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 spring boot 应用程序:

对于 Maven,使用如下所示的命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,使用如下所示的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

使用如下所示的命令运行 JAR 文件:

java –jar <JARFILE> 

现在,您将收到发送到“收件号码”的短信。

消息已收到“收件号码”。

Sent from your Twilio trail account
- Message from Spring Boot Application

注意:在此示例中,我们使用了试用账户。因此,在发送短信之前,您应该验证号码。

语音通话

要使用 Twilio 拨打电话,我们需要调用 Call.creator() 方法。对于此方法,我们需要提供收件号码、发件号码和语音提示,如下所示。

Call.creator(new PhoneNumber("<to-number>"), new PhoneNumber("<from-number>"),
   new URI("http://demo.twilio.com/docs/voice.xml")).create();

主 Spring Boot 应用程序类文件的代码如下所示。

package com.tutorialspoint.smsdemo; 

import java.net.URI;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Call;
import com.twilio.type.PhoneNumber;

@SpringBootApplication
public class SmsdemoApplication implements ApplicationRunner {
   private final static String ACCOUNT_SID = "<ACCOUNT-SID>";
   private final static String AUTH_ID = "AUTH-ID";

   static {
      Twilio.init(ACCOUNT_SID, AUTH_ID);
   }
   public static void main(String[] args) {
      SpringApplication.run(SmsdemoApplication.class, args);
   }
   @Override
   public void run(ApplicationArguments arg0) throws Exception {
      Call.creator(new PhoneNumber("<to-number>"), new PhoneNumber("<from-number>"),
         new URI("http://demo.twilio.com/docs/voice.xml")).create();
   }
}

完整构建配置文件的代码如下所示:

Maven – 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.tutorialspoint</groupId>
   <artifactId>smsdemo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>smsdemo</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath /> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>com.twilio.sdk</groupId>
         <artifactId>twilio</artifactId>
         <version>7.16.1</version>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter')
   testCompile('org.springframework.boot:spring-boot-starter-test')
   compile group: "com.twilio.sdk", name:"twilio", version: "7.11.+"   
}

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,使用如下所示的命令:

 mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,使用如下所示的命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用此处提供的命令运行 JAR 文件:

java –jar <JARFILE> 

现在,您将收到来自 Twilio 的“收件号码”的电话。

接听电话后按任意键,您将听到来自 https://demo.twilio.com/docs/voice.xml 的语音提示。

注意:在此示例中,我们使用了试用账户。因此,在拨打电话之前,您应该验证号码。

Spring Boot - 单元测试用例

单元测试是开发人员进行的一种测试,以确保各个单元或组件的功能正常工作。

在本教程中,我们将了解如何使用 Mockito 和 Web Controller 编写单元测试用例。

Mockito

要将 Mockito 模拟注入 Spring Bean,我们需要在构建配置文件中添加 Mockito-core 依赖项。

Maven 用户可以在 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.mockito</groupId>
   <artifactId>mockito-core</artifactId>
   <version>2.13.0</version>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项。

compile group: 'org.mockito', name: 'mockito-core', version: '2.13.0'
testCompile('org.springframework.boot:spring-boot-starter-test')

此处提供了编写服务类(包含返回字符串值的方法)的代码。

package com.tutorialspoint.mockitodemo;

import org.springframework.stereotype.Service;

@Service
public class ProductService {
   public String getProductName() {
      return "Honey";
   } 
}

现在,将 ProductService 类注入另一个服务类文件,如下所示。

package com.tutorialspoint.mockitodemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
   @Autowired
   ProductService productService;

   public OrderService(ProductService productService) {
      this.productService = productService;
   }
   public String getProductName() {
      return productService.getProductName();
   }
}

主要的 Spring Boot 应用程序类文件如下所示:

package com.tutorialspoint.mockitodemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MockitoDemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(MockitoDemoApplication.class, args);
   }
}

然后,为测试配置应用程序上下文。@Profile(“test”) 注解用于在测试用例运行时配置类。

package com.tutorialspoint.mockitodemo;

import org.mockito.Mockito;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;

@Profile("test")
@Configuration
public class ProductServiceTestConfiguration {
   @Bean
   @Primary
   public ProductService productService() {
      return Mockito.mock(ProductService.class);
   }
}

现在,您可以为 Order Service 编写单元测试用例,位于 src/test/resources 包下。

package com.tutorialspoint.mockitodemo;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@SpringBootTest
@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
public class MockitoDemoApplicationTests {
   @Autowired
   private OrderService orderService;
   
   @Autowired
   private ProductService productService;

   @Test
   public void whenUserIdIsProvided_thenRetrievedNameIsCorrect() {
      Mockito.when(productService.getProductName()).thenReturn("Mock Product Name");
      String testName = orderService.getProductName();
      Assert.assertEquals("Mock Product Name", testName);
   }
}

构建配置文件的完整代码如下所示。

Maven – 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.tutorialspoint</groupId>
   <artifactId>mockito-demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

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

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath /> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>
      <dependency>
         <groupId>org.mockito</groupId>
         <artifactId>mockito-core</artifactId>
         <version>2.13.0</version>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter')
   compile group: 'org.mockito', name: 'mockito-core', version: '2.13.0'
   testCompile('org.springframework.boot:spring-boot-starter-test')
}   

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle1 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用如下所示的命令:

mvn clean install 

您可以在控制台窗口中看到测试结果。

Test Results in Console Window

对于 Gradle,您可以使用以下命令:

gradle clean build 

您可以在控制台窗口中看到其余结果。

Rest Results in Console Window

Spring Boot - Rest Controller 单元测试

Spring Boot 提供了一种简单的方法来为 Rest Controller 文件编写单元测试。借助 SpringJUnit4ClassRunner 和 MockMvc,我们可以创建一个 Web 应用程序上下文,为 Rest Controller 文件编写单元测试。

单元测试应编写在 src/test/java 目录下,编写测试的类路径资源应放置在 src/test/resources 目录下。

要编写单元测试,我们需要在构建配置文件中添加 Spring Boot Starter Test 依赖项,如下所示。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>

Gradle 用户可以在您的 build.gradle 文件中添加以下依赖项。

testCompile('org.springframework.boot:spring-boot-starter-test')

在编写测试用例之前,我们应该首先构建 RESTful Web 服务。有关构建 RESTful Web 服务的更多信息,请参阅本教程中提供的同一章节。

为 REST Controller 编写单元测试

在本节中,让我们了解如何为 REST Controller 编写单元测试。

首先,我们需要创建一个抽象类文件,使用 MockMvc 创建 Web 应用程序上下文,并定义 mapToJson() 和 mapFromJson() 方法,以将 Java 对象转换为 JSON 字符串,并将 JSON 字符串转换为 Java 对象。

package com.tutorialspoint.demo;

import java.io.IOException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class)
@WebAppConfiguration
public abstract class AbstractTest {
   protected MockMvc mvc;
   @Autowired
   WebApplicationContext webApplicationContext;

   protected void setUp() {
      mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
   }
   protected String mapToJson(Object obj) throws JsonProcessingException {
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.writeValueAsString(obj);
   }
   protected <T> T mapFromJson(String json, Class<T> clazz)
      throws JsonParseException, JsonMappingException, IOException {
      
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.readValue(json, clazz);
   }
}

接下来,编写一个扩展 AbstractTest 类的类文件,并为每个方法(如 GET、POST、PUT 和 DELETE)编写单元测试。

GET API 测试用例的代码如下所示。此 API 用于查看产品列表。

@Test
public void getProductsList() throws Exception {
   String uri = "/products";
   MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get(uri)
      .accept(MediaType.APPLICATION_JSON_VALUE)).andReturn();
   
   int status = mvcResult.getResponse().getStatus();
   assertEquals(200, status);
   String content = mvcResult.getResponse().getContentAsString();
   Product[] productlist = super.mapFromJson(content, Product[].class);
   assertTrue(productlist.length > 0);
}

POST API 测试用例的代码如下所示。此 API 用于创建产品。

@Test
public void createProduct() throws Exception {
   String uri = "/products";
   Product product = new Product();
   product.setId("3");
   product.setName("Ginger");
   
   String inputJson = super.mapToJson(product);
   MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(uri)
      .contentType(MediaType.APPLICATION_JSON_VALUE).content(inputJson)).andReturn();
   
   int status = mvcResult.getResponse().getStatus();
   assertEquals(201, status);
   String content = mvcResult.getResponse().getContentAsString();
   assertEquals(content, "Product is created successfully");
}

下面给出 PUT API 测试用例的代码。此 API 用于更新现有产品。

@Test
public void updateProduct() throws Exception {
   String uri = "/products/2";
   Product product = new Product();
   product.setName("Lemon");
   
   String inputJson = super.mapToJson(product);
   MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put(uri)
      .contentType(MediaType.APPLICATION_JSON_VALUE).content(inputJson)).andReturn();
   
   int status = mvcResult.getResponse().getStatus();
   assertEquals(200, status);
   String content = mvcResult.getResponse().getContentAsString();
   assertEquals(content, "Product is updated successsfully");
}

下面给出 Delete API 测试用例的代码。此 API 将删除现有产品。

@Test
public void deleteProduct() throws Exception {
   String uri = "/products/2";
   MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.delete(uri)).andReturn();
   int status = mvcResult.getResponse().getStatus();
   assertEquals(200, status);
   String content = mvcResult.getResponse().getContentAsString();
   assertEquals(content, "Product is deleted successsfully");
}

下面给出完整的 Controller 测试类文件 -

package com.tutorialspoint.demo;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import com.tutorialspoint.demo.model.Product;

public class ProductServiceControllerTest extends AbstractTest {
   @Override
   @Before
   public void setUp() {
      super.setUp();
   }
   @Test
   public void getProductsList() throws Exception {
      String uri = "/products";
      MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get(uri)
         .accept(MediaType.APPLICATION_JSON_VALUE)).andReturn();
      
      int status = mvcResult.getResponse().getStatus();
      assertEquals(200, status);
      String content = mvcResult.getResponse().getContentAsString();
      Product[] productlist = super.mapFromJson(content, Product[].class);
      assertTrue(productlist.length > 0);
   }
   @Test
   public void createProduct() throws Exception {
      String uri = "/products";
      Product product = new Product();
      product.setId("3");
      product.setName("Ginger");
      String inputJson = super.mapToJson(product);
      MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(uri)
         .contentType(MediaType.APPLICATION_JSON_VALUE)
         .content(inputJson)).andReturn();
      
      int status = mvcResult.getResponse().getStatus();
      assertEquals(201, status);
      String content = mvcResult.getResponse().getContentAsString();
      assertEquals(content, "Product is created successfully");
   }
   @Test
   public void updateProduct() throws Exception {
      String uri = "/products/2";
      Product product = new Product();
      product.setName("Lemon");
      String inputJson = super.mapToJson(product);
      MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put(uri)
         .contentType(MediaType.APPLICATION_JSON_VALUE)
         .content(inputJson)).andReturn();
      
      int status = mvcResult.getResponse().getStatus();
      assertEquals(200, status);
      String content = mvcResult.getResponse().getContentAsString();
      assertEquals(content, "Product is updated successsfully");
   }
   @Test
   public void deleteProduct() throws Exception {
      String uri = "/products/2";
      MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.delete(uri)).andReturn();
      int status = mvcResult.getResponse().getStatus();
      assertEquals(200, status);
      String content = mvcResult.getResponse().getContentAsString();
      assertEquals(content, "Product is deleted successsfully");
   }
}

您可以创建一个可执行的 JAR 文件,并使用下面给出的 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用以下命令:

mvn clean install 

现在,您可以在控制台窗口中查看测试结果。

Test Results in Console Window

对于 Gradle,您可以使用以下命令:

gradle clean build

您可以在控制台窗口中看到其余结果,如下所示。

Rest Results in Console Window

Spring Boot - 数据库处理

Spring Boot 为创建数据库的 DataSource 提供了非常好的支持。我们不需要编写任何额外的代码来在 Spring Boot 中创建 DataSource。只需添加依赖项并进行配置详细信息就足以创建 DataSource 并连接数据库。

在本章中,我们将使用 Spring Boot JDBC 驱动程序连接来连接数据库。

首先,我们需要在构建配置文件中添加 Spring Boot Starter JDBC 依赖项。

Maven 用户可以在 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项。

compile('org.springframework.boot:spring-boot-starter-jdbc')

连接到 H2 数据库

要连接 H2 数据库,我们需要在构建配置文件中添加 H2 数据库依赖项。

对于 Maven 用户,请在您的 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
</dependency>

对于 Gradle 用户,请在您的 build.gradle 文件中添加以下依赖项。

compile('com.h2database:h2')

我们需要在类路径 src/main/resources 目录下创建 schema.sql 文件和 data.sql 文件以连接 H2 数据库。

schema.sql 文件如下所示。

CREATE TABLE PRODUCT (ID INT PRIMARY KEY, PRODUCT_NAME VARCHAR(25));

data.sql 文件如下所示。

INSERT INTO PRODUCT (ID,PRODUCT_NAME) VALUES (1,'Honey');
INSERT INTO PRODUCT (ID,PRODUCT_NAME) VALUES (2,'Almond');

连接 MySQL

要连接 MySQL 数据库,我们需要将 MySQL 依赖项添加到我们的构建配置文件中。

对于 Maven 用户,请在您的 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
</dependency>

对于 Gradle 用户,请在您的 build.gradle 文件中添加以下依赖项。

compile('mysql:mysql-connector-java')

现在,在 MySQL 中创建数据库和表,如下所示 -

Database and Tables in MySQL

对于属性文件用户,请在 application.properties 文件中添加以下属性。

spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/PRODUCTSERVICE?autoreconnect = true
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.testOnBorrow = true
spring.datasource.testWhileIdle = true
spring.datasource.timeBetweenEvictionRunsMillis = 60000
spring.datasource.minEvictableIdleTimeMillis = 30000
spring.datasource.validationQuery = SELECT 1
spring.datasource.max-active = 15
spring.datasource.max-idle = 10
spring.datasource.max-wait = 8000

对于 YAML 用户,请在 application.yml 文件中添加以下属性。

spring:
   datasource: 
      driverClassName: com.mysql.jdbc.Driver
      url: "jdbc:mysql://127.0.0.1:3306/PRODUCTSERVICE?autoreconnect=true"
      username: "root"
      password: "root"
      testOnBorrow: true
      testWhileIdle: true
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 30000
      validationQuery: SELECT 1
      max-active: 15
      max-idle: 10
      max-wait: 8000

连接 Redis

Redis 是一个开源数据库,用于存储内存中的数据结构。要在 Spring Boot 应用程序中连接 Redis 数据库,我们需要在构建配置文件中添加 Redis 依赖项。

Maven 用户应在您的 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

Gradle 用户应在您的 build.gradle 文件中添加以下依赖项。

compile('org.springframework.boot:spring-boot-starter-data-redis')

对于 Redis 连接,我们需要使用 RedisTemplate。对于 RedisTemplate,我们需要提供 JedisConnectionFactory 的详细信息。

@Bean
JedisConnectionFactory jedisConnectionFactory() {
   JedisConnectionFactory jedisConFactory = new JedisConnectionFactory();
   jedisConFactory.setHostName("localhost");
   jedisConFactory.setPort(6000);
   jedisConFactory.setUsePool(true);
   return jedisConFactory;
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
   RedisTemplate<String, Object> template = new RedisTemplate<>();
   template.setConnectionFactory(jedisConnectionFactory());
   template.setKeySerializer(new StringRedisSerializer());
   template.setHashKeySerializer(new StringRedisSerializer());
   template.setHashValueSerializer(new StringRedisSerializer());
   template.setValueSerializer(new StringRedisSerializer());
   return template;
}

现在自动连接 RedisTemplate 类并从 Redis 数据库访问数据。

@Autowired

RedisTemplate<String, Object> redis;
Map<Object,Object> datalist = redis.opsForHash().entries(“Redis_code_index_key”);

JDBCTemplate

要在 Spring Boot 应用程序中使用 JdbcTemplate 访问关系数据库,我们需要在构建配置文件中添加 Spring Boot Starter JDBC 依赖项。

然后,如果您 @Autowired JdbcTemplate 类,Spring Boot 会自动连接数据库并为 JdbcTemplate 对象设置 Datasource。

@Autowired
JdbcTemplate jdbcTemplate;
Collection<Map<String, Object>> rows = jdbc.queryForList("SELECT QUERY");

@Repository 注解应该添加到类文件中。@Repository 注解用于为您的 Spring Boot 应用程序创建数据库存储库。

@Repository
public class ProductServiceDAO {
}

多个 DataSource

我们可以在单个 Spring Boot 应用程序中保留 'n' 个 DataSource。此处给出的示例显示了如何在 Spring Boot 应用程序中创建多个数据源。现在,在 application 属性文件中添加两个数据源配置详细信息。

对于属性文件用户,请将以下属性添加到您的 application.properties 文件中。

spring.dbProductService.driverClassName = com.mysql.jdbc.Driver
spring.dbProductService.url = jdbc:mysql://127.0.0.1:3306/PRODUCTSERVICE?autoreconnect = true
spring.dbProductService.username = root
spring.dbProductService.password = root
spring.dbProductService.testOnBorrow = true
spring.dbProductService.testWhileIdle = true
spring.dbProductService.timeBetweenEvictionRunsMillis = 60000
spring.dbProductService.minEvictableIdleTimeMillis = 30000
spring.dbProductService.validationQuery = SELECT 1
spring.dbProductService.max-active = 15
spring.dbProductService.max-idle = 10
spring.dbProductService.max-wait = 8000

spring.dbUserService.driverClassName = com.mysql.jdbc.Driver
spring.dbUserService.url = jdbc:mysql://127.0.0.1:3306/USERSERVICE?autoreconnect = true
spring.dbUserService.username = root
spring.dbUserService.password = root
spring.dbUserService.testOnBorrow = true
spring.dbUserService.testWhileIdle = true
spring.dbUserService.timeBetweenEvictionRunsMillis = 60000
spring.dbUserService.minEvictableIdleTimeMillis = 30000
spring.dbUserService.validationQuery = SELECT 1
spring.dbUserService.max-active = 15
spring.dbUserService.max-idle = 10
spring.dbUserService.max-wait = 8000

Yaml 用户应在您的 application.yml 文件中添加以下属性。

spring:
   dbProductService: 
      driverClassName: com.mysql.jdbc.Driver
      url: "jdbc:mysql://127.0.0.1:3306/PRODUCTSERVICE?autoreconnect=true"
      password: "root"
      username: "root"
      testOnBorrow: true
      testWhileIdle: true
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 30000
      validationQuery: SELECT 1
      max-active: 15
      max-idle: 10
      max-wait: 8000
   dbUserService: 
      driverClassName: com.mysql.jdbc.Driver
      url: "jdbc:mysql://127.0.0.1:3306/USERSERVICE?autoreconnect=true"
      password: "root"
      username: "root"
      testOnBorrow: true
      testWhileIdle: true
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 30000
      validationQuery: SELECT 1    
      max-active: 15
      max-idle: 10
      max-wait: 8000

现在,创建一个配置类来为多个数据源创建 DataSource 和 JdbcTemplate。

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;

@Configuration
public class DatabaseConfig {
   @Bean(name = "dbProductService")
   @ConfigurationProperties(prefix = "spring.dbProductService")
   @Primary
   public DataSource createProductServiceDataSource() {
      return DataSourceBuilder.create().build();
   }
   @Bean(name = "dbUserService")
   @ConfigurationProperties(prefix = "spring.dbUserService")
   public DataSource createUserServiceDataSource() {
      return DataSourceBuilder.create().build();
   }
   @Bean(name = "jdbcProductService")
   @Autowired
   public JdbcTemplate createJdbcTemplate_ProductService(@Qualifier("dbProductService") DataSource productServiceDS) {
      return new JdbcTemplate(productServiceDS);
   }
   @Bean(name = "jdbcUserService")
   @Autowired
   public JdbcTemplate createJdbcTemplate_UserService(@Qualifier("dbUserService") DataSource userServiceDS) {
      return new JdbcTemplate(userServiceDS);
   }
}

然后,使用 @Qualifier 注解自动连接 JDBCTemplate 对象。

@Qualifier("jdbcProductService")
@Autowired
JdbcTemplate jdbcTemplate;

@Qualifier("jdbcUserService")
@Autowired
JdbcTemplate jdbcTemplate;

Spring Boot - 保护 Web 应用程序

如果在类路径上添加了 Spring Boot Security 依赖项,则 Spring Boot 应用程序会自动要求所有 HTTP 端点进行基本身份验证。端点“/”和“/home”不需要任何身份验证。所有其他端点都需要身份验证。

要将 Spring Boot Security 添加到您的 Spring Boot 应用程序中,我们需要在构建配置文件中添加 Spring Boot Starter Security 依赖项。

Maven 用户可以在 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项。

compile("org.springframework.boot:spring-boot-starter-security")

保护 Web 应用程序

首先,使用 Thymeleaf 模板创建一个不安全的 Web 应用程序。

然后,在src/main/resources/templates目录下创建一个 home.html 文件。

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:th = "http://www.thymeleaf.org" 
   xmlns:sec = "http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
   
   <head>
      <title>Spring Security Example</title>
   </head>
   <body>
      <h1>Welcome!</h1>
      <p>Click <a th:href = "@{/hello}">here</a> to see a greeting.</p>
   </body>
   
</html>

使用 Thymeleaf 模板在 HTML 文件中定义的简单视图/hello

现在,在src/main/resources/templates目录下创建一个 hello.html。

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:th = "http://www.thymeleaf.org" 
   xmlns:sec = "http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
   
   <head>
      <title>Hello World!</title>
   </head>
   <body>
      <h1>Hello world!</h1>
   </body>
   
</html>

现在,我们需要为 home 和 hello 视图设置 Spring MVC - 视图控制器。

为此,创建一个扩展 WebMvcConfigurerAdapter 的 MVC 配置文件。

package com.tutorialspoint.websecuritydemo;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
   @Override
   public void addViewControllers(ViewControllerRegistry registry) {
      registry.addViewController("/home").setViewName("home");
      registry.addViewController("/").setViewName("home");
      registry.addViewController("/hello").setViewName("hello");
      registry.addViewController("/login").setViewName("login");
   }
}

现在,将 Spring Boot Starter security 依赖项添加到您的构建配置文件中。

Maven 用户可以在 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项。

compile("org.springframework.boot:spring-boot-starter-security")

现在,创建一个 Web 安全配置文 件,用于通过基本身份验证保护应用程序以访问 HTTP 端点。

package com.tutorialspoint.websecuritydemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http
         .authorizeRequests()
            .antMatchers("/", "/home").permitAll()
            .anyRequest().authenticated()
            .and()
         .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .logout()
            .permitAll();
   }
   @Autowired
   public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
      auth
         .inMemoryAuthentication()
         .withUser("user").password("password").roles("USER");
   }
}

现在,在src/main/resources目录下创建一个 login.html 文件,以允许用户通过登录屏幕访问 HTTP 端点。

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:th = "http://www.thymeleaf.org"
   xmlns:sec = "http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
   
   <head>
      <title>Spring Security Example </title>
   </head>
   <body>
      <div th:if = "${param.error}">
         Invalid username and password.
      </div>
      <div th:if = "${param.logout}">
         You have been logged out.
      </div>
      
      <form th:action = "@{/login}" method = "post">
         <div>
            <label> User Name : <input type = "text" name = "username"/> </label>
         </div>
         <div>
            <label> Password: <input type = "password" name = "password"/> </label>
         </div>
         <div>
            <input type = "submit" value = "Sign In"/>
         </div>
      </form>
      
   </body>
</html>

最后,更新 hello.html 文件 - 以允许用户从应用程序注销并在下面显示当前用户名 -

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml" xmlns:th = "http://www.thymeleaf.org" 
   xmlns:sec = "http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
   
   <head>
      <title>Hello World!</title>
   </head>
   <body>
      <h1 th:inline = "text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
      <form th:action = "@{/logout}" method = "post">
         <input type = "submit" value = "Sign Out"/>
      </form>
   </body>
   
</html>

下面给出主 Spring Boot 应用程序的代码 -

package com.tutorialspoint.websecuritydemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebsecurityDemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(WebsecurityDemoApplication.class, args);
   }
}

构建配置文件的完整代码如下所示。

Maven – 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.tutorialspoint</groupId>
   <artifactId>websecurity-demo</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>websecurity-demo</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.security</groupId>
         <artifactId>spring-security-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-security')
   compile('org.springframework.boot:spring-boot-starter-thymeleaf')
   compile('org.springframework.boot:spring-boot-starter-web')
   
   testCompile('org.springframework.boot:spring-boot-starter-test')
   testCompile('org.springframework.security:spring-security-test')
}

现在,创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

Maven 用户可以使用如下所示的命令 -

mvn clean install

在“BUILD SUCCESS”之后,您可以在 target 目录下找到 JAR 文件。

Gradle 用户可以使用如下所示的命令 -

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用以下显示的命令运行 JAR 文件:

java –jar <JARFILE> 

在您的 Web 浏览器中访问 URLhttps://127.0.0.1:8080/。您可以看到如下所示的输出。

Output on Web Browser Click Link

Output Login Page

Output Signout Page

Output Logged Out

Invalid Username Password

Spring Boot - 使用 JWT 的 OAuth2

在本章中,您将详细了解 Spring Boot Security 机制以及 OAuth2 与 JWT。

授权服务器

授权服务器是 Web API 安全性的最高架构组件。授权服务器充当集中式授权点,允许您的应用程序和 HTTP 端点识别应用程序的功能。

资源服务器

资源服务器是一个应用程序,它向客户端提供访问令牌以访问资源服务器 HTTP 端点。它是包含 HTTP 端点、静态资源和动态网页的库的集合。

OAuth2

OAuth2 是一种授权框架,它使应用程序 Web 安全性能够访问客户端的资源。要构建 OAuth2 应用程序,我们需要关注授权类型(授权码)、客户端 ID 和客户端密钥。

 

JWT 令牌

JWT 令牌是 JSON Web 令牌,用于表示在双方之间保护的声明。您可以在www.jwt.io/了解更多关于 JWT 令牌的信息。

现在,我们将构建一个 OAuth2 应用程序,该应用程序通过 JWT 令牌启用授权服务器和资源服务器的使用。

您可以使用以下步骤通过访问数据库来实现带有 JWT 令牌的 Spring Boot Security。

首先,我们需要在构建配置文件中添加以下依赖项。

Maven 用户可以在您的 pom.xml 文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.security.oauth</groupId>
   <artifactId>spring-security-oauth2</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-jwt</artifactId>
</dependency>

<dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>

<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-test</artifactId>
   <scope>test</scope>
</dependency>

Gradle 用户可以在 build.gradle 文件中添加以下依赖项。

compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.security:spring-security-test')

compile("org.springframework.security.oauth:spring-security-oauth2")
compile('org.springframework.security:spring-security-jwt')
compile("org.springframework.boot:spring-boot-starter-jdbc")
compile("com.h2database:h2:1.4.191")  

其中,

  • Spring Boot Starter Security - 实现 Spring Security

  • Spring Security OAuth2 - 实现 OAUTH2 结构以启用授权服务器和资源服务器。

  • Spring Security JWT - 为 Web 安全生成 JWT 令牌

  • Spring Boot Starter JDBC - 访问数据库以确保用户可用与否。

  • Spring Boot Starter Web - 编写 HTTP 端点。

  • H2 数据库 - 存储用于身份验证和授权的用户的信息。

完整的构建配置文件如下所示。

<?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.tutorialspoint</groupId>
   <artifactId>websecurityapp</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>websecurityapp</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath /> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-jdbc</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.security.oauth</groupId>
         <artifactId>spring-security-oauth2</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.security</groupId>
         <artifactId>spring-security-jwt</artifactId>
      </dependency>
      
      <dependency>
         <groupId>com.h2database</groupId>
         <artifactId>h2</artifactId>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      
      <dependency>
         <groupId>org.springframework.security</groupId>
         <artifactId>spring-security-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
   
</project>

Gradle – build.gradle

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}

dependencies {
   compile('org.springframework.boot:spring-boot-starter-security')
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
   testCompile('org.springframework.security:spring-security-test')
   compile("org.springframework.security.oauth:spring-security-oauth2")
   compile('org.springframework.security:spring-security-jwt')
   compile("org.springframework.boot:spring-boot-starter-jdbc")
   compile("com.h2database:h2:1.4.191")  
} 

现在,在主 Spring Boot 应用程序中,添加 @EnableAuthorizationServer 和 @EnableResourceServer 注解,以在同一应用程序中充当 Auth 服务器和资源服务器。

此外,您可以使用以下代码编写一个简单的 HTTP 端点,以使用 JWT 令牌通过 Spring Security 访问 API。

package com.tutorialspoint.websecurityapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableAuthorizationServer
@EnableResourceServer
@RestController
public class WebsecurityappApplication {
   public static void main(String[] args) {
      SpringApplication.run(WebsecurityappApplication.class, args);
   }
   @RequestMapping(value = "/products")
   public String getProductName() {
      return "Honey";   
   }
} 

使用以下代码定义 POJO 类以存储用于身份验证的用户的信息。

package com.tutorialspoint.websecurityapp;

import java.util.ArrayList;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;

public class UserEntity {
   private String username;
   private String password;
   private Collection<GrantedAuthority> grantedAuthoritiesList = new ArrayList<>();
   
   public String getPassword() {
      return password;
   }
   public void setPassword(String password) {
      this.password = password;
   }
   public Collection<GrantedAuthority> getGrantedAuthoritiesList() {
      return grantedAuthoritiesList;
   }
   public void setGrantedAuthoritiesList(Collection<GrantedAuthority> grantedAuthoritiesList) {
      this.grantedAuthoritiesList = grantedAuthoritiesList;
   }
   public String getUsername() {
      return username;
   }
   public void setUsername(String username) {
      this.username = username;
   }
}

现在,使用以下代码并定义 CustomUser 类,该类扩展 org.springframework.security.core.userdetails.User 类以进行 Spring Boot 身份验证。

package com.tutorialspoint.websecurityapp;

import org.springframework.security.core.userdetails.User;

public class CustomUser extends User {
   private static final long serialVersionUID = 1L;
   public CustomUser(UserEntity user) {
      super(user.getUsername(), user.getPassword(), user.getGrantedAuthoritiesList());
   }
} 

您可以创建 @Repository 类以从数据库读取用户信息并将其发送到自定义用户服务,还可以添加授予的权限“ROLE_SYSTEMADMIN”。

package com.tutorialspoint.websecurityapp;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Repository;

@Repository
public class OAuthDao {
   @Autowired
   private JdbcTemplate jdbcTemplate;

   public UserEntity getUserDetails(String username) {
      Collection<GrantedAuthority> grantedAuthoritiesList = new ArrayList<>();
      String userSQLQuery = "SELECT * FROM USERS WHERE USERNAME=?";
      List<UserEntity> list = jdbcTemplate.query(userSQLQuery, new String[] { username },
         (ResultSet rs, int rowNum) -> {
         
         UserEntity user = new UserEntity();
         user.setUsername(username);
         user.setPassword(rs.getString("PASSWORD"));
         return user;
      });
      if (list.size() > 0) {
         GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_SYSTEMADMIN");
         grantedAuthoritiesList.add(grantedAuthority);
         list.get(0).setGrantedAuthoritiesList(grantedAuthoritiesList);
         return list.get(0);
      }
      return null;
   }
} 

您可以创建一个自定义用户详细信息服务类,该类扩展 org.springframework.security.core.userdetails.UserDetailsService 以调用 DAO 存储库类,如下所示。

package com.tutorialspoint.websecurityapp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class CustomDetailsService implements UserDetailsService {
   @Autowired
   OAuthDao oauthDao;

   @Override
   public CustomUser loadUserByUsername(final String username) throws UsernameNotFoundException {
      UserEntity userEntity = null;
      try {
         userEntity = oauthDao.getUserDetails(username);
         CustomUser customUser = new CustomUser(userEntity);
         return customUser;
      } catch (Exception e) {
         e.printStackTrace();
         throw new UsernameNotFoundException("User " + username + " was not found in the database");
      }
   }
} 

接下来,创建一个 @configuration 类以启用 Web 安全性,定义密码编码器 (BCryptPasswordEncoder),并定义 AuthenticationManager bean。安全配置类应扩展 WebSecurityConfigurerAdapter 类。

package com.tutorialspoint.websecurityapp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
   @Autowired
   private CustomDetailsService customDetailsService;

   @Bean
   public PasswordEncoder encoder() {
      return new BCryptPasswordEncoder();
   }
   @Override
   @Autowired
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(customDetailsService).passwordEncoder(encoder());
   }
   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests().anyRequest().authenticated().and().sessionManagement()
         .sessionCreationPolicy(SessionCreationPolicy.NEVER);
   }
   @Override
   public void configure(WebSecurity web) throws Exception {
      web.ignoring();
   }
   @Override
   @Bean
   public AuthenticationManager authenticationManagerBean() throws Exception {
      return super.authenticationManagerBean();
   }
} 

现在,定义 OAuth2 配置类以添加客户端 ID、客户端密钥、定义 JwtAccessTokenConverter、私钥和公钥以用于令牌签名密钥和验证密钥,以及为令牌有效期和范围配置 ClientDetailsServiceConfigurer。

package com.tutorialspoint.websecurityapp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
   private String clientid = "tutorialspoint";
   private String clientSecret = "my-secret-key";
   private String privateKey = "private key";
   private String publicKey = "public key";

   @Autowired
   @Qualifier("authenticationManagerBean")
   private AuthenticationManager authenticationManager;
   
   @Bean
   public JwtAccessTokenConverter tokenEnhancer() {
      JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
      converter.setSigningKey(privateKey);
      converter.setVerifierKey(publicKey);
      return converter;
   }
   @Bean
   public JwtTokenStore tokenStore() {
      return new JwtTokenStore(tokenEnhancer());
   }
   @Override
   public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
      endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore())
      .accessTokenConverter(tokenEnhancer());
   }
   @Override
   public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
      security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
   }
   @Override
   public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
      clients.inMemory().withClient(clientid).secret(clientSecret).scopes("read", "write")
         .authorizedGrantTypes("password", "refresh_token").accessTokenValiditySeconds(20000)
         .refreshTokenValiditySeconds(20000);

   }
} 

现在,使用 openssl 创建私钥和公钥。

您可以使用以下命令生成私钥。

openssl genrsa -out jwt.pem 2048
openssl rsa -in jwt.pem 

您可以使用以下命令生成公钥。

openssl rsa -in jwt.pem -pubout 

对于 1.5 版本之后的 Spring Boot 版本,请在您的 application.properties 文件中添加以下属性以定义 OAuth2 资源过滤器顺序。

security.oauth2.resource.filter-order=3 

YAML 文件用户可以在 YAML 文件中添加以下属性。

security:
   oauth2:
      resource:
         filter-order: 3 

现在,在类路径资源src/main/resources/directory下创建 schema.sql 和 data.sql 文件以将应用程序连接到 H2 数据库。

schema.sql 文件如下所示 -

CREATE TABLE USERS (ID INT PRIMARY KEY, USERNAME VARCHAR(45), PASSWORD VARCHAR(60));

data.sql 文件如下所示 -

INSERT INTO USERS (ID, USERNAME,PASSWORD) VALUES (
   1, '[email protected]','$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG');

INSERT INTO USERS (ID, USERNAME,PASSWORD) VALUES (
   2, '[email protected]','$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG'); 

注意 - 密码应以 Bcrypt 编码器的格式存储在数据库表中。

您可以创建一个可执行的 JAR 文件,并使用以下 Maven 或 Gradle 命令运行 Spring Boot 应用程序。

对于 Maven,您可以使用以下命令:

mvn clean install

在“BUILD SUCCESS”之后,您可以在target目录下找到JAR文件。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

现在,使用此处显示的命令运行 JAR 文件:

java –jar <JARFILE> 

应用程序在 Tomcat 端口 8080 上启动。

Tomcat Port 8080 Application Output

现在通过 POSTMAN 访问 POST 方法 URL 以获取 OAUTH2 令牌。

https://127.0.0.1:8080/oauth/token

现在,添加请求标头,如下所示 -

  • Authorization - 使用您的客户端 ID 和客户端密钥的基本身份验证。

  • Content Type - application/x-www-form-urlencoded

Add Request Headers

现在,添加请求参数,如下所示 -

  • grant_type = password
  • username = 您的用户名
  • password = 您的密码
Add Request Parameters

现在,访问 API 并获取 access_token,如下所示 -

Get the Access-Token

现在,在请求标头中使用 Bearer 访问令牌访问资源服务器 API,如下所示。

Resource Server API with Bearer Access Token

然后,您可以看到如下所示的输出 -

OAuth2 with JWT Output

Spring Boot - Google Cloud Platform

Google Cloud Platform 提供云计算服务,这些服务在云环境中运行 Spring Boot 应用程序。在本章中,我们将了解如何在 GCP App Engine 平台上部署 Spring Boot 应用程序。

首先,从 Spring Initializer 页面www.start.spring.io下载 Gradle 构建 Spring Boot 应用程序。观察以下屏幕截图。

Spring Initializer Page

现在,在 build.gradle 文件中,添加 Google Cloud appengine 插件和 appengine 类路径依赖项。

build.gradle 文件的代码如下所示 -

buildscript {
   ext {
      springBootVersion = '1.5.9.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
      classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.3.3'
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'com.google.cloud.tools.appengine'

group = 'com.tutorialspoint'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
} 

现在,编写一个简单的 HTTP 端点,它返回字符串“success”,如下所示 -

package com.tutorialspoint.appenginedemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class AppengineDemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(AppengineDemoApplication.class, args);
   }
   @RequestMapping(value = "/")
   public String success() {
      return "APP Engine deployment success";
   }
} 

接下来,在 src/main/appengine 目录下添加 app.yml 文件,如下所示 -

runtime: java
env: flex

handlers:
- url: /.*
   script: this field is required, but ignored 

现在,转到 Google Cloud 控制台,然后单击页面顶部的“激活 Google Cloud Shell”。

Activate Google Cloud Shell

现在,使用 Google Cloud Shell 将您的源文件和 Gradle 文件移动到 Google Cloud 机器的主目录中。

Moving to Home Directory Using Google Cloud Shell

现在,执行命令 gradle appengineDeploy,它会将您的应用程序部署到 Google Cloud App Engine 中。

注意 - GCP 应启用计费,并且在将应用程序部署到 App Engine 之前,您应在 GCP 中创建 App Engine 平台。

将您的应用程序部署到 GCP App Engine 平台需要几分钟时间。

构建成功后,您可以在控制台窗口中看到服务 URL。

Spring Initializer Page

现在,访问服务 URL 并查看输出。

App Engine Development Success

Google Cloud SQL

要将 Google Cloud SQL 连接到您的 Spring Boot 应用程序,您应将以下属性添加到您的 application.properties 文件中。

JDBC URL 格式

jdbc:mysql://google/<DATABASE-NAME>?cloudSqlInstance = <GOOGLE_CLOUD_SQL_INSTANCE_NAME> &socketFactory = com.google.cloud.sql.mysql.SocketFactory&user = <USERNAME>&password = <PASSWORD>

注意 - Spring Boot 应用程序和 Google Cloud SQL 应位于同一 GCP 项目中。

application.properties 文件如下所示。

spring.dbProductService.driverClassName = com.mysql.jdbc.Driver
spring.dbProductService.url = jdbc:mysql://google/PRODUCTSERVICE?cloudSqlInstance = springboot-gcp-cloudsql:asia-northeast1:springboot-gcp-cloudsql-instance&socketFactory = com.google.cloud.sql.mysql.SocketFactory&user = root&password = rootspring.dbProductService.username = root

spring.dbProductService.password = root
spring.dbProductService.testOnBorrow = true
spring.dbProductService.testWhileIdle = true
spring.dbProductService.timeBetweenEvictionRunsMillis = 60000
spring.dbProductService.minEvictableIdleTimeMillis = 30000
spring.dbProductService.validationQuery = SELECT 1
spring.dbProductService.max-active = 15
spring.dbProductService.max-idle = 10
spring.dbProductService.max-wait = 8000

YAML 文件用户可以将以下属性添加到您的 application.yml 文件中。

spring:
   datasource: 
      driverClassName: com.mysql.jdbc.Driver
      url: "jdbc:mysql://google/PRODUCTSERVICE?cloudSqlInstance=springboot-gcp-cloudsql:asia-northeast1:springboot-gcp-cloudsql-instance&socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=root&password=root"
      password: "root"
      username: "root"
      testOnBorrow: true
      testWhileIdle: true
      validationQuery: SELECT 1
      
      max-active: 15
      max-idle: 10
      max-wait: 8000

Spring Boot - Google OAuth2 登录

在本章中,我们将了解如何使用带有 Gradle 构建的 Spring Boot 应用程序添加 Google OAuth2 登录。

首先,在您的构建配置文件中添加 Spring Boot OAuth2 安全依赖项,您的构建配置文件如下所示。

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

group = 'com.tutorialspoint.projects'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter')
   testCompile('org.springframework.boot:spring-boot-starter-test')
   compile('org.springframework.security.oauth:spring-security-oauth2')
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}  

现在,添加 HTTP 端点以在通过 Spring Boot 进行身份验证后从 Google 读取用户主体,如以下 Spring Boot 应用程序类文件所示:

package com.tutorialspoint.projects.googleservice;

import java.security.Principal;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class GoogleserviceApplication {
   public static void main(String[] args) {
      SpringApplication.run(GoogleserviceApplication.class, args);
   }
   @RequestMapping(value = "/user")
   public Principal user(Principal principal) {
      return principal;
   }
}

现在,编写一个配置文件以启用 Web 安全的 OAuth2SSO 并删除 index.html 文件的身份验证,如下所示:

package com.tutorialspoint.projects.googleservice;

import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableOAuth2Sso
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http
         .csrf()
         .disable()
         .antMatcher("/**")
         .authorizeRequests()
         .antMatchers("/", "/index.html")
         .permitAll()
         .anyRequest()
         .authenticated();
   }
}

接下来,在静态资源下添加 index.html 文件,并添加链接以重定向到用户 HTTP 端点以读取 Google 用户主体,如下所示:

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "ISO-8859-1">
      <title>Insert title here</title>
   </head>
   <body>
      <a href = "user">Click here to Google Login</a>
   </body>
</html> 

注意 - 在 Google Cloud 控制台中,启用 Gmail 服务、分析服务和 Google+ 服务 API。

然后,转到“凭据”部分并创建凭据,然后选择“OAuth 客户端 ID”。

Credentials Section

接下来,在 OAuth2 同意屏幕中提供产品名称。

Product Name in OAuth2 Consent Screen

接下来,将应用程序类型选择为“Web 应用程序”,并提供授权的 JavaScript 来源和授权的重定向 URI。

Authorized Redirect URIs

现在,您的 OAuth2 客户端 ID 和客户端密钥已创建。

OAuth2 Client Id Created

接下来,在您的应用程序属性文件中添加客户端 ID 和客户端密钥。

security.oauth2.client.clientId = <CLIENT_ID>
security.oauth2.client.clientSecret = <CLIENT_SECRET>
security.oauth2.client.accessTokenUri  =  https://www.googleapis.com/oauth2/v3/token
security.oauth2.client.userAuthorizationUri  =  https://127.0.0.1/o/oauth2/auth
security.oauth2.client.tokenName = oauth_token
security.oauth2.client.authenticationScheme = query
security.oauth2.client.clientAuthenticationScheme = form
security.oauth2.client.scope = profile email

security.oauth2.resource.userInfoUri  =  https://www.googleapis.com/userinfo/v2/me
security.oauth2.resource.preferTokenInfo = false

现在,您可以创建一个可执行的 JAR 文件,并使用以下 Gradle 命令运行 Spring Boot 应用程序。

对于 Gradle,您可以使用以下命令:

gradle clean build

在“BUILD SUCCESSFUL”之后,您可以在build/libs目录下找到JAR文件。

使用命令 java –jar <JARFILE> 运行 JAR 文件,应用程序将在 Tomcat 端口 8080 上启动。

现在访问 URL https://127.0.0.1:8080/ 并点击 Google 登录链接。

Google Login link

它将重定向到 Google 登录屏幕,并提供 Gmail 登录详细信息。

Google Login Screen

如果登录成功,我们将收到 Gmail 用户的主体对象。

Principal Object of The Gmail User
广告