天天看点

【框架】Spring Boot 2.0 介绍 + 问题汇总(包括:异步非阻塞)(未完结)

  • 提问:什么是 Spring Boot?

    Spring Boot 是 Spring 开源组织下的子项目,是【Spring 组件一站式解决方案】,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。

    更多 Spring Boot 详细介绍请看这篇文章《什么是Spring Boot?》。

——————————————————————————————

  • 提问:Spring Boot优点?

    独立运行

    简化配置

    自动配置

    无代码生成和XML配置

    应用监控

    上手容易

——————————————————————————————

  • 提问:Spring Boot 的核心配置文件有哪几个?它们的区别是什么?

Spring Boot 的核心配置文件是

application

bootstrap

配置文件。

Spring Boot 中有两种【上下文】一种是

bootstrap

, 另外一种是

application

bootstrap

是【应用程序】的父上下文,也就是说

bootstrap

加载优先于

applicaton

bootstrap

主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。

因此,对比 application 配置文件,bootstrap 配置文件具有以下几个特性。

  • boostrap 由

    父 ApplicationContext

    加载,比

    applicaton

    优先加载;
  • boostrap 里面的属性不能被覆盖;

bootstrap/ application 的应用场景:

application

配置文件这个容易理解,主要用于 Spring Boot 项目的自动化配置。

bootstrap

配置文件有以下几个应用场景:

使用

Spring Cloud Config

配置中心时,这时需要在

bootstrap

配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息;

  • 一些固定的不能被覆盖的属性
  • 一些加密/解密的场景;

——————————————————————————————

  • 提问:Spring Boot 的配置文件有哪几种格式?它们有什么区别?

    .properties 和 .yml,它们的区别主要是书写格式不同。

1).properties
app.user.name = javastack

2).yml
app:
  user:
    name: javastack
           

另外,.yml 格式不支持 @PropertySource 注解导入配置。

——————————————————————————————

  • 提问:Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

    启动类上面的注解是

    @SpringBootApplication

    ,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:

    @SpringBootConfiguration

    :组合了 @Configuration 注解,实现配置文件的功能。

    @EnableAutoConfiguration

    :打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。

    @ComponentScan

    :Spring组件扫描。

——————————————————————————————

  • 提问:开启 Spring Boot 特性有哪几种方式?

    1)继承spring-boot-starter-parent项目

    2)导入spring-boot-dependencies项目依赖

    具体请参考这篇文章《Spring Boot开启的2种方式》。

——————————————————————————————

  • 提问:Spring Boot 需要独立的容器运行吗?

    可以不需要,内置了 Tomcat/ Jetty 等容器。

——————————————————————————————

  • 提问:运行 Spring Boot 有哪几种方式?

    1)打包用命令或者放到容器中运行

    2)用 Maven/ Gradle 插件运行

    3)直接执行 main 方法运行

——————————————————————————————

  • 提问:Spring Boot 自动配置原理是什么?

    注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自动配置的核心,首先它得是一个配置文件,其次根据类路径下是否有这个类去自动配置。

    具体看这篇文章《Spring Boot自动配置原理、实战》。

——————————————————————————————

  • 提问:Spring Boot 的目录结构是怎样的?
cn
 +- javastack
     +- MyApplication.java
     |
     +- customer
     |   +- Customer.java
     |   +- CustomerController.java
     |   +- CustomerService.java
     |   +- CustomerRepository.java
     |
     +- order
         +- Order.java
         +- OrderController.java
         +- OrderService.java
         +- OrderRepository.java
           

这个目录结构是主流及推荐的做法,而在主入口类上加上

@SpringBootApplication

注解来开启 Spring Boot 的各项能力,如自动配置、组件扫描等。具体看这篇文章《Spring Boot 主类及目录结构介绍》。

——————————————————————————————

  • 提问:你如何理解 Spring Boot 中的 Starters?

    Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA 访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。

    Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。

——————————————————————————————

  • 提问:如何在 Spring Boot 启动的时候运行一些特定的代码?

    可以实现接口 ApplicationRunner 或者 CommandLineRunner,这两个接口实现方式一样,它们都只提供了一个 run 方法,具体请看这篇文章《Spring Boot Runner启动器》。

——————————————————————————————

  • 提问:Spring Boot 有哪几种读取配置的方式?

    Spring Boot 可以通过 @PropertySource,@Value,@Environment, @ConfigurationProperties 来绑定变量,具体请看这篇文章《Spring Boot读取配置的几种方式》。

——————————————————————————————

  • 提问:Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?

    Spring Boot 支持 Java Util Logging, Log4j2, Lockback 作为日志框架,如果你使用 Starters 启动器,Spring Boot 将使用 Logback 作为默认日志框架,具体请看这篇文章《Spring Boot日志集成》。

——————————————————————————————

  • 提问:SpringBoot 实现热部署有哪几种方式?

    主要有两种方式:

Spring Loaded

Spring-boot-devtools

Spring-boot-devtools 使用方式可以参考这篇文章《Spring Boot实现热部署》。

——————————————————————————————

  • 提问:你如何理解 Spring Boot 配置加载顺序?

    在 Spring Boot 里面,可以使用以下几种方式来加载配置。

    1)properties文件;

    2)YAML文件;

    3)系统环境变量;

    4)命令行参数;

    等等……

    具体请看这篇文章《Spring Boot 配置加载顺序详解》。

——————————————————————————————

  • 提问:Spring Boot 如何定义多套不同环境配置?

    提供多套配置文件,如:

    applcation.properties

    application-dev.properties

    application-test.properties

    application-prod.properties

运行时指定具体的配置文件,具体请看这篇文章《Spring Boot Profile 不同环境配置》。

——————————————————————————————

  • 提问:Spring Boot 可以兼容老 Spring 项目吗,如何做?

    可以兼容,使用 @ImportResource 注解导入老 Spring 项目配置文件。

——————————————————————————————

  • 提问:保护 Spring Boot 应用有哪些方法?

在生产中使用HTTPS

使用Snyk检查你的依赖关系

升级到最新版本

启用CSRF保护

使用内容安全策略防止XSS攻击

更多请看这篇文章《10 种保护 Spring Boot 应用的绝佳方法》。

——————————————————————————————

  • 提问:Spring Boot 2.X 有什么新特性?与 1.X 有什么区别?

配置变更

JDK 版本升级

第三方类库升级

响应式 Spring 编程支持

HTTP/2 支持

配置属性绑定

更多改进与加强…

——————————————————————————————

  • 提问:Spring和Spring Boot有什么区别?

Spring Framework提供了多种功能,使Web应用程序的开发更加容易。这些功能包括依赖注入,数据绑定,面向方面的编程,数据访问等等。

多年来,Spring一直在变得越来越复杂,这样的应用程序所需的配置量可能会令人生畏。这就是Spring Boot派上用场的地方 - 它使配置Spring应用程序变得轻而易举。

从本质上讲,尽管Spring是不受欢迎的, Spring Boot 会对 平台和库有一个看法,让我们快速入门。

以下是Spring Boot带来的两个最重要的好处:

根据在类路径中找到的工件自动配置应用程序

提供生产中应用程序通用的非功能性功能,例如安全性或健康检查

请查看我们的其他教程之一,了解vanilla Spring和Spring Boot之间的详细比较。

——————————————————————————————

  • 提问:我们如何使用Maven设置Spring Boot应用程序?

我们可以像在任何其他库中一样在Maven项目中包含Spring Boot。但是,最好的方法是从 spring-boot-starter-parent 项目继承并声明依赖于Spring Boot启动器。这样做可以让我们的项目重用Spring Boot的默认设置。

继承 spring-boot-starter-parent 项目非常简单 - 我们只需要在 pom.xml中 指定一个 父元素:

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

我们可以在Maven Central找到最新版本的

spring-boot-starter-parent

使用启动父项目很方便,但并不总是可行。 例如,如果我们公司要求所有项目都从标准POM继承,我们就不能依赖Spring Boot的启动父级。

在这种情况下,我们仍然可以通过此

POM

元素获得依赖关系管理的好处:

<dependencyManagement> 
  <dependencies>
     <dependency> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-dependencies</artifactId> 
       <version>2.1.1.RELEASE</version> 
       <type>pom</type>
       <scope>import</scope> 
   </dependency> 
  </dependencies>
</dependencyManagement>
           

最后,我们可以为Spring Boot启动器添加一些依赖项,然后我们就可以了。

——————————————————————————————

  • 提问:有什么Spring Boot启动器可供选择吗?

依赖管理是任何项目的关键方面。当一个项目足够复杂时,管理依赖项可能会变成一场噩梦,因为涉及太多的工件。

这就是Spring Boot入门者派上用场的地方。每个入门者都可以作为我们所需的所有Spring技术的一站式服务。然后,以一致的方式传递和管理其他所需的依赖关系。

所有启动器都在

org.springframework.boot

组下,其名称以

spring-boot-starter-

开头 。 这种命名模式使得查找启动器变得很容易,尤其是在使用支持按名称搜索依赖关系的IDE时。

在撰写本文时,我们有超过50名初学者。最常用的是:

spring-boot-starter

: 核心启动器,包括自动配置支持,日志记录和YAML

spring-boot-starter-aop

: 使用Spring AOP和AspectJ进行面向方面编程的初学者

spring-boot-starter-data-jpa

: 使用Spring Data JPA和Hibernate的启动器

spring-boot-starter-jdbc

: 用于将JDBC与HikariCP连接池一起使用的启动器

spring-boot-starter-security

: 使用Spring Security的启动器

spring-boot-starter-test

: 用于测试Spring Boot应用程序的启动器

spring-boot-starter-web

: 使用Spring MVC构建Web的启动器,包括RESTful应用程序

有关启动器的完整列表,请参阅此存储库。

要查找有关Spring Boot启动器的更多信息,请查看Spring启动器简介。

——————————————————————————————

  • 提问:如何禁用特定的自动配置?

如果我们要禁用特定的自动配置,我们可以使用

@EnableAutoConfiguration

批注的

exclude

属性来指示它。例如,此代码段中和了

DataSourceAutoConfiguration

// other annotations @EnableAutoConfiguration (exclude = DataSourceAutoConfiguration. class ) 
public class MyConfiguration { }
           

如果我们使用

@SpringBootApplication

注释启用自动配置- 它具有

@EnableAutoConfiguration

作为元注释 - 我们可以使用相同名称的属性禁用自动配置:

// other annotations @SpringBootApplication (exclude = DataSourceAutoConfiguration. class ) 
public class MyConfiguration { }
           

我们还可以使用

spring.autoconfigure.exclude

环境属性禁用自动配置。

application.properties

文件中的此设置与以前相同:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
           

——————————————————————————————

  • 提问:如何注册自定义自动配置?

要注册自动配置类,我们必须在

META-INF/spring.factories

文件的

_EnableAutoConfiguration

_key

下列出其完全限定名称:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.baeldung.autoconfigure.CustomAutoConfiguration
           

如果我们使用Maven构建一个项目,那么该文件应放在

resources/META-INF

目录中。

——————————————————————————————

  • 提问:如何告诉自动配置在bean存在时退回?

要指示自动配置类在bean已经存在时退出,我们可以使用

@ConditionalOnMissingBean

注解。

此注解的最显着属性是:

value

: 要检查的bean类型

name

: 要检查的bean的名称

放置在使用

@Bean

装饰的方法上时 ,目标类型默认为方法的返回类型:

@Configuration 
public class CustomConfiguration { 
    @Bean 
    @ConditionalOnMissingBean 
    public CustomService service() { 
    ... 
    } 
}
           

——————————————————————————————

  • 提问:如何将Spring Boot Web应用程序部署为JAR和WAR文件?

传统上,我们将Web应用程序打包为WAR文件,然后将其部署到外部服务器中。这样做可以让我们在同一台服务器上安排多个应用程序。在CPU和内存稀缺的时候,这是节省资源的好方法。

但事情发生了变化。现在计算机硬件相当便宜,并且注意力转向服务器配置。在部署期间配置服务器的一个小错误可能会导致灾难性后果。

Spring通过提供一个插件即

spring-boot-maven-plugin

来解决这个问题,将Web应用程序打包为可执行的JAR 。要包含此插件,只需向

pom.xml

添加一个plugin元素:

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

有了这个插件,我们将在执行 package 阶段后得到一个fat JAR 。此JAR包含所有必需的依赖项,包括嵌入式服务器。因此,我们不再需要担心配置外部服务器。

然后我们可以像运行普通的可执行JAR一样运行应用程序。

请注意,必须将

pom.xml

文件中的

packaging

元素设置为

jar

才能构建JAR文件:

<packaging>jar</packaging>

如果我们不包含这个元素,它也默认为 jar 。

如果我们想要构建WAR文件,请将packing元素更改为

ar

<packaging>war</packaging>

并将容器依赖关系从打包文件中删除:

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

执行Maven package阶段后,我们将拥有一个可部署的WAR文件。

——————————————————————————————

  • 提问:如何将Spring Boot用于命令行应用程序?

与任何其他Java程序一样,Spring Boot命令行应用程序必须具有 main 方法。此方法用作入口点,它调用

SpringApplication#run

方法来引导应用程序:

@SpringBootApplication 
public class MyApplication { 
    public static void main(String[] args) { 
        SpringApplication.run(MyApplication. class ); 
        // other statements 
        } 
}
           

然后 SpringApplication 类启动一个Spring容器并自动配置bean。

请注意,我们必须将配置类传递给

run

方法才能作为主要配置源。按照惯例,这个参数就是入门类本身。

在调用

run

方法之后,我们可以像在常规程序中那样执行其他语句。

——————————————————————————————

  • 提问:有哪些可能的外部配置来源?

Spring Boot支持外部配置,允许我们在各种环境中运行相同的应用程序。我们可以使用属性文件,YAML文件,环境变量,系统属性和命令行选项参数来指定配置属性。

然后,我们可以访问使用这些属性

@Value

注释,经由绑定对象

@ConfigurationProperties

注解,或 环境 抽象。

以下是最常见的外部配置来源:

命令行属性:命令行选项参数是以双连字符开头的程序参数,例如

-server.port = 8080

。Spring Boot将所有参数转换为属性,并将它们添加到环境属性集中。

应用程序属性:应用程序属性是从

application.properties

文件或其YAML对应文件加载的属性。默认情况下,Spring Boot会在当前目录,类路径根或其 config 子目录中搜索此文件。

特定于配置文件的属性:特定的配置文件的属性从

application- {profile} .properties

文件或其YAML对应文件加载。这些文件与非特定属性文件位于相同位置,并且优先于非特定属性文件。

——————————————————————————————

  • 提问:Spring Boot支持relaxed binding是什么意思?

Spring Boot中的relaxed binding适用于配置属性的类型安全绑定。

使用relaxed binding时,环境属性的键不需要与属性名称完全匹配。这样的环境属性可以用

camelCase

kebab-case

snake_case

或大写字母写成,单词用下划线分隔。

例如,如果带有

@ConfigurationProperties

批注的bean类中的属性名为 myProp ,则可以将其绑定到以下任何环境属性:

myProp

my-prop

my_prop

MY_PROP

——————————————————————————————

  • 提问:什么是Spring Boot DevTools?

Spring Boot Developer Tools或DevTools是一组工具,使开发过程更容易。要包含这些开发时功能,我们只需要在 pom.xml 文件中添加依赖项:

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

Spring Boot DevTools在生产运行模块将自动禁用。

默认情况下,重新打包存档也会排除此模块。因此,它不会给生产环境带来任何开销。

默认情况下,DevTools应用适合开发环境的属性。

这些属性禁用模板缓存,为Web组启用调试日志记录,等等。

因此,我们拥有这种合理的开发时配置,而无需设置任何属性。

只要类路径上的文件发生更改,使用DevTools的应用程序就会重新启动。

这是开发中非常有用的功能,因为它可以快速反馈修改。

默认情况下,静态资源(包括视图模板)不会启动重新启动。

相反,资源更改会触发浏览器刷新。请注意,只有在浏览器中安装

LiveReload

扩展以与

DevTools

包含的嵌入式

LiveReload

服务器进行交互时,才会发生这种情况。

有关此主题的更多信息,请参阅

Spring Boot DevTools

概述。

——————————————————————————————

  • 提问:如何编写集成测试?

在为Spring应用程序运行集成测试时,我们必须有一个

ApplicationContext

为了让我们的生活更轻松,Spring Boot为测试提供了一个特殊的注释

@SpringBootTest

。此注解从其 classes 属性指示的配置类创建

ApplicationContext

如果未设置 classes 属性,Spring Boot将搜索主配置类。 搜索从包含测试的包开始,直到找到使用

@SpringBootApplication

@SpringBootConfiguration

注释的类。

请注意,如果我们使用

JUnit 4

,我们必须使用

@RunWith(SpringRunner.class)

装饰测试类。

有关详细说明,请查看我们的Spring Boot测试教程。

——————————————————————————————

  • 提问:什么是Spring Boot Actuator?

从本质上讲,Actuator通过支持生产就绪功能让Spring Boot应用跑起来。这些功能使我们能够在生产环境运行时监控和管理应用程序。

将Spring Boot Actuator集成到一个项目中非常简单。我们需要做的就是在

pom.xml

文件中包含

spring-boot-starter-actuator

启动器:

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

Spring Boot Actuator可以使用HTTP或JMX公开操作。但是大多数应用程序都使用HTTP,其中端点的标识为 /执行器前缀形成的URL路径。

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

——————————————————————————————

附:

Spring问题汇总 (on IDEA MAC)

https://blog.csdn.net/weixin_42915286/article/details/85017091

课程内容:

  • 1.核心特性
  • 2.Web应用
  • 3.数据相关
  • 4.功能扩展
  • 5.运维管理

分成两篇:核心技术+生态整合

核心技术关注:SpringBoot和Spring Framework/SpringEE规范之间的联系;

生态整合关注:JavaEE;其中运维整合较难理解,此部分和以往JavaEE不太相关;

技术储备要求:

1.语言:JAVA8

2.框架:Spring Framework 基础熟练

3.运用:SpringBoot基础

【框架】Spring Boot 2.0 介绍 + 问题汇总(包括:异步非阻塞)(未完结)

这里有几个问题:

1.SpringBoot是如何基于Spring Framework逐步走向自动装配?

2.SpringApplication是如何掌控Spring应用生命周期?

3.SpringBoot外部化配置与SpringEnvironment抽象之间是什么关系?

4.SpringWebMVC向Spring Reactive WebFlux过渡地真实价值和意义?

建议:

想学好SpringBoot或JAVA,多写API,少用自动化的工具。终身受益。

——————————————————————————————-——

Web应用

Spring Web Flux 应用 (Spring5开始支持,对Servlet补充)

我们知道传统的Web框架,比如说:

struts2

springmvc

等 都是基于

Servlet API

Servlet容器

基础之上运行的,在Servlet3.1之后才有了异步非阻塞的支持。

而WebFlux是一个典型非阻塞异步的框架,它的核心是基于

Reactor

相关API

实现的。

相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上,因此它的运行环境的可选择行要比传统web框架多的多。

根据官方的说法,webflux主要在如下两方面体现出独有的优势:

1)非阻塞式

其实在servlet3.1提供了非阻塞的API,WebFlux提供了一种比其更完美的解决方案。使用非阻塞的方式可以利用较小的线程或硬件资源来处理并发进而提高其可伸缩性;

  1. 函数式编程端点

    老生常谈的编程方式了,Spring5必须让你使用java8,那么函数式编程就是java8重要的特点之一,而WebFlux支持函数式编程来定义路由端点处理请求。

  • Reactor基础:Java Lambda、Mono、Flux
  • Web Flux核心:Web MVC注解(

    @Controller @RequestMapping ...

    )、函数式声明(

    RouterFunction

    )、异步非阻塞(

    Servlet 3.1+``Netty Reactor

  • 使用场景:页面渲染、REST应用;Web Flux优势和限制

blog.ippon.tech 了解下

Web Server 应用

  • 切换Web Server,比如Tomcat与Jetty的切换,或不用Server;
  • 自定义Servlet Web Server
  • 自定义Reactive Web Server

SpringBoot易学:

  • 组建自动装配:规约大于配置,专注核心业务
  • 外部化配置:一次构建、按需配置、到处运行
  • 嵌入式容器:内置容器、无需部署、独立运行
  • Spring Boot Starter:简化依赖、按需装配、自我包含
  • Production-Ready:一站式运维、生态无缝整合

SpringBoot难静:

  • 组建自动装配:模式注解、@Enable模块、条件装配、加载机制
  • 外部化配置:Environment抽象、生命周期、破坏性变更
  • 嵌入式容器:Servlet Web容器、Reactive Web容器
  • Spring Boot Starter:依赖管理、装配条件、装配顺序
  • Production-Ready:健康检查、数据指标、@Endpoint管控

1.核心特性

SpringBoot三大特性:

组建自动装配:WebMVC、WebFlux、JDBC等

嵌入式Web容器:Tomcat、Jetty、Undertow

生产准备特性:指标、健康检查、外部化配置等

组建自动装配

  • 1.激活:

    @EnableAutoConfiguration

  • 2.配置:

    /META-INF/spring.factories

  • 3.实现:

    XXXAutoConfiguration

start.spring.io

【框架】Spring Boot 2.0 介绍 + 问题汇总(包括:异步非阻塞)(未完结)

下好后,导入IDE中:

注意!导入时的路径不要随便放在桌面或其他地方,放在正式仓库文件夹为好;

————————————————

1.激活

官网查看SampleController可知

SpringBootController中比SpringMVC中多了一句

@EnableAutoConfiguration

一旦加上就启动了SpringBoot

但实际上项目中的注解是

@SpringBootApplication

它包括了

@EnableAutoConfiguration

2.配置:

/META-INF/spring.factories

项目中其实有很多同名文件,如:

【框架】Spring Boot 2.0 介绍 + 问题汇总(包括:异步非阻塞)(未完结)

3.实现:

XXXAutoConfiguration

【框架】Spring Boot 2.0 介绍 + 问题汇总(包括:异步非阻塞)(未完结)

从这里看得出来,enableConfiguration可以作为一个键,实现很多value装配

所以SB启动时,可以启动很多BEAN。

————————————————————————————————

Web应用

传统Servlet应用

Spring自定义操作方式,结合Servlet规范;

目录:

  • *.依赖;
  • 1.Servlet组件:Servlet、Filter、Listener
  • 2.Servlet注册:Servlet注解、Spring Bean、RegistrationBean
  • 3.异步非阻塞(重要):异步Servlet、非阻塞Servlet

    —————————————————————

    ** *.依赖 **

传统的Servlet应用使用依赖如下:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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>
           

其实就是spring-boot-starter分成了多个模块,如-web、-test;

综上所见,可以发现

<groupId>

都是固定的:org.springframework.boot

<artifactId>

前缀都是固定的:spring-boot-starter。。。

把 artifactid: spring-boot-starter-web加入POM后,发现MavenProjects发生了变化:

BEFORE:

【框架】Spring Boot 2.0 介绍 + 问题汇总(包括:异步非阻塞)(未完结)

AFTER:新增了一条

【框架】Spring Boot 2.0 介绍 + 问题汇总(包括:异步非阻塞)(未完结)

运行后:

【框架】Spring Boot 2.0 介绍 + 问题汇总(包括:异步非阻塞)(未完结)

明显,此时的容器就为Tomcat。

此时访问下

Localhost:8080

:出现白页错误404警告,因为无映射;

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Wed Feb 06 21:28:52 CST 2019
There was an unexpected error (type=Not Found, status=404).
No message available
           

—————————————————————

1.Servlet组件: Servlet、Filter、Listener

新建

web/servlet/MyServlet.java

Servlet

1).实现

  • @WebServlet

  • extends

    HttpServlet

  • 注册

    2).URL 映射(这样写适用于浏览器,无法让程序识别)
  • @WebServlet(urlPatterns = "/my/servlet")

    3).注册 (在此包名下搜索所有组件)
  • @ServletComponentScan(basePackages = "com.example.springboot.web.servlet")

    Filter

    Listener

MyServlet.java

@WebServlet(urlPatterns = "/my/servlet")   //这里实现映射(到浏览器访问)

public class MyServlet extends HttpServlet {    //实现此接口(因他是Servlet3.0的规范)

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().println("OKKKKKKKK");
    }

}

           

—————————————————————

2. Servlet注册:(3.0) : 1).Servlet注解、2).Spring Bean、3).RegistrationBean

1).Servlet 注解

@ServletComponentScan +(使用他,扫描上面servlet中所有的组件)

  • @WebServlet
  • @WebFilter
  • @WebListener

2).Spring Bean

@Bean +

  • Servlet
  • Filter
  • Listener

3).RegistrationBean

  • ServletRegistrationBean
  • FilterRegistrationBean
  • ServletListenerRegistrationBean

这里先使用1).1).Servlet 注解 @ServletComponentScan +

Application.java

@SpringBootApplication
@ServletComponentScan(basePackages = "com.example.springboot.web.servlet")
public class Application {

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

}
           

此时访问localhost.com/8080/my/sevlet,即可看到输出语句

OKKKKKKKK

———————————————————

异步非阻塞(重要):两个方面,异步Servlet 和 非阻塞Servlet

注:同步,异步 (asynchronous),阻塞,非阻塞:

同步异步是数据通信的方式,阻塞和非阻塞是一种状态。

比如同步这种数据通讯方式里面可以有阻塞状态也可以有非阻塞状态。从另外一个角度理解同步和异步,就是如果一个线程干完的事情都是同步,有线程切换才能干完的事情就是异步。

异步 Servlet (3.0)

  • javax.servlet.ServletRequest#startAsync()

  • javax.servlet.AsyncContext

    非阻塞 Servlet (3.1)
  • javax.servlet.ServletInputStream#setReadListener

  • javax.servlet.ReadListener

  • javax.servlet.ServletOutputStream#setWriteListener

  • javax.servlet.WriteListener

在MyServlet.java中

doGet()

内 添加异步上下文条件语句:

AsyncContext asyncContext = request.startAsync();

和添加操作语句:

asyncContext.start(()->{ });

把已写代码

response.getWriter().println("OKKKKKKKK");

挪入操作语句中;

.getWriter

还报错,把他try catch,暂不加日志说明;

(不可用)
@WebServlet(urlPatterns = "/my/servlet")
public class MyServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        AsyncContext asyncContext = request.startAsync();
        asyncContext.start(()->{
            try {
                response.getWriter().println("OKKKKKKKK");
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
}
           

重启访问

Localhost.com/8080/my/servlet

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu Feb 07 00:43:56 CST 2019
There was an unexpected error (type=Internal Server Error, status=500).
A filter or servlet of the current chain does not support asynchronous operations.
           

A filter or servlet of the current chain does not support asynchronous operations.

查看

WebServlet.class

源码可知:

boolean asyncSupported() default false;

于是需要在

@WebServlet

后注明

true

(非最终版)
@WebServlet(urlPatterns = "/my/servlet",asyncSupported=true)
public class MyServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        AsyncContext asyncContext = request.startAsync();
        asyncContext.start(()->{
            try {
                response.getWriter().println("OKKKKKKKK");
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
}
           

此时浏览器访问链接,速度慢到难以忍受,报错超时:

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu Feb 07 01:17:29 CST 2019
There was an unexpected error (type=Internal Server Error, status=500).
No message available
           

原因是异步与同步处理有区别,(方法内)结尾必须告诉IDE已经完结;

需要添加触发完成,加上

asyncContext.complete();

;(重要!!!)

(非最终版)
@WebServlet(urlPatterns = "/my/servlet",asyncSupported=true)

public class MyServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        AsyncContext asyncContext = request.startAsync();
        asyncContext.start(()->{
            try {
                response.getWriter().println("OKKKKKKKK");
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        asyncContext.complete();
    }

}
           

浏览器不报错了,显示空白;

如果把触发完成移步到打印的"OKKKKKKKK"后,浏览器即可显示输出这句话。

@WebServlet(urlPatterns = "/my/servlet",asyncSupported=true)

public class MyServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        AsyncContext asyncContext = request.startAsync();
        asyncContext.start(()->{
            try {
                response.getWriter().println("OKKKKKKKK");
                asyncContext.complete();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
}
           

异步非阻塞比同步操作麻烦很多,极容易遇坑,需要注意的问题之后再讨论;

此部分完结。

————————————————————————————————

Spring Web MVC 应用

目录:

  • 1. Web MVC 视图:模版引擎、内容协商、异常处理等;
  • 2. Web MVC REST:(JSON、XML为例)资源服务、资源跨域、服务发现等;
  • 3. Web MVC 核心:核心架构、处理流程、核心组件。

1. Web MVC 视图

  • ViewResolver
  • View

1).模板引擎:渲染

  • Thymeleaf
  • Freemarker
  • JSP

2).内容协商: 多种模版引擎时,内容协商帮助选择最佳匹配的模版引擎

  • ContentNegotiationConfigurer
  • ContentNegotiationStrategy
  • ContentNegotiatingViewResolver

3).异常处理

  • @ExceptionHandler
  • HandlerExceptionResolver
    • ExceptionHandlerExceptionResolver
  • BasicErrorController (Spring Boot) :生成白页

————————————————————————————————

2. Web MVC REST

资源服务

  • @RequestMapping :请求映射
    • @GetMapping
  • @ResponseBody
  • @RequestBody (少用)

资源跨域

  • CrossOrigin
  • WebMvcConfigurer#addCorsMappings
  • 传统解决方案(浏览器中不推荐)
    • IFrame
    • JSONP

服务发现

  • HATEOS

————————————————————————————————

3. Web MVC 核心

  • 核心架构
  • 处理流程
  • 核心组件
    • DispatcherServlet (主要)
    • HandlerMapping
    • HandlerAdapter
    • ViewResolver

————————————————————————————————

Spring Web Flux 应用

————————————————

Reactor 基础

  • Java Lambda (Reactor的基础)
  • Mono(核心接口之一)
  • Flux(核心接口之一)

    ————————————————

    Web Flux 核心 (可与SpringMVC兼容)

1).Web MVC 注解兼容

  • @Controller
  • @RequestMapping
  • @ResponseBody
  • @RequestBody

2).函数式声明

  • RouterFunction (路由器函数)

3).异步非阻塞

  • Servlet 3.1 +
  • Netty Reactor

    ————————————————

    使用场景(与SpringMVC没什么区别)

  • 页面渲染 (视图应用)
  • REST 应用
  • 性能测试

    http://blog.ippon.tech/spring-5-webflux-performance-tests/

    ————————————————————————————————

Web Server 应用

切换 Web Server

1).切换其他 Servlet 容器

  • Tomcat -> Jetty
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Exclude the Tomcat dependency -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
           

2).替换 Servlet 容器

  • WebFlux
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Exclude the Tomcat dependency -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-web</artifactId>-->
<!--<exclusions>-->
<!--&lt;!&ndash; Exclude the Tomcat dependency &ndash;&gt;-->
<!--<exclusion>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-tomcat</artifactId>-->
<!--</exclusion>-->
<!--</exclusions>-->
<!--</dependency>-->
<!--&lt;!&ndash; Use Jetty instead &ndash;&gt;-->
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-jetty</artifactId>-->
<!--</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
           

3).自定义 Servlet Web Server

  • WebServerFactoryCustomizer

4).自定义 Reactive Web Server

  • ReactiveWebServerFactoryCustomizer

————————————————————————————————

数据相关

1.关系型数据

JDBC

1).依赖

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

2).数据源

  • javax.sql.DataSource
  • JdbcTemplate

    3).自动装配

  • DataSourceAutoConfiguration

继续阅读