看了很多关于JFinal 关于 websocket 实现方法,不过很多都是在早前版本,或Tomcat下面实现,结合JFinal(3.4) + Jbolt(1.8.1) + undertow(1.8) 才是王道,先将代码贴出来。
pom.xml 添加
<dependency> <groupId>io.undertow</groupId> <artifactId>undertow-websockets-jsr</artifactId> <version>2.0.25.Final</version> </dependency>
Session 管理类 WebSocketMapUtil
public class WebSocketMapUtil { public static ConcurrentMap<String, MyWebSocket> webSocketMap = new ConcurrentHashMap<>(); public static void put(String key, MyWebSocket myWebSocket){ webSocketMap.put(key, myWebSocket); } public static MyWebSocket get(String key){ return webSocketMap.get(key); } public static void remove(String key){ webSocketMap.remove(key); } public static Collection<MyWebSocket> getValues(){ return webSocketMap.values(); } }
实现类 MyWebSocket
@ServerEndpoint("/quotes.ws") public class MyWebSocket { public Session session; @OnMessage public void message(String message, Session session) { for (Session s : session.getOpenSessions()) { s.getAsyncRemote().sendText(message); } } /** * 连接建立后触发的方法 */ @OnOpen public void onOpen(Session session){ this.session = session; LogKit.info("====== onOpen:"+session.getId()+" ======"); WebSocketMapUtil.put(session.getId(),this); } /** * 连接关闭后触发的方法 */ @OnClose public void onClose() { WebSocketMapUtil.remove(session.getId()); LogKit.info("====== onClose:"+session.getId()+" ======"); } /** * 发生错误时触发的方法 */ @OnError public void onError(Session session,Throwable error){ LogKit.info(session.getId()+"连接发生错误"+error.getMessage()); error.printStackTrace(); } }
MainConfig 启动配置
public static void main(String[] args) { UndertowServer undertowServer = UndertowServer.create(MainConfig.class,"undertow.properties"); undertowServer.configWeb(builder->{builder.addWebSocketEndpoint(MyWebSocket.class);}); undertowServer.start(); }
test.html
<html> <head> <title>Undertow Chat</title> <script> var socket; if (window.WebSocket) { socket = new WebSocket("ws://localhost/quotes.ws"); socket.onmessage = function (event) { var chat = document.getElementById('chat'); chat.innerHTML = chat.innerHTML + event.data + "<br />"; }; } else { alert("Your browser does not support Websockets. (Use Chrome)"); } function send(message) { if (!window.WebSocket) { return false; } if (socket.readyState == WebSocket.OPEN) { socket.send(message); } else { alert("The socket is not open."); } return false; } </script> <style type="text/css"> html,body {width:100%;height:100%;} html,body,ul,ol,dl,li,dt,dd,p,blockquote,fieldset,legend,img,form,h1,h2,h3,h4,h5,h6 {margin:0;padding:0;} body { font:normal 12px/1.5 Arial,Helvetica,'Bitstream Vera Sans',sans-serif; background: #c5deea; /* Old browsers */ background: -moz-linear-gradient(top, #c5deea 0%, #066dab 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #c5deea), color-stop(100%, #066dab)); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, #c5deea 0%, #066dab 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, #c5deea 0%, #066dab 100%); /* Opera 11.10+ */ background: -ms-linear-gradient(top, #c5deea 0%, #066dab 100%); /* IE10+ */ background: linear-gradient(to bottom, #c5deea 0%, #066dab 100%); /* W3C */ height: 90%; } .center { margin-left: auto; margin-right: auto; width: 70%; background: white; } .chatform { margin-left: auto; margin-right: auto; margin-bottom: 0; width: 70%; height: 200px; } form{ width: 100%; } label{ display: inline; width: 100px; } #msg{ display: inline; width: 100%; } </style> </head> <body> <div class="page"> <div class="center" > <h1>Socket Chat</h1> <div id="chat" style="height:80%;width: 100%; overflow: scroll;"> </div> <form onsubmit="return false;" class="chatform" action=""> <label for="msg">Message</label> <input type="text" name="message" id="msg" onkeypress="if(event.keyCode==13) { send(this.form.message.value); this.value='' } " /> </form> </div> </div> </body> </html>
默认IndexController 里添加方法
public void test() { render("test.html"); }
以上都配置好后,运行MainConfig 打开 http://127.0.0.1/test
底下输入信息回车,后台会将收到的信息推送到页面,另外再打开一个新的浏览器输入上面地址,其中一个输入信息,后台也会将信息推送给另外的浏览器。
另外同时问一下JFinal的大神们,如果我要服务端定时主动给客户端推送信息,比如我结合了任务quartz,一分钟推送一次信息,我要怎么调用,网上找了没有太好的办法?
此外,jfinal 建议升级到 4.4, jfinal undertow 建议升级到 1.9