1.Spring框架的基本理解(重点)
记忆关键字:1.核心思想(IOC、AOP)2.作用(解耦、简化)3.简单描述框架组成
定义: Spring是一个轻量级的控制反转(loC)和面向切面(AOP)的容器(框架)。
**核心思想:**核心是IOC(控制反转)和AOP(面向切面编程)
**作用:**用于组件之间的解耦,以及简化第三方JavaEE中间技术的使用(JMS、任务调度、缓存、ORM框架
**框架组成:**IOC容器、Validation数据校验、AOP面向切面编程、Transactions事务管理、Spring JDBC、Spring MVC框架、以及各类第三方JavaEE中间件技术集成。
2、Spring框架由哪些模块组成?(重点)
记忆关键字:官方文档描述,由7个模块组成
Spring Framework根据官方文档的描述,主要包括以下常用5个模块:
①core:核心模块
包括:IOC Container(loc容器),Events(事件通知机制)、Resources(资源加载机制)、i18n(国际化)、Validation(数据校验).Data Binding(数据绑定)、Type Conversion(类型转换),SpEL(Spring表达式)、AOP(面向切面编程)
②Testing:测试模块
包括:Mock Obiects(测试模拟对象),TestContext Framework(测试框架),Spring MVCTest(用于测试Spring Mvc),webTestclient(用于测试 Webclient、Restful、webflux等);
③Data Access:数据访问模块
包括:Transactions(事务管理),DAOsupport(统一的Data Access Object DAO模式封装),JDBc(Spring对于DC的操作封装),O/RMapping(Spring 对于对象关系映射框架的封装,例如Hibernate等框架)等;
④Web Servlet:基于Servlet的Web应用开发
包括:Spring MNc( Spring基于MVC模式设计封装的Web框架),Websocket(Spring集成Websocket,websocket是一个服务器与客户端双向通信的技术)等;
⑤Integration:企业级系统集成模块(不同系统之间的交互集成)
包括:Remoting(spring 用于在分布式系统中进行远程服务调用的通讯框架),IMS(Spring集成各类Java消息中间件、Java消息服务[JavaMessage Service]、例如ActiveMQ等),Java Emai1(邮件发送),Tasks Scheduling(任务调度);
3.Spring IOC的理解(重点)
记忆关键字:IOC名词解释,作用是解耦,使用IOC容器管理项目组件之间的耦合关系。
lOC(Inversion of Control,中文释义∶控制反转),是Spring框架的核心思想之一,主要用于解耦。
IOC是指将创建对象的控制权转移给Spring框架进行管理,由Spring框架根据配置文件或注解等方式,创建bean对象并管理各个bean对象之间的依赖关系。使对象之间形成松耦合的关系,实现解耦。
控制:指的是对象的创建(实例化、管理)的权利
反转:控制权交给外部环境(Spring框架、IOC容器)
4.Spring IOC容器的理解(重点)
记忆关键字:IOC容器的作用、存储形式、初始化过程
①I0C通常被理解为IOC Container容器,I0C容器其实就是一个Map,key是每个 bean对象的ID,value是bean对象本身。IOC容器负责创建bean对象并管理 bean的生命周期并且根据配置好配置文件或注解,管理IOC容器中的每个bean,以及根据 bean之间的依赖关系,完成bean之间的注入。
②IOC容器属于Spring core模块,用来创建和管理Bean,默认使用单例的方式将bean存储在DefaulListableBeanFactory类的beanDefinitionMap中(-个 ConcurrentHashMap类型的Map集合);
③IOC容器使用ConcurrentHashMap集合存储了BeanDefinition对象,该对象封装了Sprin8对一个Bean所有配置信息,包括:类名,属性,构造方法参数,依赖,是否延迟加载,是否是单例等配置信息;
5.Spring DI的理解
记忆关键字:名词解释
DI ( Dependecy Inject,中文释义︰依赖注入)是对IOC概念的不同角度的描述,是指应用程序在运行时,每一个bean对象都依赖IoC容器注入当前bean对象所需要的另外一个bean对象。(例如在(MyBatis 整合Spring时, SqlSessionFactoryBean依赖(IOC 容器注入一个Datasource数据源bean ) ;
6.什么是Spring 的bean
简单来说,Bean代表被IoC容器管理的对象。
我们通过配置文件或注解,告诉IoC容器帮助我们管理哪些对象。
<bean id="student2" class="com.ztt.pojo.Student">
<constructor-arg name="stuName" value="甜甜"></constructor-arg>
<constructor-arg name="stuAge" value="18"></constructor-arg>
<constructor-arg name="stuHobby" value="学习"></constructor-arg>
</bean>
7.将一个类声明为Bean的注解有哪些?
@Component:定义通用Bean的注解,可标注任意类为Bean。如果一个Bean 不知道属于哪个层,可以使用@Component注解标注。
@Repository:定义数据访问层Bean的注解。
@service:定义业务层Bean的注解。
@controller:定义控制器Bean的注解。
8.@Component和@Bean的区别是什么?
@Component 注解作用于类,而@Bean注解作用于方法。
@Component通常是通过类路径扫描来实现自动扫描并完成装配Bean到Spring Ioc容器中。
@Bean注解通常用于注解某个方法,通过@Bean注解告诉了Spring Ioc容器,该方法的返回值实例是一个Bean 。
9.@Autowired和@Resource的区别是什么?
@Autowired是 Spring提供的注解,@Resource是JDK提供的注解。
@Autowired默认的注入方式为byType(按类型自动注入),@Resource默认注入方式为 byName(按名称自动注入)。
10.Spring框架中的常见注入方式有几种?
记忆关键字:整体介绍三种注入方式、分别介绍每个注入方式的细节.
Spring Ioc有三种注入方式:构造注入、Setter注入、属性注入;
构造注入 :使用构造方法注入bean ;
Setter注入 :使用Setter方法注入bean ;
属性注入:使用成员属性注入bean,不推荐。原因:使用私有的成员属性变量,依靠反射实现,破坏封装,只能依靠IoC容器实现注入,不严谨;
11. Spring中常见的ApplicationContext实现类有哪些?
记忆关键字:分别介绍每种实现类或子接口
ClassPathXmlApplicationContext: 根据项目类路径classpath下的配置文件加载bean **FileSystemXmlApplicationContext:**根据当前磁盘的一个绝对系统文件路径下的配置文件加载bean ;
**AnnotationConfigApplicationcontext:**根据读取到的注解加载bean ;
webApplicationContext : web容器下按照配置文件加载 bean ;
12. BeanFactory和ApplicationContext有什么区别?
记忆关键字:两者之间的关系、区别与不同、Bean的创建加载方式
两者之间的关系: BeanFactory 和ApplicationContext 是 Spring 的两大核心接口,都可以当做Spring 的容器;
两者区别与不同:
BeanFactory是 Spring里面最底层的接口,是Ioc的核心,定义了Ioc的基本功能,包含了各种Bean的定义、加载、实例化,依赖注入和生命周期管理等行为;
ApplicationContext接口作为BeanFactory 接口的子接口,包含BeanFactory所具备的功能外,还提供了其它框架功能:继承MessageSource(支持国际化),资源文件访问、可以同时加载多个配置文件、可以通过监听器管理bean的生命周期;
Bean的创建加载方式:
BeanFactroy采用的是延迟加载形式来注入Bean,只有在使用到某个 Bean时,才对该Bean进行加载实例化。这样不能提前发现一些存在的 Spring 的配置问题。如果 Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean()方法才会抛出异常;
ApplicationContext是在容器启动时,一次性创建了所有的 Bean。这样,在容器启动时,我们就可以发现Spring 中存在的配置错误,这样有利于检查所依赖属性是否注入。ApplicationContext 启动后预载入所有的单实例 Bean,所以在运行的时候速度比较快,因为它们已经创建好了。相对于 BeanFactory , ApplicationContext唯一的不足是占用内存空间,当应用程序配置Bean较多时,程序启动较慢;
14. Spring框架中的Bean的作用域
- singleton : Spring 只会为该bean对象只会创建唯一实例,Spring中的 bean默认都是单例;
- prototype:每次获取 bean ,Spring会创建一个新的bean 实例;
- request:每一次HTTP 请求,Spring会创建一个新的bean 实例;
- session:不同的HTTP会话,Spring会创建不同的bean 实例;
通过XML方式设置bean的作用域
通过XML方式设置bean的作用域
1<bean id="demoDaoBean" class=" com.apesource.dao.DemoDAOImpl" scope="singleton" />
通过注解方式设置bean的作用域
1 @Scope(configurableBeanFactory.sCOPE_PROTOTYPE)
2public class DemoDAOImpl implements IDemoDAO{ }
15. Spring框架中的Bean的线程安全
- 对于 prototype作用域的Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题
- 对于singleton作用域的Bean,所有的线程都共享一个单例状态的 Bean,存在资源竞争,因此是存在线程安全问题的
- 解决办法:
-
- 对于singleton作用域的单例bean,它的线程安全问题,常见有两种解决办法:
-
-
- 在bean中尽量避免定义可变的成员变量(用于保存数据的成员变量);
- 在类中定义一个ThreadLocal成员变量,将需要可变的成员变量保存在ThreadLocal中;
-
16.Spring 框架中的Bean生命周期
- Spring Bean 的生命周期总体分四个阶段:实例化=>属性注入=>初始化=>销毁
- Step1实例化Bean:根据配置文件中Bean 的定义,利用Java Reflection反射技术创建Bean的实例
- Step2注入对象依赖的属性值(或对象)
- Step3处理各种Aware接口:Spring 会检测该Bean是否实现了xxxAware接口,通过(Aware类型的接口,可以让Spring框架为当前Bean注入相应的内容。
-
- 如果Bean实现 BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,注入Bean的名字;
- 如果 Bean实现 BeanclassLoaderAware接口,调用setBeanClassLoader()方法,注入classLoader对象的实例;
- 如果Bean实现BeanFactoryAware 接口,会调用它实现的setBeanFactory()方法,注入的是Spring工厂;
- 如果 Bean实现 ApplicationContextAware接口,会调用setApplicationContext()方法,注入Spring上下文;
- Step4执行BeanPostProcessor前置处理:如果想对Bean进行一些自定义的前置处理,那么可以让Bean 实现了(BeanPostProcessor接口,将会在该阶段调用postProcessBeforeInitialization(Object obj,string s)方法。
- Step5执行InitializingBean初始化方法:如果Bean 实现了InitializingBean接口,执行afeterPropertiesSet()方法。
- Step6执行init-method自定义初始化方法:如果Bean 在 Spring 配置文件中配置了init-method属性,则会自动调用其配置的初始化方法。
- .Step7执行BeanPostProcessor后置处理:如果这个 Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(0bject obj,string s)方法,由于这个方法是在 Bean初始化结束后调用;
- 以上几个步骤完成后,|Bean已经被正确创建,可以正常使用这个Bean
- Step8执行DisposableBean销毁Bean:当Bean 不再需要时,会经过清理阶段,如果Bean 实现了DisposableBean这个接口,会调用其实现的destroy()方法执行销毁;
- Step9执行destroy-method自定义销毁方法:如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的自定义销毁方法。
17.Spring框架如何解决循环依赖?
- 循环依赖问题是指:类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。例如A类依赖了B类,B类依赖了C类,而最后C类又依赖了A类,这样就形成了循环依赖问题;
一级缓存:存储的是完整的、初始化后的单例(Singleton)Bean 实例。
二级缓存:存储的是早期的 Bean 实例,通常是已经实例化但还未进行完全初始化(如未完成属性填充)的 Bean。
三级缓存:存储的是一个 Bean 的工厂对象,用于创建半成品的 Bean 实例(通常是代理对象)。
18. Spring框架中有哪些注解?
- 用于声明Bean的注解:
-
- @Component:定义通用Bean的注解,可标注任意类为Bean。如果一个Bean 不知道属于哪个层,可以使用@Component注解标注。
- @Repository:定义数据访问层Bean的注解。
- @service:定义业务层Bean的注解。
- @controller:定义控制器Bean的注解。
- 用于注入的注解:
-
- @Autowired :按类型自动注入
- @Qualifier :按名称自动注入
- 声明配置、扫描、启用特性的注解:
-
- @Configuration :声明配置类
- @Componentscan :组件扫描
- @Enablescheduling :启用任务调度
- @EnableAspectAutoProxy :启用自动代理工厂
19. Spring框架中用到的设计模式
- 工厂模式: Spring使用工厂模式,通过BeanFactory或 Applicationcontext来创建对象;
- 单例模式: Bean默认作用域为单例,按照单例设计模式进行设计实现;
- 策略模式:Resource的实现类,针对不同的资源文件,实现了不同方式的资源获取策略;
- 代理模式:Spring 的AOP的实现依靠动态代理(JDK的反射和CGLIB) ;
- 模板方法:Spring 提供了JdbcTemplate,RedisTemplate等模板对象,将相同的操作步骤进行了封装;
- 适配器模式:Spring AoP 的增强或通知(Advice)使用到了适配器模式,Spring MvC 中也用到了适配器模式适配Controller ;
20. Spring框架中AOP的基本理解
- 关键字:AOP名词解释,AOP实现原理(动态代理)
- AOP ( Aspect-Oriented Programming:面向切面编程)︰将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为"切面"(Aspect ),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;
- Spring AOP基于动态代理实现:
-
- 如果被代理的对象,已经实现某个接口,则Spring AOP会使用JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是(InvocationHandler 接口和Proxy类);
- 如果被代理的对象,没有实现某个接口,就无法使用JDK Proxy去进行代理了,这时候Spring AOP会使用Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(cglib动态代理的核心是 MethodInterceptor接口和Enhancer类);
21.Spring AOP和AspectJ AOP有什么区别?
- 关键字:增强方式的差异(运行时、编译时),实现方式的差异(动态代理、字节码操作)
- Spring AoP已经集成了Aspect], Aspect]是一个Java技术生态系统中实现 AOР编程思想的独立框架;Aspect]相比于Spring AOP功能更加强大,但是Spring AoP相对来说更简单更容易;
- Spring AOP属于运行时增强,而Aspect是编译时增强;
- Spring AOP基于动态代理(Proxying ),而Aspect]基于字节码操作( Bytecode Maripulation );
22. Spring AOP有哪些通知类型?
- 关键字:分别介绍每种通知的实现接口,执行方式
- 前置通知:实现 MethodBeforeAdvice接口,在目标方法调用前,执行通知;
- 环绕通知:实现 MethodInterceptor 接口,是一个包围目标方法的通知。环绕通知可以在方法调用前后完成自定义的行为。
- 后置通知:实现AfterReturningAdvice接口,在在目标方法调用后,执行通知(如果方法抛出异常,则不执行通知);
- 异常通知:实现ThrowsAdvice接口,在方法抛出异常时,执行通知;
23. Spring 管理事务的方式有几种?
- 编程式事务︰在代码中硬编码(不推荐使用):通过TransactionTemplate或者TransactionManager手动管理事务,实际应用中很少使用,用于理解Spring事务管理。
- 声明式事务:在XML配置文件或者基于注解@Transactional推荐使用),通过AOP实现。
24. Spring事务中有哪几种事务传播行为?
- 事务传播行为是为了解决业务层方法之间互相调用时,产生事务问题。
- 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
- 事务传播行为有如下分类:
- TransactionDefinition.PROPAGATION_REQUIRED
如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。@Transactiona1注解默认使用的事务传播行为。
2.TransactionDefinition.PROPAGATION_REQUIRES_NEW
创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEw修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
3.TransactionDefinition.PROPAGATION_NESTED
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
4.TransactionDefinition.PROPAGATION_MANDATORY
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:代表强制性)
5.TransactionDefinition.PROPAGATION_SUPPORTS
如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- TransactionDefinition.PROPAGATION_NOT_sUPPORTED
以非事务方式运行,如果当前存在事务,则把当前事务挂起。7.TransactionDefinition.PROPAGATION_NEVER
以非事务方式运行,如果当前存在事务,则抛出异常。
25.Spring 事务中有哪几种事务隔离级别?
- TransactionDefinition.ISOLATION_DEFAULT 默认隔离级别
使用当前数据库的默认隔离级别,MySQL默认采用的是可重复读REPEATABLE_READ隔离级别。oracle 默认采用的是读已提交READ_COMMITTED隔离级别.
- TransactionDefinition.ISOLATION_READ_uNCOMMITTED读未提交
最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读3. TransactionDefinition.ISOLATION_READ_COMMITTED读已提交
允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生4. TransactionDefinition.ISOLATION_REPEATABLE_READ可重复读
对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- TransactionDefinition.ISOLATION_SERIALIZABLE串行化
最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
26. Spring事务在什么情况下会失效
1.数据库不支持事务
Spring事务生效的前提是所连接的数据库要支持事务,如果底层的数据库都不支持事务,则Spring的事务肯定会失效。例如:如果使用的数据库为MysQL,并且选用了MyISAM存储引擎,则 Spring 的事务就会失效。
2.事务方法未被Spring管理
如果事务方法所在的类没有加载到Spring Ioc 容器中,也就是说,事务方法所在的类没有被Spring 管理,则Spring 事务会失效。例如: Productservice类上没有标注@service注解,(Product的实例没有加载到Spring Ioc容器中,就会造成_updateProductStockCountById()方法的事务在Spring中失效。
public class ProductService {
@Autowired
private ProductDao productDao;
@Transactional(propagation = Propagation.REQUIRES_NEw)
public void updateProductStockCountById(Integer stockCount,Long id){productDao.updateProductstockcountById(stockCount,id);
}
}
3.方法没有被public修饰
如果事务所在的方法没有被public修饰,此时Spring 的事务会失效,例如:虽然 ProductServEice上标注了@service注解,同时updateProductstockCountById()方法上标注了@Transactional(propagation = Propagation.REQUIRES_NEW)注解。
但是,由于updateProductStockCountById()方法为内部的私有方法(使用 private修饰),那么此时updateProductStockCountById()方法的事务在Spring中会失效。
@service
public class ProductService {@Autowired
private ProductDao productDao;
@Transactional(propagation = Propagation.REQUIRES_NEw)
private void updateProductStockCountById(Integer stockCount,Long id){productDao.updateProductstockCountById(stockcount, id);
}
4.同一类中方法调用
如果同一个类中的两个方法分别为A和B,方法A上没有添加事务注解,方法B上添加了@Transactional事务注解,方法A调用方法B,则方法B的事务会失效。例如:(submitorder()方法和updateProductStockCountById()方法都在OrderService类中,submitOrder()方法上没有标注事务注解,_updateProductStockCountById()方法上标注了事务注解,submitorder()方法调用了(updateProductStockCountById()方法,此时,(updateProductStockCountById()方法的事务在Spring中会失效。
@Service
public class orderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
public void submitorder( ){//生成订单
order order = new Order();
long number = Math.abs(new Random( ).nextInt( 500) );order.setId(number);
order.setOrderNo( "order_" +number);orderDao.saveOrder( order);
//减库存
this.updateProductstockCountById(1,1L);}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateProductStockCountById(Integer stockCount,Long id){productDao.updateProductStockCountById(stockCount,id);
)
5.未配置事务管理器
如果在项目中没有配置Spring的事务管理器,即使使用了Spring 的事务管理功能,Spring 的事务也不会生效。例如:没有在项目的配置类中配置如下代码。
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
6.方法的事务传播类型不支持事务
如果内部方法的事务传播类型为不支持事务的传播类型,则内部方法的事务在Spring 中会失效。例如:由于(updateProductStockCountById()方法的事务传播类型为(NOT_SUPPORTED,不支持事务,则updateProductstockcountById()方法的事务会在Spring中失效。
@Service
public class OrderService {@Autowired
private OrderDao orderDao;@Autowired
private ProductDao productDao;
@Transactional(propagation = Propagation.REQUIRED)public void submitOrder( ){
/生成订单
order order = new Order( );
long number = Math.abs ( new Random( ).nextInt(500) );order.setId(number) ;
order.setOrderNo( "order_" + number) ;orderDao.saveOrder(order);
//减库存
this.updateProductStockCountById(1,1L);}
@Transactional( propagation = Propagation.NOT_SUPPORTED)
public void updateProductStockCountById( Integer stockCount,Long id){productDao.updateProductStockCountById(stockCount, id);
}
}
7.不正确的捕获异常
不正确的捕获异常也会导致Spring 的事务失效。例如: updateProductStockCountById()方法中使用try-catch 代码块捕获了异常,即使(updateProductStockCountById()方法内部会抛出异常,但也会被catch代码块捕获到,此时updateProductStockCountById()方法的事务会提交而不会回滚,并且 submitorder()方法的事务会提交而不会回滚,这就造成了(Spring 事务的回滚失效问题。
service
public class orderService {@Autowired
private orderDao orderDao;@Autowired
private ProductDao productDao;
@Transactional( propagation = Propagation.REQUIRED)public void submitorder(){
l/生成订单
order order = new Order();
long number - Math.abs(new Random( ).nextInt (500) );order.setId( number);
order.setOrderNo( "order_" + number);orderDao.saveorder(order);
//减库存
this.updateProductStockCountById(1,1L);}
@Transactional(propagation = Propagation.REQUIRED)
public void updateProductstockCountById(Integer stockCount,Long id){try{
productDao.updateProductstockcountById(stockcount,id);int i = 1 / 0;
}catch(Exception e){
logger.error("扣减库存异常: ", e.getMesaage( ));}
}}
8.错误的标注异常类型
如果在@Transactional注解中标注了错误的异常类型,则Spring事务的回滚会失效。例如:在(updateProductStockCountById()方法中捕获了异常,并且在异常中抛出了(Exception类型的异常,此时,updateProductstockcountById()方法事务的回滚会失效。"
为何会失效呢?这是因为Spring 中对于默认回滚的事务异常类型为(RuntimeException,上述代码抛出的是Exception异常。
默认情况下,Spring 事务中无法捕获到Exception异常,所以此时updateProductstockCountById()方法事务的回滚会失效。
@Transactional(propagation = Propagation.REQUIRED)
public void updateProductstockCountById(Integer stockCount,Long id){
try{
productDao.updateProductStockCountById(stockCount, id);}catch(Exception e){
logger.error( "扣减库存异常:",e.getMesaage());throw new Exception("扣减库存异常");
}
}
此时可以手动指定updateProductstockCountById()方法标注的事务异常类型,如下所示:
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
27.谈谈对SpringMVC的理解?
首先,MC模式是模型(Model )、视图(View )、控制器(Controller )的简写,其核心思想是通过将请求处理控制、业务逻辑、数据封装、数据显示等流程节点分离的思想来组织代码。
所以,MVC是一种设计模式,而Spring MVC是一款基于(MVC设计模式思想实现的的MVC框架,属于Spring技术栈的一部分。Spring MVC可以帮助我们进行更简洁的 web层的开发,并且它天生与Spring框架集成,更利于架构的设计与搭建。
28. SpringMVC的工作原理(执行流程)?
1.客户端(浏览器)发送请求,统一由DispatcherServlet拦截处理请求。
- DispatcherServlet根据请求信息调用HandlerMapping 。HandlerMapping根据uri去
匹配查找能处理的Handler(也就是我们定义的Controller控制器),并会将请求涉及到的拦截器和Handler一起封装。
-
DispatcherServlet调用HandlerAdapter适配执行Handler。
-
Handler 完成对用户请求的处理后,会返回一个ModelAndView模型视图对象给 DispatcherSe
rvlet。ModelAndView中包含了数据模型以及相应的视图信息。Model是返回的数据对象,iew是view视图的逻辑名称。
-
ViewResolver 会根据逻辑View名称查找并解析实际的view视图文件,并根据DispaterServlet返回的Model数据模型传给view视图文件,进行渲染执行,产生响应结果。
-
DispaterServlet负责将响应结果,输出至客户端浏览器。
29. SpringMVC的核心组件有哪些?
- DispatcherServlet:核心处理器,负责统一接收请求、将请求分发至不同的控制器,并负责客户端响应。
- HandlerMapping:处理器映射器,根据uri去匹配查找能处理的Handler,并会将请求涉及到的拦截器和Handler一起封装。
- HandlerAdapter:处理器适配器,根据HandlerMapping找到的Handler,适配执行对应的Handler ;
- Handler:请求处理器,处理实际请求的处理器。
- ViewResolver:视图解析器,根据Handler返回的逻辑视图名称,解析并渲染真正的视图文件,并传递给DispatcherServlet响应至客户端