Spring Boot学习笔记01--基本介绍

摘要

看完本文你将掌握如下知识点:

  1. 如何搭建一个SpringBoot项目
  2. SpringBoot自动配置原理
  3. SpringBoot属性配置方法
  4. 修改默认的Logback日志为log4j和log4j2的方法
  5. 修改默认的内置tomcat容器为Jetty容器和Undertow容器的方法
  6. SpringBoot单元测试方法
  7. 使用war包运行项目

SpringBoot系列Spring Boot学习笔记


Spring Boot简介

  • 要我给Spring Boot做个定义,简单来说就是一个基于强大的Spring框架的、推崇JavaConfig的极简配置的web开发框架;
  • Spring Boot通过内嵌Servlet容器(Tomcat、Jetty,等等)的方式,可以以jar包的形式独立运行一个web项目;
  • Spring Boot提倡JavaConfig和注解的零配置方式,并且默认配置满足绝大多数场景的需要,意味着少量修改默认配置即可快速搭建一个web项目,极大的提高开发效率;
  • 项目中加入某一个spring-boot-starter-*依赖,就可以引入该功能的完整jar包,降低pom的复杂度
  • 本文基于Spring Boot的版本为1.4.2.RELEASE

Spring Boot项目创建方法

  • http://start.spring.io:可以通过网页创建项目结构并下载;
  • Spring Boot CLI:通过命令行的方式创建Spring Boot项目;
  • Spring Tool Suite:习惯Eclipse的用户可以使用STS创建『Spring Starter Project』项目;
  • IntelliJ IDEA:强大的生产力工具,推荐使用,创建『Spring Initializr』项目;

使用IntelliJ IDEA创建一个web项目

  1. 新建Spring Initializr项目


说明:Spring Boot要求JDK1.6+

  1. 填写项目信息,构建工具使用maven


  2. 选择项目使用的依赖,这里我们只需要勾选web


  1. Spring Boot当前最新的稳定版是1.4.2;
  2. 所有依赖可以在创建时勾选,也可以在创建后手工将依赖添加到pom中,如果对依赖比较熟悉,推荐手工添加,这样可以加快创建项目的时间;
  1. 填写项目名称,点击Finish


  2. 新建的项目结构如下


SpringBoot项目只会在项目根目录下生成一个类--SpringBootWebDemoApplication(artifactId+Application),它就是一个带有main函数的启动类;

package com.example;

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

@SpringBootApplication
public class SpringBootWebDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootWebDemoApplication.class, args);
    }
}
  • 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.example</groupId>
    <artifactId>springbootwebdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SpringBootWebDemo</name>
    <description>Demo project for Spring Boot</description>

  <!-- 创建的Springboot项目需要继承于spring-boot-starter-parent -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.2.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>
    <!-- 创建项目是勾选的web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    <!-- 每个项目都会自动添加一个test依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
      <!-- Springboot的编译插件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

这就是一个web项目的pom文件,可以看到只关联了很少的依赖,这是因为我们继承的spring-boot-starter-parent和关联的spring-boot-starter-web本身已经为我们关联了全部的依赖,如下是该项目所有的依赖包



运行Spring Boot项目

  1. maven运行:mvn spring-boot:run
  2. main函数运行:右键单击SpringBootWebDemoApplication,选择『Run 或者 Debug』;
  3. 推荐安装JRebel插件,支持热部署;
  4. 当然,也可以maven先打成jar,然后通过命令行执行java -jar xx.jar
  • 运行成功会看到控制台打印了如下信息


  • 可以看到打印信息中有tomcat的启动信息,说明springboot默认使用tomcat作为web运行容器,这点从上面的依赖包中也可以看到。因为当前项目并没有开放任何服务,所以此时访问8080端口会提示无服务


添加服务

  • 我们可以在项目中创建一个Controller控制器,比如DemoController
package com.example.Controller;

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

@RestController
public class DemoController {

    @RequestMapping("/")
    String index(){
        return "Hello Spring Boot!";
    }
}

一切似乎就是那么美好,我们什么都没配置,一个web项目就这样运行起来了,SpringBoot自动帮我们默认了一些常用的配置


自动配置原理说明

SpringBootWebDemoApplication类上的注解:@SpringBootApplication

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    Class<?>[] exclude() default {};

    String[] excludeName() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};
}
  • @SpringBootConfiguration实际上就是@Configuration,说明这是一个JavaConfig
  • @ComponentScan,启用注解自动扫描
  • @EnableAutoConfiguration的作用是根据类路径中jar包是否存在来决定是否开启某一个功能的自动配置,比如,我们项目中添加了spring-boot-starter-web依赖,因其关联Tomcat和Srping MVC,所以类路径下就会存在Tomcat和Spring MVC的jar包,SpringBoot项目扫描到这些jar包后会自动开启两者的配置,当然,这个配置是默认配置,我们可以根据需要进行修改(下文介绍)。
  • exclude和excludeName用于关闭指定的自动配置,比如关闭数据源相关的自动配置
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
  • scanBasePackages和scanBasePackageClasses用于指定扫描的路径,默认情况下会自动扫描被@SpringBootApplication注解的类(这里是SpringBootWebDemoApplication)的同级包以及子包中的Bean。比如我们创建的DemoController,因为开启了SpringMVC自动配置,同时又在对应的路径下,所以该Controller会被自动加载。比如我们这里指定扫描的包路径如下:
@SpringBootApplication(scanBasePackages = {"com.temp.Controller"})

再次运行程序,发现原来的DemoController不能被访问了,而『com.temp.Controller』下的controller却可以被访问。

那么问题来了,SpringBoot到底为我们自动配置了哪些功能呢?

  • 开启Debug模式,方式有多种:
  • java -jar xx.jar --debug
  • 在IDE中执行Run时添加VM arguments:-Ddebug
  • 在项目resources下的application.properties文件中增加debug=true
  • Debug模式运行程序,打印信息中会显示如下内容

启动的自动配置



未启用的自动配置


  • 从打印结果中看到,每一个*AutoConfiguration*都对应着一类功能的自动配置类,比如HttpEncodingAutoConfiguration:
HttpEncodingAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.filter.CharacterEncodingFilter' (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)
      - @ConditionalOnProperty (spring.http.encoding.enabled) matched (OnPropertyCondition)
  • 开启的自动配置中都会有@ConditionalOnClass@ConditionalOnWebApplication等标识,这是什么意思呢?为了弄清楚这个,我们需要先来认识一下@EnableAutoConfiguration

@EnableAutoConfiguration

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector;
import org.springframework.context.annotation.Import;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

  • 这里我们需要了解一下@Import注解中的EnableAutoConfigurationImportSelector

感兴趣的可以看一下源码,大体的功能就是扫描jar包里是否含有META-INF/spring.factories文件;
并在spring.factories中找到@EnableAutoConfiguration的全路径名称org.springframework.boot.autoconfigure.EnableAutoConfiguration这个key,该key对应的value就是用于声明都需要启用哪些自动配置类;
比如spring-boot-autoconfigure-1.4.2.RELEASE.jar中就有一个spring.factories,可以看到org.springframework.boot.autoconfigure.EnableAutoConfiguration参数中列出了自动配置类列表,而HttpEncodingAutoConfiguration这个自动配置类就是其声明的;

HttpEncodingAutoConfiguration

  • 先看下源码
@Configuration
@EnableConfigurationProperties({HttpEncodingProperties.class})
@ConditionalOnWebApplication
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
    private final HttpEncodingProperties properties;

    public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
        this.properties = properties;
    }

    @Bean
    @ConditionalOnMissingBean({CharacterEncodingFilter.class})
    public CharacterEncodingFilter characterEncodingFilter() {
        OrderedCharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
        return filter;
    }

    //.......省略以下........
}
  • 熟悉JavaConfig的都会明白,这就是一个配置类@Configuration,并且通过@Bean注册了一个CharacterEncodingFilter;

但是还有一些注解,是什么意思呢,我们分别说明:


  • @EnableConfigurationProperties:开启属性注入

本例中表示HttpEncodingProperties是属性类,并使用@Autowired自动注入;
属性类实际上是一个是注解了@ConfigurationProperties的JavaBean,SpringBoot将属性文件(application.properties)中的键值对与JavaBean的属性建立起一一对应关系:

@ConfigurationProperties(
    prefix = "spring.http.encoding" //属性值的前缀
)

/*
举例:application.properties中设置如下属性
spring.http.encoding.charset=UTF-8
spring.http.encoding.force=true
*/
public class HttpEncodingProperties {
    private Charset charset;
    private Boolean force;
    //....属性声明及set、get方法........
    }

所有@ConditionalOn开头的注解都是用于进行条件判断的


  • @ConditionalOnWebApplication:当前项目是web项目的条件下才加载当前配置类
  • @ConditionalOnClass:当类路径下有指定的类的条件下才加载当前配置类
//本例表示,当前类路径(含jar)下必须存在CharacterEncodingFilter
@ConditionalOnClass({CharacterEncodingFilter.class})
  • @ConditionalOnProperty:当指定的属性等于指定的值的情况下加载当前配置类
// spring.http.encoding=enabled
// matchIfMissing = true表示如果没有在application.properties设置该属性,则默认为条件符合
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
  • @ConditionalOnMissingBean:当前容器里没有指定的Bean的情况下
// 如果当前容器中找不到CharacterEncodingFilter实例,则创建当前的Bean
@ConditionalOnMissingBean({CharacterEncodingFilter.class})

通过上面的分析,应该可以明白SpringBoot是如何做到自动配置的,简单总结如下:

  1. @SpringBootConfiguration实际上就是@Configuration,说明这是一个JavaConfig
  2. @EnableAutoConfiguration负责扫描jar包中的META-INF/spring.factories来找到要初始化的各种AutoConfiguration
  3. 各种@Conditional注解决定哪些Bean可以被容器初始化
  4. 如果希望进一步了解SpringBoot的自动配置,建议查看每一个AutoConfiguration类的源码

除了上面介绍的,@Conditional注解还有如下形式

  • @ConditionalOnExpression:基于SpEL表达式作为条件判断
  • @ConditionalOnJava:基于JAVA版本作为判断条件
  • @ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
  • @ConditionalOnMissingClass:当前类路径下没有指定的类的条件下
  • @ConditionalOnNotWebApplication:当前项目不是web项目的条件下
  • @ConditionalOnResource:类路径下是否有指定的值
  • @ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个的情况下

如果我们希望自己创建一个自动配置类(AutoConfiguration),则只需要在我们自己创建的JavaConfig中加上@ConditionalOn注解,并且在类路径下创建META-INF/spring.factories,加入参数org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxxxAutoConfiguration


SpringBoot的配置文件

  • SpringBoot支持常规的properties配置文件(application.properties),还支持yaml语言的配置文件(application.yml)
  • SpringBoot会从classpath下的/config目录或者classpath的根目录查找application.properties或application.yml
  • 如果要修改SpringBoot自动配置中默认配置,可以通过在配置文件中配置相应的参数即可
  • 比如,项目启动时,tomcat默认的端口号是『8080』,访问路径是『/』,修改如下:
  • application.properties
server.port=8081
server.context-path=/demo
  • application.yml
server:
  port: 8081
  context-path: /demo
  • IntelliJ IDEA支持对properties和yml的代码提示功能,编辑起来还是很方便的,不需要特别记住这些属性名称
  • SpringBoot默认使用priperites进行配置

SpringBoot的属性可以通过多种方式指定,配置文件只是其中一种方式,常用的方式还有如下几种,按加载的优先级列出:

命令行参数:java -jar xx.jar --server.port=8081 --server.context-path=/demo
操作系统环境变量:有些OS不支持使用.这种名字,如server.port,可以使用SERVER_PORT来配置。
项目中的配置文件:application.properties或者application.yml
项目依赖jar包中的配置文件:application.properties或者application.yml

关于SpringBoot支持的配置属性可以查看官网地址1.4.2.RELEASE


Profile配置

  • 不同的环境可以使用不同的配置文件,application-{profile}.properties,比如

开发:application-rnd.properties
测试:application-release.properties
验证:application-verify.properties
生产:application-prod.properties

  • 通过在application.properties(项目中必须包含该文件)中设置spring.profiles.active=prod来指定启用哪一个Profile。

关于属性配置还想多说的一些内容

  • application.properties也可以配置自定义属性:my.name=hanqf
  • 通过@Value将属性注入Bean属性
@Value("${my.name}")
private String myName;
  • 通过@ConfigurationProperties将属性注入Bean对象

使用prefix

my.name=hanqf
my.servers[0]=rnd.hanqf.com
my.servers[1]=release.hanqf.com
@ConfigurationProperties(prefix="my")
public class Config {
    private String name;
    private List<String> servers = new ArrayList<String>();//list需要初始化

    //....set and get method
}

不使用prefix

name=hanqf
jdbc.username=root
jdbc.password=root
@ConfigurationProperties
public class Config {
    private String name;
    private Jdbc jdbc;
    class Jdbc {
        private String username;
        private String password;
        //....set and get method
    }

    //....set and get method
}
  • 属性占位符
app.name=MyApp
app.description=${app.name} is a Spring Boot application 

server.port=${port:8080} # 如果没有设置port,则使用默认值8080
  • 属性名匹配规则
@ConfigurationProperties(prefix="person")
public class Config {
    private String firstName;

    //....set and get method
}

firstName可以使用的属性名如下:

person.firstName,标准的驼峰式命名
person.first-name,虚线(-)分割方式,推荐在.properties和.yml配置文件中使用
PERSON_FIRST_NAME,大写下划线形式,建议在系统环境变量中使用

日志配置

  • Spring Boot默认使用Logback作为日志框架,这是推荐的方式,如果希望修改为熟悉的log4j可以看下文

创建项目时我们引入了spring-boot-starter-web,其依赖spring-boot-starterspring-boot-starter又依赖于spring-boot-starter-logging,该依赖内容就是Spring Boot默认的日志框架Logback
Logback相关设置,可以在application.properties中进行如下配置:

# 日志文件路径
logging.file=D:/my_log.log 

# 配置日志打印级别
logging.level.org.springframework=INFO

当然,也可以直接将自己的logback.xml放到项目根路径下

  • 修改为log4j框架
    pom中排除对spring-boot-starter-logging的依赖,并加入对spring-boot-starter-log4j的依赖
    目前maven中央仓库的最新版本是1.3.8.RELEASE
<dependency>  
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion> 
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>  
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j</artifactId>
    <version>1.3.8.RELEASE</version> 
</dependency>

项目根路径下添加log4j.properties

  • 修改为log4j2框架
    与log4j类似,修改pom,增加spring-boot-starter-log4j2依赖
    目前maven中央仓库的最新版本是1.4.2.RELEASE
<dependency>  
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion> 
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>  
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    <version>1.4.2.RELEASE</version> 
</dependency>

项目根路径下添加log4j2.xml


说明
这里需要说明一个问题,如果切换为其它log框架,debug=true将会失效,需要在各自的log配置文件中声明,比如log4j需要添加log4j.logger.org.springframework.boot=debug


修改内置Tomcat为Jetty

  • 修改pom,去除spring-boot-starter-tomcat的依赖,增加spring-boot-starter-jetty依赖
    目前maven中央仓库的最新版本是1.4.2.RELEASE
<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>
    <version>1.4.2.RELEASE</version>
</dependency>
  • application.properties中的属性配置与tomcat一致

修改内置Tomcat为Undertow容器

  • 修改pom,去除spring-boot-starter-tomcat的依赖,增加spring-boot-starter-undertow依赖
    目前maven中央仓库的最新版本是1.4.2.RELEASE
<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-undertow</artifactId>
    <version>1.4.2.RELEASE</version>
</dependency>
  • application.properties中的属性配置与tomcat一致

单元测试

  • 创建一个单元测试的抽象父类,用于初始化必要的对象
package com.common;

import org.junit.Before;
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.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringRunner.class)
//1.4.2.RELEASE中不再需要@SpringApplicationConfiguration和@WebAppConfiguration
@SpringBootTest 
public abstract class SpringBootTestParent {

    public MockMvc mockMvc;

    @Autowired
    WebApplicationContext webApplicationContext;

    @Before
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();

    }
}
  • 继承抽象父类,并实现测试逻辑
public class SpringBootWebDemoApplicationTests extends SpringBootTestParent{

    @Autowired
    DemoService demoService;

    @Test
    public void content(){
        String content = "456";
        System.out.println(demoService.printContent(content));
        Assert.assertEquals(content,demoService.printContent(content));
    }

    @Test
    public void  DemoControllerContent(){
        String uri = "/content/123";
        MvcResult mvcResult;
        try {
            mvcResult = mockMvc.perform(MockMvcRequestBuilders.get(uri)).andReturn();
            System.out.println(mvcResult.getResponse().getStatus() + "##" + mvcResult.getResponse().getContentAsString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用war包的形式运行项目

上面我们介绍了SpringBoot通过jar的形式运行项目的方法,这也是SpringBoot推荐的方式,因其内置Servlet容器,所以发布和部署都非常方便,但是某些情况下(比如使用JSP作为VIEW层,内置容器的形式并不能支持),我们希望将web项目部署到自己的容器中,这时候就需要将SpringBoot项目打成war包部署,有两种方式:
1.创建项目时打包方式选择:war


war项目目录结构


2.将原打包方式为jar的项目修改为war形式
与war项目对比发现,通过修改如下内容,可以将jar项目修改为war项目
2.1 pom中将<packaging>jar</packaging>==><packaging>war</packaging>
2.2 pom中添加tomcat依赖,显示声明scope为provided,这样打包时就不会将tomcat的jar包打到war中

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

2.3 创建ServletInitializer

public class ServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(DemoWarApplication.class);
    }
}

说明

  • Servlet3.0规范,支持将web.xml相关配置也硬编码到代码中,并由javax.servlet.ServletContainerInitializer的实现类负责在容器启动时进行加载
  • spring提供了一个实现类org.springframework.web.SpringServletContainerInitializer,
    该类会调用所有org.springframework.web.WebApplicationInitializer的实现类的onStartup(ServletContext servletContext)方法,从而将相关的容器组件注册到容器;
  • SpringBootServletInitializer就是WebApplicationInitializer的实现类;
  • 我之前写过一篇SpringMVC4零配置的文章,对零配置感兴趣的同学可以参考。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容