SpringBoot基础

1.什么是springboot?

 是简化Spring应用开发的一个框架;整个Spring技术栈的一个大整合;J2EE开发的一站式解决方案;

2.springboot入门

1)创建一个maven的工程(jar),导入依赖:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
 </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

2)新建主程序,用来启动springboot:

@SpringBootApplication
// @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
public class Test {
    public static void main(String[] args) {
        SpringApplication.run(Test.class,args);//启动springboot
    }
}

3)在主程序的同包下编写一个controller类,进行测试:

@RestController
public class MyController {
    @RequestMapping("/get")
    public String get(){
        return "hello world!";
    }
}

4)运行主程序。启动成功后会在控制台输入

5)在浏览器测试。在浏览器输入localhost:8080/get.do,即可输出hello world!。此时已经入门了。需要注意的就是第二步的注解@SpringBootApplication必须要写。

6)修改tomcat的端口。在资源目录新建一个application.properties的配置文件,添加下面一行代码,即可修改tomcat的端口,注意这个文件名是固定的:

server.port=8888

7)读取配置文件的信息

我们可以在application.properties中定义自己的配置,然后来读取

(1)在application.properties中添加:

url=http://www.baidu.com

(2)在controller类中添加获取配置的方法

 @Autowired
  private Environment env;
  //包:import org.springframework.core.env.Environment;
  @RequestMapping("getUrl")
  public String getUrl(){
      return env.getProperty("url");
  }

启动springboot,在浏览器输入http://localhost:8080/getUrl 就会在浏览器显示http://www.baidu.com。

8)热部署(不常用)

当修改程序后,不需要重启springboot,就可以更新。添加以下依赖,那么热部署就可以实现了。

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

9)注解深究

(1)打开SpringBoootApplication注解的类,可用看到一些注解:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

@SpringBootConfiguration:是Spring Boot的配置类;标注在某个类上,表示这是一个Spring Boot的配置类。

@EnableAutoConfiguration:开启允许自动配置。这样spring会帮我们自动配置。

@ComponentScan:完成包扫描,是扫描启动类所在的包以及下面的包。

(2)进入@EnableAutoConfiguration类,有如下部分注解:

@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {

@AutoConfigurationPackage:自动配置包

@Import(AutoConfigurationPackages.Registrar.class):是Spring的底层注解@Import,给容器中导入一个组件;导入的组件由AutoConfigurationPackages.Registrar.class将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器。

(3)给容器中导入组件

EnableAutoConfigurationImportSelector:它是导入哪些组件的选择器,将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中。它会给容器中导入非常多的自动配置类(xxxAutoConfiguration)。就是给容器中导入这个场景需要的所有组件,并配置好这些组件。

Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。

10)不使用spring-boot-starter-parent

如果需要使用自己的parent,那么就需要对依赖进行管理,添加如下代码到pom.xml:

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

此时就不需要继承spring-boot-starter-parent了,但还有一些需要配置,配置java的版本:

<plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-compiler-plugin</artifactId>
       <version>3.1</version>
       <configuration>
             <source>1.8</source>
             <target>1.8</target>
      </configuration>
  </plugin>

至于格式编码,这里是使用maven创建的,需要配置,如果是按照下面的快速方法创建,就不需要配置:

<properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

3.使用Spring Initializer快速创建springboot项目

新建一个项目,选择spring initializer来创建:

 点击下一步,填写项目组和项目名称,再点击下一步,根据需要选择需要的组件,然后完成即可。这里就选择spring web。

 创建成功后会发现它已经帮我们创建好了主程序代码,我们只需要在里面进行其他的开发即可。

1)定制banner

springboot启动时会打印一个banner,就是spring的艺术字,这个是可以自定义的。在资源目录下创建一个banner.txt,在里面写入的文本就会在项目启动的时候打印出来。

A.若设置艺术字,可以到下面的网站去生成艺术字,然后复制到txt文件中即可。网址:

http://www.network-science.de/ascii/
http://www.kammerl.de/ascii/AsciiSignature.php
http://www.patorjk.com/software/taag

B.不过这个banner也是可以设置关闭的,修改mian方法:

public static void main(String[] args) {
        SpringApplicationBuilder builder=new SpringApplicationBuilder(DemoApplication.class);
        builder.bannerMode(Banner.Mode.OFF).run(args);
//      SpringApplication.run(DemoApplication.class, args);
 }

C.若要显示SpringBoot的版本信息,则可以在里面添加下面的代码

${spring-boot.version}
${spring-boot.formatted-version}

第二行是对第一行进行格式化后显示的版本信息,如图

2)tomcat常规配置

在applicatopn.properties中加:

#配置项目的端口号
server.port=8081
#配置项目出错时跳转的页面
server.error.path=/error
#配置session的生效时间,30m表示30分钟
server.servlet.session.timeout=30m
#配置项目的名称,配置后需在访问路径中加项目名称,若不配置则默认是/
server.servlet.context-path=/demo
#配置tomcat的编码
server.tomcat.uri-encoding=UTF-8
#配置tomcat的最大线程数
server.tomcat.max-connections=1000
#配置tomcat运行日志和临时文件的目录
server.tomcat.basedir=/home/tmp

对于applicatopn.properties配置文件,可以存放在四个位置,分别是项目的根目录下的config文件夹中、项目根目录下、资源目录的config文件夹中、资源目录下。springboot的加载优先级是:上面四个位置依次从高到低,然后加载到Spring Environment中。yml的优先级同上。

3)jetty配置

Jetty 是一个开源的servlet容器,它为基于Java的web容器,例如为JSP和servlet提供运行环境。使用和tomcat类似,这里就去除tomcat,添加jetty进行配置:

 <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
       <!--去除默认的tomcat,添加jetty依赖-->
       <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>

undertow是红帽公司开源的java服务器,配置和jetty一样,在此略。

4.Spring Boot的配置文件

虽然springboot已经帮我们写好了很多的配置,但是有些配置需要使用我们自己的,就可以进行配置。springboot使用全局的配置文件。文件名是固定的,为application.properties或application.yml。两者的功能是类似的,只是内容的格式不一样,但是properties 的优先级要高于yml。

yml原名叫yaml,现在简称为yml。使用yml的方式文件名必须是application.yml,properties的形式在这里不介绍了。对于properties的文件,要转换成yml文件,需要把"."变成树形结构

4.1yml内容形式

(1)k: v。键值对的形式,中间必须有空格。也可以使用缩进的方式控制层级关系,清楚明了,大小写敏感。

server:
  port: 8888

(2)给(对象、map)变量赋值。字符串不需要加双引号:

person:
  name: 张三
  age: 20

(3)也可以使用行内式,如下:

person: {name: 张三,age: 20}

4.2将数据注入bean

@Component
@ConfigurationProperties(prefix = "person")
public class Test {
    private String name;
    private int age;
}

@ConfigurationProperties 表示 告诉 SpringBoot 将本类中的所有属性和配置文件中相关的配置进行绑定。prefix = "person" 表示 将配置文件中 key 为 person的下面所有的属性与本类属性进行一一映射注入值,如果配置文件中不存在 "person" 的 key,则不会为 POJO 注入值,属性值仍然为默认值

4.3获取属性值

    @Resource
    private PersonTest personTest;

    @Test
    public void test1() {
        System.out.println(personTest);
    }

4.4其他类型赋值

(1)给数组(list,set)赋值 

animal:
  - dog
  - cat
  - pig

也可以使用行内式,如下:

animal: [cat,dog,pig]

4.5读取配置文件内容示例

application.yml的内容如下:

# 项目相关配置
student:
    # 项目名称
    name: Student
    #文件路径
    path: c:/student

创建项目配置的实体类,如下:

package com.kanq.exchange.domain;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/*
* 读取项目相关配置
* */
@Component
@ConfigurationProperties(prefix = "student")
public class SystemConfig {
    //项目名称
    private String name;
    //文件路径
    private static String path;

    public String getName() {
        return name;
    }

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

    public static String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
    //返回文件路径
    public static String getFilePath()
    {
        return getPath();
    }
}

获取路径:

package com.kanq.exchange.action;

import com.kanq.exchange.domain.SystemConfig;
import org.springframework.stereotype.Controller;

@Controller
public class StuController {

    //获取路径
    public void getPath(){
        String path=SystemConfig.getFilePath();
    }

}

5.使用配置文件给对象注入值

新建一个springboot的工程,使用spring initializer创建。

1)配置文件application.yml:

person:
  name: 张三
  age: 20
  map:
    key: v1
  brith: 2019/5/5
  list:
    - name: 测试1
    - name: 测试2
  dog:
    name: 小三
    age: 1

2)实体类

类Dog:

public class Dog {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

类Student:

public class Student {
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}

类Person:

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private int gae;
    private Date brith;
    private Map map;
    private List<Student> list;
    private Dog dog;

    public String getName() {
        return name;
    }

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

    public int getGae() {
        return gae;
    }

    public void setGae(int gae) {
        this.gae = gae;
    }

    public Date getBrith() {
        return brith;
    }

    public void setBrith(Date brith) {
        this.brith = brith;
    }

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    public List<Student> getList() {
        return list;
    }

    public void setList(List<Student> list) {
        this.list = list;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", gae=" + gae +
                ", brith=" + brith +
                ", map=" + map +
                ", list=" + list +
                ", dog=" + dog +
                '}';
    }
}

3)导入配置文件处理器依赖,配置文件进行绑定就会有提示

 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
 </dependency>

4)处理乱码。properties配置文件在idea中可能会乱码,需要进行处理:

 5)测试。在测试类中修改:

   @Autowired
    private Person person;
    @Test
    public void contextLoads() {
        System.out.println(person);
    }

运行测试类,会在控制台打印person的内容。

6)配置文件的占位符

(1)随机数

${random.int},${random.value}。。。

(2)指定默认值。占位符获取之前配置的值,如果没有可以使用:默认值。下面是用.properties的配置演示的:

person.last‐name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.map.k1=v1
person.map.k2=14
person.list=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15

6.@Bean的使用

springboot通常使用@Bean来注入对象,在方法上加这个注解,把此方法的返回值添加到spring容器中,也可以在这个类中把其他类交给spring管理。

@Configuration
public class Hello {
    @Bean
    public Hello getHello(){
        return new Hello();
    }
    public void say(){
        System.out.println("hello");
    }
}

这样也可以把Hello这个对象交给spring来管理,也是通过@Autowired来获取。

7.profile

不同的时期配置可能不同,可以在配置文件中定义不同的环境来做不同的配置。

7.1使用properties方式:

1)创建测试的环境配置文件application-dev.properties,以配置端口号为例:

server.port=8888

2)创建debug的环境配置文件application-debug.properties

server.port=9999

3)创建配置文件application.properties,指定激活的配置文件,这里激活dev的环境:

spring.profiles.active=dev

7.2使用yml方式:

yml方式是在同一个配置文件中编写多个环境块,用---分隔

#在一个文件中进行配置
#指定激活哪个配置
spring:
  profiles:
    active: bug

---
server:
  port: 6666
#指定环境的名字
spring:
  profiles: test

---
server:
  port: 5555
#指定环境的名字
spring:
  profiles: bug

也可以通过命令行的方式来指定运行那个环境,运行方式如下:

--spring.profiles.active=test

点击ok,然后再运行,会发现运行的是test的环境,而不是配置文件中的bug,原因是在外部的配置大于在内部的配置。

8.日志

1)日志框架

市面上的日志框架:JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....

日志门面(日志的抽象层)API     日志实现
JCL、SLF4j、Jboss-logging

Log4j、JUL、Log4j2、Logback

SpringBoot的底层是Spring框架,Spring框架默认是用JCL;SpringBoot选用 SLF4jlogback。

2)SLF4j的使用

在测试类中新建一个方法,用来测试日志。(这里默认已经创建了springboot的工程)

 @Test
    public void logTest(){
        Logger logger = LoggerFactory.getLogger(SpringbootDemoApplicationTests.class);
        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
        logger.warn("warn");
        logger.error("error");
    }

使用properties方式配置日志级别,在application.properties加下面一行代码,运行测试类发现只打印warn以上级别的信息:

#要配置到包,指定某一个包的日志级别
logging.level.com=warn

使用yml方式配置日志级别,在application.yml加下面的代码,运行测试类发现只打印trace以上级别的信息:

spring:
  profiles:
    active: pro

---
logging:
  level: {com: trace}
spring:
  profiles: pro

---
logging:
  level: {com: error}
spring:
  profiles: release

其他问题:使用不同的框架,就会产生不同的日志框架,让系统中所有的日志都统一到slf4j? 在api和实现层的中间添加不同的适配层即可,具体来说,先将系统中其他日志框架先排除出去,再用中间包来替换原有的日志框架,最后导入slf4j其他的实现。

3)日志输出到文件

path:后接目录,会把日志文件放在项目所在的目录的根目录下,默认文件名是spring.log。

file:后接文件名,会把日志文件放在项目下。如果两个同时使用,则file生效。

logging:
  level: {com: trace}
  path: abc/log

这里日志文件存放位置是:springboot-demo1\abc\log\spring.log。其中springboot-demo1是项目名。

logging:
  level: {com: trace}
  file: log.log

这里日志文件存放位置是:springboot-demo1\log.log。其中springboot-demo1是项目名。

 4)为日志文件指定配置

如果有自己的配置文件,就引入进来,但是必须以logback-spring.xml为名或logback.xml。

如果名字是logback.xml,那么它直接就被日志框架识别了;如果名字是logback-spring.xml,那么日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能。

新建一个配置文件,名为logback.xml,测试:

<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
    <!-- 定义日志的根目录 -->
    <property name="LOG_HOME" value="/app/log" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="atguigu-springboot"></property>
    <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!--
        日志输出格式:
            %d表示日期时间,
            %thread表示线程名,
            %-5level:级别从左显示5个字符宽度
            %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 
            %msg:日志消息,
            %n是换行符
        -->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </layout>
    </appender>

    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->  
    <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 指定日志文件的名称 -->
        <file>${LOG_HOME}/${appName}.log</file>
        <!--
        当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
        TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--
            滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 
            %i:当文件大小超过maxFileSize时,按照i进行文件滚动
            -->
            <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <!-- 
            可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
            且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
            那些为了归档而创建的目录也会被删除。
            -->
            <MaxHistory>365</MaxHistory>
            <!-- 
            当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
            -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 日志输出格式: -->     
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
        </layout>
    </appender>

    <!-- 
        logger主要用于存放日志对象,也可以定义日志类型、级别
        name:表示匹配的logger类型前缀,也就是包的前半部分
        level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
        additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,
        false:表示只用当前logger的appender-reftrue:
        表示当前logger的appender-ref和rootLogger的appender-ref都有效
    -->
    <!-- hibernate logger -->
    <logger name="com" level="debug" />
    <!-- Spring framework logger -->
    <logger name="org.springframework" level="debug" additivity="false"></logger>

    <!-- 
    root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
    要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。 
    -->
    <root level="info">
        <appender-ref ref="stdout" />
        <appender-ref ref="appLogAppender" />
    </root>
</configuration> 
View Code

将文件名修改为logback-spring.xml,添加两行代码,添加多个配置,不同的配置在不同的环境下生效:

  <springProfile name="staging">
            <!--指定配置在某个环境下生效-->
          .....
  </springProfile>

配置举例:

<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">

    <springProfile name="dev">
    <pattern>%d{yyyy‐MM‐dd HH:mm:ss.SSS} ‐‐‐‐> [%thread] ‐‐‐> %‐5level
    %logger{50} ‐ %msg%n</pattern>
    </springProfile>
    <springProfile name="!dev">
    <pattern>%d{yyyy‐MM‐dd HH:mm:ss.SSS} ==== [%thread] ==== %‐5level
    %logger{50} ‐ %msg%n</pattern>
  </springProfile>

</layout>
</appender>

指定级别,然后测试:

<root level="info">
        <appender-ref ref="stdout" />
        <appender-ref ref="appLogAppender" />
    </root>

 只要使用springboot依赖了不被springboot管理的框架,一定要排除日志依赖,同时引入对应的适配层。

9.SpringBoot与SpringMvc的区别

SrpingBoot是一个快速开发的框架,原理是利用maven依赖整合第三方框架;去除xml配置,采用注解的形式;内置了很多的容器(如tomcat服务器)。

SpringMvc是spring的一个框架,在SpringBoot中使用SPringMvc。

10.SpringBoot其他知识

1)SpringBoot启动流程

第一步:new SpringApplication

第二步:调用run方法

2)WebApplicationType的三种

第一种:NONE,不嵌入web服务器,通过外部tomcat服务器运行

第二种:SERVLET,需要使用web服务器运行

第三种:REACTIVE,使用响应式web启动

就是这么简单,你学废了吗?感觉有用的话,给笔者点个赞吧 !
原文地址:https://www.cnblogs.com/zys2019/p/11603590.html