SSM实现comet4j实时消息推送

comet4j消息推送,先向项目中加入comet4j的jar包,注意有tomcat6和tomcat7的区分

tomcat中需要将conf/server.xml文件的

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

改成

    <Connector port="8080"
			   URIEncoding="UTF-8"
               connectionTimeout="20000"
			   protocol="org.apache.coyote.http11.Http11NioProtocol"
               redirectPort="8443" />

comet4j.js 及comet4j-tomcat6.jar / comet4j-tomcat7.jar 下载链接

点击打开链接


1.因为需要用到在普通的类中调用service方法,所以先放个SpringContextUtil,用来调用service方法,这里只用到了getBean(name)

package com.utils;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;


public class SpringContextUtil implements ApplicationContextAware {
	private static ApplicationContext applicationContext; 

	// 实现
	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		SpringContextUtil.applicationContext = applicationContext;
	}

	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	public static Object getBean(String name) throws BeansException {
		try {
			return applicationContext.getBean(name);
		} catch (Exception e) {
			throw new RuntimeException("获取的Bean不存在!");
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T gtBeanByName(Class<T> clazz) throws BeansException{
		try {
			char[] cs = clazz.getSimpleName().toCharArray();
			cs[0] += 32;
			return (T)applicationContext.getBean(String.valueOf(cs));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public static <T> T getBean(String name, Class<T> requiredType)
			throws BeansException {
		return applicationContext.getBean(name, requiredType);
	}

	public static boolean containsBean(String name) {
		return applicationContext.containsBean(name);
	}

	public static boolean isSingleton(String name)
			throws NoSuchBeanDefinitionException {
		return applicationContext.isSingleton(name);
	}

	public static Class<? extends Object> getType(String name)
			throws NoSuchBeanDefinitionException {
		return applicationContext.getType(name);
	}

	public static String[] getAliases(String name)
			throws NoSuchBeanDefinitionException {
		return applicationContext.getAliases(name);
	}


}

2.ApplicationContextAware需要注入

在spring-mvc.xml中配置一下

<bean id="SpringContextUtil" class="com.utils.SpringContextUtil"></bean>

3.comet4j实现的java类,需要的时候自己写方法获取数据源

package com.meeting.news.controller;

import java.util.Timer;
import java.util.TimerTask;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.comet4j.core.CometConnection;
import org.comet4j.core.CometContext;
import org.comet4j.core.CometEngine;
import org.comet4j.core.event.ConnectEvent;
import org.comet4j.core.listener.ConnectListener;

import com.meeting.news.model.CacheConstant;
import com.meeting.news.model.CacheManager;
import com.meeting.news.service.impl.NewsServiceImpl;
import com.utils.SpringContextUtil;

public class NewsComet4j2 extends ConnectListener  implements ServletContextListener {

	private static final String CHANNEL_1 = "result";
	
	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		
		// CometContext : Comet4J上下文,负责初始化配置、引擎对象、连接器对象、消息缓存等。
		CometContext context = CometContext.getInstance();
		// 注册频道,即标识哪些字段可用当成频道,用来作为向前台传送数据的“通道”
		context.registChannel(CHANNEL_1);
		
		CometEngine engine = CometContext.getInstance().getEngine();
		
		engine.addConnectListener(this);
	}

	
	
	
	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		
	}

	@Override
	public boolean handleEvent(ConnectEvent conEvent) {
		final CometConnection conn = conEvent.getConn();
		doCache(conn);
		final String connId = conn.getId();
		Timer timer = new Timer(true);
		TimerTask task = new TimerTask() {
		NewsServiceImpl newsserviceImpl = (NewsServiceImpl) SpringContextUtil.getBean("newsServiceImpl");//根据自己的项目需要写
			@Override
			public void run() {
				CometEngine engine = CometContext.getInstance().getEngine();
				if(CacheManager.getContent(connId).isExpired()){
					doCache(conn);
				}
				Long newsCount = simulateService(conn, newsserviceImpl);
				if(newsCount != 0){
					engine.sendTo(CHANNEL_1, engine.getConnection(connId), 
							newsCount);
				}
			}
		};
		timer.schedule(task, 10000, 1000*5);
		return false;
	}
	
	public void doCache(final CometConnection conn){
		Object userId = conn.getRequest().getSession().getAttribute("loginUserId");
		if(userId != null){
			CacheManager.putContent(conn.getId(), String.valueOf(userId), CacheConstant.EXPIRE_AFTER_ONE_HOUR);
		}
	}
        //这是从数据库中获取未读消息的数量,自己根据项目做调整获取数据源
	public Long simulateService(CometConnection conn,NewsServiceImpl newsService){
		Long newsCount = newsService.selectCountUnread(new Long(conn.getRequest().getSession().getAttribute("loginUserId").toString()));//根据自己项目需要自己调整修改
		if(newsCount == 0){
			return 0L;
		}
		return newsCount;
	}

}

4.在web.xml中添加listener,注意conn的配置路径,/views/center/是WebContent下页面的路径,如果不按页面路径配置会报404的错误

<!-- comet4j 消息监听 -->
	<listener>  
        <listener-class>org.comet4j.core.CometAppListener</listener-class>  
    </listener>  
    
    <listener>  
		<description>newsComet4jController</description>
        <listener-class>com.meeting.news.controller.NewsComet4j2</listener-class>
    </listener>  
    <servlet>
    	<display-name>cometServlet</display-name>
        <servlet-name>cometServlet</servlet-name>  
        <servlet-class>org.comet4j.core.CometServlet</servlet-class>  
    </servlet>  
    <servlet-mapping>  
        <servlet-name>cometServlet</servlet-name>  
        <url-pattern>/views/center/conn</url-pattern>  
    </servlet-mapping>

5.补充上面的Java类,Cache,CacheConstant,CacheManager

Cache类

package com.meeting.news.model;

public class Cache {

	private String key;
	private Object value;
	private Long timeOut;
	private boolean expired;

	public Cache() {
		super();
	}

	public Cache(String key, Object value, Long timeOut, boolean expired) {
		super();
		this.key = key;
		this.value = value;
		this.timeOut = timeOut;
		this.expired = expired;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public Object getValue() {
		return value;
	}

	public void setValue(Object value) {
		this.value = value;
	}

	public Long getTimeOut() {
		return timeOut;
	}

	public void setTimeOut(Long timeOut) {
		this.timeOut = timeOut;
	}

	public boolean isExpired() {
		return expired;
	}

	public void setExpired(boolean expired) {
		this.expired = expired;
	}

	//
}

CacheConstant类

package com.meeting.news.model;

public class CacheConstant {

	public static long EXPIRE_AFTER_ONE_HOUR = 0;//自己配置时间
}

CacheManager类

package com.meeting.news.model;

import java.util.Date;
import java.util.HashMap;

public class CacheManager {

	private static HashMap cacheMap = new HashMap<>();
	
	private CacheManager(){
		super();
	}
	
	private synchronized static Cache getCache(String key){
		return (Cache)cacheMap.get(key);
	}
	
	private synchronized static boolean hasCache(String key){
		return cacheMap.containsKey(key);
	}
	
	public synchronized static void invalidateAll(){
		cacheMap.clear();
	}
	
	public synchronized static void invalidate(String key){
		cacheMap.remove(key);
	}
	
	public synchronized static void putCache(String key,Cache object){
		cacheMap.put(key, object);
	}
	
	public static Cache getContent(String key){
		if(hasCache(key)){
			Cache cache = getCache(key);
			if(cacheExpired(cache)){
				cache.setExpired(true);
			}
			return cache;
		}else{
			return null;
		}
	}
	
	public static void putContent(String key,Object content,long ttl){
		Cache cache = new Cache();
		cache.setKey(key);
		cache.setValue(content);
		cache.setTimeOut(ttl+new Date().getTime());
		cache.setExpired(false);
		putCache(key, cache);
	}
	
	private static boolean cacheExpired(Cache cache){
		if(cache == null){
			return false;
		}
		long milisNow = new Date().getTime();
		long milisExpire = cache.getTimeOut();
		if(milisExpire < 0){
			return false;
		}else if(milisNow >= milisExpire){
			return true;
		}else{
			return false;
		}
	}
	
	
	
}

6.用的jsp

需引comet4j.js

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
			+ path;
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="<%=basePath %>/js/jquery1.8.3.min.js"></script>
<script type="text/javascript" src="<%=basePath%>/js/comet4j.js"></script>
</head>
<script type="text/javascript">
function init(){
	
	var number_1 = document.getElementById("number_1");
	JS.Engine.start("conn");
	JS.Engine.on(
		{
			result:function(res){
				number_1.innerHTML = res;
			}
		}		
	)
}
</script>
<body onload="init()">
<span id="number_1"></span>
</body>
</html>

7.comet4j.js 及comet4j-tomcat6.jar / comet4j-tomcat7.jar 下载链接

点击打开链接


8.补充一下

获取消息的top是引用的,每个页面都有,所以web.xml中配置时候路径不能固定成一个,所以就配置成了

<url-pattern>*.conn</url-pattern>
相应的页面代码也需要将conn改成.conn
JS.Engine.start(".conn");

猜你喜欢

转载自blog.csdn.net/chaijw0928/article/details/80482900