一、简介:

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 expiresreturn 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);}@Overridepublic void contextDestroyed(ServletContextEvent sce) {// TODO Auto-generated method stub}@Overridepublic boolean handleEvent(ConnectEvent connEvent) {// TODO Auto-generated method stubfinal 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 exceptionSystem.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 exceptione.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 {@Autowiredprivate DeviceAlarmService deviceAlarmService;@Autowiredprivate 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” 的值 msgStatusmsgStatus : function(msgStatus) {},// 对应服务端 “频道2” 的值 msgDatamsgData : 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);// (个推)推送消息到频道1cometUtil.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);//删除登录状态cookiewindow.location.href = "../../logout";//请求登出方法return false;}// 建立连接,conn 即web.xml中 CometServlet的<url-pattern>JS.Engine.start('../../conn');// 监听后台某个频道JS.Engine.on({// 对应服务端 “频道1” 的值 msgStatusmsgStatus : function(msgStatus) {if (msgStatus == "-1") {$.cookie("main_loginStatus", true);//true:让用户自动掉线//给用户提示(然后不管用户点击的是确定还是取消,都让他自动退出)if (confirm("您的账号在另一地点登录,您已被迫下线!")) {$.cookie("main_loginStatus", null);//删除登录状态cookiewindow.location.href = "../../logout";//请求登出方法} else {$.cookie("main_loginStatus", null);//删除登录状态cookiewindow.location.href = "../../logout";//请求登出方法}}},// 对应服务端 “频道2” 的值 msgDatamsgData : 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/CometProcessorat 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.CometProcessorat 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/CometProcessorat 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.CometProcessorat 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 ErrorType Exception ReportMessage org/apache/catalina/comet/CometProcessorDescription The server encountered an unexpected condition that prevented it from fulfilling the request.Exceptionjava.lang.NoClassDefFoundError: org/apache/catalina/comet/CometProcessorjava.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 Causejava.lang.ClassNotFoundException: org.apache.catalina.comet.CometProcessororg.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进行使用的。

Web后台向前台推送消息(comet4j的使用)相关推荐

  1. android极光推送声音,解决极光推送后台接收到推送消息,无提示音不震动

    ----以下方法前提确保你的设备,打开了此APP的通知提示. 正题------ 我遇到的情况是,安卓客户端是有提示音和振动提示的. iOS端在极光的web后台编辑消息 推送到我的手机有提示音和振动,通 ...

  2. SpringBoot 集成 webSocket,实现后台向客户端推送消息

    图文等内容参考链接 SpringBoot2.0集成WebSocket,实现后台向前端推送信息_Moshow郑锴的博客-CSDN博客_springboot websocket WebSocket 简介 ...

  3. 极光推送:java后台向APP推送消息(android,ios极光推送消息)

    Maven添加依赖 <!--极光推送--><dependency><groupId>cn.jpush.api</groupId><artifact ...

  4. iOS 点击推送消息跳转指定界面 —总结篇

    收到推送的准备: 首先至于说消息推送的原理,证书配置等等这些我在这里就不在累述,有很多写的很好的文章相信您已经可以搞定这块,这里我重点讲下各种情况下的跳转处理. 复制代码 ####点击推送触发的几个方 ...

  5. SpringBoot使用Socket向前端推送消息

    个人资源与分享网站:http://xiaocaoshare.com/ 1.对webSocket理解 WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-dup ...

  6. 友盟小米收不到推送消息_一个轻量级、可插拔的Android消息推送框架。一键集成推送(极光推送、友盟推送、华为、小米推送等)...

    XPush 一个轻量级.可插拔的Android消息推送框架.一键集成推送(极光推送.友盟推送.华为.小米推送等),提供有效的保活机制,支持推送的拓展,充分解耦推送和业务逻辑,解放你的双手! 在提iss ...

  7. Websocket实现Java后台主动推送消息到前台

    写在前面 需求: 项目测试, 缺少用户登录失败给admin推送消息, 想到这个方式, 当用户登录失败时, admin用户会在页面看到咣咣乱弹的alert. 正文 pom.xml <!-- web ...

  8. Android,ios,安卓app推送消息通知,java后台向手机推送app的通知教程

    文章目录 一.业务介绍 1.1 产品简介 1.2 名词解释 1.3 消息推送流程 二.应用创建 三.客户端 SDK 集成 3.1 Android 3.2 iOS 四.服务端推送 4.1 服务端消息下发 ...

  9. java web 服务器推送技术--comet4j

    1.背景 首先实现服务器推送技术一直一来是B/S应用开发的一块难题,因为是基于HTTP协议的,HTTP协议为无状态,单向性的协议,即,必须由客户端发起一个请求建立连接,服务器接收请求,把数据返回给客户 ...

最新文章

  1. ansys选择一个面上所有节点_如何使用ANSYS经典界面的选择工具
  2. android gradle 目录,Android Gradle:将目录列入文件
  3. 【iOS-cocos2d-X 游戏开发之四】Cocos2dX创建Android NDK新项目并编译导入Eclipse中正常运行!...
  4. 在${}中为甚么采用@Param及多参数查询@Param
  5. python字符串添加_python字符串的增删改查
  6. Golang tcp转发 remoteAddr错误
  7. 手机连接投影机的步骤_投影机安装过程详解
  8. 最新25个高质量PSD素材免费下载
  9. 日常积累--javaweb
  10. 实例详解ISA防火墙策略元素:ISA2006系列之五
  11. 累加器A用c语言,在c语言数组累加器的使用
  12. 图像处理基础与理解 随笔一 图像的内插
  13. 台式计算机怎样能搜无线连接,台式电脑怎么设置无线网络!台式电脑也能上wifi...
  14. python——利用记忆曲线制作单词计划表
  15. 安卓 输入框身份证号限制
  16. 【人事管理系统2.0 Linq to SQL】企业人事管理系统
  17. 【图数据库】GalaxyBase 查询优化之索引
  18. MFSK调制与相干解调-MATLAB基带仿真
  19. 北京某金融公司(Java开发实习生)面试及答案
  20. V880/N880/N880S USB调试模式开启方法

热门文章

  1. awk中字符串处理函数
  2. 开发对象转换组件starter——dozer
  3. 苹果PDF压缩工具:PDF Squeezer
  4. 百名经济学家企业家88%认为当前通胀情况严重
  5. ng bootstrap css,Angular2学习笔记-ng bootstrap中motal组件使用
  6. Markdown插入图片的方法
  7. 基于N32G45智能家居平台
  8. 常用python爬虫框架
  9. 关于迅雷电影的下载地址
  10. 手绘 | 深入解析风控8大场景中的机器学习应用