Java SSM框架
文章目录
1. 简介
框架是一个集成了基本结构、规范、设计模式、编程语言和程序库等基础组件的软件系统,用于提高开发效率、降低开发成本、提高应用程序的稳定性
1.1. 项目构架
1.1.1. 单体架构
把业务的所有功能集中在一个项目中去开发,打成一个包部署
技术框架:Spring、SpringMVC、Mybatis
1.1.2. 分布式架构
根据业务功能对系统做拆分,每个业务模块(服务)作为独立项目去开发和部署
技术框架:SpringBoot(SSM)、SpringCloud、中间件
1.2. 代理
- 代理是指封装非核心逻辑的类、对象或方法
- 目标是指封装核心逻辑的类、对象或方法
1.2.1. 代理分类
- 静态代理:代理类在编译时已经确定的代理方式
- 动态代理:代理类在程序运行时才创建的代理方式
1.3. 编程思想
1.3.1. OOP思想
面向对象编程(OOP)是一种以对象为中心的编程范式,将数据和相关操作封装在一起形成对象
主要特点
封装、继承、多态
1.3.2. AOP思想
面向切面编程(AOP)是一种编程范式,用于将横切关注点从核心业务逻辑中分离出来,一遍重用和管理这些关注点
主要特点
- 将横切关注点模块化,通过定义切面来实现
相关术语
- 横切关注点:横越多个模块的一类动作/行为
- 通知(增强):特定连接点执行的动作/行为
- 连接点:程序执行的某个特定位置
- 切入点:执行特定动作/行为的连接点
- 切面:切入点+通知
- 目标:代理的目标对象
- 代理:向目标对象应用通知后创建的对象
- 织入:应用通知、生成对象的过程
应用场景
日志记录、事务处理、安全控制、性能监控、异常处理、缓存控制、动态代理等
2. Spring Framework
2.1. Spring IoC
Spring核心容器(IoC容器)是一种复杂容器,用于创建、保存、组装组件对象和管理事务、整合其他框架,主要功能为
- 控制反转(Inversion of Control, IoC):程序中的对象由IoC容器创建和管理,即控制权转移到IoC容器
- 依赖注入(Dependency Injection, DI):IoC容器内部处理组件间的依赖关系,实现对象解耦合
2.1.1. 接口/实现类
接口/实现类 | 说明 | 功能 |
---|---|---|
BeanFactory | IoC容器的超接口 | 规定配置框架的基本功能 |
ApplicationContext | BeanFactory的子接口 | 用于IoC容器的功能扩展 |
ClassPathXmlApplicationContext | IoC容器的实现类 | 读取类路径下的XML配置创建容器 |
FileSystemXmlApplicationContext | IoC容器的实现类 | 读取文件系统中的XML配置创建容器 |
AnnotationConfigApplicationContext | IoC容器的实现类 | 读取配置类创建容器 |
WebApplicationContext | IoC容器的实现类 | 基于Web环境创建容器并存入ServletContext |
2.1.2. 开发步骤
- 配置元数据:XML配置文件、注解 + XML配置文件和注解 + 配置类三种方式
- 实例化容器:读取配置元数据,并创建接口实现类的实例
- 获取组件:调用容器实例的getBean方法获取组件
2.2. Spring IoC配置
配置元数据有XML文件、注解 + XML文件和注解 + 配置类三种方式
- 基于XML文件:在XML文件中编写组件配置、外部配置
- 组件配置:bean标签配置组件、注入依赖,context:property-placeholder标签引入外部配置
- 容器实例:创建ClassPathXmlApplicationContext对象解析组件配置
- 基于注解 + XML文件:使用注解标记组件,并用XML文件配置扫描信息
- 组件配置:用Java注解标记组件、注入依赖,XML文件配置第三方组件、引入外部配置
- 组件扫描:context:component-scan标签指定扫描包含/排除的组件
- 容器实例:创建ClassPathXmlApplicationContext对象解析组件配置
- 基于注解 + 配置类:使用注解标记组件、定义配置类
- 组件配置:用Java注解标记组件、注入依赖、引入外部配置
- 组件扫描:定义Java配置类指定扫描的组件信息
- 容器实例:创建AnnotationConfigApplicationContext对象解析组件配置
2.2.1. 配置文件方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="..."/>
<bean id="..." class="...">...</bean>
...
</beans>
组件声明
<bean id="..." class="..."/>
<bean id="..." class="...">...</bean>
-
bean标签用于声明组件,双标签之间配置依赖信息,单标签不配置依赖
-
常用属性
属性 说明 id 组件的beanId,用于唯一标识组件 class 组件的全类名 factory-method 组件的工厂方法名 factory-bean 组件类在容器中的唯一标识即beanId init-method 组件的初始化方法名,要求方法用public void修饰且不含参数 destroy-method 组件的销毁方法名,要求方法用public void修饰且不含参数 scope 组件的作用范围,其值分为以下几种
- WebApplicationContext容器:请求范围(request)和会话范围(session)
- 其他容器:容器范围(singleton,默认)和每次获取(prototype)
根据组件类的不同设计,组件声明有以下类型
- 通过无参构造器创建:单标签声明,需配置组件的id、class属性
- 通过带参构造器创建:双标签声明,需配置组件的id、class属性并配置依赖
- 通过静态工厂创建:单标签声明,需配置组件的id、class、factory-method属性
- 通过实例工厂创建:1)单标签声明组件类,需配置组件类的id、class属性;2)单标签使用组件类声明组件实例,需配置组件的id和上一步中组件类的factory-bean、factory-method属性
依赖配置
<constructor-arg name/index="..." ref/value="..."/>
<property name="..." ref/value="..."/>
- constructor-arg、property均是bean标签的子标签,用于配置组件的依赖
- constructor-arg标签用于构造器方式注入依赖,每个标签一个参数,name/index属性指定参数名/索引
- property用于setter方法注入依赖,name为setter方法的标识(去掉set且使用小驼峰的方法名)
- ref/value属性配置依赖的值,其中ref用于值为beanId的情形,value用于一般情形
- 若依赖项为其他组件,需保证对应组件在IoC容器中配置,但引用、配置的先后顺序无影响
- 构造器注入多个依赖时,若不指定name/index则需按照构造器的形参顺序配置
FactoryBean接口
- 用于配置复杂组件Bean,在getObject方法的实现中配置具体的创建过程
- 三个抽象方法:
T getObject()
、boolean isSingleton()
和Class<?> getObjectType()
使用方法
- 定义类实现FactoryBean,并实现getObject和getObjectType方法
- 在xml文件中配置实现类的元数据(id、class属性,无需factory-method属性)
- 调用getBean方法,传入beanId获取复杂组件,传入&beanId获取实现类组件
2.2.2. 注解 + 配置文件方式
组件声明
注解 | 说明 |
---|---|
@Component | 将类标识为Spring组件 |
@Repository | 将数据访问层(Dao层)的类标识为Spring组件,作用同@Component |
@Service | 将业务层(Service层)的类标识为Spring组件,作用同@Component |
@Controller | 将控制层(Controller层)的类标识为Spring组件,作用同@Component |
- 注解方式声明组件的beanId默认是类名的小驼峰,也可使用value(默认)属性指定
依赖配置
组件类型依赖
注解 | 说明 |
---|---|
@Autowired | 标识需要依赖注入的属性/构造器/构造器参数/setter方法 |
@Qualifier | 标识依赖注入的组件类beanId(value属性) |
@Resource | 标识依赖注入的属性/setter方法(name属性指定beanId) |
- 依赖装配流程大致如下:
- 根据所需的组件类型匹配容器中的组件,若找不到该类型的组件则报错
- 若找到唯一的组件则装配成功,否则根据注解指定的beanId或变量名匹配组件
- 若找到唯一的组件则装配成功,否则装配失败并报错
基本类型依赖
- 直接赋值:直接赋值给组件的属性,即field = value
- 注解赋值:使用
@Value()
注解为属性、参数赋值(可用${}
引用外部配置)
其他配置
注解 | 说明 |
---|---|
@PostConstruct | 标识组件的初始化方法 |
@PreDestory | 标识组件的销毁方法 |
@Scope | 标识组件的作用范围,其中scopeName属性的值为 - ConfigurableBeanFactory类:单例(SCOPE_SINGLETON)、多例(SCOPE_PROTOTYPE) |
扫描配置
标签 | 说明 |
---|---|
context:component-scan | 一级子标签,配置扫描的组件,常用属性 - base-package:指定扫描的包 - use-default-filters:是否使用默认过滤器 |
context:exclude-filter | 二级子标签,配置排除的组件,常用属性 - type:配置类型,注解用annotation - expression:排除注解的全类名 |
context:include-filter | 二级子标签,配置包含的组件,常用属性 - type:配置类型,注解用annotation - expression:排除注解的全类名 |
2.2.3. 注解 + 配置类(完全注解)方式
组件声明
注解 | 说明 |
---|---|
@Bean | 用于标识一个创建、配置和返回组件的方法,其属性 - name/value:指定beanId,默认为方法名 - initMethod/destoryMethod:指定声明周期方法名 |
- @Bean修饰的方法名为组件的默认beanId,方法形参类型为依赖的类型,形参名为依赖的beanId
配置类注解
注解 | 说明 |
---|---|
@Configuration | 标识一个配置类,用于替代xml配置 |
@ComponentScan | 标识扫描注解,其basePackages属性指定扫描的包 |
@ComponentScans | 标识扫描注解,其basePackages属性指定扫描的包 |
@PropertySource | 标识资源文件,其默认属性指定资源文件 |
@import | 引入其他配置类,用于配置类的统一管理 |
- 组件声明、依赖注入的方法同注解 + XML文件方式
- 配置类用于替代XML文件,用于配置扫描注解、第三方组件配置
2.3. Spring IoC使用
2.3.1. 实例化容器
**方式一:**实例化时配置
- 选择IoC容器的实现类,将配置元数据(XML文件/配置类)作为构造器参数创建容器实例
**方式二:**实例化+配置+刷新
- 选择IoC容器的实现类,使用空参构造器创建容器实例
- 调用容器的setConfigLocation/setConfigLocation方法指定配置元数据
- 调用refresh方法刷新配置
2.3.2. 获取组件
context.getBean(beanId, beanClass)
- beanId:要获取组件的唯一标识
- beanClass:要获取组件的类对象(可用多态),默认为Object类型
说明
- 仅传入组件的类对象获取组件,则要求配置中仅有一个该类型的组件
2.3.3. Spring整合JUnit
- 导入依赖:spring-test、junit
- 编写测试类并注入依赖
- 添加JUnit配置注解:@SpringJUnitConfig、@RunWith
2.4. Spring AoP
Spring AoP是一种简化动态代理实现的框架,其底层基于AOP编程思想和动态代理技术
通知类型
- 前置通知:在切点之前执行的通知
- 后置返回通知:在切点正常结束后执行的通知
- 后置异常通知:在切点抛出异常时执行的通知
- 后置通知:在切点退出时执行的通知
- 环绕通知:环绕切点的通知
开发步骤
- 导入依赖:spring-context、spring-aspects
- 实现核心业务类,并加入IoC容器
- 实现业务增强类、配置切入点和切面,并加入IoC容器
- 配置AspectJ自动代理
注意
- IoC容器管理的是生成的代理类,若目标类实现接口则代理类基于JDK代理(实现类)实现,否则基于CGLib实现(继承类)
- 获取代理类组件时,若目标类实现接口则应定义接口类型变量(否则报错)
2.4.1. Spring AoP配置
注解方式
类型 | 注解 | 说明 |
---|---|---|
切面 | @Aspect | 标识一个切面 |
切面 | @Order | 标识切面的优先级,值越小越优先(前置先执行、后置后执行) |
通知 | @Before | 标识前置通知 |
通知 | @After | 标识后置通知 |
通知 | @AfterReturning | 标识后置返回通知 |
通知 | @AfterThrowing | 标识前置异常通知 |
通知 | @Around | 标识环绕通知 |
切点 | @Pointcut | 标识一个切点方法 |
配置文件方式
标签 | 说明 |
---|---|
aop:config | 所有AOP配置的父标签 |
aop:pointcut | 切点表达式标签,其属性 - id:切点表达式的ID - expression:切点表达式 |
aop:aspect | 切面标签,用于关联切面类和通知,其属性 - ref:指定切面表达式的值 |
aop:before | 前置通知标签,用于添加前置通知,其属性 - method:通知方法 - pointcut-ref:切点表达式的引用 |
aop:after | 后置通知标签,用于添加后置通知,其属性 - method:通知方法 - pointcut-ref:切点表达式的引用 |
aop:after-returning | 后置返回通知标签,用于添加后置返回通知,其属性 - method:通知方法 - pointcut-ref:切点表达式的引用 - returning:返回参数 |
aop:after-throwing | 后置异常通知标签,用于添加后置异常通知,其属性 - method:通知方法 - pointcut-ref:切点表达式的引用 - throwing:异常参数 |
注意
- 环绕通知的方法必须指定ProceedingJoinPoint类型的形参,用于获取实参并调用proceed方法
2.4.2. 开启自动代理
- 配置类方式:配置类添加注解
@EnableAspectJAutoProxy
- 配置文件方式:XML文件添加标签
<aop:aspectj-autoproxy/>
2.4.3. 获取通知细节
获取切点信息
在通知方法声明中添加JoinPoint类型的形参,通过形参获取切点信息
常用方法
方法 | 说明 |
---|---|
Signature getSignature() | 获取目标方法签名对象,调用方法获取详细信息 |
Object[] getArgs() | 获取目标方法的实参列表 |
获取返回值信息
- 在后置返回通知方法中添加名为result的形参
- 设置@AfterReturning注解returning属性的值为result
返回异常信息
- 在后置返回通知方法中添加名为exception形参
- 设置@AfterReturning注解的throwing属性的值为exception
2.4.4. 切点表达式
切点表达式通过定义匹配规则来选择要切入的连接点
语法结构
execution(modifiersPattern retTypePattern declaringTypePattern?methodNamePattern(paramsPattern))
- modifiersPattern:方法的权限修饰符规则
- retTypePattern:方法的返回值类型规则
- declaringTypePattern:方法所在类的全限定名规则
- methodNamePattern:方法名规则
- paramsPattern:方法形参规则
说明
- 通配符
*
匹配一个单词、以某单词为前缀或后缀的单词 - 通配符
..
匹配任意个数的项,主要用于declaringTypePattern和paramsPattern ..
不能用于全限定名规则的开头,必须使用非模糊匹配或*
开头- 权限修饰符规则、返回值规则均为任意时,可使用
*
模糊匹配 - 形参规则中,可同时使用模糊匹配
..
和非模糊匹配
提取和重用
- 提取:定义无参、无返回值的方法pc,并添加切点表达式注解@Pointcut
- 定义类提取切点表达式时,需要将该类添加到IoC容器中
- 使用:将通知注解的value属性赋值为pc方法调用(需要
“”
)- 使用其他类中定义的切点表达式,需要使用全限定名.方法名调用
2.5. Spring Tx
- 编程式事务:手动编写程序管理事务的开启、提交和回滚
- 声明式事务:使用注解或配置文件管理事务的开启、提交和回滚
事务管理器
事务管理器 | 说明 |
---|---|
DataSourceTransactionManager | 整合JDBC、JdbcTemplate、Mybatis方式实现的事务管理器 |
HibernateTransactionManager | 整合Hibernate方式实现的事务管理器 |
JpaTransactionManager | 整合Jpa方式实现的事务管理器 |
开发步骤
- 导入依赖:spring-tx、spring-jdbc、spring-orm(Hibernate/Jpa)
- 实现业务代码并加入IoC容器
- 创建事务管理器对象加入IoC容器
- 在对应类/方法上添加事务注解,并开启事务管理
2.5.1. 声明式事务注解
@Transactional
用于声明一个事务,可用在类或方法上
常用属性
属性 | 说明 |
---|---|
readOnly | 设置事务是否只读(默认为false),若是则执行DML语句报错 |
timeout | 设置事务超时时间,单位秒(默认为-1,即不超时) |
rollbackFor | 设置发生异常时回滚的异常类型,默认为RuntimeException和Error |
noRollbackFor | 设置回滚异常类型中不发生回滚的异常类型,默认为空 |
isolation | 设置事务的隔离级别,常用属性值有 -Isolation.DEFAULT:(默认值),取决于具体数据库,MySQL为REPEATABLE_READ - Isolation.READ_UNCOMMITTED:读未提交 - Isolation.READ_COMMITTED:读已提交 - Isolation.REPEATABLE_READ:可重复读 - Isolation.SERIALIZABLE:序列化 |
propagation | 设置事务的传播行为,常用属性值有 - Propagation.REQUIRED:(默认值)当前存在事务就加入,否则新建事务 - Propagation.REQUIRES_NEW:新建事务,当前存在的事务挂起 - Propagation.NESTED:当前存在事务嵌套新事务,否则新建事务 - Propagation.SUPPORTS:当前存在事务就加入,否则不使用事务 - Propagation.NOT_SUPPORTED:不适用事务,当前存在的事务挂起 - Propagation.MANDATORY:必须存在事务,否则抛出异常 - Propagation.NEVER:必须不存在事务,否则抛出异常 |
注意
- 类上的事务注解作用与所有方法,但会被方法上的注解覆盖(就近原则)
- 同一个类中方法的调用不会经过代理
3. MyBatis
MyBatis 是一款优秀的持久层框架,支持自定义 SQL、存储过程以及高级映射
开发步骤
- 导入依赖:mysql-connector-java、mybatis
- 定义实体类、Mapper接口
- 编写Mapper配置、MyBatis配置文件
- 运行:获取Mapper对象执行SQL语句
3.1. 配置文件
3.1.1. MyBatis配置
级别 | 标签 | 说明 |
---|---|---|
0 | configuration | 所有配置的顶级父标签 |
1 | settings | 设置标签的父标签 |
1 | typeAliases | 类型别名的父标签 |
1 | plugins | 插件标签的父标签 |
1 | environments | 环境标签的父标签,其default属性设置选中的环境 |
1 | mappers | 映射标签的父标签 |
2 | setting | 设置标签,常用属性有 - logImpl:日志的具体实现,常用值有LOG4J、STDOUT_LOGGING - mapUnderscoreToCamelCase:下划线自动映射为驼峰式命名 - autoMappingBehavior:resultMap中result自动映射的级别,可选值有NONE、PARTIAL、FULL,默认为PARTIAL即不嵌套时映射 |
2 | typeAlias | 单个类型别名标签,其alias属性设置别名,type属性指定类型(类的全限定符) |
2 | environment | 环境配置标签,其id属性设置环境的唯一标识 |
2 | plugin | 插件标签配置,其interceptor属性配置拦截器 |
2 | package | 批量类型别名标签,其name属性指定设置别名的包。默认别名为类名的小驼峰,也可通过@Alias 注解取别名 |
3 | mapper | 映射配置标签,其resource属性设置XML文件路径 |
3 | package | 批量配置文件标签,其name属性指定配置文件对应接口所在的包,但要求 1. 配置文件与接口文件名相同 2. 配置文件与接口的包结构相同 |
3 | transactionManager | 事务管理器配置的父标签,其type属性设置类型(JDBC/MANAGED) |
3 | dataSource | 数据源配置的父标签,其type属性设置是否用连接池(POOLED/UNPOOLED) |
- | property | 配置项标签,常用属性有 - name:配置项的名称 - value:配置项的值 |
说明
- 配置文件的读取按照从上到下的顺序,故配置项应按照文档顺序编写方式不生效
3.1.2. Mapper配置
常用标签
标签 | 说明 |
---|---|
mapper | 所有映射的顶级父标签,其namespace属性为Mapper接口全限定符 |
insert | INSERT语句标签,标签之间编写语句,常用属性 - id:语句标识符,对应Mapper接口的方法名 - useGeneratedKeys:是否用生成的主键为对象赋值 - keyColumn:主键对应的列名 - keyProperty:主键对应的属性名 - timeout:等待数据库响应的最大时长(秒),超时抛出异常,默认为unset - statementType:使用的语句类型,可选值有STATEMENT,PREPARED和CALLABLE,分别对应Statement,PreparedStatement和CallableStatement |
delete | DELETE语句标签,标签之间编写语句,常用属性 - id:语句标识符,对应Mapper接口的方法名 - timeout:等待数据库响应的最大时长(秒),超时抛出异常,默认为unset - statementType:使用的语句类型,可选值有STATEMENT,PREPARED和CALLABLE,分别对应Statement,PreparedStatement和CallableStatement |
update | UPDATE语句标签,标签之间编写语句,常用属性 - id:语句标识符,对应Mapper接口的方法名 - useGeneratedKeys:是否用生成的主键为对象赋值 - keyColumn:主键对应的列名 - keyProperty:主键对应的属性名 - timeout:等待数据库响应的最大时长(秒),超时抛出异常,默认为unset - statementType:使用的语句类型,可选值有STATEMENT,PREPARED和CALLABLE,分别对应Statement,PreparedStatement和CallableStatement |
select | SELECT语句标签,标签之间编写语句,常用属性 - id:语句标识符,对应Mapper接口的方法名 - resultType:返回结果的实体类全限定符,与resultMap二选一 - resultMap:返回结果的自定义映射标识符,与resultType二选一 - timeout:等待数据库响应的最大时长(秒),超时抛出异常,默认为unset - statementType:使用的语句类型,可选值有STATEMENT,PREPARED和CALLABLE,分别对应Statement,PreparedStatement和CallableStatement |
selectKey | 用于生成键值的SQL子句标签,常用属性 - order:执行的时机,BEFORE表示SQL语句执行前,AFTER表示SQL语句执行后 - keyProperty:键对应的属性名 - resultType:键对应的返回类型 |
注意:
- Mapper接口的方法名不能重复,即方法不能重写
动态赋值
${}
:基于字符串拼接方式,能够替代SQL语句的所有部分#{}
:基于?
占位符 + 赋值方式,只能替代SQL语句中的值
3.2. 运行流程
- 获取配置资源流
- 调用工厂方法创建SqlSessionFactory对象
- 获取SqlSession对象:sqlSessionFactory.openSqlSession()
- 获取Mapper对象,并执行语句
- 提交结果、关闭连接
3.3. 数据传递
3.3.1. 数据输入
使用${}
和#{}
接收SQL语句的输入输入
单个简单类型参数
- SQL语句的参数命名没有要求,但推荐使用Mapper方法的参数名
多个简单类型参数
- (推荐)使用注解为参数命名
- 使用默认参数名:arg0, arg1… 或 param1, param2…
单个复杂类型参数
- 实体对象:SQL语句的参数名为对象的字段名
- Map类型:SQL语句的参数名为Map的键名
3.3.2. 数据输出
通过标签的resultType属性配置SQL语句的输出数据类型
单个查询结果
- 使用Mybatis内部定义的数据类型别名(72种)
_xxx
:基本数据类型xxx的别名xxx
:包装类或与内部类型Xxx的别名
- 使用返回结果类型或实体类的全限定符
- 使用typeAlias标签定义的数据类型别名
- 使用Map类型(列名为键,数据为值)
多个查询结果
- 使用查询结果列表的泛型全限定符或别名
3.3.3. 结果映射标签
标签 | 说明 |
---|---|
resultMap | 用于自定义映射关系,常用属性 - id:自定义映射的标识符 - type:映射的实体类型 |
resultMap.id | 自定义主键属性的映射关系,常用属性 - column:主键的列名 - property:主键的属性名 |
resultMap.result | 自定义简单类型的映射关系,常用属性 - column:简单类型的列名 - property:简单类型的属性 |
resultMap.association | 自定义实体对象的映射关系,常用属性 - property:实体类型的属性 - javaType:实体对象的类型 |
resultMap.collection | 自定义集合类型的映射关系,常用属性 - property:集合类型的属性 - ofType:集合元素的类型 |
3.4. 动态语句标签
标签 | 说明 |
---|---|
if | 条件子句标签,根据test属性的动态值拼接语句条件 |
where | WHERE子句标签,根据内部动态条件个数 1. 拼接where关键字 2. 删除多余的and/or关键字 |
set | SET子句标签,根据内部动态条件个数 1. 拼接set关键字 2. 删除多余的 , |
trim | 前后缀标签,常用属性有 - prefix:动态添加的前缀 -suffix:动态添加的后缀 - prefixOverrides:动态去除的前缀,有多个可能值使用` |
choose…when…otherwise | 条件选择标签,找到choose中第一个为真的when作为语句条件,否则使用otherwise作为语句条件 |
foreach | 批量遍历标签,常用属性有 - collection:遍历的集合 - index:元素的索引 - item:集合元素的别名 - separator:元素拼接的分隔符 - open:元素拼接的开始字符 - close:元素拼接的结束字符 |
sql | 语句片段定义标签,常用属性有 - id:语句片段的标识符 |
include | 语句片段引用标签,常用属性有 - refId:引用的语句片段标识 |
3.5. 使用扩展
3.5.1. 分页插件
插件机制的组件
Interceptor
(拦截器):定义拦截方法intercept,在语句执行、返回结果时调用Invocation
(调用):封装拦截方法,包括Object target
、Method method
和Object[] args
三个字段InterceptorChain
(拦截器链):管理所有的拦截器,按顺序调用
使用步骤
- 导入依赖:pagehelper
- 配置分页插件:通过MyBatis配置文件的plugins.plugin设置
- 设置分页参数并执行查询,创建PageInfo对象获取分页信息
注意
- 分页插件不能去除句尾的
;
3.5.2. 逆向工程
半自动框架Mybatis全自动化的方式:逆向工程、MyBatis Plus
4. Spring MVC
Spring MVC全程Spring Web MVC,是基于Servlet API构建的Web层(表述层)框架
4.1. 简介
4.1.1. 主要作用
- 简化前端数据接收
- 简化后端数据响应
4.1.2. 核心组件
- DispatcherServlet:负责请求处理和分发,由SpringMVC提供,在web.xml中配置
- HandlerMapping:缓存Handler方法和路径,由SpringMVC提供,用IoC容器管理
- HandlerAdapter:处理请求参数和响应数据,由SpringMVC提供,用IoC容器管理
- ViewResovler:简化模板视图页面查找,由SpringMVC提供,用IoC容器管理
- Handler:接收请求参数、调用业务并返回结果,由程序员定义
4.2. 数据接收
4.2.1. 访问路径
注解 | 范围 | 说明 |
---|---|---|
@RequestMapping | 类型/方法 | 关联请求的URL地址和处理方式(handler方法),常用属性 - value:请求路径列表,不要求以 / 开头- method:请求方法列表,取值由RequestMethod枚举类指定 |
@GetMapping | 方法 | 关联GET请求的URL地址和处理方式(handler方法),常用属性 - value:请求路径列表,不要求以 / 开头 |
@PostMapping | 方法 | 关联POST请求的URL地址和处理方式(handler方法),常用属性 - value:请求路径列表,不要求以 / 开头 |
@PutMapping | 方法 | 关联PUT请求的URL地址和处理方式(handler方法),常用属性 - value:请求路径列表,不要求以 / 开头 |
@DeleteMapping | 方法 | 关联DELETE请求的URL地址和处理方式(handler方法),常用属性 - value:请求路径列表,不要求以 / 开头 |
说明
- 请求路径由类型上的通用路径和方法上的具体路径组成
- 请求路径支持模糊路径匹配,其中
*
匹配一层路径,**
匹配任意层路径 - 请求路径中
{key}
用于动态路径设置,匹配任意一层路径并通过key
取值 - 请求方法不正确会抛出405异常
4.2.2. 请求参数
方式一:简单参数
在handler方法的形参列表中,定义与请求参数同名、同类型的变量即可自动接收
说明
- 请求参数不存在则对应形参赋值为空或报错
方式二:@RequestParam注解
在handler方法的形参列表中,添加@RequestParam注解并设置属性
- name/value:请求参数名,形参名与其一致可省略
- required:是否必须,默认为true,此时参数不存在报400错误
- defaultValue:不存在时设置的默认值,与required = false搭配使用
方式三:实体参数
在handler方法的形参列表中,定义属性名与请求参数同名、同类型的实体对象
方式四:列表参数
在handler方法的形参列表中,定义参数的列表类型并添加@RequestParam注解
4.2.3. 路径参数
在handler方法的形参列表中,添加@PathVariable注解并设置属性
- name/value:路径参数名,形参名与其一致可省略
4.2.4. 请求体
在handler方法的形参列表中,添加@RequestBody注解
说明
- 需要添加JSON依赖,并在配置类添加@EnableWebMvc
4.2.5. Cookie值
在handler方法的形参列表中,添加@CookieValue注解并设置属性
- name/value:Cookie名,形参名与其一致可省略
4.2.6. 请求头
在handler方法的形参列表中,添加@RequestHeader注解并设置属性
- name/value:请求头字段名,形参名与其一致可省略
4.2.7. 原生API参数
在handler方法的形参列表中,添加对应类型的参数即可,常用的有ServletRequest、ServletResponse、HttpSession、InputStream/OutputStream/Reader/Writer
4.2.8. 共享域参数
- 使用共享域对象:setAttribute、getAttribute、removeAttribute方法
- 使用Map类型形参:put、get、remove方法
- 使用Model/ModelMap类型形参:addAttribute、getAttribute、remove方法
- 使用ModelAndView类型对象:addObject、setViewName、getModel/getModelMap方法
4.3. 数据响应
4.3.1. 响应动态页面
实现步骤
- 导入jsp依赖并创建动态页面
- 配置列中添加JSP视图解析器
- handler中返回视图:handler不添加
@ResponseBody
注解,仅返回页面路径
转发和重定向
- 转发:返回的页面路径前添加
forward:
- 重定向:返回的页面路径前添加
redirect:
说明
- 在Spring-MVC中,转发和重定向项目内资源的路径是一样的
4.3.2. 响应JSON数据
实现步骤
- 导入json依赖并开启数据转化器
- handler添加
@ResponseBody
注解 - 返回响应数据,由HandlerAdapter转化为JSON或XML格式的响应数据
4.3.3. 响应静态资源
实现步骤
- 开启默认Servlet资源处理器
4.4. RESTful风格
RESTful(Representational State Transfer)是一种基于HTTP和标准化设计原则的软件架构风格,用于设计和实现可靠、可扩展和易于集成的Web服务和应用程序
4.4.1. 风格特点
- URI代表一种资源,是名词
- 客户端使用GET、POST、PUT和DELETE操作服务端资源:GET用于获取资源,POST用于新建资源,PUT用于更新资源,DELETE用于删除资源
- 资源的表现形式为XML或者JSON
- 客户端与服务端的交互在请求之间是无状态的,每个请求都必须包含理解请求所必需的信息
4.4.2. 设计规范
- 根据动作选择HTTP协议的请求方式
- 路径使用名词,仅唯一标识资源而不标识动作
4.4.3. 通用原则
- 路径参数用于指定资源的唯一标识,请求参数用于指定查询条件或操作参数
- 请求参数应限制在10个以内,以便于接口的维护和使用
- 对于敏感信息最好使用POST和请求体来传递参数
4.5. 使用扩展
4.5.1. 全局异常处理
实现步骤
- 定义异常处理控制器类:@RestControllerAdvice注解、@ControllerAdvice注解
- 声明异常处理方法handler:@ExceptionHandler注解
- 配置扫描异常处理控制器类
4.5.2. 拦截器
实现步骤
- 自定义拦截器类(实现HandlerInterceptor接口),并重写preHandle、postHandle和afterCompletion方法
- 注册拦截器:配置类中重写addInterceptors方法,调用registry.addInterceptor添加拦截器
拦截配置
- 默认情况下拦截所有分发的请求
- 链式调用addPathPatterns方法添加拦截的请求路径,excludePathPatterns方法排除配置拦截的路径
优先级
- 多个拦截器的优先级按照注册的顺序依次递减
- 对于preHandle拦截器,优先级高者先执行,对于postHandle和afterHandle拦截器,优先级高者后执行
4.5.3. 参数校验
实现步骤
- 导入依赖:hibernate-validator和hibernate-validator-annotation-processor
- 配置类添加@EnableWebMvc注解以添加LocalValidatorFactoryBean组件
- 在实体类的定义中添加校验注解,并在实体对象前添加@Validated注解
校验注解
注解 | 说明 |
---|---|
@Null | 标注值必须为null |
@NotNull | 标注值不可为null |
@AssertTrue | 标注值必须为true |
@AssertFalse | 标注值必须为false |
@Min(value) | 标注值必须大于或等于指定值value |
@Max(value) | 标注值必须小于或等于指定值value |
@DecimalMin(value) | 标注值必须大于或等于指定值value |
@DecimalMax(value) | 标注值必须小于或等于指定值value |
@Size(max, min) | 标注值大小必须在max和min限定的范围内 |
@Digits(integer, fratction) | 标注值必须包含指定的整数位和小数位 |
@Past | 标注值必须是过去的日期 |
@Future | 标注值必须是将来的日期 |
@Pattern(pattern) | 标注值必须符合指定的正则表达式pattern |
标注值必须是格式正确的Email地址 | |
@NotEmpty | 标注值长度必须大于0 |
@Length(min, max) | 标注值的字符串长度必须在指定的范围内 |
@Range(min, max) | 标注值必须在指定的范围内 |
错误捕获
- 在@Validated注解的形参后(必须紧邻)定义BindingResult类型的对象,接收校验的错误信息并处理
4.5.4. 跨域访问
在Controller类上添加@CrossOrigin注解
5. Spring Boot
Spring Boot是一个基于Spring的框架,通过自动配置和约定大于配置的原则,使开发者能够快速搭建独立、生产级别的应用程序,旨在简化 Spring 应用的配置和开发过程
开发步骤
- 创建Maven工程,继承spring-boot-starter-parent项目
- 添加启动器依赖:spring-boot-starter-*
- 编写控制层、服务层和持久化层的逻辑
- 编写启动引导类:添加注解并编写main方法
说明
- 父项目的父项目
spring-boot-dependencies
定义所需的依赖的版本 - 启动器预定义了依赖项集合,用以简化依赖管理
- 引导类的@SpringBootApplication注解有以下作用
- 自动配置:包含@EnableAutoConfiguration注解,启动自动配置机制
- 组件扫描:包含@ComponentScan注解,自动扫描并加载引导类所在包及其子包下的组件
- 声明配置类:包含@Configuration注解,将被标注的类声明为配置类
5.1. 统一配置管理
使用固定位置、固定命名的配置文件集中式配置管理,其中
- 固定位置:项目的resources文件夹下,即
src/main/resources
- 固定命名:
application.properties
或application.yml(.yaml)
,其中properties优先级更高
说明
- 基本配置的都有默认值
- 支持自定义键值对以在程序中使用
5.1.1. 配置文件
.properties
格式
- 使用
=
形式的键值对,即key=value
- 使用
.
表示键之间的层次结构
.yml(.yaml)
格式
- 使用
:
形式的键值对,即key: value
(冒号后有空格) - 使用
-
表示连续的集合 - 使用缩进表示键之间的层次结构
5.1.2. 配置注入
- 单个注入:变量添加@Value注解
- 批量注入:类型添加@ConfigurationProperties注解,要求注解的
prefix
+.
+属性名与配置中键相同
5.1.3. 多文件配置
- 创建配置文件
application-{key}.properties(yml/yaml)
,并编写配置 - 激活配置文件
application-{key}.properties(yml/yaml)
- 配置中激活:在
application.properties(yml/yaml)
中激活配置:spring.profiles.active: key
,多个key使用,
隔开 - 命令行激活:添加命令行参数
--spring.profiles.active=key
- 配置中激活:在
说明
- 配置文件中有同名属性时,激活配置中的属性优先,多个激活配置中后者优先
5.2. 常用配置
5.2.1. 控制层配置
配置 | 说明 |
---|---|
server.port | 应用程序的HTTP服务器的端口号 |
server.servlet.context-path | 应用程序的上下文路径 |
spring.mvc.view.prefix spring.mvc.view.suffix | 视图解析器的前、后缀 |
spring.web.resources.static-locations | 静态资源的路径,默认的路径为: - classpath:/META-INF/resources/ - classpath:/resources/ - classpath:/static/ - classpath:/public/ |
spring.http.encoding.charset | 应用程序的HTTP请求和响应的字符编码 |
5.2.2. 持久层配置
数据源配置
配置 | 说明 |
---|---|
spring.datasource.type | 数据源类型 |
spring.datasource.url | 数据源URL |
spring.datasource.driver-class-name | 数据源驱动名 |
spring.datasource.username | 数据源用户名 |
spring.datasource.password | 数据源密码 |
MyBatis配置
配置 | 说明 |
---|---|
mybatis.mapper-locations | Mapper配置的路径 |
mybatis.type-aliases-package | 自定义类型取别名的包 |
mybatis.configuration.log-impl | 日志配置 |
mybatis.configuration.map-underscore-to-camel-case | 下滑-驼峰自动映射 |
mybatis.configuration.auto-mapping-behavior | 自动映射行为 |
说明
- 在启动引导类需要添加@MapperScan扫描Mapper接口所在的包
5.3. 项目部署
-
添加插件:
spring-boot-maven-plugin
插件 -
打包项目:执行Maven命令将项目打包成可执行的jar包
-
运行项目:控制台执行命令运行程序
java -jar [options] [params] xxx.jar
说明
-D<name>=<value>
:设置系统属性-X
:设置JVM参数,常用的选现有-Xmx<size>
:设置JVM的最大堆内存大小-Xms<size>
:设置JVM的初始堆内存大小
6. MyBatis-Plus
MyBatis-Plus是一个 MyBatis的增强工具,为简化开发、提高效率而生
6.1. 基础功能
6.1.1. Mapper层
Mapper接口继承BaseMapper接口,其中泛型参数为实体类
分页查询
- 导入插件:在启动类中创建Bean并添加分页拦截器PaginationInnerInterceptor
- 自定义接口:自定义分页查询方法,并编写SQL语句
- 分页查询:创建分页对象并查询结果
常用方法
方法 | 说明 |
---|---|
int insert(T entity) | 插入实体对象记录 |
int updateById(T entity) | 根据ID更新实体对象记录 |
int update(T updateEntity, Wrapper<T> whereWrapper) | 根据条件更新实体对象记录 |
int deleteById(Serializable id) | 根据ID删除记录 |
int deleteBatchIds(Collection<? extends Serializable> idList) | 根据ID列表批量删除记录 |
int deleteByMap(Map<String, Object> columnMap) | 根据Map条件删除记录 |
int delete(Wrapper<T> wrapper) | 根据条件删除记录 |
T selectById(Serializable id) | 根据ID获取实体对象 |
List<T> selectBatchIds(Collection<? extends Serializable> idList) | 根据ID列表批量获取实体对象列表 |
T selectOne(Wrapper<T> queryWrapper) | 根据查询条件获取实体对象 |
List <T> selectList(Wrapper<T> queryWrapper) | 根据查询条件获取实体对象列表 |
List <T> selectByMap(Map<String, Object> columnMap) | 根据Map条件获取实体对象列表 |
List <Map<String, Object>> selectMaps(Wrapper<T> queryWrapper) | 根据查询条件获取实体对象的Map列表 |
IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper) | 根据查询条件获取分页的实体对象列表 |
IPage<T> selectMapsPage(IPage<T> page, Wrapper<T> queryWrapper) | 根据查询条件获取分页的实体对象Map列表 |
Integer selectCount(Wrapper<T> queryWrapper) | 获取满足条件的记录总数 |
6.1.2. Service层
Service接口继承IService接口,实现类继承ServiceImpl类
常用方法
法 | 说明 |
---|---|
boolean save(T entity) | 保存实体对象记录 |
boolean saveBatch(Collection<T> entityList[, int batchSize]) | 批量保存实体对象记录 |
boolean saveOrUpdate(T entity) | 保存或更新实体对象记录 |
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) | 根据条件保存或更新实体对象 |
boolean saveOrUpdateBatch(Collection<T> entityList[, int batchSize]) | 批量保存或更新实体对象记录 |
boolean update(Wrapper<T> updateWrapper) | 根据条件更新实体对象记录 |
boolean update(T updateEntity, Wrapper<T> whereWrapper) | 根据条件更新实体对象记录 |
boolean updateById(T entity) | 根据ID更新实体对象记录 |
boolean updateBatchById(Collection<T> entityList[, int batchSize]) | 根据ID列表批量更新实体对象记录 |
boolean remove(Wrapper<T> queryWrapper) | 根据条件删除记录 |
boolean removeById(Serializable id) | 根据ID删除记录 |
boolean removeByMap(Map<String, Object> columnMap) | 根据Map条件删除记录 |
boolean removeByIds(Collection<? extends Serializable> idList) | 根据ID列表批量删除记录 |
T getById(Serializable id) | 根据ID获取实体对象 |
T getOne(Wrapper<T> queryWrapper) | 根据查询条件获取实体对象 |
Map<String, Object> getMap(Wrapper<T> queryWrapper) | 根据查询条件获取实体对象的Map |
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) | 根据查询条件获取实体对象并映射为V类型 |
List<T> list([Wrapper<T> queryWrapper]) | 获取(满足条件的)实体对象列表 |
Collection<T> listByIds(Collection<? extends Serializable> idList) | 根据ID列表获取实体对象集合 |
Collection<T> listByMap(Map<String, Object> olumnMap) | 根据Map条件获取实体对象集合 |
List<Map<String, Object> > listMaps([Wrapper<T> queryWrapper]) | 获取(满足条件的)实体对象的Map列表 |
<V> List<V> listObjs([Wrapper<T> queryWrapper, Function<? super Object, V> mapper) | 根据查询条件获取实体对象并映射为V类型对象的列表 |
int count() | 查询记录总数 |
int count(Wrapper<T> queryWrapper) | 查询满足条件的记录总数 |
6.1.3. 条件查询
通过条件构造器支持:调用方法设置条件、链式调用组合条件
常用方法
方法名 | 说明 |
---|---|
eq/ne/gt/ge/lt/le | 比较,等于/不等于/大于/大于等于/小于/小于等于 |
in/notIn | 包含,IN/NOT IN |
between/notBetween | 区间,BETWEEN…AND… |
like/notLike | 模糊,LIKE |
isNull/isNotNull | 空值,IS NULL/IS NOT NULL |
groupBy | 分组,GROUP BY… |
orderByAsc/orderByDesc/orderBy | 排序,ORDER BY…ASC/DSC |
having | HAVING |
or/and | 拼接,OR/AND |
6.1.4. 核心配置
常用注解
注解 | 说明 |
---|---|
@TableName | 实体类与数据库表的映射 |
@TableId | 类属性与数据表主键的映射以及主键策略,其中主键策略用type属性设置,常用值为 - AUTO:ID自增,需配置数据库的主键自增长 - ASSIGN_ID(默认):雪花算法分配无重复的Long或String类型主键 |
@TableField | 类属性与数据表字段的映射以及是否存在 |
@TableLogic | 数据库记录逻辑删除字段注解 |
@Version | 数据库记录版本号字段注解 |
常用配置
配置 | 说明 |
---|---|
mapper-locations | mapper配置文件的路径,默认为classpath*:/mapper/**/*.xml |
global-config.db-config.table-prefix | 数据库表明的前缀,默认为空 |
global-config.db-config.id-type | 数据库的主键策略,默认为雪花算法(生成Long类型的无重复整数) |
global-config.db-config.logic-delete-field | 逻辑删除字段名 |
global-config.db-config.logic-delete-value | 逻辑删除字段值,默认为1 |
global-config.db-config.logic-not-delete-value | 逻辑未删除字段值,默认为0 |
6.2. 高级扩展
6.2.1. 逻辑删除
- 数据表添加逻辑删除字段
- 实体类添加逻辑删除属性,并使用@TableLogic标识
- 执行删除操作
6.2.2. 乐观锁
- 数据表添加版本号字段
- 实体类添加版本号属性,并使用@Version标识
- 启动类获取拦截器并添加乐观锁拦截器OptimisticLockerInnerInterceptor
- 执行数据库操作
6.2.3. 防止全表更改
- 启动类获取拦截器并添加组织攻击拦截器BlockAttackInnerInterceptor
7. 扩展
7.1. 模板类
7.1.1. JDBC模板类
org.springframework.jdbc.core.JdbcTemplate
用于简化JDBC的CURD操作- 使用JDBC模板类需要导入
spring-jdbc
依赖
使用步骤
- 实例化模板类对象并配置JDBC数据源
- 调用相关方法执行SQL语句
常用方法
方法 | 说明 |
---|---|
void setDataSource(dataSource) | 设置数据源 |
int update(String sql, Object… args) | 执行DDL、DML、DCL语句 |
<T> T queryForObject(String sql, RowMapper<T> rowMapper, Object… args) | 执行查询单个对象的DQL语句 |
<T> List<T> query(String sql, RowMapper<T> rowMapper) | 执行查询集合的DQL语句 |