spring chat(一)

5 篇文章 0 订阅
参考资料:
1.http://spring.io/blog/2012/05/16/spring-mvc-3-2-preview-chat-sample/
2.spring mvc异步请求处理的资料(比如http://blog.csdn.net/xiejx618/article/details/41285085)
3.Thymeleaf:http://www.thymeleaf.org/
4.knockoutjs:http://knockoutjs.com/


这个例子的源码主要来自于https://github.com/rstoyanchev/spring-mvc-chat,其中加入了Thymeleaf和knockoutjs两大技术点,增加了此例子的难度,但两大官网都有比较详细的资料介绍.
一.前期准备:
1.确保spring mvc支持异步请求,可参考前两篇文章.
2.集成Thymeleaf:

2.1.pom.xml主要加入依赖:

<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring4</artifactId>
    <version>${thymeleaf.version}</version>
</dependency>
2.2.继承WebMvcConfigurerAdapter的MvcConfig加入:
@Bean
public TemplateResolver templateResolver() {
	ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
	resolver.setPrefix("/WEB-INF/templates/");
	resolver.setSuffix(".html");
	resolver.setTemplateMode("HTML5");
	resolver.setCacheable(false);
	return resolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
	SpringTemplateEngine engine = new SpringTemplateEngine();
	engine.setTemplateResolver(templateResolver());
	return engine;
}
@Bean
public ViewResolver viewResolver() {
	ThymeleafViewResolver resolver = new ThymeleafViewResolver();
	resolver.setTemplateEngine(templateEngine());
	return resolver;
}
2.3.建立chat.html,以上设置HTML5,标签格式是比较严格的,不严格可能即时抛异常.
2.4.在DefaultController写一个方法,启动jetty测试

@RequestMapping(value = "/",method = RequestMethod.GET)
public String index(){
	return "chat";
}
二.后端处理分析.
ChatController
1.使用了ConcurrentHashMap来装请求,key是DeferredResult<List<String>>类型,因为不同的请求是不一样的,所以不会覆盖已有的元素.
2.先看用于获取消息的getMessages方法.final DeferredResult<List<String>> deferredResult = new DeferredResult<List<String>>(null, Collections.emptyList());这里并不是使用于构造一个deferredResult,null的意思使用servlet容器的默认超时时间,当异步处理超时时,返回空集.
onCompletion回调是用于处理请求完成时做的清理.chatRepository.getMessages(messageIndex);是传入一个信息的索引,获取从此索引之后的所有消息.
3.再看用于发送消息的postMessage方法.this.chatRepository.addMessage(message);用于向messages添加消息.然后将已有未处理的请求处理并返回消息到页面.
三.前端处理分析.
前端好像没有什么可以说的,但要强调的一点是一旦调用了pollForMessages之后,就开始长轮询了.
四.测试调试.


从调试结果来看发现一个问题:
当进入聊天界面发送消息之后,立刻退出,不关闭页面,界面没刷新,再进入聊天界面发送消息.此时后台抛异常了,前台也报错了.引起这问题的原因:
1.当进入聊天界面,轮询开始,发送消息之后,轮询继续.因为传到后台的索引已经达到获取消息的最大值,所以后台并没有立即提交响应.
2.退出聊天,界面没刷新,刚才那个响应还没提交的响应并没有断开,再次进入聊天界面,页面又开始轮询了,也就是说又发起了一个未处理的请求(因为请求的索引也达到了最大值),再次发送消息,此时postMessage方法会将这两个请求的结果发回来,此时success回调会两次加1,再去轮询.虽然message的大小因为刚才的发送消息加1,但这次的轮询已经越界了,所以后台会抛异常.
对于这个异常可以认为是编程错误了,可以这样处理:
将InMemoryChatRepository的getMessages改为如下
public List<String> getMessages(int index) {
	if (index<0||this.messages.isEmpty()||index > this.messages.size()) {
		return Collections.<String> emptyList();
	}
	return this.messages.subList(index, this.messages.size());
}
这样messages的取子集就不会越界了,但还是没解决界面两次返回同样的消息处理结果.因为还是同样存在有相同的请求索引去拿消息,这个解决应该要从页面入手,当退出聊天页面,关闭一个页闭,让之前的那个请求断开连接,这样即使后台处理成超时,也不会再返回到success使messageIndex加两次1.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值