Redis缓存的应用
1. 问题:使用系统管理员登录后,选择角色,点击权限按钮,每一次都会查询角色及其对应的权限,每一次都查询数据库。
* 一个角色用于哪些菜单,类似这种是公有的数据,可以存入到缓存中
2. 重构代码:加入Redis缓存技术
/**
* 使用FastJson转换json字符串
* @return
* @throws Exception
*/
public String roleModuleJsonStr() throws Exception {
// 先查询该角色对象
model = roleService.get(Role.class, model.getId());
Set<Module> modules = model.getModules();
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
// ==============加入Redis代码====================
// 先获取到连接池对象
Jedis jedis = jedisPool.getResource();
// 定义key值,这个key值注意:使用字符串和角色的ID拼接到一起组成的
String key = SysConstant.REDIS_TREE+model.getId();
// 先通过key从缓存中获取数据
String value = jedis.get(key);
// 判断,如果获取的值是空的,说明缓存中没有
if(UtilFuns.isEmpty(value)){
// 从数据库中查询
// 查询所有的菜单
List<Module> moduleList = moduleService.find("from Module where state = 1", Module.class, null);
// 拼接json的字符串
for (Module module : moduleList) {
Map<String, String> map = new HashMap<String, String>();
map.put("id", module.getId());
map.put("pId", module.getParentId());
map.put("name", module.getName());
// 判断
if(modules.contains(module)){
map.put("checked", "true");
}else{
map.put("checked", "false");
}
list.add(map);
}
// 查询到了数据,把数据转换成json字符串
String jsonString = FastJsonUtils.toJSONString(list);
// 把jsonString存入到缓存中
jedis.set(key, jsonString);
// 关闭连接
jedis.close();
// 给字符串赋值
value = jsonString;
System.out.println("查询的数据库...");
}else{
System.out.println("从Redis缓存中获取...");
}
// 响应
// FastJsonUtils.write_json(ServletActionContext.getResponse(), list);
// 响应json
FastJsonUtils.write_json(ServletActionContext.getResponse(), value);
return NONE;
}
3. 问题:当为角色分配了新的菜单,那么需要清除Redis缓存中的数据
/**
* 菜单分配功能
* @return
* @throws Exception
*/
public String module() throws Exception {
model = roleService.get(Role.class, model.getId());
Set<Module> modules = new HashSet<Module>();
String[] ids = moduleIds.split(",");
for (String id : ids) {
Module module = moduleService.get(Module.class, id);
modules.add(module);
}
model.setModules(modules);
roleService.saveOrUpdate(model);
// 清除指定的缓存
Jedis jedis = jedisPool.getResource();
// 定义key值,这个key值注意:使用字符串和角色的ID拼接到一起组成的
String key = SysConstant.REDIS_TREE+model.getId();
// 清除缓存
jedis.del(key);
// 关闭连接
jedis.close();
return "page";
}
Spring Data JPA整合Redis缓存的配置
1. 整合的配置文件如下
<!-- Spring整合redis -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="30"/>
</bean>
<!-- 配置JedisConnectionFactoryBean对象 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="localhost"/>
<property name="port" value="6379"/>
<property name="poolConfig" ref="poolConfig"/>
</bean>
<!-- 配置RedisTemplate -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
</property>
</bean>
2. 测试代码如下
@Test
public void run7() throws Exception{
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-redis.xml");
RedisTemplate<String, String> t = (RedisTemplate<String, String>) ac.getBean("redisTemplate");
t.opsForValue().set("msg", "haha");
}
消息中间件
消息中间件
1. 消息中间件的概述
2. 消息中间件的应用场景(查看大纲文档,了解消息队列的应用场景)
* 异步处理
* 应用解耦
* 流量削峰
* 消息通信
JMS消息服务
JMS的概述
1. JMS消息服务的概述
2. JMS消息模型
* P2P模式
* Pub/Sub模式
3. 消息消费的方式
* 同步的方式
* 异步的方式
4. JMS编程模型
消息中间件:ActiveMQ
ActiveMQ的下载与安装
1. ActiveMQ的下载与安装
* 在资料中找到ActiveMQ的压缩文件,解压apache-activemq-5.14.5-bin.zip文件
* 双击运行:activemq.bat文件,启动服务
2. 测试ActiveMQ是否安装成功
* 打开浏览器,输入:http://localhost:8161
3. 点击Manage ActiveMQ broker连接,可以查看ActiveMQ中已经发布的消息等
* 用户名密码都是:admin
4. ActiveMQ的服务器和默认的端口号
* 使用协议是TCP的协议:tcp://localhost:61616
ActiveMQ的消息队列方式入门
1. 在父工程的pom.xml文件中引入ActiveMQ和Spring整合JMS的坐标依赖(项目中已经引入)
<!-- activemq start -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.2.0</version>
</dependency>
<!-- activemq end -->
<!-- spring 与 mq整合 start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.7</version>
</dependency>
<!-- spring 与 mq整合 end -->
2. ActiveMQ的向消息队列中发送消息的入门程序(没有使用Spring整合JMS的方式)
* 具体的代码如下
@Test
public void run1() throws Exception{
// 创建连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory();
// 使用工厂,创建连接
Connection connection = factory.createConnection();
// 启动连接
connection.start();
// 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// 创建队列队形
Queue queue = session.createQueue("hello");
// 创建生产者
MessageProducer producer = session.createProducer(queue);
// 创建消息
TextMessage message = session.createTextMessage("美美");
// 发送消息
producer.send(message);
// 提交事务
session.commit();
session.close();
connection.close();
}
3. ActiveMQ从消息队列中获取消息
* 具体的代码如下
@Test
public void run2() throws Exception{
// 创建连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory();
// 使用工厂,创建连接
Connection connection = factory.createConnection();
// 启动连接
connection.start();
// 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// 创建队列队形
Queue queue = session.createQueue("hello");
// 创建消费者
MessageConsumer consumer = session.createConsumer(queue);
// 接收消息
TextMessage message = (TextMessage)consumer.receive();
System.out.println(message.getText());
// 提交事务
session.commit();
session.close();
connection.close();
}
4. 使用监听器的方式,从队列中消费消息
/**
* 使用监听器的方式消费消息
* @throws Exception
*/
@Test
public void run3() throws Exception{
// 创建连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory();
// 使用工厂,创建连接
Connection connection = factory.createConnection();
// 启动连接
connection.start();
// 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建队列队形
Queue queue = session.createQueue("hello");
// 创建消费者
MessageConsumer consumer = session.createConsumer(queue);
// 给消费者添加监听器
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message msg) {
TextMessage message = (TextMessage) msg;
try {
System.out.println(message.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
while(true){}
// 使用监听器的方式不能关闭,需要监听器一直工作
// session.commit();
// session.close();
// connection.close();
}
ActiveMQ的消息订阅方式入门
1. 发送消息的入门程序
/**
* 订阅方式发送消息
* @throws Exception
*/
@Test
public void run4() throws Exception{
// 创建连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory();
// 使用工厂,创建连接
Connection connection = factory.createConnection();
// 启动连接
connection.start();
// 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// 创建消息订阅
Topic topic = session.createTopic("helloTopic");
// 创建生产者
MessageProducer producer = session.createProducer(topic);
// 创建消息,一组可以存储key value的消息
MapMessage message = session.createMapMessage();
message.setString("phone", "119");
message.setString("code", "123456");
// 发送消息
producer.send(message);
// 提交事务
session.commit();
session.close();
connection.close();
}
2. 消费者的代码如下
/**
* 消费者
* @throws Exception
*/
@Test
public void run5() throws Exception{
// 创建连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory();
// 使用工厂,创建连接
Connection connection = factory.createConnection();
// 启动连接
connection.start();
// 使用连接,创建会话,true表示开始事务,代码执行后需要提供事务
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建消息订阅
Topic topic = session.createTopic("helloTopic");
// 创建消费者
MessageConsumer consumer = session.createConsumer(topic);
// 设置监听器
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message msg) {
MapMessage message = (MapMessage) msg;
try {
String phone = message.getString("phone");
String code = message.getString("code");
System.out.println(phone + ":" + code);
} catch (JMSException e) {
e.printStackTrace();
}
}
});
while(true){
}
}
Spring整合ActiveMQ
Spring整合ActiveMQ
1. 创建applicationContext-mq.xml的配置文件,导入约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd">
</beans>
2. 具体的配置如下
<!-- 配置连接工厂 -->
<amq:connectionFactory id="connectionFactory" userName="admin" password="admin" brokerURL="tcp://localhost:61616"/>
<!-- 配置Session,但是Spring已经整合了,进行管理,使用Spring的配置 -->
<bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<!-- 要缓存Session的数量 -->
<property name="sessionCacheSize" value="5"/>
<!-- 连接工厂 -->
<property name="targetConnectionFactory" ref="connectionFactory"/>
</bean>
<!-- 配置queue的jms模板 -->
<bean id="queueJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 不是pubsub方式是,那就是队列方式 -->
<property name="pubSubDomain" value="false"/>
<property name="connectionFactory" ref="cachingConnectionFactory"/>
</bean>
<!-- 配置topic的jms模板 -->
<bean id="topicJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 是主题方式 -->
<property name="pubSubDomain" value="true"/>
<property name="connectionFactory" ref="cachingConnectionFactory"/>
</bean>
3. 发送消息的代码如下
@Test
public void run6() throws Exception{
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-mq.xml");
JmsTemplate template = (JmsTemplate) ac.getBean("queueJmsTemplate");
// 发送消息
template.send("hello",new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
// 使用session创建消息,发送
TextMessage message = session.createTextMessage("haha");
return message;
}
});
}
4. 接收消息的代码如下
@Test
public void run7() throws Exception{
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-mq.xml");
JmsTemplate template = (JmsTemplate) ac.getBean("queueJmsTemplate");
// 发送消息
TextMessage message = (TextMessage) template.receive("hello");
System.out.println(message.getText());
}
Spring配置监听器
1. 自定义监听器代码的编写
public class MyQueueListener implements MessageListener{
public void onMessage(Message msg) {
// 把msg强转
TextMessage message = (TextMessage) msg;
try {
// 输出消息
System.out.println(message.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
2. 编写配置文件
<!-- 配置连接工厂 -->
<amq:connectionFactory id="connectionFactory" userName="admin" password="admin" brokerURL="tcp://localhost:61616"/>
<!-- 配置Session,但是Spring已经整合了,进行管理,使用Spring的配置 -->
<bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<!-- 要缓存Session的数量 -->
<property name="sessionCacheSize" value="5"/>
<!-- 连接工厂 -->
<property name="targetConnectionFactory" ref="connectionFactory"/>
</bean>
<!-- 配置自定义的监听器 -->
<bean id="myQueueListener" class="ee66_jms.MyQueueListener"/>
<!-- 配置监听器 -->
<jms:listener-container destination-type="queue" connection-factory="cachingConnectionFactory">
<!-- 监听的是hello的消息队列 -->
<jms:listener destination="hello" ref="myQueueListener"/>
</jms:listener-container>
3. 编写测试的方法
@Test
public void run8() throws Exception{
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext-mq-listener.xml");
while(true){
}
}