spring全家桶

2023-11-01

目录

一、Spring基础

1、Spring的核心模块

2、Spring中用到的设计模式

3、Spring、SpringMVC、SpringBoot、SpringCloud

二、SpringIOC

1、IOC的理解

 2、Spring中的循环依赖

3、ApplicationContext和BeanFactory的区别

4、BeanFactory和FactoryBean的区别

5、@Component和@Bean的区别

6、将一个类声明为Spring的bean的注解

7、Spring中的bean的作用域

8、Spring框架中的单例Bean是线程安全的么?

9、Spring中的bean生命周期

10、依赖注入的方式

11、如何实现一个IOC容器?

12、@Autowired和@Resource区别

三、SpringAOP

1、AOP的理解

2、SpringAOP与AspectJAOP区别

3、AOP的常见概念

4、通知类型

5、AOP的实现方式

四、Spring事务

1、Spring中事务的管理方式

2、@Transactional

属性:

作用范围:

实现原理:

自调用问题:

失效场景:

3、Spring事务中的隔离级别

4、Spring中事务传播行为

五、SpringMVC

1、对Spring MVC的了解

2、SpringMVC的核心组件

3、Spring MVC的工作原理

4、SpringMVC中参数传递方式

5、统一异常的处理

六、SpringBoot

1、什么是SpringBoot

2、为什么使用SpringBoot

3、SpringBoot的自动配置原理

4、SpringBoot启动自动执行代码的方式

5、SpringBoot的核心配置文件

6、Spring Boot Starter的理解

7、spring-boot-starter-parent作用

8、如何自定义Spring Boot Starter

9、SpringBoot 打成jar和普通的jar区别

10、使用Spring Boot实现异常处理

11、SpringBoot 实现热部署方式

12、Spring Boot中的监视器

13、Spring Boot 是否可以兼容老 Spring 项目吗

14、SringBoot导入配置文件数据方式

15、@ConfigurationProperties和@value的区别


一、Spring基础

1、Spring的核心模块

容器模块( Spring Core):是Spring框架最基础的部分,它提供了依赖注入(DI)特征来实现容器对Bean的管理。核心容器的主要组件是 BeanFactory,BeanFactory是工厂模式的一个实现,是任何Spring应用的核心

AOP模块(Spring AOP):提供了对面向切面编程的丰富支持,Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中,可以自定义拦截器、切点、日志等操作

Web模块(Spring Web):Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文,提供了Spring和其它Web框架的集成,比如Struts、WebWork。还提供了一些面向服务支持,例如:实现文件上传的multipart请求

Test模块(spring Test):提供了对JUnit和TestNG测试的支持。

数据访问(DataAccess):提供了数据访问功能,例如jdbc、orm框架、事务

Messageing:为 Spring 框架集成一些基础的报文传送应用。

2、Spring中用到的设计模式

1、单例模式:Spring中的Bean默认都是单例的

2、原型模式:Bean的作用域可以指定为prototype

3、工厂模式:在BeanFactory和ApplicationContext创建中用到了

4、代理模式:AOP动态代理

5、观察者模式:Spring中ApplicationListener、ApplicationEvent

6、策略模式:加载资源文件的方式,使用了不同的方法,比如: ClassPathResoureceFileSystemResource, ServletContextResource, UrlResource但他们都有共同的借口Resource; 在Aop的实现中,采用了两种不同的方式JDK动态代理和CGLIB代理

7、适配器模式:Adapter

8、模板方法模式:在BeanFactory和ApplicationContext实现中用到了

9、建造者模式:builder

10、责任链模式:使用AOP的时候会生成一个拦截器链

3、Spring、SpringMVC、SpringBoot、SpringCloud

Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都是Spring的IOC和AOP。IOC提供了依赖注入的容器, AOP解决了面向横切面编程,然后在此两者的基础上实现了其他延伸产品的高级功能;

SpringMVC是Spring基础之上的一个MVC框架,主要处理web开发的路径映射和视图渲染属于spring框架中WEB层开发的一部分;

springBoot主要是为了简化开发,约定大于配置,具有自动配置的功能,并且内置了Tomcat等服务器。

SpringCloud它和springBoot一样,注重的是微服务的开发,但是springCloud更关注的是全局微服务的整合和管理,相当于管理多个springBoot框架的单体微服务;

二、SpringIOC

1、IOC的理解

IOC:控制反转,原来我们使用的时候对象是由使用者控制的,有了spring之后,可以将整个象交给容器来帮我们进行管理。

DI:依赖注入,将对应的属性设置到具体的对象中,在工作中我们一般使用@Autowired、@Resource、PopulateBean方决来完成注入

容器:用来储存对象,使用Map的结构进行储存,在Spring储存对象的时候一般会有三级缓存,

SinaletonObiects:一级缓存,存放完整的对象

earlySinaletonObiects:二级缓存,存放半成品的对象

SinaletonFactory:三级缓存,存放lambda表达式和对象名称的映射。

整个Bean的生命周期从创建到使用到销毁,各个环节都是由容器来帮我们控制的。

当前,在整个IOC体系中还又很多细节的点,但是我是之前看的,太久了,记不清楚了。当然,Spring中所有的Bean都是通过反射生成的(主要是Construction和newInstance方法),在整个流程中还会包含很多扩展的点,比如有2个非常重要的接口(BeanFactoryPOSTProcess和BeanPOSTProcess),用来实现扩展功能。

 2、Spring中的循环依赖

 A对象中有B的属性b,而对象B有A的属性a,在A进行实例化后,就要进行赋值操作,但是A的赋值依赖于B,所以它就要去找内存中有没有B,发现没有B,所以就要创建一个B的实例,在B进行赋值时,发现需要A才能完成填充,而A又处于等待B的状态(是不是很像死锁),所以就会循环的互相依赖,这就叫循环依赖。

spring中bean对象的创建都要经历实例化和初始化(属性填充)的过程,根据对象的状态分类,存在半成品和成品对象的方式,来分别进行初始化和实例化,成品和半成品在存储的时候需要分不同的缓来进行存储;

1、只有一级缓存行不行?

不行,会把成品状态的bean对象和办成品状态的bean对象放到一起,而半成品对象是无法暴露给外部使用的,所以要将成品和半成品分来,一级缓存(singletonObjects)中放成品对象二级缓存(earlySingletonObjects)放半成品对象

2、只有二级缓存行不行?

如果整个应用程序中不涉及aop的存在,那么二级缓存中足以解决循环依赖的问题,如果aop中存在了循环依赖,那么就必须要使用三级缓存才能解决

3、为什么需要三级缓存?

三级缓存的value类型是ObiectFactory,是一个函数式接口,不是直接进行调用的,只有在调用getObiect方法的时候才会去调用里面存储的lambda表达式,存在的意义是保证在整个容器的运行过程中同名的bean对象只能有一个

缓存的存放时间和删除时间:

  • 三级缓存:crateBeanInstance后存放三级缓存(调用addSingletonFactory
  • 二级缓存:第一次从三级缓存中确定对象是代理对象还是普通的对象后存放二级缓存,同时删除三级缓存(整个过程在getSingleton方法中执行
  • 一级缓存:生成完整对象之后存放到一级缓存,同时删除二级缓存和三级缓存(整个过程在addSingleton方法中执行

名称 作用
singletonObjects 一级缓存:存放完整的Bean
earlySingletonObjects 二级缓存:存放提前暴露的Bean,Bean不是完整的,为完成属性注入和执行初始化方法
singletonFactories 三级缓存:存放的是Bean工厂,主要生产Bean,存放到二级缓存中

3、ApplicationContext和BeanFactory的区别

BeanFactory是访问Spring容器的顶级接口,采用延迟加载的形式来创建Bean,里面知识提供了一些基本方法的约束和规范。

而为了满足更多的需求,ApplicationContext实现BeanFactory接口,使用立即加载的形式创建Bean,并在此接口的基础上进行了某些功能的扩展(获取环境变量、事件发布、支持国际化),提供更多API的调用,一般我们在工作中更常使用ApplicationContext接口

4、BeanFactory和FactoryBean的区别

BeanFactory和FactoryBean都可以用来创建对象,只不过创建的流程和方式有些不同。

当使用BeanFactory的时候,我们必须要严格的遵守Bean的生命周期,需要经过一系列繁杂的步骤之后才可以创建出单例的对象,是流水线式的创建过程。

而FactoryBean是用户可以自定义Bean对象的创建流程,不需要按照Bean的生命周期来创建,在此接口中包含了3个方法:

isSingleton():判断改对象是否为单例的

getObjectType():获取对象的类型

getObject():在此方法中可以自己创建对象(使用new方式或代理对象的方式),用户可以按照自己的需求随意创建对象,在很多框架集成的时候都会实现该接口,比如Feign

5、@Component和@Bean的区别

首先@Component和 @Bean 是两种使用注解来定义bean的方式。

  • 作用对象:@Component注解作用于类,而@Bean注解作用于方法。
  • @Bean与配置类(使用@Configuration)一起使用,方法的返回值就是要注入到容器的Bean,方法的名称就是Bean的name;
  • @Component注解作用的类需要使用@ComponentScan注解一起使用,@Component注解作用的类在@ComponentScan注解扫描路径下才能将此类注入到容器中;
  • @Bean注解比@Component注解更加灵活,例如:引入第三方库、根据条件注入Bean

6、将一个类声明为Spring的bean的注解

  • @Component:通用的注解,可标注任意类为Spring组件。如果一个Bean不知道属于哪一个层,可以使用@Component注解标注。
  • @Repository:对应持久层,即Dao层,主要用于数据库相关操作。
  • @Service:对应服务层,即Service层,主要涉及一些复杂的业务逻辑
  • @Controller:对应Spring MVC的控制层,主要用于接受用户请求并调用Service层的方法返回数据给前端页面。

7、Spring中的bean的作用域

  • singleton:唯一bean实例,Spring中的bean默认都是单例的。

  • prototype:每次请求都会创建一个新的bean实例。

  • request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。

  • session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。

  • global-session:全局session作用域,Spring5中已经没有了。

如何定义Bean的作用域:

  • 在Bean标签中,可以通过bean定义中的scope属性进行设置;
  • 在注解创建Bean时,可以使用@Scope注解进行设置;

8、Spring框架中的单例Bean是线程安全的么?

Spring中的Bean对象默认是单例的,框架并没有对bean进行多线程的封装处理。

如果Bean是有状态的,那么就需要开发人员自己来保证线程安全的保证,最简单的办法就是改变bean的作用域把singleton改成prototype,这样每次请求bean对象就相当于是创建新的对象来保证线程的安全。

有状态就是由数据存储的功能。

无状态就是不会存储数据,你想一下,我们的controller,service和dao本身并不是线程安全的,只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制遍历,这是自己线程的工作内存,是最安全的。

因此在进行使用的时候,不要在bean中声明任何有状态的实例变量或者类变量,如果必须如此,也推荐大家使用ThreadLocal把变量变成线程私有,如果bean的实例变量或者类变量需要在多个线程之间共享,那么就只能使用synchrnized,lock,cas等这些实现线程同步的方法了。

9、Spring中的bean生命周期

Bean的生命周期主要包括实例化、属性填充和初始化3个关键的环节,当然在整个过程中会有一些扩展点的存在。

实例化:

1、实例化bean对象(源码中createBeanInstance方法):通过反射的方式进行对象的创建,此时的创建只是在堆空间中申请空间,属性都是默认值。

属性填充:

2、设置对象属性(源码中populateBean方法):给对象中的属性进行值的设置工作,可能出现循环依赖。

初始化:

3、检查Aware相关接口并设置相关依赖(BeanNameAware、BeanFactoryAware):如果对象中需要引用容器内部的对象,那么需要调用aware接口的子类方法来进行统一的设置

4、BeanPostProcessor的前置处理:对生成的bean对象进行前置的处理工作

5、判断当前bean对象是否设置了InitializingBean接口:进行属性的设置等基本工作

6、检查是否配置有自定义的init-method方法:如果当前bean对象定义了初始化方法,那么在此处调用初始化方法

7、BeanPostProcessor后置处理:对生成的bean对象进行后置的处理工作。(AOP的动态代理在此实现)

8、销毁Bean:首先会判断是否实现了DispoableBean接口,然后去调用destroyMethod方法

10、依赖注入的方式

  • 使用属性的set方法注入:通过setXxx()方法注入Bean的属性值或依赖对象,该方式要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。
    • 原理:Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值      
<!-- 属性注入 -->
<bean id="car" class="com.spring.model.Car">  
    <property name="maxSpeed" value="200"></property>
    <property name="brand" value="红旗CA72"></property>  
    <property name="price" value="200000.00"></property>
</bean>
  • 使用构造器注入:在类中,不用为属性设置setter方法,但是需要生成该类带参的构造方法,在配置文件中配置该类的bean,并配置构造器;
    • index:索引,指定注入的属性,从0开始;
    • type:指该属性所对应的类型;
    • ref :指引用的依赖对象;
    • value :注入的不是依赖对象,而是基本数据类型时,就用value
<!-- 构造函数注入(通过入参类型和位置索引确定对应关系) -->
<bean id="car3" class="com.spring.model.Car">  
    <constructor-arg index="0" type="java.lang.String" value="奔驰"></constructor-arg>
    <constructor-arg index="1" type="java.lang.String" value="中国一汽"></constructor-arg>
    <constructor-arg index="2" type="int" value="200"></constructor-arg>
</bean>
  • 使用注解注入(推荐):可以使用@Autowired或@Resource注解方式进行Spring的依赖注入;两者的区别是:@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean时,才会按类型装配。

11、如何实现一个IOC容器?

1、先准备一个基本的容器对象,包含一些map结构的集合,用来方便后续过程中存储具体的对象

2、进行配置文件的读取工作或者注解的解析工作,将需要创建的bean都封装成BeanDefinition对象存储在容器中

3、容器将封装好的BeanDefinition对象通过反射的方式进行实例化,完成对象的实例化工作

4、进行对象的初始化操作,也就是给类中的对应属性值就行设置,也就是进行依赖注入,完成整个对象的创建,变成一个完整的bean对象,存储在容器的某个map结构中

5、通过容器对象来获取对象,进行对象的获取和逻辑处理工作

 6、提供销毁操作,当对象不用或者容器关闭的时候,将无用的对象进行销毁

12、@Autowired和@Resource区别

1、来源不同:@Autowired 来自 Spring 框架,而 @Resource 来自于(Java)JSR-250;

2、依赖查找的顺序不同:@Autowired 先根据类型再根据名称查询,而 @Resource 先根据名称再根据类型查询;

3、支持的参数不同:@Autowired 只支持设置 1 个参数,而 @Resource 支持设置 7 个参数;

4、依赖注入的用法支持不同:@Autowired 既支持构造方法注入,又支持属性注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入;

5、编译器 IDEA 的提示不同:当注入 Mapper 对象时,使用 @Autowired 注解编译器会提示错误,而使用 @Resource 注解则不会提示错误。
 

三、SpringAOP

1、AOP的理解

AOP是IOC的一个扩展功能,先有的IOC,再有的AOP,只是在IOC的整个流程中新增的一个扩展点而已,在BeanPostProcessor的后置处理方法

AOP的意思是面向切面编程,主要应用于事务处理、日志管理、权限控制等,减少重复代码,降低耦合度,并有利于程序扩展和维护;

Spring AOP是基于动态代理的,如果要代理的对象实现了某个接口,那么就会使用JDK动态代理;而对于没有实现接口的对象,就使用CGlib动态代理。

2、SpringAOP与AspectJAOP区别

Spring AOP 属于运行时增强,基于代理(Proxying);而 AspectJ 是编译时增强,基于字节码操作。Spring AOP已经集成了AspectJ。AspectJ相比于Spring AOP功能更加强大,但是Spring AOP相对来说更简单。

3、AOP的常见概念

  1. 切面(Aspect):可以将@Aspect注解标注在类上,表示这个类是切面,切面中存放的是共公的代码。切面由通知和连接点组成
  2. 通知(Advice):在切面的某个特定的连接点上执行的动作,可以理解为切面类中的方法,是切面的具体实现。
  3. 连接点(Join Point):指的是在什么方法上添加公共代码
  4. 目标对象(Target Object):是指所有被通知的对象,也被称为被增强对象。如果AOP框架采用的是动态的AOP实现,那么该对象就是一个被代理对象。
  5. 代理(Proxy):将通知应用到目标对象之后,被动态创建的对象。
  6. 织入(Weaving):将切面代码插入到目标对象上,从而生成代理对象的过程。

总结:

目标对象某些方法(连接点)添加不同种类的操作(通知),最后通过织入操作实现一个新的代理目标对象

4、通知类型

通知的分类:

执行顺序:

  • 无异常情况下:

    环绕前通知——》前置通知——》执行业务代码——》环绕后通知——》后置通知——》返回通知

  • 有异常情况下:

    环绕前通知——》前置通知——》执行业务代码——》环绕后通知——》后置通知——》异常发生——》异常通知

5、AOP的实现方式

  • 静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;(AspectJAOP)
    • 编译时编织(特殊编译器实现)
    • 类加载时编织(特殊的类加载器实现)。
  • 动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
    • JDK 动态代理是 Java 语言自带的功能,无需通过加载第三方类实现;
      • JDK Proxy 是通过拦截器加反射的方式实现的;
      • JDK Proxy 只能代理实现接口的类;
    • CGLIB
      • CGLib 是第三方提供的工具,基于 ASM 实现的,性能比较高;
      • CGLib 无需通过接口来实现,它是针对类实现代理,主要是对指定的类生成一个子类,它是通过实现子类的方式来完成调用的。因为采用的是继承,所以不能对 final 修饰的类进行代理。

四、Spring事务

1、Spring中事务的管理方式

  • 编程式事务 : 在代码中硬编码(不推荐使用) : 通过 TransactionTemplate或者 TransactionManager 手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。
  • 声明式事务 : 在 XML 配置文件中配置或者直接基于注解(推荐使用) : 实际是通过 AOP 实现(基于@Transactional 的全注解方式使用最多)

2、@Transactional

属性:

作用范围:

1、方法 :推荐将注解使用于方法上,不过需要注意的是:该注解只能应用到 public 方法上,否则不生效。

2、类 :如果这个注解使用在类上的话,表明该注解对该类中所有的 public 方法都生效。

3、接口 :不推荐在接口上使用。

实现原理:

@Transactional 的工作机制是基于 AOP 实现的,AOP 又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理,如果目标对象没有实现了接口,会使用 CGLIB 动态代理。

如果一个类或者一个类中的 public 方法上被标注@Transactional 注解的话,Spring 容器就会在启动的时候为其创建一个代理类,在调用被@Transactional 注解的 public 方法的时候,实际调用的是,TransactionInterceptor 类中的 invoke()方法。这个方法的作用就是在目标方法之前开启事务,方法执行过程中如果遇到异常的时候回滚事务,方法调用完成之后提交事务。

自调用问题:

若同一类中的其他没有 @Transactional 注解的方法内部调用有 @Transactional 注解的方法,有@Transactional 注解的方法的事务会失效。

这是由于Spring AOP代理的原因造成的,因为只有当 @Transactional 注解的方法在类以外被调用的时候,Spring 事务管理才生效。

失效场景:

3、Spring事务中的隔离级别

  • 默认:使用后端数据库默认的隔离级别,Mysql默认采用可重复读;Oracle默认采用读已提交
  • 读未提交:事务尚未提交,其他事务即可以看到该事务的修改结果。隔离级别最差,脏读、不可重复读、幻读都不能避免。
  • 读已提交:事务只能看到其他事务提交之后的数据。可避免脏读,不可重复读、幻读无法避免。
  • 可重复度:一个事务多次查询,无论其他事务对数据如何修改,看到的数据都是一致的。可避免脏读、不可重复读,幻读无法避免。
  • 序列化:事务顺序执行,可避免脏读、不可重复读、幻读,但效率最差。因为A事务执行时,其他事务必须等待。

4、Spring中事务传播行为

支持当前事务的情况:

  • required(默认):如果当前没有事务,则创建一个新的事务。如果当前存在事务,则加入该事务
  • supports: 当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • mandatory: 当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

不支持当前事务的情况:

  • required_new: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
  • not_supported: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • never: 以非事务方式运行,如果当前存在事务,则抛出异常。

其他情况:

  • nested: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则等价于required

required_new与nested区别:required_new是新建一个事务并且新开始的这个事务与原有事务无关,而nested则是当前存在事务时会开启一个嵌套事务,在nested情况下,父事务回滚时,子事务也会回滚,而required_new情况下,原有事务回滚,不会影响新开启的事务。

nested和required的区别:required情况下,调用方存在事务时,则被调用方和调用方使用同一个事务,那么被调用方出现异常时,由于共用一个事务,所以无论是否catch异常,事务都会回滚,而在nested情况下,被调用方发生异常时,调用方可以catch其异常,这样只有子事务回滚,父事务不会回滚。

五、SpringMVC

1、对Spring MVC的了解

MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将业务逻辑、数据、显示分离来组织代码。

MVC是一种设计模式,而Spring MVC是MVC模式所实现的框架。

Spring MVC可以帮助我们进行更简洁的Web层的开发,并且它天生与Spring框架集成。

Spring MVC下我们一般把后端项目分为Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台页面)。

2、SpringMVC的核心组件

1、DispatcherServlet(核心的中央处理器负责接收请求、分发,并给予客户端响应。

2、HandlerMapping(处理器映射器根据 uri 去匹配查找能处理的 Handler ,并会将请求涉及到的拦截器和 Handler 一起封装。

3、HandlerAdapter(处理器适配器根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler

4、Handler(请求处理器:处理实际请求的处理器,也就是我们平常说的 Controller 控制器。

5、ViewResolver(视图解析器):根据 Handler 返回的逻辑视图,解析并渲染真正的视图,并传递给 DispatcherServlet 响应客户端

3、Spring MVC的工作原理

流程说明(重要):

1、客户端(浏览器)发送请求, DispatcherServlet拦截请求。

2、DispatcherServlet 根据请求信息调用 HandlerMapping(处理器映射器)他根据 uri 去匹配查找能处理的 Handler并返回给DispatcherServlet (也就是我们平常说的 Controller 控制器)。

3、DispatcherServlet 调用 HandlerAdapter适配执行 Handler ;Handler 完成对用户请求的处理后,会返回一个 ModelAndView 对象给DispatcherServlet

ModelAndView 包含了数据模型以及相应的视图的信息。

4、DispaterServlet 会调用ViewResolver 根据逻辑 View 查找实际的 View

5、DispaterServlet 把返回的 Model 传给 View进行渲染,并返回给DispaterServlet

6、DispaterServlet 把 View 返回给请求者(浏览器)

4、SpringMVC中参数传递方式

实体 Bean 接收请求参数:适用于 get 和 post 方式,Bean 的属性名称必须与请求参数名称相同。

@RequestMapping("/login")
public String login(@RequestBody User user) {
}

处理方法的形参接收请求参数:适用于 get 和 post 方式,直接把表单参数写在控制器类相应方法的形参中,即形参名称与请求参数名称完全相同。

@RequestMapping("/login")
public String login(String name, String pwd) {
}

HttpServletRequest 接收请求参数:适用于 get 和 post 方式,通过该类的getParameter等方法获取参数

@RequestMapping("/login")
public String login(HttpServletRequest request) {
    String name = request.getParameter("name");
    String pwd = request.getParameter("pwd");
}

@PathVariable 接收 URL 中的请求参数:

@RequestMapping("/login/{name}/{pwd}")
public String login(@PathVariable String name, @PathVariable String pwd) {
}

@RequestParam 接收请求参数:适用于 get 和 post 方式,在方法入参处使用此 注解指定其对应的请求参数

@RequestMapping("/login")
public String login(@RequestParam String name, @RequestParam String pwd) {
}

@ModelAttribute 接收请求参数:适用于 get 和 post 方式,将多个请求参数封装到一个实体对象中,从而简化数据绑定流程,而且自动暴露为模型数据,在视图页面展示时使用

@RequestMapping("/login")
public String login(@ModelAttribute("user") User user) {
}

5、统一异常的处理

推荐使用注解的方式统一异常处理,具体会使用到 @ControllerAdvice + @ExceptionHandler 这两个注解 

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    @ExceptionHandler(BaseException.class)
    public ResponseEntity<?> handleAppException(BaseException ex, HttpServletRequest request) {
      //......
    }

    @ExceptionHandler(value = ResourceNotFoundException.class)
    public ResponseEntity<ErrorReponse> handleResourceNotFoundException(ResourceNotFoundException ex, HttpServletRequest request) {
      //......
    }
}

这种异常处理方式下,会给所有或者指定的 Controller 织入异常处理的逻辑(AOP),当 Controller 中的方法抛出异常的时候,由被@ExceptionHandler 注解修饰的方法进行处理。

六、SpringBoot

1、什么是SpringBoot

Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。

  • 用来简化Spring应用的初始搭建以及开发过程,使用特定的方式来进行配置
  • 创建独立的Spring引用程序main方法运行
  • 嵌入的tomcat无需部署war文件
  • 简化maven配置
  • 自动配置Spring添加对应的功能starter自动化配置
  • SpringBoot来简化Spring应用开发,约定大于配置,去繁化简

2、为什么使用SpringBoot

  • 独立运行:内嵌了Tomcat、Jetty等服务器
  • 简化配置:避免大量的Maven导入和各种版本冲突。
  • 自动配置:Spring Boot 能根据当前类路径下的类、jar 包来自动配置 bean。
  • 无代码生成和XML配置:
  • 应用监控:提供一系列端点可以监控服务及应用,做健康检测。

3、SpringBoot的自动配置原理

启动类上面的注解是@SpringBootApplication,他也是SpringBoot的核心注解,主要组合包含了以下3个注解:

1、@SpringBootConfiguration:组合了@Configuration注解,实现配置文件的功能;

2、@EnableAutoConfiguration:打开自动配置的功能;内部实际上就去加载META-INF/spring.factories文件的信息,然后筛选出以EnableAutoConfiguration为key的数据,结合@Condition条件注解去生成Bean并加入到IOC容器中

3、@ComponentScan:Spring组件扫描。

4、SpringBoot启动自动执行代码的方式

Java自身启动加载方式:

  • static代码块:在类加载的时候自动执行。

  • 构造方法:在对象初始化的时候执行(在static后)

Spring启动加载方式:

  • @PostConstruct注解:标注在方法上,这个方法在对象依赖注入初始化后执行。
  •  ApplicationRunner接口:实现ApplicationRunner接口,重写run方法。SpringBoot在启动时会自动执行run方法。
  • CommandLineRunner接口:CommandLineRunner接口,重写run方法。SpringBoot在启动时会自动执行run方法。

默认加载顺序为:

static > 构造方法 > @PostConstruct > ApplicationRunner接口 > CommandLineRunner接口

5、SpringBoot的核心配置文件

SpringBoot的核心配置文件是application和bootstrap配置文件。

bootstrap的在application之前加载

application配置文件这个容易理解,主要用于Spring Boot项目的自动化配置。

bootstrap配置文件有以下几个应用场景:

  • 使用Spring Cloud Config配置中心时,这时需要在bootstrap配置文件中添加连接到配置中心的配置属性来加载外部配置中心的配置信息;
  • 一些固定的不能被覆盖的属性;
  • 一些加密/解密的场景

6、Spring Boot Starter的理解

和自动配置一样,Spring Boot Starter的目的也是简化配置,而Spring Boot Starter解决的是依赖管理配置复杂的问题,有了它,当我需要构建一个Web应用程序时,不必再遍历所有的依赖包,一个一个地添加到项目的依赖管理中,而是只需要一个配置spring-boot-starter-web, 同理,如果想引入持久化功能,可以配置spring-boot-starter-data-jpa:

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

Spring Boot 也提供了其它的启动器项目,包括用于开发特定类型应用程序的典型依赖项。

spring-boot-starter-web-services - SOAP Web Services

spring-boot-starter-web - Web 和 RESTful 应用程序

spring-boot-starter-test - 单元测试和集成测试

spring-boot-starter-jdbc - 传统的 JDBC

spring-boot-starter-hateoas - 为服务添加 HATEOAS 功能

spring-boot-starter-security - 使用 SpringSecurity 进行身份验证和授权

spring-boot-starter-data-jpa - 带有 Hibernate 的 Spring Data JPA

spring-boot-starter-data-rest - 使用 Spring Data REST 公布简单的 REST 服务

7、spring-boot-starter-parent作用

我们知道,新建一个SpringBoot项目,默认都是有parent的,这个parent就是spring-boot-starter-parent,spring-boot-starter-parent主要有如下作用:

  • 定义了Java编译版本
  • 使用UTF-8格式编码
  • 继承自spring-boor-dependencies,这里面定义了依赖的版本,也正是因为继承了这个依赖,所以我们在写依赖时才不需要写版本号
  • 执行打包操作的配置
  • 自动化的资源过滤
  • 自动化的插件配置

8、如何自定义Spring Boot Starter

  • 实现功能
  • 添加Properties
@Data
@ConfigurationProperties(prefix = "com.pdai")
public class DemoProperties {
    private String version;
    private String name;
}
  • 添加AutoConfiguration
@Configuration
@EnableConfigurationProperties(DemoProperties.class)
public class DemoAutoConfiguration {

    @Bean
    public com.pdai.demo.module.DemoModule demoModule(DemoProperties properties){
        com.pdai.demo.module.DemoModule demoModule = new com.pdai.demo.module.DemoModule();
        demoModule.setName(properties.getName());
        demoModule.setVersion(properties.getVersion());
        return demoModule;

    }
}
  • 添加spring.factory

在META-INF下创建spring.factory文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pdai.demospringbootstarter.DemoAutoConfiguration
  • install

9、SpringBoot 打成jar和普通的jar区别

Spring Boot 项目最终打包成的 jar 是可执行 jar ,这种 jar 可以直接通过java -jar xxx.jar命令来运行,这种 jar 不可以作为普通的 jar 被其他项目依赖,即使依赖了也无法使用其中的类。

Spring Boot 的 jar 无法被其他项目依赖,主要还是他和普通 jar 的结构不同。普通的 jar 包,解压后直接就是包名,包里就是我们的代码,而 Spring Boot 打包成的可执行 jar 解压后,在 \BOOT-INF\classes目录下才是我们的代码,因此无法被直接引用。如果非要引用,可以在 pom.xml 文件中增加配置,将 Spring Boot 项目打包成两个 jar ,一个可执行,一个可引用。

10、使用Spring Boot实现异常处理

Spring提供了一种使用ControllerAdvice处理异常的非常有用的方法。通过实现一个ControlerAdvice类,来处理控制类抛出的所有异常。

11、SpringBoot 实现热部署方式

主要有两种方式:

  • Spring Loaded
  • Spring-boot-devtools

12、Spring Boot中的监视器

Spring boot actuator是spring启动框架中的重要功能之一。Spring boot监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。

有几个指标必须在生产环境中进行检查和监控。即使一些外部应用程序可能正在使用这些服务来向相关人员触发警报消息。监视器模块公开了一组可直接作为HTTP URL访问的REST端点来检查状态。

13、Spring Boot 是否可以兼容老 Spring 项目吗

可以兼容,使用 @ImportResource 注解导入老 Spring 项目配置文件。

14、SringBoot导入配置文件数据方式

1、通过@ConfigurationProperties注解:先将一个类声明为配置类,然后在该类上增加此注解,通过此注解可以导入yml配置文件中的多个属性。

2、@Value:通过此注解可以导入yml配置文件中的单个属性。

3、@ImportResource:通过此注解可以导入多个xml的配置文件。

4、@Import:通过此注解可以导入多个配置类。

15、@ConfigurationProperties和@value的区别

1、@ConfigurationProperties作用在类上,@value作用在属性上;

2、@ConfigurationProperties主要用于多个字段的批量绑定,@value主要用单个字段的绑定;

3、@ConfigurationProperties支持松散绑定,@value不支持松散绑定;

4、@ConfigurationProperties支持所有类型的绑定(集合、对象、基本数据类型),@value只支持基本数据类型的绑定;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring全家桶 的相关文章

  • 使用 Ant 将非代码资源添加到 jar 文件

    我正在将 java 应用程序打包成 jar 文件 我正在使用 ant 和 eclipse 我实际上需要在 jar 中直接在根文件夹下包含几个单独的非代码文件 xml 和 txt 文件 而不是与代码位于同一位置 我正在尝试使用includes
  • JVisualVM/JConsole 中的 System.gc() 与 GC 按钮

    我目前正在测试处理 XML 模式的概念验证原型 并围绕一个非常消耗内存的树自动机外部库 我已经获得了源代码 构建 我想绘制 真实峰值 堆 随着模式大小的增加 不同运行的内存消耗 使用的指标符合我的目的并且不会影响问题 或者至少是它的合理近似
  • Spring Data JPA 选择不同

    我有一个情况 我需要建立一个select distinct a address from Person a 其中地址是 Person 内的地址实体 类型的查询 我正在使用规范动态构建我的 where 子句并使用findAll Specifi
  • Spring Boot自动装配存储库始终为空[重复]

    这个问题在这里已经有答案了 每次我进入我的服务类时 存储库似乎都没有自动连接 因为它不断抛出 NullPointerException 谁能帮我检查一下我缺少什么吗 这是我的代码 演示应用程序 java package com exampl
  • org.hibernate.QueryException:无法解析属性:文件名

    我正在使用休眠Criteria从列中获取值filename在我的桌子上contaque recording log 但是当我得到结果时 它抛出异常 org hibernate QueryException 无法解析属性 文件名 com co
  • Integer.parseInt("0x1F60A") 以 NumberformatException 结束

    我尝试从数据库中获取长字符串内的表情符号代码 格式如下 0x1F60A 所以我可以访问代码 但它将是String 起初 我尝试通过执行以下操作来转换变量tv setText beforeEmo getEmijoByUnicode int e
  • 使用 JUnit 时,有没有办法验证测试方法中是否调用了 try/catch 指令的 Catch 部分?

    例如 如果我想测试以下课程 public class SomeClass public void someMethod try Some code where comething could go wrong catch Exception
  • Jackson XML ArrayList 输出具有两个包装器元素

    我在 Jackson 生成的 XML 输出中得到了两个包装器元素 我只想拥有一个 我有一个 Java bean Entity Table name CITIES JacksonXmlRootElement localName City pu
  • 如何检测 Java 字符串中的 unicode 字符?

    假设我有一个包含 的字符串 我如何找到所有这些 un icode 字符 我应该测试他们的代码吗 我该怎么做呢 例如 给定字符串 A X 我想将其转换为 AYXY 我想对其他 unicode 字符做同样的事情 并且我不想将它们存储在某种翻译映
  • 内部存储的安全性如何?

    我需要的 对于 Android 我需要永久保存数据 但也能够编辑 并且显然是读取 它 用户不应访问此数据 它可以包含诸如高分之类的内容 用户不得对其进行编辑 我的问题 我会 并且已经 使用过Internal Storage 但我不确定它实际
  • GWT 2.3 开发模式 - 托管模式 JSP 编译似乎不使用 java 1.5 兼容性

    无法编译 JSP 类 生成的 servlet 错误 DefaultMessage 上次更新 0 日期 中 0 时间 HH mm ss z 语法 错误 注释仅在源级别为 1 5 时可用 在尝试以开发模式在 Web 浏览器中打开我的 gwt 模
  • HashMap 值需要不可变吗?

    我知道 HashMap 中的键需要是不可变的 或者至少确保它们的哈希码 hashCode 不会改变或与另一个具有不同状态的对象发生冲突 但是 HashMap中存储的值是否需要与上面相同 为什么或者为什么不 这个想法是能够改变值 例如在其上调
  • QuerySyntaxException:无法找到类

    我正在使用 hql 生成 JunctionManagementListDto 类的实际 Java 对象 但我最终在控制台上出现以下异常 org hibernate hql internal ast QuerySyntaxException
  • 如何在 Java 中创建接受多个值的单个注释

    我有一个名为 Retention RetentionPolicy SOURCE Target ElementType METHOD public interface JIRA The Key Bug number JIRA referenc
  • 是否可以使用 Java Guava 将函数应用于集合?

    我想使用 Guava 将函数应用于集合 地图等 基本上 我需要调整 a 的行和列的大小Table分别使所有行和列的大小相同 执行如下操作 Table
  • Android:无法发送http post

    我一直在绞尽脑汁试图弄清楚如何在 Android 中发送 post 方法 这就是我的代码的样子 public class HomeActivity extends Activity implements OnClickListener pr
  • 使用按钮作为列表的渲染器

    我想使用一个更复杂的渲染器 其中包含列表的多个组件 更准确地说 类似于this https stackoverflow com questions 10840498 java swing 1 6 textinput like firefox
  • 如何重新启动死线程? [复制]

    这个问题在这里已经有答案了 有哪些不同的可能性可以带来死线程回到可运行状态 如果您查看线程生命周期图像 就会发现一旦线程终止 您就无法返回到新位置 So 没有办法将死线程恢复到可运行状态 相反 您应该创建一个新的 Thread 实例
  • 如何使用play框架上传多个文件?

    我在用play framework 2 1 2 使用java我正在创建视图来上传多个文件 我的代码在这里 form action routes upload up enctype gt multipart form data
  • 在java中使用多个bufferedImage

    我正在 java 小程序中制作游戏 并且正在尝试优化我的代码以减少闪烁 我已经实现了双缓冲 因此我尝试使用另一个 BufferedImage 来存储不改变的游戏背景元素的图片 这是我的代码的相关部分 public class QuizApp

随机推荐

  • count(distinct 多个字段)

    select count distinct col1 col2 col3 from table 但是 这样是不允许的 因为count是不能统计多个字段的 虽然distinct是可行的 有种比较直接的方法就是把消除重复后在统计查询 selec
  • ubuntu 20.4 + openswan 实现点对点VPN

    需求背景 多个IDC机房或者办公地点 不同地址位置 用linux系统和软件 组一个局域网 共享网络资源 需求环境 ubuntu 20 4 openswan 实现点对点VPN 需要技能 熟悉ubuntu 会用日常网络指令 了解网络结构 理解私
  • 使用C++实现Flutter Windows插件

    上周实现的Flutter条形码插件已经发布到https pub dev packages flutter barcode sdk 平台相关部分只包含了Android的Java代码 这周新增用于Windows的C 代码 后续计划还包含iOS和
  • 关于scrapy网络爬虫的xpath书写经验总结

    借助于scapy的爬虫框架 能方便实现低网络数据的爬取 其中xpath如何写法 对元素的定位在爬取过程中起着至关重要的作用 以下是对xpath写法的一些经验 1 优先遵循 自底向上 原则 即从所要爬取的字段节点出发 层层向上 向父节点去遍历
  • 判断App版本号

  • 各个硬件的工作原理

    前情回顾 主存储器的基本组成 存储体 用于存放数据的东西 由一系列的存储元件构成 可以存放二进制的 0 和 1 运算器的基本组成 控制器的基本组成 计算机的工作过程 案例分析 执行指令0 执行指令1 执行指令2 执行指令3 执行指令4 总结
  • Pytorch 提取权重等参数 写入Excel

    Pytorch 提取权重等参数 写入Excel表 标签 Pytorch Topic 网络参数导出 时间 2022 5 27 写在最前 最近有在做量化相关的东西 不确定是不是我这边没设置好怎么 量化后只给出了相应层的s z值 这里就需要将网络
  • JavaWeb-Filter过滤器

    Filter过滤器是JavaWeb的三大组件之一 Filter过滤器是JavaEE的规范也就是接口 Filter的作用是拦截请求 过滤响应 拦截请求常见的应用场景 权限检查 日志操作 事务管理等等 Filter过滤器的基本使用 例如权限检查
  • Activity沉浸式

    沉浸式依赖 implementation com gyf immersionbar immersionbar 2 3 3 beta05 ImmersionBar with this transparentStatusBar 透明状态栏 不写
  • go 源码分析string、[]byte的相互转换

    string 简单的来说字符串是一系列8位字节的集合 通常但不一定代表UTF 8编码的文本 字符串可以为空 但不能为nil 而且字符串的值是不能改变的 不同的语言字符串有不同的实现 在go的源码中src runtime string gos
  • 怎么阅读源码【调试观察源码】

    读源码需要掌握的编译器知识 编译器为eclipse为例子 调试准备工作 步骤 Window gt Show View 打开调试断点Breakpoint 打开变量监视 要看一个方法的内部细节 按f5 进入 要快速跳到某个位置 在目标位置上打个
  • 【蓝桥杯嵌入式最全备考资料】真题、代码、原理图、指导手册、资源包等

    目录 前言 公众号回复 蓝桥杯 获取全部资料 欢迎大家过来关注一起玩呀 一 蓝桥杯嵌入式省赛个人总结的模板流程 十四届模拟试题 详解 超详细 二 第六 十四届省 国赛真题 主观题 客观题 三 蓝桥杯 全国软件和信息技术专业人才大赛实训指导书
  • C#中this的 四种 用法

    C 中的this用法 相信大家应该有用过 但你用过几种 以下是个人总结的this几种用法 欢迎大家拍砖 废话少说 直接列出用法及相关代码 this用法1 限定被相似的名称隐藏的成员
  • WIN10与VMware中的Ubuntu20.04.3系统文件共享(可视化界面居多、无脚本)

    1 在WIN10本地创建一个用于共享的文件夹 2 安装VMware Tools并完成配置 3 开启 共享文件夹
  • 我用了两年时间去读《Thinking in Java》

    路漫漫其修远兮 吾将上下而求索 题记 我用了两年时间去读 Thinking in Java 无论在学校还是在工作 都能听到过来人说 Java编程思想是一本经典著作 于是乎在工作以后 我就买了一本来看看 后来呢 在这断断续续两年时间 精读略读
  • 域名反查、权重查询以及ICP备案查询——ipInfoSearch

    域名反查 权重查询以及ICP备案查询 ipInfoSearch ipInfoSearch 一 配置需要python三方包 二 基本用法 三 多线程用法 文中工具已上传至github https github com Potato py ip
  • 时域和空域和频域

    傅立叶变换是f t 乘以正弦项的展开 正弦项的频率由u 其实是miu 的值决定 因为积分后左边剩下的为一变量是频率 所以我们说傅立叶变换域是频率域 数字图像处理 冈萨雷斯 中文第三版P128 当变量t用于说明图像时 我们一般将变量t的域称为
  • [Python人工智能] 四.神经网络和深度学习入门知识

    从本篇文章开始 作者正式开始研究Python深度学习 神经网络及人工智能相关知识 前三篇文章讲解了神经网络基础概念 Theano库的安装过程及基础用法 theano实现回归神经网络 theano实现分类神经网络 这篇文章又回到基础知识 结合
  • Chromedriver安装教程【无需翻墙】

    第一步 查看你当前Chrome浏览器的版本 如下图所示 第二步 查看当前Chrome浏览器的版本号 如下图所示 版本 108 0 5359 125 正式版本 64 位 中的 108就是我们的版本号 第三步 到谷歌驱动下载地址 https n
  • spring全家桶

    目录 一 Spring基础 1 Spring的核心模块 2 Spring中用到的设计模式 3 Spring SpringMVC SpringBoot SpringCloud 二 SpringIOC 1 IOC的理解 2 Spring中的循环