Spring Boot并不重复“造轮子”

2.1 Spring Boot简介

Spring Boot是由Pivotal团队提供的基于Spring的全新框架,其设计目的是简化Spring应用的搭建和开发过程。该框架遵循“约定大于配置”原则,采用特定的方式进行配置,从而使开发者无须进行大量的XML配置。Spring Boot致力于成为蓬勃发展的快速应用开发领域的领导者。html

Spring Boot并不重复“造轮子”,而是在原有Spring框架的基础上进行封装,而且它集成了一些类库,用于简化开发。换句话说,Spring Boot就是一个大容器。java

关于Spring Boot,其官网是这样描述的:web

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.spring

We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration.数据库

从上面的描述中,咱们能够了解到,Spring Boot带给了咱们全新的应用部署方案,经过它能够很方便地建立独立的、生产级的基于Spring的应用程序。同时,经过Spring平台和第三方库能够轻松构建视图。apache

其实,Spring Boot默认集成了Tomcat,所以咱们能够只编译成jar包,经过Java命令启动应用,大多数Spring Boot应用程序只须要不多的Spring配置。json

2.2 第一个Spring Boot工程

本节中,咱们将建立第一个Spring Boot工程,读者能够按照下面的步骤进行操做。api

(1) 打开IntelliJ IDEA,依次点击File→New→Module,在弹出的对话框中选择Maven,并点击Next按钮,建立一个Maven项目。这里咱们在ArtifactId一栏中输入demo-lesson-one,在GroupId一栏中输入com.lynn.boot。建立好工程后,为pom.xml增长如下内容:浏览器

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

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
复制代码

其中,标签声明了Spring Boot的父项目,版本号定义为2.0.3.RELEASE。咱们还能够注意到,标签中声明了spring-boot-starter-web依赖,它提供了对Spring MVC的支持。tomcat

(2) 编写应用启动类Application:

package com.lynn.boot;

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);
    }
}
复制代码

Spring Boot的强大之处在于能够直接经过main方法启动Web应用程序。在上述代码中,咱们提供了应用程序的入口,经过调用SpringApplication.run()来启动内置Web容器。咱们注意到,在Application类中添加了@SpringBootApplication注解,咱们将在2.4节中介绍它的做用。

默认状况下,Spring Boot内置了Tomcat。固然,它还支持其余容器,如Jetty。假若咱们要将默认容器改成Jetty,能够将pom.xml文件修改为下面这样:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
复制代码

在上述代码中,咱们经过标签将Tomcat的依赖包移除,并增长了Jetty的依赖包。

(3) 编写控制器以验证Spring Boot框架:

package com.lynn.boot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping(value = "hello")
    public String hello(){
       return "Hello World!";
    }
}
复制代码

在上述代码中,@RestController注解指示了该类为控制器类,与它对应的注解是 @Controller。@RestController注解至关于 @Controller注解和@ResponseBody注解的结合。@RequestMapping注解的做用是定义一个HTTP请求地址,默认不限制请求方式,能够是GET、POST亦或其余方法,若是要限制请求方法,能够在注解后面增长method属性,如method=RequestMethod.GET表示只有GET请求才能调用该HTTP地址。

上面提到的注解均为Spring MVC注解,咱们之因此可以在这里很方便地使用Spring MVC注解,是由于第(1)步的依赖中添加了spring-boot-starter-web依赖,该依赖集成了Spring MVC。

(4) 运行Application类的main方法,并访问localhost:8080/hello,便可看到如图2-1所示的界面。

图像说明文字

经过以上示例,咱们能够知道:

 使用Spring Boot建立一个工程很是简单,既没有XML配置文件,也没有Tomcat,经过几个简单的注解,运行main方法就能启动一个Web应用;

 Spring Boot默认内置Tomcat;

 Spring Boot用注解代替了烦琐的XML配置。

2.3 使用YAML文件配置属性

在上一节中,咱们实现了一个最简单的Web工程,没有建立任何配置文件。固然,Spring Boot的任何配置均可以经过代码实现。为了便于扩展,它引入了PROPERTIES格式和YAML格式 的文件,能够在其中定义一些经常使用属性或自定义属性。

2.3.1 YAML的基本用法

下面咱们先来看一下Spring Boot的通常配置,步骤以下。

(1) 在src/main/resources目录下建立一个名为application.yml的配置文件,并编写如下内容:

server:
    servlet:
        #定义上下文路径
        context-path: /demo
    #定义工程启动的端口
    port: 8081复制代码

在上述配置中,咱们经过server.servlet.context-path定义了应用的上下文路径为/demo,它的默认值为/,server.port定义应用的启动端口,其默认值为8080,这里设置为8081。

(2) 启动工程并访问localhost:8081/demo/hello,就能够看到如图2-1所示的界面。

① 本书的全部示例都使用了YAML 栺式的配置文件。复制代码

在2.2节中,咱们启动工程时的监听端口为8080,上下文路径为/,可是咱们并无配置任何信息,那是由于全部配置属性都有默认值,如端口的默认值为8080。

接下来,咱们看一下YAML文件的结构,其基本格式为:

key1:
    key2:
        key3: value复制代码

咱们将它替换成properties的形式,即key1.key2.key3=value。固然,key的个数不是固定的。这里须要说明的是,YAML格式很是严格。若是当前key后面须要跟value,则冒号后面必须至少有一个空格,不然编译不会经过;其次,每一个子属性之间须要经过空格或制表符(即按下Tab键)分隔,不然可能没法正确取到属性值。

若是咱们将上面例子中的YAML文件改为如下形式:

server:
    servlet:
        context-path: /demo
    #冒号后面直接跟端口号
    port:8081复制代码

那么启动工程后,控制台会打印以下的报错信息:

Caused by: org.yaml.snakeyaml.scanner.ScannerException: while scanning a simple key in 'reader', line 6, column 3:
    port:8081
    ^
could not find expected ':'
in 'reader', line 6, column 12:
    port:8081复制代码

2.3.2 多环境配置

在一个企业级应用中,咱们可能开发时使用开发环境,测试时使用测试环境,上线时使用生产环境。每一个环境的配置都不同,好比开发环境的数据库是本地地址,而测试环境的数据库是测试地址。所以会遇到这样一个问题:咱们在打包的时候,如何生成不一样环境的包呢?

这里的解决方案有不少,具体以下。

 每次编译以前,手动把全部配置信息修改为当前运行的环境信息。这种方式致使每次都须要修改,至关麻烦,也容易出错。

 利用Maven,在pom.xml里配置多个环境,每次编译以前将settings.xml修改为当前要编译的环境ID。这种方式的缺点就是每次都须要手动指定环境,并且若是环境指定错误,发布前是不知道的。

 建立多个针对不一样环境的配置文件,经过启动命令指定。这个方案就是本节重点介绍的,也是我强烈推荐的方式。

接下来,咱们看一下配置多环境的步骤。

(1) 将application.yml文件修改以下:

server:
    servlet: 
        context-path: /demo 
    port: 8081
spring:
    profiles:
        active: dev复制代码

这里经过spring.profiles.active指了明当前启动的环境。

(2) 建立多环境配置文件,文件命名格式为application-{profile}.yml,其中{profile}即为上述配置将要指定的环境名,如新增名为application-dev.yml的文件,咱们能够在里面添加配置:

server:
    port: 8080复制代码

并将spring.profiles.active设置为dev。

此时启动工程,能够看到工程的监听端口已变为8080。

你能够继续建立多环境文件,好比命名为application-test.yml,将监听端口改成8082,而后将spring.profiles.active改成test,再启动工程观察效果。在实际项目发布的过程当中,不会手动修改spring.profiles.active的值,而是经过启动命令来动态修改,具体细节见2.7节。

2.4 经常使用注解

前面提到过,Spring Boot主要是以注解形式代替烦琐的XML配置。在这一节中,我将带领你们了解一些经常使用注解的用法。

2.4.1 @SpringBootApplication

在前面的章节中,读者是否注意到,Spring Boot支持main方法启动。在咱们须要启动的主类中加入注解 @SpringBootApplication,就能够告诉Spring Boot这个类是工程的入口。若是不加这个注解,启动就会报错。读者能够尝试去掉该注解,看一下效果。

查看 @SpringBootApplication注解的源码,能够发现该注解由 @SpringBootConfiguration、@EnableAutoConfiguration和 @ComponentScan组成。咱们能够将 @SpringBootApplication替换为以上3个注解,如:

package com.lynn.boot;

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

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public class Application {

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

此时代码的运行效果与2.2节一致。

2.4.2 @SpringBootConfiguration

加入了 @SpringBootConfiguration注解的类会被认为是Spring Boot的配置类。咱们既能够在application.yml中进行一些配置,也能够经过代码进行配置。

若是要经过代码进行配置,就必须在这个类中添加 @SpringBootConfiguration注解。咱们既能够在标注了这个注解的类中定义Bean,也能够经过它用代码动态改变application.yml的一些配置。例如,建立WebConfig类,并改变工程启动的端口号:

package com.lynn.boot;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;

@SpringBootConfiguration
public class WebConfig implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    @Override
    public void customize(ConfigurableServletWebServerFactory factory) {
        //给代码设置应用启动端口
        factory.setPort(8888);
    }
}
复制代码

启动工程,能够看到监听端口已经变成了8888。


说明:若是YAML配置文件和代码配置了一样的属性,则会以代码配置为准。由于在Spring Boot应用启动后,会先加载配置文件,而后再执行被 @SpringBootConfiguration标注的类,因此它会覆盖配置文件配置的属性。


此外,也可使用 @Configuration注解,它和 @SpringBootConfiguration的效果同样,不过Spring Boot官方推荐采用 @SpringBootConfiguration注解。

2.4.3 @Bean

@Bean注解是方法级别的注解,主要添加在 @SpringBootConfiguration注解的类中,有时也添加在 @Component注解的类中。它的做用是定义一个Bean,相似于Spring XML配置文件的。

下面咱们就来看一下如何经过 @Bean注解注入一个普通类。

(1) 建立一个普通类Person,为了便于测试,咱们为该类增长了一个字段name:

package com.lynn.boot.bean;

public class Person {
    private String name;

    public void setName(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' + '}'; } } 复制代码

(2) 在2.4.2节建立的WebConfig类中增长如下代码:

@Bean
public Person person(){
    Person person = new Person();
    person.setName("lynn");
    return person;
}复制代码

在上述代码中,咱们经过一个 @Bean注解就能够将Person对象加入Spring容器中,它简化了传统的Spring XML的方式。

(3) 进行单元测试。首先,添加单元测试依赖:

org.springframework.boot
spring-boot-starter-test
test
复制代码

Spring Boot默认集成JUnit测试框架,经过添加spring-boot-starter-test依赖就能够集成它。而后在src/main/test目录下建立一个测试类,并编写测试代码:

package com.lynn.boot.test;

import com.lynn.boot.Application;
import com.lynn.boot.bean.Person;
import org.junit.Test;
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;

@SpringBootTest(classes = Application.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MyTest {

    @Autowired
    private Person person;

    @Test
    public void test(){
        System.out.println(person);
    }
}
复制代码

在上述代码中,咱们添加 @SpringBootTest注解来指定入口类为Application,再添加 @RunWith注解指定单元测试的运行环境为SpringJUnit4ClassRunner,即便用JUnit4的单元测试框架,接着经过 @Autowired注解注入了Person类,最后经过test方法打印person信息。

注意:在test方法中须要添加 @Test注解才能启用单元测试。

启动单元测试时,能够看到控制台打印出了如下信息:

Person{name='lynn'}复制代码

2.4.4 @Value

一般状况下,咱们须要定义一些全局变量,此时想到的方法是定义一个public static常量并在须要时调用它。那么是否有其余更好的方案呢?答案是确定的,这就是本节要讲的 @Value注解。

(1) 在application.yml里自定义一个属性data:

self:
    message:
        data: 这是我自定义的属性复制代码

上述配置不是Spring Boot内置属性,而是咱们自定义的属性。

(2) 修改HelloController类:

package com.lynn.boot.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @Value("${self.message.data}")
    private String value;

    @RequestMapping(value = "hello",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String hello(){
        return value;
    }
}
复制代码

其中,@Value注解的参数须要使用 ${} 将目标属性包装起来,该属性既能够是Spring内置的属性,也能够是自定义的属性。


注意:若是返回的是String类型的值,那么须要注明produces为application/json而且charset=utf8,不然可能会出现乱码;若是返回的是对象,则无须注明。由于Spring MVC不会对返回的String类型的值作任何处理,而若是返回对象的话,会执行Spring默认的JSON转换器,它会处理编码问题。


(3) 启动工程并访问localhost:8080/demo/hello,能够看到如图2-2所示的界面。

图像说明文字


说明:@Value注解能够获取YAML文件的任何属性值,它的好处以下:

 能够经过启动参数动态改变属性值,而不用修改代码;

 交给Spring统一管理常量,便于扩展和维护。

复制代码复制代码


2.5 Spring Boot集成模板引擎

在传统的Spring MVC架构中,咱们通常将JSP、HTML页面放到webapps目录下。但Spring Boot没有webapps,更没有web.xml,若是要写界面的话,该如何作呢?

咱们能够集成模板引擎。Spring Boot官方提供了几种模板引擎:FreeMarker、Velocity、Thymeleaf、Groovy、Mustache和JSP。本节中,咱们以FreeMarker为例讲解Spring Boot是如何集成模板引擎的。

首先,在pom.xml中添加对FreeMarker的依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>复制代码

在resources目录下创建static和templates两个目录,如图2-3所示。其中static目录用于存放静态资源,譬如CSS、JavaScript和HTML等,templates目录用于存放模板引擎文件。

图像说明文字

而后在templates目录下面建立index.ftl 文件,并添加以下内容:

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <h1>Hello World!</h1>
    </body>
</html>复制代码

接着建立控制器类:

@Controller
public class PageController {

    @RequestMapping("index.html")
    public String index(){
        return "index";
    }
}
复制代码
① freemarker 文件的默认后缀为.ftl。复制代码

最后,启动Application.java,访问localhost:8080/demo/index.html,就能够看到如图2-4所示的界面。

图像说明文字

在上述代码中,咱们要返回FreeMarker模板页面,所以必须将其定义为 @Controller,而不是前面定义的 @RestController。@RestController至关于 @Controller和 @ResponseBody的结合体。标注为 @RestController注解时,SpringMVC的视图解析器(ViewResolver)将不起做用,即没法返回HTML或JSP页面。ViewResolver的主要做用是把一个逻辑上的视图名解析为一个真正的视图。当咱们将一个控制器标注为 @Controller并返回一个视图名时,ViewResolver会经过该视图名找到实际的视图,并呈现给客户端。

2.6 更改默认的JSON转换器

Spring Boot默认使用Jackson引擎去解析控制器返回的对象,该引擎在性能和便捷性上与第三方引擎(FastJson和Gson等)还有必定的差距,本节将介绍如何将默认转换器替换为FastJson转换器。

(1) 在pom.xml中添加对FastJson的依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>复制代码

(2) 修改WebConfig类,为其添加方法并设置FastJson转换器:

@SpringBootConfiguration
public class WebConfig extends WebMvcConfigurationSupport{
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        FastJsonHttpMessageConverter fastConverter=new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig=new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.PrettyFormat
        );
        List<MediaType> mediaTypeList = new ArrayList<>();
        //设置编码为UTF-8
        mediaTypeList.add(MediaType.APPLICATION_JSON_UTF8);
        fastConverter.setSupportedMediaTypes(mediaTypeList);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        converters.add(fastConverter);
    }
}复制代码

首先应继承WebMvcConfigurationSupport类,该类提供了Spring Boot对Spring MVC的支持。而后重写configureMessageConverters方法,该方法配置了消息转换器。若是第三方框架但愿处理Spring MVC中的请求和响应时,那么须要实现HttpMessageConverter接口。而在上述代码中,FastJsonHttpMessageConverter即是如此,它实现了HttpMessageConverter接口,并经过FastJsonConfig设置FastJson的处理参数,如经过MediaType设置编码为UTF-8,最后添加到HttpMessageConverter中。

这样Spring MVC在处理响应时就能够将JSON解析引擎替换为FastJson。


说明:前面提到,若是控制器返回的是String类型的值,则须要显式设置编码。咱们替换成FastJson后,因为已经设置了编码,因此不管是字符串仍是对象,都无须设置编码方式,读者能够试一试。


2.7 打包发布到服务器上

Spring Boot支持使用jar和war两种方式启动应用,下面分别来介绍这两种方式是怎么启动的。

2.7.1 使用内置Tomcat发布jar包

因为Spring Boot内置了Tomcat,咱们能够将工程打包成jar,经过Java命令运行咱们的Web工程,具体步骤以下。

(1) 在pom.xml文件中添加如下内容:

<build>
    <finalName>api</finalName>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>      
         <mainClass>com.lynn.boot.Application</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.5</version>
            <configuration>
                <encoding>UTF-8</encoding>
                <useDefaultDelimiters>true</useDefaultDelimiters>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.18.1</version>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
 </build>复制代码

在pom.xml中,<build>标签订义了关于Maven编译和打包的一些信息。其中,<finalName>为打包后的文件名,<plugins>设置了编译的一些参数。Maven支持第三方插件,而Spring Boot的编译插件就是spring-boot-maven-plugin,并经过<mainClass>指定了启动类。后面maven-surefire-plugin就是Maven官方提供的用于构建测试用例的插件,若是有单元测试类,它在编译完成后会执行单元测试,单元测试成功后才会打包;若是不但愿执行单元测试,那么将<skipTests>设置为true便可。我建议将设置为true,若是设置为false,会致使打包时间过长。若是单元测试类中存在对数据库的增删改测试,编译时执行了它,可能会对原有数据形成影响。maven-compiler-plugin为Maven官方提供的指定编译器版本的插件,上述代码中的1.8表示使用JDK 1.8版本编译。

(2) 经过mvn clean package编译并打包,如图2-5所示。

图像说明文字

(3) 将打包的内容上传到服务器中,运行命令:

java -jar api.jar复制代码

这样就能启动一个Spring Boot应用。前面提到,能够经过命令参数来设置不一样环境或者动态设置参数,那么如何设置呢?下面以设置环境为例,输入命令:

java -jar api.jar --spring.profiles.active=dev复制代码

应用启动时,就会拉取application-dev.yml内的配置信息。若是你想改变任何属性值,在--后面加上相应的属性名和要改变的属性值便可。

2.7.2 打包成war包发布

除了编译成jar包发布外,Spring Boot也支持编译成war包部署到Tomcat。

(1) 在pom.xml中将应用打包格式改为war:

<packaging>war</packaging>复制代码

这里的就是告诉Maven,须要编译成何种后缀的文件。

(2) 将标签下的内容修改以下:

<build>
    <finalName>api</finalName>
    <resources>
        <resource>
             <directory>src/main/resources</directory>
             <filtering>true</filtering>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.5</version>
            <configuration>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.18.1</version>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
    </plugins>
</build>复制代码

上述内容和2.7.1节中的内容类似,增长了maven-resources-plugin插件,它用于编译resources目录下的文件。而在spring-boot-maven-plugin插件中无须指定<mainClass>,由于编译后的war部署在外部Tomact上,它依托于Tomcat容器运行,不会执行main方法。

(3) 添加Tomcat依赖,将<scope>设置为provided。这样作的目的是编译时去掉tomcat包,不然启动时可能会报错。咱们也不能直接经过<exclusion>标签去掉tomcat包,由于在本地开发时,须要经过Application类启动。相关代码以下:

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

(4) 修改启动类Application,它继承了SpringBootServletInitializer类,并重写了configure方法,以便Tomcat在启动时能加载Spring Boot应用:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }
}
复制代码

在上述代码中,若是咱们是经过外部Tomcat启动应用,则能够去掉main方法。由于Tomcat在启动时会执行configure方法,而configure方法会调用source方法并指定Application类,其做用与main方法一致。

(5) 使用mvn clean package编译并打包成WAR格式的文件,而后将其复制到Tomcat中。启动Tomcat,能够看到应用可以被正常访问。若是经过外部Tomcat启动应用,则server.port指定的端口失效,转而使用Tomcat设置的端口号。

经过war启动程序没法像jar包那样,在启动时指定运行环境或其余想要动态改变的参数值,且上下文路径以war包的名字为准,还须要本身安装Tomcat,比较麻烦,所以我推荐优先考虑jar包的启动方式。


注意:若是以war方式部署多个Spring Boot工程到一个Tomcat下,可能会报错,其缘由是Spring Boot的资源管理是默认打开的,而两个项目同时使用会冲突。此时须要在每一个项目中增长如下配置:

spring:
    jvm:
       default-domain: api复制代码

其中,在default-domain后面须要设置domain名,以保证每一个工程的domain不一致,这样才能同时启动多个工程。


2.8 WebFlux快速入门

Spring Boot 2.0为咱们带来了WebFlux,它采用Reactor做为首选的流式框架,而且提供了对RxJava的支持。经过WebFlux,咱们能够创建一个异步的、非阻塞的应用程序。接下来,咱们就一块儿来领略WebFlux的风采。

(1) 建立一个基于Spring Boot的Maven工程,将其命名为demo-lesson-one-webflux,而后在pom.xml文件中添加对WebFlux的依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>复制代码

(2) 编写一个Handler,用于包装数据:

@Component
public class HelloHandler {

    public Mono<ServerResponse> hello(ServerRequest request) {
        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
            .body(BodyInserters.fromObject("Hello, World!"));
    }
}
复制代码

该类自定义了一个方法,该方法返回Mono 对象。这里在ServerResponse的body方法中设置要返回的数据。

(3) 编写接口类,即定义咱们一般所说的路由地址(接口地址):

@SpringBootConfiguration
public class HelloRouter {
    @Bean
    public RouterFunction<ServerResponse> routeHello(HelloHandler helloHandler) {
        return RouterFunctions.route(RequestPredicates.GET("/hello")
            .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), helloHandler::hello);
    }
}复制代码
① Mono 是WebFlux 中属于publisher(収布者)的类。在WebFlux 中,开収者的方法只需返回Mono 或Flux 类便可。复制代码

由于路由须要注册到Spring容器中,因此该类也须要添加 @SpringBootConfiguration注解,而将返回的路由标识为一个Bean,这样才能注册到Spring容器中。

在上述代码中,咱们定义一个方法routeHello而且返回了RouterFunction对象。在RouterFunction中,指定路由地址为/hello,并指定Handler和对应的方法,即前面建立的HelloHandler。这样经过路由地址/hello就能够返回Handler的hello方法所设置的数据。

(4) 启动Application.java并访问地址localhost:8080/hello,能够看到浏览器正常显示HelloWorld。

经过控制台,咱们能够很清楚地看到它是经过NettyServer 启动的:

Netty started on port(s): 8080复制代码

这样咱们就创建了一个路由地址。细心的读者能够发现,上述代码过于烦琐,Spring Boot也考虑到了这一点。为了便于将MVC应用迁移到WebFlux,Spring Boot官方兼容了WebFlux和MVC,即咱们可使用MVC的注解来建立WebFlux的路由地址。

(1) 建立HelloController类并编写如下代码:

@RestController
public class HelloController {
    @RequestMapping(value = "hello")
    public Mono<String> hello(){
        return Mono.just("Hello World!");
    }
}复制代码

能够看到,上述代码和前面编写的代码很类似,只是这里咱们须要返回Mono对象,WebFlux将数据都包装到Mono返回,经过调用just方法便可。just方法传入的参数类型取决于Mono后面的泛型指定的类型。

(2) 启动Application.java,咱们能够获得和前面代码同样的结果。


说明:若是咱们经过 @Controller和 @Router两种方式定义了相同名字的路由地址,则会优先采用@Router方式。


① Netty 是一个异步的、事件驱动的网络应用程序框架。复制代码

2.9 小结

经过本章的学习,咱们了解了Spring Boot的基本用法并感觉到了YAML的优雅。本章涵盖了一些实际项目中可能会用到的知识点,如经常使用注解、Spring Boot默认引擎的集成、JSON转换器的更改以及编译部署应用等。最后还介绍了目前较为流行的WebFlux框架。在后面的内容中,咱们将进一步学习Spring Boot的其余特性。

本文摘自《Spring Cloud实战演练》

相关文章
相关标签/搜索