`
chenshangge
  • 浏览: 87845 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类

SpringMVC 异步(长轮询)实现消息定点推送

阅读更多
$(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聊天

使用支付宝扫描上方二维码领取红包

 

  • 大小: 6.3 KB
分享到:
评论

相关推荐

    springMVC+dwr技术实现消息推送实例

    通过这个实例,你可以了解到如何利用SpringMVC处理业务逻辑,以及如何借助DWR实现从服务器到客户端的实时消息推送。理解这两个技术的结合,对于构建现代、交互性强的Web应用是非常有价值的。同时,这也是对传统HTTP...

    springMvc + dwr 注解 实现消息推送

    总结起来,"springMvc + dwr 注解 实现消息推送"项目利用了Spring MVC的注解驱动开发和DWR的双向通信能力,为Web应用提供了一种高效且易于实施的消息推送解决方案。这种方案减少了配置工作,使开发者能更专注于业务...

    SpringMVC整合websocket实现消息推送及触发功能

    SpringMVC整合websocket实现消息推送及触发功能 SpringMVC是一种流行的基于Java的Web应用程序框架,而websocket是一种实时通信协议,用于实现实时的双向通信。本文将详细介绍如何使用SpringMVC与websocket实现消息...

    SpringMVC+Ajax异步文件上传

    在本教程中,我们将探讨如何结合`SpringMVC`和`Ajax`来实现异步文件上传,并讨论短视频背景以及`a`标签绑定文件域的相关知识。 1. **SpringMVC中的文件上传** - **MultipartFile接口**:`SpringMVC`提供了一个名为...

    SpringMVC 异步 数据返回后台模型

    下面是一个简单的例子,展示了如何在SpringMVC中实现异步JSON返回: ```java import org.springframework.web.bind.annotation.*; import org.springframework.scheduling.annotation.Async; import org.spring...

    ActiveMq+SpringMVC实现邮件异步发送

    在本项目中,ActiveMQ与SpringMVC框架结合,实现了邮件的异步发送功能。 首先,我们需要理解ActiveMQ的基本概念。ActiveMQ是Apache软件基金会的产品,遵循JMS(Java消息服务)规范,支持多种协议,并且可以跨平台...

    webSocket 消息推送

    WebSocket是一种在客户端和服务器之间建立长连接的协议,它允许双方进行实时、双向的数据通信,极大地优化了Web应用中的消息推送。与传统的HTTP协议不同,WebSocket在建立连接后,通信双方不再需要通过频繁的HTTP...

    springmvc+mybatis整合websocke推送

    总结来说,"springmvc+mybatis整合websocke推送"意味着将WebSocket的实时通信能力与Spring MVC的MVC架构和MyBatis的持久层操作结合,构建出能够高效推送数据的Web应用。这个过程中,你需要理解WebSocket的工作原理,...

    JAVA整合WebSocket实现服务器消息推送(项目源码)

    1、项目需要,定时向所有在线用户推送一个广告或是推送一个通知之类的(比如服务器升级,请保存好手头工作之类的)。 2、相关环境 , Nginx、tomcat7、centos 6.5 3、项目框架,springMvc 4.0.6、layer

    SpringMVC使用MultipartFile 实现异步上传方法介绍

    SpringMVC使用MultipartFile 实现异步上传方法介绍 SpringMVC是Java web开发中常用的框架之一,它提供了许多实用的功能和组件,例如MultipartFile,可以用来实现文件上传功能。异步上传是现代Web应用程序中常用的...

    Java基于Spring+SpringMVC+MyBatis实现的学生信息管理系统源码.zip

    Java基于Spring+SpringMVC+MyBatis实现的学生信息管理系统源码,SSM+Vue的学生管理系统。 Java基于Spring+SpringMVC+MyBatis实现的学生信息管理系统源码,SSM+Vue的学生管理系统。 Java基于Spring+SpringMVC+...

    SpringMVC注册功能的实现.docx

    在 SpringMVC 框架中,我们需要在 `applicationContext.xml` 文件中配置数据库连接信息,创建 sqlSession 工厂,实现 dao 层及 service 层的动态代理。 结论 SpringMVC 框架提供了一个完善的注册功能实现方法,...

    SpringMVC的Socket实现+Java Tomcat websocket实现+Java Socket通信实现 +Java UDP通信实现

    SpringMVC的Socket实现+Java Tomcat websocket实现+Java Socket通信实现 +Java UDP通信实现。websocket_study.rar 为springMVC版本的socket实现 websocket02.rar 里面包含tomcat的websocket实现+java socket双向通信...

    springMVC配置连接数据库实现登录功能的一个小demo

    在这个"springMVC配置连接数据库实现登录功能的小demo"中,我们将探讨如何使用Spring MVC与Hibernate集成来处理用户登录功能。Hibernate是一个流行的ORM(对象关系映射)框架,它简化了与数据库的交互。 首先,我们...

    基于SpringMVC+Hibernate实现的在线购物商城.zip

    基于springmvc+Hibernate实现的在线购物商城.zip基于springmvc+Hibernate实现的在线购物商城.zip基于springmvc+Hibernate实现的在线购物商城.zip基于springmvc+Hibernate实现的在线购物商城.zip基于springmvc+...

    SpringMvc+SWFUpload实现文件异步上传

    在结合Spring MVC和SWFUpload实现异步上传时,首先需要在前端HTML页面上配置SWFUpload插件。`index.html`文件中通常会包含SWFUpload所需的JavaScript和CSS资源,以及相关的HTML结构。JavaScript部分会初始化...

    netty整合SpringMVC实现下载

    - 异步处理:在 SpringMVC 中,可以利用 @Async 注解进行异步处理,提高服务性能。 - 错误处理:设置适当的异常处理器,处理网络中断、文件不存在等异常情况。 5. **测试与部署**: - 使用单元测试验证各个组件...

    SSM框架Demo并包含扫码上传,ejabberd消息推送

    在这个"SSM框架Demo"中,开发者不仅实现了基础的SSM整合,还引入了二维码生成和扫码上传图片的功能,以及ejabberd消息推送。这些功能的实现为学习者提供了丰富的实践案例,有助于深入理解SSM框架的实战运用。 1. **...

    SpringMVC+Ajax异步上传图片并显示(源码)

    在本文中,我们将深入探讨如何使用SpringMVC和Ajax实现异步上传图片并实时显示的功能。这个技术组合常用于Web应用开发中,提供流畅的用户体验,避免页面刷新带来的不便。 首先,SpringMVC是Spring框架的一部分,专...

    springMVC activemq简单聊天室

    总的来说,“springMVC activemq简单聊天室”项目展示了如何利用SpringMVC处理Web请求,与ActiveMQ结合实现异步通信,构建一个实时、多用户交互的在线聊天系统。这种架构模式在许多实时协作应用、社交平台和企业级...

Global site tag (gtag.js) - Google Analytics