$(function () { getMsg(); }); function getMsg() { $.ajax({ url:"/polling/msg", type:"get", data:{}, success:function(data) { if(data != null && data!="") alertShow(data.msg); getMsg(); } }); }
/** * * @author {chensg}:2016年6月1日 * example * */ @Controller @RequestMapping("/polling/") public class PollingController { @Autowired MessageContainer messageContainer; //全局存放每一个user创建的DeferredResult实例,key:userId,value:DeferredResult @Autowired RabbitTemplate rabbitTemplate; /** * 长轮询 * @return */ @RequestMapping(value="msg", method=RequestMethod.GET) public @ResponseBody DeferredResult<UserMessage> getMessage() { final String userId = (UserDetails) SecurityContextHolder.getContext() .getAuthentication() .getPrincipal().getUsername(); DeferredResult<UserMessage> result = new DeferredResult<UserMessage>(30000l,null); //设置超时30s,超时返回null final Map<String, DeferredResult> resultMap=messageContainer.getUserMessages(); resultMap.put(userId, result); result.onCompletion(new Runnable() { @Override public void run() { resultMap.remove(userId); } }); return result; } /** * test 新增需要推给某某用户的消息 * @return */ @RequestMapping(value="msg", method=RequestMethod.POST) public @ResponseBody RestResult addMessage(String msg,String userId) { UserMessage userMsg = new UserMessage(); userMsg.setUserId(userId); userMsg.setMsg(msg); //系统或者其他用户需要推送的消息放入消息队列 rabbitTemplate.convertAndSend("test.exchange", "test.binding", userMsg); return null; } }
页面加载完成时,该用户请求/polling/msg控制器接口,接口里会创建一个DeferredResult实例,设置超时30S,超时返回null。DeferredResult<?> 允许应用程序从一个线程中返回,而何时返回则由线程决定。
消息实体类
public class UserMessage implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String userId; private String msg; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
配置rabbitMQ
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.5.xsd"> <!-- 创建一个connectionFactory --> <rabbit:connection-factory id="rabbitConnectionFactory" host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}" virtual-host="/" /> <!-- 创建一个rabbitTemplate, 设置retryTemplate --> <rabbit:template id="rabbitTemplate" connection-factory="rabbitConnectionFactory" retry-template="retryTemplate" /> <!-- 创建一个retryTemplate --> <bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate"> <property name="backOffPolicy"> <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy"> <property name="initialInterval" value="500" /> <property name="multiplier" value="10.0" /> <property name="maxInterval" value="10000" /> </bean> </property> </bean> <rabbit:admin connection-factory="rabbitConnectionFactory" /> <!-- 创建一个用于消息推送的队列 --> <rabbit:queue id="testQueue" name="test.polling" /> <rabbit:direct-exchange name="test.exchange"> <rabbit:bindings> <rabbit:binding queue="test.polling" key="test.binding" /> </rabbit:bindings> </rabbit:direct-exchange> <!-- 创建一个消息处理器 --> <bean id="servicePollingHandler" class="com.xxx.controller.test.ServicePollingHandler" /> <!-- 绑定监听器和队列 --> <rabbit:listener-container connection-factory="rabbitConnectionFactory"> <rabbit:listener ref="servicePollingHandler" method="testPollingHandle" queues="testQueue" /> </rabbit:listener-container> </beans>
public class ServicePollingHandler { @Autowired MessageContainer messageContainer; public void testPollingHandle(UserMessage userMessage) { Map<String, DeferredResult> msgContainer = messageContainer.getUserMessages(); DeferredResult<UserMessage> deferredResult = msgContainer.get(userMessage.getUserId()); if (deferredResult!=null){ deferredResult.setResult(userMessage); //调用setResult(),线程返回信息。 } } }
@PropertySource(value="classpath:application.properties") @ImportResource({"classpath:amqp.xml"}) public class RootConfig { @Bean public MessageContainer messageContainer() { return new MessageContainer(); } }
public class MessageContainer { private ConcurrentHashMap<String, DeferredResult> userMessages = new ConcurrentHashMap<String, DeferredResult>(); //线程安全 public ConcurrentHashMap<String, DeferredResult> getUserMessages() { return userMessages; } }
该例子的用途,当一个用户登录页面时,异步请求后台/polling/msg,后台创建一个线程,维持改长连接30s,当超时或者返回信息,页面则再次请求后台,维持一个30s的长连接(长轮询)。
系统或者其他用户调用/polling/msg method:post,传入msg与userId,控制器把消息放入消息队列,消息队列把消息推送到ServicePollingHandler类testPollingHandle()方法,该方法根据userId获得该用户登陆之后的页面长轮询创建的deferredResult实例,调用setResult,页面接受到线程返回消息。
可以基于以上代码,实现web聊天
使用支付宝扫描上方二维码领取红包
相关推荐
通过这个实例,你可以了解到如何利用SpringMVC处理业务逻辑,以及如何借助DWR实现从服务器到客户端的实时消息推送。理解这两个技术的结合,对于构建现代、交互性强的Web应用是非常有价值的。同时,这也是对传统HTTP...
总结起来,"springMvc + dwr 注解 实现消息推送"项目利用了Spring MVC的注解驱动开发和DWR的双向通信能力,为Web应用提供了一种高效且易于实施的消息推送解决方案。这种方案减少了配置工作,使开发者能更专注于业务...
SpringMVC整合websocket实现消息推送及触发功能 SpringMVC是一种流行的基于Java的Web应用程序框架,而websocket是一种实时通信协议,用于实现实时的双向通信。本文将详细介绍如何使用SpringMVC与websocket实现消息...
在本教程中,我们将探讨如何结合`SpringMVC`和`Ajax`来实现异步文件上传,并讨论短视频背景以及`a`标签绑定文件域的相关知识。 1. **SpringMVC中的文件上传** - **MultipartFile接口**:`SpringMVC`提供了一个名为...
下面是一个简单的例子,展示了如何在SpringMVC中实现异步JSON返回: ```java import org.springframework.web.bind.annotation.*; import org.springframework.scheduling.annotation.Async; import org.spring...
在本项目中,ActiveMQ与SpringMVC框架结合,实现了邮件的异步发送功能。 首先,我们需要理解ActiveMQ的基本概念。ActiveMQ是Apache软件基金会的产品,遵循JMS(Java消息服务)规范,支持多种协议,并且可以跨平台...
WebSocket是一种在客户端和服务器之间建立长连接的协议,它允许双方进行实时、双向的数据通信,极大地优化了Web应用中的消息推送。与传统的HTTP协议不同,WebSocket在建立连接后,通信双方不再需要通过频繁的HTTP...
总结来说,"springmvc+mybatis整合websocke推送"意味着将WebSocket的实时通信能力与Spring MVC的MVC架构和MyBatis的持久层操作结合,构建出能够高效推送数据的Web应用。这个过程中,你需要理解WebSocket的工作原理,...
1、项目需要,定时向所有在线用户推送一个广告或是推送一个通知之类的(比如服务器升级,请保存好手头工作之类的)。 2、相关环境 , Nginx、tomcat7、centos 6.5 3、项目框架,springMvc 4.0.6、layer
SpringMVC使用MultipartFile 实现异步上传方法介绍 SpringMVC是Java web开发中常用的框架之一,它提供了许多实用的功能和组件,例如MultipartFile,可以用来实现文件上传功能。异步上传是现代Web应用程序中常用的...
Java基于Spring+SpringMVC+MyBatis实现的学生信息管理系统源码,SSM+Vue的学生管理系统。 Java基于Spring+SpringMVC+MyBatis实现的学生信息管理系统源码,SSM+Vue的学生管理系统。 Java基于Spring+SpringMVC+...
在 SpringMVC 框架中,我们需要在 `applicationContext.xml` 文件中配置数据库连接信息,创建 sqlSession 工厂,实现 dao 层及 service 层的动态代理。 结论 SpringMVC 框架提供了一个完善的注册功能实现方法,...
SpringMVC的Socket实现+Java Tomcat websocket实现+Java Socket通信实现 +Java UDP通信实现。websocket_study.rar 为springMVC版本的socket实现 websocket02.rar 里面包含tomcat的websocket实现+java socket双向通信...
在这个"springMVC配置连接数据库实现登录功能的小demo"中,我们将探讨如何使用Spring MVC与Hibernate集成来处理用户登录功能。Hibernate是一个流行的ORM(对象关系映射)框架,它简化了与数据库的交互。 首先,我们...
基于springmvc+Hibernate实现的在线购物商城.zip基于springmvc+Hibernate实现的在线购物商城.zip基于springmvc+Hibernate实现的在线购物商城.zip基于springmvc+Hibernate实现的在线购物商城.zip基于springmvc+...
在结合Spring MVC和SWFUpload实现异步上传时,首先需要在前端HTML页面上配置SWFUpload插件。`index.html`文件中通常会包含SWFUpload所需的JavaScript和CSS资源,以及相关的HTML结构。JavaScript部分会初始化...
- 异步处理:在 SpringMVC 中,可以利用 @Async 注解进行异步处理,提高服务性能。 - 错误处理:设置适当的异常处理器,处理网络中断、文件不存在等异常情况。 5. **测试与部署**: - 使用单元测试验证各个组件...
在这个"SSM框架Demo"中,开发者不仅实现了基础的SSM整合,还引入了二维码生成和扫码上传图片的功能,以及ejabberd消息推送。这些功能的实现为学习者提供了丰富的实践案例,有助于深入理解SSM框架的实战运用。 1. **...
在本文中,我们将深入探讨如何使用SpringMVC和Ajax实现异步上传图片并实时显示的功能。这个技术组合常用于Web应用开发中,提供流畅的用户体验,避免页面刷新带来的不便。 首先,SpringMVC是Spring框架的一部分,专...
总的来说,“springMVC activemq简单聊天室”项目展示了如何利用SpringMVC处理Web请求,与ActiveMQ结合实现异步通信,构建一个实时、多用户交互的在线聊天系统。这种架构模式在许多实时协作应用、社交平台和企业级...