本來想寫一個網頁聊天的東西,架構用的jfinal , 寫好後一直報Error during WebSocket handshake: Unexpected response code: 404,納悶半天,開始使用的是jetty 9.0,這個版本不支援websocket,然後看網上又人說 更換為 jetty9.4版本及以上就可以正常使用了, 更換後果然可以。特此記錄,順便記錄下jfinal的一些配置。
AppConfig中
@Override
public void configHandler(Handlers me) {
me.add(new WebSocketHandler("/websocket"));
}
使用jfinal攔截websocket請求,轉發到自己的socket類。
public class WebSocketHandler extends Handler{
private Pattern filterUrlRegxPattern;
public WebSocketHandler(String filterUrlRegx) {
if (StrKit.isBlank(filterUrlRegx))
throw new IllegalArgumentException("The para filterUrlRegx can not be blank.");
filterUrlRegxPattern = Pattern.compile(filterUrlRegx);
}
@Override
public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
if (filterUrlRegxPattern.matcher(target).find())
return ;
else
next.handle(target, request, response, isHandled);
}
}
下面這個就是socket主體檔案了。
package com.momo.api.websocket;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
/**
* @ServerEndpoint 注解是一個類層次的注解,它的功能主要是将目前的類定義成一個websocket伺服器端,
* 注解的值将被用于監聽使用者連接配接的終端通路URL位址,用戶端可以通過這個URL來連接配接到WebSocket伺服器端
*/
@ServerEndpoint("/websocket")
public class ImWebSocket {
//靜态變量,用來記錄目前線上連接配接數。應該把它設計成線程安全的。
private static int onlineCount = 0;
//concurrent包的線程安全Set,用來存放每個用戶端對應的MyWebSocket對象。若要實作服務端與單一用戶端通信的話,可以使用Map來存放,其中Key可以為使用者辨別
private static CopyOnWriteArraySet<ImWebSocket> webSocketSet = new CopyOnWriteArraySet<ImWebSocket>();
//與某個用戶端的連接配接會話,需要通過它來給用戶端發送資料
private Session session;
/**
* 連接配接建立成功調用的方法
* @param session 可選的參數。session為與某個用戶端的連接配接會話,需要通過它來給用戶端發送資料
*/
@OnOpen
public void onOpen(Session session){
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //線上數加1
System.out.println("有新連接配接加入!目前線上人數為" + getOnlineCount());
}
/**
* 連接配接關閉調用的方法
*/
@OnClose
public void onClose(){
webSocketSet.remove(this); //從set中删除
subOnlineCount(); //線上數減1
System.out.println("有一連接配接關閉!目前線上人數為" + getOnlineCount());
}
/**
* 收到用戶端消息後調用的方法
* @param message 用戶端發送過來的消息
* @param session 可選的參數
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("來自用戶端的消息:" + message);
//群發消息
for(ImWebSocket item: webSocketSet){
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
/**
* 發生錯誤時調用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
System.out.println("發生錯誤");
error.printStackTrace();
}
/**
* 這個方法與上面幾個方法不一樣。沒有用注解,是根據自己需要添加的方法。
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
ImWebSocket.onlineCount++;
}
public static synchronized void subOnlineCount() {
ImWebSocket.onlineCount--;
}
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVP9cXT0IkbiFjTzwEMW1mY1RzRapnTtxkb5ckYplTeMZTTINGMShUYvwFd4VGdvwlMvw1ayFWbyVGdhd3P1UzM0UDNzEDMxgDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)