SSM入门
Java_SSM入门
参考课程:黑马程序员2022最新SSM框架教程
学习预备
为什么要学
- 使用Spring技术JavaEE开发,企业开发技术选型命中率>90%
- 专业角度
- 简化开发,降低企业级开发的复杂性
- 框架整合,高效整合其他技术,提高企业级应用开发与运行效率
学什么
- 简化开发
- IoC
- AOP
- 事务处理
- 框架整合
- MyBatis
- MyBatis-plus
- Struts
- Struts2
- Hibernate
- ……
怎么学
- 学习Spring框架设计思想
- 学习基础操作,思考操作与思想之间的联系
- 学习案例,熟练应用操作的同时,体会思想
初识Spring
- 官网:https://spring.io/
- Spring形成了一种开发生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能
- Spring Framework
- Spring Boot
- Spring Cloud
- Spring发展史
Spring Framework
Spring Framework系统架构
- Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基
Spring Framework系统架构图:
Data Access:数据访问
Data Integration:数据集成
Web:Web开发
AOP:面向切面编程
Aspects:AOP思想实现
Core Container:核心容器
Test:单元测试与集成测试
Spring Framework学习路线
- 第一部分:核心容器
- 核心概念(Ioc/DI)
- 容器基本操作
- 第二部分:整合
- 整合数据层技术MyBatis
- 第三部分:AOP
- 核心概念
- AOP基础操作
- AOP实用开发
- 第四部分:事务
- 事务实用开发
核心容器的核心概念
- 代码书写现状
- 耦合度偏高
- 解决方案
- 使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象
- IoC(Inversion of Control)控制翻转
- 对象的创建控制权由程序转移到外部,这种思想称为控制反转
- 目的:解耦
- Spring技术对Ioc思想进行了实现
- Spring提供了一个容器,称为Ioc容器,用来充当Ioc思想中的“外部”
- Ioc容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC中统称为Bean
- DI(Dependency Injection)依赖注入
- 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
- 目标:充分解耦
- 使用IoC容器管理bean(IoC)
- 在IoC容器内将有依赖关系的bean进行关系绑定(DI)
- 最终效果
- 使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
IoC入门案例思路分析
- 管理什么?(Service与Dao)
- 如何将被管理的对象告知IoC容器?(配置)
- 被管理的对象交给IoC容器,如何获取到IoC容器?(接口)
- IoC容器得到后,如何从容器中获取bean?(接口方法)
- 使用Spring导入哪些坐标?(pom.xml)
IoC入门案例(XML版)
- 导入Spring坐标
- 定义Spring管理的类(接口)
- 创建Spring配置文件,配置对应类作为Spring管理的bean
注意:bean定义时id属性在同一个上下文中不能重复 - 初始化IoC容器(Spring核心容器/Spring容器),通过容器获取bean
DI入门案例思路分析
- 基于IoC管理bean
- Service中使用new形式创建的Dao对象是否保留?(否)
- Service中需要的Dao对象如何进入到Service中?(提供方法)
- Service与Dao间的关系如何描述?(配置)
DI入门案例(XML版)
- 删除使用new 的形式创建对象的代码
- 提供依赖对象对应的setter方法
- 配置service与dao之间的关系
bean基础配置
bean别名配置
bean作用范围配置
- 为什么bean默认为单例?
- 适合交给容器管理的bean
- 表现层对象
- 业务层对象
- 数据层对象
- 工具对象
- 不适合交给容器进行管理的bean
- 封装实体的域对象
bean实例化
- bean本质上就是对象,创建bean使用构造方法完成
实例化bean的三种方式——构造方法(常用)
实例化bean的三种方式——静态工厂(了解)
实例化bean的三种方式——实例工厂
实例化bean的第四种方式——FactoryBean(实用)
bean的生命周期
- 生命周期:从创建到消亡的完整过程
- bean生命周期:bean从创建到销毁的整体过程
- bean生命周期控制:在bean创建后到销毁前做一些事情
bean生命周期控制
bean生命周期控制——接口控制(了解)
bean生命周期
- 初始化容器
- 创建对象(内存分配)
- 执行构造方法
- 执行属性注入(set操作)
- 执行bean初始化方法
- 使用bean
- 执行业务操作
- 关闭/销毁容器
- 执行bean销毁方法
bean销毁时机
容器关闭前触发bean的销毁
关闭容器方式:
手工关闭容器
ConfigurableApplicationContext接口close()方法
注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机
ConfigurableApplicationContext接口registerShutdownHook()操作
依赖注入方式
- 思考:向一个类中传递数据的方式有几种
- 普通方法(set方法)
- 构造方法
- 思考:依赖注入描述了在容器中建立bean与bean之间依赖关系的过程,如果bean运行需要的是数字或字符串呢?
- 引用类型
- 简单类型(基本类型与String)
- 依赖注入方式
- setter注入
- 简单类型
- 引用类型
- 构造器注入
- 简单类型
- 引用类型
- setter注入
setter注入——引用类型
setter注入——简单类型
构造器注入——引用类型(了解)
构造器注入——简单类型(了解)
构造器注入——参数适配(了解)
依赖注入方式选择
- 前置依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
- 可选依赖使用setter注入进行,灵活性强
- Spring框架倡导使用构造器,第三方框架内部大多采用构造器注入的形式进行数据初始化,相对严谨
- 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
- 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
- 自己开发的模块推荐使用setter注入
依赖自动装配
IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配
自动装配方式
- 按类型(常用)
- 按名称
- 按构造方法
- 不启用自动装配
配种中使用bean标签autowire属性设置自动装配的类型
自动装配用于引用类型依赖注入,不能对简单类型进行操作
使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效
集合注入
注入数组对象
注入List对象(重点)
注入Set对象
注入Map对象(重点)
注入Properties对象(重点)
第三方资源配置管理
加载properties文件
容器
创建容器
获取bean
容器类层次结构图
BeanFactory初始化
核心容器总结
- BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
- ApplicationContext接口是Spring容器的核心接口,初始化是bean立即加载
- ApplicationContext接口提供基础的bean操作相关方法,通过其他接口拓展其功能
- ApplicationContext接口常用初始化类
- ClassPathXMLApplicationContext
- FileSystemXMLApplicationContext
bean相关
1 |
|
依赖注入相关
1 |
|
注解开发
注解开发定义bean
使用@Component定义bean
核心配置文件中通过组件扫描加载bean
Spring提供@Component注解的三个衍生注解
- @Controller:用于表现层bean定义
- @Service:用于业务层bean定义
- @Respository:用于数据层bean定义
纯注解开发
Spring3.0升级了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发通道
Java类替代了Spring核心配置文件
@Configuration注解用于设定当前类为配置类
@ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式
读取Spring核心配置文件初始化容器独享切换为读取Java配置类初始化容器对象
bean作用范围
使用@Scope定义bean作用范围
bean生命周期
使用@PostConstruct、@PreDestroy定义bean生命周期
依赖注入
使用@Autowired注解开启自动装配模式(按类型)
注意:自动装配基于反射设计创建对象并暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法
注意:自动装配建议使用无参构造方法创建对象(默认),如果不提供对应构造方法,请提供唯一的构造方法
使用@Qualifier注解开启指定名称创配bean
注意:@Qualifier注解无法单独使用,必须配合@Autowired注解使用
使用@Value实现简单类型注入
加载properties文件
使用@PropertySource注解加载properties文件
注意:路径仅支持单一文件配置,多文件请使用数组格式配置,不允许使用通配符*
第三方bean管理
- 使用@Bean配置第三方bean
使用独立的配置类管理第三方bean
使用@Import注解手动加入配置类到核心配置,此注解只能添加一次,多个数据请用数组格式
将独立的配置类加入核心配置
方式二:扫描式
使用@ComponentScan注解扫描配置类所在的包,加载对应的配置类信息
第三方bean依赖注入
简单类型依赖注入
引用类型依赖注入
引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象
注解开发总结
XML配置与注解配置比较
Spring整合MyBatis
将MyBatis的配置文件转换为一个MyBatisConfig类,并且造一个sqlSessionFactory的Bean,完成配置和dataSource的注入
为了完成MyBatis的配置,还需要声明mapper在哪里,所以使用一个方法生成mapperScannerConfigurer类。
此时,当运行时,sqlSessionFactory会自动产生,并且会自动实现dao层中的接口,并将实现好的dao自动注入到写好的对应的Service类中,此时在主程序中只需获取一个Service的实例,即可执行相应的方法了。
Spring整合JUnit
使用Spring整合Junit专用的类加载器
AOP简介
AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构
- OOP(Object Oriented Programming)面向对象编程
作用:在不惊动原始设计的基础上为其进行功能增强
Spring理念:无入侵式/无侵入式
连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等
- 在SpringAOP中,理解为方法的执行
切入点(Pointcut):匹配连接点的式子
在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
- 一个具体方法:com.dicemy.dao包下的BookDao接口中的无型材无返回值的save方法
- 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
通知(Advice):在切入点处执行的操作,也就是共性功能
- 在SpringAOP中,功能最终以方法的形式呈现
通知类:定义通知的类
切面(Aspect):描述通知与切入点的对应关系
AOP入门案例
AOP入门案例(注解版)
导入aop相关坐标
定义dao接口实现类
定义通知类,制作通知
定义切入点
绑定切入点与通知关系,并制定通知添加到原式连接点的具体执行位置
定义通知类受Spring容器管理,并定义当前类为切面类
开启Spring对AOP注解驱动支持
AOP工作流程
Spring容器启动
读取所有切面配置中的切入点
初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
- 匹配失败,创建对象
- 匹配成功,创建原始对象(目标对象)的代理对象
获取bean执行方法
- 获取bean,调用方法并执行,完成操作
- 获取的bean是代理对象时,更具代理对象的运行模式运行原始方法与增强的内容,完成操作
AOP核心概念
- 目标对象(Target):原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的
- 代理(Proxy):目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现。
AOP切入点表达式
切入点:要进行增强的方法
切入点表达式:要进行增强的方法的描述方式
切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)
- 动作关键字:描述契入点的行为动作,例如execution表示执行到执行切入点
- 访问修饰符:public,private等,可以省略
- 返回值
- 包名
- 类/接口名
- 方法名
- 参数
- 异常名:方法定义中抛出执行异常,可以省略
可以使用通配符描述切入点快速描述
*
:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现..
:多个连续的任意符号,可以单独出现,常用于简化包名与参数的书写+
:专用于匹配子类类型
书写技巧
- 所有代码按照标准规范开发,否则以下技巧全部失效
- 描述切入点通常描述接口,而不描述实现类
- 范围控制修饰符针对接口开发即采用public描述(可省略访问控制修饰符描述)
- 返回值类型对于增删改查类使用精确类型加速匹配,对于查询类使用*统配快速匹配
- 报名书写尽量不用..匹配,效率过低,常用*做单个包描述匹配,或精准匹配
- 接口名/类名书写名称与模块相关的采用匹配,例如UserService书写成\Service,绑定业务层接口名
- 方法名书写以动词进行精确匹配,名词采用匹配,例如getById书写成getBy\,selectAll写成selectAll
- 参数规则较为复杂,更具业务方法灵活调整
- 通常不使用异常作为匹配规则
AOP通知类型
AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合适的位置
AOP通知共分为5种类型
前置通知
后置通知
环绕通知(重点)
返回后通知(了解)
抛出异常后通知(了解)
@Around注意事项
案例:测量业务层接口执行效率(万次核心代码执行效率)
- 需求:任意业务层接口执行均可显示其执行效率(执行时长)
- 分析:
- 业务功能:业务层接口执行前后分别记录时间,求差值得到执行效率
- 通知类型选择前后均可以增强的类型——环绕通知
- 补充说明:
- 当前测试的接口执行效率仅仅是一个理论值,并不是一次完整的执行过程
AOP通知获取数据
获取切入点方法的参数
- JoinPoint:适用于前置、后置、返回后、抛出异常后通知
- ProceedJointPoint:适用于环绕通知
获取切入点方法返回值
- 返回后通知
- 环绕通知
获取切入点方法运行异常信息
- 抛出异常后通知
- 环绕通知
JoinPoint对象描述了连接点方法的运行状态,可以获取到原始方法的调用参数
ProceedJoinPoint是JoinPoint的子类
抛出异常后可以获取切入点方法中出现的异常信息,使用形参可以接收到对应的异常对象
环绕通知中可以手工书写对原始方法的调用,得到的结果即为原始方法的返回值
案例:百度网盘密码数据兼容处理
- 需求:对百度网盘分享链接输入密码时尾部多输入的空格做兼容处理
- 分析:
- 在业务方法执行之前对所有的输入参数进行格式处理——trim()
- 使用处理后的参数调用原方法——环绕通知中存在对原始方法的调用
AOP总结
- 概念:AOP面向切面编程,一种编程范式
- 作用:在不惊动原始设计的基础上为方法进行功能增强
- 核心概念
- 代理(Proxy):SpringAOP的核心本质是采用代理模式实现的
- 连接点(JoinPoint):在SpringAOP中,理解为任意方法的执行
- 切入点(PointCut):匹配连接点的式子,也是具有共性功能的方法描述
- 通知(Advice):若干个方法的共性功能,在切入点处执行,最终体现为一个方法
- 切面(Aspect):描述通知与切入点的对应关系
- 目标对象(Target):被代理的原始对象称为目标对象
- 切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)
- execution(* com.dicemy.service.*Service.*(..))
- 切入点表达式描述通配符
- 略
- 切入点表达式书写技巧
- 通知类型
- 前置通知
- 后置通知
- 环绕通知(重点)
- 环绕通知依赖形参ProceedingJoinPoint才能实现对原始方法的调用
- 环绕通知可以隔离原始方法的调用执行
- 环绕通知返回值设置为Object类型
- 环绕通知中可以对原始方法调用过程中出现的异常进行处理
- 返回后通知
- 抛出异常后通知
- 获取切入点方法的参数
- JoinPoint:适用于前置、后置、返回后、抛出异常后通知
- ProceedJointPoint:适用于环绕通知
- 获取切入点方法返回值
- 返回后通知
- 环绕通知
- 获取切入点方法运行异常信息
- 抛出异常后通知
- 环绕通知
Spring事务简介
事务作用:在数据层保障一系列的数据库操作同成功同失败
Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败
案例:银行账户转账
需求:实现任意两个账户间转账操作
需求微缩:A账户减钱,B账户加钱
分析:
- 数据层提供基础操作,执行账户减钱,指定账户加钱
- 业务层提供转账操作,调用减钱与加钱操作
- 提供两个账号和操作金额执行转账操作
- 基于Spring整合MyBatis环境搭建上述操作
结果分析:
- 程序正常执行时,账户金额A减B加,没有问题
- 程序出现异常后,转账失败,但是异常之前操作成功,异常之后操作失败,整体业务失败
步骤
在业务层接口上添加Spring事务管理
设置事务管理器
开启注解式事务驱动
Spring事务角色
事务角色
- 事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法
- 事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法
事务相关配置
案例:转账业务追加日志
需求:实现任意两个账户间转账操作,并对每次转账操作在数据库进行留痕
需求微缩:A账户减钱,B账户加钱,数据库记录日志
分析:
- 基于转账操作案例添加日志模块,实现数据库中记录日志
- 业务层转账操作(transfer),调用减钱、加钱与日志记录功能
实现效果预期
- 无论转账操作是否成功,均进行转账操作的日志留痕
存在的问题
- 日志的记录与转账操作隶属同一个事务,同成功同失败
实现效果预期改进
- 无论转账操作是否成功,日志必须保留
步骤
在业务层接口上添加Spring事务,设置事务传播行为REQUIRES_NEW(需要新事务)
事故传播行为
事务传播行为:事务协调员对事务管理员所携带事务的处理态度
SpringMVC
SpringMVC简介
SpringMVC概述
- SpringMVC技术与Servlet技术功能等同,均属于web层开发技术
- SpringMVC是一种基于Java实现MVC模型的轻量级Web框架
- 优点
- 使用简单,开发便捷(相比于Servlet)
- 灵活性强
SpringMVC入门案例
使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标
创建SpringMVC控制器类(等同于Servlet功能)
初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean
初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求
SpringMVC入门程序开发总结(1+N)
- 一次性工作
- 创建工程,设置服务器,加载工程
- 导入坐标
- 创建web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径
- SpringMVC核心配置类(设置配置类,扫描Controller包,加载Controller控制器bean)
- 多次工作
- 定义处理请求的控制类
- 定义处理请求的控制器方法,并配置映射路径(@RequestMapping)与返回json数据(@ResponseBody)
- 一次性工作
AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
AbstractDispatcherServletInitializer提供三个接口方法供用户实现
createServletApplicationContext()方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个Web容器范围。
getServletMappings()方法,设定SpringMVC对应的请求映射路径,设置为/表示拦截所有请求,任意请求都将转入到SpringMVC进行处理
createRootApplicationContext()方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式同createServletApplicationContext()
SpringMVC注解
@Controller
名称:@Controller
类型:类注解
位置:SpringMVC控制器类定义上方
作用:设定SpringMVC的核心控制器bean
范例:
@RequestMapping
名称:@RequestMapping
类型:方法注解 类注解
位置:SpringMVC控制器方法定义上方
作用:设置当前控制器方法请求访问路径,如果设置在类上统一设置当前控制器方法请求访问路径前缀
范例:
相关属性
- value(默认):请求访问路径
- method:http请求动作,标准动作(GET/POST/PUT/DELETE)
@ResponseBody
名称:@ResponseBody
类型:方法注解
位置:SpringMVC控制器方法定义上方
作用:设置当前控制器方法相应内容为当前返回值,无需解析
作用:设置当前控制器返回值作为响应体范例:
@ComponentScan
名称:@ComponentScan
类型:类注解
范例:
属性
- excludeFilters:排除扫描路径中加载的bean,需要指定类别(Type)与具体项(classes)
- includeFilters:加载指定的bean,需要指定类别(Type)与具体项(classes)
@RequestParam
名称:@RequestParam
类型:形参注解
位置:SpringMVC控制器方法形参定义前面
作用:绑定请求参数与处理器方法形参间的关系
范例:
参数:
- required:是否为必传参数
- defaultValue:参数默认值
@EnableWebMVC
名称:@EnableWebMVC
类型:配置类注解
位置:SpringMVC配置类定义上方
作用:开启SpringMVC多项辅助功能
范例:
@RequsetBody
名称:@RequsetBody
类型:形参注解
位置:SpringMVC控制器方法形参定义前面
作用:将请求中请求体所包含的数据传递给请求参数,此注解一个处理器方法只能使用一次
范例:
@DateTimeFormat
名称:@DateTimeFormat
类型:形参注解
位置:SpringMVC控制器方法形参前面
作用:设定日期时间数据类型
范例:
属性:
- pattern:日期时间格式字符串
@PathVariable
名称:@PathVariable
类型:形参注解
位置:SpringMVC控制器方法形参定义前面
作用:绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应
范例:
@RestController
名称:@RestController
类型:类注解
位置:基于SpringMVC的RESTful开发控制器类定义上方
作用:设置当前控制器为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能
范例
@GetMapping @PostMapping @PutMapping @DeleteMapping
名称:@GetMapping @PostMapping @PutMapping @DeleteMapping
类型:方法注解
位置:基于SpringMVC的RESTful开发控制器方法定义上方
作用:设置当前控制器方法青穹访问路径与请求动作,每种对应一个请求动作,例如@GetMapping对应GET请求
范例:
属性
- value(默认):请求访问路径
@RestControllerAdvice
名称:@RestControllerAdvice
类型:类注解
位置:Rest风格开发的控制器增强类定义上方
作用:为Rest风格开发的控制器做增强
范例:
说明:
- 次注解自带@ResponseBody注解与@Component注解,具备对应的功能
@ExceptionHandler
名称:@ExceptionHandler
类型:方法注解
位置:专用于异常处理的控制器方法上方
作用:设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原式控制器执行,并转入当前方法执行
范例:
说明
- 此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常
入门案例工作流程分析
启动服务器初始化过程
- 服务器启动,执行ServletContainersInitConfig类,初始化Web容器
- 执行createServletApplicationContext方法,创建了WebApplicationContext对象
- 加载SpringMvcConfig
- 执行@ComponentScan加载对应的bean
- 加载UserController,每个@RequestMapping的名称对应一个具体的方法
- 执行getServletMapping方法,定义所有的请求都通过SpringMVC
单次请求过程
- 发送请求localhost/save
- web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
- 解析请求路径/save
- 由/save匹配中对应的方法save()
- 执行save()
- 检测到有@ResponseBody直接将save()方法的返回值作为响应体返回给请求方
Controller加载控制与业务bean加载控制
SpringMVC相关bean(表现层bean)
Spring控制的bean
- 业务bean(Service)
- 功能bean(DataSource等)
SpringMVC相关bean加载控制
- SpringMVC加载的bean对应的包均在com.dicemy.controller包内
Spring相关bean加载控制
- 方式一:Spring加载的bean设定扫描范围为com.dicemy,排除掉controller包内的bean
- 方式二:Spring加载的bean设定扫描范围为精确范围,例如Service包,dao包等
- 方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中
bean的加载格式
简化开发
- 因为功能不同,如何避免Spring错误的加载到SpringMVC的bean?
- SpringMVC的bean—加载Spring控制的bean的时候排除掉SpringMVC控制的bean
PostMan
PostMan简介
- Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件
- 作用:常用于进行接口测试
- 特征
- 简单
- 实用
- 美观
- 大方
PostMan基本使用
- 注册登录
- 创建工作空间/进入工作空间
- 发起请求测试结果
请求与相应
请求映射路径
- 团队多人开发,每人设置不同的请求路径,冲突问题如何解决?
- 设置模块名作为请求路径前缀
请求方式
- Get请求
- Post请求
Get请求传参
普通参数:url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
为web容器添加过滤器并指定字符集,Spring-web包中提供了专用的自负过滤器
请求参数
参数种类
- 普通参数
- POJO类型参数
- 嵌套POJO类型参数
- 数组类型参数
- 集合类型参数
普通参数:url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
普通参数:请求参数名与形参变量名不同,使用@RequestParam绑定参数关系
POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数
嵌套POJO参数:POJO对象中包含POJO对象
数组参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数
集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
请求参数(传递json数据)
- json数组
- json对象(POJO)
- json数组(POJO)
步骤:
添加json数据转换相关坐标
设置发送json数据(请求body中添加json数据)
开启自动转换json数据的支持
设置接收json数据
POJO参数:json数据与形参对象属性名相同,定义POJO类型形参即可接收参数
POJO集合参数:json数组数据与集合泛型属性名相同,定义List类型形参即可接收参数
@RequestBody与@RequestParam区别
区别
- @RequestParam用于接收url地址传参,表单传参【application/x-www-form-urlencoded】
- @RequestBody用于接收json数据【application/json】
应用
- 后期开发中,发送json格式数据为主,@RequestBody应用较广
- 如果发送非json格式数据,选用@RequestParam接收请求参数
日期类型参数传递
日期类型数据基于系统不同格式也不尽相同
- 2088-08-18
- 2088/08/18
- 08/18/2088
接收形参时,根据不同的日期格式设置不同的接受方式
类型转换器
Converter接口
- 请求参数年龄数据(String->Integer)
- 日期格式转换(String->Date)
@EnableWebMVC功能之一:更具类型匹配对应的类型转换器
响应
响应页面(了解)
响应数据
文本数据(了解)
json数据(对象转json)
json数据(对象集合转json数组)
HttpMessageConverter接口
REST风格
REST(Representational State Transfer),表现形式状态转换
传统风格资源描述形式
http://localhost/user/getById?id=1
http://localhost/user/saveUser
REST风格描述形式
http://localhost/user/1
http://localhost/user
优点:
- 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
- 书写简化
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
根据REST风格对资源进行访问称为RESTful
入门案例
设定http请求动作(动词)
设定请求参数(路径变量)
@RequestBody @RequestParam @PathVariable
- 区别
- @RequestParam用于接收url地址传参或表单传参
- @RequestBody用于接收json数据
- @PathVariable用于接收路径参数,使用{参数名称}描述路径参数
- 应用
- 后期开发中,发送请求参数超过1个时,以json格式为主,@RequestBody应用较广
- 如果发送非json格式数据,选用@RequestParam接收请求参数
- 采用RESTful进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值
RESTful快速开发
案例:基于RESTful页面数据交互
制作SpringMVC控制器,并通过PostMan测试接口功能
设置对静态资源的访问放行
前端页面通过异步提交访问后台控制器
- 先做后台功能,开发接口并调通接口
- 再做页面异步调用,确认功能可以正常访问
- 最后完成页面数据展示
- 补充:放行静态资源访问
SSM整合
SSM整合流程
- 创建工程
- SSM整合
- Spring
- SpingConfig
- MyBatis
- MyBatisConfig
- JdbcConfig
- jdbc.properties
- SpringMVC
- ServletConfig
- SpringMvcConfig
- Spring
- 功能模块
- 表与实体类
- dao(接口+自动代理)
- service(接口+实现类)
- 业务层接口测试(整合JUnit)
- controller
- 表现层接口测试(PostMan)
事务处理
表现层数据封装
前端接受数据格式
增删改
查单条
查全部
统一格式
前端接受数据格式-封装操作结果到code属性中
前端接受数据格式-封装特殊消息到message(msg)属性中
设置统一数据返回结果类
设置统一数据返回结果编码
根据情况设定合理的Result
异常处理器
程序开发过程中不可避免的会遇到异常现象
出现异常现象的常见位置与常见诱因如下:
- 框架内部抛出的异常:因使用不合规导致
- 数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)
- 业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务数学操作,导致索引异常等)
- 表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
- 工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)
各个层级均出现异常,异常处理代码书写在哪一层?
所有的异常均抛出到表现层处理表现层处理异常,每个方法中单独书写,代码书写量巨大且意义不强,如何解决?
AOP思想
异常处理器
集中的、统一的处理项目中出现的异常
异常处理器处理效果对比
项目异常处理方案
项目异常分类
- 业务异常(BuesinessException)
- 规范的用户行为产生的异常
- 不规范的用户行为操作产生的异常
- 系统异常(SystemException)
- 项目运行过程中可预计且无法避免的异常
- 其他异常(Exception)
- 编程人员未预期到的异常
- 业务异常(BuesinessException)
项目异常处理方案
- 业务异常(BuesinessException)
- 发送对应消息传递给用户,提醒规范操作
- 系统异常(SystemException)
- 发送固定信息传递给用户,安抚用户
- 发送特定信息给运维人员,提醒维护
- 记录日志
- 其他异常(Exception)
- 发送固定消息传递给用户,安抚用户
- 发送特定信息给编程人员,提醒维护(纳入预期范围内)
- 记录日志
- 业务异常(BuesinessException)
步骤
自定义项目系统级异常
自定义项目业务级异常
自定义异常编码(持续补充)
触发自定义异常
拦截并处理异常
异常处理器效果对比
拦截器
拦截器概念
- 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
- 作用:
- 在指定的方法调用前后执行预先设定的代码
- 阻止原式方法的执行
拦截器与过滤器的区别
- 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
- 拦截内容不同:Filter对所有访问进行增强,Interceptor仅对SpringMVC的访问进行增强
入门案例
声明拦截器的bean,并实现HandlerInterceptor接口(注意:扫描加载bean)
定义配置类,继承WebMVCConfigurationSupport,实现addInterceptor方法(注意:扫描加载配置)
添加拦截器并设定拦截的访问路径,路径可以通过可变参数设置多个
使用标准接口WebMvcConfigurer简化开发(注意:侵入式较强 )
执行流程
拦截器参数
前置处理
参数
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装
返回值
- 返回值为false,被拦截的处理器将不执行
后置处理
参数
- medelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整
完成后处理
参数
- ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理
多拦截器执行顺序
当配置多个拦截器时,构成拦截器链
拦截器的运行顺序参照拦截器添加顺序为准
当拦截器中出现对原式处理器的拦截,后面的拦截器均终止运行
当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作
Maven进阶
分模块开发与设计
分模块开发意义
- 将原始的模块按照功能才分成若干个子模块,方便模块间的互相调用,接口共享。
分模块开发步骤
创建Maven模块
书写模块代码
通过maven执行安装模块到本地仓库(install指令)
依赖管理
依赖指当前项目运行所需的jar,一个项目可以设置多个依赖
格式:
依赖传递
依赖具有传递性
直接依赖:在当前项目中通过依赖配置建立的依赖关系
间接依赖:被依赖的资源如果依赖其他资源,当前项目简介依赖其他资源
依赖传递冲突问题
- 路径优先:当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高
- 声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的
- 特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的
可选依赖
可选依赖指对外隐藏当前所依赖的资源——不透明
排除依赖
排除依赖值主动断开依赖的资源,被排除的资源无需指定版本——不需要
排除依赖资源仅指定GA即可,无需指定V
聚合
聚合:将多个模块组织成一个整体,同时进行项目构建的过程称为聚合
聚合工程:通常是一个不具有业务功能的“空”工程(有且仅有一个pom文件)
作用:使用聚合工程可以将多个工程编组,通过对聚合工程进行构建,实现对所包含的模块进行构建
- 当工程中某个模块发生更新(变更)时,必须保障工程中与已更新模块关联的模块同步更新,此时可以使用聚合工程来解决批量模块同步构建的问题
聚合工程开发步骤
创建Maven模块,设置打包类型为pom
设置当前聚合工程所包含的子模块名称
继承
- 概念:继承描述的是两个工程间的关系,与java中的继承相似,子工程可以继承父工程中的配置信息,常见于依赖关系的继承
- 作用
- 简化配置
- 减少版本冲突
继承关系步骤
创建Maven模块,设置打包类型为pom
在父工程的pom文件中配置依赖关系(子工程将沿用父工程的依赖关系)
配置子工程中可选的依赖关系
在子工程中配置当前工程所继承的父工程
在子工程中配置使用父工程中可选依赖的坐标
聚合与继承的区别
- 作用
- 聚合用于快速构建项目
- 继承用于快速配置
- 相同点:
- 聚合与继承的pom.xml文件打包方式均为pom,可以将两种关系制作到同一个pom文件中
- 聚合与继承均属于设计性模块,并无实际的模块内容
- 不同点:
- 聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些
- 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己
属性
属性配置与使用
定义属性
引用属性
资源文件引用属性步骤
定义属性
引用属性
开启资源文件目录加载属性的过滤器
配置maven大war包时,忽略web.xml检查
其他属性(了解)
属性列表
- 自定义属性(常用)
- 内置属性
- Setting属性
- Java系统属性
- 环境变量属性
版本管理
- 工程版本
- SNAPSHOT(快照版本)
- 项目开发过程中临时输出的版本,称为快照版本
- 快照版本会随着开发的进展不断更新
- RELEASE(发布版本)
- 项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构建文件是稳定的,即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本
- SNAPSHOT(快照版本)
- 发布版本
- alpha版
- beta版
- 纯数字版
多环境开发
- maven提供配置多种环境的设定,帮助开发者使用过程中快速切换环境
多环境开发步骤
定义多环境
使用多环境(构建过程)
跳过测试
应用场景
- 功能更新中并且没有开发完毕
- 快速打包
- ……
跳过测试
范例:
细粒度控制跳过测试
私服
团队开发分析
私服简介
- 私服是一台独立的服务器,用于解决团队内部的资源共享与资源同步问题
- Nexus
- Sonatype公司的一款maven私服产品
- 下载地址:https://help.sonatype.com/repomanager3/product-information/download
Nexus安装与启动
启动服务器(命令行启动)
访问服务器(默认端口:8081)
修改基础配置信息
- 安装路径下etc目录中nexus-default.properties文件中保存有nexus基础配置信息,例如默认访问端口
修改服务器运行配置信息
- 安装路径下bin目录中nexus.vmoptions文件保存有nexus服务器启动对应的配置信息,例如默认占用内存空间
私服资源操作流程分析
私服仓库分类
资源上传与下载
本地私服访问私服权限设置
本地仓库访问私服权限设置
配置位置(setting.xml文件中)
配置位置(setting.xml文件中)
工程上传到私服服务器设置
配置位置(工程pom文件中)
发布命令
私服访问中央服务器设置
配置位置(nexus服务器页面设置)
SpringBoot
SpringBoot简介
- SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程
入门案例
原生开发SpringMVC程序过程
最简SpringBoot程序所包含的基础文件
- pom.xml
- Application类
Spring程序与SpringBoot程序对比
SpingBoot入门程序步骤
创建新模块,选择Spring初始化,并配置模块相关基础信息
选择当前模块需要的技术集
开发控制器类
运行自动生成的Application类
SpringBoot项目快速启动
对SpringBoot项目打包(执行Maven构建指令package)
执行启动指令
SpringBoot概述
- SpringBoot是由SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程
- Spring程序缺点
- 配置繁琐
- 依赖设置繁琐
- SpringBoot程序优点
- 自动配置
- 起步依赖(简化依赖配置)
- 辅助功能(内置服务器,……)
- 起步依赖
- starter
- SpringBoot中常见项目名称,定义了当前项目使用的所有项目坐标,以达到减少依赖配置的目的
- parent
- 所有SpringBoot项目要继承的项目,定义了若干个坐标版本号(依赖管理,而非依赖),以达到减少依赖冲突的目的
- spring-boot-starter-parent(2.5.0)与spring-boot-starter-parent(2.4.6)共计57处版本不同
- 实际开发
- 使用任意坐标时,仅书写GAV中的G和A,V由SpringBoot提供
- 如发生坐标错误,再指定version(要小心版本冲突)
- 辅助功能
SpringBoot程序启动
启动方式
SpringBoot在创建项目时,采用jar的打包方式
SpringBoot的引导类是项目的入口,运行main方法就可以启动项目
使用maven依赖管理变更起步依赖项
Jetty比Tomcat更轻量级,可扩展性更强(相较于Tomcat),谷歌应用引擎(GAE)已经全面切换为Jetty
基础配置
配置格式
修改服务器端口
SpringBoot提供了多种属性配置方式
application.properties
application.yml
application.yaml
SpringBoot配置文件加载顺序(了解)
- application.properties > application.yml > application.yaml
yaml
- YAML(YAML Ain’t Markup Language),一种数据序列化格式
- 优点:
- 容易阅读
- 容易与脚本语言交互
- 以数据为核心,重数据轻格式
- YAML文件扩展名
- .yml(主流)
- .yaml
yaml语法格式
大小写敏感
属性层级关系使用多行描述,每行结尾使用冒号结束
使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用tab键)
属性前面添加空格(属性名与属性之间的冒号+空格作为分隔)
#表示注释
核心规则:数据前面要加空格与冒号隔开
数组数据在书写位置的下方使用减号作为数据开始符号,每行书写一个数据,减号与数据间空格分隔
yaml数据读取
使用@Value读取单个数据,属性名引用方式:${一级属性名.二级属性名}
封装全部数据到Environment对象
自定义对象封装指定数据
自定义对象封装数据警告解决方案
多环境启动
properties文件多环境启动
主启动配置文件application.properties
环境分类配置文件application-pro.properties
环境分类配置文件application-dev.properties
环境分类配置文件application-test.properties
多环境启动命令格式
带参数启动SpringBoot
参数加载优先顺序
Maven与SpringBoot多环境兼容步骤
Maven中设置多环境属性
SpringBoot中引用Maven属性
对资源文件开启对默认占位符的解析
Maven打包加载到属性,打包顺利通过
配置文件分类
- SpringBoot中4级配置文件
- 1级:file:config/application.yml 【最高】
- 2级:file:application.yml
- 3级:classpath:config/application.yml
- 4级:classpath:application.yml 【最低】
- 作用:
- 一级与二级留作系统打包后设置通用属性
- 三级与四级用于系统开发阶段设置通用属性
整合第三方技术
SpringBoot注解
@SpringBootTest
名称:@SpringBootTest
类型:测试类注解
位置:测试类定义上方
作用:设置JUnit加载的SpringBoot启动类
范例:
相关属性
- classes:设置SpringBoot启动类
整合JUnit
Spring整合JUnit(复习)
SpringBoot整合JUnit
基于SpringBoot实现SSM整合
SpringBoot整合Spring(不存在)
SpringBoot整合SpringMVC(不存在)
SpringBoot整合MyBatis(主要)
整合MyBatis
- SpringConfig
- 导入JdbcConfig
- 导入MyBatisConfig
- JDBCConfig
- 定义数据源(加载properties配置项:driver、url、username、password)
- MyBatisConfig
- 定义SQLSessionFactoryBean
- 定义映射配置
SpringBoot整合MyBatis步骤
创建新模块,选择Spring初始化,并配置模块相关基础信息
选择当前模块需要的技术集(MyBatis、Mysql)
设置数据源参数
定义数据层接口与映射配置
测试类中注入dao接口,测试功能
基于SpringBoot的SSM整合案例
pom.xml
设置起步依赖,必要的资源坐标(druid)
application.yml
设置数据源、端口等
配置类
全部删除
dao
设置@Mapper
测试类
页面
放置在resource目录下的static目录中
MyBatis Plus
MyBatisPlus简介
MyBatis Plus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率。
开发方式
- 基于MyBatis使用MyBatisPlus
- 基于Spring使用MyBatisPlus
- 基于SpringBoot使用MyBatisPlus
SpringBoot整合MyBatis开发过程(复习)
- 创建SpringBoot工程
- 勾选配置使用的技术
- 设置DataSource相关属性(JDBC参数)
- 定义数据层接口映射配置
SpringBoot整合MyBatisPlus入门程序步骤
创建新模块,选择Spring初始化,并配置模块相关基础信息
选择当前模块需要使用的技术集(仅保留JDBC)
手动添加mp起步依赖
设置JDBC参数(application.yml)
制作实体类与表结构(类名与表名对应,属性名与字段名对应)
定义数据接口,继承BaseMapper<User>
MyBatisPlus特性
- 无侵入:只做增强不做改变,不会对现有工程产生影响
- 强大的CRUD操作:你日志通用Mapper,少量配置即可实现单表CRUD操作
- 支持Lambda:编写查询条件无需担心字段写错
- 支持主键自动生成
- 内置分页插件
- …
标准数据层开发
标准数据层CRUD功能
lombok
Lombok,一个Java类库,提供了一组注解,简化POJO实体类开发
常用注解:@Data
为当前实体类在编译期设置对应的get/set方法,无参/有参构造方法,toString方法,hashCode方法,equals方法等
分页功能
MP分页查询功能步骤
设置分页拦截器作为Spring管理的Bean
执行分页查询
开启日志
DQL编程控制
条件查询
MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合
条件查询——设置查询条件
格式一:常规格式
格式二:链式编程格式
格式三:lambda格式(推荐)
格式四:lambda格式(推荐)
条件查询——组合查询条件
并且(and)
或者(or)
条件查询——null值处理
if语句控制条件追加
条件参数控制
条件参数控制(链式编程)
查询投影
查询结果包含模型类中部分属性
查询结果包含模型类中未定义的属性
查询条件
范围匹配(>、=、between)
模糊匹配(like)
空判定(null)
包含性判定(in)
分组(group)
排序(order)
……
用户登录(eq匹配)
购物设定价格区间、户籍设定年龄区间(le ge匹配,或 between匹配)
查信息,搜索新闻(非全文检索版:like匹配)
统计报表(分组查询聚合函数)
更多查询条件设置:https://www.mybatis-plus.com/guide/wrapper.html#abstractwrapper
字段映射与表名映射
主要问题
问题一:表字段与编码属性设计不同步
问题二:编码中添加了数据库中未定义的属性
问题三:采用默认查询开发了更多的字段查看权限
问题四:表名与编码开发设计不同步
注解
@TableField
名称:@TableField
类型:属性注解
位置:模型类属性定义上方
作用:设置当前属性对应的数据库表中的字段关系
范例:
相关属性
- value(默认):设置数据库表字段名称
- exist:设置属性在数据库表字段中是否存在,默认为true。此属性无法与value合并使用
- select:设置属性是否参与查询,此属性与select()映射配置不冲突
@TableName
名称:@TableName
类型:类注解
位置:模型类定义上方
作用:设置当前类对应的数据库表关系
范例:
相关属性
- value:设置数据库表名称
id生成策略控制
不同的表应用不同的id生成策略
- 日志:自增(1,2,3,4……)
- 购物定单:特殊规则
- 外卖单:管理地区日期等信息
- 关系表:可省略id
- …..
注解
名称:@TableId
类型:属性注解
位置:模型类中用于表示主键的属性定义上方
作用:设置当前类中主键属性的生成策略
范例:
相关属性
- value:设置数据库主键名称
- type:设置主键属性的生成策略,值参照IdType枚举值
全局配置
多记录操作
按照主键删除多条记录
根据主键查询多条记录
逻辑删除
- 删除操作业务问题:业务数据从数据库中丢弃
- 逻辑删除:为设置数据是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库汇中
逻辑删除案例步骤
数据库表中条件逻辑删除标记字段
实体类中添加对应字段,并设定当前子墩为逻辑删除标记字段
配置逻辑删除字面值
乐观锁
- 业务并发现象带来的问题:秒杀
乐观锁案例步骤
数据库表中添加锁标记字段
实体类中添加对应字段,并设定当前字段为逻辑删除标记字段
配置乐观锁拦截器实现锁机制对应的动态SQL语句拼装
使用乐观锁机制在修改前必须先获取到对应数据的version方可正常进行
快速开发
代码生成器
- 模板:MyBatisPlus提供
- 数据库相关配置:读取数据库获取信息
- 开发者自定义配置:手工配置
完结撒花~