转,Comet4J

--------------------- 
作者:Dai_Haijiao 
来源:CSDN 
原文:https://blog.csdn.net/Dai_Haijiao/article/details/80498979 
版权声明:本文为博主原创文章,转载请附上博文链接!

--------------------- 

一、简介:

        Comet4J(Comet for Java)是一个纯粹基于AJAX(XMLHTTPRequest)的服务器推送框架,消息以JSON方式传递,具备长轮询、长连接、自动选择三种工作模式。它是一个微型的即时推送框架(类似于goeasy),它分为服务端与客户端两部分,你只要将服务器端(JAR文件,目前仅支持Tomcat6、7)放入WEB-INF\lib,客户端(JavaScript文件)引入到页面,那么你的应用就具备了向客户端推送信息的能力,而你仅需要在服务器端调用Comet4J所提供发送方法,信息就会被主动的推送到客户的浏览器上。

二、使用前准备工作:

1. 修改tomcat配置文件conf/server.xml
    修改之前为:
        <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    修改之后为:

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

2. 引入jar文件:

项目中引入comet4j-tomcat7.jar和comen4j.js(下载地址:)https://download.csdn.net/download/dai_haijiao/9985319)。

目前网上只流传有comet4j-tomcat7.jar和comet4j-tomcat6.jar两个版本,先说明一下:

若项目tomcat容器用的是tomcat7,则引用comet4j-tomcat7.jar,

若用的是tomcat6则引用comet4j-tomcat6.jar

3. 修改web.xml配置文件

        <listener>
        <description>Comet4JListener</description>
        <listener-class>org.comet4j.core.CometAppListener</listener-class>
    </listener>
    <listener>
        <description>ListenerClass</description>
        <listener-class>com.abc.tools.comet4j.CometUtil</listener-class>
    </listener>
    <servlet>
        <description>ClientEntrance</description>
        <servlet-name>CometServlet</servlet-name>
        <servlet-class>org.comet4j.core.CometServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CometServlet</servlet-name>
        <url-pattern>/conn</url-pattern>
    </servlet-mapping>
4. 创建推送工具类

    a. Comet.java

package com.abc.tools.comet4j;
 
public class Comet {
 
    /**
     * 人像布控告警
     */
    public static final String DISPATCHE_ALARM = "100001";
 
    /**
     * 设备告警
     */
    public static final String DEVICE_ALARM = "100002";
 
    /**
     * 被迫下线
     */
    public static final String FORCED_LOGOUT = "-1";
 
    private String userId = "";
 
    private String msgStatus = "";
 
    private Object msgData = new Object();
 
    public String getUserId() {
        return userId;
    }
 
    public void setUserId(String userId) {
        this.userId = userId;
    }
 
    public String getMsgStatus() {
        return msgStatus;
    }
 
    public void setMsgStatus(String msgStatus) {
        this.msgStatus = msgStatus;
    }
 
    public Object getMsgData() {
        return msgData;
    }
 
    public void setMsgData(Object msgData) {
        this.msgData = msgData;
    }
 
}
    b.Constant.java

package com.abc.tools.comet4j;
 
public class Constant {
 
    public static long EXPIRE_AFTER_ONE_HOUR = 30; // cache过期时间
 
    public static String CHANNEL_MSGSTATUS = "msgStatus";
 
    public static String CHANNEL_MSG_DATA = "msgData";
}
    c. Cache.java

package com.abc.tools.comet4j;
 
public class Cache {
 
    private String key;
 
    private Object value;
 
    private long timeOut;
 
    private boolean expired;
 
    public Cache() {
        super();
    }
 
    public Cache(String key, String value, long timeOut, boolean expired) {
        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;
    }
 
}
    d. CacheManager.java

package com.abc.tools.comet4j;
 
import java.util.Date;
import java.util.HashMap;
 
public class CacheManager {
 
    @SuppressWarnings("rawtypes")
    private static HashMap cacheMap = new HashMap();
 
    /**
     * This class is singleton so private constructor is used.
     */
    private CacheManager() {
        super();
    }
 
    /**
     * returns cache item from hashmap
     * 
     * @param key
     * @return Cache
     */
    private synchronized static Cache getCache(String key) {
        return (Cache) cacheMap.get(key);
    }
 
    /**
     * Looks at the hashmap if a cache item exists or not
     * 
     * @param key
     * @return Cache
     */
    private synchronized static boolean hasCache(String key) {
        return cacheMap.containsKey(key);
    }
 
    /**
     * Invalidates all cache
     */
    public synchronized static void invalidateAll() {
        cacheMap.clear();
    }
 
    /**
     * Invalidates a single cache item
     * 
     * @param key
     */
    public synchronized static void invalidate(String key) {
        cacheMap.remove(key);
    }
 
    /**
     * Adds new item to cache hashmap
     * 
     * @param key
     * @return Cache
     */
    @SuppressWarnings("unchecked")
    private synchronized static void putCache(String key, Cache object) {
        cacheMap.put(key, object);
    }
 
    /**
     * Reads a cache item's content
     * 
     * @param key
     * @return
     */
    public static Cache getContent(String key) {
        if (hasCache(key)) {
            Cache cache = getCache(key);
            if (cacheExpired(cache)) {
                cache.setExpired(true);
            }
            return cache;
        } else {
            return null;
        }
    }
 
    /**
     * 
     * @param key
     * @param content
     * @param ttl
     */
    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);
    }
 
    public static void putContent(String key, Object content) {
        Cache cache = new Cache();
        cache.setKey(key);
        cache.setValue(content);
        cache.setExpired(false);
        putCache(key, cache);
    }
 
    /** @modelguid {172828D6-3AB2-46C4-96E2-E72B34264031} */
    private static boolean cacheExpired(Cache cache) {
        if (cache == null) {
            return false;
        }
        long milisNow = new Date().getTime();
        long milisExpire = cache.getTimeOut();
        if (milisExpire < 0) { // Cache never expires
            return false;
        } else if (milisNow >= milisExpire) {
            return true;
        } else {
            return false;
        }
    }
}
e. CometUtil.java

package com.abc.tools.comet4j;
 
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;
 
public class CometUtil extends ConnectListener implements ServletContextListener {
    /**
     * 初始化上下文
     */
    public void contextInitialized(ServletContextEvent arg0) {
        // CometContext : Comet4J上下文,负责初始化配置、引擎对象、连接器对象、消息缓存等。
        CometContext cc = CometContext.getInstance();
        // 注册频道,即标识哪些字段可用当成频道,用来作为向前台传送数据的“通道”
        cc.registChannel(Constant.CHANNEL_MSGSTATUS);
        cc.registChannel(Constant.CHANNEL_MSG_DATA);
        // 添加监听器
        CometEngine engine = CometContext.getInstance().getEngine();
        engine.addConnectListener(this);
    }
 
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub
    }
 
    @Override
    public boolean handleEvent(ConnectEvent connEvent) {
        // TODO Auto-generated method stub
        final CometConnection conn = connEvent.getConn();
        Object userId = conn.getRequest().getSession().getAttribute("userId");// userId是当前登录用户的id,用户登录成功后存于session中
        if (null == userId) {
            return false;
        }
        CacheManager.putContent(userId.toString(), connEvent);
        return true;
    }
 
    private void doCache(final CometConnection conn, String userId) {
        if (userId != null) {
            CacheManager.putContent(conn.getId(), String.valueOf(userId), Constant.EXPIRE_AFTER_ONE_HOUR);
        }
    }
 
    /**
     * 推送给所有的客户端
     * 
     * @param comet
     */
    public void pushToAll(Comet comet) {
        try {
            CometEngine engine = CometContext.getInstance().getEngine();
            // 推送到所有客户端
            engine.sendToAll(Constant.CHANNEL_MSGSTATUS, comet.getMsgStatus());
            engine.sendToAll(Constant.CHANNEL_MSG_DATA, comet.getMsgData());
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println(e.getMessage());
        }
 
    }
 
    /**
     * 推送给指定客户端
     * 
     * @param comet
     */
    public void pushTo(Comet comet) {
        try {
            Cache cache = CacheManager.getContent(comet.getUserId());
            if (null == cache) {
                return;
            }
            ConnectEvent connEvent = (ConnectEvent) cache.getValue();
            final CometConnection conn = connEvent.getConn();
            // 建立连接和用户的关系
            doCache(conn, comet.getUserId());
            final String connId = conn.getId();
            CometEngine engine = CometContext.getInstance().getEngine();
            if (CacheManager.getContent(connId).isExpired()) {
                doCache(conn, comet.getUserId());
            }
            // 推送到指定的客户端
            engine.sendTo(Constant.CHANNEL_MSGSTATUS, engine.getConnection(connId), comet.getMsgStatus());
            engine.sendTo(Constant.CHANNEL_MSG_DATA, engine.getConnection(connId), comet.getMsgData());
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}


三、后台进行推送实例

用法1(进行消息推送):

后台代码

package com.abc.controller.univiewinterface;
 
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
 
import com.abc.entity.DeviceAlarm;
import com.abc.entity.DispatcheAlarm;
import com.abc.entity.Result;
import com.abc.service.DeviceAlarmService;
import com.abc.service.DispatcheAlarmService;
import com.abc.tools.comet4j.Comet;
import com.abc.tools.comet4j.CometUtil;
 
import net.sf.json.JSONObject;
 
/**
 * 告警控制层
 * 
 * @author DaiHaijiao
 *
 */
@Controller
@RequestMapping("/alarm/*")
public class AlarmController {
 
    @Autowired
    private DeviceAlarmService deviceAlarmService;
 
    @Autowired
    private DispatcheAlarmService dispatcheAlarmService;
 
    private static Map<String, Object> map = null;
 
    private static CometUtil cometUtil = null;
 
    /**
     * 设备告警
     * 
     * @param param
     */
    @SuppressWarnings("unlikely-arg-type")
    @RequestMapping(value = "common.do", method = RequestMethod.POST, consumes = "application/json")
    public @ResponseBody Result commonAlarm(@RequestBody String param) {
        JSONObject json = JSONObject.fromObject(param);
        // 保存设备告警到本地数据库
        DeviceAlarm deviceAlarm = new DeviceAlarm();
        String alarmContet = json.getString("contet");
        deviceAlarm.setContent(alarmContet);// 告警内容
        String alarmTime = json.getString("time");
        deviceAlarm.setTime(alarmTime);// 告警时间
        deviceAlarm = deviceAlarmService.add(deviceAlarm);
        // 实例化消息推送类
        if (cometUtil == null) {
            cometUtil = new CometUtil();
        }
        // 进行推送消息设置
        map.put("id", deviceAlarm.getId() + "");
        map.put("msgStatus", Comet.DEVICE_ALARM);
        map.put("content", alarmContet);
        map.put("time", alarmTime);
        // 推送消息到所有用户
        Comet comet = new Comet();
        comet.setMsgStatus(Comet.DEVICE_ALARM);
        comet.setMsgData(map);
        cometUtil.pushToAll(comet);
        return Result.genSuccess();
    }
 
    /**
     * 布控告警
     * 
     * @param param
     */
    @SuppressWarnings("unlikely-arg-type")
    @RequestMapping(value = "faceSurveillance.do", method = RequestMethod.POST, consumes = "application/json")
    public @ResponseBody Result faceSurveillanceAlarm(@RequestBody String param) {
        JSONObject json = JSONObject.fromObject(param);
        // 保存布控告警到本地数据库
        DispatcheAlarm dispatcheAlarm = new DispatcheAlarm();
        String alarmTime = json.getString("time");// 告警时间
        String alarmContet = json.getString("contet");// 告警内容
        String userId = json.getString("userId");// 要推送的用户
        dispatcheAlarm.setContent(alarmContet);
        dispatcheAlarm.setTime(alarmTime);
        dispatcheAlarm = dispatcheAlarmService.add(dispatcheAlarm);
        // 实例化消息推送类
        if (cometUtil == null) {
            cometUtil = new CometUtil();
        }
        // 进行推送消息设置
        map = new HashMap<String, Object>();
        map.put("id", dispatcheAlarm.getId() + "");
        map.put("msgStatus", Comet.DISPATCHE_ALARM);
        map.put("content", alarmContet);
        map.put("time", alarmTime);
        // 推送消息到指定用户
        Comet comet = new Comet();
        comet.setUserId(userId);
        comet.setMsgStatus(Comet.DISPATCHE_ALARM);
        comet.setMsgData(map);
        cometUtil.pushTo(comet);
        return Result.genSuccess();
    }
 
}
页面接收消息       

     接收前准备:页面引入

    <script type="text/javascript" src="../js/comet4j.js"></script>
    在页面初始化js里增加消息接收相关代码,效果如下:

    $(function() {
        //...
        //...Something...
        //...
 
        // 建立连接,conn 即web.xml中 CometServlet的<url-pattern>
        JS.Engine.start('../../conn');//根据自己项目情况进行修改
        // 监听后台某个频道
        JS.Engine.on({
            // 对应服务端 “频道1” 的值 msgStatus
            msgStatus : function(msgStatus) {
                              
            },
            // 对应服务端 “频道2” 的值 msgData
            msgData : function(msgData) {
                if (msgData.msgStatus == "100001") {//布控告警
                    var id = msgData.id;
                    var content = msgData.content;
                    var time = msgData.time;
                    //...值已经拿到
                    //...To do something
                    //...
                } else if (msgData.msgStatus == "100002") {//设备告警
                    var id = msgData.id;
                    var content = msgData.content;
                    var time = msgData.time;
                    //...值已经拿到
                    //...To do something
                    //...
                }
            },
        });
 
        //...
        //...Something...
        //...
    })
用法2(实现同一个账号只能在一个地方登陆):
    后台代码

        /**
     * 用户登录
     *
     * @param username
     * @param password
     * @return Result
     */
    @RequestMapping(value = "login.do")
    public @ResponseBody Result login(String username, HttpSession session, String password) {
        try {
            //用户登录
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            token.setRememberMe(true);
            subject.login(token);
            Object userId = (User) subject.getPrincipal().getId();
 
            CometUtil cometUtil = new CometUtil();// 实例化消息推送类
            // set值
            Comet comet = new Comet();
            comet.setUserId(userId + "");
            comet.setMsgStatus(Comet.FORCED_LOGOUT);
            // (个推)推送消息到频道1
            cometUtil.pushTo(comet);
 
            session.setAttribute("userId", userId);//登录成功后session中放入userId(个推用)
            return Result.genSuccess();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.genResult(Result.USER_PASSWORD_WRONG);
        }
    }
页面代码(页面除了需要引用comet4j.js还有引入jquery.cookie.js)

增加cookie是为了避免用户收到"您的账号在另一地点登录,您已被迫下线!"提示以后直接刷新页面!

        $(function() {
        var loginStatus = $.cookie("main_loginStatus");//登录状态
        if (typeof (loginStatus) == "undefined") {
            $.cookie("main_loginStatus", false);//false:用户不掉线标识
        } else if (loginStatus == true || loginStatus == "true") {
            $.cookie("main_loginStatus", null);//删除登录状态cookie
            window.location.href = "../../logout";//请求登出方法
            return false;
        }
 
        // 建立连接,conn 即web.xml中 CometServlet的<url-pattern>
        JS.Engine.start('../../conn');
        // 监听后台某个频道
        JS.Engine.on({
            // 对应服务端 “频道1” 的值 msgStatus
            msgStatus : function(msgStatus) {
                if (msgStatus == "-1") {
                    $.cookie("main_loginStatus", true);//true:让用户自动掉线
                    
                    //给用户提示(然后不管用户点击的是确定还是取消,都让他自动退出)
                    if (confirm("您的账号在另一地点登录,您已被迫下线!")) {
                        $.cookie("main_loginStatus", null);//删除登录状态cookie
                        window.location.href = "../../logout";//请求登出方法
                    } else {
                        $.cookie("main_loginStatus", null);//删除登录状态cookie
                        window.location.href = "../../logout";//请求登出方法
                    }
                }
            },
            // 对应服务端 “频道2” 的值 msgData
            msgData : function(msgData) {
                 
            },
        });
    })
用法3(自行去研究...)

四、使用中发现

1. 项目中引入comet4j-tomcat7.jar,且tomcat为8.0.X时,使用一切正常,“F12”查看控制台的“Network”,会发现“conn?cmd=conn&cv=0.0.2&ram=0.7725908122133494”访问正常,点击进去,控制台显示:

<{data:{channel:["msgStatus","msgData"],ws:"stream",timeout:60000,cld:"08be33b1-c409-4177-ba79-74e551379923"},channel:"",time:"1527580183535}">
2. 项目中引入comet4j-tomcat7.jar,且tomcat为8.5.X时,eclipse控制台会报错,信息如下:

五月 29, 2018 4:14:31 下午 org.apache.catalina.core.StandardHostValve invoke
严重: Exception Processing /conn
java.lang.NoClassDefFoundError: org/apache/catalina/comet/CometProcessor
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2277)
    at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:811)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1254)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    at org.apache.catalina.core.StandardWrapper.servletSecurityAnnotationScan(StandardWrapper.java:1128)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.catalina.comet.CometProcessor
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1285)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    ... 23 more

五月 29, 2018 4:16:27 下午 org.apache.catalina.core.StandardHostValve invoke
严重: Exception Processing /conn
java.lang.NoClassDefFoundError: org/apache/catalina/comet/CometProcessor
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2277)
    at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:811)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1254)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    at org.apache.catalina.core.StandardWrapper.servletSecurityAnnotationScan(StandardWrapper.java:1128)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.apache.catalina.comet.CometProcessor
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1285)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    ... 23 more
“F12”查看控制台的“Network”,会发现“conn?cmd=conn&cv=0.0.2&ram=0.7725908122133494”有“500”错误,点击进去,控制台显示如同eclipse控制台所报错误信息:

HTTP Status 500 – Internal Server Error

Type Exception Report

Message org/apache/catalina/comet/CometProcessor

Description The server encountered an unexpected condition that prevented it from fulfilling the request.

Exception

java.lang.NoClassDefFoundError: org/apache/catalina/comet/CometProcessor
    java.lang.ClassLoader.defineClass1(Native Method)
    java.lang.ClassLoader.defineClass(Unknown Source)
    java.security.SecureClassLoader.defineClass(Unknown Source)
    org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2277)
    org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:811)
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1254)
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Unknown Source)
Root Cause

java.lang.ClassNotFoundException: org.apache.catalina.comet.CometProcessor
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1285)
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    java.lang.ClassLoader.defineClass1(Native Method)
    java.lang.ClassLoader.defineClass(Unknown Source)
    java.security.SecureClassLoader.defineClass(Unknown Source)
    org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2277)
    org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:811)
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1254)
    org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Unknown Source)
Note The full stack trace of the root cause is available in the server logs.
综上,总结出:tomcat8.0.X版本是可以结合comet4j-tomcat7.jar进行使用的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Comet4J(Comet for Java)是一个纯粹基于AJAX(XMLHTTPRequest)的服务器推送框架,消息以JSON方式传递,具备长轮询、长连接、自动选择三种工作模式。 功能特性 推送消息广播。 推送定向消息。 提供连接上线前、上线、下线前、下线、发送消息等多种可处理事件。 消息缓存机制,确保长轮询工作模式下不丢失消息。 客户端正常下线,服务端可立即感知。 客户端异常停止工作,服务端可定时检查并感知。 以注册通道应用的方式,让开发者对框架功能进行扩展,实现自己的应用。 框架特性 独立小巧,不依赖于第三方包。 与应用紧密集成,无需独立应用或服务器。 与Session无关的连接机制,为开发人员提供最大程度的功能可控性。 面向事件编程,客户端与服务器端均为事件驱动开发模式,提供了良好的可扩展性机制。 各项性能参数均可配置。 支持多种主流浏览器,并支持Air应用环境。 服务器支持情况 Tomcat6、Tomcat7 浏览器支持情况 支持XMLHTTPRequest对象的浏览器均可支持长轮询工作模式,但不一定能够支持长连接。 | 浏览器/平台 | 版本 | 长轮询 | 长连接 | |:-----------|:-------|:--------|:--------| | Internet Explorer | 6,7,8,9 | √ | X | | FireFox | 3.0+(更底版本未知) | √ | √ | | Chrome | 7.0+(更底版本未知) | √ | √ | | Safari | 5+(更底版本未知) | √ | √ | | Opera | 11.10+(更底版本未知) | √ | X | | Air | 1.5+(更底版本未知) | √ | √ | | IOS(Iphone/Ipad)| 3.1+(更底版本未知) | √ | √ | | Android | 未测试 | 未知 | 未知 | | BlackBerry | 未测试 | 未知 | 未知 |

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值