SpringBoot

SpringBoot

1. springboot多环境配置
1.1 properties文件

spring.profiles.active=dev【激活dev文件】

创建三个文件,然后在默认文件application中激活某个文件

  1. application.properties 默认

  2. application-dev.properties 开发环境

  3. application-test.properties 测试环境

1.2 yaml文件

yaml可以直接给实体类赋值

@Value 可以赋值

server:

​ port: 8081

spring:

​ profiles:

​ active: dev(激活dev)

–(三条横线)【分割线将文件分割成多个文件】

server:

​ port: 8082

spring:

​ profiles: dev(dev)

server:

​ port:8083

spring:

​ profiles:test

# 对空格的要求十分高!
# 普通的key-value
name: qinjiang

# 对象
student: 
  name: qinjiang
  age: 3

# 行内写法
student: {name: qinjiang,age: 3}

#数组
pets:
  - cat
  - dog
  - pig
pets: [cat,dog,pig]
1.3 配置文件内容

在我们配置文件中能配置的东西,都存在一个固有的规律。

2.springboot自动装配原理
  1. springboot启动会加载大量的类。
  2. 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中。
  3. 我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在其中,我们就不需要再手动配置了)
  4. 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性值。我们只需要在配置文件中指定这些属性的值即可;

xxxxAutoConfiguration:自动配置类;给容器中添加组件

xxxxProperties:封装配置文件的相关属性

ApplicationContext:容器,里面可以找到所有的bean

2.1 原理初探

自动配置

自动配置原理

1)、springboot启动的时候加载主配置类,开启了自动配置动能@EnableAutoConfiguration

2)、@EnableAutoConfiguration作用:

  • 利用EnableAutoConfigurationImportSelector给容器中导入一些组件?

  • 可以插件selectimports()方法的内容:

  • List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置

    • SpringFactoriesLoader.loadFactoryNames()
      扫描所有jar包类路径下  META-INFO/spring.factories
      把扫描到的这些文件的内容包装成properties对象
      从properties中获取到EnableAutoConfiguration.class(类名)对应的值,然后把他们添加在容器中
      

      将类路径下 META-INFO/spring.factories里面配置的所有EnableAutoConfiguration的值加入到了容器中;

      每一个这样的xxxAutoConfiguration类都是容器中的一个组件,都加入到了容器-中;用他们来做自动配置;

3)、每一个自动配置类进行自动配置功能

4)、以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

@Configuration //表示这是一个配置类,与以前编写的配置文件一样,也可以给容器中添加组件
@EnableConfigurationProperties(HttpEncodingProperties.class)  //启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncondingProperties绑定起来;

@ConditionalOnWebApplication  //spring底层@Conditional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效;  判断当前应用是否web应用,如果是,当前配置类生效

@ConditionOnClass  //判断当前项目有没有这个类CharacterEncodingFilter:SpringMVC中进行乱码解决的过滤器;
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) //判断配置文件中是否存在某个配置  spring.http.encoding.enabled:如果不存在,判断也是成立的
//即使我们配置文件中不配置spring.http.encoding.enabled=true,也是默认生效的
public class HttpEncodingAutoConfiguration{
    
    @Bean  //给容器中添加一个组件,这个组件的某些值需要从properties中获取

根据当前不容的条件判断,决定这个类是否生效?

一旦这个配置类生效:这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的。

5)、所有配置文件中能配置的属性都是在xxxProperties类中封装着;配置文件能配置什么就可以参照某个功能对应的这个属性类

精髓:

1)、SpringBoot启动会加载大量的自动配置类

2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;

3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们组件有,我们就不需要再来配置了)

4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,我们就可以在配置文件中指定这些属性的值。

xxxAutoConfiguration:自动配置类

给容器中添加组件

xxxProperties:封装配置文件中的相关属性

1、@Conditional派生注解(@Conditional作用)

作用必须是@Conditional指定的条件成立,才给容器中添加组件,配置里面的所有内容才生效;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oNTf4fY0-1605000337773)(images\15953136071202.png)]

自动配置类必须在一定条件下才能生效;

通过在application.properties中配置debug=true属性,来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;

============================
CONDITIONS EVALUATION REPORT
============================


Positive matches:(自动配置类启用的)
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

   AopAutoConfiguration.ClassProxyingConfiguration matched:
      - @ConditionalOnMissingClass did not find unwanted class'org.aspectj.weaver.Advice' 		(OnClassCondition)
      - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched 			       (OnPropertyCondition)

   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'javax.sql.DataSource', 				        'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'                      (OnClassCondition)
      - @ConditionalOnMissingBean (types: io.r2dbc.spi.ConnectionFactory; SearchStrategy: 			all) did not find any beans (OnBeanCondition)

Negative matches:(没有启动,没有配置成功的自动配置类)
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory'         (OnClassCondition)

   AopAutoConfiguration.AspectJAutoProxyingConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.aspectj.weaver.Advice'            (OnClassCondition)

pom.xml

spring-boot-dependencies:核心依赖在父工程中!

我们在写或者引入一些springboot依赖的时候,不需要指定版本号,就是因为有这些版本仓库

spring-boot-stater:场景启动器

启动器

  • <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
    </dependency>
    
  • 启动器:说白了就是springboot的启动场景

  • 比如spring-boot-starter-web,他就会帮我们自动导入web环境所有的依赖!

  • springboot会将所有的功能场景,都变成一个个启动器

  • 我们要使用什么功能,就只需要找到对应的启动器就可以了 starter

主程序

  • @SpringBootApplication
    public class HelloworldApplication {
    
        public static void main(String[] args) {
            //将springboot应用启动
            SpringApplication.run(HelloworldApplication.class, args);
        }
    
    }
    
  • 注解

    • @SpringBootConfiguration:  springboot配置
          @Configuration: spring配置类
          @Component: 说明这也是spring的一个组件
          
      @EnableAutoConfiguration:自动配置
          @AutoConfigurationPackage:自动配置包
          	@Import({Registrar.class}):spring的底层注解,给容器中导入一个组件
          @Import({AutoConfigurationImportSelector.class}):自动配置导入选择
      
          //获取所有的配置
           List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
          
      

      获取候选的配置

      META-INF/spring.factories:自动配置的核心文件
      

      结论:springboot所有自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效。

      1. springboot在启动的时候,从类路径下/META_INF/spring.factories获取指定的值!
      2. 将这些自动配置的类导入容器,自动配置类就会生效,帮我们进行自动配置!
      3. 以前我们需要自动配置的东西,现在springboot帮我们做了!
      4. 整合JavaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure-2.2.0.RELEASE.jar
      5. 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器。
      6. 容器中也会存在非常多的xxxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要的所有组件,并自动配置,@Configuration,@JavaConfig!
      7. 有了自动配置类,免去了我们手动编写配置文件的工作!

      SpringApplication

      这个类主要做了以下四件事情:

      1. 推断应用的类型是普通的项目还是web项目
      2. 查找并加载所有可用初始化器,设置到initializers属性中
      3. 找出所有的应用程序监听器,设置到listeners属性中
      4. 推断并设置main方法的定义类,找到运行的主类
2.2 配置文件加载位置

springboot启动会扫描以下位置的application.properties或者application.yml文件作为SpringBoot默认配置文件。

优先级:

  1. 项目路径下的config文件夹配置文件
  2. 项目路径下配置文件
  3. 资源路径(resource)下的config文件夹配置文件
  4. 资源路径(resource)下配置文件

优先级从高到低,高优先级的配置会覆盖低优先级的配置;

SpringBoot会从这四个位置加载主配置文件,互补配置【高优先级配置的用高优先级的,高优先级没有配置的,用低优先级的】;

我们还可以用spring.config.location来改变默认文件的位置

项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;【运维的时候用的比较多】

2.3 外部配置加载顺序

SpringBoot也可以从以下位置加载配置;优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置

  1. 命令行参数 java -jar xxxx.jar --server.port=8082

  2. 来自java:comp/env的NDI属性

  3. java系统属性(System.getProperties())

  4. 操作系统环境变量

  5. RandomValuePropertySource配置的random.*属性值

    由jar包外向jar包内进行寻找

    优先加载带profile

  6. jar包外部的application-{profile}.properties或application.yml(带spring-profile)配置文件

  7. jar包内部的application-{profile}.properties或application.yml(带spring-profile)配置文件

    再来加载不带profile

  8. jar包外部的application.properties或application.yml(不带spring-profile)配置文件

  9. jar包内部的application.properties或application.yml(不带spring-profile)配置文件

  10. @configuration注解类上的@PropertySource

  11. 通过SpringApplication.setDefaultProperties指定的默认属性

3.springboot web开发

使用SpringBoot:

1)、创建SpringBoot应用,选中我们需要的模块

2)、SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来

3)、自己编写业务代码

自动装配

springboot到底帮我们配置了什么?我们能不能进行修改?能修改哪些东西?能不能扩展

  • xxxxAutoConfiguration:向容器中自动配置文件
  • xxxxproperties:自动配置类,装配配置文件中自定义的一些内容。

要解决的问题:

  • 导入静态资源…
  • 首页
  • jsp,模板引擎
  • 装配扩展springMVC
  • 增删改查
  • 拦截器
  • 国际化

总结:

  1. 在springboot,我们可以使用以下方式处理静态资源
    • webjars --> localhost:8080/webjars/
    • public,static,/**,resources -->localhost:8080/
  2. 优先级:resources>static>public
4. SpringBoot常用注解
4.1 @SpringBootApplication注解

1.@SpringBootApplication:包含了@ComponentScan、@SpringBootConfiguration和@EnableAutoConfiguration。一般@SpringBootApplication注解放在项目的启动类上,用来把启动类注入到容器中,用来定义容器的扫描范围,用来加载classpath环境一些bean。【@SpringBootApplication同时拥有三种注解的功能】

1)@SpringBootConfiguration主要用来把bean注入到容器中,因为该注解又封装了@Configuration注解。@Configuration注解又封装了@Component注解,@Component注解主要用来把一个bean注入到容器中。因此,@SpringBootConfiguration注解就拥有了@Component注解的功能,用来把一个bean注入到容器中。

2)@EnableAutoConfiguration这个注释告诉SpringBoot“猜”你将如何配置Spring,基于你已经添加jar依赖项。如果spring-boot-starter-web已经添加Tomcat和SpringMVC,这个注解自动将假设您在开发一个web应用程序并添加相应的spring设置。自动设置被设计用来和“Starters”一起更好的工作,但是这两个概念并不直接相关。您可以自由挑选starter依赖意外的jar包,springboot仍将尽力自动配置您的应用程序。

3)@ComponentScan注解主要用来指定扫描容器的范围。

4)@SpringBootApplication的用法

package net.evecom.beans;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Configuration;

/*@SpringBootConfiguration注解包装了@Configuration注解,而@Configuration注解又包装了@Component注解,所以此地用三者注解中的任何一个都可以*/
@SpringBootConfiguration
//@Configuration
public class Person{
    
}

在启动类中获取Person类对应的bean

package net.evecom.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import net.evecom.beans.Person;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
        SpringApplication app = new SpringApplication(App.class);
        ConfigurableApplicationContext context = app.run(args);
        Person person = (Person) context.getBean("person");
        System.out.println(person);
    }
}

运行启动类,会报一个找不到person bean的异常。因为@SpringBootApplication注解默认只扫描该注解注解类所在的包,即默认只扫描net.evecom.demo包下的bean,但是person bean对应的类在net.evecom.beans下,所以在启动类中获取不到person。

用@SpringbootApplication注解中的scanBasePackages属性显示指定要扫描的包的范围。

package net.evecom.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import net.evecom.beans.Person;

/*指定扫描net.evecom包下的所有bean*/
@SpringBootApplication(scanBasePackages="net.evecom")
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
        SpringApplication app = new SpringApplication(App.class);
        ConfigurableApplicationContext context = app.run(args);
        Person person = (Person) context.getBean("person");
        System.out.println(person);
    }
}

运行启动类,会获取到person的bean

可以用@SpringBootApplication注解中的scanBasePackageClasses属性指定要扫描的类。

package net.evecom.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import net.evecom.beans.Person;

/*显示指定只扫描Person类,程序中只能加载Person类对应的bean*/
@SpringBootApplication(scanBasePackageClasses=Person.class)
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
        SpringApplication app = new SpringApplication(App.class);
        ConfigurableApplicationContext context = app.run(args);
        Person person = (Person) context.getBean("person");
        System.out.println(person);
    }
}

运行启动类,会获取到person的bean

可以用@SpringBootApplication注解中的exclude属性显示指定要排除的类。再建一个Animal类。

package net.evecom.beans;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Configuration;

@SpringBootConfiguration
public class Animal{
    
}

在启动类中获取bean

package net.evecom.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import net.evecom.beans.Animal;
import net.evecom.beans.Person;

/*exclude排除掉了扫描的类*/
@SpringBootApplication(scanBasePackages="net.evecom", exclude=Animal.class)
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
        SpringApplication app = new SpringApplication(App.class);
        ConfigurableApplicationContext context = app.run(args);
        /*可以获取到person的bean*/
        Person person = (Person) context.getBean("person");
        System.out.println(person);
        /*获取不到Animal类型的bean*/
        Animal animal = context.getBean(Animal.class);
        System.out.println(animal);
    }
}

运行启动类,只能获取到person的bean,不能获取关于Animal类型的bean。

可以使用@SpringBootApplication注解中的excludeName属性显示指定要排除的类的名字。

package net.evecom.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import net.evecom.beans.Animal;
import net.evecom.beans.Person;

@SpringBootApplication(scanBasePackages="net.evecom", excludeName="net.evecom.beans.Animal")
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
        SpringApplication app = new SpringApplication(App.class);
        ConfigurableApplicationContext context = app.run(args);
        /*可以获取perosn的bean*/
        Person person = (Person) context.getBean("person");
        System.out.println(person);
        /*获取不到Animal类型的bean*/
        Animal animal = context.getBean(Animal.class);
        System.out.println(animal);
    }
}

运行启动类,可以获取到person的bean,但是获取不到Animal类型的bean。

4.2 @EnableDiscoveryClient注解和@EnableEurekaClient注解

SpringCloud中的“Discovery Service”有多种实现,比如:Eureka,consul,zookeeper。

  1. @EnableDiscoverClient注解是基于spring-cloud-commons依赖,并且在classpath中实现;
  2. @EnableEurekaClient注解是基于spring-cloud-netflix依赖,只能为eureka作用;
  3. @EnableDiscoveryClient和@EnableEurekaClient共同点就是:都是能够让注册中心能够发现,扫描到该服务。
  4. @EnableEurekaClient只适用于Eureka作为注册中心,@EnableDiscoveryClient可以是其他注册中心。
4.3 @MapperScan和@Mapper的使用
  1. 使用@Mapper注解

    ​ 为了让DemoMapper类能够让别的类进行引用,我们可以在DemoMapper类上添加@Mapper注解:

    @Mapper
    public interface DemoMapper{
        @Insert("insert into Demo(name) values(#{name})")
        @Options(keyProperty="id", keyColumn="id",useGeneratedKeys=true)
        public void save(Demo demo);
    }
    

    直接在Mapper类上面添加注解@Mapper,但是这种方式要求每一个mapper类都需要添加此注解,非常麻烦

  2. 使用@MapperScan注解

    ​ 通过使用@MapperScan可以指定要扫描的Mapper类的包路径,比如:

    @MapperScan("net.evecom.*.mapper")
    public class App{
        public static void main(String[] args){
            SpringApplication.run(App.class,args);
        }
    }
    

    或者:

    @SpringBootApplication
    @MapperScan("net.evecom.mapper")
    public class App{
        public static void main(String[] args){
            SpringApplication.run(App.class,args);
        }
    }
    
  3. 使用@MapperScan注解多个包

    可以根据包的结构指定不同的表达式。

    使用@MapperScan注解多个包,可以使用如下的方式指定多个包:

    @SpringBootApplication
    @MapperScan({"net.evecom.mapper","net.evecom.demo"})
    public class App{
        public static void main(String[] args){
            SpringApplication.run(App.class,args);
        }
    }
    
4.4 @EnableFeignClients客户端详细

在Spring Cloud应用中,当我们要使用feign客户端时,一般要做以下三件事情。

  1. 使用注解@EnableFeignClients启用feign客户端;

    @SpringBootApplication
    /*@EnableFeignClients默认扫描并创建所在工程下的包。如果在SpringBoot分布式中需要用到别的微服务的工程的接口实例,那么就要写成如下形式:【此注解并不管理bean的依赖关系】
    @EnableFeignClients(
            basePackages = { "com.wisdombud.dth.boss.customer","com.wisdombud.dth.boss.his""com.wisdombud.dth.boss.product.srv"})   
    */
    @EnableFeignClients
    public class TestApplication{
        public static void main(String[] args){
            SpringApplication.run(TestApplication.class,args);
        }
    }
    
  2. 使用注解@FeignClient定义feign客户端;

    该例子定义了一个feign客户端,将远程服务http://test-service/test/echo映射为一个本地java方法调用。

    @FeignClient(name = "test-service", path = "/test")
    public interface TestService {
        @RequestMapping(value = "/echo", method = RequestMethod.GET)
        TestModel echo(@RequestParam("parameter") String parameter);
    }
    
  3. 使用注解@Autowired使用上面所定义的feign的客户端

    @Autowired   
        TestService testService;
    
        public void run()
        {
            // 这里的使用本地Java API的方式调用远程的Restful接口
            TestModel dto = testService.echo("Hello,你好!");
            log.info("echo : {}", dto);
         }
    

    上面三个步骤,前面两个步骤可以理解为定义feign客户端,第三步是使用所定义的feign客户端。通过调试发现,上面第三步所注入的testService是一个代理对象

    • 注解@EnableFeignClients:扫描和注册feign客户端bean定义
    • 注解@EnableFeignClients用于告诉框架扫描所有通过注解@FeignClient定义的feign客户端.
4.5 @EnableScheduling注解

要实现计划任务,首先通过在配置类注解@EnableScheduling来开启对计划任务的支持,然后在要执行计划任务的方法上注解@Scheduled,声明这是一个计划任务。

  1. @EnableScheduling注解开启对计划任务的支持

  2. @Scheduled注解

    package cn.hncu.p3.p3_taskscheduler;
     
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Service;
     
    import java.text.SimpleDateFormat;
    import java.util.Date;
     
    /**
     * Explain:计划任务执行类
     */
    @Service
    public class ScheduledTaskService {
        private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
     
        @Scheduled(fixedRate = 5000) //通过@Scheduled声明该方法是计划任务,使用fixedRate属性每隔固定时间执行
        public void reportCurrentTime(){
            System.out.println("每隔5秒执行一次" + dateFormat.format(new Date()));
        }
     
        @Scheduled(cron = "0 07 20 ? * *" ) //使用cron属性可按照指定时间执行,本例指的是每天20点07分执行;
        //cron是UNIX和类UNIX(Linux)系统下的定时任务
        public void fixTimeExecution(){
            System.out.println("在指定时间 "+dateFormat.format(new Date())+" 执行");
        }
    }
    
4.6 注解(annotations)列表
  1. @Controller:用于定义控制器类,在spring项目中由控制器负责将用户发来的URL请求转发到对应的服务接口(service层),一般这个注解在类中,通常方法需要配合注解@RequestMapping。
  2. @RestController:用于标注控制层组件(如struts中的action),@ResponseBody和@Controller的合集。
  3. @RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。
  4. @EnableAutoConfiguration:SpringBoot自动配置(auto-configuration):尝试根据你添加的jar依赖自动配置你的Spring应用。例如,如果你的classpath下存在HSQLDB,并且你没有手动配置任何数据库连接beans,那么我们将自动配置一个内存型(in-memory)数据库”。你可以将@EnableAutoConfiguration或者@SpringBootApplication注解添加到一个@Configuration类上来选择自动配置。如果发现应用了你不想要的特定自动配置类,你可以使用@EnableAutoConfiguration注解的排除属性来禁用它们。
  5. @ComponentScan:其实很简单,@ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中,你一定都有用过@Controller,@Service,@Repository注解,查看其源码你会发现,他们中有一个共同的注解@Component,没错@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中。当然,这个的前提就是你需要在所扫描包下的类上引入注解。
  6. @Configuration:相当于传统的xml配置文件,如果有些第三方库需要用到xml文件,建议仍然通过@Configuration类作为项目的配置主类——可以使用@ImportResource注解加载xml配置文件。
  7. @Import:用来导入其他配置类。
  8. @ImportResource:用来加载xml配置文件。
  9. @Autowired:自动导入依赖的bean
  10. @Service:一般用于修饰service层的组件
  11. @Repository:使用@Repository注解可以确保DAO或者repositories提供异常转译,这个注解修饰的DAO或者repositories类会被ComponetScan发现并配置,同时也不需要为它们提供XML配置项。
  12. @Bean:用@Bean标注方法等价于XML中配置的bean。
  13. @Value:注入Spring boot application.properties配置的属性的值。
  14. @Inject:等价于默认的@Autowired,只是没有required属性;
  15. @Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
  16. @Bean:相当于XML中的,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。
  17. @AutoWired:自动导入依赖的bean。byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。当加上(required=false)时,就算找不到bean也不报错。
  18. @Qualifier:当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用。@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者。
  19. @Resource(name=”name”,type=”type”):没有括号内内容的话,默认byName。与@Autowired干类似的事。
5、日志
5.1、日志框架

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

日志门面(日志的抽象层)日志实现
JCL(Jakarta Commons Logging) 、SLF4j(Simple Logging Facade for java) jboss-loggingLog4j、JUL(java.util.logging)、Log4j2、Logback

SLF4j(Simple Logging Facade for java)Log4jLogback出自同一人之手

左边选一个门面(抽象层)、右边来选一个实现:

日志门面:SLF4J;

日志实现:Logback;

SpringBoot选用SLF4j和Logback

5.2 SLF4J使用

1、如何在系统中使用SLF4J

以后在开发的时候,日志记录方法的调用,不应该直接调用日志的实现类,而是调用日志抽象层里面的方法;给系统里面导入SLF4J的jar和logback的实现jar

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

图示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5kAaZS92-1605000337779)(images\concrete-bindings.png)]

每一个日志的实现框架都有自己的配置文件,使用slf4j以后,配置文件还是用日志实现框架本身的配置文件

2、遗留问题

统一日志记录,即使是别的框架也和我一起使用slf4j进行输出。

图示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tlGcqRDl-1605000337791)(images\legacy.png)]

如何让系统中所有的日志都统一到slf4j:

1、将系统中其他日志框架先排除出去;

2、用中间包来替换原有的日志框架;

3、我们导入slf4j其他的实现

5.3 SpringBoot日志关系

SpringBoot使用它来做日志功能:

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

底层依赖关系:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oNnAzj5y-1605000337806)(images/企业微信截图_15953192527105.png)]

总结;

​ 1)、SpringBoot底层也是使用slf4j+logback方式进行日志记录;

​ 2)、SpringBoot也把其他的日志都替换成了slf4j;

​ 3)、中间替换包

​ 4)、如果我们要引入其他框架?一定要把这个框架的默认日志依赖移除掉。

SpringBoot能自动适配所有的日志,而且底层使用slf4j+logback的方式巨鹿日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉

5.4 日志使用

1、默认配置

SpringBoot默认帮我们配置好了日志:

//记录器
    Logger logger = LoggerFactory.getLogger(getClass());
    @Test
    void hcontextLoads() {

        //日志的级别,由低到高
        /*
        * 由低到高  trance<debug<info<warn<error
        * 可以调整输出的日志级别,日志只会在这个级别以后的高级别生效
        * */
        logger.trace("这是跟踪,trace日志");
        logger.debug("这是debug日志");
        /*
        * SpringBoot默认给我们使用的是info级别的,没有指定就用
        * SpringBoot默认规定的级别:root级别
        * */
        logger.info("这是info日志");
        logger.warn("这是警告,warn日志");
        logger.error("这是错误日志");
    }

2、指定配置

给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用它的默认配置了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K1ItTRKv-1605000337809)(images/企业微信截图_1595322554721.png)]

logback.xml:直接被日志框架识别了;

logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能。

<springProfile name="staging">
	<!-- configuration to be enabled when the "staging" profile is active -->
    可以指定某段配置只在某个环境下生效
</springProfile>

否则就会报错,找不到[springProfile].

5.5 切换日志框架

可以按照slf4j的日志适配图,进行相关切换;

6、错误处理机制

1)、SpringBoot默认的处理机制

默认效果:

​ 1]、返回一个默认的错误页面

​ 2]、如果是其他客户端,默认相应一个json数据

原理:

​ 可以参照ErrorMvcAutoConfiguration:错误处理的自动配置

​ 给容器中添加了以下组件

​ 1、DefaultErrorAttributes

帮我们在页面共享attributes值

​ 2、BasicErrorController:处理默认/error请求

public ModelAndView errorHtml(){} //产生html类型的数据;浏览器发送的请求来到这个方法处理

public ResponseEntity<Map<String,Object>> error(){} // 产生json数据;其他客户端来到这个方法处理

​ 3、ErrorPageCustomizer

​ 4、DefaultErrorViewResolver

步骤:

一旦系统出现4xx或者5xx之类的错误;ErrorPageCustomizer就会生效(定制错误的响应规则),就会来到/error请求,就会被BasicErrorController处理。

1)、响应页面;去哪个页面是由DefaultErrorViewResolver解析得到的

2)、如果定制错误的页面:

​ 1]、如何定制错误的页面

​ 1> 、有模板引擎的情况下:error/状态码:【将错误页面命名为错误状态码html放在模板引擎下的文件夹下的error文件中】

​ 我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确状态码.html)

​ 页面能获取的信息:

​ timestamp:时间戳

​ status:状态码

​ error:错误提示

​ exception:异常对象

​ message:异常消息

​ errors:jsr303数据校验的错误都在这里

​ 2>、没有模板引擎(模板引擎找不到这个错误的页面)的情况下,静态资源文件夹下找;

​ 3>、以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面

​ 2]、如何定制错误的json数据

​ 1>、自定义异常处理&返回固定列json数据

​ 2>、转发到/error进行自适应响应效果处理

​ 3>、将我们的定制数据携带出去

​ 出现错误以后,回来到/error请求,会被BaseErrorController处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)规定的方法);

​ 1、完全编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中。

​ 2、页面上能用的数据或者是json返回能用的数据都是通过errorAttributes.getErrorAttributes();默认进行数据局出炉

7、配置嵌入式Servlet容器

SpringBoot默认使用Tomcat作为嵌入式的Servlet容器

问题?

1)、如何定制和修改Servlet容器相关的配置

​ 1>、修改和server有关的配置

# 通用的servlet配置
serve.xxx

# tomcat的配置
server.tomcat.xxx

​ 2>、注册servlet三大组件[Servlet、Filter、Listener]

SpringBoot帮我们配置SpringMVC的时候,自动注册了SpringMVC的前端控制器DispatcherServlet

2)、Springboot能不能支持其他的serverlet容器

支持jetty、Undertow

步骤:

​ 1)、SpringBoot根据导入的依赖的情况,给容器中添加相应的EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】

​ 2)、容器中某个组件要创建对象就会惊动后置处理器;EmbeddedServletContainerCustomizerBeanPostProcessor;

​ 只要是嵌入式的Servlet容器工厂,后置处理器就开始工作;

​ 3)、后置处理器,从容器中获取所有的EmbeddedServletContainerCustomizer,调用定制器的定制方法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值