【后端开发】08-Java SSM框架

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. 接口/实现类
接口/实现类说明功能
BeanFactoryIoC容器的超接口规定配置框架的基本功能
ApplicationContextBeanFactory的子接口用于IoC容器的功能扩展
ClassPathXmlApplicationContextIoC容器的实现类读取类路径下的XML配置创建容器
FileSystemXmlApplicationContextIoC容器的实现类读取文件系统中的XML配置创建容器
AnnotationConfigApplicationContextIoC容器的实现类读取配置类创建容器
WebApplicationContextIoC容器的实现类基于Web环境创建容器并存入ServletContext
2.1.2. 开发步骤
  1. 配置元数据:XML配置文件注解 + XML配置文件注解 + 配置类三种方式
  2. 实例化容器:读取配置元数据,并创建接口实现类的实例
  3. 获取组件:调用容器实例的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()

使用方法

  1. 定义类实现FactoryBean,并实现getObject和getObjectType方法
  2. 在xml文件中配置实现类的元数据(id、class属性,无需factory-method属性)
  3. 调用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)
  • 依赖装配流程大致如下:
    1. 根据所需的组件类型匹配容器中的组件,若找不到该类型的组件则报错
    2. 若找到唯一的组件则装配成功,否则根据注解指定的beanId或变量名匹配组件
    3. 若找到唯一的组件则装配成功,否则装配失败并报错

基本类型依赖

  • 直接赋值:直接赋值给组件的属性,即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文件/配置类)作为构造器参数创建容器实例

**方式二:**实例化+配置+刷新

  1. 选择IoC容器的实现类,使用空参构造器创建容器实例
  2. 调用容器的setConfigLocation/setConfigLocation方法指定配置元数据
  3. 调用refresh方法刷新配置
2.3.2. 获取组件
context.getBean(beanId, beanClass)
  • beanId:要获取组件的唯一标识
  • beanClass:要获取组件的类对象(可用多态),默认为Object类型

说明

  • 仅传入组件的类对象获取组件,则要求配置中仅有一个该类型的组件
2.3.3. Spring整合JUnit
  1. 导入依赖:spring-test、junit
  2. 编写测试类并注入依赖
  3. 添加JUnit配置注解:@SpringJUnitConfig、@RunWith

2.4. Spring AoP

Spring AoP是一种简化动态代理实现的框架,其底层基于AOP编程思想和动态代理技术

aop-principle-removebg-preview

通知类型

  • 前置通知:在切点之前执行的通知
  • 后置返回通知:在切点正常结束后执行的通知
  • 后置异常通知:在切点抛出异常时执行的通知
  • 后置通知:在切点退出时执行的通知
  • 环绕通知:环绕切点的通知

开发步骤

  1. 导入依赖:spring-context、spring-aspects
  2. 实现核心业务类,并加入IoC容器
  3. 实现业务增强类、配置切入点和切面,并加入IoC容器
  4. 配置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()获取目标方法的实参列表

获取返回值信息

  1. 在后置返回通知方法中添加名为result的形参
  2. 设置@AfterReturning注解returning属性的值为result

返回异常信息

  1. 在后置返回通知方法中添加名为exception形参
  2. 设置@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方式实现的事务管理器

开发步骤

  1. 导入依赖:spring-tx、spring-jdbc、spring-orm(Hibernate/Jpa)
  2. 实现业务代码并加入IoC容器
  3. 创建事务管理器对象加入IoC容器
  4. 在对应类/方法上添加事务注解,并开启事务管理
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、存储过程以及高级映射

开发步骤

  1. 导入依赖:mysql-connector-java、mybatis
  2. 定义实体类、Mapper接口
  3. 编写Mapper配置、MyBatis配置文件
  4. 运行:获取Mapper对象执行SQL语句

3.1. 配置文件

3.1.1. MyBatis配置
级别标签说明
0configuration所有配置的顶级父标签
1settings设置标签的父标签
1typeAliases类型别名的父标签
1plugins插件标签的父标签
1environments环境标签的父标签,其default属性设置选中的环境
1mappers映射标签的父标签
2setting设置标签,常用属性有
- logImpl:日志的具体实现,常用值有LOG4J、STDOUT_LOGGING
- mapUnderscoreToCamelCase:下划线自动映射为驼峰式命名
- autoMappingBehavior:resultMap中result自动映射的级别,可选值有NONE、PARTIAL、FULL,默认为PARTIAL即不嵌套时映射
2typeAlias单个类型别名标签,其alias属性设置别名,type属性指定类型(类的全限定符)
2environment环境配置标签,其id属性设置环境的唯一标识
2plugin插件标签配置,其interceptor属性配置拦截器
2package批量类型别名标签,其name属性指定设置别名的包。默认别名为类名的小驼峰,也可通过@Alias注解取别名
3mapper映射配置标签,其resource属性设置XML文件路径
3package批量配置文件标签,其name属性指定配置文件对应接口所在的包,但要求
1. 配置文件与接口文件名相同
2. 配置文件与接口的包结构相同
3transactionManager事务管理器配置的父标签,其type属性设置类型(JDBC/MANAGED)
3dataSource数据源配置的父标签,其type属性设置是否用连接池(POOLED/UNPOOLED)
-property配置项标签,常用属性有
- name:配置项的名称
- value:配置项的值

说明

  • 配置文件的读取按照从上到下的顺序,故配置项应按照文档顺序编写方式不生效
3.1.2. Mapper配置

常用标签

标签说明
mapper所有映射的顶级父标签,其namespace属性为Mapper接口全限定符
insertINSERT语句标签,标签之间编写语句,常用属性
- id:语句标识符,对应Mapper接口的方法名
- useGeneratedKeys:是否用生成的主键为对象赋值
- keyColumn:主键对应的列名
- keyProperty:主键对应的属性名
- timeout:等待数据库响应的最大时长(秒),超时抛出异常,默认为unset
- statementType:使用的语句类型,可选值有STATEMENT,PREPARED和CALLABLE,分别对应Statement,PreparedStatement和CallableStatement
deleteDELETE语句标签,标签之间编写语句,常用属性
- id:语句标识符,对应Mapper接口的方法名
- timeout:等待数据库响应的最大时长(秒),超时抛出异常,默认为unset
- statementType:使用的语句类型,可选值有STATEMENT,PREPARED和CALLABLE,分别对应Statement,PreparedStatement和CallableStatement
updateUPDATE语句标签,标签之间编写语句,常用属性
- id:语句标识符,对应Mapper接口的方法名
- useGeneratedKeys:是否用生成的主键为对象赋值
- keyColumn:主键对应的列名
- keyProperty:主键对应的属性名
- timeout:等待数据库响应的最大时长(秒),超时抛出异常,默认为unset
- statementType:使用的语句类型,可选值有STATEMENT,PREPARED和CALLABLE,分别对应Statement,PreparedStatement和CallableStatement
selectSELECT语句标签,标签之间编写语句,常用属性
- 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. 运行流程

  1. 获取配置资源流
  2. 调用工厂方法创建SqlSessionFactory对象
  3. 获取SqlSession对象:sqlSessionFactory.openSqlSession()
  4. 获取Mapper对象,并执行语句
  5. 提交结果、关闭连接

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属性的动态值拼接语句条件
whereWHERE子句标签,根据内部动态条件个数
1. 拼接where关键字
2. 删除多余的and/or关键字
setSET子句标签,根据内部动态条件个数
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 targetMethod methodObject[] args三个字段
  • InterceptorChain(拦截器链):管理所有的拦截器,按顺序调用

使用步骤

  1. 导入依赖:pagehelper
  2. 配置分页插件:通过MyBatis配置文件的plugins.plugin设置
  3. 设置分页参数并执行查询,创建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. 响应动态页面

实现步骤

  1. 导入jsp依赖并创建动态页面
  2. 配置列中添加JSP视图解析器
  3. handler中返回视图:handler不添加@ResponseBody注解,仅返回页面路径

转发和重定向

  • 转发:返回的页面路径前添加forward:
  • 重定向:返回的页面路径前添加redirect:

说明

  • 在Spring-MVC中,转发和重定向项目内资源的路径是一样的
4.3.2. 响应JSON数据

实现步骤

  1. 导入json依赖并开启数据转化器
  2. handler添加@ResponseBody注解
  3. 返回响应数据,由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. 全局异常处理

实现步骤

  1. 定义异常处理控制器类:@RestControllerAdvice注解、@ControllerAdvice注解
  2. 声明异常处理方法handler:@ExceptionHandler注解
  3. 配置扫描异常处理控制器类
4.5.2. 拦截器

实现步骤

  1. 自定义拦截器类(实现HandlerInterceptor接口),并重写preHandle、postHandle和afterCompletion方法
  2. 注册拦截器:配置类中重写addInterceptors方法,调用registry.addInterceptor添加拦截器

拦截配置

  • 默认情况下拦截所有分发的请求
  • 链式调用addPathPatterns方法添加拦截的请求路径,excludePathPatterns方法排除配置拦截的路径

优先级

  • 多个拦截器的优先级按照注册的顺序依次递减
  • 对于preHandle拦截器,优先级高者先执行,对于postHandle和afterHandle拦截器,优先级高者后执行
4.5.3. 参数校验

实现步骤

  1. 导入依赖:hibernate-validator和hibernate-validator-annotation-processor
  2. 配置类添加@EnableWebMvc注解以添加LocalValidatorFactoryBean组件
  3. 在实体类的定义中添加校验注解,并在实体对象前添加@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标注值必须是格式正确的Email地址
@NotEmpty标注值长度必须大于0
@Length(min, max)标注值的字符串长度必须在指定的范围内
@Range(min, max)标注值必须在指定的范围内

错误捕获

  • 在@Validated注解的形参后(必须紧邻)定义BindingResult类型的对象,接收校验的错误信息并处理
4.5.4. 跨域访问

在Controller类上添加@CrossOrigin注解

5. Spring Boot

Spring Boot是一个基于Spring的框架,通过自动配置约定大于配置的原则,使开发者能够快速搭建独立、生产级别的应用程序,旨在简化 Spring 应用的配置和开发过程

开发步骤

  1. 创建Maven工程,继承spring-boot-starter-parent项目
  2. 添加启动器依赖:spring-boot-starter-*
  3. 编写控制层、服务层和持久化层的逻辑
  4. 编写启动引导类:添加注解并编写main方法

说明

  • 父项目的父项目spring-boot-dependencies定义所需的依赖的版本
  • 启动器预定义了依赖项集合,用以简化依赖管理
  • 引导类的@SpringBootApplication注解有以下作用
    • 自动配置:包含@EnableAutoConfiguration注解,启动自动配置机制
    • 组件扫描:包含@ComponentScan注解,自动扫描并加载引导类所在包及其子包下的组件
    • 声明配置类:包含@Configuration注解,将被标注的类声明为配置类

5.1. 统一配置管理

使用固定位置、固定命名的配置文件集中式配置管理,其中

  • 固定位置:项目的resources文件夹下,即src/main/resources
  • 固定命名:application.propertiesapplication.yml(.yaml),其中properties优先级更高

说明

  • 基本配置的都有默认值
  • 支持自定义键值对以在程序中使用
5.1.1. 配置文件

.properties格式

  • 使用=形式的键值对,即key=value
  • 使用.表示键之间的层次结构

.yml(.yaml)格式

  • 使用:形式的键值对,即key: value(冒号后有空格)
  • 使用-表示连续的集合
  • 使用缩进表示键之间的层次结构
5.1.2. 配置注入
  • 单个注入:变量添加@Value注解
  • 批量注入:类型添加@ConfigurationProperties注解,要求注解的prefix + . +属性名与配置中键相同
5.1.3. 多文件配置
  1. 创建配置文件application-{key}.properties(yml/yaml),并编写配置
  2. 激活配置文件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-locationsMapper配置的路径
mybatis.type-aliases-package自定义类型取别名的包
mybatis.configuration.log-impl日志配置
mybatis.configuration.map-underscore-to-camel-case下滑-驼峰自动映射
mybatis.configuration.auto-mapping-behavior自动映射行为

说明

  • 在启动引导类需要添加@MapperScan扫描Mapper接口所在的包

5.3. 项目部署

  1. 添加插件:spring-boot-maven-plugin插件

  2. 打包项目:执行Maven命令将项目打包成可执行的jar包

  3. 运行项目:控制台执行命令运行程序

    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接口,其中泛型参数为实体类

分页查询

  1. 导入插件:在启动类中创建Bean并添加分页拦截器PaginationInnerInterceptor
  2. 自定义接口:自定义分页查询方法,并编写SQL语句
  3. 分页查询:创建分页对象并查询结果

常用方法

方法说明
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
havingHAVING
or/and拼接,OR/AND
6.1.4. 核心配置

常用注解

注解说明
@TableName实体类与数据库表的映射
@TableId类属性与数据表主键的映射以及主键策略,其中主键策略用type属性设置,常用值为
- AUTO:ID自增,需配置数据库的主键自增长
- ASSIGN_ID(默认):雪花算法分配无重复的Long或String类型主键
@TableField类属性与数据表字段的映射以及是否存在
@TableLogic数据库记录逻辑删除字段注解
@Version数据库记录版本号字段注解

常用配置

配置说明
mapper-locationsmapper配置文件的路径,默认为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. 逻辑删除
  1. 数据表添加逻辑删除字段
  2. 实体类添加逻辑删除属性,并使用@TableLogic标识
  3. 执行删除操作
6.2.2. 乐观锁
  1. 数据表添加版本号字段
  2. 实体类添加版本号属性,并使用@Version标识
  3. 启动类获取拦截器并添加乐观锁拦截器OptimisticLockerInnerInterceptor
  4. 执行数据库操作
6.2.3. 防止全表更改
  1. 启动类获取拦截器并添加组织攻击拦截器BlockAttackInnerInterceptor

7. 扩展

7.1. 模板类

7.1.1. JDBC模板类
  • org.springframework.jdbc.core.JdbcTemplate用于简化JDBC的CURD操作
  • 使用JDBC模板类需要导入spring-jdbc依赖

使用步骤

  1. 实例化模板类对象并配置JDBC数据源
  2. 调用相关方法执行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语句
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值