SpringBoot服务整合
本小记学习目标
-
整合数据源
-
整合ORM开发框架
-
整合消息服务组件
-
整合Redis数据库
SpringBoot开发框架可以极大地简化第三方框架及第三方服务之间的整合处理。
一、SpringBoot整合数据源
实际的项目开发中,一般来说都会使用到数据库,为了提高数据库的操作性能,开发的过程中通常会使用数据库的连接池进行处理,在项目中则使用DataSrouce进行数据源的连接。
常用的数据库连接池有两类:C3P0、Druid
1.1 整合C3P0
C3P0是一个开源的JDBC连接池,它实现了数据源与JNDI绑定,支持JDBC3规范和JDBC2的标准扩展,在Hibernate、Spring项目中经常使用。
1.在父项目中添加C3P0的依赖及mysql依赖,修改它的pom.xml文件
在<properties></properties>中添加相关的版本信息
<!-- C3P0的版本属性 -->
<
c3p0.version
>0.9.5.2
</
c3p0.version
>
<!--
mysql
连接的版本属性 -->
<
mysql-connector-java.version
>5.1.21
</
mysql-connector-java.version
>
在<dependencies></dependencies>中添加对应的依赖
<!--
mysql
的依赖 -->
<
dependency
>
<
groupId
>
mysql
</
groupId
>
<
artifactId
>
mysql-connector-java
</
artifactId
>
<
version
>${
mysql-connector-java.version}
</
version
>
</
dependency
>
<!-- C3P0的依赖 -->
<
dependency
>
<
groupId
>com.mchange
</
groupId
>
<
artifactId
>c3p0
</
artifactId
>
<
version
>${c3p0.version}
</
version
>
</
dependency
>
2.在父工程下新增一个Maven的new module,xiaoxieboot-integration
3.修改新增项目的pom.xml文件
<
project
xmlns=
"
http://maven.apache.org/POM/4.0.0
"
xmlns:xsi=
"
http://www.w3.org/2001/XMLSchema-instance
"
xsi:schemaLocation=
"
http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd
"
>
<
modelVersion
>4.0.0
</
modelVersion
>
<
parent
>
<
groupId
>com.xiaoxie
</
groupId
>
<
artifactId
>
xiaoxieboot
</
artifactId
>
<
version
>0.0.1-SNAPSHOT
</
version
>
</
parent
>
<
artifactId
>
xiaoxieboot-integration
</
artifactId
>
<
packaging
>war
</
packaging
>
<
dependencies
>
<
dependency
>
<
groupId
>
junit
</
groupId
>
<
artifactId
>
junit
</
artifactId
>
<
scope
>test
</
scope
>
</
dependency
>
<
dependency
>
<
groupId
>org.springframework.boot
</
groupId
>
<
artifactId
>spring-boot-starter-test
</
artifactId
>
<
scope
>test
</
scope
>
</
dependency
>
<
dependency
>
<
groupId
>org.springframework.boot
</
groupId
>
<
artifactId
>spring-boot-starter-web
</
artifactId
>
</
dependency
>
<
dependency
>
<
groupId
>org.springframework.boot
</
groupId
>
<
artifactId
>spring-boot-
devtools
</
artifactId
>
</
dependency
>
<
dependency
>
<
groupId
>com.mchange
</
groupId
>
<
artifactId
>c3p0
</
artifactId
>
</
dependency
>
<
dependency
>
<
groupId
>
mysql
</
groupId
>
<
artifactId
>
mysql-connector-java
</
artifactId
>
</
dependency
>
</
dependencies
>
<
build
>
<
plugins
>
<
plugin
>
<
groupId
>org.apache.maven.plugins
</
groupId
>
<
artifactId
>
maven-war-
plugin
</
artifactId
>
<
configuration
>
<
warName
>xiaoxieboot-web
</
warName
>
</
configuration
>
</
plugin
>
</
plugins
>
</
build
>
</
project
>
4.在src/main/resource下新增配置文件:application.yml(新增c3p0的配置信息)
c3p0
:
#定义c3p0配置
jdbcUrl: jdbc:
mysql://localhost:3306/test
#数据库连接地址
user: root
#数据库连接用户名
password: root
#数据库连接密码
driverClass: org.gjt.mm.mysql.Driver
#数据库的驱动
minPoolSize: 1
maxPoolSize: 1
maxIdelTime: 3000
initalPoolSize: 1
5.新增关于C3P0的连接池的配置类,com.xiaoxie.config.C3P0DataSourceConfig
package com.xiaoxie.config;
import javax.sql.DataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.Configuration;
@
Configuration
public
class C3P0DataSourceConfig {
@Bean(name=
"dataSource")
//定义一个Bean datasrouce
@
ConfigurationProperties(prefix=
"c3p0")
//定义资源导入前导标记
public DataSource dataSource() {
return DataSourceBuilder.
create().type(ComboPooledDataSource.
class).build();
}
}
6.新增SpringBoot的启动类com.xiaoxie.SpringBootStartApplication
package com.xiaoxie;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public
class SpringBootStartApplication
extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder
builder) {
return
builder.sources(SpringBootStartApplication.
class);
}
public
static
void main(String[]
args) {
SpringApplication.
run(SpringBootStartApplication.
class,
args);
}
}
7.在src/test/java中新增测试类:com.xiaoxie.test.DataSourceTest
package com.xiaoxie.test;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import
org.springframework.test.context.web.WebAppConfiguration;
import com.xiaoxie.SpringBootStartApplication;
@SpringBootTest(classes=SpringBootStartApplication.
class)
@RunWith(SpringJUnit4ClassRunner.
class)
@
WebAppConfiguration
public
class DataSourceTest {
@Autowired
private DataSource
dataSource;
@Test
public
void testConnection()
throws Exception {
System.
out.println(
dataSource.getConnection());
}
}
运行测试类,正常情况下测试类执行成功,且会在控制台中打印出dataSource中获取到的mysql连接
1.2 整合Druid
Druid,它是阿里推出的数据库连接池组件,也是一个用于大数据实时查询和分析的高容错、高性能开源分布式系统,可以高效处理大规模的数据并实现快速的查询分析。
1.在父项目中添加Durid的依赖依赖,修改它的pom.xml文件
在<properties></properties>中添加相关的版本信息
<!--
Druid
的版本 -->
<
druid-version
>1.1.6
</
druid-version
>
在<dependencies></dependencies>中新增相对durid的依赖
<!--
Druid
的依赖 -->
<
dependency
>
<
groupId
>com.alibaba
</
groupId
>
<
artifactId
>
druid
</
artifactId
>
<
version
>${
druid-version}
</
version
>
</
dependency
>
2.在新增的maven moudle工程中新装置druid的依赖,修改它的pom.xml文件
<
dependency
>
<
groupId
>com.alibaba
</
groupId
>
<
artifactId
>
druid
</
artifactId
>
</
dependency
>
3.在application.yml配置文件中新增durid的配置信息
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
#配置数据源的操作类型
driver-class-name: org.gjt.mm.mysql.Driver
#数据库的驱动
url: jdbc:
mysql://localhost:3306/test
#数据库连接地址
username: root
#数据库连接用户名
password: root
#数据库连接密码
dbcp2:
min-idle: 1
#连接池最小维持连接数
initial-size: 1
#初始化提供的连接数
max-total: 1
#最大连接数
max-wait-millis: 3000
#超时最大等待时间
4.新增durid的配置类:com.xiaoxie.config.DuridDataSourceConfig
package com.xiaoxie.config;
import javax.sql.DataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.pool.DruidDataSource;
@Configuration
public
class DuridDataSourceConfig {
@Bean(name=
"dataSrouce_durid")
@
ConfigurationProperties(prefix=
"spring.datasource")
public DataSource druid() {
return
new DruidDataSource();
}
}
5.新增测试类:com.xiaoxie.test.DataSourceByDuridTest
package com.xiaoxie.test;
import javax.sql.DataSource;
import
org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.xiaoxie.SpringBootStartApplication;
@SpringBootTest(classes=SpringBootStartApplication.
class)
@RunWith(SpringJUnit4ClassRunner.
class)
@WebAppConfiguration
public
class DataSrouceByDuridTest {
@Autowired
private DataSource
dataSrouce_durid;
@
Test
public
void testConnection()
throws Exception {
System.
out.println(
dataSrouce_durid.getConnection());
}
}
运行测试类,正常情况下测试类执行成功,且会在控制台中打印出dataSource中获取到的mysql连接
二、SpringBoot整合ORM开发框架
使用Spring整合ORM组件的过程中,为了达到简化的目的,往往都会进行大量的配置。利用SpringBoot可以进一步实现配置的简化。
2.1 SpringBoot整合MyBatis
MyBatis是一款常用且配置简单的ORM开发框架,它与Spring结合后,可以利用Spring的特征实现DAO接口的自动配置。SpringBoot中又对MyBatis框架的整合进行了进一步的简化,在项目中需要引入mybatis-spring-boot-starter依赖支持库。
注意:如果SpringBoot要与ORM开发框架整合前提需要数据库连接池的支持
把c3p0相关的连接池配置去掉,我们使用Durid来做连接池
1.在测试库test,新增数据库表 dept
CREATE TABLE `dept` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`deptno` varchar(50) NOT NULL DEFAULT '' COMMENT '部门编号',
`deptname` varchar(50) NOT NULL DEFAULT '' COMMENT '部门名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
新增测试数据
INSERT INTO `test`.`dept` (`id`, `deptno`, `deptname`) VALUES ('1', '001', '人事部');
INSERT INTO `test`.`dept` (`id`, `deptno`, `deptname`) VALUES ('2', '002', '销售部');
INSERT INTO `test`.`dept` (`id`, `deptno`, `deptname`) VALUES ('3', '003', '技术部');
INSERT INTO `test`.`dept` (`id`, `deptno`, `deptname`) VALUES ('4', '004', '财务部');
2.新增一个数据库实体VO对象:com.xiaoxie.vo.Dept
package com.xiaoxie.vo;
import java.io.Serializable;
@SuppressWarnings(
"serial")
public
class Dept
implements Serializable{
private Long
id;
private String
deptno;
private String
deptname;
public Long getId() {
return
id;
}
public
void setId(Long
id) {
this.
id =
id;
}
public String getDeptno() {
return
deptno;
}
public
void setDeptno(String
deptno) {
this.
deptno =
deptno;
}
public String getDeptname() {
return
deptname;
}
public
void setDeptname(String
deptname) {
this.
deptname =
deptname;
}
}
3.集成mybatis,并完成mybatis的配置
在pom.xml中新增mybatis相关的依赖
<
dependency
>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</
dependency
>
在src/main/resources下新增mybatis文件夹并在其下新增mybatis.cfg.xml配置文件
<?
xml
version=
"1.0"
encoding=
"UTF-8"
?>
<!
DOCTYPE
configuration
<
configuration
>
<
settings
>
<!-- 开启二级缓存 -->
<
setting
name=
"cacheEnabled"
value=
"true"
/>
</
settings
>
</
configuration
>
在application.yml配置中添加mybatis相关配置
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml
#mybatis的配置文件位置
type-aliases-package: com.xiaoxie.vo
#定义所有操作类的别名所在的包
4.新增一个DAO接口:com.xiaoxie.dao.IDeptDAO
package com.xiaoxie.dao;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import com.xiaoxie.vo.Dept;
@Mapper
public
interface IDeptDAO {
@Select(
"SELECT id,deptno,deptname FROM dept")
public List<Dept> findAll();
//查找所有部门信息
}
5.新增一个service接口:com.xiaoxie.service.IDeptService
package com.xiaoxie.service;
import java.util.List;
import com.xiaoxie.vo.Dept;
public
interface IDeptService {
public List<Dept>
list();
}
6.新增一个service的实现类:com.xiaoxie.service.impl.DeptServiceImpl
package com.xiaoxie.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xiaoxie.dao.IDeptDAO;
import com.xiaoxie.service.IDeptService;
import com.xiaoxie.vo.Dept;
@Service
public
class DeptServiceImpl
implements IDeptService {
//注入
dao
@Autowired
private IDeptDAO
deptDAO;
@Override
public List<Dept> list() {
return
deptDAO.
findAll();
}
}
7.在src/test/java下新增测试类:com.xiaoxe.test.DeptService
package com.xiaoxie.test;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.xiaoxie.SpringBootStartApplication;
import com.xiaoxie.service.IDeptService;
import com.xiaoxie.vo.Dept;
@SpringBootTest(classes=SpringBootStartApplication.
class)
@RunWith(SpringJUnit4ClassRunner.
class)
@WebAppConfiguration
public
class DeptServiceTest {
//注入service
@Autowired
private IDeptService
deptService;
@Test
public
void testList() {
List<Dept>
depts =
deptService.list();
for (Dept
dept :
depts) {
System.
out.println(
"ID:" +
dept.getId() +
" 部门编号:" +
dept.getDeptno() +
" 部门名称:" +
dept.getDeptname());
}
}
}
运行测试类,控制台打印的结果如下:
ID:1 部门编号:001 部门名称:人事部
ID:2 部门编号:002 部门名称:销售部
ID:3 部门编号:003 部门名称:技术部
ID:4 部门编号:004 部门名称:财务部
2.2 SpringBoot整合JPA开发框架
JPA是官方推出的JAVA持久层操作标准(现在主要使用Hibernate来实现),使用Spring-Data技术和JpaRepository接口技术,也可以达到简化数据层的目的,在SpringBoot中使用SpringDataJPA需要spring-boot-starter-data-jpa依赖库的支持。
在pom.xml中新增JPA相关的依赖
<!-- JPA相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
</dependency>
修改Dept类为如下
package com.xiaoxie.vo;
import javax.persistence.*;
import java.io.Serializable;
@SuppressWarnings("serial")
@Cacheable(true)
@Entity
public class Dept implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String deptno;
private String deptname;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDeptno() {
return deptno;
}
public void setDeptno(String deptno) {
this.deptno = deptno;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
}
新增一个DAO的接口:com.xiaoxie.dao.Dept_01DAO
package com.xiaoxie.dao;
import com.xiaoxie.vo.Dept;
import org.springframework.data.jpa.repository.JpaRepository;
public interface IDeptDAO_01 extends JpaRepository<Dept,Long> {
//这里继承了JpaRepository所以已经包含了基础的CRUD
}
注意:这里的接口继承了JpaRepository接口,在这个接口中已经包含了基本的CRUD方法,所在在我们新增的这个类中无需再做接口方法的定义
新增一个service的接口和实现类
接口:com.xiaoxie.service.IDeptService_01
package com.xiaoxie.service;
import com.xiaoxie.vo.Dept;
import java.util.List;
public interface IDeptService_01 {
public List<Dept> list();
}
service的实现类:com.xiaoxie.service.impl.DeptService_01impl
package com.xiaoxie.service.impl;
import com.xiaoxie.dao.IDeptDAO_01;
import com.xiaoxie.service.IDeptService_01;
import com.xiaoxie.vo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DeptService_01impl implements IDeptService_01 {
@Autowired
private IDeptDAO_01 deptDAO;
@Override
public List<Dept> list() {
return deptDAO.findAll();
}
}
修改程序启动主类,增加对Repository扫描配置,在启动主类上新增一个注解
@EnableJpaRepositories
(basePackages =
"com.xiaoxie.dao"
)
新增一个测试类:com.xiaoxie.test.DeptService_01Test
package com.xiaoxie.test;
import com.xiaoxie.SpringBootStartApplication;
import com.xiaoxie.service.IDeptService_01;
import com.xiaoxie.vo.Dept;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import java.util.List;
@SpringBootTest(classes = SpringBootStartApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class DeptService_01Test {
@Autowired
private IDeptService_01 deptService01;
@Test
public void testList(){
List<Dept> depts = deptService01.list();
for(Dept dept:depts){
System.out.println("部门编号:" + dept.getDeptno() + " 部门名称:" + dept.getDeptname());
}
}
}
运行测试方法testList后,程序在控制台输出结果如下:
部门编号:001 部门名称:人事部
部门编号:002 部门名称:销售部
部门编号:003 部门名称:技术部
部门编号:004 部门名称:财务部
2.3 事务处理
SpringBoot中可以使用PlatformTransactionManager接口来实现事务的统一控制,进行控制的时候也可以也可以使用注解或AOP切面配置形式来完成。
在业务层的方法启用事务控制,在业务层的接口对应的方法上加上类似如下的注解
@Transactional
(propagation = Propagation.
REQUIRED
,readOnly =
true
)
在实际的开发过程中会存在多个业务层接口方法,如果每一个添加注解则比较麻烦,可以定义一个业务的配置类
package com.xiaoxie.config;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import java.util.HashMap;
import java.util.Map;
@Configuration //定义配置Bean
@Aspect //使用AOP切面处理
public class TransactionConfig {
//定义事务超时时间(秒)
private static final int TRANSACTION_TIMEOUT = 5;
//定义切面表达式
private static final String AOP_EXPRESSION="execution(* com.xiaoxie.service.*.*(..))";
@Autowired //自动注入事务管理对象
private PlatformTransactionManager platformTransactionManager;
@Bean("txAdvice")
public TransactionInterceptor transactionConfig(){
//定义只读事务控制
RuleBasedTransactionAttribute readOnly = new RuleBasedTransactionAttribute();
readOnly.setReadOnly(true);
readOnly.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
//定义更新事务
RuleBasedTransactionAttribute required = new RuleBasedTransactionAttribute();
required.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
required.setTimeout(TRANSACTION_TIMEOUT);
//定义业务切面
Map<String,TransactionAttribute> transactionAttributeMap = new HashMap<>();
transactionAttributeMap.put("add",required);
transactionAttributeMap.put(
"edit"
,required);
transactionAttributeMap.put("delete",required);
transactionAttributeMap.put("get",readOnly);
transactionAttributeMap.put("list",readOnly);
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
source.setNameMap(transactionAttributeMap);
TransactionInterceptor transactionInterceptor = new TransactionInterceptor(platformTransactionManager,source);
return transactionInterceptor;
}
@Bean
public Advisor transactionAdviceAdvisor(){
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(AOP_EXPRESSION);
return new DefaultPointcutAdvisor(pointcut,transactionConfig());
}
}
三、SpringBoot整合消息服务组件
消息服务组件常用来做系统整合与异步服务通信,它的基本结构包含生产者、消费者及消息服务的中间件。

常用消息组件主要有两类:JMS标准(ActiveMQ)、AMQP标准(RabbitMQ、Kafka)
3.1 SpringBoot整合ActiveMQ消息组件
ActiveMQ:它是Apache提供的开源消息组件,基于JMS标准实现的。
在Windows环境下安装ActiveMQ
下载后解压文件,有两个重要的配置文件在conf的目录下:
jetty-relm.properties:在这个文件中保存着相关的用户名和密码
jetty.xml:在这个文件中可以看到相应的端口号
activemq.xml:在name="openwire"的配置处可以看到对应的服务器地址端口配置
启动ActiveMQ:
1、在bin目录下找到win64目录,运行activemq.bat文件
2、在浏览器中访问:
http://localhost:8161/admin
注意:8161是它的默认端口
3、输入对应的用户名、密码则进入ActiveMQ的界面

在程序pom.xml中新增对ActiveMQ的依赖
<!--ActiveMQ依赖-->
<
dependency
>
<
groupId
>org.springframework.boot</
groupId
>
<
artifactId
>spring-boot-starter-activemq</
artifactId
>
</
dependency
>
在application.yml配置文件中添加ActiveMQ配置信息
Spring:
jms:
pub-sub-domain: false #确认消息类型,true表示topic消息,false表示Queue消息
activemq:
user: xiaoxie #连接用户名
password: xiaoxie #连接密码
broker-url: tcp://localhost:61616
新增一个消息消费监听类:com.xiaoxie.service.consumer.MessageConsumer
package com.xiaoxie.service.consumer;
import org.springframework.jms.annotation.JmsListener;
import
org.springframework.stereotype.
Service
;
@Service
public class MessageConsumer {
@JmsListener
(destination =
"xiaoxie.msg.queue"
)
public void
receiveMessage(String msg){
System.
out
.println(
"
【接收消息】:
"
+ msg);
}
}
在这里定义了消息队例:xiaoxie.msg.queue
定义消息生产者业务接口:com.xiaoxie.service.producer.IMessageProducer
package
com.xiaoxie.service.producer;
public interface IMessageProducer {
public void send(String msg); //消息发送
}
定义消息的业务实现类:com.xiaoxie.service.impl.MessageProducerImpl
package
com.xiaoxie.service.impl;
import com.xiaoxie.service.producer.IMessageProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import
org.springframework.stereotype.
Service
;
import javax.jms.Destination;
import javax.jms.Queue;
@Service
public class MessageProducerImpl implements IMessageProducer {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private Queue queue;
@Override
public void send(String msg) {
jmsMessagingTemplate.convertAndSend((Destination) queue,msg);
}
}
定义JMS消息发送配置类,这个类用来配置队列信息:com.xiaoxie.config.ActiveMQConfig
package
com.xiaoxie.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import
org.springframework.jms.annotation.
EnableJms
;
import javax.jms.Queue;
@Configuration
@EnableJms
public class ActiveMQConfig {
@Bean
public Queue queue(){
return new ActiveMQQueue("xiaoxie.msg.queue");
}
}
新增测试类进行测试:com.xiaoxie.test.ActiveMQMessageTest
package
com.xiaoxie.test;
import com.xiaoxie.SpringBootStartApplication;
import com.xiaoxie.service.producer.IMessageProducer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@SpringBootTest(classes = SpringBootStartApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class ActiveMQMessageTest {
@Autowired
private
IMessageProducer
messageProducer
;
@Test
public void testMessage(){
messageProducer.send("你好 ActiveMq!");
}
}
运行测试类,在控制台可以看到输出信息:
【接收消息】:你好 ActiveMq!
3.2 SpringBoot整合RabbitMQ消息组件
RabbitMQ组件是在AMQP基础上构建出的新一代企业级消息系统,这个组件由Pivotal公司提供。使用ErLang语言开发。
首先安装ErLang,选择23.0版本
安装完成后,添加相应的环境变量
变量名:ERLANG_HOME
变量值:C:\Program Files\erl-23.0(这个与安装的位置有关系,浏览到安装的目录即可)
在path环境变量中新增一项:%ERLANG_HOME%\bin
完成上面操作后,打开cmd,运行erl如果成功则表示安装成功!如下所示表示ErLang安装成功
其次要安装 rabbitMQ ,选择版本为3.8.9
安装守铖后,添加相应的环境变量
变量名称:RABBITMQ_SERVER
变量值:C:\Program Files\RabbitMQ Server\rabbitmq_server-3.8.9(这个与安装的位置有关,浏览到安装的目录即可)
在path环境变量中新增一项:%RABBITMQ_SERVER%\sbin
在RabbitMQ默认安装后没有启用插件,执行下面的命令,启用RabbitMQ的插件管理
rabbitmq
-plugins
.bat enable rabbitmq_management 这个时候我们在系统服务中会看到有一个RabbitMQ的服务,我们需要重启这个服务
访问如下地址:
http://localhost:15672/
用户名和密码可以使用guest(这个是安装后默认的)
可以在登录成功后进入Admin菜单,新增新的用户
在程序中导入相应的依赖
<!-- RabbitMQ依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
在springboot的配置文件中新增rabbitmq的相关配置
Spring:
rabbitmq:
addresses: 127.0.0.1
username: xiaoxie
password:
xiaoxie
virtual-host: /
新增消息生产者配置类:com.xiaoxie.config.ProducerConfig
package com.xiaoxie.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 消息生产配置
*/
@Configuration
public class ProducerConfig {
public static final String EXCHANGE = "xiaoxie.exchange"; //交换空间名称
public static final String ROUTINGKEY = "xiaoxie.routingkey"; //路由key
public static final String QUEUE_NAME = "xiaoxie.queue"; //队列名称
@Bean
public Binding bindingExchangeQueue(DirectExchange exchange, Queue queue){
return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY);
}
//直连的模式连接
@Bean
public DirectExchange getDirectExchange(){
return new DirectExchange(EXCHANGE,true,true);
}
@Bean
public Queue queue(){
return new Queue(QUEUE_NAME); //队列信息
}
}
新增消费者配置类:com.xaioxie.config.ConsumerConfig
package com.xiaoxie.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConsumerConfig {
public static final String EXCHANGE = "xiaoxie.exchange"; //交换空间名称
public static final String ROUTINGKEY = "xiaoxie.routingkey"; //路由key
public static final String QUEUE_NAME = "xiaoxie.queue"; //队列名称
@Bean
public Queue queue(){
return new Queue(QUEUE_NAME);
}
@Bean
public DirectExchange getDirectExchange(){
return new DirectExchange(EXCHANGE,true,true);
}
@Bean
public Binding bindingExchangeQueue(DirectExchange exchange,Queue queue){
return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY);
}
}
新增业务接口用来发送消息:com.xiaoxie.service.producer.IMessageProducerByRabbitmq
package com.xiaoxie.service.producer;
public interface
IMessageProducerByRabbitmq {
public void send(String msg);
}
新增业务接口的实现类:com.xiaoxie.service.impl.MessageProducerByRabbitmqImpl
package com.xiaoxie.service.impl;
import com.xiaoxie.config.ProducerConfig;
import com.xiaoxie.service.producer.IMessageProducerByRabbitmq;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class MessageProducerByRabbitmqImpl implements IMessageProducerByRabbitmq {
@Resource
private RabbitTemplate rabbitTemplate;
@Override
public void send(String msg) {
rabbitTemplate.convertAndSend(ProducerConfig.EXCHANGE,ProducerConfig.ROUTINGKEY,msg);
}
}
新增消息监听处理类:com.xiaoxie.service.consumer.
MessageConsumerByRabbitmq
package com.xiaoxie.service.consumer;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@Service
public class MessageConsumerByRabbitmq {
@RabbitListener(queues = "xiaoxie.queue")
public void receviceMessage(String msg){
System.out.println("***【RabbitMQ,接收消息】*** " + msg);
}
}
新增测试类:com.xiaoxie.test.RabbitMQMessageTest
package com.xiaoxie.test;
import com.xiaoxie.SpringBootStartApplication;
import com.xiaoxie.service.producer.IMessageProducerByRabbitmq;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@SpringBootTest(classes = SpringBootStartApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class RabbitMQMessageTest {
@Autowired
private IMessageProducerByRabbitmq messageProducerByRabbitmq;
@Test
public void testMessage(){
messageProducerByRabbitmq.send("RabbitMQ,你好!");
}
}
运行测试类,程序在控制台会打印出来信息如下:
***【RabbitMQ,接收消息】*** RabbitMQ,你好!
四、SpringBoot整合Redis数据库
Redis是用于实现缓存机制的NoSQL数据库,它通过key-value存储,支持高并发访问。
4.1 SpringBoot整合RedisTemplate操作Redis
RedisTemplate是SpringData提供的Redis操作模板,主要以Jedis驱动程序为实现基础,进行数据操作封装,可以直接调用Redis中的各种数据处理命令进行数据库操作。
下载Redis,当前使用版本 redis-2.8.9
解压后进入到目录,运行命令:redis-server redis.window.conf
运行上面的命令后则Redis服务端启动
打开另一个cmd窗口,进入到解压目录,运行命令:redis-cli
这个时候客户端会连接到服务

在启动redis的时候出现报“
VirtualAllocEx failed.: unknown error”这个错误,表示启动时分配内存不够,可以使用如下命令启动:.\redis-server.exe .\redis.windows.conf
如果开启了需要密码认证则启动时命令:redis-cli -p 6379 -a xiaoxie
其中xiaoxie则为配置的认证密码,它配置在redis.windows.conf文件中,找到#requirepass的位置,去掉注释并在后面加上需要的认证密码如:xiaoxie
在程序中新增redis相关的依赖
<!-- Redis的引用依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在配置文件application.yml中新增redis的配置
spring:
redis:
host:
127.0.0.1
port: 6379
password: xiaoxie
timeout: 1000
database: 0
pool:
max-active: 10
max-idle: 8
min-idle: 2
max-wait: 100
新增测试类使用RedisTemplate模板进行数据处理:com.xiaoxie.test.TestRedisTemplate
package com.xiaoxie.test;
import com.xiaoxie.SpringBootStartApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@SpringBootTest(classes = SpringBootStartApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestRedisTemplate {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Test
public void testSet(){
redisTemplate.opsForValue().set("xiaoxie","***【Value值】***");
System.out.println(redisTemplate.opsForValue().get("xiaoxie"));
}
}
Redis对象序列化操作
RedisTemplate可以操作Redis数据库且可以结合对象序列化操作,实现对象的保存
在程序中定义Redis序列化配置类,实现RedisSerializer接口:com.xiaoxie.util.redis.RedisObjectSerializer
package com.xiaoxie.util.redis;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
public class
RedisObjectSerializer
implements
RedisSerializer<Object> {
//对象与字节数组的转换,准备两个转换器
private Converter<Object,byte[]> serializingConverter = new SerializingConverter();
private Converter<byte[],Object> deserializingConverter = new DeserializingConverter();
//定义一个空数组
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
@Override
public byte[] serialize(Object o) throws SerializationException {
if(o == null){
return EMPTY_BYTE_ARRAY;
}
return serializingConverter.convert(o);
}
@Override
public Object deserialize(byte[] bytes) throws SerializationException {
if(bytes == null || bytes.length == 0){
return null;
}
return deserializingConverter.convert(bytes);
}
}
新增一个RedisTemplate的配置类:com.xiaoxie.config.RedisConfig
package com.xiaoxie.config;
import com.xiaoxie.util.redis.RedisObjectSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> getRedisTemplate(RedisConnectionFactory factory){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.setKeySerializer(new StringRedisSerializer()); //Key的序列化类型
redisTemplate.setValueSerializer(new RedisObjectSerializer()); //value的序列化类型
return redisTemplate;
}
}
新增一个待序列化的VO类:com.xiaoxie.vo.Member
package com.xiaoxie.vo;
import java.io.Serializable;
public class Member implements Serializable {
private String no;
private String name;
private Integer age;
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
修改测试类(com.xiaoxie.test.TestRedisTemplate)为如下:
package com.xiaoxie.test;
import com.xiaoxie.SpringBootStartApplication;
import com.xiaoxie.vo.Member;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@SpringBootTest(classes = SpringBootStartApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestRedisTemplate {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Test
public void testSet(){
redisTemplate.opsForValue().set("xiaoxie","***【Value值】***");
System.out.println(redisTemplate.opsForValue().get("xiaoxie"));
}
@Test
public void testSerialSet(){
//VO对象
Member vo = new Member();
vo.setNo("NO.001");
vo.setName("张三");
vo.setAge(20);
redisTemplate.opsForValue().set("NO.001",vo);
}
@Test
public void testSerialGet(){
System.out.println(redisTemplate.opsForValue().get("NO.001"));
}
}
运行测试类中的测试方法:testSerialSet()则会把指定的VO对象序列化
运行测试类中的测试方法:testSerialGet()则根据key去获取对象,运行后控制台可以看到打印对象信息类似如下:
com.xiaoxie.vo.Member@10c171c
配置多个RedisTemplate
如果我们需要在程序中连接多个Redis数据源,这个时候不可以依赖于SpringBoot的自动配置实现,只能由用户自已来创建RedisTemplate对象。
在配置文件application.yml中新增两个自己定义的redis的连接配置信息
#自定义Redis连接配置
myRedis:
redis-one:
host: 127.0.0.1
port: 6379
password: xiaoxie
timeout: 1000
database: 0
pool:
max-active: 10
max-idle: 8
min-idle: 2
max-wait: 100
redis-two:
host: 127.0.0.1
port: 6379
password: xiaoxie
timeout: 1000
database: 1
pool:
max-active: 10
max-idle: 8
min-idle: 2
max-wait: 100
在pom.xml文件中添加相关的依赖
<!-- 当自定义Redis配置源时需要新增如下依赖 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>
新增一个配置类:com.xiaoxie.config.RedisCustomConfig
package com.xiaoxie.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;
import javax.annotation.Resource;
@Configuration
public class RedisCustomConfig {
@Resource(name = "redisConnectionFactory")
private RedisConnectionFactory redisConnectionFactoryOne;
@Resource(name = "redisConnectionFactoryTwo")
private RedisConnectionFactory getRedisConnectionFactoryTwo;
private JedisConnectionFactory getJedisConnectionFactory(String hostName, String password, int port, int database, int maxActive, int maxIdle, int minIdle, long maxWait) {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
jedisConnectionFactory.setHostName(hostName);
jedisConnectionFactory.setPort(port);
jedisConnectionFactory.setPassword(password);
jedisConnectionFactory.setDatabase(database);
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(maxActive);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);
poolConfig.setMaxWaitMillis(maxWait);
jedisConnectionFactory.setPoolConfig(poolConfig);
jedisConnectionFactory.afterPropertiesSet(); //初始化连接池配置
return jedisConnectionFactory;
}
@Bean("redisConnectionFactoryTwo")
public RedisConnectionFactory getGetRedisConnectionFactoryTwo(
@Value("${myRedis.redis-two.host}") String hostName,
@Value("${myRedis.redis-two.password}") String password,
@Value("${myRedis.redis-two.port}") int port,
@Value("${myRedis.redis-two.database}") int database,
@Value("${myRedis.redis-two.pool.max-active}") int maxActive,
@Value("${myRedis.redis-two.pool.max-idle}") int maxIdle,
@Value("${myRedis.redis-two.pool.min-idle}") int minIdle,
@Value("${myRedis.redis-two.pool.max-wait}") long maxWait){
return getJedisConnectionFactory(hostName,password,port,database,maxActive,maxIdle,minIdle,maxWait);
}
@Bean("redisConnectionFactory")
public RedisConnectionFactory getGetRedisConnectionFactoryOne(
@Value("${myRedis.redis-one.host}") String hostName,
@Value("${myRedis.redis-one.password}") String password,
@Value("${myRedis.redis-one.port}") int port,
@Value("${myRedis.redis-one.database}") int database,
@Value("${myRedis.redis-one.pool.max-active}") int maxActive,
@Value("${myRedis.redis-one.pool.max-idle}") int maxIdle,
@Value("${myRedis.redis-one.pool.min-idle}") int minIdle,
@Value("${myRedis.redis-one.pool.max-wait}") long maxWait){
return getJedisConnectionFactory(hostName,password,port,database,maxActive,maxIdle,minIdle,maxWait);
}
@Bean("redisOne")
public RedisTemplate<String,String> getRedisTemplateOne(){
RedisTemplate<String,String> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(this.redisConnectionFactoryOne);
return redisTemplate;
}
@Bean("redisTwo")
public RedisTemplate<String,String> getRedisTemplateTwo(){
RedisTemplate<String,String> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(this.getRedisConnectionFactoryTwo);
return redisTemplate;
}
}
注意:原来配置类RedisConfig需要把配置注解注释掉,因为它会和自己定义的置类存在冲突
修改测试类com.xiaoxie.test.TestRedisTemplate为如下:
package com.xiaoxie.test;
import com.xiaoxie.SpringBootStartApplication;
import com.xiaoxie.vo.Member;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import javax.annotation.Resource;
@SpringBootTest(classes = SpringBootStartApplication.class)
@RunWith
(SpringJUnit4ClassRunner.
class
)
@WebAppConfiguration
public class TestRedisTemplate {
@Resource
(name =
"redisOne"
)
private RedisTemplate<String,String> redisOne;
@Resource(name = "redisTwo")
private RedisTemplate<String,String> redisTwo;
@Test
public void tesMoreSet(){
redisOne.opsForValue().set("xiaoxie","hello");
redisTwo.opsForValue().set("xiaoxie","hihi");
}
}
运行上面的测试方法后,我们可以使用客户端连接redis可以得到看到如下情况
