3.4Redis实现内部队列

日常工作中会出现操作的异步处理,这时候就需要队列了,redis可以模拟实现队列。原理就是模拟一个topic,然后把消息放到redis的list对象里面,由专门的监听器来捕获队列的内容。

来看看具体实现,模拟这样一个场景,用户注册时,需要发短信,把发短信的这个操作异步处理,放入redis队列。

添加依赖

 
        UTF-8
        4.12
        4.3.3.RELEASE
        2.9.0
    

    
        
            org.springframework
            spring-aop
            ${spring.version}
        
        
            org.springframework
            spring-aspects
            ${spring.version}
        
        
            org.springframework
            spring-beans
            ${spring.version}
        
        
            org.springframework
            spring-context
            ${spring.version}
        
        
            org.springframework
            spring-context-support
            ${spring.version}
        
        
            org.springframework
            spring-core
            ${spring.version}
        
        
            org.springframework
            spring-web
            ${spring.version}
        
        
            org.springframework
            spring-test
            ${spring.version}
        
        
            org.springframework.data
            spring-data-redis
            1.7.2.RELEASE
        
        
            redis.clients
            jedis
            ${jedis.version}
        
        
            junit
            junit
            ${junit.version}
        
    

这里面主要包括spring依赖和redis依赖。

新建一个web工程,并修改web.xml

 
        contextConfigLocation
        
            classpath:applicationContext-redis.xml
        
    
    
        org.springframework.web.context.ContextLoaderListener
    

这里面的核心是启动时加载applicationContext-redis.xml,利用spring的监听ContextLoaderListener

application.properties 配置

redis.host=127.0.0.1
redis.port=6379
redis.pass=
redis.maxIdle=300
redis.testOnBorrow=true

applicationContext-redis.xml配置

 
    
        
        
        
    
    
    
        
    

    
    
   
    
    
    
        
        
    
    
    
        
    
    
    
        
    

SmsMessageVo.java 模拟消息的一个VO

public class SmsMessageVo implements Serializable {
    private static final long serialVersionUID = 1L;
    // 手机号
    private String mobile;

    // 短信内容
    private String content;
    //省略get set方法
}

里面包括一个手机号,一个短信内容即验证码

SmsMessageDelegateListener消息队列监听

public class SmsMessageDelegateListener {

    // 监听Redis消息
    public void handleMessage(Serializable message) {
        System.out.println("收到消息" + message);
    }
}

接收到消息后就可以进行后续的处理,比如调用发短信服务等等。
这里面需要把message一般是一个json串,先转换成对应的vo,再进行后续的处理

SendMessage.java 发送消息类

public class SendMessage {
    private RedisTemplate redisTemplate;

    public RedisTemplate getRedisTemplate() {
        return redisTemplate;
    }

    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void sendMessage(String channel, Serializable message) {
        redisTemplate.convertAndSend(channel, message);
    }
}

这里面最核心的一句redisTemplate.convertAndSend(channel, message),发送到指定通道消息。

模拟发送消息

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:applicationContext-redis.xml"})
public class TestSendMessage {

    @Autowired
    private SendMessage sendMessage;

    @Test
    public void testSendMessage() {
        SmsMessageVo smsMessageVo = new SmsMessageVo();
        smsMessageVo.setMobile("13811111111");
        smsMessageVo.setContent("1234");
        //一般消息内容会是一个json串,消费时再把json转成对象
        sendMessage.sendMessage("sms_queue_shortmessage", smsMessageVo.toString());
    }
}

首先启动web工程,然后点击TestSendMessage进行消息的发送。

3.4Redis实现内部队列_第1张图片
消息接收结果

利用redis实现的消息队列可以进行事务的异步处理,不过这个消息队列和其他的消息中间件有本质的区别,最大的区别就是redis不能保证同一个消息被一个应用接收,比如当前有多个应用监听redis实现的队列,如果队列里面加入新消息,就会被多个应用同时接收,不能实现消息被唯一应用接收。

当然这只是一个简单的队列,如果有更多需求,需要采用专门的消息中间件来实现,比如rabbitmq、activemq等等

源码下载

[本工程详细源码]
(https://github.com/chykong/java_component/tree/master/chapter3_4_redis_queue)

你可能感兴趣的:(3.4Redis实现内部队列)