SpringMVC+WebSocket

1 根据我的另一篇博客创建一个web框架的maven工程

https://blog.csdn.net/u014377655/article/details/81332959

 

2 在工程中添加文件

结构如下图

SpringMVC+WebSocket_第1张图片

 

3 配置spring-mvc.xml

 

4 jsp以及类内容

index.jsp







Hello World!

   
        username:            

ws.jsp







    WebSocket测试页



    

    

    






    Input:        

 

SpringWebSocketConfig

public class SpringWebSocketConfig extends WebMvcConfigurerAdapter implements

        WebSocketConfigurer {

    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

        registry.addHandler(webSocketHandler(),"/websocket/socketServer.do").addInterceptors(new SpringWebSocketHandlerInterceptor());

        registry.addHandler(webSocketHandler(), "/sockjs/socketServer.do").addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();

    }

    @Bean

    public TextWebSocketHandler webSocketHandler(){

        return new SpringWebSocketHandler();
    }
}

SpringWebSocketHandler

public class SpringWebSocketHandler extends TextWebSocketHandler {



    //在线用户列表

    private static final Map users;

    static {
        users = new HashMap<>();
    }
    public SpringWebSocketHandler() { }


    /**

     * 建立连接后触发的回调

     * 记录用户的连接标识,便于后面发信息,

     * 这里我是记录将id记录在Map集合中。

     * 一个Map中不能包含相同的key,每个key只能映射一个value,根据先后put的顺序覆盖

     * @param session

     * @throws Exception

     */

    @Override

    public void afterConnectionEstablished(WebSocketSession session) throws Exception {

        System.out.println("成功建立连接");

        String userName = getClientId(session);
        if (userName != null) {
            System.out.println("用户"+userName+"登录!");
            users.put(userName, session);
            session.sendMessage(new TextMessage("server:成功建立socket连接"));
            System.out.println("当前在线用户"+users.size()+": "+users);

        }

        //userName为空时,不存储该用户,不与该用户交互

    }
    /**

     * 断开连接后触发的回调

     * 连接已关闭,移除在Map集合中的记录。

     * @param session

     * @param closeStatus

     * @throws Exception

     */

    @Override

    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {

        String userName = getClientId(session);

        System.out.println("\n用户"+userName+"已退出: " + closeStatus);

        users.remove(userName);

        System.out.println("剩余在线用户"+users.size()+": "+users);

    }

    /**

     * 收到消息时触发的回调

     * 对H5 Websocket的send方法进行处理

     * @param session

     * @param message

     */

    @Override

    public void handleTextMessage(WebSocketSession session, TextMessage message) {

        //显示客户端发送过来的消息内容

        System.out.println("client:"+message.getPayload());
        WebSocketMessage message1 = new TextMessage("server:"+message);

        try {
            session.sendMessage(message1);
        } catch (IOException e) {

            e.printStackTrace();
        }
    }


    /**

     * 传输消息出错时触发的回调

     * 连接出错处理,主要是关闭出错会话的连接,和删除在Map集合中的记录

     * @param session

     * @param exception

     * @throws Exception

     */

    @Override

    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

        if (session.isOpen()) {

            session.close();

        }
        System.out.println("连接出错");
        users.remove(getClientId(session));

    }

    /**

     * 是否处理分片消息

     * @return

     */

    public boolean supportsPartialMessages() {
        return false;
    }


    /**

     * 发送信息给指定用户

     * 传入用户标识和消息体

     * @param clientId

     * @param message

     * @return

     */

    public boolean sendMessageToUser(String clientId, TextMessage message) {

        if (users.get(clientId) == null) return false;

        WebSocketSession session = users.get(clientId);

        System.out.println("sendMessage:" + session);

        if (!session.isOpen()) return false;

        try {

            session.sendMessage(message);

        } catch (IOException e) {

            e.printStackTrace();

            return false;

        }

        return true;

    }


    /**

     * 广播信息

     * 只需要传入消息体

     * @param message

     * @return

     */

    public boolean sendMessageToAllUsers(TextMessage message) {

        boolean allSendSuccess = true;

        Set clientIds = users.keySet();

        WebSocketSession session = null;

        for (String clientId : clientIds) {

            try {

                session = users.get(clientId);

                if (session.isOpen()) {

                    session.sendMessage(message);

                }

            } catch (IOException e) {

                e.printStackTrace();

                allSendSuccess = false;

            }

        }
        return  allSendSuccess;
    }



    /**

     * 获取用户标识

     * @param session

     * @return

     */

    private String getClientId(WebSocketSession session) {

        try {

            String clientId = (String)session.getAttributes().get(Const.CLIENT_NAME);

            return clientId;

        } catch (Exception e) {

            return null;
        }

    }

}

SpringWebSocketHandlerInterceptor

public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
   @Override

    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,

                                   WebSocketHandler wsHandler, Map attributes) throws Exception 

        System.out.println("Before Handshake");

        if (request instanceof ServletServerHttpRequest) {

            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;

            HttpSession session = servletRequest.getServletRequest().getSession(false);

            if (session != null) {

                //使用userName区分WebSocketHandler,以便定向发送消息

                String userName = (String) session.getAttribute("userName");

                if (userName==null) {

                    userName="default-system";

                }

                attributes.put("userName",userName);

            }else{

                System.out.println("beforeHandshake 没有获取到 session");

            }

        }

        return super.beforeHandshake(request, response, wsHandler, attributes);

    }

    @Override

    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,

                               WebSocketHandler wsHandler, Exception ex) {

        System.out.println("After Handshake");

        super.afterHandshake(request, response, wsHandler, ex);
    }
}
 

controller

@Controller

public class WebsocketController {
@Bean

public SpringWebSocketHandler infoHandler() {

    return new SpringWebSocketHandler();

}

@RequestMapping("/websocket/login")

public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {

    String userName = request.getParameter("userName");

    System.out.println(userName+"登录");



    HttpSession session = request.getSession(false);

    session.setAttribute(Const.CLIENT_NAME, userName);

    ModelAndView mv = new ModelAndView();
    mv.setViewName("ws");

    return mv;

}}

5 测试

SpringMVC+WebSocket_第2张图片

输入用户名,点击login

跳转至

SpringMVC+WebSocket_第3张图片

 

发送消息测试

SpringMVC+WebSocket_第4张图片

参考博文

spring配置websocket并实现群发/单独发送消息

https://blog.csdn.net/u014520745/article/details/62046396

Spring WebSocket实现消息推送

https://www.cnblogs.com/3dianpomian/p/5902084.html

你可能感兴趣的:(SpringMVC,WebSocket,SpringMVC,聊天)