Spring Boot 简明教程

Spring Boot - Quick Guide

Spring Boot - Introduction

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

What is Micro Service?

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

Advantages

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

  1. Easy deployment

  2. Simple scalability

  3. Compatible with Containers

  4. Minimum configuration

  5. Lesser production time

What is Spring Boot?

Spring Boot 为 Java 开发人员提供了一个非常好的平台,用于开发您可以在 just run 的独立而且可用于生产的 Spring 应用程序。您可以在无需进行整个 Spring 配置设置的情况下开始使用最低配置。

Advantages

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

  1. 易于理解和开发 Spring 应用程序

  2. Increases productivity

  3. Reduces the development time

Goals

Spring Boot 基于以下目标设计−

  1. 避免在 Spring 中进行复杂的 XML 配置

  2. 以一种更轻松的方式开发可用于生产的 Spring 应用程序

  3. 减少开发时间并独立运行应用程序

  4. 提供一种更轻松方式来开始使用应用程序

Why Spring Boot?

您可以根据这里提供的特性和优势选择 Spring Boot−

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

  2. 它提供强大的批处理功能并管理 REST 终结点。

  3. 在 Spring Boot 中,所有内容都是自动配置的;无需手动配置。

  4. 它提供了基于注释的 Spring 应用程序

  5. Eases dependency management

  6. 它包含嵌入式 Servlet 容器

How does it work?

Spring Boot 根据您使用 @EnableAutoConfiguration 注释添加到项目的依赖项自动配置您的应用程序。例如,如果 MySQL 数据库在您的类路径中,但是您还未配置任何数据库连接,那么 Spring Boot 会自动配置一个内存数据库。

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

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

Spring Boot Starters

处理依赖管理对于大型项目而言是一项艰巨的任务。Spring Boot 通过为开发者提供一组依赖项来解决这个问题。

例如,如果您想使用 Spring 和 JPA 访问数据库,那么只需要在项目中包含 spring-boot-starter-data-jpa 依赖项就足够了。

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

Examples

查看下面解释的以下 Spring 引导启动器以更好地理解 −

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

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

Spring Boot Starter Security dependency 用于 Spring Security。其代码如下所示 −

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

Spring Boot Starter web dependency 用于编写 REST 端点。其代码如下所示 −

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

Spring Boot Starter Thyme Leaf dependency 用于创建 Web 应用程序。其代码如下所示 −

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

Spring Boot Starter Test dependency 用于编写测试用例。其代码如下所示 −

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

Auto Configuration

Spring Boot 自动配置会根据您在项目中添加的 JAR 依赖项自动配置您的 Spring 应用程序。例如,如果 MySQL 数据库在您的类路径中,但您尚未配置任何数据库连接,那么 Spring Boot 会自动配置内存数据库。

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

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

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 Application

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

如果您向类中添加 @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);
   }
}

Component Scan

当应用程序初始化时,Spring 引导应用程序扫描所有 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 - Quick Start

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

Prerequisites

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

  1. Java 7

  2. Maven 3.2

  3. Gradle 2.5

Spring Boot CLI

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

本节向你介绍手动安装 Spring Boot CLI 所涉及的步骤。如需获得进一步的帮助,你可以使用以下链接: https://docs.spring.io/springboot/ docs/current-SNAPSHOT/reference/htmlsingle/#getting-started-installing-springboot

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

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

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

Run Hello World with Groovy

创建一个简单的 groovy 文件,其中包含 Rest Endpoint 脚本,并使用 spring boot CLI 运行该 groovy 文件。观察此处为此目的所示的代码 −

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

现在,以 hello.groovy 的名称保存该 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 http://localhost:8080/ ,您可以看到所示的输出。

hello spring boot

Spring Boot - Bootstrapping

本章将向您解释如何在 Spring Boot 应用程序上执行启动。

Spring Initializer

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

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

spring initializer

在您提供组、制品、依赖项、构建项目、平台和版本后,单击 Generate Project 按钮。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')
}

Class Path Dependencies

Spring Boot 提供许多 Starters ,用于向我们的类路径中添加 jar。例如,对于编写 Rest 端点,我们需要在我们的类路径中添加 spring-boot-starter-web 依赖项。观察下面显示的代码以获得更好的理解 −

Maven dependency

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

Gradle dependency

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

Main Method

spring boot 应用程序类应该编写这个主方法。这个类应该使用 @SpringBootApplication 进行注释。这是 spring boot 应用程序开始的入口点。你可以在使用默认包的 src/java/main 目录中找到主类文件。

在这个例子中,主类文件位于使用默认包 com.tutorialspoint.demosrc/java/main 目录中。观察这里展示的代码以获得更好的理解 −

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

Write a Rest Endpoint

要在 spring boot 应用程序主类文件中编写一个简单的 Hello Word Rest 端点,请遵循以下步骤 −

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

  2. 现在,使用 @RequestMapping 注释编写一个 Request URI 方法。

  3. 然后,Request 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";
   }
}

Create an Executable JAR

让我们使用如下所示在命令提示符中使用 Maven 和 Gradle 命令创建一个可执行 JAR 文件来运行 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

Run Hello World with Java

创建可执行 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 浏览器并输入 URL http://localhost:8080/ ,你将能看到如下所示的输出 −

tomcat started on port 8080 http

Spring Boot - Tomcat Deployment

通过使用 Spring Boot 应用程序,我们可以在 web 服务器中创建 war 文件进行部署。在此章节中,您将学习如何创建一个 WAR 文件,并在 Tomcat web 服务器中部署 Spring Boot 应用程序。

Spring Boot Servlet Initializer

传统的部署方式是让 Spring Boot 应用程序 @SpringBootApplication 类继承 SpringBootServletInitializer 类。Spring Boot Servlet Initializer 类文件允许您在启动应用程序时使用 Servlet Container 进行配置。

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

Setting Main Class

在 Spring Boot 中,我们需要在构建文件中提及应启动的主类。为此,您可以使用以下代码片断 -

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

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

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

mainClassName="com.tutorialspoint.demo.DemoApplication"

Update packaging JAR into 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 starter 依赖项添加到构建文件中。

对于 Maven,使用以下代码在 pom.xml 中添加 Spring Boot starter 依赖项:

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

对于 Gradle,使用以下代码在 build.gradle 中添加 Spring Boot starter 依赖项:

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

Packaging your Application

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

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

maven mvn package
maven packaging application target directory

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

gradle clean build command
maven packaging application target directory

Deploy into Tomcat

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

tomcat web application maneger
webapps directory

成功部署后,在 Web 浏览器 http://localhost:8080/demo-0.0.1-SNAPSHOT/ 中输入 URL,你会看到输出的外观如下面给出的屏幕截图所示:

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

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

Dependency Management

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

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

Maven Dependency

对于 Maven 配置,我们应继承 Spring Boot Starter 父项目以管理 Spring Boot Starter 依赖项。为此,我们可以像下面所示一样简单地继承 our pom.xml 文件中的 starter parent。

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

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

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

Gradle Dependency

我们可以直接将 Spring Boot Starter 依赖项导入 build.gradle 文件中。我们不需要像针对 Gradle 的 Maven 那样的 Spring Boot Start 父依赖项。观察下面给出的代码 −

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

Spring Boot 没有可供使用的代码布局。但是,有一些最佳做法将有助于我们。本章将详细讨论这些做法。

Default package

一个不包含任何 package 声明的类被视为一个 default package 。请注意,通常不建议使用默认的 package 声明。当您使用默认 package 时,Spring Boot 将导致问题,例如自动配置或组件扫描出现故障。

Note - Java 为 package 声明推荐的命名约定是反转域名。例如 − com.tutorialspoint.myproject

Typical Layout

Spring Boot 应用程序的典型布局如下面给出的图片所示 −

typical layout of spring boot application

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

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

Beans and Dependency Injection

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

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

以下示例提供了有关自动连接 Rest 模板对象并为其创建 Bean 的思路:

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

以下代码显示了在 Spring 引导应用程序主类文件中自动连接的 Rest 模板对象和 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 - Runners

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

查看下面 控制台窗口中的“来自 Command Line Runner 的 Hello world”,在 Tomcat 启动后执行 println 语句。

command line runner

Spring Boot - Application Properties

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

Command Line Properties

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

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

Step 2 − 使用下面截图中给出的命令,通过使用命令行属性更改 Spring Boot 应用程序的端口号。

command line properties jarfile

Note − 使用分隔符 − ­可以提供多个应用程序属性。

Properties File

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

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

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

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

YAML File

Spring Boot 支持基于 YAML 的属性配置以运行应用程序。我们可以使用 application.yml 文件代替 application.properties 。此 YAML 文件还应保留在 classpath 中。示例 application.yml 文件如下 −

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

Externalized Properties

我们可以将属性保留在不同位置或路径,而不用将属性文件保留在 classpath 中。在运行 JAR 文件时,我们可以指定属性文件路径。你可以使用以下命令来指定运行 JAR 时属性文件的位置 −

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

Use of @Value Annotation

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

Note − 如果在运行应用程序时未找到属性,Spring Boot 会抛出 Illegal Argument 异常,形式为 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 Active Profile

Spring Boot 支持基于 Spring 活动配置文件的不同属性。例如,我们可以保持两个独立的文件,用于开发和生产,以运行 Spring Boot 应用程序。

Spring active profile in application.properties

让我们了解如何在 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)

Spring active profile for application.yml

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

下面是一个示例代码,用于将 Spring 活动配置文件保存在 application.yml 文件中。请注意,分隔符 (---) 用于在 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

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

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

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

如果您使用的是 Spring Boot Starter,则 Logback 将很好地支持记录。此外,Logback 同样为通用记录、Util 记录、Log4J 和 SLF4J 提供良好的支持。

Log Format

Spring Boot 的 Log 默认格式如下面给出的屏幕截图中所示。

spring boot log format

它向您提供以下信息 −

  1. DateTime ,它们给出了日志的日期和时间

  2. Log level 表示 INFO、ERROR 或 WARN

  3. Process ID

  4. 分隔符 ---

  5. Thread name 用方括号 [] 括起来

  6. Logger Name 表示 Source 类名

  7. The Log message

Console Log Output

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

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

java –jar demo.jar --debug

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

debug = true

File Log Output

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

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

logging.path = /var/tmp/

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

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

Note - 文件在达到 10 MB 大小时将自动轮换。

Log Levels

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

logging.level.root = WARN

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

Configure Logback

Logback 支持基于 XML 的配置来处理 Spring Boot Log 配置。日志配置详细信息配置在 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>

下面给出的代码展示如何将 slf4j 记录器添加到 Spring Boot 主类文件中。

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 - Building RESTful Web Services

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

Note - 对于构建 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 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>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 – 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 Controller

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

@RestController
public class ProductServiceController {
}

Request Mapping

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

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

Request Body

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

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

Path Variable

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

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

Request Parameter

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

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

GET API

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

定义 HTTP GET 请求方法的示例代码如下所示。在此示例中,我们使用 HashMap 来存储产品。请注意,我们使用 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 来存储产品,其中产品是一个 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 来更新现有产品,其中产品是一个 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);
   }
}

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

The Spring Boot main application class – 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);
   }
}

The POJO class – 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;
   }
}

The Rest Controller class – 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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,使用以下所示的命令 −

gradle clean build

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

您可以使用以下所示的命令运行 JAR 文件 −

java –jar <JARFILE>

这将启动 8080 端口上的应用程序,如下所示 −

started application on tomcat port 8080

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

GET API URL 为: http://localhost:8080/products

postman application get api url

POST API URL 为: http://localhost:8080/products

postman application post api url
postman application put api url

DELETE API URL 为: http://localhost:8080/products/3

postman application delete api url

Spring Boot - Exception Handling

在 API 中处理异常和错误,并向客户端发送适当响应,这对于企业应用程序而言十分有益。在本章中,我们将学习如何在 Spring Boot 中处理异常。

在开始异常处理之前,让我们了解一下以下注解。

Controller Advice

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

Exception Handler

@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 方法来处理异常,如下所示。这种方法应该用于编写控制器建议类文件。

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

全局处理异常的控制器建议类如下所示。我们可以在这个类文件中定义任何异常处理方法。

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 class 的代码如下所示 −

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 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>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 – 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”之后,您可以在目标目录中找到 JAR 文件。

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

gradle clean build

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

你可以使用以下命令运行 JAR 文件 −

java –jar <JARFILE>

这将启动 8080 端口上的应用程序,如下所示 −

exception handling tomcat application startded

现在在 POSTMAN 应用程序中访问下面的 URL,你就可以看到如下所示的输出 −

更新 URL: [role="bare"] [role="bare"]http://localhost:8080/products/3

postman application update url

Spring Boot - Interceptor

你可以在 Spring Boot 中使用 Interceptor 在下列情况中执行操作 −

  1. 在向控制器发送请求之前

  2. 在向客户端发送响应之前

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

要使用拦截器,你需要创建支持它的 @Component 类,并实现 HandlerInterceptor 接口。

以下是使用拦截器时你需要了解的三种方法 −

  1. preHandle() 方法 − 该方法用于在向控制器发送请求之前执行操作。该方法应返回 true 以将响应返回给客户端。

  2. postHandle() 方法 − 该方法用于在向客户端发送响应之前执行操作。

  3. 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 将此 Interceptor 注册到 InterceptorRegistry ,如下所示 −

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

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

在下面的示例中,我们将触及 GET products API,其输出如下所示 −

Interceptor 类 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");
   }
}

注册 Interceptor 的应用程序配置类文件的代码,InterceptorRegistry – 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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,像下面这样使用命令 -

gradle clean build

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

你可以使用以下命令运行 JAR 文件 −

java –jar <JARFILE>

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

started application on tomcat port 8080

现在在 POSTMAN 应用程序中点击下面的 URL,您会看到像下面显示的输出−

postman application get api url

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

interceptor output console window

Spring Boot - Servlet Filter

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

  1. 在向控制器发送请求之前

  2. 在向客户端发送响应之前。

以下代码展示了一个 Servlet 过滤器实现类的样例代码,带 @Component 注解。

@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

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

对于 Gradle,像下面这样使用命令 -

gradle clean build

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

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

java –jar <JARFILE>

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

现在点击 URL http://localhost:8080/ 并查看输出 Hello World。它应该像下面显示的那样−

tomcat started on port 8080 http

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

remote host remote address on console log

Spring Boot - Tomcat Port Number

Spring Boot 允许您在不同的端口号上多次运行同一应用程序。本章将对此进行详细说明。请注意,默认端口号为 8080。

Custom Port

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

server.port = 9090

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

server:
   port: 9090

Random Port

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

server.port = 0

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

server:
   port: 0

Note − 如果在启动 Spring Boot 应用程序时 server.port 号码为 0,则 Tomcat 将使用随机端口号。

Spring Boot - Rest Template

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

Consuming the GET API by using RestTemplate - exchange() method

假设此 URL http://localhost:8080/products 返回以下 JSON,我们将使用以下代码通过 Rest Template 使用此 API 响应 -

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

您将必须遵循给定的要点来使用 API -

  1. 自动化 Rest Template 对象。

  2. 使用 HttpHeaders 设置请求标头。

  3. 使用 HttpEntity 包装请求对象。

  4. 提供 URL、HttpMethod 和 Exchange() 方法的返回类型。

@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("
         http://localhost:8080/products", HttpMethod.GET, entity, String.class).getBody();
   }
}

POST

Consuming POST API by using RestTemplate - exchange() method

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

以下给出的代码为请求正文 -

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

以下给出的代码为响应正文 -

Product is created successfully

您将必须遵循下面给出的要点来使用 API -

  1. 自动化 Rest Template 对象。

  2. 使用 HttpHeaders 设置请求标头。

  3. 使用 HttpEntity 包装请求对象。在此,我们将包装 Product 对象以将其发送到请求正文。

  4. 提供 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(
         "http://localhost:8080/products", HttpMethod.POST, entity, String.class).getBody();
   }
}

PUT

Consuming PUT API by using RestTemplate - exchange() method

假设此 URL http://localhost:8080/products/3 返回如下响应,我们将使用 Rest Template 使用此 API 响应。

以下代码为请求正文 -

{
   "name":"Indian Ginger"
}

以下给出的代码为响应正文 -

Product is updated successfully

您将必须遵循下面给出的要点来使用 API -

  1. 自动化 Rest Template 对象。

  2. 使用 HttpHeaders 设置请求标头。

  3. 使用 HttpEntity 包装请求对象。在此,我们将包装 Product 对象以将其发送到请求正文。

  4. 提供 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(
         "http://localhost:8080/products/"+id, HttpMethod.PUT, entity, String.class).getBody();
   }
}

DELETE

Consuming DELETE API by using RestTemplate - exchange() method

假设此 URL http://localhost:8080/products/3 返回给定的响应,并且我们准备使用 Rest 模板来处理此 API 响应。

下面显示的此代码行是响应主体 -

Product is deleted successfully

您必须遵循下方所示步骤,以处理 API -

  1. 自动化 Rest Template 对象。

  2. 使用 HttpHeaders 设置请求标头。

  3. 使用 HttpEntity 包装请求对象。

  4. 提供 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(
         "http://localhost:8080/products/"+id, HttpMethod.DELETE, entity, String.class).getBody();
   }
}

完整的 Rest 模板控制器类文件如下 -

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(
         "http://localhost: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(
         "http://localhost: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(
         "http://localhost: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(
         "http://localhost: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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,您可以使用下面显示的命令 −

gradle clean build

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

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

java –jar <JARFILE>

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

started application on tomcat port 8080

现在在 POSTMAN 应用程序中输入以下 URL,您将看到输出。

使用 Rest 模板获取产品 - http://localhost:8080/template/products

get products by rest template
create products post
update products post
delete products post

Spring Boot - File Handling

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

File Upload

对于上传文件,您可以使用 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";
   }
}

File Download

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

Note − 在以下示例中,文件应可在应用程序正在运行的指定路径上获得。

@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

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

对于 Gradle,您可以使用以下所示命令 −

sgradle clean build

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

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

java –jar <JARFILE>

这将启动 8080 端口上的应用程序,如下所示 −

started application on tomcat port 8080

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

文件上传 − http://localhost:8080/upload

postman application file upload

文件下载 − http://localhost:8080/upload

Spring Boot - Service Components

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

public interface ProductService {
}

实现 @Service 批注的接口的类如下所示:

@Service
public class ProductServiceImpl implements ProductService {
}

请注意,在本教程中,我们使用 Product Service API(s) 来存储、检索、更新和删除产品。我们在 @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();
}

以下代码可让你创建一个实现 ProdutoService 接口的类,用 @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 控制器的类文件,在这里我们 @Autowired 了 ProdutoService 接口并调用了方法。

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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,你可以使用如下所示的命令:

gradle clean build

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

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

java –jar <JARFILE>

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

build successful

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

postman application get api url
postman application post api url
postman application put api url

DELETE API URL 是− http://localhost:8080/products/3

postman application delete api url

Spring Boot - Thymeleaf

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

Thymeleaf Templates

Thymeleaf 将你的文件转换为格式良好的 XML 文件。它包含 6 种类型的模板,如下所示 −

  1. XML

  2. Valid XML

  3. XHTML

  4. Valid XHTML

  5. HTML5

  6. Legacy HTML5

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

Web Application

你可以使用 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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,像下面这样使用命令 -

gradle clean build

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

使用此处提供的命令运行 JAR 文件 −

java –jar <JARFILE>

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

started application on tomcat port 8080

现在在您的浏览器中输入 URL,您可以看到输出如下所示 −

spring boot thymleaf web application

Consuming RESTful Web Services

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

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

我们需要在构建配置文件中添加 Spring Boot 入门 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 http://localhost: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("http://localhost:9090/products", function(result){
      $.each(result, function(key,value) {
         $("#productsJson").append(value.id+" "+value.name+" ");
      });
   });
});
</script>

POST 方法和此 URL http://localhost: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 : "http://localhost: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("http://localhost: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 : "http://localhost: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 引导应用程序。

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

mvn clean install

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

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

gradle clean build

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

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

java –jar <JARFILE>

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

started application on tomcat port 8080

现在在您的浏览器中输入 URL,您可以看到输出如下所示 −

[role="bare"] [role="bare"]http://localhost:8080/view-products

1honey 2almond

[role="bare"] [role="bare"]http://localhost:8080/add-products

submit form spring boot

现在,单击按钮 Click here to submit the form ,您便可以看到结果,如下所示

submit form spring boot output window

现在,点击查看产品网址,查看已创建的产品。

1honey 2almond 3ginger

Angular JS

如需使用 Angular JS 消费 API,可以使用以下提供的示例 −

使用以下代码创建 Angular JS 控制器以消费 GET API - http://localhost:9090/products

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

使用以下代码创建 Angular JS 控制器以消费 POST API - http://localhost:9090/products

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

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

Spring Boot - CORS Support

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

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

需要两个条件来处理此问题 −

  1. RESTful Web 服务应该支持跨源资源共享。

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

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

Enable CORS in Controller Method

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

@RequestMapping(value = "/products")
@CrossOrigin(origins = "http://localhost:8080")

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

Global CORS Configuration

我们需要定义所示的 @Bean 配置,以将 CORS 配置支持全局应用于你的 Spring Boot 应用程序。

@Bean
public WebMvcConfigurer corsConfigurer() {
   return new WebMvcConfigurerAdapter() {
      @Override
      public void addCorsMappings(CorsRegistry registry) {
         registry.addMapping("/products").allowedOrigins("http://localhost: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("http://localhost:8080");
         }
      };
   }
}

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

Spring Boot - Internationalization

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

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

Dependencies

我们需要 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());
}

Messages Sources

Spring Boot 应用程序默认情况下从 classpath 下的 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

Note − 消息源文件应该保存为 “UTF-8” 文件格式。

HTML file

在 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 应放置在类路径模板目录下,如下所示 −

<!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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,使用以下命令 −

gradle clean build

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

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

java –jar <JARFILE>

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

started application on tomcat port 8080

现在在你的 Web 浏览器中点击 URL http://localhost:8080/locale ,你将看到以下输出 −

output web browser

URL http://localhost:8080/locale?language=fr 将为你提供以下输出 −

output web browser salut bienvenue

Spring Boot - Scheduling

调度是一个针对特定时间段执行任务的过程。Spring 引导为在 Spring 应用程序上编写调度器提供了良好的支持。

Java Cron Expression

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

@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

Fixed Rate

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

@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

Fixed Delay

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

@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 - Enabling HTTPS

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

started application on tomcat port 8080

你需要执行以下步骤配置 Spring Boot 应用程序中的 HTTPS 和端口 443 −

  1. 获取 SSL 证书——创建自签名证书或从证书颁发机构获取

  2. 启用 HTTPS 和 443 端口

Self-Signed Certificate

要创建自签名证书,Java 运行时环境自带证书管理实用程序 key tool。该实用程序用于创建自签名证书。在给定的代码中展示了这一点 −

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。

Configure HTTPS

我们需要在 application.properties 文件中提供服务器端口 443、密钥库文件路径、密钥库密码、密钥库类型和密钥别名。观察给定的代码 −

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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,你可以使用以下命令

gradle clean build

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

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

java –jar <JARFILE>

现在,该应用程序已经使用 https(如下图所示)在 Tomcat 端口 443 上启动 −

started application on tomcat port 443

Spring Boot - Eureka Server

Eureka 服务器是一个保存所有客户端服务应用程序的信息的应用程序。每个微服务将在 Eureka 服务器中进行注册,Eureka 服务器知道运行在每个端口和 IP 地址上的所有客户端应用程序。Eureka 服务器还可以被称为发现服务器。

在本章中,我们将详细了解如何构建 Eureka 服务器。

Building a Eureka Server

Eureka 服务器随 Spring Cloud 软件包提供。为此,我们需要开发 Eureka 服务器并在默认端口 8761 上运行它。

访问 Spring Initializer 主页 https://start.spring.io/ ,并使用 Eureka 服务器依赖项下载 Spring Boot 项目。它在下面屏幕截图中展示 −

build eureka server

在 main Spring Boot 应用程序类文件中下载项目后,我们需要添加 @EnableEurekaServer 注释。@EnableEurekaServer 注释用于让您的 Spring Boot 应用程序充当 Eureka 服务器。

main 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 服务器依赖项。

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 服务器会将它自身注册到发现中。您应该将下面提供的配置添加到您的 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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,您可以使用下面显示的命令 −

gradle clean build

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

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

 java –jar <JARFILE>

您可以发现应用程序已在 Tomcat 端口 8761 上启动,如下所示 −

application started on tomcat port 8761

现在,在您的网络浏览器中点击 URL http://localhost:8761/ ,您会发现 Eureka Server 在端口 8761 上运行,如下所示 −

eureka server running on port 8761

Service Registration with Eureka

在本教程中,你将详细了解如何将 Spring Boot 微服务应用程序注册到 Eureka Server 中。在注册该应用程序之前,请确保 Eureka Server 正在端口 8761 上运行,或者先构建 Eureka Server 然后运行它。有关构建 Eureka Server 的更多信息,你可以参考前一章。

首先,你需要在我们的构建配置文件中添加以下依赖项来将微服务注册到 Eureka Server 中。

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 micro service应用程序注册到 Eureka Server 中,我们需要在其 application.properties 文件或 application.yml 文件中添加以下配置并在其配置中指定 Eureka Server URL。

application.yml 文件的代码如下所示 −

eureka:
   client:
      serviceUrl:
         defaultZone: http://localhost:8761/eureka
      instance:
      preferIpAddress: true
spring:
   application:
      name: eurekaclient

application.properties 文件的代码如下所示 −

eureka.client.serviceUrl.defaultZone  = http://localhost:8761/eureka
eureka.client.instance.preferIpAddress = true
spring.application.name = eurekaclient

现在,添加 Rest Endpoint 在 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";
   }
}

整个配置文件如下所示。

For Maven user - 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>

For Gradle user – 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”之后,您可以在目标目录中找到 JAR 文件。

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

gradle clean build

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

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

java –jar <JARFILE>

现在,该应用程序已经使用 https(如下图所示)在 Tomcat 端口 8080 上启动,并且 Eureka Client 应用程序已经注册到 Eureka Server 中 −

started application on tomcat port

访问 URL [role="bare"] [role="bare"]http://localhost:8761/ 中的 Web 浏览器,你就可以看到 Eureka Client 应用程序已注册到 Eureka Server 中。

eureka client application

现在在你的网页浏览器中点击 URL http://localhost:8080/ 并查看 rest 端点的输出。

eureka client application output

Spring Boot - Zuul Proxy Server and Routing

Zuul 服务器是一个网关应用程序,处理所有请求并对微服务应用程序进行动态路由。Zuul 服务器也被称为边缘服务器。

例如, /api/user 映射到用户服务,/api/products 映射到产品服务,Zuul 服务器将动态地将请求路由到各自的后端应用程序。

在本章中,我们将详细地了解如何在 Spring Boot 中创建 Zuul 服务器应用程序。

Creating Zuul Server Application

Zuul 服务器与 Spring Cloud 依赖项捆绑在一起。你可以从 Spring Initializer 页面 https://start.spring.io/ 下载 Spring Boot 项目,并选择 Zuul 服务器依赖项。

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 = http://localhost: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: http://localhost:8080/

Note - 在通过 Zuul 代理路由之前, http://localhost: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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,你可以使用下面给出的命令:

gradle clean build

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

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

java –jar <JARFILE>

你可以在此处看到应用程序已经启动,端口为 Tomcat 端口 8111。

started application on tomcat port 8111

现在,在你的网页浏览器中点击 URL http://localhost:8111/api/demo/products ,你可以看到 /products REST 端点的输出,如下所示:

products rest endpoint

Spring Boot - Cloud Configuration Server

Spring Cloud 配置服务器是一个管理所有应用程序相关配置属性的集中式应用程序。在本章,您将详细了解如何创建 Spring Cloud 配置服务器。

Creating Spring Cloud Configuration Server

首先,从 Spring Initializer 页面下载 Spring Boot 项目,并选择 Spring Cloud Config Server 依赖。观察以下给出的屏幕截图 −

creating spring cloud configuration server

现在,在构建配置文件中添加 Spring Cloud 配置服务器依赖,具体解释如下 −

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/ 中放置您的客户端应用程序应用程序。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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,使用以下给出的命令 −

gradle clean build

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

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

 java –jar <JARFILE>

现在,该应用程序已在 Tomcat 8888 端口上启动,如下所示 −

tomcat port 8888 output

现在,在您的 Web 浏览器中点击 URL http://localhost:8888/config-client/default/master ,您将可以看到您的 config-client 应用程序配置属性,如下所示。

config client application

Spring Boot - Cloud Configuration Client

一些应用程序可能需要需要更改的配置属性,开发人员可能需要将它们关闭或重启应用程序来执行此操作。然而,这可能会导致生产中的停机时间和重启应用程序的需要。Spring Cloud Configuration Server 允许开发人员在不重启应用程序和不产生任何停机时间的情况下加载新的配置属性。

Working with Spring Cloud Configuration Server

首先,从 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,并提供您的应用程序名称。

Note − [role="bare"] [role="bare"]http://localhost:8888 配置服务器应在启动配置客户端应用程序之前运行。

spring.application.name = config-client
spring.cloud.config.uri = http://localhost: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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,您可以使用下面显示的命令 −

gradle clean build

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

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

java –jar <JARFILE>

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

started application on tomcat port 8080

您可以在控制台窗口中看到日志;配置客户端应用程序正在从 https://localhost:8888 中获取配置

2017-12-08 12:41:57.682  INFO 1104 --- [
   main] c.c.c.ConfigServicePropertySourceLocator :
   Fetching config from server at: http://localhost:8888

现在点击 URL, http://localhost:8080/ 欢迎消息从配置服务器加载。

spring cloud config server

现在,进入配置服务器更改属性值,然后点击执行器端点 POST URL http://localhost:8080/refresh ,并在 URL http://localhost:8080/ 中查看新配置属性值

Spring Boot - Actuator

Spring Boot Actuator 为监视和管理您的 Spring Boot 应用程序提供了安全端点。默认情况下,所有 actuator 端点都是安全的。本章将详细介绍如何为您的应用程序启用 Spring Boot actuator。

Enabling Spring Boot Actuator

要为 Spring Boot 应用程序启用 Spring Boot actuator 端点,我们需要在我们的构建配置文件中添加 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 引导执行器端点,请在 application.properties 文件中添加管理端口号。

management.port = 9000

YAML 文件用户可以在 application.yml 文件中添加以下属性。

management:
   port: 9000

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

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

mvn clean install

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

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

gradle clean build

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

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

java –jar <JARFILE>

现在,应用程序已在 Tomcat 端口 8080 上启动。请注意,如果您指定了管理端口号,则同一个应用程序将运行在两个不同的端口号上。

started application on tomcat port

下面给出了几个重要的 Spring 引导执行器端点。您可以在 Web 浏览器中输入它们并监控您的应用程序行为。

ENDPOINTS

USAGE

/metrics

查看应用程序指标,例如已用内存、可用内存、线程、类、系统正常运行时间等。

/env

查看应用程序中使用的环境变量列表。

/beans

查看 Spring Bean 及其类型、作用域和依赖关系。

/health

查看应用程序运行状况

/info

查看有关 Spring 引导应用程序的信息。

/trace

查看 Rest 端点的跟踪列表。

Spring Boot - Admin Server

使用 Spring Boot Actuator 端点监控您的应用程序有点困难。这是因为,如果您有“n”个应用程序,则每个应用程序都有单独的执行器端点,从而使监控变得困难。Spring Boot Admin Server 是一款用于管理和监控您的微服务应用程序的应用程序。

为了处理这种情况,CodeCentric Team 提供了一个 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 和应用程序名称,如下所示 −

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

对于 YAML 用户,使用下列属性来在 application.yml 文件中定义端口号和应用程序名。

server:
   port: 9090
spring:
   application:
      name: adminserver

构建配置文件如下。

For Maven users – 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>

For Gradle users – build.gradle file

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

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

对于 Gradle,使用此处所示命令 −

gradle clean build

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

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

java –jar <JARFILE>

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

tomcat port 9090 output

现在从 Web 浏览器访问以下 URL,查看 Admin Server UI。

web browser admin server ui

Spring Boot - Admin Client

要通过 Spring Boot Admin Server 监控和管理微服务应用程序,您应该添加 Spring Boot Admin Starter 客户端依赖项并在应用程序属性文件中指出 Admin Server URI。

Note - 为了监控应用程序,您应该为您的微服务应用程序启用 Spring Boot Actuator 端点。

首先,在您的构建配置中添加以下 Spring Boot Admin starter 客户端依赖项和 Spring Boot starter actuator 依赖项。

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 文件中添加以下属性。

spring.boot.admin.url = http://localhost:9090/

对于 YAML 用户,在 application.yml 文件中添加以下属性。

spring:
   boot:
      admin:
         url: http://localhost:9000/

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

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

mvn clean install

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

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

gradle clean build

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

现在,运行 JAR 文件,使用所示命令 −

java –jar <JARFILE>

现在,应用程序已经启动在 Tomcat 端口 9090 中,具体如下所示:

tomcat port 9090 output

现在,从网络浏览器访问以下网址,查看您的 Spring Boot 应用程序已经注册于 Spring Boot Admin Server。

spring boot admin server

现在,点击 Details 按钮,然后在 Admin Server UI 中查看执行器端点。

actuator endpoints in admin server ui

Spring Boot - Enabling Swagger2

Swagger2 是一个用于为 RESTful Web 服务生成 REST API 文档的开源项目。它提供了一个用户界面,能够通过网络浏览器访问我们的 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。我们需要定义基本包以配置 REST API 以供 Swagger2 使用。

@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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,您可以使用此处所示的命令:

gradle clean build

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

现在,通过使用此处所示命令运行 JAR 文件:

java –jar <JARFILE>

现在,应用程序将启动在 Tomcat 端口 8080 中,具体如下所示:

started application on tomcat port 8080

现在,在您的网络浏览器中访问该 URL,然后查看 Swagger API 功能。

swagger api functionalities

Spring Boot - Creating Docker Image

Docker 是一种容器管理服务,可简化构建和部署。如果您是 Docker 新手,可以从以下链接详细了解它: [role="bare" [role="bare"]https://www.tutorialspoint.com/docker/index.htm ]

在本章中,我们将了解如何使用 Spring Boot 应用程序的 Maven 和 Gradle 依赖关系创建 Docker 镜像。

Create 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

Note - 在 tcp://localhost:2375 上启用公开守护进程,不使用 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 - Tracing Micro Service Logs

如果出现任何问题,大多数开发人员都面临着跟踪日志的困难。这个问题可以通过弹簧云 Sleuth 和 ZipKin 服务器解决,以用于弹簧启动应用程序。

Spring Cloud Sleuth

弹簧云 Sleuth 日志以以下格式打印 −

[application-name,traceid,spanid,zipkin-export]

其中,

  1. 应用程序名称 = 应用程序的名称

  2. Traceid = 调用同一服务或一个服务调用另一个服务时,每个请求和响应 traceid 是相同的。

  3. Spanid = Span Id 与 Trace Id 一起打印。Span Id 是对一个服务调用另一个服务的每个请求和响应。

  4. Zipkin 导出 = 默认情况下它是错误的。如果为真,日志将导出到 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 控制器类文件中 −

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”之后,您可以在目标目录中找到 JAR 文件。

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

gradle clean build

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

现在,通过使用此处所示命令运行 JAR 文件:

java –jar <JARFILE>

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

started application on tomcat port 8080

现在,在 Web 浏览器中按 URL 并查看控制台日志中的输出。

output welcome sleuth

您可以在控制台窗口中看到以下日志。注意,日志采用以下格式打印 [应用程序名称、traceid、spanid、zipkin-export]

log is printed

Zipkin Server

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

现在,在应用程序属性文件中配置 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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,使用以下给出的命令 −

gradle clean build

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

使用显示的命令运行 JAR 文件 −

java –jar <JARFILE>

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

output tomcat port 9411

现在,点击下面的 URL 并查看 Zipkin 服务器 UI。

zipkin server ui

然后,在客户端服务应用程序中添加以下依赖,并指出 Zipkin 服务器 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 Export 选项会自动从 false 变为 true。

接下来,在客户端服务 application.properties 文件中配置你的 Zipkin 服务器基本 URL。

spring.zipkin.baseUrl = http://localhost:9411/zipkin/

然后,提供跟踪 ID 并找出 Zipkin UI 中的跟踪。

Spring Boot - Flyway Database

Flyway 是一款版本控制应用程序,可以轻松可靠地在所有实例上改造您的数据库架构。要了解有关 Flyway 的更多信息,您可以使用以下链接: www.flywaydb.org

许多软件项目使用关系数据库。这需要对数据库迁移(也称为架构迁移)进行处理。

在本章中,您将详细了解如何在 Spring Boot 应用程序中配置 Flyway 数据库。

Configuring Flyway Database

首先,从 Spring Initializer 页面 www.start.spring.io 下载 Spring Boot 项目并选择以下依赖项:

  1. Spring Boot Starter Web

  2. Flyway

  3. MySQL

  4. 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')

在应用程序属性中,我们需要配置数据库属性以创建 DataSource,还需要配置我们在应用程序属性中要配置的 flyway 属性。

对于属性文件用户,请在 application.properties 文件中添加以下属性。

spring.application.name = flywayapp

spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost: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://localhost: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://localhost: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://localhost: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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,可以使用此处显示的命令:

gradle clean build

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

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

 java –jar <JARFILE>

现在,Tomcat 在端口 8080 上启动,并且可以在控制台窗口中看到 flyway 数据库日志,如下所示。

flyway database logs

你现在可以转到数据库并执行选择查询。

database and select the queries

Spring Boot - Sending Email

通过使用 Spring Boot RESTful Web 服务,您可以通过 Gmail 传输层安全性发送电子邮件。在本章中,让我们详细了解如何使用此特性。

首先,我们需要在 build 配置文件中添加 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 API,如下所示在 Rest 控制器类文件中发送电子邮件。

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("tutorialspoint@gmail.com", "<your password>");
      }
   });
   Message msg = new MimeMessage(session);
   msg.setFrom(new InternetAddress("tutorialspoint@gmail.com", false));

   msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("tutorialspoint@gmail.com"));
   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";
}

Note - 在发送电子邮件之前,请打开 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”之后,您可以在目标目录中找到 JAR 文件。

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

gradle clean build

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

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

java –jar <JARFILE>

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

tomcat port 8080 application output

现在,从您的 Web 浏览器访问以下 URL,您将收到一封电子邮件。

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

现在,在您的主 Spring Boot 应用程序类文件中添加 @EnableHystrix 注解。@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 添加 @HystrixCommand 和 @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 file

<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
   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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,使用命令,如所示 −

gradle clean build

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

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

java –jar <JARFILE>

这将启动 8080 端口上的应用程序,如下所示 −

tomcat application command prompt

现在,从 Web 浏览器点击网址 http://localhost:8080/ ,然后查看 Hystrix 响应。API 响应时间为 3 秒,但 Hystrix 超时时间为 1 秒。

request fail hystrix timeout

Spring Boot - Web Socket

在本章中,让我们了解如何通过使用 Spring Boot 和 Web 套接字构建交互式 Web 应用程序。

若要在 Spring Boot 中使用 Web 套接字构建交互式 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 注解来配置 Websocket 消息代理来创建 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 - Batch Service

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

对于 Maven,你可以使用下面给出的命令 −

mvn clean install

“BUILD SUCCESS”之后,您可以在目标目录中找到 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 http://localhost:8080/ 并连接 Websocket,发送问候语并接收消息。

web socket send 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")

现在,在类路径资源下添加简单的 CSV 数据文件 – src/main/resources,并将文件命名为 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”之后,您可以在目标目录中找到 JAR 文件。

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

gradle clean build

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

使用此处提供的命令运行 JAR 文件 −

java –jar <JARFILE>

您可以看到控制台窗口中的输出,如下所示 −

batch service output 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'

Producing Messages

要向 Apache Kafka 中发送消息,我们需要为生产者配置定义 Configuration 类,如所示 −

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

Consuming a Message

要使用消息,我们需要编写 Consumer 配置类文件,如所示 −

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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,使用命令,如所示 −

gradle clean build

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

使用此处提供的命令运行 JAR 文件 −

java –jar <JARFILE>

您可以看到控制台窗口中的输出。

Spring Boot - Twilio

Twilio 是一个第三方应用程序,用于发送短信并通过我们的应用程序拨打语音电话。它允许我们以编程方式发送短信并拨打语音电话。

在本章中,你将学习如何使用带 Twilio 的 Spring Boot 实现发送 SMS 及拨打语音电话。

Note − 我们使用 Twilio 中的 Trail 帐户来发送短信并拨打语音电话。你可以在 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"

现在,在静态块中初始化 Twilio 帐户,其中包含 ACCOUNT_SID 和 AUTH_ID,如下所示:

static {
   Twilio.init(ACCOUNT_SID, AUTH_ID);
}

Sending SMS

要发送短信,我们需要向 Message.create() 方法提供 from-number 和 to-number。消息正文内容,我们还需要为方法 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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,使用命令,如所示 −

gradle clean build

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

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

java –jar <JARFILE>

现在,你将收到发送到你的 “to-number” 的短信。

消息已收到 “to-number”。

Sent from your Twilio trail account
- Message from Spring Boot Application

Note − 在此示例中,我们使用了 Trail 帐户。因此,你应当在发送短信前验证号码。

Voice Calls

要使用 Twilio 拨打语音电话,我们需要调用 Call.creator() 方法。对于此方法,我们需要提供 to-number、from-number 和语音注释,如下所示:

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”之后,您可以在目标目录中找到 JAR 文件。

对于 Gradle,使用命令,如所示 −

gradle clean build

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

现在,使用此处提供的命令运行 JAR 文件:

java –jar <JARFILE>

现在,你将从 Twilio 收到呼叫到你的 “to-number”。

在接听电话后按任意键,你将听到来自 https://demo.twilio.com/docs/voice.xml 的语音注释。

Note − 在此示例中,我们使用了 Trail 帐户。因此,你应当在拨打电话前验证号码。

Spring Boot - Unit Test Cases

单元测试是由开发人员进行的测试,用于确保各个单元或组件功能正常工作。

在本教程中,我们将学习如何通过 Mockito 和 Web 控制器编写单元测试用例。

Mockito

要将 Mockito Mocks 注入到 Spring Beans,我们需要在我们的构建配置文件中添加 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);
   }
}

然后,为测试配置应用程序上下文。 src/test/resources 注释用于在测试用例运行时配置类。

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

现在,您可以在 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 Unit Test

Spring Boot 提供了一种便捷的方式来针对 Rest Controller 文件编写单元测试。借助于 SpringJUnit4ClassRunner 和 MockMvc,我们可以创建一个 Web 应用程序上下文来针对 Rest Controller 文件编写单元测试。

单元测试应该编写在 src/test/java 目录下,用于编写测试的类路径资源应该放在 src/test/resources 目录下。

要编写一个单元测试,我们需要在构建配置文件中添加 Spring Boot Starter 测试依赖,如下所示。

<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 服务的更多信息,请参阅本教程中给出的相同章节。

Writing a Unit Test for REST Controller

在本节中,让我们看看如何编写 REST 控制器的单元测试。

首先,我们需要创建一个用于通过 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");
}

下面给出了完整的控制器测试类文件 −

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 结果,如下所示。

rest results in console window

Spring Boot - Database Handling

Spring Boot 提供了非常好的支持来创建用于数据库的数据源。我们不需要编写任何额外的代码在 Spring Boot 中创建一个数据源。只需添加依赖并进行配置详细信息就足以创建一个数据源并连接数据库。

在本章中,我们将使用 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')

Connect to H2 database

要连接 H2 数据库,我们需要在构建配置文件中添加 H2 数据库依赖项。

对于 Maven 用户,在 pom.xml 文件中添加以下依赖:

<dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
</dependency>

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

compile('com.h2database:h2')

我们需要在 classpath 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');

Connect 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://localhost: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://localhost: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

Connect 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

为了使用 JdbcTemplate 在 Spring Boot 应用程序中访问关系数据库,我们需要在构建配置文件中添加 Spring Boot Starter JDBC 依赖。

然后,如果你 @Autowired 了 JdbcTemplate 类,Spring Boot 会自动连接数据库,并为 JdbcTemplate 对象设置数据源。

@Autowired
JdbcTemplate jdbcTemplate;
Collection<Map<String, Object>> rows = jdbc.queryForList("SELECT QUERY");

应该向 class 文件添加 @Repository 注解。@Repository 注解用于为 Spring Boot 应用程序创建数据库存储库。

@Repository
public class ProductServiceDAO {
}

Multiple DataSource

我们可以在单个 Spring Boot 应用程序中保留“n”个数据源。这里给出的示例显示了如何在 Spring Boot 应用程序中创建多个数据源。现在,在应用程序属性文件中添加两个数据源配置详细信息。

对于属性文件用户,添加以下属性到您的 application.properties 文件中。

spring.dbProductService.driverClassName = com.mysql.jdbc.Driver
spring.dbProductService.url = jdbc:mysql://localhost: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://localhost: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://localhost: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://localhost: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

现在,创建一个 Configuration 类来创建针对多个数据源的 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 - Securing Web Applications

如果在类路径上添加了 Spring Boot Security 依赖项,Spring Boot 应用程序会自动为所有 HTTP 端点要求基本身份验证。端点 “/” 和 “/home” 不需要任何身份验证。所有其他端点都需要身份验证。

要在您的 Spring Boot 应用程序中添加 Spring Boot Security,我们需要在我们的构建配置文件中添加 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")

Securing a Web application

首先,使用 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>

HTML 文件中定义的简单视图 /hello 使用了 Thymeleaf 模板。

现在,在 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 启动器安全依赖项添加到您的构建配置文件。

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

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

Gradle 用户可以使用如下所示的命令:

gradle clean build

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

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

java –jar <JARFILE>

在您的 Web 浏览器中输入 URL http://localhost:8080/ 。您可以看到如图所示的输出。

output on web browser click link
output login page
output signout page
output logged out
invalid username password

Spring Boot - OAuth2 with JWT

在本章中,您将详细了解 Spring 引导安全机制和带有 JWT 的 OAuth2。

Authorization Server

授权服务器是 Web API 安全的一个最高架构组件。授权服务器充当集中授权点,允许您的应用程序和 HTTP 端点识别您的应用程序的功能。

Resource Server

资源服务器是向客户端提供访问令牌用来访问资源服务器 HTTP 端点的一个应用程序。它是包含 HTTP 端点、静态资源和动态网页的库集合。

OAuth2

OAuth2 是授权框架,它让应用程序 Web Security 能够从客户端访问资源。为构建 OAuth2 应用程序,我们需要关注授权类型(授权代码)、客户端 ID 和客户端机密。

JWT Token

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

其中,

  1. Spring Boot Starter Security − 实施 Spring Security

  2. Spring Security OAuth2 − 实施 OAUTH2 结构以启用授权服务器和资源服务器。

  3. Spring Security JWT − 为 Web 安全生成 JWT 令牌

  4. Spring Boot Starter JDBC − 访问数据库以确保用户是否可用。

  5. Spring Boot Starter Web − 编写 HTTP 端点。

  6. H2 Database − 存储用于身份验证和授权的用户信息。

完整的构建配置文件如下所示。

<?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 注解,以在同一应用程序中充当身份验证服务器和资源服务器。

此外,你可以使用以下代码编写一个简单的 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 类,该类拓展了用于 Spring Boot 认证的 org.springframework.security.core.userdetails.User 类。

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 类以从数据库中读取用户信息并将其发送到 Custom 用户服务,并添加已授予的权限 “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;
   }
}

你可以创建一个 Custom User 详细信息服务类,该类拓展了 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 Security,定义密码编码器 (BCryptPasswordEncoder),并定义 AuthenticationManager bean。Security 配置类应该拓展 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 Configuration 类以添加 Client ID、Client Secret,定义用于 Token 签名密钥和验证密钥的 JwtAccessTokenConverter、私钥和公钥,并使用作用域配置 Token 有效性的 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

对于 Spring Boot 1.5 发行版之后的版本,在你的 application.properties 文件中添加以下属性以定义 OAuth2 Resource 过滤器顺序。

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, 'tutorialspoint@gmail.com','$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG');

INSERT INTO USERS (ID, USERNAME,PASSWORD) VALUES (
   2, 'myemail@gmail.com','$2a$08$fL7u5xcvsZl78su29x1ti.dxI.9rYO8t0q5wk2ROJ.1cdR53bmaVG');

Note − 密码应该按照 Bcrypt Encoder 格式存储在数据库表中。

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

对于 Maven,你可以使用下面给出的命令 −

mvn clean install

“BUILD SUCCESS”之后,您可以在目标目录中找到 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 令牌。

现在,添加请求头如下 −

  1. Authorization − 使用你的客户端 ID 和客户端机密进行基本认证。

  2. Content Type − application/x-www-form-urlencoded

add request headers

现在,按以下方式添加请求参数 −

  1. grant_type = password

  2. username = your username

  3. password = your 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 应用程序。在本章中,我们将了解如何将 Spring Boot 应用程序部署到 GCP app engine 平台中。

首先,从 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 端点,使其返回字符串成功,如下所示 −

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 Appengine 中。

Note − GCP 应启用计费并且在将您的应用程序部署到 appengine 之前,您应在 GCP 中创建 appengine 平台。

将您的应用程序部署到 GCP appengine 平台需要几分钟时间。

构建成功后,您可以在控制台窗口中看到服务 URL。

spring initializer page

现在,点击服务 URL 并查看输出。

app engine development success

Google Cloud SQL

要将 Google Cloud SQL 连接到您的 Spring Boot 应用程序,您应将以下属性添加到您的 application.properties 文件中。

JDBC URL Format

jdbc:mysql://google/<DATABASE-NAME>?cloudSqlInstance = <GOOGLE_CLOUD_SQL_INSTANCE_NAME> &socketFactory = com.google.cloud.sql.mysql.SocketFactory&user = <USERNAME>&password = <PASSWORD>

Note − Spring Boot 应用程序和 Google Cloud SQL 应位于同一 GCP 项目中。

应用程序属性文件如下。

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

在本章中,我们将了解如何使用 Spring Boot 应用程序及 Gradle 构建添加 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')
}

现在,在主 Spring Boot 应用程序类文件中的 Spring Boot 进行身份验证后,添加 HTTP 端点来读取用户的 Google 主体,如下所示 −

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>

Note − 在 Google Cloud 控制台中 - 启用 Gmail 服务、Analytics 服务和 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://accounts.google.com/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 http://localhost:8080/ 并点击 Google 登录链接。

google login link

它将重定向到 Google 登录屏幕并提供 Gmail 登录详细信息。

google login screen

如果登录成功,我们将收到 Gmail 用户的主体对象。

principal object of the gmail user