springmvc通过注解搭建websocket

本文详细介绍了一个基于WebSocket的双向通信项目,包括Maven依赖配置、SpringMVC与WebSocket整合、前端Vue与Axios交互,以及JSON数据传输过程。涵盖web.xml、springmvc.xml配置,后端WebSocketController设计,前端socket.js及HTML布局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是我的项目,下载后用idea打开
https://github.com/yonggandeliuguang/websocket-test
选择pom.xml右键添加为maven工程
在这里插入图片描述
点击file->project Structure,添加jdk
在这里插入图片描述
在这里插入图片描述

唯一要改的地方就是socket.js下面的tomcat端口号,改为自己的。
在这里插入图片描述
运行
在这里插入图片描述

1.依赖:

	<properties>
        <spring.version>5.1.5.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!--SpringMVC依赖包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!--ServletAPI依赖包-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!--webSocket依赖-->
        <dependency>
            <groupId>javax.websocket</groupId>
            <artifactId>javax.websocket-api</artifactId>
            <version>1.1</version>
        </dependency>
        
        <!--JSON依赖包-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.51</version>
        </dependency>
    </dependencies>

2.web.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         id="WebApp_ID" version="3.0">
      <!-- 项目名,改为自己的 -->   
    <display-name>websocket-demo</display-name>

    <!-- 编码过滤器 -->
    <filter>
        <filter-name>characterEncoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>

        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>characterEncoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--//End 编码过滤器 -->

    <!-- SpringMVC -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--指定SpringMVC核心配置文件的位置-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>

        <!--启动加载优先级-->
        <load-on-startup>1</load-on-startup>
    </servlet>


    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.shtml</url-pattern>
    </servlet-mapping>
    <!-- //End SpringMVC -->

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>

3.springmvc.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        ">
    <!-- 包扫描,写自己的包 -->
    <context:component-scan base-package="com.demo"/>

    <!--注解驱动-->
    <mvc:annotation-driven/>

</beans>

4.websocket后端配置:

package com.demo.websocket.controller;

import org.springframework.stereotype.Controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
//该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。
@ServerEndpoint(value = "/websocket/{id}")
@Controller
public class WebSocketController {
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    public WebSocketController() {
    }
    // 若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    private static Map<String,Session> sessionMap = new HashMap<String,Session>();

    /**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") String id){
        sessionMap.put(id,session);     //加入map中
        addOnlineCount();           //在线数加1
        System.out.println("有新连接加入!id为"+id+",当前在线人数为" + getOnlineCount());
    }
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("id")String id){
        sessionMap.remove(id);  //从map中删除
        subOnlineCount();           //在线数减1
        System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    }
    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     * @param id   用户id标识
     */
    @OnMessage
    public void onMessage(String message, Session session,@PathParam("id")String id) {
        System.out.println("来自客户端"+id+"的消息:" + message);
    }
    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("发生错误");
        error.printStackTrace();
    }
    /**
     * 向客户端发送消息
     * @param message	要发送的消息
     * @param id   用户id标识
     * @throws IOException
     */
    public void sendMessage(String id,String message) throws IOException{
        Session session = sessionMap.get(id);	//获得当前用户的session
        session.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
    public static synchronized void addOnlineCount() {
        WebSocketController.onlineCount++;
    }
    public static synchronized void subOnlineCount() {
        WebSocketController.onlineCount--;
    }
}

5.controller配置,用于调用服务端向客户端发送消息

package com.demo.websocket.controller;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private WebSocketController webSocketController;
    
    /**
     * 调用服务端向客户端发送消息
     * @param id 用户id标识
     * @return
     */
    @RequestMapping("/message")
    public String sendMessage(String id) throws IOException {
        String message = id+"调用服务端向客户端发送消息成功!";
        webSocketController.sendMessage(id,message);
        return "success";
    }

    /**
     * 调用服务端向客户端发送json数据
     * @param id 用户id标识
     * @return
     */
    @RequestMapping("/json")
    public String sendJson(String id) throws IOException {
        Map<String,String> map = new HashMap<String,String>();
        map.put("name","张三");
        map.put("age","22");
        String json = JSON.toJSONString(map);
        webSocketController.sendMessage(id,json);
        return "success";
    }
}

6.前端配置,使用vue完成,所以必须先把vue.js和axios.js导入项目,如图
在这里插入图片描述
然后创建一个js,比如我起的名字是socket.js,然后配置如下:

let ws = {}
let app = new Vue({
    el:'#app',
    data:{
        id:'',  //用户id
        message:'',  //向服务器发送的消息
    },
    methods:{
        //创建webSocket连接
        createSession(){
            //生成随机id,模拟用户唯一id
            this.id=Math.floor(Math.random()*100000+1000)

            if ("WebSocket" in window) {
                // alert("您的浏览器支持 WebSocket!");

                // 打开一个 web socket
                ws = new WebSocket("ws://localhost:28087/websocket/"+this.id);

                ws.onopen = function () {
                    // Web Socket 已连接上,使用 send() 方法发送数据
                    ws.send("发送数据");
                    alert("数据发送中...");
                };

                ws.onmessage = function (evt) {
                    //获取服务端发来的消息
                    alert(evt.data)
                };

                ws.onclose = function () {
                    // 关闭 websocket
                    alert("连接已关闭...");
                };
            }

            else {
                // 浏览器不支持 WebSocket
                alert("您的浏览器不支持 WebSocket!");
            }
        },

        //调用服务端向客户端发送消息
        recallMessage(){
            axios.post('/demo/message.shtml?id='+this.id).then(function (response) {
                console.log(response.data)
            })
        },

        //调用服务端向客户端发送json对象
        recallJson(){
            axios.post('/demo/json.shtml?id='+this.id).then(function (response) {
                console.log(response.data)
            })
        },

        //向客户端发送消息
        sendMessage(){
            ws.send(app.message)
        }
    },
    created(){
        //初始化建立socket连接
        this.createSession();
    }
})

7.html配置如下,为H5

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/js/vuejs-2.5.16.js"></script>
    <script src="/js/axios-0.18.0.js"></script>
</head>
<body>
<div id="app">
    <button @click="recallMessage()">调用服务端向客户端发消息</button><br>
    <button @click="recallJson()">调用服务端向客户端发JSON对象</button>
    <hr/>
    请输入要发送的消息:<input type="text" v-model="message"><br>
    <button @click="sendMessage()">向服务端发送消息</button>
</div>
<script src="/js/socket.js"></script>
</body>
</html>

总结,那个发送json其实就是把对象转换为字符串发送,前端接到的只是json格式的字符串,可以通过一下方法转换为json对象

//可以在ws.onmessage中转换
let json = JSON.parse(evt.data)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值