前端建立websocket鏈接的時候,控制檯打印Error during WebSocket handshake: Unexpected response code: 200,
這種情況多半是因爲服務端的攔截器出了問題。
要知道websocket是基於http的,建立websocket鏈接的時候也用經過握手,這個握手走的就是傳統的http請求(好像不同瀏覽器實現的細節也不太一樣,chrome應該是走的http),因此如果服務端有攔截器的話,是會把握手信息攔截下來的。
解決辦法:
我的服務端是springboot+shrio, 解決辦法很簡單
@Configuration
public class ShiroConfig {
/**
* Shiro的Web過濾器Factory 命名:shiroFilter<br /> * * @param securityManager * @return
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
System.out.println(("注入Shiro的Web過濾器-->shiroFilter" + ShiroFilterFactoryBean.class));
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/user/login");
shiroFilterFactoryBean.setSuccessUrl("/index");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/user/login", "anon");
filterChainDefinitionMap.put("/websocket", "anon"); //避免攔截/websocket鏈接
filterChainDefinitionMap.put("/reg", "anon");
filterChainDefinitionMap.put("/plugins/**", "anon");
filterChainDefinitionMap.put("/pages/**", "anon");
filterChainDefinitionMap.put("/api/**", "anon");
filterChainDefinitionMap.put("/dists/img/*", "anon");
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
shiroFilterFactoryBean.getFilters().put("authc", new MyFormAuthenticationFilter());
return shiroFilterFactoryBean;
}
}
核心代碼其實就這一行 filterChainDefinitionMap.put("/websocket", “anon”);
另外附上我的websocket配置:
@Configuration
public class WebsocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
/**
* 坑點:
* \@ServerEndpoint註解的類,不可以用AOP, 否則會出現無法注入的情況
*/
@ServerEndpoint(value = "/websocket")
@Component
public class WSServer {
private static Hashtable<String, WSServer> websocketTable = new Hashtable<>();
private static final String TYPE_INIT = "0";
private static final String TYPE_EXCEPTION = "-1";
private Session session;
//心跳定時器
private Timer pulsTimer;
private long timerPeriod = 45 * 1000;
private String userName; //標識用戶
@OnOpen
public void onOpen(Session session){
this.session = session;
//第一個鏈接後,啓動定時器發送定時心跳
if(pulsTimer == null){
pulsTimer = new Timer();
pulsTimer.schedule(new TimerTask() {
@Override
public void run() {
try {
WSServer.broadcast(WSMessage.pulseMessage());
}catch (IOException e){
e.printStackTrace();
}
}
}, 0L, timerPeriod);
}
}
@OnClose
public void onClose() {
if(!StringUtils.isEmpty(userName)){
websocketTable.remove(userName);
}
}
/**
* {
* type:"1",
* message:"JSON",
* rdnum:"用來唯一標識這條消息的id"
* }
*/
@OnMessage
public void onMessage(String message, Session session) {
try {
JSONObject jsonObject = JSONObject.parseObject(message);
String type = jsonObject.getString("type");
switch (type){
case TYPE_INIT: init(jsonObject);break;
default:;
}
}catch (JSONException e){
e.printStackTrace();
WSMessage wsMessage = new WSMessage(TYPE_EXCEPTION, "json格式出錯");
sendMessage(wsMessage);
}
}
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public void sendMessage(WSMessage message){
try {
sendMessage(message.toString());
}catch (IOException e){
e.printStackTrace();
}
}
public void init(JSONObject jsonObject){
JSONObject messge = jsonObject.getJSONObject("message");
if(messge != null){
String userName = messge.getString("userName");
if(StringUtils.isEmpty(userName)){
websocketTable.put(userName, this);
}
}
}
public static synchronized void broadcast(String message) throws IOException{
for(Iterator<String> iterator = websocketTable.keySet().iterator(); iterator.hasNext(); ){
WSServer wsServer = websocketTable.get(iterator.next());
wsServer.sendMessage(message);
}
}
public static synchronized void broadcast(WSMessage message) throws IOException{
broadcast(message.toString());
}
public static synchronized void broadcast(WSMessage message, String userName) throws IOException{
broadcast(message.toString(), userName);
}
public static synchronized void broadcast(String message, String userName) throws IOException{
WSServer wsServer = websocketTable.get(userName);
if(wsServer != null){
wsServer.sendMessage(message);
}
public static synchronized int getOnlineCount() {
return websocketTable.size();
}
}
看都看到這兒了,點個贊再走唄(。・∀・)ノ