Appearance
分布式锁中间件集成组件
基于Redisson实现的Redis统一集成组件。
1. 集成说明
(1)在 pom.xml 配置文件中引入 :
xml
<dependency>
<groupId>com.chinapost.mids</groupId>
<artifactId>cpms-redisson-spring-boot-starter</artifactId>
<version>1.0.1-RELEASE</version>
</dependency>
(2)在 application.yml
配置文件增加:
yaml
#单Redis节点模式
redisson:
singleServerConfig:
address: 127.0.0.1:6379
2. 使用说明
2.1. 如何使用分布式锁?
在方法增加 @Lock
注解
java
//1.支持spel表达式,keyConstant是常量(可选)
@Lock(keys = "#user.name",keyConstant = "常量"))
public String test(User user) {
System.out.println("进来了test");
return "test";
}
@Lock 注解参数介绍
java
/**
* REENTRANT(可重入锁),FAIR(公平锁),MULTIPLE(联锁),REDLOCK(红锁),READ(读锁), WRITE(写锁),
* AUTO(自动模式,当参数只有一个.使用 REENTRANT 参数多个 MULTIPLE)
*/
LockModel lockModel() default LockModel.AUTO;
/**
* 需要锁定的keys
* @return
*/
String[] keys() default {};
/**
* 锁超时时间,默认30000毫秒(可在配置文件全局设置)
* @return
*/
long lockWatchdogTimeout() default 0;
/**
* 等待加锁超时时间,默认10000毫秒 -1 则表示一直等待(可在配置文件全局设置)
* @return
*/
long attemptTimeout() default 0;
2.2. 如何存储数据?
目前实现了三个对象模板:RedissonObject、RedissonBinary、RedissonCollection。
(1)RedissonObject
RedissonObject 这个是比较通用的模板,任何对象都可以存在这里面,在spring 容器中注入对象即可:
java
@Resource
private RedissonObject redissonObject;
完整示例:
java
@Controller
public class ObjectController {
@Resource
private RedissonObject redissonObject;
/**
* 设置值
* @param user
* @param request
* @param response
* @return
* @throws InterruptedException
*/
@RequestMapping("/object1")
@ResponseBody
public String object1(User user, HttpServletRequest request, HttpServletResponse response) throws InterruptedException {
User user1 = new User();
user1.setName("test");
user1.setAge("123");
redissonObject.setValue("object1", user1,-1L);
return "";
}
/**
* 获取值
* @param user
* @param request
* @param response
* @return
* @throws InterruptedException
*/
@RequestMapping("/object2")
@ResponseBody
public Object object2(User user, HttpServletRequest request, HttpServletResponse response) throws InterruptedException {
return redissonObject.getValue("object1");
}
/**
* 如果对象不存在则设置,否则不设置
* @param user
* @param request
* @param response
* @return
* @throws InterruptedException
*/
@RequestMapping("/object3")
@ResponseBody
public String object3(User user, HttpServletRequest request, HttpServletResponse response) throws InterruptedException {
return redissonObject.trySetValue("object1","object1-2")+"";
}
}
(2)RedissonBinary
RedissonBinary 这个是存储二进制的模板,可以存放图片之内的二进制文件,在spring 容器中注入对象即可:
java
@Resource
private RedissonBinary redissonBinary;
完整示例:
java
@Controller
public class BinaryController {
@Resource
private RedissonBinary redissonBinary;
/**
* 存放图片
* @param user
* @param request
* @param response
* @return
* @throws Exception
*/
@RequestMapping("/binary1")
@ResponseBody
public String binary1(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
redissonBinary.setValue("binary",new FileInputStream(new File("f:/1.png")));
return "11";
}
/**
* 获取图片
* @param user
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("/binary2")
public void binary2(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
redissonBinary.getValue("binary",response.getOutputStream());
}
}
(3)RedissonCollection
RedissonCollection这个是集合模板,可以存放 Map
, List
, Set
集合元素,在spring 容器中注入对象即可:
java
@Resource
private RedissonCollection redissonCollection;
完整示例:
java
@Controller
public class CollectionController {
@Resource
private RedissonCollection redissonCollection;
/**
* map操作
* @param user
* @param request
* @param response
* @return
* @throws Exception
*/
@RequestMapping("/collection1")
@ResponseBody
public String collection1(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String,String> map=new HashMap<>();
map.put("test1","test11");
map.put("test2","test22");
map.put("test3","test33");
map.put("test4","test44");
//设置值
redissonCollection.setMapValues("test",map);
//获取值
RMap<String, String> test = redissonCollection.getMap("test");
System.out.println(test);
return "11";
}
/**
* list操作
* @param user
* @param request
* @param response
* @return
* @throws Exception
*/
@RequestMapping("/collection2")
@ResponseBody
public String collection2(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
List<String> list=new ArrayList<>();
list.add("test1");
list.add("test2");
list.add("test3");
list.add("test4");
list.add("test5");
//设置值
redissonCollection.setListValues("list",list);
//获取值
RList<Object> list1 = redissonCollection.getList("list");
System.out.println(list1);
return "11";
}
/**
* set操作
* @param user
* @param request
* @param response
* @return
* @throws Exception
*/
@RequestMapping("/collection3")
@ResponseBody
public String collection3(User user, HttpServletRequest request, HttpServletResponse response) throws Exception {
Set<String> set=new HashSet<>();
set.add("test1");
set.add("test2");
set.add("test3");
set.add("test4");
set.add("test5");
//设置值
redissonCollection.setSetValues("set",set);
//获取值
RSet<Object> set1 = redissonCollection.getSet("set");
System.out.println(set1);
return "11";
}
}
2.3. 如何session集群?
在启动类标注 @EnableRedissonHttpSession
即可。
2.4. 如何使用 redisson
客户端实现自定义操作
只需要在spring 容器中注入redisson客户端就行,如下:
java
@Autowired
private RedissonClient redissonClient;
2.5. 如何集成 spring cache
启动类加上 @EnableCache(value = {"cache1","cache2"})
,@Cacheable,@CachePut,@CacheEvict的value必须包含在这里面。
完整示例:
java
package com.chinapost.mids.redisson.starter.test.controller;
import com.chinapost.mids.redisson.starter.test.bean.User;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class CacheController {
@RequestMapping("/cache1")
@ResponseBody
@Cacheable(value = "cache1",key = "'test1'")
public String cache1(){
return "test";
}
@RequestMapping("/cache2")
@ResponseBody
@Cacheable(value = "cache2",key = "'test2'")
public User cache2(){
User user=new User();
user.setName("name");
user.setAge("123");
return user;
}
}
2.6. 如何使用消息队列MQ.
两个注解即可完成操作。
消息队列分为 生产者
以及 消费者
,生产者
生产消息供 消费者
消费。
生产者
配置
发送消息有两种模式,二选一即可:
(1)代码模式
java
RTopic testMq = redissonClient.getTopic("testMq");
User message = new User();
message.setAge("12");
message.setName("的身份为");
testMq.publish(message);
(2)注解模式
java
@RequestMapping("testMq1")
@ResponseBody
@MQPublish(name = "test")
public User testMq1(){
User user=new User();
user.setName("garegarg");
user.setAge("123");
return user;
}
消费者
配置
(1)启动类加上 @EnableMQ
开启消费者
(2)使用注解@MQListener(name = "testMq")
配置消费者
java
@MQListener(name = "testMq")
public void test1(CharSequence charSequence,User o,Object object){
System.out.println("charSequence="+charSequence);
System.out.println("收到消息2"+o);
}
完整示例:
生产者
java
import MQPublish;
import com.chinapost.mids.redisson.starter.test.bean.User;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
@Controller
public class MQController {
@Resource
private RedissonClient redissonClient;
/**
* 发送方式一: 使用代码发送消息
*/
@RequestMapping("testMq")
@ResponseBody
public void testMq() {
RTopic testMq = redissonClient.getTopic("testMq");
User message = new User();
message.setAge("12");
message.setName("的身份为");
testMq.publish(message);
}
/**
* 发送方式二:使用注解发送消息, 返回值就是需要发送的消息
* @return
*/
@RequestMapping("testMq1")
@ResponseBody
@MQPublish(name = "test")
public User testMq1() {
User user = new User();
user.setName("garegarg");
user.setAge("123");
return user;
}
}
消费者
java
package com.chinapost.mids.redisson.starter.test.listener;
import MQListener;
import MQModel;
import com.chinapost.mids.redisson.starter.test.bean.User;
import org.springframework.stereotype.Component;
//注入到spring容器中
@Component
public class MQListeners {
/**
* 接受消息方式一:PRECISE精准的匹配 如:name="myTopic" 那么发送者的topic name也一定要等于myTopic (如果消息类型不明确,请使用Object 接收消息)
* @param charSequence
* @param o
*/
@MQListener(name = "testMq")
public void test1(CharSequence charSequence, User o, Object object) {
System.out.println("charSequence=" + charSequence);
System.out.println("收到消息2" + o);
}
/**
*
* 接收消息方式二: PATTERN模糊匹配 如: name="myTopic.*" 那么发送者的topic name 可以是 myTopic.name1 myTopic.name2.尾缀不限定
* @param patten
* @param charSequence
* @param o
*/
@MQListener(name = "test*", model = MQModel.PATTERN)
public void test1(CharSequence patten, CharSequence charSequence, User o) {
System.out.println("patten=" + patten);
System.out.println("charSequence=" + charSequence);
System.out.println("test*=" + o);
}
}
2.7. 集群模式配置(也可以使用yml写法)
单例模式
单机版redis
yaml
#单Redis节点模式
redisson:
singleServerConfig:
address: 127.0.0.1:6379
集群模式
集群模式除了适用于Redis集群环境,也适用于任何云计算服务商提供的集群模式,例如AWS ElastiCache集群版、Azure Redis Cache和阿里云(Aliyun)的云数据库Redis版。
yaml
#集群模式
redisson:
model: CLUSTER
password: xxx
multiple-server-config:
#redis机器.一直累加下去
node-addresses:
- 127.0.0.1:6379
- 127.0.0.1:6380
- 127.0.0.1:6381
云托管模式
云托管模式适用于任何由云计算运营商提供的Redis云服务,包括:亚马逊云的AWS ElastiCache、微软云的Azure Redis 缓存和阿里云(Aliyun)的云数据库Redis版
yaml
#云托管模式
redisson:
model: REPLICATED
password: xxx
multiple-server-config:
#redis机器.一直累加下去
node-addresses:
- 127.0.0.1:6379
- 127.0.0.1:6380
- 127.0.0.1:6381
哨兵模式
yaml
redisson:
model: SENTINEL
password: xxx
#主服务器的名称是哨兵进程中用来监测主从服务切换情况的。
multiple-server-config:
master-name: mymaster
#redis机器.一直累加下去
node-addresses:
- 127.0.0.1:6379
- 127.0.0.1:6380
- 127.0.0.1:6381
只有一个代理地址的redis哨兵模式
yaml
redisson:
model: SENTINEL
password: xxx
#主服务器的名称是哨兵进程中用来监测主从服务切换情况的。
multiple-server-config:
master-name: mymaster
check-sentinels-list: false
node-addresses: 127.0.0.1:6379
主从模式
yaml
redisson:
model: MASTERSLAVE
password: xxx
multiple-server-config:
#第一台机器就是主库.其他的为从库
node-addresses:
- 127.0.0.1:6379
- 127.0.0.1:6380
- 127.0.0.1:6381