看了很多关于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