1.1什么是Spring

Spring的核心是提供了一个容器(container),通常称为Spring应用上下文(Spring application context),它们会创建和管理应用组件。这些组件也可以称为bean,会在Spring应用上下文中装配在一起,从而形成一个完整的应用程序。这就像砖块、砂浆、木材、管道和电线组合在一起,形成一栋房子似的。
将bean装配在一起的行为是通过一种基于依赖注入(dependency injection,DI)的模式实现的。此时,组件不会再去创建它所依赖的组件并管理它们的生命周期,使用依赖注入的应用依赖于单独的实体(容器)来创建和维护所有的组件,并将其注入到需要它们的bean中。通常,这是通过构造器参数和属性访问方法来实现的。

在Spring技术中,自动配置起源于所谓的自动装配(autowiring)和组件扫描(component scanning)。借助组件扫描技术,Spring能够自动发现应用类路径下的组件,并将它们创建成Spring应用上下文中的bean。借助自动装配技术,Spring能够自动为组件注入它们所依赖的其他bean。
最近,随着Spring Boot的引入,自动配置的能力已经远远超出了组件扫描和自动装配。Spring Boot是Spring框架的扩展,提供了很多增强生产效率的方法。最为大家所熟知的增强方法就是自动配置(autoconfiguration),Spring Boot能够基于类路径中的条目、环境变量和其他因素合理猜测需要配置的组件并将它们装配在一起。 

1.2 使用Spring Tool Suite初始化Spring项目

spring出版社word模板_spring

spring出版社word模板_后端_02

spring出版社word模板_后端_03

你可能已经看出来了,这就是一个典型的Maven或Gradle项目结构,其中应用的源码放到了“src/main/java”中,测试代码放到了“src/test/java”中,而非Java的资源放到了“src/main/resources”。在这个项目结构中,我们需要注意以下几点。

mvnw和mvnw.cmd:这是Maven包装器(wrapper)脚本。借助这些脚本,即便你的机器上没有安装Maven,也可以构建项目。
pom.xml:这是Maven构建规范,随后我们将会深入介绍该文件。
TacoCloudApplication.java:这是Spring Boot主类,它会启动该项目。随后,我们会详细介绍这个类。
application.properties:这个文件起初是空的,但是它为我们提供了指定配置属性的地方。在本章中,我们会稍微修改一下这个文件,但是我会将配置属性的详细阐述放到第5章。
static:在这个文件夹下,你可以存放任意为浏览器提供服务的静态内容(图片、样式表、JavaScript等),该文件夹初始为空。
templates:这个文件夹中存放用来渲染内容到浏览器的模板文件。这个文件夹初始是空的,不过我们很快就会往里面添加Thymeleaf模板。
TacoCloudApplicationTests.java:这是一个简单的测试类,它能确保Spring应用上下文可以成功加载。在开发应用的过程中,我们会将更多的测试添加进来。 

<?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>sia</groupId>
  <artifactId>taco-cloud</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>           ⇽--- 打包为JAR

  <name>taco-cloud</name>
  <description>Taco Cloud Example</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.4.RELEASE</version>                    ⇽--- Spring Boot的版本
    <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>                         ⇽--- Starter依赖
      <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-devtools</artifactId>
      <scope>runtime</scope>
    </dependency>

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

    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
        <scope>test</scope>
    </dependency>

     <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>htmlunit-driver</artifactId>
        <scope>test</scope>
      </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>                           ⇽--- Spring Boot插件
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>

这是创建之后的maven文件,请留意<parent>元素,更具体来说是它的<version>子元素。这表明我们的项目要以spring-boot-starter-parent作为其父POM。除了其他的一些功能之外,这个父POM为Spring项目常用的一些库提供了依赖管理,现在你不需要指定它们的版本,因为这是通过父POM来管理的。这里的2.0.4.RELEASE表明要使用Spring Boot 2.0.4,所以会根据这个版本的Spring Boot定义来继承依赖管理。
既然我们谈到了依赖的话题,那么需要注意在<dependencies>元素下声明了 3 个依赖。你可能也会注意到这 3 个依赖的artifact ID上都有starter这个单词。Spring Boot starter依赖的特别之处在于它们本身并不包含库代码,而是传递性地拉取其他的库。这种starter依赖主要有3个好处。
构建文件会显著减小并且更易于管理,因为这样不必为每个所需的依赖库都声明依赖。
我们能够根据它们所提供的功能来思考依赖,而不是根据库的名称。如果是开发Web应用,那么你只需要添加web starter就可以了,而不必添加一堆单独的库再编写Web应用。
我们不必再担心库版本的问题。你可以直接相信给定版本的Spring Boot,传递性引入的库的版本是兼容的。现在,你只需要关心使用的是哪个版本的Spring Boot就可以了。

package tacos;

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

@SpringBootApplication                  ⇽--- Spring Boot应用
public class TacoCloudApplication {

  public static void main(String[] args) {
    SpringApplication.run(TacoCloudApplication.class, args);    ⇽--- 运行应用
  }

}

@SpringBootApplication注解明确表明这是一个Spring Boot应用。但是,@SpringBootApplication远比看上去更强大。
@SpringBootApplication是一个组合注解,它组合了3个其他的注解。
@SpringBootConfiguration:将该类声明为配置类。尽管这个类目前还没有太多的配置,但是后续我们可以按需添加基于Java的Spring框架配置。这个注解实际上是@Configuration注解的特殊形式。
@EnableAutoConfiguration:启用Spring Boot的自动配置。我们随后会介绍自动配置的更多功能。就现在来说,我们只需要知道这个注解会告诉Spring Boot自动配置它认为我们会用到的组件。
@ComponentScan:启用组件扫描。这样我们能够通过像@Component、@Controller、@Service这样的注解声明其他类,Spring会自动发现它们并将它们注册为Spring应用上下文中的组件。

处理Web请求:

Spring自带了一个强大的Web框架,名为Spring MVC。Spring MVC的核心是控制器(controller)的理念。控制器是处理请求并以某种方式进行信息响应的类。在面向浏览器的应用中,控制器会填充可选的数据模型并将请求传递给一个视图,以便于生成返回给浏览器的HTML。

package tacos;

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

@Controller                            ⇽--- 控制器
public class HomeController {

  @GetMapping("/")                    ⇽--- 处理对根路径“/”的请求
  public String home() {
    return "home";         ⇽--- 返回视图名
  }

}

 可以看到,这个类带有@Controller。就其本身而言,@Controller并没有做太多的事情。它的主要目的是让组件扫描将这个类识别为一个组件。因为HomeController带有@Controller,所以Spring的组件扫描功能会自动发现它,并创建一个HomeController实例作为Spring应用上下文中的bean。
实际上,有一些其他的注解与@Controller有着类似的目的(包括@Component、@Service和@Repository)。你可以为HomeController添加上述的任意其他注解,其作用是完全相同的。但是,在这里选择使用@Controller更能描述这个组件在应用中的角色。
home()是一个简单的控制器方法。它带有@GetMapping注解,表明如果针对“/”发送HTTP GET请求,那么这个方法将会处理请求。该方法所做的只是返回String类型的home值。
这个值将会被解析为视图的逻辑名。

spring出版社word模板_spring出版社word模板_04

 在启动之后你会看到一些组件日志,在控制台输出的最后,你将会看到一条Tomcat已经在port(s): 8080 (http)启动的日志,这意味着此时你可以打开Web浏览器并导航至主页,这样就能看到我们的劳动成果了。

了解Spring Boot DevTools

DevTools为Spring开发人员提供了一些便利的开发期工具,其中包括:
代码变更后应用会自动重启;
当面向浏览器的资源(如模板、JavaScript、样式表)等发生变化时,会自动刷新浏览器;
自动禁用模板缓存;
如果使用H2数据库的话,内置了H2控制台。

 应用自动重启:
如果将DevTools作为项目的一部分,那么你可以看到,当对项目中的Java代码和属性文件做出修改后,这些变更稍后就能发挥作用。DevTools会监控变更,当它看到有变化的时候,将会自动重启应用。
更准确地说,当DevTools运行的时候,应用程序会被加载到Java虚拟机(Java virtual Machine,JVM)两个独立的类加载器中。其中一个类加载器会加载你的Java代码、属性文件以及项目中“src/main/”路径下几乎所有的内容。这些条目很可能会经常发生变化。另外一个类加载器会加载依赖的库,这些库不太可能经常发生变化。
当探测到变更的时候,DevTools只会重新加载包含项目代码的类加载器,并重启Spring的应用上下文,在这个过程中另外一个类加载器和JVM会原封不动。这个策略非常精细,但是它能减少应用启动的时间。
这种策略的一个不足之处就是自动重启无法反映依赖项的变化。这是因为包含依赖库的类加载器不会自动重新加载。这意味着每当我们在构建规范中添加、变更或移除依赖的时候,为了让变更生效,我们需要重新启动应用。

浏览器自动刷新和禁用模板缓存:
默认情况下,像Thymeleaf和FreeMarker这样的模板方案在配置时会缓存模板解析的结果。这样的话,在为每个请求提供服务的时候,模板就不用重新解析了。在生产环境中,这是一种很好的方式,因为它会带来一定的性能收益。
但是,在开发期,缓存模板就不太好了。在应用运行的时候,如果缓存模板,那么我们刷新浏览器就无法看到模板变更的效果了。即便我们对模板做了修改,在应用重启之前,缓存的模板依然会有效。
DevTools通过禁用所有模板缓存解决了这个问题。你可以对模板进行任意数量的修改,只需要刷新一下浏览器就能看到结果。
如果你像我这样,连浏览器的刷新按钮都懒得点,那么对代码做出变更之后,马上在浏览器中看到结果就好了。幸运的是,DevTools有一些特殊的功能可以供我们使用。
DevTools在运行的时候,它会和你的应用程序一起,同时自动启动一个LiveReload服务器。LiveReload服务器本身并没有太大的用处。但是,当它与LiveReload浏览器插件结合起来的时候,就能够在模板、图片、样式表、JavaScript等(实际上,几乎涵盖为浏览器提供服务的所有内容)发生变化的时候自动刷新浏览器。
LiveReload有针对Google Chrome、Safari和Firefox的浏览器插件(要对Internet Explorer和Edge粉丝说声抱歉)。请访问LiveReload官网,以了解如何为你的浏览器安装LiveReload。

内置的H2控制台:
虽然我们的项目还没有使用数据库,但是这种情况在第3章中就会发生变化。如果你使用H2数据库进行开发,DevTools将会自动启用H2。这样的话,我们可以通过Web浏览器进行访问。你只需要让浏览器访问http://localhost:8080/h2-console,就能看到应用所使用的数据。
 

本章回顾:

回想一下我们是怎样完成这一切的。简短来说,在构建基于Spring的Taco Cloud应用的过程中,我们执行了如下步骤:
使用Spring Initializr创建初始的项目结构;
编写控制器类处理针对主页的请求;
定义了一个视图模板来渲染主页;
编写了一个简单的测试类来验证工作符合预期。
这些步骤都非常简单直接,对吧?除了初始化应用的第一个步骤之外,我们所做的每一个操作都专注于生成主页的目标。
实际上,我们所编写的每行代码都致力于实现这个目标。除了Java import语句之外,我只能在控制器中找到两行Spring相关的代码,而在视图模板中一行Spring相关的代码都没有。尽管测试类的大部分内容都使用了Spring对测试的支持,但是它在测试的上下文中似乎没有那么具有侵入性。
这是使用Spring进行开发的一个重要收益。你可以只关注满足应用需求的代码,无须考虑如何满足框架的需求。尽管我们偶尔还是需要编写一些框架特定的代码,但是它们通常只占整个代码库很小的一部分。正如我在前文所述,Spring(以及Spring Boot)可以视为感受不到框架的框架(frameworkless framework)。
但是这又是如何运行起来的呢?Spring在幕后做了些什么来保证应用的需求能够得到满足呢?要理解Spring到底做了些什么,我们首先来看一下构建规范。
在pom.xml文件中,我们声明了对Web和Thymeleaf starter的依赖。这两项依赖会传递引入大量其他的依赖,包括:
Spring的MVC框架;
嵌入式的Tomcat;
Thymeleaf和Thymeleaf布局方言;
它还引入了Spring Boot的自动配置库。当应用启动的时候,Spring Boot的自动配置将会探测到这些库,并自动完成如下功能:
在Spring应用上下文中配置bean以启用Spring MVC;
在Spring应用上下文中配置嵌入式的Tomcat服务器;
配置Thymeleaf视图解析器,以便于使用Thymeleaf模板渲染Spring MVC视图。
简而言之,自动配置功能完成了所有的脏活累活,让我们能够集中精力编写实现应用功能的代码。如果你问我对此的观点,那么我认为这是一个很好的安排!

俯瞰Spring风景线:

Spring核心框架:

Spring核心框架:
如你所料,Spring核心框架是Spring领域中一切的基础。它提供了核心容器和依赖注入框架,另外还提供了一些其他重要的特性。
其中有一项是Spring MVC,也就是Spring的Web框架。你已经看到了如何使用Spring MVC来编写控制器类以处理Web请求。但是,你还没看到的是,Spring MVC还能用来创建REST API,以生成非HTML的输出。在第2章中,我们将会更深入地介绍Spring MVC,并在第6章重新学习如何使用它来创建REST API。
Spring核心框架还提供了一些对数据持久化的基础支持,尤其是基于模板的JDBC支持。在第3章中,你将会看到如何使用JdbcTemplate。
在最新版本的Spring中,还添加了对反应式(reactive)风格编程的支持,其中包括名为Spring WebFlux的新反应式Web框架,这个框架大量借鉴了Spring MVC。在第3部分中,我们将会学习Spring反应式编程模型,并在第11章专门学习Spring WebFlux。

 Spring Boot:

我们已经看到了Spring Boot带来的很多收益,包括starter依赖和自动配置。在本书中,我们会尽可能多地使用Spring Boot,并避免任何形式的显式配置,除非显式配置是绝对必要的。除了starter依赖和自动配置,Spring Boot还提供了大量其他有用的特性:
Actuator能够洞察应用运行时的内部工作状况,包括指标、线程dump信息、应用的健康状况以及应用可用的环境属性;灵活的环境属性规范;
在核心框架的测试辅助功能之上提供了对测试的额外支持。
除此之外,Spring Boot还提供了一个基于Groovy脚本的编程模型,称为Spring Boot 命令行接口(Command-Line Interface,CLI)。使用Spring Boot CLI,我们可以将整个应用程序编写为Groovy脚本的集合,并通过命令行运行它们。我们不会花太多时间介绍Spring Boot CLI,但是当它匹配我们的需求时,我们会偶尔提及它。
Spring Boot已经成为Spring开发中不可或缺的一部分,很难想象如果没有它我该如何开发Spring应用程序。因此,本书采用以Spring Boot为核心的视角。当我介绍Spring Boot所做的事情时,你可能会发现我却使用了Spring这个词。

Spring Data 

尽管Spring核心框架提供了基本的数据持久化支持,但是Spring Data提供了非常令人惊叹的功能:将应用程序的数据repository定义为简单的Java接口,在定义驱动存储和检索数据的方法时使用一种命名约定即可。
此外,Spring Data能够处理多种不同类型的数据库,包括关系型数据库(JPA)、文档数据库(Mongo)、图数据库(Neo4j)等。在第3章中,我们将使用Spring Data为Taco Cloud应用程序创建repository。

Spring Security 

应用程序的安全性一直是一个重要的话题,而且正在变得越来越重要。幸运的是,Spring有一个健壮的安全框架,名为Spring Security。
Spring Security解决了应用程序通用的安全性需求,包括身份验证、授权和API安全性。Spring Security的范围太大,在本书中无法得到充分的介绍,但是我们将在第4章和第11章中讨论一些常见的使用场景。

Spring Integration和Spring Batch

从一定程度上来讲,大多数应用程序都需要与其他应用甚至本应用中的其他组件进行集成。在这方面,有一些应用程序集成模式可以解决这些需求。Spring Integration和Spring Batch为基于Spring的应用程序提供了这些模式的实现。
Spring Integration解决了实时集成问题。在实时集成中,数据在可用时马上就会得到处理。相反,Spring Batch解决的则是批处理集成的问题,在此过程中,数据可以收集一段时间,直到某个触发器(可能是一个时间触发器)发出信号,表示该处理批量数据了才会对数据进行批处理。我们将会在第9章中研究Spring Batch和Spring Integration。

Spring Cloud 

在撰写本书的时候,应用程序开发领域正在进入一个新的时代,我们不再将应用程序作为单个部署单元来开发,而是使用由微服务组成的多个独立部署单元来组合形成应用程序。
微服务是一个热门话题,解决了开发期和运行期的一些实际问题。然而,在这样做的过程中,它们也面临着自己所带来的挑战。这些挑战将由Spring Cloud直面解决,Spring Cloud是使用Spring开发云原生应用程序的一组项目。
Spring Cloud覆盖了很多领域,本书不可能面面俱到,我们将在第13~15章中研究Spring Cloud的一些常见组件。要更全面地研究Spring Cloud,我建议阅读John Carnell的Spring Microservices in Action一书(Manning,2017)。

本章知识点总结

  1. 什么是spring

spring是一个容器,通常被称为spring应用上下文,它会创建和管理组件,这些组件也被称为bean,会在spring应用中基于“依赖注入”将bean装配再一起,之后spring不会去创建bean所依赖的组件和它们的生命周期,使用“依赖注入”bean依赖单独的实体(容器),通常使用属性和构造方法实现

2.SpringBootApplication注解

SpringbootApplication是一个组合注解,一共包含三个注解

  • SpringbootConfiguration:声明此类是配置类
  • EnbleAutoConfiguration:启动Springboot的自动装配
  • ComponentScan:启动组件扫描,@Controller,@Service,@Repository,@Component,在扫描到需要装配的类自动装配到Spring容器中

3.Configuration和SpringbootConfiguration的区别

两者功能一致,Configuration是Spring注解,而SpringbootConfiguration是Springboot注解 

SpringBootConfiguration 可以作为 Spring 标准中 @Configuration 注解的替代。SpringBoot 项目中推荐使用@SpringBootConfiguration 替代 @Configuration。

4.pom的srarter的依赖

不用担心库的版本问题,我们只需要给定一个Springboot版本即可,它会自动拉取在当前场景可能需要的依赖,并且版本兼容,Springboot会自动扫描要加载的信息并开启默认配置,这些statrer都遵循着“约定大于配置”的约定并允许我们进行修改

Spring旨在简化开发人员所面临的挑战,比如创建Web应用程序、处理数据库、保护应用程序以及实现微服务。 Spring Boot构建在Spring之上,通过简化依赖管理、自动配置和运行时洞察,使Spring更加易用。
Spring应用程序可以使用Spring Initializr进行初始化。Spring Initializr是基于Web的应用,并且为大多数Java开发环境提供了原生支持。
在Spring应用上下文中,组件(通常称为bean)既可以使用Java或XML显式声明,也可以通过组件扫描发现,还可以使用Spring Boot自动配置功能实现自动化配置。