1. WebSocketとhttpの違いは何ですか?
1. httpプロトコルは、アプリケーション層で使用されるプロトコルであり、tcpプロトコルに基づいています。また、httpプロトコルでは、リンクを確立するために情報を送信するために3ウェイハンドシェイクが必要です。
httpリンクは、短いリンク、長いリンクに分けられ、短いリンクでは、独自の情報を送信するために、リクエストごとに3回のハンドシェイクが必要です。つまり、各要求は応答に対応します。ロングリンクとは、リンクを一定期間維持することです。TCP接続を切断しないでください。クライアントとサーバー間の通信はクライアントによって開始される必要があり、サーバーは結果を返します。クライアントはアクティブで、サーバーはパッシブです。
2. WebSocket
WebSocketは、クライアントがサーバーリソースブラウザーへの複数のhttp要求を開始するために、ブラウザーが長時間ローテーショントレーニングを受ける必要があるという問題を解決するために誕生しました。多重化を実現し、全二重通信です。カスタマーサービス端末とブラウザは、webSocketプロトコルの下で同時に情報を送信できます。
2.例
(1)Mavenの依存関係を追加する
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
(2)コアコード
@ServerEndpoint(value = "/ws/asset")
@Component
public class WebSocketServer {
@PostConstruct
public void init() {
System.out.println("websocket 加载");
}
private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
private static final AtomicInteger OnlineCount = new AtomicInteger(0);
// concurrent包的线程安全Set,用来存放每个客户端对应的Session对象。
private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
SessionSet.add(session);
int cnt = OnlineCount.incrementAndGet(); // 在线数加1
log.info("有连接加入,当前连接数为:{}", cnt);
SendMessage(session, "连接成功");
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
SessionSet.remove(session);
int cnt = OnlineCount.decrementAndGet();
log.info("有连接关闭,当前连接数为:{}", cnt);
}
/**
* 收到客户端消息后调用的方法
*
* @param message
* 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("来自客户端的消息:{}",message);
SendMessage(session, "收到消息,消息内容:"+message);
}
/**
* 出现错误
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误:{},Session ID: {}",error.getMessage(),session.getId());
error.printStackTrace();
}
/**
* 发送消息,实践表明,每次浏览器刷新,session会发生变化。
* @param session
* @param message
*/
public static void SendMessage(Session session, String message) {
try {
session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId()));
} catch (IOException e) {
log.error("发送消息出错:{}", e.getMessage());
e.printStackTrace();
}
}
/**
* 群发消息
* @param message
* @throws IOException
*/
public static void BroadCastInfo(String message) throws IOException {
for (Session session : SessionSet) {
if(session.isOpen()){
SendMessage(session, message);
}
}
}
/**
* 指定Session发送消息
* @param sessionId
* @param message
* @throws IOException
*/
public static void SendMessage(String message,String sessionId) throws IOException {
Session session = null;
for (Session s : SessionSet) {
if(s.getId().equals(sessionId)){
session = s;
break;
}
}
if(session!=null){
SendMessage(session, message);
}
else{
log.warn("没有找到你指定ID的会话:{}",sessionId);
}
}
}
3.一般的な問題(404エラーが発生します)
理由:これは、websocketによって作成されたBeanがそれ自体で管理されており、それによって作成されたBeanを春までに管理する必要があるためです。
解決
@Configuration
public class WebSocketConfig {
/**
* ServerEndpointExporter 作用
*
* 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint
*
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Bean
public MySpringConfigurator mySpringConfigurator() {
return new MySpringConfigurator();
}
}
/**
* 以websocketConfig.java注册的bean是由自己管理的,需要使用配置托管给spring管理
*
*/
public class MySpringConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
private static volatile BeanFactory context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
MySpringConfigurator.context = applicationContext;
}
@Override
public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
return context.getBean(clazz);
}
}
Springはwebsocketで作成されたBeanを取得できます