# SpringBoot入门

# 问题引入

# 问题背景

Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE)的轻量级代替品。无需开发重量级的Enterprise JavaBean(EJB),Spring为企业级Java开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的Java对象(Plain Old Java Object,POJO)实现了EJB的功能。

但是Spring有两个重要缺点:

  1. 虽然组件是轻量级的,但它的配置是重量级的。一开始Spring用XML配置,在Spring 2.5引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的XML配置。在Spring 3.0引入基于Java的配置,这是一种类型安全可重构配置方式,可替代XML。
  2. 项目的依赖管理也是一件耗时耗力的事情,在环境搭建时,需要分析导入哪些库的坐标,以及库之间的依赖关系。

# SpringBoot基本概念

SpringBoot针对上面的缺点,基于约定优于配置的思想,可以让Spring开发人员更快速的上手Spring,它有如下优点:

  1. 为基于Spring的开发提供更快的入门体验。
  2. 开箱即用,没有代码生成,无需XML配置,可通过修改默认值来定制。
  3. 提供了一些功能特性,比如:嵌入式服务器,健康检测,外部配置。
  4. SpringBoot不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式。

# 核心功能

SpringBoot有两个核心功能:

  • 起步依赖:起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
  • 自动配置:Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定Spring配置应该用哪个,不该用哪个。该过程是Spring自动完成的。

# 快速入门

# 从零开始

  1. 创建Maven工程。

  2. 添加SpringBoot的起步依赖。

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  3. 编写SpringBoot的引导类。

    package com.muyun;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    //告诉SpringBoot此类为引导类
    @SpringBootApplication
    public class MainClass {
        public static void main(String[] args){
            //运行SpringBoot的启动类,参数为SpringBoot启动类的字节码对象
            SpringApplication.run(MainClass.class);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  4. 编写Controller。

    package com.muyun;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    public class QuickReq {
        @RequestMapping("/test1")
        @ResponseBody
        public String Req1(){
            return "访问成功";
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

# Intellij创建SpringBoot

Intellij提供了一种更方便方式来创建SpringBoot方式:

  1. 使用向导:

    SpringBootCreate

  2. 选择哪些组件:

    SelectFrame

  3. 编写Controller来测试下:

    package com.muyunsoft.springbootlesson2.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class TestRun {
        @RequestMapping("/testpath")
        public String TestRunFunc(){
            return "TestRun running!";
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

# 热部署

在开发中可能会反复修改源码,修改完需要重新启动才能生效。我们可以让它热部署。添加如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>
1
2
3
4

Intellij还需要做如下修改:

hotreload1

摁住Shift+Ctrl+Alt+/,选择Registry。

hotreload2

# 服务器部署

参考资料:

要打包的时候,有三种格式:

包类型 英文 包含内容 部署文件 容器 级别
jar Java Archive file class、properties文件,是文件封装的最小单元;包含Java类的普通库、资源(resources)、辅助文件(auxiliary files)等 application-client.xml 应用服务器(application servers)
war Web Archive file Servlet、JSP页面、JSP标记库、JAR库文件、HTML/XML文档和其他公用资源文件,如图片、音频文件等 web.xml 小型服务程序容器(servlet containers)
ear Enterprise Archive file 除了包含JAR、WAR以外,还包括EJB组件 application.xml EJB容器(EJB containers)

spring boot支持jar包和war包两种格式。

# jar包

jar(java归档文件)是与平台无关的文件格式,它以ZIP格式为基础,不仅用于压缩和发布,还用于部署和封装库,组件和插件程序,可被编译器和JVM直接使用。

简单说Java编译好之后生成class文件,如果直接发布这些class会不方便,需要把class打包成jar,jar除了包含class文件还包括一些资源和配置文件,可以将这些jar包放到lib目录下,直接使用其中的类和属性。

jar包是直接通过内置的Tomcat运行,spring boot中的spring-boot-starter-web包含内置tomcat,不需要额外安装Tomcat,如果需要修改Tomcat配置,只需要在SpringBoot的配置文件中配置,内置Tomcat没有自己的日志输出,全靠jar包应用输出日志。

打jar包不会把src/main/webapp下的内容打包到jar包里,它是不管静态文件的。

# 实战jar包

  1. 设置打包方式:

    <packaging>jar</packaging>
    
    1
  2. 指定jsp打包配置:

    <resources>
      <!-- 打包时将jsp文件拷贝到META-INF目录下-->
      <resource>
        <!-- 指定resources插件处理哪个目录下的资源文件 -->
        <directory>src/main/webapp</directory>
        <!--指定必须要放在此目录下才能被访问到-->
        <targetPath>META-INF/resources</targetPath>
        <includes>
          <include>**/**</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/**</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

下面是服务器上部署时运行时指定配置文件:

nohup java -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Shanghai -jar PicTool.jar --spring.config.location=/tomcat/webapps/applications.properties > templog.log &
1

# war包

它通常表示这是一个Java的Web应用程序的包,是一个可直接运行的web模块,通常用于网站,打成包部署到容器中。比如把war包放到Tomcat中的webapps目录下,启动Tomcat会自动部署。

war包中的文件按照一定的目录结构来组织,根目录下包含html和jsp,以及WEB-INF目录,通常该目录下包含一个web.xml(配置文件),classes目录(servlet类和jsp)和lib目录(servlet所依赖的其他类)。

war包是传统的应用交付方式,需要外置的Tomcat,放到其webapps下以部署,可以直接修改Tomcat的配置,有自己的Tomcat日志。注意这种情况下不能直接使用spring boot配置文件中的端口,比如appllication.yml中的server.port,这个配置是给内置Tomcat使用的,同样context-path也会失效。注意这种需要设置访问的上下文,上下文名应该是war包解压后的文件夹名。

打war包时会把静态文件打包到war里,一般如果应用有静态资源时是打war包,这样替换时只替换特定的静态文件即可。在HTML页面里面,资源路径全部从/static/开始写,然后下面代码就是进行一个映射,将/static/下的文件全部映射到实际位置为classpath:/static/的代码;

@Configuration
public class BookWebConfiguration implements WebMvcConfigurer {
  @Bean
  public WebMvcConfigurer webMvcConfigurer() {
    return new WebMvcConfigurer() {
      //加载资源路径;还可以添加拦截器,视图控制器;
      @Override
      public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
      }
    };
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 实战war包

  1. 在pom文件中修改打包方式:

    <packaging>war</packaging>
    
    1
  2. 排除内置的tomcat依赖:

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-tomcat</artifactId>
       <scope>provided</scope>
    </dependency>
    
    1
    2
    3
    4
    5
  3. 增加启动类

    package com.test;
    
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
    
    public class ServletInitializer extends SpringBootServletInitializer {
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
            return application.sources(HuaweiMeetingApplication.class);
        }
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  4. 使用打成war包的名字和外部tomcat端口号访问项目。

# SpringBoot初理解

SpringBootApplication一个注解相当于至少下面三个注解:

  1. @SpringBootConfiguration:等同与@Configuration,标注该类是Spring的一个配置类。

  2. EnableAutoConfiguration:是否可以完成自动配置。

    1. 它自动导入AutoConfigurationImportSelector。该类中有一句话:"No auto configuration classes found in META-INF/spring.factories"。

    2. 该文件位置为:

      SpringBootAutoConfiguration

    3. 以其中一个为例搜索,比如ServletWebServerFactoryAutoConfiguration,进入相应类,里面有一个ServerProperties类,进入这个类就可以发现了相应的配置相关东西。

    4. 在第二步位置的文件夹里有一个spring-configuration-metadata.json。这里面有这些配置文件的默认值。

    5. 我们可以在如下的位置复写上面的配置文件:

      SpringBootConfiguration

    6. 我们在Resource文件夹下创建一个配置文件:application.properties。

      # 修改端口
      server.port=9090
      # 修改上下文
      server.servlet.context-path=/test
      
      1
      2
      3
      4
  3. ComponentScan:扫描当前引导类的包以及子包。