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客户端监听器.
@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.
@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监听到消息马上处理,基本就没什么延迟了.