当前位置 : 主页 > 编程语言 > java >

Spring框架必知,满满干货!

来源:互联网 收集:自由互联 发布时间:2023-12-28
1、认识Spring框架 1.1 Spring框架定义 定义:Spring是 轻量级的开源框架 。以 IOC(控制反转)和AOP(面向切面编程)为内核 ,使用 最基本的JavaBean 完成工作。 1.2 Spring框架的优点 控制反转(IOC)和

1、认识Spring框架


1.1 Spring框架定义

  • 定义:Spring是轻量级的开源框架。以IOC(控制反转)和AOP(面向切面编程)为内核,使用最基本的JavaBean完成工作。

1.2 Spring框架的优点

  1. 控制反转(IOC)和依赖注入(DI)实现松耦合,简化开发。
  2. 支持AOP(面向切面编程),并且把应用业务与系统服务分开
  3. 支持声明式事务处理。通过配置就可以完成对事务的处理,提高开发效率。
  4. 方便程序的测试。Spring支持JUnit4的支持,添加注解便可以测试Spring。
  5. 方便集成各种优秀框架。内部提供了对一些框架的直接支持。
  6. 降低了Java EE API的使用难度。对JDBC、Mail等模块进行了封装

1.3 Spring框架体系结构和模块组成

  1. 体系结构:分层架构
  2. 主要模块
  1. Core Container(核心容器层):是其他模块建立的基础,主要模块组成:
  1. Beans模块提供了BeanFactory(工厂模式),Spring将管理对象称为Bean。
  2. Core模块:提供了Spring框架的基本组成部分,包括IOC(控制反转)和DI(依赖注入)功能。
  3. Context模块:建立在Beans和Core基础之上,访问定义和配置的任何对象的媒介。ApplicationContext接口是Context模块的焦点。
  4. Context-support模块:提供了第三方库嵌入Spring应用的集成支持。
  1. DataAccess/Integration(数据访问/集成层)
  1. JDBC模块:提供了JDBC的抽象层,大幅度地减少了在开发过程中对数据库操作的编码。
  2. ORM模块:对流行的对象关系映射API,包括JPA、JDO、Hibernate提供了集成层面支持。
  3. OMX模块:提供了一个支持对象/XML映射的抽象层实现,如JAXB、Castor、XStream等。
  4. JMS模块:Java消息传递,使用和传递信息的特性。
  5. Transactions事务模块:支持对实现特殊接口以及所有实体类的编程和注解式的事务管理
  1. Web层
  1. WebSocket模块:提供了WebSocket和SockJS的实现。
  2. Servlet模块:Spring-MVC模块,包含了Spring模型-视图-控制器(MVC)。
  1. 其他模块
  1. AOP模块:提供了面向切面编程的实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,降低耦合性
  2. Aspects模块:提供了AspectJ一个强大且成熟的AOP框架。
  3. Test模块:提供了单元测试和集成测试的支持。
  1. 体系结构图

Spring框架必知,满满干货!_AOP

1.4 Spring框架的两种核心容器

  1. BeanFactory:基础类型的IOC容器,提供了完整的IOC服务支持。BeanFactory就是一个管理Bean的工厂,它主要负责初始化各种Bean,并调用它们的生命周期方法
  2. ApplicationContext:它是BeanFactory的子接口,除了提供BeanFactory的所有功能外,还添加了对国际化、资源访问、事件传播等方面的支持。
  3. 创建ApplicationContext的三种方式:
  1. ClassPathXmlApplicationContext(从类路径中读取配置文件)创建:
  1. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml")
  1. FileSystemXmlApplicationContext(参数指定的配置文件位置)创建:
  1. ApplicationContext applicationContext = new FileSystemXmlApplicationContext("applicationContext.xml")
  1. Web服务器实例化ApplicationContext,基于ContextLoaderListener实现。

1.5 获取Spring中的Bean

  1. Object getBean(String name):根据Bean的id或者name来获取指定的Bean,需要强转
  2. <T> T getBean(Class<T> requiredType):根据类的类型来获取Bean实例,有泛型不需要强转

1.6 BeanFactory和ApplicationContext的区别

  1. 功能上的区别。
  1. BeanFactory是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。
  2. ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能,如继承MessageSource、支持国际化、统一的资源文件访问方式、同时加载多个配置文件等功能。
  1. 加载方式的区别
  1. BeanFactory采用的是延迟加载的形式来注入Bean,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常
  2. ApplicationContext在容器启动时,一次性创建了所有的Bean。在容器启动时就可以检查所依赖的属性是否注入。
  1. 创建方式的区别
  1. BeanFactory通常以编程的方式被创建。
  2. ApplicationContext除了使用编程方式创建(new 实例),还能以声明的方式创建,例如使用ContextLoader。
  1. 注册方式的区别:BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用。
  1. BeanFactory需要手动注册
  2. ApplicationContext是自动注册的

1.7 控制反转(IOC)和依赖注入(DI)

  1. 控制反转
  1. 概念:IOC也称控制反转,由Spring容器管理Bean的整个生命周期,通过反射实现对其他对象的控制,对象的实例不再由调用者来创建,而是由Spring容器来创建有效的降低类之间的耦合度
  2. IOC的好处
  1. 资源集中管理,实现资源的可配置和易管理。
  2. 降低了使用资源双方的依赖程度,耦合度
  1. 依赖注入
  1. 概念:DI也称依赖注入,在Spring创建对象过程中,把对象依赖的属性注入到对象中
  2. 主要的两种方式:属性setter方法注入构造器注入


2、Spring中的Bean


2.1 Bean的三种实例化方式

  1. 构造器实例化:Spring容器通过Bean对应类中默认的无参构造器来实现实例化Bean。
  2. 静态工厂方式实例化:配置factory-method属性。
  3. 实例工厂方式实例化:配置factory-bean、factory-method属性。

2.2 Bean的作用域

  1. singleton(单例)Spring容器中的默认作用域,该作用域表示使用singleton定义的Bean在Spring容器中将只有一个实例。无论有多少个Bean引用它,始终将指向同一个对象。
  2. prototype(原型)每次通过Spring容器获取prototype定义的Bean时,容器都将创建一个新的Bean实例
  3. request:对不同的Http请求每次请求都会产生一个新的Bean,仅在当前Http request内有效。
  4. session:对不同的Http请求每次请求都会产生一个新的Bean,仅在当前Http session内有效。
  5. globalSession:在一个全局的Http Session中,容器会返回该Bean的同一个实例。仅在使用portlet上下文时有效。

2.3 Bean的生命周期

注意:Spring可以管理Singleton单例作用域的Bean完整的生命周期,对于Prototype多例作用域的Bean,Spring只负责创建,创建实例后,Bean的实例就交由客户端代码管理,Spring不再跟踪其生命周期。生命周期图示:

Spring框架必知,满满干货!_AOP_02

  1. 调用bean的构造方法创建Bean。
  2. 通过反射调用setter方法进行属性的依赖注入。
  3. 如果Bean实现了BeanNameAware接口,Spring将调用setBeanName(),设置Bean的name(xml文件中bean标签的id)。
  4. 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory() 把beanfactory设置给Bean。
  5. 如果存在BeanPostProcessor ,Spring将调用它们的postProcessBeforeInitialization (预初始化)方法,在Bean初始化前对其进行处理。
  6. 如果Bean实现了InitializingBean接口,Spring将调用它的afterPropertiesSet方法,然后调用xml定义的 init-method方法,两个方法作用类似,都是在初始化bean的时候执行。
  7. 如果存在BeanPostProcessor ,Spring将调用它们的postProcessAfterInitialization (后初始化)方法,在Bean初始化后对其进行处理。
  8. Bean初始化完成,供应用使用,这里分两种情况:
  1. 如果Bean为单例的话,那么容器会返回Bean给用户,并存入缓存池。如果Bean实现了DisposableBean接口,Spring将调用它的destory方法,然后调用在xml中定义的destory-method方法,这两个方法作用类似,都是在Bean实例销毁前执行。
  2. 如果Bean是多例的话,容器将Bean返回给用户,剩下的生命周期由用户控制

2.4 Bean的装配方式(依赖注入)

  1. 基于XML装配:setter注入构造器注入
  2. 注解方式装配
  1. @Configuration+@Bean注解:@configuration声明该类是一个配置类,并将该类交由Spring管理@Bean一般加在该类的方法上,表示该方法会返回一个Bean。
  2. 通过包扫描特定注解方式:@ConponentScan放在配置类上,然后指定一个路径,进行扫描带有特定注解的Bean,然后加到Spring容器中。特定注解包括@Controller、@Service、@Repository、@Component等。
  1. 自动装配:通过设置Autowrited属性值实现自动装配。
  2. 根据类型自动装配:byType,必须存在setter方法
  3. 根据名称自动装配:byName
  4. 根据构造方法自动装配。
  5. 存在单例的Bean优先按照类型进行参数匹配,当存在多个类型相同实例时按照名称优先匹配,没有找到则匹配失败。

2.5 @Autowrited和@Resource注解

  1. 两个注解都可以实现Bean的自动装配
  2. @Autowrited默认按照类型进行装配(byType)。
  3. @Resource默认按照Bean的名称进行装配(byName)。
  1. @Resource有name和type两个属性,指定谁就按照谁来装配,若都不指定,默认byName,若都没有匹配到,抛异常。
  1. @Qualifier与@Autowrited注解配合使用,会将默认按照Bean类型装配改为按照Bean的名称进行装配
  2. 对于配置文件中获取值以及一些简单类型(int、long、String等)进行依赖注入,可以直接使用@Value注解。
// 详细使用Spring Boot中说明
@Value("${jdbc.url}")
private String url;

2.6 @Component和@Bean注解的区别

  1. @Bean是Java代码装配Bean,@Component是自动装配Bean
  2. @Component注解用在类上,表示一个类会作为组件类,并告知Spring要为这个类创建Bean,每个类对应一个Bean。
  3. @Bean注解用在方法上,表示这个方法会返回一个Bean,一般@Bean使用在配置类中,类上需要使用@Configuration注解。

2.7 常用的特定注解

  1. @Component:最普通的组件,可以被注入到Spring容器中管理,以下注解也可被注入到Spring中管理。
  2. @Controller:将类标记为Spring web mvc的控制器。
  3. @Service:将类标记为业务层组件。
  4. @Repository:将类标记为数据访问层组件。

2.8 Spring Bean如何保证并发安全

  1. 单例模式变原型模式
  2. 尽量避免使用成员变量
  3. 使用并发安全的类,CurrentHashMap等。
  4. 分布式或微服务的并发安全:使用Redis等中间件。


3、Spring AOP


3.1 初识AOP

  1. 概念:AOP也称为面向切面编程,它是OOP(面向对象编程)的一种补充
  1. AOP将公共逻辑(事务管理、日志、缓存等)封装成切面。与业务代码进行分离,可以减少系统的重复代码和降低模块之间的耦合度
  2. 切面就是那些与业务无关,但所有业务模块都会调用的公共逻辑。
  1. AOP框架
  1. Spring AOP:使用纯Java实现,不需要专门的编译过程和类加载器,在运行期间通过代理的方式向目标类织入增强的代码
  2. AspectJ:一个基于Java语言的AOP框架,它扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入

3.2 使用AOP的好处

  1. 有效的减少了系统的重复代码降低了模块间的耦合度
  2. 提高代码的复用性
  3. 更好的分离关注点,提高代码的可读性和可维护性

3.3 AOP的专业术语

  1. 切面(Aspect):封装的用于横向插入系统功能(事务、日志等)的类
  2. 连接点(JoinPoint):在程序执行过程中的某个阶段点,它实际上是对象的一个操作。在Spring AOP框架中,指的就是方法的调用
  3. 切入点(Pointcut):切面与流程的交叉点,即那些需要处理的连接点。通常在程序中,切入点指的是具体的类或方法名,又或者是正则表达式所匹配到的一些类或方法名
  4. 通知/增强处理(Advice):在定义好的切入点处所要执行的代码,理解为切面类中的方法,切面的具体实现
  5. 目标对象(Target Object):所有被通知的对象,通常是一个代理对象。
  6. 代理(Proxy):将通知应用到目标对象之后,被动态创建的对象
  7. 织入(Weaving):将切面代码插入到目标对象上,从而生成代理对象的过程

3.4 AOP中织入的时机

*应对的是目标对象的生命周期

  1. 编译期:切面在目标类编译时被织入AspectJ框架就是这样实现的。
  2. 加载期:切面在目标类加载到JVM时织入,需要特殊的类加载器。
  3. 运行期:切面在应用运行的某个时刻被织入,一般情况下,在织入切面时,AOP容器会为目标对象动态的创建一个代理对象,Spring AOP框架就是以这种方式织入的切面。

3.5 AOP的实现方式(代理方式)

  1. 静态代理
  1. 实现机制:代理类在编译阶段生成,在编译阶段将通知织入Java字节码中,编译期增强。AspectJ框架使用的是静态代理。
  2. 缺陷:代理对象需要与目标对象实现一样的接口,并且实现接口的方法存在一定的冗余代码,其次,一旦接口增加方法,目标对象与代理对象都需要进行维护
  1. 动态代理
  1. 实现机制:代理类在程序运行时创建,Spring AOP框架不会去修改字节码,而是在内存中临时生成一个代理对象,在运行期间对业务方法进行增强。

3.6 Spring AOP的实现原理

通过动态代理实现的。如果我们为Spring的某个Bean配置了切面,那么Spring在创建这个Bean的时候,实际上创建的是这个Bean的一个代理对象,后续对目标类Bean的方法调用,实际上调用的是代理类重写的代理方法

3.7 Spring AOP主要的两种动态代理

  1. JDK动态代理
  1. 实现机制:如果目标类实现了接口Spring AOP会选择使用JDK动态代理目标类。代理类根据目标类实现的接口动态生成,不需要自己编写,生成的动态代理类和目标类都实现相同的接口
  2. 核心:实现InvocationHandler接口和Proxy类
  3. 局限性:目标类必须实现一个或多个接口,如果类没有实现接口,就不能使用JDK动态代理该目标类。
  1. CGLIB动态代理
  1. 实现机制:CGLIB动态代理是通过继承实现的。如果目标类没有实现一个或多个接口,Spring AOP框架会选择使用CGLIB动态代理目标类。CGLIB动态代理可以在运行时动态生成目标类的字节码动态创建目标类的子类对象,在子类对象中增强目标类。
  2. 特别注意:由于CGLIB动态代理是通过继承实现的,如果某个类使用了final关键字修饰,该类将无法被继承,所以就无法使用CGLIB动态代理目标类。
  3. 相比于JDK动态代理的优势:目标类不需要实现接口,更加灵活。
  1. Spring AOP框架对两种动态代理的使用场景
  1. 如果目标类实现了接口,Spring AOP框架默认使用JDK动态代理,也可强制使用CGLIB动态代理。
  2. 如果目标类没有实现接口,必须使用CGLIB动态代理

3.8 JDK动态代理和CGLIB动态代理的区别

  1. JDK动态代理使用JDK中的Proxy类来创建代理对象,它使用反射技术来实现,不需要导入其他依赖;CGLIB需要引入相关依赖-asm.jar使用字节码增强技术来实现。
  2. 当目标类实现了接口的时候,Spring AOP框架默认使用的是JDK动态代理增强方法,目标类没有实现接口的时候,使用CGLIB动态代理。

3.9 Spring的通知类型

  1. 环绕通知(Around):在目标方法执行前后实施增强,可以应用于日志、事务管理等功能。
  2. 前置通知(Before):在目标方法执行前实施增强,可以应用于权限管理等功能。
  3. 后置通知(After-running):在目标方法执行后实施增强,可以应用于关闭流、上传/删除临时文件等功能。
  4. 异常通知(After-throwing):在方法抛出异常后实施增强,可以应用于处理异常、记录日志等功能。
  5. 引介通知(IntroductionInterceptor):在目标类中添加一些新的属性和方法,通常用于老版本程序的修改

3.10 基于注解使用AspectJ

  1. @Aspect:注解用在类上,标注该类是一个切面类。
  2. @Pointcut:定义切入点表达式,需要指定一个包含和任意参数的方法签名来表示切入点名称。通常为返回值为viod的空方法
  3. @通知类型(Before/After等):标注在方法上,value值传入切入点的空方法名@After最终通知,不管是否异常,该通知都会执行
  4. 使用前需要先导入AOP和AspectJ的依赖(Spring Boot)
<!-- 复制粘贴下载即可 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>
/**
 * 定义切面类
 */
@Aspect
@Component
public class MyAspect {
    // 切点
    @Pointcut("execution(* com.lz.learning.*.*(..))")
    public void myPointCut() {
    }
    // 前置通知
    @Before("myPointCut()")
    public void myBefore(JoinPoint joinPoint) {
        System.out.println("前置通知,目标类:" + joinPoint.getTarget() + ",增强的目标方法:"
                + joinPoint.getSignature().getName());
    }
    // 后置通知
    @AfterReturning("myPointCut()")
    public void myAfterRunning(JoinPoint joinPoint) {
        System.out.println("后置通知,目标类:" + joinPoint.getTarget() + ",增强的目标方法:"
                + joinPoint.getSignature().getName());
    }
    // 环绕通知
    @Around("myPointCut()")
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("模拟环绕开始...");
        // 执行当前目标方法
        Object obj = proceedingJoinPoint.proceed();
        System.out.println("模拟环绕结束...");
        return obj;
    }
    // 异常通知
    @AfterThrowing(value = "myPointCut()", throwing = "e")
    public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
        System.out.println("异常通知:" + e.getMessage());
    }
    // 最终通知,不管是否异常,该通知都会执行
    @After("myPointCut()")
    public void myAfter() {
        System.out.println("最终通知...");
    }
}


4、Spring的事务管理


4.1 认识Spring事务

  1. 概念:多个操作单元组成的集合,多个单元操作是整体不可分割的。
  2. 基本特性:原子性、一致性、隔离性、持久性
  3. Spring事务的实现方式
  1. 编程式事务:通过编程式的方式进行管理事务,灵活性强,但很难维护。
  2. 声明式事务:将事务管理代码从业务方法中分离出来,通过AOP进行封装,无需处理关闭连接、提交/回滚等操作。

4.2 Spring事务管理的核心接口

  1. PlatformTransactionManager接口:Spring提供的平台事务管理器来管理事务。主要实现方法:
  1. TransactionStatus getTransaction(TransactionDefinition td):获取事务的状态信息。
  2. void commit(TransactionStatus status):事务提交。
  3. void rollback(TransactionStatus status):事务回滚。
  1. TransactionDefinition接口:事务描述的对象,定义了事务的规则。
  1. String getName():获取事务对象的名称。
  2. int getlsolationLevel():获取事务的隔离级别。
  3. int getPropagationBehavior():获取事务的传播行为。
  4. int getTimeout():获取事务的超时时间。
  5. boolean isReadOnly():是否是只读事务。
  1. TransactionStatus接口:事务的状态,某一时间点上事务的状态信息。
  1. void flush():刷新事务。
  2. boolean hasSavepoint():获取事务是否存在保存点。
  3. boolean isCompleted():获取事务是否完成。
  4. void setRollbackOnly():设置事务回滚。

4.3 @Transactional注解

  1. 作用域
  1. 声明在上:表示整个类的所有方法都起作用
  2. 声明在方法上:表示只对当前方法有效
  1. 可配置的相关参数
  1. value:指定需要使用的事务管理器。默认为"",其别名为transactionManager。
  2. isolation:指定事务的隔离级别,默认为DEFAULT。
  3. noRollbackFor:指定遇到特定异常时强制不回滚事务noRollbackFor=RuntimeException.class
  4. rollbackFor:指定遇到特定异常强制回滚事务。不指定默认为对RuntimeException异常进行回滚,一般可以指定Exception,rollbackFor=Exception.class
  5. noRollbackForClassName:指定遇到特定的多个异常强制不回滚事务,可以指定多个异常类名。
  6. rollbackForClassName:指定遇到特定的多个异常强制回滚事务,可以指定多个异常类名。
  7. read-only指定事务是否为只读,默认false
  8. propagation:指定事务的传播行为,默认为REQUIRED。
  9. timeout:指定事务的超时时间,默认为TIMEOUT_DEFAULT(底层事务系统的默认时间)。

4.4 @Transactional注解失效的情况

  1. 访问权限的问题
  1. 权限大小:private < default < protected < public
  2. 如果所注解的方法的访问权限不是public,会导致事务失效,Spring要求被代理方法必须是public
  1. 目标方法使用了final关键字
  1. 如果目标方法使用了final关键字修饰,事务会失效。
  2. 原因:Spring事务底层使用了AOP,通过JDK的动态代理或者CGLIB动态代理的方式生成了代理类,在代理类中实现了事务的功能,使用final修饰有悖于两种动态代理的底层机制。
  1. 对象没有被Spring管理
  1. 使用Spring事务的前提是对象要被Spring容器管理,需要创建Bean的实例,如果类没有加@Component、@Service、@Controller等特定注解,该类也就没有交由Spring去管理,事务不会生效。
  1. 表的存储引擎不支持事务
  1. 如果MySQL使用的存储引擎是myisam,它是不支持事务的。
  1. 异常被捕获后没有抛出[实际开发中常遇到]
  1. 目标方法中使用了try{}catch(){}手动捕获了异常,并对异常做了处理,没有继续抛出异常或异常被吞掉了,此时Spring事务机制认为异常已经被处理,没有了异常,自然也不会触发回滚
  2. 若需要事务能够回滚生效,手动捕获后可以再手动的抛出它所接收的异常
@Transactional(rollbackFor = Exception.class)
public int test() {
    int y = 12;
    int x = 0;
    int result = 0;
    try {
        // 算术异常
        result = y / x;
    } catch (Exception e) {
        result = -1;
        System.out.println(e.getMessage());
        // 捕获异常处理之后不再抛出,事务失效
        // 捕获处理之后需将异常抛出,此时事务才会生效
        throw new RuntimeException(e.getMessage(), e);
    }
    return result;
}
  1. 一个类的方法的内部调用
  1. 同一类中,某个方法方法调用了加了事务注解的目标方法,此时事务注解不会生效。
  2. 原因:这实际上是在同一个对象中调用了方法,并没有经过Spring的代理类,所以事务会失效。
@Component
public class MyTransaction {
    @Transactional(rollbackFor = Exception.class)
    public void printA() {
        System.out.println("A");
    }
    public void printB() {
        // 内部直接调用事务方法,此时A方法事务不生效
        printA();
    }
}
  1. 未开启事务
  1. 如果是Spring项目,需要在配置中手动配置开启事务的相关参数。
  2. 如果是Spring Boot项目,不需要手动配置,因为在DataSourceTransactionManagerAutoConfiguration类中已经开启了事务。


5、Spring MVC

5.1 MVC模式

  1. 定义:MVC(model模型-view视图-controller控制器)是一种软件设计规范,是将业务逻辑、数据、显示分离的方法来组织代码。MVC不是一种设计模式,而是一种架构模式
  2. 主要作用:降低了视图与业务逻辑的双向耦合,代码的重用性高,易于维护和扩展
  3. 分层解读
  1. model层:用于处理应用程序中数据逻辑的部分。
  2. view层:负责进行模型的展示,一般是用户界面。
  3. controller层:接收用户输入并返回数据的部分,数据交互

5.2 认识Spring MVC

  1. 定义:Spring提供的一个实现了Web MVC模式的轻量级web框架属于Spring框架的一个模块
  2. 实现机制:Spring MVC通过一套注解让一个简单的Java类成为处理请求的控制器,而无需实现任何接口,同时它还支持REST风格的请求。
  3. 特点:
  1. 它是Spring框架的一部分,可以方便使用Spring框架提供的其他功能。
  2. 灵活性强,易于和其他框架集成。
  3. 自动绑定用户输入,正确转换数据类型。
  4. 支持国际化,根据用户区域显示多国语言。
  5. 支持多种视图技术,JSP、Velocity等。
  6. 支持REST风格请求。
  7. 提供了一个前端控制器DispatcherServlet,无需额外开发控制器对象。
  8. 内置常见的校验器,可以校验用户输入。校验不通过会重定向到原表单。

5.3 Spring MVC的主要组件

  1. 前端控制器(DispatcherServlet):接收用户请求,给用户返回结果。
  2. 处理器映射器(HandlerMapping):根据请求的URL路径,通过XML配置或者注解来寻找匹配的处理器
  3. 处理器适配器(HandlerAdapter):Handler处理器的适配器,调用Handler中的方法处理请求
  4. 处理器(Handler):执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装到ModelAndView对象中
  5. 视图解析器(ViewResolver):将视图逻辑解析成真正的View视图。
  6. 视图(View):View接口,实现类可支持不同的View类型(JSP等)。

5.4 Spring MVC内部的工作流程

Spring框架必知,满满干货!_@Transactional_03

  1. 用户通过客户端向服务器发送请求,请求会被Spring MVC的前端控制器DispatcherServlet拦截。
  2. DispatcherServlet拦截到请求后,会调用HandlerMapping处理器映射器。
  3. 处理器映射器根据请求的URL找到具体的处理器,生成处理器对象以及处理器拦截器,一并返回给前端控制器。
  4. 前端控制器会通过返回的信息选择合适的HandlerAdapter处理器适配器。
  5. 处理器适配器会调用并执行Handler处理器,这里的处理器指的就是程序中的Controller类,也被称为后端控制器。
  6. Controller执行完之后,会返回一个ModelAndView对象,包含模型和视图名
  7. 处理适配器将ModelAndView对象返回给前端控制器
  8. 前端控制器会根据ModelAndView对象选择一个合适的ViewResolver视图解析器。
  9. ViewResolver解析之后,会向前端控制器中返回具体的View视图
  10. 前端控制器对View视图进行渲染。
  11. 渲染结果会返回给客户端浏览器进行显示。

5.5 Spring MVC常用注解

  1. @Controller:标识此类的实例是一个控制器。
  1. 机制:Spring容器会扫描该类,然后扫描该类下面的带有@RequestMapping注解的方法,为这个方法生成一个对应的处理器对象
  1. @RequestMapping:映射一个请求或映射一个方法。
  1. 标注在方法上:该方法成为一个请求处理的方法,它会在接收到对应的URL请求时被调用。
  2. 标注在类上:该类所有的方法都将映射为相对于类级别的请求,该控制器所处理的所有请求都被映射到value属性所指定的路径下(常用在类上)。
  1. @Get/Post/Put/Delete/PatchMapping:匹配GET/POST等方式的请求。
  2. @RequestBody接收Http请求的JSON数据,将JSON数据转换为Java对象,标注在方法的形参上
  3. @ResponseBody返回JSON格式的数据标注在方法上
  4. @PathVariable:获得URL路径中的变量的值,常与REST风格请求适配,标注在方法的形参上。
  1. 若请求参数中的变量名与形参的名称相同,注解后可以省略标注
@GetMapping("user/{id}")
// 注解里面的id可以省略
public User getUserById(@PathVariable("id") int id)
  1. @RestController:组合注解,@Controller + @ResponseBody
  2. @ExceptionHandle:标识一个方法为全局异常处理的方法。

5.6 Spring MVC的异常处理

可以将异常抛给Spring框架,由Spring框架来处理;只需要配置简单的异常处理器,在异常处理器中添视图页面即可。

  1. 使用系统定义好的异常处理器 SimpleMappingExceptionResolver
  2. 使用自定义异常处理器
  3. 使用异常处理注解

5.7 Spring MVC用什么对象从后台向前台传递数据

  1. 将数据绑定到request中。
  2. 返回ModelAndView
  3. 通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前端就可以通过el表达式拿到。
  4. 绑定数据到 Session中。

5.8 @RequestParam和@PathVariable的区别

两个注解都作用于方法的形参上,它们获取参数值的方式不同。@RequestParam注解的参数值从请求携带的参数中获取,而@PathVariable从请求的URL中获取。

5.9 @RequestBody和@RequestParam的区别

处理的请求数据类型不同

  1. @RequestBody一般处理的是ajax请求中contentType:application/json类型的数据,也就是JSON或XML格式数据。
  2. @RequestParam:一般处理没有声明contentType格式的数据。

5.10 REST风格

  1. 定义:一种软件架构的风格或设计风格,而不是一个标准。
  1. Representational:某种表现形式,例如:JSON、XML等
  2. states Transfer:状态变化,通过Http method实现。
  1. 表现形式:把请求参数变为请求路径的一种风格。例
  2. 原:http://.../queryItems?id=6;REST:http://.../items/6
  3. REST风格中URL不存在动词形式的路径,在HTTP请求中,put(添加)、delete(删除)、post(修改)、get(查询)
  4. 通常配合@PathVariable注解使用。
  5. 使用REST的优势
  1. 风格统一
  2. 面向资源,具有自解释性
  3. 充分利用http本身语义

5.11 Spring MVC拦截器

  1. 概述:主要用于拦截用户请求并作相应的处理,用于权限验证、记录请求、判断登录等功能。
  2. 实现方式:通过实现HandlerInterceptor接口中的方法(常用的一种)
  1. preHandler():该方法会在Controller控制器的方法执行前执行,其返回值表示是否中断后续操作。返回true,继续向下执行,返回false将中断后续所有操作
  2. postHandler():控制器方法执行之后再执行,且解析视图之前执行。可以对请求域中的模型和视图做出进一步的修改。
  3. afterCompletion():该方法会在整个请求完成,即视图渲染结束之后执行。实现一些资源清理、记录日志等功能。
  1. 三个方法的执行顺序
  1. preHandler -> controller中的方法 -> postHandler -> 前端控制器 -> afterCompletion
  1. Spring MVC拦截器的XML配置
<!-- 配置Spring Mvc拦截器 -->
<mvc:interceptors>
    <bean id="myInterceptor" class="com.dabin.MyHandlerInterceptor">
    </bean>
    
    <!-- 只拦截部分请求 -->
    <mvc:interceptor>
       <mvc:mapping path="/xxx.do" />
       <bean class="com.dabin.MyHandlerInterceptorAdapter" />
    </mvc:interceptor>
</mvc:interceptors>

5.12 Spring MVC拦截器和Filter过滤器的区别

  1. 功能相同:都可以实现相同的功能。
  2. 容器不同:拦截器构建在Spring MVC体系中,Filter构建在servlet容器之上。
  3. 使用的便利性不同:前者实现了三个方法,分别在不同的时机执行,Filter过滤器仅提供了一个方法。
上一篇:堆 Heap
下一篇:没有了
网友评论