spring chat(二)

参考资料:
1.http://spring.io/blog/2012/05/16/spring-mvc-3-2-preview-chat-sample/
2.spring redis Message-Driven相关资料(比如http://blog.csdn.net/xiejx618/article/details/41413417)


本文是spring chat(一)的延伸,加入redis,以致可以进行多台服务器的分布式部署.

1.spring mvc的Root Config配置AppConfig.

@Configuration
@ComponentScan(basePackages={"org.exam.repository","org.exam.handler"})
@PropertySource("classpath:redis.properties")
public class AppConfig {
    @Autowired
    private Environment env;
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory cf = new JedisConnectionFactory();
        cf.setHostName(this.env.getProperty("redis.host"));
        cf.setPort(this.env.getProperty("redis.port", int.class));
        cf.setPassword(this.env.getProperty("redis.password"));
        return cf;
    }
    @Bean
    public StringRedisTemplate redisTemplate() {
        return new StringRedisTemplate(redisConnectionFactory());
    }
    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer(MessageHandler messageHandler) {
        RedisMessageListenerContainer mlc = new RedisMessageListenerContainer();
        mlc.setConnectionFactory(redisConnectionFactory());
        mlc.addMessageListener(messageHandler, new PatternTopic("chat"));
        return mlc;
    }
}
这里注册了3个bean,连接redis服务器的工厂,redis收发信息工具和注册一个Redis客户端监听器.
2.上面这个监听器使用MessageHandler作为消息处理.内容如下:
@Component
public class MessageHandler implements MessageListener {
    @Autowired
    private ChatRepository chatRepository;
    private final Map<DeferredResult<List<String>>, Integer> chatRequests =
            new ConcurrentHashMap<DeferredResult<List<String>>, Integer>();

    public Map<DeferredResult<List<String>>, Integer> getChatRequests() {
        return chatRequests;
    }
    @Override
    public void onMessage(Message message, byte[] pattern) {
        for (Map.Entry<DeferredResult<List<String>>, Integer> entry : this.chatRequests.entrySet()) {
            List<String> messages = this.chatRepository.getMessages(entry.getValue());
            entry.getKey().setResult(messages);
        }
    }
}
实现MessageListener接口的onMessage方法,即一旦redis客户端接收到消息,马上将相应的消息返回给现有未处理的request,并提交响应.ChatRepository注入的是RedisChatRepository(详细看:https://github.com/rstoyanchev/spring-mvc-chat/blob/redis/src/main/java/org/springframework/samples/async/chat/RedisChatRepository.java)此工具实现了发信息,获取信息的功能.消息的存储在redis.
3.再看看Controller的改变.
@Controller
@RequestMapping("/mvc/chat")
public class ChatController {
    @Autowired
    private MessageHandler messageHandler;
    @Autowired
    private ChatRepository chatRepository;
    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public DeferredResult<List<String>> getMessages(@RequestParam int messageIndex) {
        final DeferredResult<List<String>> deferredResult = new DeferredResult<List<String>>(null, Collections.emptyList());
        final Map<DeferredResult<List<String>>, Integer> chatRequests = messageHandler.getChatRequests();
        chatRequests.put(deferredResult, messageIndex);
        deferredResult.onCompletion(new Runnable() {
            @Override
            public void run() {
                chatRequests.remove(deferredResult);
            }
        });
        List<String> messages = chatRepository.getMessages(messageIndex);
        if (!messages.isEmpty()) {
            deferredResult.setResult(messages);
        }
        return deferredResult;
    }
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    @ResponseStatus(value = HttpStatus.OK)
    public void postMessage(@RequestParam String message) {
        chatRepository.addMessage(message);
    }
}
改变不大,可以将请求放入到messageHandler的chatRequests,也可以从chatRequests取出未处理的请求.chatRepository用于发送消息或获取消息.post方法把处理那些未处理的请求代码去掉了,我觉得没必要.只要在redis监听到消息马上处理,基本就没什么延迟了.
4.页面与前文一样,不作任何改变.启动redis,然后测试.


你可能感兴趣的:(redis,spring,chat)