1. Spring是什么?
- Spring是于2003 年兴起的一个轻量级的Java开发框架,由Rod Johnson在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。
- 它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。
- 分层架构降低了系统层次之间的耦合性,同时
- Spring的核心是控制反转(IoC控制反转)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EE的full-stack(一站式) 轻量级开源框架。
2. Spring的分层架构
Spring的分层架构为Model层+Dao层+Service层+Controller层
为什么这么划分,实际上经历了漫长的演变
MVC概述
设计模式之MVC模式
MVC模式中包含了三种策略模式:
Composite:组合模式
Strategy:策略模式
Observer :观察者模式
1. 模型是被观察者,视图和控制器是观察者,它们之间构成观察者模式;
2. 视图委托给控制器来处理用户动作,控制器是视图的策略,控制器知道如何处理用户动作,可通过改变控制器来提供不同的处理,它们之间构成策略模式;
3. 视图是GUI组件的组合,是组合模式的典型实例
从这篇2016年的文章当中,我们可以提炼出以下的几个重点:
1. MVC不是一种单独的设计模式,而是一种软件开发的架构 + 复合设计模式
2. MVC实际上包含了三种设计模式:观察者模式Observer(观察者模式) ,Composite(组合/合成模式)和Strategy(策略模式)。所以说MVC模式又称复合模式
3. 模型(Model)负责数据管理(数据的CURD),视图(View)负责数据显示,控制器(Controller)负责响应策略(模型和视图的多对多的关系处理)
4. 从MVC的形成过程来看,最初只有模型和视图两个元素;模型封装了数据并提供操作接口,视图用来表现数据和接收用户请求。模型是独立的,而视图依赖于模型:从模型获取数据进行显示;向模型发送用户请求,并根据返回结果刷新自己
5. 一个模型被多个视图依赖时(一个模型用于表现多个视图),其中一个视图对此模型发出数据的更新请求后(新增/更改/删除)刷新,其他视图也要跟着刷新;由于每个视图都可能发出修改,每个视图都要知道其他所有视图,这种关联过于复杂,不但难以维护,而且不便于增加新的视图。
6. 上述问题用观察者模式可以完美解决:Model 是观察者模式中的被观察者(Subject), View层是观察者模式中的观察者(Observer);Model的状态变化,被观察者会主动通知观察者View,从而引发View 层次的变动。从View通知每一个View变为Model通知每一个View。而Model不依赖于具体的View,最后View之间相互独立。
7. 观察者模式中,被观察者Subject负责注册(register),通知(notify),销毁(remove)观察者;观察者负责接收到通知后更新自身(update方法)
观察者模式确立的视图-模型关系是MVC的核心
8. 之所以出现了Controller控制层,是因为视图的显示和请求的处理不应该放在一起,视图的频繁修改可能会破坏比较稳定的请求处理的业务代码。将请求处理的业务逻辑分离出来,由一个控制器负责,就是为了避免这种干扰;另外Controller相当于计算机网络中的路由器或者交换机:View可以使用不同的Controller提供不同的响应方式,这是策略(Strategy)模式的应用(响应策略由Controller负责)
9. Controller在Model和View之间起到了沟通的作用,处理用户在View上的输入,并转发给Model来更改其状态值。这样 Model和View两者之间可以做到松散耦合,甚至可以彼此不知道对方,而由Controller连接起这两个部分。View用一个特定的Controller的实例来实现一个特定的响应策略。同一个View不变的前提下,只需要更换不同的Controller,可以改变View对用户输入的响应。
10. MVC还允许视图嵌套,通过使用组合(Composite)模式,一致地处理组合视图和普通视图
11. MVC 模式有许多变体。前述结构中,由Model通知View刷新,称为主动MVC;如果由Controller更新Model以后通知View,称为被动MVC结构。Web浏览器就是被动MVC结构的一个实例(ajax的promise回调异步通知,就是Controller通知浏览器进而刷新View的)
总结:模型使用观察者模式,以便观察者更新,同时保持两者之间的解耦。
控制器是视图的策略,视图可以使用不同的控制器实现,得到不同的行为。
视图使用组合模式实现用户界面,用户界面通常组合了嵌套的组件,像面板、框架和按钮。
这些模式携手合作,把MVC模式的三层解耦,这样可以保持设计干净又有弹性。
Spring的分层架构
在这张图中,model+dao+service组成了MVC模式中的Model层,用于数据的处理
3. Spring的组成
Spring由20个核心依赖组成,这20个核心依赖可以分为6个核心模块
这里对这些模块做一些简单的介绍
① 数据访问/集成
1.1 Spring-JDBC
Spring JDBC 是 Spring 框架中对 JDBC 的封装。它提供了对 JDBC 操作的简化和抽象,减少了冗长的样板代码。例如,JdbcTemplate 类简化了常见的数据库操作,如查询、更新、插入和删除,并自动管理资源。
spring-jdbc与jdbc的区别
- 抽象层次
JDBC 是 Java 标准的数据库访问 API。它提供了基本的类和接口,用于连接数据库、执行 SQL 查询以及处理结果集。使用 JDBC 时,开发者需要手动管理数据库连接、SQL 语句的执行以及异常处理。
Spring JDBC 是 Spring 框架中对 JDBC 的封装。它提供了对 JDBC 操作的简化和抽象,减少了冗长的样板代码。例如,JdbcTemplate 类简化了常见的数据库操作,如查询、更新、插入和删除,并自动管理资源。 - 资源管理
JDBC: 在 JDBC 中,开发者必须手动管理数据库连接、语句和结果集的生命周期。这包括显式地打开和关闭这些资源,否则可能导致资源泄漏。
Spring JDBC: Spring JDBC 通过 JdbcTemplate 自动管理资源。在执行操作后,Spring 自动关闭连接、语句和结果集,减少了出错的机会。 - 异常处理
JDBC: JDBC 使用标准的 SQLException,开发者需要处理 SQL 相关的异常,通常需要编写大量的异常处理代码。
Spring JDBC: Spring JDBC 将 JDBC 异常转换为 Spring 的数据访问异常层次结构(如 DataAccessException),这些异常是非受检异常,这意味着开发者不需要在每次数据库操作时都显式地捕获和处理这些异常。 - 模板方法
JDBC: 开发者需要手动编写 SQL 执行代码、结果集处理代码,并处理异常。每次执行数据库操作时都需要重复这些步骤。
Spring JDBC: Spring 提供了 JdbcTemplate 和其他模板方法,简化了常见的数据库操作。开发者只需要关注业务逻辑,其他细节(如资源管理和异常处理)由 Spring 处理。 - 更好的集成
JDBC 是一个独立的 API,不能直接与其他框架(如 Spring)进行集成。
Spring JDBC 可以轻松地与其他 Spring 模块(如事务管理、ORM 框架等)集成,提供一个统一的编程模型。
总结来说,Spring JDBC 提供了对 JDBC 的简化和增强,使数据库操作变得更加简洁和安全,减少了重复代码的编写和资源管理的复杂性。
spring-jdbc的pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
<name>Spring JDBC</name>
<description>Spring JDBC</description>
<url>https://github.com/spring-projects/spring-framework</url>
<organization>
<name>Spring IO</name>
<url>http://projects.spring.io/spring-framework</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>jhoeller</id>
<name>Juergen Hoeller</name>
<email>jhoeller@pivotal.io</email>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-projects/spring-framework</connection>
<developerConnection>scm:git:git://github.com/spring-projects/spring-framework</developerConnection>
<url>https://github.com/spring-projects/spring-framework</url>
</scm>
<issueManagement>
<system>Jira</system>
<url>https://jira.springsource.org/browse/SPR</url>
</issueManagement>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.2</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.14.1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>10.14.1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.4.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>1.1.61</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.1.61</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
其中也使用了spring-beans,spring-context,spring-core,spring-tx这些其他Spring的依赖
1.2 ORM
Spring ORM(Object-Relational Mapping)是 Spring 框架中的一个模块,旨在帮助开发者简化使用 ORM 框架(如 Hibernate、JPA、iBatis/MyBatis 等)与数据库交互的过程。Spring ORM 提供了与这些 ORM 框架的无缝集成,使得开发者能够更轻松地管理数据持久化,处理事务,并在整个 Spring 应用中实现统一的编程模型。
Spring ORM 的主要用途:
简化 ORM 框架的集成:Spring ORM 模块为多个流行的 ORM 框架(如 Hibernate、JPA、iBatis/MyBatis)提供了支持。它通过 Spring 的依赖注入、面向切面的编程(AOP)等功能,简化了 ORM 框架的配置和使用。
统一事务管理:Spring ORM 允许开发者使用 Spring 的事务管理功能来管理 ORM 操作中的事务。开发者可以声明式地管理事务,而无需依赖 ORM 框架本身的事务机制。这使得跨多个 ORM 框架或 JDBC 操作的事务处理更加简单和一致。
简化数据访问层的开发:通过与 Spring Data JPA 等模块的集成,Spring ORM 提供了数据访问层的高层抽象,减少了编写重复性代码的需求。开发者可以专注于业务逻辑,而将数据持久化的细节交由 Spring 管理。
增强的异常处理:Spring ORM 将 ORM 框架抛出的受检异常转换为 Spring 的非受检异常(如 DataAccessException),使得异常处理更加统一和简洁。
跨平台的持久化方案:Spring ORM 可以与多种 ORM 框架集成,开发者可以根据具体项目的需求选择适合的持久化方案,而不需要改变应用的其他部分。这使得 Spring ORM 非常灵活,可以在不同的项目中复用。
典型应用场景:
Hibernate 与 Spring 的集成:使用 Spring ORM 让 Hibernate 管理实体和持久化,Spring 管理事务和资源,减少了 Hibernate 配置的复杂性。
Spring Data JPA:在 Spring 应用中使用 JPA 规范进行数据持久化,Spring ORM 提供了对 JPA 的集成支持,简化了实体管理和查询操作。
跨 ORM 框架的事务管理:在使用多个 ORM 框架的应用中,Spring ORM 提供统一的事务管理解决方案,确保事务的一致性和完整性。
spring-orm的pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.0.2.RELEASE</version>
<name>Spring Object/Relational Mapping</name>
<description>Spring Object/Relational Mapping</description>
<url>https://github.com/spring-projects/spring-framework</url>
<organization>
<name>Spring IO</name>
<url>http://projects.spring.io/spring-framework</url>
</organization>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>jhoeller</id>
<name>Juergen Hoeller</name>
<email>jhoeller@pivotal.io</email>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/spring-projects/spring-framework</connection>
<developerConnection>scm:git:git://github.com/spring-projects/spring-framework</developerConnection>
<url>https://github.com/spring-projects/spring-framework</url>
</scm>
<issueManagement>
<system>Jira</system>
<url>https://jira.springsource.org/browse/SPR</url>
</issueManagement>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.7.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.12.Final</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>
javax.servlet-api,hibernate-core,spring-aop,spring-beans,spring-context,spring-core,spring-jdbc,spring-tx,spring-web
1.3 OXM
Spring OXM(Object XML Mapping)是 Spring 框架中的一个模块,专门用于在 Java 对象和 XML 数据之间进行转换(即序列化和反序列化)。Spring OXM 提供了一个抽象层,支持多个 XML 绑定框架,如 JAXB、Castor、XStream 和 XMLBeans,使得在不同的 XML 绑定实现之间进行切换更加容易。
Spring OXM 的主要用途:
对象和 XML 之间的映射:Spring OXM 允许开发者轻松地将 Java 对象序列化为 XML,或将 XML 反序列化为 Java 对象。这在需要与外部系统交换数据或配置文件时非常有用。
统一接口:通过 Marshaller 和 Unmarshaller 接口,Spring OXM 提供了一个统一的 API 来处理对象到 XML 的转换操作。开发者可以使用这些接口而不必关注底层的 XML 绑定技术。
支持多种 XML 绑定技术:Spring OXM 支持包括 JAXB、Castor、XStream、XMLBeans 等在内的多种 XML 绑定技术。这意味着你可以根据项目的需求选择合适的技术,并且可以在这些技术之间切换而不影响代码的其他部分。
简化配置:通过 Spring 的配置方式,可以轻松集成和配置各种 XML 绑定框架,从而简化 XML 数据处理的复杂性。
典型使用场景:
Web 服务开发:在开发基于 SOAP 的 Web 服务时,通常需要将 Java 对象转换为 XML(用于请求或响应),Spring OXM 可以简化这一过程。
配置文件管理:当应用程序需要读取或生成复杂的 XML 配置文件时,Spring OXM 可以将这些配置文件与 Java 对象进行映射,从而简化配置管理。
数据交换:在需要与其他系统交换数据的场景中,通过将数据封装为 XML,Spring OXM 可以帮助开发者方便地实现数据的序列化和反序列化。
主要功能和优势:
框架无关性:Spring OXM 通过统一的接口封装了不同的 XML 绑定框架,使得应用可以轻松地在不同框架之间切换。
配置简便:通过 Spring 配置,开发者可以轻松管理和配置 XML 绑定框架,避免了繁琐的配置工作。
强大的 XML 数据处理能力:Spring OXM 适用于各种需要处理 XML 数据的场景,如 Web 服务、配置文件管理、数据交换等。
pom依赖中依然可以看到spring-core,spring-beans,spring-context的身影
1.4 Transactions
Spring Transactions(Spring 事务管理)功能是由 spring-tx 包提供的。这个包包含了所有与事务管理相关的类和接口,它是 Spring 框架中处理事务的核心模块。
声明式事务管理:
提供了 @Transactional 注解,用于声明事务边界。
支持通过 XML 配置和注解配置来定义事务管理规则。
提供了事务传播行为、隔离级别、超时设置等高级配置选项。
编程式事务管理:
提供了 TransactionTemplate 类,可以通过编程的方式在代码中明确控制事务的提交和回滚。
提供了 PlatformTransactionManager 接口及其实现类(如 DataSourceTransactionManager、JpaTransactionManager 等),用于管理不同持久化技术的事务。
事务管理器:
Spring 提供了多种事务管理器实现,用于不同的持久化技术,如 JDBC、JPA、Hibernate 等。
这些事务管理器负责实际的事务控制(如开始、提交、回滚事务等)。
事务同步:
spring-tx 支持事务同步,即允许在同一个事务中协调多个资源,如数据库连接和消息队列等(非常强大,可以和消息队列的事务统一起来)。
spring transactions和mysql事务的区别
Spring 事务(Spring Transactions) 和 MySQL 事务 都是用于管理数据库操作以确保数据一致性和完整性的机制,但它们的作用范围、实现方式以及使用场景有所不同。以下是二者的主要区别和联系:
1. 作用范围
MySQL 事务:
MySQL 事务是数据库级别的事务管理机制,直接在数据库服务器上执行。
事务的管理由 MySQL 数据库引擎(如 InnoDB)负责。MySQL 事务的范围仅限于单个数据库,通常涉及一个或多个 SQL 语句。
Spring 事务:
Spring 事务是应用程序级别的事务管理机制,作用于 Java 应用程序的业务逻辑层。
Spring 事务可以管理多个资源的事务(如多个数据库、消息队列等),并将这些操作组合成一个逻辑上的整体事务。
- 管理方式
MySQL 事务:
通过 SQL 语句手动控制事务的开始、提交和回滚,如 BEGIN, COMMIT, ROLLBACK。
典型的 MySQL 事务控制示例如下:
START TRANSACTION;
INSERT INTO accounts (user_id, balance) VALUES (1, 100);
UPDATE accounts SET balance = balance - 10 WHERE user_id = 1;
COMMIT;
Spring 事务:
Spring 通过 @Transactional 注解或编程方式来管理事务。开发者可以在业务方法上标注 @Transactional,让 Spring 自动处理事务的开启、提交和回滚。
Spring 事务不仅支持数据库事务,还可以整合其他资源(如消息队列的事务)。
典型的 Spring 事务控制示例如下:
@Transactional
public void transferMoney(Long fromAccountId, Long toAccountId, BigDecimal amount) {
accountRepository.debit(fromAccountId, amount);
accountRepository.credit(toAccountId, amount);
}
总结
MySQL 事务 是数据库原生的事务管理机制,专注于数据库层面的数据一致性管理,操作简单直接。
Spring 事务 是应用程序层面的事务管理框架,提供了更高层次的抽象和灵活性,能够管理跨多个资源的事务,并简化了事务管理的复杂性,特别适合复杂的业务逻辑和多资源协调的应用场景。
1.5 JMS
spring-jms的作用和spring-jdbc差不多,都是为了简化开发。
Spring JMS 是 Spring 框架中的一个模块,用于简化与 Java Message Service (JMS) 的集成和使用。JMS 是 Java EE 中的标准 API,用于在分布式系统中实现消息的异步通信。Spring JMS 提供了一套抽象层,简化了 JMS 资源的配置和管理,使开发者能够更加专注于业务逻辑,而不用过多关注 JMS 的底层实现细节。
Spring JMS 的主要功能和优势:
-
简化 JMS 的使用:
Spring JMS 提供了模板类(如 JmsTemplate),用于简化 JMS 消息的发送和接收操作。开发者无需直接管理 JMS 连接和会话,可以通过 Spring 的模板类轻松实现消息的发送和接收。 -
消息驱动 POJO (MDP):
Spring JMS 支持将普通的 POJO 类作为消息驱动的组件,通过 Spring 的 @JmsListener 注解,可以轻松地将 POJO 方法与 JMS 消息队列或主题进行绑定,从而实现对消息的异步处理。 -
事务支持:
Spring JMS 提供了对 JMS 事务的支持,可以通过 **Spring 的事务管理机制(也就是我们上文提到的Spring Transactions)**来确保消息的可靠性和一致性。你可以使用 Spring 的 @Transactional 注解来管理 JMS 事务。
集成 Spring 的其他功能:
Spring JMS 无缝集成了 Spring 的依赖注入、AOP、事务管理等核心功能,使得开发 JMS 应用更加便捷和灵活。
多种 JMS 提供者支持:
Spring JMS 可以与各种 JMS 提供者(如 ActiveMQ、RabbitMQ 等)集成,并通过配置来切换不同的 JMS 提供者,而无需修改业务逻辑代码。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
1.6 Messaging
Spring Messaging 是 Spring 框架中的一个模块,旨在简化消息传递和处理。它为构建基于消息的应用程序提供了抽象和支持,并与 Spring 的其他模块紧密集成。Spring Messaging 是一个广义的模块,它不仅涵盖了 JMS(Java Message Service),还支持其他消息传递机制,如 STOMP(Simple Text Oriented Messaging Protocol)、WebSocket、AMQP 等。
Spring Messaging 的主要功能和组件
1. 消息抽象(Message Abstraction):
Spring Messaging 定义了一个通用的消息抽象,包含 Message、MessageHeaders 和 MessageHandler 等接口。这些接口为消息的创建、处理和传递提供了标准化的 API,可以在不同的消息传递机制之间使用。
Message<String> message = MessageBuilder.withPayload("Hello, World!")
.setHeader("key", "value")
.build();
Message:代表一个消息对象,包含消息体(payload)和消息头(headers)。
MessageHeaders:封装消息的元数据。
MessageHandler:处理消息的通用接口。
2. 消息处理器(Message Handler):
Spring Messaging 提供了消息处理器的抽象,如 MessageHandler 接口,用于定义消息的处理逻辑。开发者可以实现这个接口,来处理从各种通道(如队列、主题、WebSocket 等)接收到的消息。
public class MyMessageHandler implements MessageHandler {
@Override
public void handleMessage(Message<?> message) {
System.out.println("Received message: " + message.getPayload());
}
}
3. 消息通道(Message Channel):
消息通道是 Spring Messaging 中的核心概念,代表消息传递的路径。MessageChannel 接口提供了一个抽象,用于在应用程序的各个部分之间传递消息。
SubscribableChannel:可以订阅一个或多个 MessageHandler,每当有消息通过时,都会通知这些处理器。
PollableChannel:允许通过轮询的方式获取消息,常用于队列场景。
4. 注解驱动的消息监听:
Spring Messaging 支持使用注解来简化消息处理方法的声明。@MessageMapping 和 @SendTo 等注解可用于定义消息的处理逻辑和返回目标。
@MessageMapping("/chat")
@SendTo("/topic/messages")
public String processMessageFromClient(String message) {
return "Received: " + message;
}
5. 集成 WebSocket 和 STOMP:
Spring Messaging 提供了对 WebSocket 和 STOMP 协议的支持,能够构建实时的双向通信应用程序。通过 @EnableWebSocketMessageBroker 注解可以启用消息代理,并配置消息传递路径。
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();
}
}
6. 与 AMQP 的集成:
Spring Messaging 还可以与 AMQP(如 RabbitMQ)集成,提供对高级消息队列协议的支持。
Spring Messaging 的典型应用场景
1. WebSocket 实时通信:
Spring Messaging 非常适合构建基于 WebSocket 的实时通信应用,比如在线聊天、股票行情推送、协作编辑工具等。通过结合 STOMP 协议,可以轻松地实现客户端与服务器之间的双向通信。
2. 消息驱动的微服务架构:
在微服务架构中,各个服务之间常常需要通过消息来进行异步通信。Spring Messaging 提供的抽象层使得这种通信变得更加容易,支持多种消息传递协议和中间件,如 JMS、AMQP 等。
3. 事件驱动的架构:
Spring Messaging 支持事件驱动的架构,通过消息通道在不同组件之间传递事件,并由相应的消息处理器进行处理。这种架构在复杂的业务逻辑中非常有用,能够提高系统的解耦性和可扩展性。
总结
Spring Messaging 是 Spring 框架中处理消息传递的核心模块,为开发者提供了简化的 API 和丰富的功能支持。无论是基于 JMS 的传统消息队列、实时的 WebSocket 通信,还是 AMQP 的高级消息传递协议,Spring Messaging 都能为开发者提供一致的开发体验,并与 Spring 的其他组件无缝集成。
这个模块的主要优势在于它的抽象性和灵活性,使得开发者可以专注于业务逻辑,而不用过多关注底层消息机制的实现细节。在构建复杂的分布式系统和微服务架构时,Spring Messaging 提供了强大的支持。
spring-jms和spring-messaging的区别
Spring Messaging 是一个更高层次的消息传递抽象,适用于多种消息传递技术,提供统一的消息处理 API。
Spring JMS 是基于 Spring Messaging 的专门用于 JMS 集成的模块,简化了与 JMS 相关的操作和配置。
Spring Messaging:
Spring Messaging 是一个更广泛的抽象层,专注于消息传递的抽象和通用机制。它为处理消息提供了统一的 API,适用于各种消息传递协议,如 JMS、AMQP、STOMP、WebSocket 等。
Spring Messaging 主要定义了消息的核心概念,如 Message、MessageHeaders、MessageHandler、MessageChannel 等,这些概念可以在不同的消息传递技术中使用。
Spring JMS:
Spring JMS 是 Spring 框架中专门用于与 JMS(Java Message Service)进行集成的模块。它构建在 Spring Messaging 之上,专门为 JMS 提供了支持。
Spring JMS 提供了 JmsTemplate、MessageListenerContainer、DefaultMessageListenerContainer 等工具来简化与 JMS 相关的操作,如发送和接收消息、管理消息监听器等。
依赖关系:
Spring JMS 是基于 Spring Messaging 构建的(这一点在pom文件中也能体现出来)。
Spring Messaging 提供了基础的消息抽象,而 Spring JMS 则在此基础上提供了具体的 JMS 实现。因此,Spring JMS 使用了 Spring Messaging 中定义的消息概念和接口。
一致的编程模型:
由于 Spring JMS 构建在 Spring Messaging 的抽象之上,开发者可以使用一致的编程模型来处理不同的消息传递技术。例如,Spring Messaging 定义的 Message 和 MessageHandler 概念在 Spring JMS 中也适用,这意味着开发者可以通过统一的接口处理 JMS 消息。
集成能力:
如果你的应用需要处理多种类型的消息传递技术(如 JMS 和 AMQP),可以通过 Spring Messaging 的统一抽象层来实现,利用不同的模块(如 Spring JMS 和 Spring AMQP)来处理具体的消息传递细节。这种方式极大地提高了代码的可重用性和灵活性。