前端建立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();
}
}
看都看到这儿了,点个赞再走呗(。・∀・)ノ