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() {
@Override
public void run() {
CometEngine engine = CometContext.getInstance().getEngine();
if(CacheManager.getContent(connId).isExpired()){
doCache(conn);
}
Long newsCount = simulateService(conn);
if(newsCount != 0){
engine.sendTo(CHANNEL_1, engine.getConnection(connId),
newsCount);
}
}
};
timer.schedule(task, 1000, 1000*2);
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 = (NewsServiceImpl) SpringContextUtil.getBean("newsServiceImpl");
return newsService.selectCountUnread(new Long(conn.getRequest().getSession().getAttribute("loginUserId").toString()));
}
}
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 οnlοad="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");