范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Springwebsocketquartz实现消息定时推送

  简单的说,websocket是真正实现了全双工通信的服务器向客户端推的互联网技术。
  全双工与单工、半双工的区别? 全双工:简单地说,就是可以同时进行信号的双向传输(A->B且B->A),是瞬时同步的。 单工、半双工:一个时间段内只有一个动作发生。
  推送和拉取的区别? 推:由服务器主动发消息给客户端,就像广播。优势在于,信息的主动性和及时性。 拉:由客户端主动请求所需要的数据。
  实现消息通信的几种方式? 传统的http协议实现方式:。 传统的socket技术。 websocket协议实现方式。
  接下来我们主要讲第三种,使用websocket协议,来实现服务端定时向客户端推送消息。 开发环境:jdk1.8、tomcat7 后台:springmvc、websocket、quartz 前台:html5中新增的API 开发工具:IDEA、maven 实现步骤一、环境搭建(1)导入相关约束:
  在pom文件中加入需要的约束,spring相关的约束,请各位自己导入,这里我就不贴出来了。             org.quartz-scheduler       quartz       2.3.0                  org.springframework       spring-context-support       5.1.1.RELEASE                  javax.websocket       javax.websocket-api       1.1       provided            (2)配置xml文件
  web.xml中就配置前端控制器,大家自行配置。然后,加载springmvc的配置文件。
  springmvc.xml文件中                                                                                                                                                               text/html;charset=UTF-8                         application/json                                                                                                     WriteMapNullValue                         QuoteFieldNames                                                                 
  到此,环境就基本搭建完成了。 二、完成后台的功能
  这里我就直接贴出代码了,上面有相关的注释。
  首先,完成websocket的实现类。 package com.socket.web.socket;  import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component;  import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap;  /**  * @Author: 清风一阵吹我心  * @ProjectName: socket  * @Package: com.socket.web.socket  * @ClassName: WebSocketServer  * @Description:  * @Version: 1.0  **/ //ServerEndpoint它的功能主要是将目前的类定义成一个websocket服务器端。注解的值将被用于监听用户连接的终端访问URL地址。 @ServerEndpoint(value = "/socket/{ip}") @Component public class WebSocketServer {      //使用slf4j打日志     private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);      //用来记录当前在线连接数     private static int onLineCount = 0;      //用来存放每个客户端对应的WebSocketServer对象     private static ConcurrentHashMap webSocketMap = new ConcurrentHashMap();      //某个客户端的连接会话,需要通过它来给客户端发送数据     private Session session;      //客户端的ip地址     private String ip;      /**      * 连接建立成功,调用的方法,与前台页面的onOpen相对应      * @param ip ip地址      * @param session 会话      */     @OnOpen     public void onOpen(@PathParam("ip")String ip,Session session){         //根据业务,自定义逻辑实现         this.session = session;         this.ip = ip;         webSocketMap.put(ip,this);  //将当前对象放入map中         addOnLineCount();  //在线人数加一         LOGGER.info("有新的连接加入,ip:{}!当前在线人数:{}",ip,getOnLineCount());     }      /**      * 连接关闭调用的方法,与前台页面的onClose相对应      * @param ip      */     @OnClose     public void onClose(@PathParam("ip")String ip){         webSocketMap.remove(ip);  //根据ip(key)移除WebSocketServer对象         subOnLineCount();         LOGGER.info("WebSocket关闭,ip:{},当前在线人数:{}",ip,getOnLineCount());     }      /**      * 当服务器接收到客户端发送的消息时所调用的方法,与前台页面的onMessage相对应      * @param message      * @param session      */     @OnMessage     public void onMessage(String message,Session session){         //根据业务,自定义逻辑实现         LOGGER.info("收到客户端的消息:{}",message);     }      /**      * 发生错误时调用,与前台页面的onError相对应      * @param session      * @param error      */     @OnError     public void onError(Session session,Throwable error){         LOGGER.error("WebSocket发生错误");         error.printStackTrace();     }       /**      * 给当前用户发送消息      * @param message      */     public void sendMessage(String message){         try{             //getBasicRemote()是同步发送消息,这里我就用这个了,推荐大家使用getAsyncRemote()异步             this.session.getBasicRemote().sendText(message);         }catch (IOException e){             e.printStackTrace();             LOGGER.info("发送数据错误:,ip:{},message:{}",ip,message);         }     }      /**      * 给所有用户发消息      * @param message      */     public static void sendMessageAll(final String message){         //使用entrySet而不是用keySet的原因是,entrySet体现了map的映射关系,遍历获取数据更快。         Set> entries = webSocketMap.entrySet();         for (Map.Entry entry : entries) {             final WebSocketServer webSocketServer = entry.getValue();             //这里使用线程来控制消息的发送,这样效率更高。             new Thread(new Runnable() {                 public void run() {                     webSocketServer.sendMessage(message);                 }             }).start();         }     }      /**      * 获取当前的连接数      * @return      */     public static synchronized int getOnLineCount(){         return WebSocketServer.onLineCount;     }      /**      * 有新的用户连接时,连接数自加1      */     public static synchronized void addOnLineCount(){         WebSocketServer.onLineCount++;     }      /**      * 断开连接时,连接数自减1      */     public static synchronized void subOnLineCount(){         WebSocketServer.onLineCount--;     }      public Session getSession(){         return session;     }     public void setSession(Session session){         this.session = session;     }      public static ConcurrentHashMap getWebSocketMap() {         return webSocketMap;     }      public static void setWebSocketMap(ConcurrentHashMap webSocketMap) {         WebSocketServer.webSocketMap = webSocketMap;     } }
  然后写我们的定时器(quartz),这里我就不详解定时器了。大家可以自行去了解。
  这里我使用的是xml注解的方式,创建一个job类,此类不需要继承任何类和实现任何接口。 package com.socket.web.quartz;  import com.socket.web.socket.WebSocketServer;  import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap;  /**  * @Author: 清风一阵吹我心  * @ProjectName: socket  * @Package: com.socket.web.quartz  * @ClassName: TestJob  * @Description:  * @Version: 1.0  **/ public class TestJob {      public void task(){         //获取WebSocketServer对象的映射。         ConcurrentHashMap map = WebSocketServer.getWebSocketMap();         if (map.size() != 0){             for (Map.Entry entry : map.entrySet()) {                 WebSocketServer webSocketServer = entry.getValue();                 try {                     //向客户端推送消息                     webSocketServer.getSession().getBasicRemote().sendText("每隔两秒,向客户端推送一次数据");                 }catch (IOException e){                     e.printStackTrace();                 }             }         }else {             System.out.println("WebSocket未连接");         }     } }
  定时器的实现类就完成了,我们还需要在springmvc.xml中进行配置
  springmvc.xml配置:                                                                                                                                                                                      
  接下来是controller层的代码,就一个登录的功能。 package com.socket.web.controller;  import com.socket.domain.User; import com.sun.org.apache.bcel.internal.generic.RETURN; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod;  import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.util.UUID;  /**  * @Author: 清风一阵吹我心  * @ProjectName: socket  * @Package: com.socket.web  * @ClassName: ChatController  * @Description:  * @CreateDate: 2018/11/9 11:04  * @Version: 1.0  **/ @RequestMapping("socket") @Controller public class ChatController {      /**      * 跳转到登录页面      * @return      */     @RequestMapping(value = "/login",method = RequestMethod.GET)     public String goLogin(){         return "login";     }      /**      * 跳转到聊天页面      * @param request      * @return      */     @RequestMapping(value = "/home",method = RequestMethod.GET)     public String goMain(HttpServletRequest request){         HttpSession session = request.getSession();         if (null == session.getAttribute("USER_SESSION")){             return "login";         }         return "home";     }      @RequestMapping(value = "/login",method = RequestMethod.POST)     public String login(User user, HttpServletRequest request){         HttpSession session = request.getSession();         //将用户放入session         session.setAttribute("USER_SESSION",user);         return "redirect:home";     }  }
  以上就是登录的代码了,基本上就是伪代码,只要输入用户名就可以了,后面的逻辑,大家可以根据自己的业务来实现。
  最后就是前台页面的设计了,登录,login.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %>        登录     
  消息接收页面,home.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %>       聊天               
  基本上,数据推送的功能就完成了,下面附上效果图。
  启动tomcat。后台定时器两秒刷新一次,判断是否有websocket连接。
  登录页面:
  数据推送页面:
  服务器定时向客户端推送数据的功能就完成了,有不明白的可以给博主留言,如果有什么错误,也希望各位朋友指出,谢谢大家。
  本文源码:
  https://github.com/Qingfengchuiwoxin/websocket

七一前夕,献礼艺术与科技创新之花6月16日,常州市钟楼区格瑞海思人居环境科技有限公司,榴花如火,党徽闪耀,党旗正红。国家一级美术师中国美术家协会会员原常州市美术家协会常务副主席兼秘书长丁德源老师及夫人周亦红女士,虹软科技国内视觉算法软件三甲手机业务稳定增长智能驾驶空间广选股理由一季度业绩逆势增长科创板证券代码688088评级AA本文分为六部分一主营业务二公司治理三财务分析四核心竞争力及投资逻辑五盈利预测及估值六个股点评数据截止日期2020年3月3国盛智科国产中高端机床行业前三受益国产替代业绩有望快速增长独立客观第三方研究,为您筛选优质上市公司证券代码688558综合评级A一主营业务评分751业务分析公司主营业务为数控机床,数控机床基本涉及到工业生产各个环节,但是国内的机床精度不够容百科技国内锂电池正极材料龙头,产能释放高速增长可期独立客观第三方研究,为您筛选优质上市公司证券代码688005综合评级AA一主营业务评分851业务分析公司主营业务比较集中,聚焦动力锂电池所需的正极材料,而三元前驱体也是正极材料所需八亿时空国内液晶显示材料次龙头能否把握技术替代缓冲期是核心选股理由一季度业绩逆势增长近期股价新高科创板证券代码688181评级BBB本文分为六部分一主营业务二公司治理三财务分析四核心竞争力及投资逻辑五盈利预测及估值六投资观点数据截止日期2马上年底了,确定不为自己换一款能打颜值高的新机嘛?Redmi10XRedmi10X于今年5月发布。目前,这款手机的6128GB版本已经从1799元降至1399元。Redmi10X的最大亮点是处理器。天玑8205G芯片相同价格性能最蓝牙耳机究竟怎么选?三大品牌实力比拼,颜值党先舔为敬烂大街的玫瑰巧克力娃娃你还在送吗?如何出奇制胜,让这个七夕圆满?不如为她送上蓝牙耳机,不仅视频电话可以用到,听歌也能想起你。有一说一,学生党哪有什么钱,价位合适,音质不错不会踩雷,荣耀50倍变焦旗舰降至2272,3200万屏幕指纹40W随着5G的飞速发展,各大手机制造商纷纷推出了多种5G机型,这使得市场上的5G手机数量达到十几种机型,手机的保存率也越来越低以及下半年,许多制造商都推出了新的5G型号。因此,今年上半这款机型现在入手是最佳选择,上班族都爱不释手进入下半年后,5G手机的发展取得了新的突破。轻薄的机身再次成为主要制造商生产的新手机的卖点。人们也开始将注意力从配置转移到感觉,但是目前可用的模型并不多。今天,我们将要讨论一款极具这款机型价格降到冰点,但是坚决不建议购买,没有性价比配置还低尽管现在最强大的处理器是骁龙865Plus,但与骁龙865相比,它实际上增加了约10,而且成本仍然更高。因此,总体而言,骁龙865在制造商中更受欢迎,但毕竟市场上有新处理器,因此现都是做性价比品牌,荣耀和小米你喜欢哪个?众所周知,华为手机的价格一直以来都比较高,特别是在高端旗舰中。尽管其子品牌荣耀是主打性价比的,但近年来也一直在往高端领域冲击。今年发布的荣耀30系列的高配版本的售价也近5000元。
什么情况?支付牌照又少3张!支付业十年39家退圈现代人,谁也离不开支付。哪家支付机构能卖POS机哪家电商平台能卖礼品卡,都由一张支付牌照说了算。近日,央行公布了首批支付牌照二次续展结果首批27家机构里,支付宝财付通(微信支付的主再抛减持计划!国家大基金三天两次出手这次目标是A股芯片封测龙头从2015年助力通富微电收购AMD旗下封测资产,到2018年接下富士通中国退出股份,国家集成电路产业投资基金股份有限公司(简称国家大基金)对芯片封测龙头公司通富微电的发展助力可谓不零信任网络助力工业互联网安全体系建设随着云计算大数据物联网5G边缘计算等IT技术的快速发展,支撑了工业互联网的应用快速落地。作为新基建的重点方向之一,工业互联网发展已经进入快轨道,将加速中国制造向中国智造转型,并推动相约世界智能大会体验无人驾驶乐趣在即将开启的第五届世界智能大会上,市民可以体验一把无人驾驶的新奇和乐趣了。据悉,将于5月21日至23日举办的2021世界智能驾驶挑战赛全面升级,设置驾驶辅助赛落地先行赛极限挑战赛智华为确定鸿蒙OS全面开源,小米会心甘情愿放弃安卓吗?一直以来,我都使用小米,自己用,给家人买,帮朋友买,买了不下50部小米手机,还有小米电视,充电宝,耳机,手环等等!可谓是忠实米粉!如果小米不用鸿蒙系统,以后我就不买小米了,什么品牌华为确定鸿蒙OS全面开源,小米会心甘情愿放弃安卓吗?华为已经确定,鸿蒙OS全面开源,就和安卓系统一样,所有第三方手机厂商都能用。不得不说,华为的时间点选得很巧妙,特意将鸿蒙OS全面开源的消息,选在Android12发布会之前公布。甚为什么有人宁愿每年买一部千元机,也不愿一次买部高端机?每年都买千元机说明每年只有这些手机预算,一次拿出4000元和分三年拿出4000元还是很不一样的。千元机虽然不高端但是够用,而且每年总能换新的用。何况这年头手机更新换代这么快,你就真bose音箱和BampampO的区别是什么?Bose是美国麻省理工学院教授AmarG。Bose博士于1964年创办的。是美国最大的扬声器厂家之一,不仅在比如大型体育场音乐厅等公共场所等所需的商用专业音响有一定的市场,在家庭影有什么轻薄的5G手机推荐吗?一说到轻薄手机,那多数人首先就会想到小屏手机,毕竟大屏手机还能保持轻薄的真心不多。在我们的认识中,纯正的小屏手机只有三星的Galaxy20苹果的iPhone11Pro华为的P40,最近这几年武汉为什么发展的这么好?武汉是一座没有短板的城市,所有的方面极便不是最好,但都非常的好,因此武汉的发展是全方位的,发展速度呈几何级数上升,城市越发展,就越有吸引力,人口越增长,各方面的发展相互促进,发展就如何评价朱萧木这个人,他算不算老罗最忠实的拥趸?我觉得算是。从2013年开始,朱萧木就是锤子科技的一号员工。是老罗从事手机行业的第一位下属。在锤子科技时期,他是锤子科技的产品经理,尤其是在系统软件方面,朱萧木做了很多工作。后来随