当前位置:首页 » 《随便一记》 » 正文

(java)websocket服务的两种实现方式

15 人参与  2024年10月07日 12:00  分类 : 《随便一记》  评论

点击全文阅读


1.基于java注解实现websocket服务器端

1.1需要的类

1.1.1服务终端类

用java注解来监听连接@ServerEndpoint、连接成功@OnOpen、连接失败@OnClose、收到消息等状态@OnMessage

1.1.2配置类

把spring中的ServerEndpointExporter对象注入进来

2.1代码示例

2.1.1 maven配置

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.heima</groupId>    <artifactId>ws-demo</artifactId>    <version>1.0-SNAPSHOT</version>    <properties>        <maven.compiler.source>8</maven.compiler.source>        <maven.compiler.target>8</maven.compiler.target>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter</artifactId>           <version>2.7.3</version>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <version>1.16.22</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-websocket -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-websocket</artifactId>            <version>2.7.14</version>        </dependency>    </dependencies></project>

2.1.2 WsServerEndpoint类

package com.heima;import lombok.extern.slf4j.Slf4j;import org.springframework.scheduling.annotation.EnableScheduling;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Component;import javax.websocket.OnClose;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;/*** * 监听websocket地址  /myWs */@ServerEndpoint("/myWs")@Component@Slf4j@EnableSchedulingpublic class WsServerEndpoint {    static Map<String,Session> map = new ConcurrentHashMap<String,Session>();    /***     * 连接建立时执行的操作     * @param session     */    @OnOpen    public void onOpen(Session session)    {        map.put(session.getId(),session);        log.info("websocket is open");    }    /***     * 收到客户端消息执行的操作     * @param text     */    @OnMessage    public String OnMessage(String text)    {        log.info("收到了一条信息"+text);        return "已收到你的信息" ;    }    /***     * 连接关闭时执行的操作     * @param session     */    @OnClose    public void OnClose(Session session)    {        map.remove(session.getId());        log.info("连接关闭时执行的操作");    }    /***     * 向客户端发送信息     */    @Scheduled(fixedRate = 2000)    public void sendMsg() throws IOException {        for (String key : map.keySet())        {            map.get(key).getBasicRemote().sendText("你好,你好");        }    }}

2.1.3 WebSocketConfig

package com.heima;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configurationpublic class WebSocketConfig {    @Bean public ServerEndpointExporter serverEndpointExporter() {     return new ServerEndpointExporter(); }}

2.1.3 前端测试代码

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>wsClient</title></head><body><script>     // 创建websocket    let ws = new WebSocket("ws://localhost:8080/myWs")     //向服务器发送hello    ws.onopen=function (){        ws.send("hello")    }    //监听数据ws://localhost:8080/myWs    ws.onmessage=function (message){        console.log(message.data)    }</script></body></html>

2.1.4测试结果

2.1.4.1 当打开浏览器时

2.1.4.2 当关闭浏览器时

2.1.4.3 当刷新浏览器的时候

2.基于spring提供的类和接口刷新websocket服务器端

2.1:HttpSessionHandShakeInter 握手拦截器

package com.spring;import lombok.extern.slf4j.Slf4j;import org.springframework.context.annotation.Configuration;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.stereotype.Component;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;import java.util.Map;/*** * 握手拦截器 */@Component@Slf4jpublic class MyWsInterceptor extends HttpSessionHandshakeInterceptor {    @Override    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {        log.info(request.getRemoteAddress().toString()+"开始握手");        return super.beforeHandshake(request, response, wsHandler, attributes);    }    @Override    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {         log.info(request.getRemoteAddress().toString()+"完成握手");        super.afterHandshake(request, response, wsHandler, ex);    }}

2.2  MyWsHandler 主处理程序

sessionbean封装类
import lombok.AllArgsConstructor;import lombok.Data;import org.springframework.web.socket.WebSocketSession;@Data@AllArgsConstructorpublic class SessionBean {    private WebSocketSession webSocketSession;    private Integer clientId;}
 主处理程序
package com.spring;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.web.servlet.server.Session;import org.springframework.scheduling.annotation.EnableScheduling;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Component;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.AbstractWebSocketHandler;import java.io.IOException;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.atomic.AtomicInteger;/*** * webSocket 主处理程序 */@Component@Slf4j@EnableSchedulingpublic class MyWsHandler extends AbstractWebSocketHandler {    //map有并发线程问题  所以用ConcurrentHashMap    private static Map<String, SessionBean> map ;    //id有并发问题 所以用Integer的安全类型    private static AtomicInteger clientIdMaker;    static {        map = new ConcurrentHashMap<>();        clientIdMaker=new AtomicInteger(0);    }    //连接建立    @Override    public void afterConnectionEstablished(WebSocketSession session) throws Exception {        super.afterConnectionEstablished(session);        //将session 进一步封装  id采用的是自增        SessionBean sessionBean = new SessionBean(session, clientIdMaker.getAndIncrement());        map.put(session.getId(),sessionBean);        log.info(map.get(session.getId()).getClientId()+"建立了连接");    }    //收到消息    @Override    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {        super.handleTextMessage(session, message);        log.info(map.get(session.getId()).getClientId()+":"+message.getPayload());    }    //传输异常    @Override    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {        super.handleTransportError(session, exception);        if (session.isOpen())        {            session.close();        }        map.remove(session.getId());    }    //连接关闭    @Override    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {        super.afterConnectionClosed(session, status);        log.info(map.get(session.getId()).getClientId()+"关闭连接");    }    /***     * 向客户端发送信息     */    @Scheduled(fixedRate = 2000)    public void sendMsg() throws IOException {        for (String key : map.keySet())        {            map.get(key).getWebSocketSession().sendMessage(new TextMessage("hello," +                    "spring socket"));        }    }}

2.3 WebSocketConfigurer 注册拦截器和主处理程序以及监听路径

package com.spring;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import javax.annotation.Resource;@Configuration@EnableWebSocketpublic class MyWsConfig implements WebSocketConfigurer {    @Resource    private MyWsHandler wsHandler;    @Resource    private MyWsInterceptor wsInterceptor;    @Override    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {        registry.addHandler(wsHandler,"/myWs1").addInterceptors(wsInterceptor).setAllowedOriginPatterns("*");    }}

2.4 前端测试

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>wsClient</title></head><body><script>     // 创建websocket    let ws = new WebSocket("ws://localhost:8080/myWs1")     //向服务器发送hello    ws.onopen=function (){        ws.send("hello")    }    //监听数据ws://localhost:8080/myWs    ws.onmessage=function (message){        console.log(message.data)    }</script></body></html>


点击全文阅读


本文链接:http://zhangshiyu.com/post/168504.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1