java实现一个简单的webSocket聊天demo

一、依赖

添加pom文件依赖


   <!-- websocket-->
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-websocket</artifactId>
     </dependency>
        

二、配置准备

创建webSocketConfig配置类,即注册ServerEndpointExporter,该bean用于扫描被@ServerEndpoint注解的类,并将其作为服务端.


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * @Author: chuxia0811
 * @Date: 2023/7/9 10:15
 * @Description : webSocketConfig配置类,该bean用于扫描被@ServerEndpoint注解的类
 */
@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return  new ServerEndpointExporter();
    }
}

三、demo代码编写

创建被@ServerEndpoint注解的类用于作为webSocket服务器并指定连接的uri
使用注解标记对应的方法,,并启动程序。


/**
 * @Author: chuxia0811
 * @Date: 2023/7/9 10:21
 * @Description :
 */
@ServerEndpoint(value = "/chat/{username}")
@Component
@Slf4j
public class SocketServer {
    Logger log = LoggerFactory.getLogger(getClass());

    // 保存链接的session,key为用户名,value为对应的session名
    private ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 创建连接
     * 用于监听建立连接,当有客户端与该服务端点建立连接时,将会自回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "username") String username) {
        log.info("用户{}已创建连接", username);
    }


    /**
     * 用于监听客户端向服务端发送消息,当客户端与服务端发送消息时,将会回调该注解标注的方法
     * @param msg
     * @param username
     */
    @OnMessage
    public void onMessage(String msg,@PathParam(value = "username") String username){
        log.info("用户{}发来消息:{}",username,msg);
    }


    /**
     * 用于监听连接关闭,当客户端与该服务端点断开连接时,将会回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnClose
    public void onClose(Session session,@PathParam(value = "username") String username){
        log.info("用户{}已关闭连接", username);
    }


    /**
     * 用于监听该连接上的任何错误,当客户端与该服务端点的连接发生任何异常,都将回调该注解标注的方法
     * 注意该方法的参数必选Throwable,可选Sessiion以及0-n个String参数,且String参数需要使用@PathParam注解标注
     * @param throwable
     * @param username
     */
    @OnError
    public void onError(Throwable throwable,@PathParam(value = "username") String username){
        log.error("用户{}连接发生异常", username);
    }

}

四、启动测试

项目启动后,测试websocket是否可用。
webSocket在线测试网站: Websocket在线测试链接

在这里插入图片描述
日志如下:

2023-07-09 10:49:29.185  INFO 16308 --- [nio-8080-exec-5] org.sang.websocket.SocketServer         
 : 用户初夏已创建连接
2023-07-09 10:49:35.672  INFO 16308 --- [nio-8080-exec-6] org.sang.websocket.SocketServer         
 : 用户初夏已创建连接
2023-07-09 10:49:43.470  INFO 16308 --- [nio-8080-exec-7] org.sang.websocket.SocketServer       
   : 用户初夏发来消息:你好,我是初夏~

五、编写业务

成功完成基础的websocket连接,可以开始编辑业务逻辑

1.构建后台message实体类;

/**
 * @Author: chuxia0811
 * @Date: 2023/7/9 10:58
 * @Description :
 */
public class Message {
    private Integer id;
    private String from;
    private String to;
    private String msg;
    private String date;
    private Integer type;//消息发送的类型,0系统群发,1用户私聊
    private Integer is_read;//消息是否已读,0未读,1已读

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public Integer getIs_read() {
        return is_read;
    }

    public void setIs_read(Integer is_read) {
        this.is_read = is_read;
    }
}

2.改造方法

@ServerEndpoint(value = "/chat/{username}")
@Component
@Slf4j
public class SocketServer {
    Logger log = LoggerFactory.getLogger(getClass());

    // 保存链接的session,key为用户名,value为对应的session名
    private ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

    /**
     * 创建连接
     * 用于监听建立连接,当有客户端与该服务端点建立连接时,将会自回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "username") String username) {
        log.info("用户{}已创建连接", username);
        sessionMap.put(username,session);
    }


    /**
     * 用于监听客户端向服务端发送消息,当客户端与服务端发送消息时,将会回调该注解标注的方法
     * @param msg
     * @param username
     */
    @OnMessage
    public void onMessage(String msg,@PathParam(value = "username") String username){
        log.info("用户{}发来消息:{}",username,msg);
        Message message = JSON.parseObject(msg, Message.class);
        //根据message中的to属性获取接收消息的用户的session,利用其session将消息转发过去
        Session toSession = sessionMap.get(message.getTo());
        sendMessage(toSession, message.getMsg());
    }


    /**
     * 用于监听连接关闭,当客户端与该服务端点断开连接时,将会回调该注解标注的方法
     * @param session
     * @param username
     */
    @OnClose
    public void onClose(Session session,@PathParam(value = "username") String username){
        log.info("用户{}已关闭连接", username);
        sessionMap.remove(username);
    }


    /**
     * 用于监听该连接上的任何错误,当客户端与该服务端点的连接发生任何异常,都将回调该注解标注的方法
     * 注意该方法的参数必选Throwable,可选Sessiion以及0-n个String参数,且String参数需要使用@PathParam注解标注
     * @param throwable
     * @param username
     */
    @OnError
    public void onError(Throwable throwable,@PathParam(value = "username") String username){
        log.error("用户{}连接发生异常", username);
    }


    /**
     * 用来发送消息的方法,参数分别为接收消息的用户的session,和对应的消息
     */
    private void sendMessage(Session toSession,String msg){
        try {
            toSession.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}

3.新建三个websocket在线测试的窗口创建三个链连接


2023-07-09 11:34:13.330  INFO 5812 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 20 ms
2023-07-09 11:34:13.372  INFO 5812 --- [nio-8080-exec-1] org.sang.websocket.SocketServer          : 用户初夏1已创建连接
2023-07-09 11:34:15.302  INFO 5812 --- [nio-8080-exec-2] org.sang.websocket.SocketServer          : 用户初夏2已创建连接
2023-07-09 11:34:18.101  INFO 5812 --- [nio-8080-exec-3] org.sang.websocket.SocketServer          : 用户初夏3已创建连接

测试,用初夏2用户给初夏3发聊天消息:
在这里插入图片描述

我们可以看到,只有初夏3收到了聊天消息,初夏1没收到:
在这里插入图片描述
在这里插入图片描述
到这里,我们就实现了webSocke技术,实现聊天功能了。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当然,以下是一个使用Java实现简单的MQTT发布和订阅的示例代码: ```java import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; public class MqttDemo { public static void main(String[] args) { String broker = "tcp://mqtt.example.com:1883"; // MQTT服务器地址 String clientId = "JavaClient"; // 客户端ID String topic = "test/topic"; // 主题 try { MqttClient client = new MqttClient(broker, clientId, new MemoryPersistence()); MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setCleanSession(true); System.out.println("Connecting to broker: " + broker); client.connect(connOpts); System.out.println("Connected"); // 发布消息 String content = "Hello, MQTT!"; int qos = 0; System.out.println("Publishing message: " + content); MqttMessage message = new MqttMessage(content.getBytes()); message.setQos(qos); client.publish(topic, message); // 订阅消息 System.out.println("Subscribing to topic: " + topic); client.subscribe(topic, new MqttCallback() { public void connectionLost(Throwable cause) { System.out.println("Connection lost!"); } public void messageArrived(String topic, MqttMessage message) throws Exception { System.out.println("Message received: " + new String(message.getPayload())); } public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("Delivery complete!"); } }); // 挂起程序,等待消息到达 Thread.sleep(5000); // 断开连接 client.disconnect(); System.out.println("Disconnected"); } catch (MqttException | InterruptedException e) { e.printStackTrace(); } } } ``` 请确保在运行代码之前将MQTT服务器地址、客户端ID和主题替换为正确的值。这个示例中,客户端首先连接到MQTT服务器,然后发布一条消息到指定主题,同时订阅该主题以接收消息。在接收到消息后,程序将打印出消息内容。最后,程序挂起一段时间以等待消息到达,然后断开连接。 这只是一个简单的示例,您可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初夏0811

你的鼓励将是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值