目录

Spring Boot - 快速指南

Spring Boot - Introduction

Spring Boot是一个基于Java的开源框架,用于创建微服务。 它由Pivotal Team开发,用于构建独立的生产就绪弹簧应用。 本章将向您介绍Spring Boot,并使您熟悉其基本概念。

什么是微服务?

Micro Service是一种允许开发人员独立开发和部署服务的体系结构。 每个运行的服务都有自己的流程,这实现了轻量级模型以支持业务应用程序。

优势 (Advantages)

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

  • Easy deployment
  • 简单的可扩展性
  • Compatible with Containers
  • 最低配置
  • Lesser production time

什么是Spring Boot?

Spring Boot为Java开发人员提供了一个很好的平台,可以开发一个可以just run的独立和生产级Spring应用程序。 您可以开始使用最少的配置,而无需进行整个Spring配置设置。

优势 (Advantages)

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

  • 易于理解和开发弹簧应用
  • Increases productivity
  • 缩短开发时间

Goals

Spring Boot的设计目标如下 -

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

为什么选择Spring Boot?

您可以选择Spring Boot,因为它提供的功能和优点如下所示 -

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

  • 它提供强大的批处理和管理REST端点。

  • 在Spring Boot中,一切都是自动配置的; 无需手动配置。

  • 它提供基于注释的spring应用程序

  • 简化依赖管理

  • 它包括嵌入式Servlet容器

它是如何工作的?

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

spring boot应用程序的入口点是包含@SpringBootApplication注释和main方法的类。

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

Spring Boot Starters

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

例如,如果要使用Spring和JPA进行数据库访问,则在项目中包含spring-boot-starter-data-jpa依赖项就足够了。

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

例子 (Examples)

请看下面的Spring Boot启动器,以便更好地理解 -

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>

自动配置

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

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

请注意以下代码以便更好地理解 -

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

Spring Boot应用程序

Spring Boot Application的入口点是包含@SpringBootApplication注释的类。 该类应具有运行Spring Boot应用程序的主要方法。 @SpringBootApplication注释包括自动配置,组件扫描和Spring Boot配置。

如果将@SpringBootApplication批注添加到类中,则无需添加@EnableAutoConfiguration, @ComponentScan @SpringBootConfiguration@SpringBootConfiguration批注。 @SpringBootApplication注释包括所有其他注释。

请注意以下代码以便更好地理解 -

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

组件扫描

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

请注意以下代码以便更好地理解 -

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

Spring Boot - Quick Start

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

先决条件 (Prerequisites)

您的系统需要具有以下创建Spring Boot应用程序的最低要求 -

  • Java 7
  • Maven 3.2
  • Gradle 2.5

Spring Boot CLI

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

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

您还可以从Spring Software存储库下载Spring CLI发行版: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#getting-started-manual-cli-installation : https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#getting-started-manual-cli-installation

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

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

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

下载后,解压缩归档文件并按照install.txt文件中给出的步骤进行操作。 并不是说它不需要任何环境设置。

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

Spring CLI版本

用Groovy运行Hello World

创建一个包含Rest Endpoint脚本的简单groovy文件,并使用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运行应用程序,如下面的截图所示 -

用Groovy运行Hello World

一旦你运行groovy文件,所需的依赖项将自动下载,它将在Tomcat 8080端口启动应用程序,如下面给出的屏幕截图所示 -

运行Groovy文件Tomcat端口

Tomcat启动后,转到Web浏览器并点击URL http://localhost:8080/ ,您可以看到输出,如图所示。

Hello Spring Boot

Spring Boot - Bootstrapping

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

Spring Initializer

Bootstrapping Spring Boot应用程序的一种方法是使用Spring Initializer。 为此,您必须访问Spring Initializer网页www.start.spring.io并选择Build,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.iowiki</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.iowiki'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

类路径依赖性

Spring Boot提供了许多Starters来在我们的类路径中添加jar。 例如,为了编写Rest Endpoint,我们需要在类路径中添加spring-boot-starter-web依赖项。 请遵守下面显示的代码以便更好地理解 -

Maven依赖

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

Gradle依赖

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

主要方法

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

在此示例中,主类文件位于src/java/main目录中,其默认包为com.iowiki.demo 。 请观察此处显示的代码以便更好地理解 -

package com.iowiki.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);
   }
}

写一个休息端点

要在Spring Boot Application主类文件本身中编写一个简单的Hello World Rest Endpoint,请按照以下步骤操作 -

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

  • 现在,使用@RequestMapping注释编写Request URI方法。

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

现在,您的主要Spring Boot Application类文件将如下面的代码所示 -

package com.iowiki.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @RequestMapping(value = "/")
   public String hello() {
      return "Hello World";
   }
}

创建一个可执行的JAR

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

使用maven命令mvn clean install,如下所示 -

命令MVN Clean Install

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

建立成功消息

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

Gradle Clean Build

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

在命令提示符中构建成功的消息

用Java运行Hello World

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

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

Maven JAR文件目标目录

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

构建Libs目录下的JAR文件

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

JAR文件命名为演示SNAPSHOT

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

控制台窗口中的输出

现在,看一下控制台,Tomcat在端口8080(http)上启动。 现在,转到Web浏览器并点击URL http://localhost:8080/ ,您可以看到如下所示的输出 -

Tomcat在Port 8080(http)上启动。

Spring Boot - Tomcat Deployment

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

Spring Boot Servlet初始化程序

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

下面给出了用于JAR文件部署的Spring Boot Application类文件的代码 -

package com.iowiki.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 Application类文件的代码如下 -

package com.iowiki.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
@SpringBootApplication
public class DemoApplication  extends SpringBootServletInitializer {
   @Override
   protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(DemoApplication.class);
   }
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

设置主类

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

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

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

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

mainClassName="com.iowiki.demo.DemoApplication"

将打包JAR更新为WAR

我们必须使用以下代码将包装JAR更新为WAR -

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

<packaging>war</packaging>

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

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

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

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

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

对于Gradle,使用如下所示的代码在build.gradle添加Spring Boot starter依赖build.gradle -

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

现在,使用如下所示的代码在Spring Boot Application类文件中编写一个简单的Rest端点 -

package com.iowiki.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class DemoApplication  extends SpringBootServletInitializer {
   @Override
   protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(DemoApplication.class);
   }
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @RequestMapping(value = "/")
   public String hello() {
      return "Hello World from Tomcat";
   }
}

打包您的应用程序

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

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

Maven MVN套餐

Maven包装应用目标目录

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

Gradle Clean Build命令

Maven包装应用目标目录

部署到Tomcat

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

Tomcat Web应用程序Maneger

webApps目录

成功部署后,点击网页浏览器中的URL http://localhost:8080/demo-0.0.1-SNAPSHOT/ ,观察输出结果如下图所示 -

成功部署截图

用于此目的的完整代码如下。

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.iowiki</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.iowiki.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.iowiki'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
mainClassName = "com.iowiki.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.iowiki.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.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不支持其他构建系统。

依赖管理

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

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

Maven依赖

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

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

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

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

Gradle Dependency

我们可以将Spring Boot Starters依赖项直接导入build.gradle文件。 我们不需要Spring Boot启动父依赖,例如Maven for Gradle。 观察下面给出的代码 -

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 。 请注意,通常不建议使用默认包声明。 使用默认包时,Spring Boot将导致自动配置或组件扫描出现故障等问题。

Note - Java推荐的包声明命名约定是反向域名。 例如 - com.iowiki.myproject

典型布局

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

Spring Boot应用程序的典型布局

Application.java文件应该声明main方法和@SpringBootApplication。 请遵守下面给出的代码以便更好地理解 -

package com.iowiki.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 Boot中,我们可以使用Spring Framework来定义bean及其依赖注入。 @ComponentScan注释用于查找bean以及使用@Autowired注释注入的相应内容。

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

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

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

以下代码显示主Spring Boot Application类文件中自动连接的Rest Template对象和Bean创建对象的代码 -

package com.iowiki.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是一个用于在Spring Boot应用程序启动后执行代码的接口。 下面给出的示例显示了如何在主类文件上实现Application Runner接口。

package com.iowiki.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观察Hello World from Application Runner下面的控制台窗口,则在Tomcat启动后执行println语句。 以下屏幕截图是否相关?

应用程序运行器的Hello World

Command Line Runner

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

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

查看“命令行运行器中的Hello world”下面的控制台窗口,在Tomcat启动后执行println语句。

命令行运行器

Spring Boot - Application Properties

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

Command Line Properties

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

Step 1 - 创建可执行JAR文件后,使用命令java –jar 《JARFILE》运行它。

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

命令行属性JARFILE

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

属性文件

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

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

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

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

YAML文件

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

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

外化属性

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

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

外化属性

使用@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将抛出非法参数异常,因为Could not resolve placeholder 'spring.application.name' in value "${spring.application.name}"

要解决占位符问题,我们可以使用下面给出的thr语法设置属性的默认值 -

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

Spring Boot活动配置文件

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

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

让我们了解如何在application.properties中使用Spring活动配置文件。 默认情况下,申请。 属性将用于运行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文件。 设置弹簧活动轮廓的命令如下所示 -

Prod.Properties Active Dev

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

2017-11-26 08:13:16.322  INFO 14028 --- [           
   main] com.iowiki.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)

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

生产活动档案

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

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

现在,Tomcat开始使用4431端口(http),如下所示 -

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

application.yml的Spring活动配置文件

让我们了解如何为application.yml保留Spring活动配置文件。 我们可以将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.iowiki.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)

设置生产活动配置文件的命令如下 -

生产活动档案

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

2017-11-26 08:43:10.743  INFO 13400 --- [    
   main] com.iowiki.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 Logging,Log4j2和Logback。 使用这些,我们可以配置控制台日志记录以及文件日志记录。

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

日志格式

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

Spring启动日志格式

它为您提供以下信息 -

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

  • Log level显示INFO,ERROR或WARN

  • Process ID

  • ---是一个分隔符

  • Thread name括在方括号[]中

  • Logger Name ,显示源类名称

  • 日志消息

控制台日志输出

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

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

java –jar demo.jar --debug

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

debug = true

文件日志输出

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

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

logging.path = /var/tmp/

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

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

Note - 文件将在达到10 MB后自动旋转。

日志级别

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

logging.level.root = WARN

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

配置Logback

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

您可以使用下面给出的代码在Logback.xml文件中配置ROOT级别日志 -

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

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

<?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文件中配置文件appender。 请注意,您需要在文件追加器中指定日志文件路径。

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

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

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

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

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

下面给出的代码显示了如何在Spring Boot主类文件中添加slf4j logger。

package com.iowiki.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);
   }
}

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

记录器控制台窗口

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

日志输出

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文件中添加以下依赖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.iowiki</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.iowiki'
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服务之前,建议您了解以下注释 -

休息控制器

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

@RestController
public class ProductServiceController { 
}

请求映射

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

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

请求机构

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

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

路径变量

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

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

请求参数

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

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

GET API

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

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

这里,请求URI是/products ,它将从HashMap存储库返回产品列表。 下面给出了包含GET方法REST端点的控制器类文件。

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

POST API

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

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

这里,请求URI是/products ,它会在将产品存储到HashMap存储库后返回String。

package com.iowiki.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.iowiki.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} ,它将产品后的String返回到HashMap存储库。 请注意,我们使用Path变量{id}来定义需要更新的产品ID。

package com.iowiki.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.iowiki.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删除请求用于删除现有资源。 此方法不包含任何请求正文。 我们可以发送请求参数和路径变量来定义自定义或动态URL。

下面给出的示例显示了如何定义HTTP DELETE请求方法。 在此示例中,我们使用HashMap删除现有产品,即POJO类。

请求URI是/products/{id} ,它将在从HashMap存储库中删除产品后返回String。 我们使用Path变量{id}来定义需要删除的产品ID。

package com.iowiki.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.iowiki.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.iowiki.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.iowiki.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.iowiki.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.iowiki.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> 

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

在Tomcat Port8080上开始应用程序

现在点击POSTMAN应用程序中显示的URL,查看输出。

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

POSTMAN应用程序获取API URL

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

POSTMAN Application Post API URL

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

POSTMAN应用程序放置API URL

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

POSTMAN应用程序删除API URL

Spring Boot - Exception Handling

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

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

控制器建议

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

异常处理程序

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

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

package com.iowiki.demo.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
@ControllerAdvice
   public class ProductExceptionController {
}

定义一个扩展RuntimeException类的类。

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

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

@ExceptionHandler(value = ProductNotfoundException.class)
public ResponseEntity<Object> exception(ProductNotfoundException exception) {
}

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

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

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

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

下面给出了用于全局处理异常的Controller Advice类。 我们可以在这个类文件中定义任何Exception Handler方法。

package com.iowiki.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);
   }
}

下面给出了Product Service API控制器文件以更新产品。 如果找不到Product,则抛出ProductNotFoundException类。

package com.iowiki.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.iowiki.demo.exception.ProductNotfoundException;
import com.iowiki.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.iowiki.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.iowiki.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的代码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.iowiki</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.iowiki'
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上启动应用程序,如下所示 -

异常处理Tomcat应用程序启动

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

更新URL:http:// localhost:8080/products/3

邮递员应用程序更新URL

Spring Boot - Interceptor

您可以在Spring Boot中使用Interceptor在以下情况下执行操作 -

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

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

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

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

以下是在拦截器上工作时应该了解的三种方法 -

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

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

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

请注意以下代码以便更好地理解 -

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

您必须使用WebMvcConfigurerAdapterInterceptorRegistry注册此Interceptor,如下所示 -

@Component
public class ProductServiceInterceptorAppConfig extends WebMvcConfigurerAdapter {
   @Autowired
   ProductServiceInterceptor productServiceInterceptor;
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(productServiceInterceptor);
   }
}

在下面给出的示例中,我们将使用GET产品API,该API提供的输出如下 -

Interceptor类ProductServiceInterceptor.java的代码如下 -

package com.iowiki.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注册到拦截器注册表 - ProductServiceInterceptorAppConfig.java如下 -

package com.iowiki.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);
   }
}

Controller类文件ProductServiceController.java的代码如下 -

package com.iowiki.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.iowiki.demo.exception.ProductNotfoundException;
import com.iowiki.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.iowiki.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.iowiki.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 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.iowiki</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.iowiki'
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上启动,如下所示 -

在Tomcat端口8080上启动应用程序

现在点击POSTMAN应用程序中的以下URL,你可以看到输出如下 -

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

POSTMAN应用程序获取API URL

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

拦截器输出控制台窗口

Spring Boot - Servlet Filter

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

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

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

@Component
public class SimpleFilter implements Filter {
   @Override
   public void destroy() {}
   @Override
   public void doFilter
      (ServletRequest request, ServletResponse response, FilterChain filterchain) 
      throws IOException, ServletException {}
   @Override
   public void init(FilterConfig filterconfig) throws ServletException {}
}

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

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

package com.iowiki.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.iowiki.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 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.iowiki</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.iowiki'
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上看到应用程序已启动。

现在点击URL http://localhost:8080/并查看输出Hello World。 它应该如下所示 -

Tomcat在端口8080 HTTP上启动

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

控制台日志上的远程主机远程地址

Spring Boot - Tomcat Port Number

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

自定义端口

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

server.port = 9090

application.yml文件中,您可以找到如下 -

server: 
   port: 9090

随机端口

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

server.port = 0

application.yml文件中,您可以找到如下 -

server: 
   port: 0

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

Spring Boot - Rest Template

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

package com.iowiki.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​​ -

  • 自动装配Rest模板对象。
  • 使用HttpHeaders设置请求标头。
  • 使用HttpEntity包装请求对象。
  • 为Exchange()方法提供URL,HttpMethod和Return类型。
@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模板使用此API响应。

下面给出的代码是请求正文 -

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

下面给出的代码是响应机构 -

Product is created successfully

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

  • 自动装配Rest模板对象。

  • 使用HttpHeaders设置请求标头。

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

  • 为exchange()方法提供URL,HttpMethod和Return类型。

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

  • 自动装配Rest模板对象。

  • 使用HttpHeaders设置请求标头。

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

  • 为exchange()方法提供URL,HttpMethod和Return类型。

@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 Template来使用此API响应。

下面显示的这行代码是响应正文 -

Product is deleted successfully

您必须按照下面显示的点来使用API​​ -

  • 自动装配Rest模板对象。

  • 使用HttpHeaders设置请求标头。

  • 使用HttpEntity包装请求对象。

  • 为exchange()方法提供URL,HttpMethod和Return类型。

@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 Template Controller类文件如下 -

package com.iowiki.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.iowiki.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 Application Class的代码 - DemoApplication.java如下 -

package com.iowiki.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 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.iowiki</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.iowiki'
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上启动。

在Tomcat Port_8080上启动应用程序

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

通过休息模板获取产品 - http://localhost:8080/template/products

通过休息模板获取产品

创建产品POST - http://localhost:8080/template/products

创建产品POST

更新产品PUT - http://localhost:8080/template/products/3

更新产品POST

删除产品 - http://localhost:8080/template/products/3

删除产品POST

Spring Boot - File Handling

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

上传文件

对于上载文件,您可以将MultipartFile用作请求参数,此API应使用多部分表单数据值。 观察下面给出的代码 -

@RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public String fileUpload(@RequestParam("file") MultipartFile file) {
   return null;
}

下面给出了相同的完整代码 -

package com.iowiki.demo.controller;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
public class FileUploadController {
   @RequestMapping(value = "/upload", method = RequestMethod.POST, 
      consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
   public String fileUpload(@RequestParam("file") MultipartFile file) throws IOException {
      File convertFile = new File("/var/tmp/"+file.getOriginalFilename());
      convertFile.createNewFile();
      FileOutputStream fout = new FileOutputStream(convertFile);
      fout.write(file.getBytes());
      fout.close();
      return "File is upload successfully";
   }
}

文件下载

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

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.iowiki.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.iowiki.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 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.iowiki</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.iowiki'
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,您可以使用下面显示的命令 -

sgradle clean build

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

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

java –jar <JARFILE> 

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

POSTMAN应用程序

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

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

POSTMAN应用程序文件上传

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

Spring Boot - Service Components

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

public interface ProductService {
}

使用@Service注释实现接口的类如下所示 -

@Service
public class ProductServiceImpl implements ProductService {
}

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

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

package com.iowiki.demo.service;
import java.util.Collection;
import com.iowiki.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();
}

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

package com.iowiki.demo.service;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.iowiki.demo.model.Product;
@Service
public class ProductServiceImpl implements ProductService {
   private static Map<String, Product> productRepo = new HashMap<>();
   static {
      Product honey = new Product();
      honey.setId("1");
      honey.setName("Honey");
      productRepo.put(honey.getId(), honey);
      Product almond = new Product();
      almond.setId("2");
      almond.setName("Almond");
      productRepo.put(almond.getId(), almond);
   }
   @Override
   public void createProduct(Product product) {
      productRepo.put(product.getId(), product);
   }
   @Override
   public void updateProduct(String id, Product product) {
      productRepo.remove(id);
      product.setId(id);
      productRepo.put(id, product);
   }
   @Override
   public void deleteProduct(String id) {
      productRepo.remove(id);
   }
   @Override
   public Collection<Product> getProducts() {
      return productRepo.values();
   }
}

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

package com.iowiki.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.iowiki.demo.model.Product;
import com.iowiki.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.iowiki.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.iowiki.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 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.iowiki</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.iowiki'
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上启动,如下图所示 -

建立成功

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

GET API URL是 - http://localhost:8080/products

邮递员应用程序GET API URL

POST API URL是 - http://localhost:8080/products

Postman应用程序POST API URL

PUT API URL是 - http://localhost:8080/products/3

邮递员应用程序PUT API URL

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

邮递员应用程序DELETE API URL

Spring Boot - Thymeleaf

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

Thymeleaf模板

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

  • XML
  • 有效的XML
  • XHTML
  • 有效的XHTML
  • HTML5
  • 旧版HTML5

除旧版HTML5之外的所有模板都指的是格式正确的有效XML文件。 旧版HTML5允许我们在网页中呈现HTML5标记,包括非封闭标记。

Web应用程序

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

使用以下代码创建@Controller类文件以将Request URI重定向到HTML文件 -

package com.iowiki.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文件应放在classpath中的静态目录下。 在所示的示例中,我们使用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截图

现在,我们需要在构建配置文件中添加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.iowiki.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.iowiki</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.iowiki'
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上启动,如下所示 -

在Tomcat Port_8080上启动应用程序

现在点击Web浏览器中的URL,您可以看到如下所示的输出 -

http://localhost:8080/index

Spring Boot Thymleaf Web应用程序

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应包含以下Request Body和Response正文。

请求正文的代码如下 -

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

Response body的代码如下 -

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.iowiki</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.iowiki’
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.iowiki.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 Application类文件如下 -

package com.iowiki.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
}

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

对于Maven,请使用下面给出的命令 -

mvn clean install

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

对于Gradle,请使用下面给出的命令 -

gradle clean build

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

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

java –jar <JARFILE> 

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

在Tomcat Port_8080上启动应用程序

现在点击Web浏览器中的URL,您可以看到如下所示的输出 -

HTTP://本地主机:8080 /视图副产物

1Honey_2Almond

HTTP://本地主机:8080 /附加产品

提交表单Spring Boot

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

提交表单Spring Boot输出窗口

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

http://localhost:8080/view-products

1Honey 2Almond 3Ginger

Angular JS

要使用Angular JS来使用API​​,您可以使用下面给出的示例 -

使用以下代码创建Angular JS Controller以使用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 Controller以使用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格式创建产品的Request主体。

Spring Boot - CORS Support

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

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

处理此问题需要两个要求 -

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

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

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

在Controller方法中启用CORS

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

@RequestMapping(value = "/products")
@CrossOrigin(origins = "http://localhost:8080")
public ResponseEntity<Object> getProduct() {
   return null;
}

全局CORS配置

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

@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.iowiki.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 Web服务应用程序。 有关RESTful Web Service实现的更多详细信息,请参阅本教程的“使用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

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

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

LocaleChangeInterceptor

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

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

为了起到这种作用,我们需要将LocaleChangeInterceptor添加到应用程序的注册表拦截器中。 配置类应扩展WebMvcConfigurerAdapter类并覆盖addInterceptors()方法。

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

消息来源

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

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

默认的messages.properties如下所示 -

welcome.text=Hi Welcome to Everyone

法语message_fr.properties如下所示 -

welcome.text=Salut Bienvenue à tous

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

HTML文件

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

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

完整的代码如下

Maven - pom.xml

<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.iowiki</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.iowiki'
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.iowiki.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.iowiki.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.iowiki.demo;
import java.util.Locale;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
@Configuration
public class Internationalization extends WebMvcConfigurerAdapter {
   @Bean
   public LocaleResolver localeResolver() {
      SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
      sessionLocaleResolver.setDefaultLocale(Locale.US);
      return sessionLocaleResolver;
   }
   @Bean
   public LocaleChangeInterceptor localeChangeInterceptor() {
      LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
      localeChangeInterceptor.setParamName("language");
      return localeChangeInterceptor;
   }
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(localeChangeInterceptor());
   }
}

消息源 - messages.properties如下所示 -

welcome.text = Hi Welcome to Everyone

消息源 - message_fr.properties如下所示 -

welcome.text = Salut Bienvenue à tous

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

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

您可以创建可执行的JAR文件,并使用以下Maven或Gradle命令运行Spring引导应用程序 -

对于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上启动应用程序

现在在Web浏览器中点击URL http://localhost:8080/locale ,您可以看到以下输出 -

输出Web浏览器

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

输出Web浏览器Salut Bienvenue

Spring Boot - Scheduling

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

Java Cron表达式

Java Cron表达式用于配置CronTrigger的实例,它是org.quartz.Trigger的子类。 有关Java cron表达式的更多信息,请参阅此链接 -

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

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

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

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

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

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

package com.iowiki.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作业调度程序

固定利率

固定速率调度程序用于在特定时间执行任务。 它不等待前一个任务的完成。 值应以毫秒为单位。 示例代码显示在此处 -

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

此处显示了应用程序启动时每秒执行任务的示例代码 -

package com.iowiki.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启动的应用程序,之后每隔一个固定速率调度程序任务已执行。

已执行固定费率计划程序任务

固定延迟

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

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

这里,initialDelay是在初始延迟值之后第一次执行任务的时间。

从应用程序启动完成3秒后每秒执行一次任务的示例如下所示 -

package com.iowiki.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秒后,固定延迟计划程序任务每秒执行一次。

已修复延迟计划程序任务已执行

Spring Boot - Enabling HTTPS

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

在Tomcat port_8080上启动应用程序

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

  • 获取SSL证书 - 创建自签名证书或从证书颁发机构获取证书

  • 启用HTTPS和443端口

Self-Signed Certificate

要创建自签名证书,Java Run Time环境与证书管理实用程序密钥工具捆绑在一起。 此实用程序工具用于创建自签名证书。 它显示在这里给出的代码中 -

keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
Enter keystore password:
   Re-enter new password:
   What is your first and last name?
   [Unknown]:
   What is the name of your organizational unit?
   [Unknown]:
   What is the name of your organization?
   [Unknown]:
   What is the name of your City or Locality?
   [Unknown]:
   What is the name of your State or Province?
   [Unknown]:
   What is the two-letter country code for this unit?
   [Unknown]:
   Is CN = Unknown, OU=Unknown, O = Unknown, L = Unknown, ST = Unknown, C = Unknown correct?
   [no]: yes

此代码将生成名为keystore.p12的PKCS12密钥库文件,证书别名为tomcat。

配置HTTPS

我们需要在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

如果您在application.yml下面使用YAML属性,则可以使用以下代码 -

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>

现在,应用程序已在Tomcat端口443上启动,其中显示了https -

在Tomcat端口443上启动应用程序

Spring Boot - Eureka Server

Eureka Server是一个包含所有客户端服务应用程序信息的应用程序。 每个Micro服务都将注册到Eureka服务器,Eureka服务器知道在每个端口和IP地址上运行的所有客户端应用程序。 Eureka Server也称为Discovery Server。

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

构建Eureka服务器

Eureka Server附带了Spring Cloud捆绑包。 为此,我们需要开发Eureka服务器并在默认端口8761上运行它。

访问Spring Initializer主页https://start.spring.io/并下载具有Eureka服务器依赖性的Spring Boot项目。 它显示在下面的屏幕截图中 -

构建Eureka服务器

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

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

package com.iowiki.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.iowiki</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.iowiki'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
   mavenCentral()
}
ext {
   springCloudVersion = 'Edgware.RELEASE'
}
dependencies {
   compile('org.springframework.cloud:spring-cloud-starter-eureka-server')
   testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
   imports {
      mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
   }
}

默认情况下,Eureka Server将自己注册到发现中。 您应该将以下给定的配置添加到application.properties文件或application.yml文件中。

application.properties文件如下 -

eureka.client.registerWithEureka = false
eureka.client.fetchRegistry = false
server.port = 8761

application.yml文件如下 -

eureka:
   client:
      registerWithEureka: false
      fetchRegistry: false
server:
   port: 8761

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

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

mvn clean install

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

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

gradle clean build

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

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

 java –jar <JARFILE> 

您可以在Tomcat端口8761上找到应用程序已启动,如下所示 -

应用程序在Tomcat端口8761上启动

现在,在Web浏览器中点击URL http://localhost:8761/ ,您可以在端口8761上找到运行的Eureka Server,如下所示 -

Eureka Server在端口8761上运行

Service Registration with Eureka

在本章中,您将详细了解如何将Spring Boot Micro服务应用程序注册到Eureka Server中。 在注册应用程序之前,请确保Eureka Server在端口8761上运行或首先构建Eureka Server并运行它。 有关构建Eureka服务器的更多信息,请参阅上一章。

首先,您需要在我们的构建配置文件中添加以下依赖项,以便向Eureka服务器注册微服务。

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

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

Gradle用户可以将以下依赖项添加到build.gradle文件中 -

compile('org.springframework.cloud:spring-cloud-starter-eureka')

现在,我们需要在主Spring Boot应用程序类文件中添加@EnableEurekaClient批注。 @EnableEurekaClient注释使您的Spring Boot应用程序充当Eureka客户端。

主要的Spring Boot应用程序如下所示 -

package com.iowiki.eurekaclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class EurekaclientApplication {
   public static void main(String[] args) {
      SpringApplication.run(EurekaclientApplication.class, args);
   }
}

要将Spring Boot应用程序注册到Eureka Server,我们需要在application.properties文件或application.yml文件中添加以下配置,并在我们的配置中指定Eureka Server URL。

application.yml文件的代码如下 -

eureka:
   client:
      serviceUrl:
         defaultZone: 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应用程序中返回String,并在构建配置文件中返回Spring Boot Starter Web依赖项。 观察下面给出的代码 -

package com.iowiki.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.iowiki</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.iowiki'
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> 

现在,应用程序已在Tomcat端口8080上启动,Eureka Client应用程序已在Eureka Server中注册,如下所示 -

在Tomcat端口上启动应用程序

在Web浏览器中点击URL http:// localhost:8761 /,您可以看到Eureka Client应用程序已在Eureka Server中注册。

Eureka客户端应用程序

现在,在Web浏览器中点击URL http://localhost:8080/ ,然后查看Rest Endpoint输出。

Eureka客户端应用程序输出

Spring Boot - Zuul Proxy Server and Routing

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

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

在本章中,我们将详细介绍如何在Spring Boot中创建Zuul Server应用程序。

创建Zuul服务器应用程序

Zuul Server捆绑了Spring Cloud依赖项。 您可以从Spring Initializer页面https://start.spring.io/下载Spring Boot项目,然后选择Zuul Server依赖项。

创建Zuul服务器应用程序

在主Spring Boot应用程序中添加@EnableZuulProxy批注。 @EnableZuulProxy注释用于使Spring Boot应用程序充当Zuul代理服务器。

package com.iowiki.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

这意味着http调用/api/demo/ get转发到产品服务。 例如, /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 Proxy进行路由之前, 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.iowiki</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.iowiki'
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上找到已启动的应用程序,如下所示。

在Tomcat Port_8111上启动应用程序

现在,在Web浏览器中点击URL http://localhost:8111/api/demo/products ,您可以看到/products REST Endpoint的输出,如下所示 -

产品REST端点

Spring Boot - Cloud Configuration Server

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

创建Spring Cloud配置服务器

首先,从Spring Initializer页面下载Spring Boot项目,然后选择Spring Cloud Config Server依赖项。 观察下面给出的截图 -

创建Spring Cloud配置服务器

现在,在构建配置文件中添加Spring Cloud Config服务器依赖项,如下所述 -

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

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-config-server</artifactId>
</dependency>

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

compile('org.springframework.cloud:spring-cloud-config-server')

现在,在主Spring Boot应用程序类文件中添加@EnableConfigServer批注。 @EnableConfigServer注释使您的Spring Boot应用程序充当配置服务器。

主要的Spring Boot应用程序类文件如下 -

package com.iowiki.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

Configuration Server在Tomcat端口8888上运行,应用程序配置属性从本机搜索位置加载。

现在,在file:///C:/configprop/ ,放置客户端应用程序 - application.properties文件。 例如,您的客户端应用程序名称是config-client ,然后将您的application.properties文件重命名为config-client.properties ,并将属性文件放在路径file:///C:/configprop/

config-client属性文件的代码如下 -

welcome.message = Welcome to Spring cloud config server

完整的构建配置文件如下 -

Maven用户可以使用下面给出的pom.xml -

<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.iowiki</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.iowiki'
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端口8888输出

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

配置客户端应用程序

Spring Boot - Cloud Configuration Client

某些应用程序可能需要可能需要更改的配置属性,开发人员可能需要将其关闭或重新启动应用程序才能执行此操作。 但是,这可能会导致生产停机并需要重新启动应用程序。 Spring Cloud Configuration Server允许开发人员加载新的配置属性,而无需重新启动应用程序,也不会出现任何停机。

使用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注释用于从Config服务器加载配置属性值。

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 - 在启动config客户端应用程序之前,应运行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上启动,如下所示 -

在Tomcat端口8080上启动应用程序

您可以在登录控制台窗口中看到; config-client应用程序从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/ welcome消息。

Spring Cloud Config Server

现在,转到配置服务器上的属性值并点击执行器Endpoint POST URL http://localhost:8080/refresh并在URL http://localhost:8080/查看新配置属性值

Spring Boot - Actuator

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

启用S​​pring Boot Actuator

要为Spring Boot应用程序启用Spring Boot执行器端点,我们需要在构建配置文件中添加Spring Boot Starter执行器依赖项。

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 Boot应用程序。

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

mvn clean install

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

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

gradle clean build

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

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

java –jar <JARFILE> 

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

在Tomcat端口上开始应用

下面给出了一些重要的Spring Boot Actuator端点。 您可以在Web浏览器中输入它们并监视应用程序行为。

ENDPOINTS 用法
/metrics 查看应用程序指标,例如使用的内存,无内存,线程,类,系统正常运行时间等。
/env 查看应用程序中使用的环境变量列表。
/beans 查看Spring bean及其类型,范围和依赖关系。
/health 查看应用程序运行状况
/info 查看有关Spring Boot应用程序的信息。
/trace 查看Rest端点的跟踪列表。

Spring Boot - Admin Server

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

为了处理这种情况,CodeCentric Team提供了一个Spring Boot Admin UI,用于在一个地方管理和监控所有Spring Boot应用程序Actuator端点。

要构建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注释用于使您的管理服务器监视所有其他微服务。

package com.iowiki.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和application name,如图所示 -

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.iowiki</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.iowiki'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {   
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter')
   compile group: 'de.codecentric', name: 'spring-boot-admin-server', version: '1.5.5'
   compile group: 'de.codecentric', name: 'spring-boot-admin-server-ui', version: '1.5.5'   
   testCompile('org.springframework.boot:spring-boot-starter-test')
}

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

对于Maven,请使用此处显示的命令 -

mvn clean install

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

对于Gradle,请使用此处显示的命令 -

gradle clean build

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

现在,使用下面给出的命令运行JAR文件 -

java –jar <JARFILE> 

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

Tomcat端口9090输出

现在,从Web浏览器中点击以下URL,然后查看管理服务器UI。

http://localhost:9090/

Web浏览器管理服务器UI

Spring Boot - Admin Client

要通过Spring Boot Admin Server监视和管理您的微服务应用程序,您应该添加Spring Boot Admin启动器客户端依赖项,并将Admin Server URI指向应用程序属性文件。

Note - 要监视应用程序,应为微服务应用程序启用Spring Boot Actuator端点。

首先,在构建配置文件中添加以下Spring Boot Admin启动程序客户端依赖项和Spring Boot启动程序执行程序依赖项。

Maven用户可以在pom.xml文件中添加以下依赖项 -

<dependency>
   <groupId>de.codecentric</groupId>
   <artifactId>spring-boot-admin-starter-client</artifactId>
   <version>1.5.5</version>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

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

compile group: 'de.codecentric', name: 'spring-boot-admin-starter-client', version: '1.5.5'
compile('org.springframework.boot:spring-boot-starter-actuator')

现在,将Spring Boot Admin Server URL添加到您的应用程序属性文件中。

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

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端口9090输出

现在,从Web浏览器中点击以下URL,看看您的Spring Boot应用程序已在Spring Boot Admin Server中注册。

http://localhost:9090/

Spring Boot管理服务器

现在,单击“ Details按钮,然后在管理服务器UI中查看执行器端点。

管理服务器UI中的执行器端点

Spring Boot - Enabling Swagger2

Swagger2是一个开源项目,用于为RESTful Web服务生成REST API文档。 它提供了一个用户界面,可通过Web浏览器访问我们的RESTful Web服务。

要在Spring Boot应用程序中启用Swagger2,您需要在我们的构建配置文件中添加以下依赖项。

<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.7.0</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.7.0</version>
</dependency>

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

compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.7.0'
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.7.0'

现在,在主Spring Boot应用程序中添加@EnableSwagger2注释。 @ EnableSwagger2注释用于为Spring Boot应用程序启用Swagger2。

主要Spring Boot应用程序的代码如下所示 -

package com.iowiki.swaggerdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@SpringBootApplication
@EnableSwagger2
public class SwaggerDemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(SwaggerDemoApplication.class, args);
   }
}

接下来,创建Docket Bean以为Spring Boot应用程序配置Swagger2。 我们需要定义基础包来为Swagger2配置REST API。

@Bean
   public Docket productApi() {
      return new Docket(DocumentationType.SWAGGER_2).select()
         .apis(RequestHandlerSelectors.basePackage("com.iowiki.swaggerdemo")).build();
   }

现在,在主Spring Boot应用程序类文件中添加这个bean,你的主Spring Boot应用程序类看起来如下所示 -

package com.iowiki.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.iowiki.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.iowiki.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.iowiki</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.iowiki'
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上启动,如图所示 -

在Tomcat端口8080上启动应用程序

现在,点击Web浏览器中的URL并查看Swagger API功能。

http://localhost:8080/swagger-ui.html

Swagger API功能

Spring Boot - Creating Docker Image

Docker是一种容器管理服务,可以简化构建和部署。 如果您是Docker的初学者,可以通过以下链接了解详细信息 - https://www.iowiki.com/docker/index.htm

在本章中,我们将看到如何通过为Spring Boot应用程序使用Maven和Gradle依赖项来创建Docker镜像。

创建Dockerfile

首先,在目录src/main/docker Dockerfile下创建一个名为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-iowiki</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.iowiki</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-iowiki</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包Docker Build

Note - 在没有TLS的情况下在tcp://localhost:2375上启用Expose守护程序。

构建成功后,您可以在控制台上看到输出,如下所示 -

MVN包Docker输出

现在,使用docker images通过命令查看Docker镜像,并在控制台上查看图像信息。

Docker图像命令

Gradle

要使用Gradle构建配置构建Docker镜像,我们需要添加buildDocker插件并需要编写任务buildDocker来创建Docker镜像。

Gradle Docker配置的代码如下。

buildscript {
   .....
   dependencies {
      .....
      classpath('se.transmode.gradle:gradle-docker:1.2')
   }
}
group = 'spring-boot-iowiki'
.....
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-iowiki'
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'docker'
group = 'com.iowiki'
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构建成功

现在,使用docker images通过命令查看Docker镜像,并在控制台上查看图像的信息。

使用DockerImages获取图像信息

Spring Boot - Tracing Micro Service Logs

如果发生任何问题,大多数开发人员都难以跟踪日志。 这可以通过用于Spring Boot应用程序的Spring Cloud Sleuth和ZipKin服务器来解决。

春云侦探

Spring cloud Sleuth日志以下列格式打印 -

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

Where,

  • Application-name =应用程序的名称

  • Traceid =每个请求和响应traceid在调用相同服务或一个服务到另一个服务时是相同的。

  • Spanid = Span Id与Trace Id一起打印。 对于将一个服务调用到另一个服务的每个请求和响应,Span Id都不同。

  • Zipkin-export =默认情况下为false。 如果是,则将日志导出到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')

现在,将Logs添加到Spring Boot应用程序Rest Controller类文件中,如下所示 -

package com.iowiki.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.iowiki</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.iowiki'
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上启动。

在Tomcat端口8080上启动应用程序

现在,点击Web浏览器中的URL,然后在控制台日志中查看输出。

http://localhost:8080/

输出欢迎侦探

您可以在控制台窗口中看到以下日志。 观察日志以下列格式打印[application-name,traceid,spanid,zipkin-export]

日志已打印

Zipkin服务器

Zipkin是一个监视和管理Spring Boot应用程序的Spring Cloud Sleuth日志的应用程序。 要构建Zipkin服务器,我们需要在构建配置文件中添加Zipkin UI和Zipkin Server依赖项。

Maven用户可以在pom.xml文件中添加以下依赖项 -

<dependency>
   <groupId>io.zipkin.java</groupId>
   <artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
   <groupId>io.zipkin.java</groupId>
   <artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>

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

compile('io.zipkin.java:zipkin-autoconfigure-ui')
compile('io.zipkin.java:zipkin-server')

现在,在应用程序属性文件中配置server.port = 9411。

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

server.port = 9411

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

server:
   port: 9411

在主Spring Boot应用程序类fie中添加@EnableZipkinServer批注。 @EnableZipkinServer注释用于使您的应用程序充当Zipkin服务器。

package com.iowiki.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.iowiki</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.iowiki'
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上启动,如下所示 -

输出Tomcat端口9411

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

http://localhost:9411/zipkin/

Zipkin服务器UI

然后,在客户端服务应用程序中添加以下依赖项,并指出Zipkin Server URL以通过Zipkin UI跟踪微服务日志。

现在,在构建配置文件中添加Spring Cloud Starter Zipkin依赖项,如下所示 -

Maven用户可以在pom.xml文件中添加以下依赖项 -

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>

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

compile('org.springframework.cloud:spring-cloud-sleuth-zipkin')

现在,在Spring Boot应用程序中添加Always Sampler Bean ,将日志导出到Zipkin服务器。

@Bean
public AlwaysSampler defaultSampler() {
   return new AlwaysSampler();
}

如果添加AlwaysSampler Bean,则自动Spring Sleuth Zipkin Export选项将从false更改为true。

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

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

然后,提供跟踪ID并在Zipkin UI中查找跟踪。

http://localhost:9411/zipkin/traces/{traceid}/

Spring Boot - Flyway Database

Flyway是一个版本控制应用程序,可以在所有实例中轻松可靠地发展数据库模式。 要了解有关Flyway的更多信息,您可以使用链接 - www.flywaydb.org

许多软件项目使用关系数据库。 这需要处理数据库迁移,通常也称为模式迁移。

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

配置Flyway数据库

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

  • Spring Boot Starter Web
  • Flyway
  • MySQL
  • JDBC

Maven用户可以在pom.xml文件中添加以下依赖项。

<dependency>
   <groupId>org.flywaydb</groupId>
   <artifactId>flyway-core</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>

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

compile('org.flywaydb:flyway-core')
compile('org.springframework.boot:spring-boot-starter-jdbc')
compile('org.springframework.boot:spring-boot-starter-web')
compile('mysql:mysql-connector-java')

在应用程序属性中,我们需要配置数据库属性以创建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, 'iowiki.com');

主要的Spring Boot应用程序类文件代码如下 -

package com.iowiki.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.iowiki</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.iowiki'
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数据库日志。

飞路数据库日志

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

数据库并选择查询

Spring Boot - Sending Email

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

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

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

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

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

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

主要的Spring Boot应用程序类文件的代码如下 -

package com.iowiki.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 Controller类文件中发送到电子邮件,如图所示。

package com.iowiki.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("iowiki@gmail.com", "<your password>");
      }
   });
   Message msg = new MimeMessage(session);
   msg.setFrom(new InternetAddress("iowiki@gmail.com", false));
   msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("iowiki@gmail.com"));
   msg.setSubject("IOWIKI email");
   msg.setContent("IOWIKI email", "text/html");
   msg.setSentDate(new Date());
   MimeBodyPart messageBodyPart = new MimeBodyPart();
   messageBodyPart.setContent("IOWIKI 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.iowiki</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.iowiki'
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端口8080应用程序输出

现在,从Web浏览器中点击以下URL,您将收到一封电子邮件。

http://localhost:8080/sendemail

电子邮件已成功发送浏览器窗口

电子邮件已成功发送

Spring Boot - Hystrix

Hystrix是Netflix的一个库。 Hystrix隔离了服务之间的访问点,阻止了它们之间的级联故障并提供了后备选项。

例如,当您呼叫第三方应用程序时,发送响应需要更多时间。 所以在那个时候,控件转到了回退方法并将自定义响应返回给你的应用程序。

在本章中,您将看到如何在Spring Boot应用程序中实现Hystrix。

首先,我们需要在构建配置文件中添加Spring Cloud Starter Hystrix依赖项。

Maven用户可以在pom.xml文件中添加以下依赖项 -

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

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

compile('org.springframework.cloud:spring-cloud-starter-hystrix')

现在,将@EnableHystrix注释添加到主Spring Boot应用程序类文件中。 @EnableHystrix注释用于将Hystrix功能启用到Spring Boot应用程序中。

主要的Spring Boot应用程序类文件代码如下 -

package com.iowiki.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秒后返回String。

@RequestMapping(value = "/")
public String hello() throws InterruptedException {
   Thread.sleep(3000);
   return "Welcome Hystrix";
}

现在,为Rest API添加@Hystrix命令和@HystrixProperty,并以毫秒为单位定义超时值。

@HystrixCommand(fallbackMethod = "fallback_hello", commandProperties = {
   @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
})

接下来,如果请求需要很长时间来响应,请定义回退方法fallback_hello()。

private String fallback_hello() {
   return "Request fails. It takes long time to response";
}

此处显示包含REST API和Hystrix属性的完整Rest Controller类文件 -

@RequestMapping(value = "/")
@HystrixCommand(fallbackMethod = "fallback_hello", commandProperties = {
   @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
})
public String hello() throws InterruptedException {
   Thread.sleep(3000);
   return "Welcome Hystrix";
}
private String fallback_hello() {
   return "Request fails. It takes long time to response";
}

在此示例中,REST API编写在主Spring Boot应用程序类文件本身中。

package com.iowiki.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.iowiki</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.iowiki'
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> 

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

Tomcat应用程序命令提示符

现在,从Web浏览器中点击URL http://localhost:8080/ ,然后查看Hystrix响应。 API需要3秒钟才能响应,但Hystrix超时为1秒。

请求失败Hystrix超时

Spring Boot - Web Socket

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

要使用Web套接字在Spring Boot中构建交互式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.iowiki.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。 编写一个扩展AbstractWebSocketMessageBrokerConfigurer类的WebSocketConfig类文件,如下所示。

package com.iowiki.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("/iowiki-websocket").withSockJS();
   }
}

@EnableWebSocketMessageBroker注释用于配置Web套接字消息代理以创建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('/iowiki-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.iowiki.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.iowiki</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上启动,如图所示。

批处理服务应用程序在Tomcat端口上启动

现在,在Web浏览器中点击URL http://localhost:8080/并连接Web套接字并发送问候语并接收消息。

Web套接字发送和接收消息

批处理服务是在单个任务中执行多个命令的过程。 在本章中,您将学习如何在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")

现在,在classpath resources - src/main/resources下添加简单的CSV数据文件,并将文件命名为file.csv,如图所示 -

William,John
Mike, Sebastian
Lawarance, Lime

接下来,为HSQLDB编写一个SQL脚本 - 在classpath资源目录下 - 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.iowiki.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.iowiki.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;
   }
}

让我们创建一个Batch配置文件,从CSV读取数据并写入SQL文件,如下所示。 我们需要在配置类文件中添加@EnableBatchProcessing注释。 @EnableBatchProcessing注释用于启用Spring Boot应用程序的批处理操作。

package com.iowiki.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。

接下来,我们将编写一个Job Completion Notification Listener类 - 用于在Job完成后通知。

package com.iowiki.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>

您可以在控制台窗口中看到输出,如图所示 -

控制台窗口中的批量服务输出

Spring Boot - Apache Kafka

Apache Kafka是一个开源项目,用于基于容错消息传递系统发布和订阅消息。 它设计快速,可扩展和分布。 如果您是Kafka的初学者,或想要更好地了解它,请参阅此链接 - www.iowiki.com/apache_kafka/

在本章中,我们将了解如何在Spring Boot应用程序中实现Apache Kafka。

首先,我们需要在构建配置文件中添加Spring Kafka依赖项。

Maven用户可以在pom.xml文件中添加以下依赖项。

<dependency>
   <groupId>org.springframework.kafka</groupId>
   <artifactId>spring-kafka</artifactId>
   <version>2.1.0.RELEASE</version>
</dependency>

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

compile group: 'org.springframework.kafka', name: 'spring-kafka', version: '2.1.0.RELEASE'

制作消息

要向Apache Kafka生成消息,我们需要为Producer配置定义Configuration类,如下所示 -

package com.iowiki.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);
}   

消费消息

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

package com.iowiki.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 = "iowiki", 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.iowiki.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("iowiki", msg);
   }
   public static void main(String[] args) {
      SpringApplication.run(KafkaDemoApplication.class, args);
   }
   @KafkaListener(topics = "iowiki", 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.iowiki</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.iowiki'
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是第三方应用程序,用于从我们的应用程序发送短信和拨打语音电话。 它允许我们以编程方式发送短信和拨打语音电话。

在本章中,您将学习如何使用Spring Boot with Twilio实现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"   

现在,在静态块中使用ACCOUNT_SID和AUTH_ID初始化Twilio帐户,如图所示 -

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

发送短信

要发送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.iowiki.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.iowiki</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.iowiki'
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”。

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

Note - 在此示例中,我们使用了Trail帐户。 因此,您应该在发送短信之前验证号码。

语音电话

要使用Twilio进行语音呼叫,我们需要调用Call.creator()方法。 对于这种方法,我们需要提供一个to-number,from-number和voice-note,如下所示。

Call.creator(new PhoneNumber("<to-number>"), new PhoneNumber("<from-number>"),
   new URI("http://demo.twilio.com/docs/voice.xml")).create();

下面给出了主Spring Boot应用程序类文件的代码。

package com.iowiki.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.iowiki</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.iowiki'
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 Controller编写单元测试用例。

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

此处给出了编写Service类的代码,该类包含一个返回String值的方法。

package com.iowiki.mockitodemo;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
   public String getProductName() {
      return "Honey";
   } 
}

现在,将ProductService类注入另一个Service类文件,如图所示。

package com.iowiki.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.iowiki.mockitodemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MockitoDemoApplication {
   public static void main(String[] args) {
      SpringApplication.run(MockitoDemoApplication.class, args);
   }
}

然后,为测试配置应用程序上下文。 @Profile(“test”)注释用于在测试用例运行时配置类。

package com.iowiki.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包下为Order Service编写单元测试用例。

package com.iowiki.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.iowiki</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.iowiki'
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 

您可以在控制台窗口中查看测试结果。

控制台窗口中的测试结果

对于Gradle,您可以使用如下所示的命令 -

gradle clean build 

您可以在控制台窗口中看到其余结果。

在控制台窗口中休息结果

Spring Boot - Rest Controller Unit Test

Spring Boot提供了一种为Rest Controller文件编写单元测试的简便方法。 在SpringJUnit4ClassRunner和MockMvc的帮助下,我们可以创建一个Web应用程序上下文来为Rest Controller文件编写单元测试。

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

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

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

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

testCompile('org.springframework.boot:spring-boot-starter-test')

在编写测试用例之前,我们应该首先构建RESTful Web服务。 有关构建RESTful Web服务的更多信息,请参阅本教程中给出的相同章节。

编写REST控制器的单元测试

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

首先,我们需要创建用于通过使用MockMvc创建Web应用程序上下文的Abstract类文件,并定义mapToJson()和mapFromJson()方法以将Java对象转换为JSON字符串并将JSON字符串转换为Java对象。

package com.iowiki.demo;
import java.io.IOException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class)
@WebAppConfiguration
public abstract class AbstractTest {
   protected MockMvc mvc;
   @Autowired
   WebApplicationContext webApplicationContext;
   protected void setUp() {
      mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
   }
   protected String mapToJson(Object obj) throws JsonProcessingException {
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.writeValueAsString(obj);
   }
   protected <T> T mapFromJson(String json, Class<T> clazz)
      throws JsonParseException, JsonMappingException, IOException {
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.readValue(json, clazz);
   }
}

接下来,编写一个扩展AbstractTest类的类文件,并为每个方法(如GET,POST,PUT和DELETE)编写单元测试。

下面给出了GET API测试用例的代码。 此API用于查看产品列表。

@Test
public void getProductsList() throws Exception {
   String uri = "/products";
   MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get(uri)
      .accept(MediaType.APPLICATION_JSON_VALUE)).andReturn();
   int status = mvcResult.getResponse().getStatus();
   assertEquals(200, status);
   String content = mvcResult.getResponse().getContentAsString();
   Product[] productlist = super.mapFromJson(content, Product[].class);
   assertTrue(productlist.length > 0);
}

POST API测试用例的代码如下。 此API用于创建产品。

@Test
public void createProduct() throws Exception {
   String uri = "/products";
   Product product = new Product();
   product.setId("3");
   product.setName("Ginger");
   String inputJson = super.mapToJson(product);
   MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(uri)
      .contentType(MediaType.APPLICATION_JSON_VALUE).content(inputJson)).andReturn();
   int status = mvcResult.getResponse().getStatus();
   assertEquals(201, status);
   String content = mvcResult.getResponse().getContentAsString();
   assertEquals(content, "Product is created successfully");
}

下面给出了PUT API测试用例的代码。 此API用于更新现有产品。

@Test
public void updateProduct() throws Exception {
   String uri = "/products/2";
   Product product = new Product();
   product.setName("Lemon");
   String inputJson = super.mapToJson(product);
   MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put(uri)
      .contentType(MediaType.APPLICATION_JSON_VALUE).content(inputJson)).andReturn();
   int status = mvcResult.getResponse().getStatus();
   assertEquals(200, status);
   String content = mvcResult.getResponse().getContentAsString();
   assertEquals(content, "Product is updated successsfully");
}

Delete API测试用例的代码如下。 此API将删除现有产品。

@Test
public void deleteProduct() throws Exception {
   String uri = "/products/2";
   MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.delete(uri)).andReturn();
   int status = mvcResult.getResponse().getStatus();
   assertEquals(200, status);
   String content = mvcResult.getResponse().getContentAsString();
   assertEquals(content, "Product is deleted successsfully");
}

完整的Controller Test类文件如下 -

package com.iowiki.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.iowiki.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 

现在,您可以在控制台窗口中看到测试结果。

控制台窗口中的测试结果

对于Gradle,您可以使用如下所示的命令 -

gradle clean build

您可以在控制台窗口中看到其余结果,如下所示。

在控制台窗口中休息结果

Spring Boot - Database Handling

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

在本章中,我们将使用Spring Boot JDBC驱动程序连接来连接数据库。

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

Maven用户可以在pom.xml文件中添加以下依赖项。

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

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

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

连接到H2数据库

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

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

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

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

compile('com.h2database:h2')

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

连接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中创建数据库和表,如图所示 -

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

连接Redis

Redis是一个用于存储内存数据结构的开源数据库。 要在Spring Boot应用程序中连接Redis数据库,我们需要在构建配置文件中添加Redis依赖项。

Maven用户应在pom.xml文件中添加以下依赖项。

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

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

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

对于Redis连接,我们需要使用RedisTemplate。 对于RedisTemplate,我们需要提供JedisConnectionFactory的详细信息。

@Bean
JedisConnectionFactory jedisConnectionFactory() {
   JedisConnectionFactory jedisConFactory = new JedisConnectionFactory();
   jedisConFactory.setHostName("localhost");
   jedisConFactory.setPort(6000);
   jedisConFactory.setUsePool(true);
   return jedisConFactory;
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
   RedisTemplate<String, Object> template = new RedisTemplate<>();
   template.setConnectionFactory(jedisConnectionFactory());
   template.setKeySerializer(new StringRedisSerializer());
   template.setHashKeySerializer(new StringRedisSerializer());
   template.setHashValueSerializer(new StringRedisSerializer());
   template.setValueSerializer(new StringRedisSerializer());
   return template;
}

现在自动连接RedisTemplate类并从Redis数据库访问数据。

@Autowired
RedisTemplate<String, Object> redis;
Map<Object,Object> datalist = redis.opsForHash().entries(“Redis_code_index_key”);

JDBCTemplate

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

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

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

应将@Repository注释添加到类文件中。 @Repository注释用于为Spring Boot应用程序创建数据库存储库。

@Repository
public class ProductServiceDAO {
}

多个数据源

我们可以在一个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 Security添加到Spring Boot应用程序,我们需要在构建配置文件中添加Spring Boot Starter Security依赖项。

Maven用户可以在pom.xml文件中添加以下依赖项。

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

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

compile("org.springframework.boot:spring-boot-starter-security")

保护Web应用程序

首先,使用Thymeleaf模板创建不安全的Web应用程序。

然后,在src/main/resources/templates目录下创建一个home.html文件。

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:th = "http://www.thymeleaf.org" 
   xmlns:sec = "http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
   <head>
      <title>Spring Security Example</title>
   </head>
   <body>
      <h1>Welcome!</h1>
      <p>Click <a th:href = "@{/hello}">here</a> to see a greeting.</p>
   </body>
</html>

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

现在,在src/main/resources/templates目录下创建一个hello.html。

<!DOCTYPE html>
<html xmlns = "http://www.w3.org/1999/xhtml" 
   xmlns:th = "http://www.thymeleaf.org" 
   xmlns:sec = "http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
   <head>
      <title>Hello World!</title>
   </head>
   <body>
      <h1>Hello world!</h1>
   </body>
</html>

现在,我们需要为Home和hello视图设置Spring MVC - View控制器。

为此,创建一个扩展WebMvcConfigurerAdapter的MVC配置文件。

package com.iowiki.websecuritydemo;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
   @Override
   public void addViewControllers(ViewControllerRegistry registry) {
      registry.addViewController("/home").setViewName("home");
      registry.addViewController("/").setViewName("home");
      registry.addViewController("/hello").setViewName("hello");
      registry.addViewController("/login").setViewName("login");
   }
}

现在,将Spring Boot Starter安全依赖项添加到构建配置文件中。

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.iowiki.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.iowiki.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.iowiki</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.iowiki'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-security')
   compile('org.springframework.boot:spring-boot-starter-thymeleaf')
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
   testCompile('org.springframework.security:spring-security-test')
}

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

Maven用户可以使用下面给出的命令 -

mvn clean install

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

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

gradle clean build

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

现在,使用下面显示的命令运行JAR文件 -

java –jar <JARFILE> 

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

Web浏览器上的输出单击链接

输出登录页面

输出注销页面

输出已注销

无效的用户名/密码

Spring Boot - OAuth2 with JWT

在本章中,您将详细了解Spring Boot Security机制和使用JWT的OAuth2。

授权服务器

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

资源服务器

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

OAuth2

OAuth2是一个授权框架,使应用程序Web Security可以从客户端访问资源。 要构建OAuth2应用程序,我们需要关注授权类型(授权代码),客户端ID和客户端密钥。

JWT令牌

JWT Token是一个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")  

Where,

  • Spring Boot Starter Security - 实现Spring Security

  • Spring Security OAuth2 - 实现OAUTH2结构以启用授权服务器和资源服务器。

  • Spring Security JWT - 为Web安全生成JWT令牌

  • Spring Boot Starter JDBC - 访问数据库以确保用户可用。

  • Spring Boot Starter Web - 写入HTTP端点。

  • H2 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.iowiki</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.iowiki'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
   mavenCentral()
}
dependencies {
   compile('org.springframework.boot:spring-boot-starter-security')
   compile('org.springframework.boot:spring-boot-starter-web')
   testCompile('org.springframework.boot:spring-boot-starter-test')
   testCompile('org.springframework.security:spring-security-test')
   compile("org.springframework.security.oauth:spring-security-oauth2")
   compile('org.springframework.security:spring-security-jwt')
   compile("org.springframework.boot:spring-boot-starter-jdbc")
   compile("com.h2database:h2:1.4.191")  
} 

现在,在主Spring Boot应用程序中,添加@EnableAuthorizationServer和@EnableResourceServer注释,以在同一应用程序中充当Auth服务器和资源服务器。

此外,您可以使用以下代码编写一个简单的HTTP端点,以使用JWT Token通过Spring Security访问API。

package com.iowiki.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.iowiki.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.iowiki.websecurityapp;
import org.springframework.security.core.userdetails.User;
public class CustomUser extends User {
   private static final long serialVersionUID = 1L;
   public CustomUser(UserEntity user) {
      super(user.getUsername(), user.getPassword(), user.getGrantedAuthoritiesList());
   }
} 

您可以创建@Repository类以从数据库中读取用户信息并将其发送到自定义用户服务,并添加授予的权限“ROLE_SYSTEMADMIN”。

package com.iowiki.websecurityapp;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Repository;
@Repository
public class OAuthDao {
   @Autowired
   private JdbcTemplate jdbcTemplate;
   public UserEntity getUserDetails(String username) {
      Collection<GrantedAuthority> grantedAuthoritiesList = new ArrayList<>();
      String userSQLQuery = "SELECT * FROM USERS WHERE USERNAME=?";
      List<UserEntity> list = jdbcTemplate.query(userSQLQuery, new String[] { username },
         (ResultSet rs, int rowNum) -> {
         UserEntity user = new UserEntity();
         user.setUsername(username);
         user.setPassword(rs.getString("PASSWORD"));
         return user;
      });
      if (list.size() > 0) {
         GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_SYSTEMADMIN");
         grantedAuthoritiesList.add(grantedAuthority);
         list.get(0).setGrantedAuthoritiesList(grantedAuthoritiesList);
         return list.get(0);
      }
      return null;
   }
} 

您可以创建一个自定义用户详细信息服务类,该类扩展org.springframework.security.core.userdetails.UserDetailsS​​ervice以调用DAO存储库类,如图所示。

package com.iowiki.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.iowiki.websecurityapp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
   @Autowired
   private CustomDetailsService customDetailsService;
   @Bean
   public PasswordEncoder encoder() {
      return new BCryptPasswordEncoder();
   }
   @Override
   @Autowired
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(customDetailsService).passwordEncoder(encoder());
   }
   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests().anyRequest().authenticated().and().sessionManagement()
         .sessionCreationPolicy(SessionCreationPolicy.NEVER);
   }
   @Override
   public void configure(WebSecurity web) throws Exception {
      web.ignoring();
   }
   @Override
   @Bean
   public AuthenticationManager authenticationManagerBean() throws Exception {
      return super.authenticationManagerBean();
   }
} 

现在,定义OAuth2配置类以添加客户端ID,客户端密钥,为标记签名者密钥和验证者密钥定义JwtAccessTokenConverter,私钥和公钥,并使用范围配置ClientDetailsS​​erviceConfigurer以获取令牌有效性。

package com.iowiki.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 = "iowiki";
   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 

您可以使用For公钥生成使用以下命令。

openssl rsa -in jwt.pem -pubout 

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

security.oauth2.resource.filter-order=3 

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

security:
   oauth2:
      resource:
         filter-order: 3 

现在,在classpath resources 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, 'iowiki@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端口8080应用程序输出

现在通过POSTMAN命中POST方法URL以获取OAUTH2令牌。

http://localhost:8080/oauth/token

现在,添加请求标头如下 -

  • Authorization - 使用您的客户端ID和客户端密钥进行基本身份验证。

  • Content Type - application/x-www-form-urlencoded

添加请求标头

现在,添加请求参数如下 -

  • grant_type =密码
  • username =您的用户名
  • password = your password
添加请求参数

现在,点击API并获取access_token,如图所示 -

获取Access-Token

现在,如图所示,在Request Header中使用Bearer访问令牌命中Resource Server API。

具有承载访问令牌的资源服务器API

然后你可以看到如下所示的输出 -

具有JWT输出的OAuth2

Spring Boot - Google Cloud Platform

Google Cloud Platform提供云计算服务,可在云环境中运行Spring Boot应用程序。 在本章中,我们将了解如何在GCP应用引擎平台中部署Spring Boot应用程序。

首先,从Spring Initializer页面www.start.spring.io下载Gradle build Spring Boot应用程序。 请注意以下屏幕截图。

Spring Initializer页面

现在,在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.iowiki'
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端点,它返回String成功,如图所示 -

package com.iowiki.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云端shell。

激活Google Cloud Shell

现在,使用google cloud shell将源文件和Gradle文件移动到google云计算机的主目录中。

使用Google Cloud Shell迁移到主目录

现在,执行命令gradle appengineDeploy,它会将您的应用程序部署到Google Cloud appengine中。

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

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

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

Spring Initializer页面

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

App Engine开发成功

Google Cloud SQL

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

JDBC URL格式

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

Note - Spring Boot应用程序和Google Cloud SQL应该在同一个GCP项目中。

application.properties文件如下所示。

spring.dbProductService.driverClassName = com.mysql.jdbc.Driver
spring.dbProductService.url = jdbc:mysql://google/PRODUCTSERVICE?cloudSqlInstance = springboot-gcp-cloudsql:asia-northeast1:springboot-gcp-cloudsql-instance&socketFactory = com.google.cloud.sql.mysql.SocketFactory&user = root&password = rootspring.dbProductService.username = root
spring.dbProductService.password = root
spring.dbProductService.testOnBorrow = true
spring.dbProductService.testWhileIdle = true
spring.dbProductService.timeBetweenEvictionRunsMillis = 60000
spring.dbProductService.minEvictableIdleTimeMillis = 30000
spring.dbProductService.validationQuery = SELECT 1
spring.dbProductService.max-active = 15
spring.dbProductService.max-idle = 10
spring.dbProductService.max-wait = 8000

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

spring:
   datasource: 
      driverClassName: com.mysql.jdbc.Driver
      url: "jdbc:mysql://google/PRODUCTSERVICE?cloudSqlInstance=springboot-gcp-cloudsql:asia-northeast1:springboot-gcp-cloudsql-instance&socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=root&password=root"
      password: "root"
      username: "root"
      testOnBorrow: true
      testWhileIdle: true
      validationQuery: SELECT 1
      max-active: 15
      max-idle: 10
      max-wait: 8000

Spring Boot - Google OAuth2 Sign-In

在本章中,我们将了解如何使用带有Gradle构建的Spring Boot应用程序添加Google OAuth2登录。

首先,在构建配置文件中添加Spring Boot OAuth2安全依赖项,下面给出了构建配置文件。

buildscript {
   ext {
      springBootVersion = '1.5.8.RELEASE'
   }
   repositories {
      mavenCentral()
   }
   dependencies {
      classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
   }
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
group = 'com.iowiki.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读取User Principal,如下所示 -

package com.iowiki.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;
   }
}

现在,编写一个配置文件以启用OAuth2SSO以实现Web安全性,并删除index.html文件的身份验证,如下所示 -

package com.iowiki.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用户Principal,如下所示 -

<!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服务,Google Analytics服务和Google+服务API。

然后,转到“凭据”部分并创建凭据并选择OAuth客户端ID。

证书部分

接下来,在OAuth2许可屏幕中提供产品名称。

OAuth2同意屏幕中的产品名称

接下来,选择“应用程序类型”作为“Web应用程序”,提供授权的JavaScript源和授权的重定向URI。

授权重定向URI

现在,您的OAuth2客户端ID和客户端密钥已创建。

已创建OAuth2客户端ID

接下来,在应用程序属性文件中添加客户端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 运行JAR文件,并在Tomcat端口8080上启动应用程序。

现在点击URL http://localhost:8080/并点击Google登录链接。

Google登录链接

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

谷歌登录屏幕

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

Gmail用户的主要对象
↑回到顶部↑
WIKI教程 @2018