1、web.xml配置支持异步消息:
<servlet>
	<servlet-name>dispatcherServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:springMVC.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
	<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
	<servlet-name>dispatcherServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>




2、客户端代码:

<script type="text/javascript">
var sendId ="";
var isReceiver = false;
function longPolling() {
	if(isReceiver) {
		$.ajax({
			url : "../longPolling/customer/receive",
			data : {"receiverId" : "123", "time" : new Date()},
			dataType : "json",
			type : "POST",
			success : function(data) {
				console.log(data);
				if(data.code == "success"){
					var $tbody = "";
					$.each(data.data, function(index, value) {
						var $tr = "";
						$tr += "<tr><td>"+value.receiverId+"</td><td>"+value.sendId+"</td><td>"+value.context+"</td><td>"+value.date+"</td></tr>"
						$tbody += $tr;
					});
					$("#message").append($tbody);
				} 
				longPolling();
			},
			error : function(XMLHttpRequest) {
				console.log(XMLHttpRequest.status);
				if (XMLHttpRequest.status == "500") {	 //超时
					longPolling();
				} else {
					isReceiver = false;
				}
			}
		});
	}
}
$(function(){
	$('#startReceive').click(function() {
		isReceiver = true;
		longPolling();
	});
	$("#startSend").click(function() {
		//alert("123");
		$.ajax({
			url : "../common/createId",
			type : "post",
			dataType : "json",
			data : {"time" : new Date()},
		    success : function(msg) {
 				console.log(msg);
				sendId = msg.data;
			}, 
			error : function() {
			}
		});
	});
	$("#send").click(function() {
		if(sendId != "") {
			var context = $("#sendMessage").val();
			//alert(text);
			$.ajax({
				url : "../longPolling/customer/send",
				type : "post",
				dataType : "json",
				data : {
					"receiverId" : "123", "sendId" : sendId, "context" : context, "time" : new Date()
				},
			 	success : function(msg) {
					console.log(msg);
					$("#sendMessage").val("");
				}, 
				error : function() {}
			});
		} else {
			alert("请先点击开始!");
		}
	});	
	
	window.onbeforeunload = function() {
		isReceiver = false;
		$.ajax({
			url : "../longPolling/customer/clear",
			type : "post",
			dataType : "json",
			data : {
				"receiverId" : "123", "time" : new Date()
			},
		 	success : function(msg) {
				console.log(msg);
			}, 
			error : function() {}
		});
	}
})
</script>
</head>
<body>
<button id="startSend">开始</button><br><br>
<input type="text" id="sendMessage"/><button id = "send">发送</button>
<br>
<button id = "startReceive">startReceive</button>
<table id ="message"></table>
</body>


3、控制层代码:

推送消息接口:

public DeferredResult<ResultDTO> receiverMessage(final String receiverId) {
		DeferredResult<ResultDTO> result = new DeferredResult<ResultDTO>(90000L);
		/**
		 * http连接先查询仓库中是否有消息
		 */
		Integer messageSize = longCustomerService.countReceiverMessageNum(receiverId);
		SysoutLogUtil.log(messageSize);
		if(messageSize > 0){
			result.setResult(new ResultDTO("success", "", longCustomerService.listMessage(receiverId)));
		}
		
		longCustomerService.saveReceiverRequest(receiverId, result);
		result.onCompletion(new Runnable() {
			@Override
			public void run() {
				longCustomerService.removeReceiverRequest(receiverId);			
			}
		});
		SysoutLogUtil.log("获取到"+messageSize+"条消息");
		return result;
	}
发送消息接口:

	public Object sendMessage(String receiverId, String sendId, String context) {
		MessageDO message = new MessageDO(receiverId, sendId, context);
		longCustomerService.saveMessage(message);
		return new ResultDTO("success");
	}

浏览器刷新接口:

	public Object clearRequest(String receiverId){
		SysoutLogUtil.log("调用了刷新接口"+receiverId +"end");
		longCustomerService.removeReceiverRequest(receiverId);
		return new ResultDTO("success");
	}

4、Service层代码:

private static Map<String, DeferredResult<ResultDTO>> receiverRequest = new ConcurrentHashMap<String, DeferredResult<ResultDTO>>();
	
	private static ConcurrentHashMap<String, ConcurrentLinkedQueue<MessageDO>> repository = new ConcurrentHashMap<>();
	
	@Override
	public void saveMessage(MessageDO message) {
		String receiverId = message.getReceiverId();
		/**
		 * 检测是否有http连接
		 */
		DeferredResult<ResultDTO> result = receiverRequest.get(receiverId);
		if(result != null){
			SysoutLogUtil.log("有http连接,直接输出消息!");
			List<MessageDO> receiverMessage = new ArrayList<>();
			receiverMessage.add(message);
			result.setResult(new ResultDTO("success", "", receiverMessage));
			return;
		}
		/**
		 * 没有http连接入库
		 */
		ConcurrentLinkedQueue<MessageDO> messageQueue = repository.get(receiverId);
		if(messageQueue == null){
			messageQueue = new ConcurrentLinkedQueue<>();
			messageQueue.add(message);
		} else {
			messageQueue.add(message);	
		}
		SysoutLogUtil.log(messageQueue.size());
		repository.put(receiverId, messageQueue);
	}

	@Override
	public List<MessageDO> listMessage(String receiverId) {
		List<MessageDO> receiverMessage = new ArrayList<>();
		ConcurrentLinkedQueue<MessageDO> messageQueue = repository.get(receiverId);
		if(messageQueue == null){
			return null;
		} else {
			while (messageQueue.peek() != null) {
				receiverMessage.add(messageQueue.poll());
			}
		}
		return receiverMessage;
	}

	@Override
	public Integer countReceiverMessageNum(String receiverId) {
		ConcurrentLinkedQueue<MessageDO> messageQueue = repository.get(receiverId);
		if(messageQueue == null){
			return 0;
		} else {
			return messageQueue.size();	
		}
	}

	@Override
	public void saveReceiverRequest(String receiverId, DeferredResult<ResultDTO> Object) {
		receiverRequest.put(receiverId, Object);
	}

	@Override
	public void removeReceiverRequest(String receiverId) {
		SysoutLogUtil.log("删除"+receiverId+"的连接");
		receiverRequest.remove(receiverId);
	}

就这样完了。。。










Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐