WebSocket(二)——spring websocket实现前后端通信(服务器端)

步骤一:添加maven依赖
步骤二:编辑SpringWebSocketConfig,xml配置和使用注解两种方式。
registerWebSocketHandlers:这个方法是向spring容器注册一个handler地址,我把他理解成requestMapping。
addInterceptors:拦截器,当建立websocket连接的时候,我们可以通过继承spring的HttpSessionHandshakeInterceptor来搞事情。
setAllowedOrigins:跨域设置,*表示所有域名都可以,不限制, 域包括ip:port, 指定*可以是任意的域名,不加的话默认localhost+本服务端口
withSockJS: 这个是应对浏览器不支持websocket协议的时候降级为轮询的处理。
package com.ssm.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
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 org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
/*
@Configuration的作用
声明当前类是一个配置类
@Configuration不可以是final类型;
@Configuration不可以是匿名类;
嵌套的configuration必须是静态类。
@EnableWebSocket  声明该类支持WebSocket
 */
@Configuration
@EnableWebSocket
public class MySocketConfig implements WebSocketConfigurer {

    //websocket入口,允许访问的域、注册Handler、SockJs支持和拦截器。
    
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(),"/websocket")//入口路径为websocket
                .addInterceptors(new SpringWebSocketHandler())
                .setAllowedOrigins("*");
        //setAllowedOrigins()方法的支持spring4.1.5之后的版本才支持
        //setAllowedOrigins(String... val),允许指定的域名或IP(含端口号)建立长连接,
        // 可以只设置允许自家域名访问,如果不限时使用"*"号,如果指定了域名,
        // 则必须要以http或https开头。
    }

    @Bean
    public WebSocketHandler myHandler(){
        return new MySocketHandler();
    }

    @Bean
    public HttpSessionHandshakeInterceptor myHandlerInterceptor(){
        return new SpringWebSocketHandler();
    }

}
步骤三:编写SpringWebSocketHandlerInterceptor    
这个是创建websocket连接是的拦截器,记录建立连接的用户的session以便根据不同session来通信
package com.ssm.websocket;

import com.lingdian.pojo.User;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.*;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import javax.servlet.http.HttpSession;
import java.util.Map;
/*
握手拦截器类
 */
public class SpringWebSocketHandler extends HttpSessionHandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        System.out.println("Before Handshake");
        //在握手之前将HttpSession中的用户,copy放到WebSocket Session中
        if (request instanceof ServletServerHttpRequest){
            ServletServerHttpRequest servletServerHttpRequest=
                    (ServletServerHttpRequest) request;
            HttpSession session=
                    servletServerHttpRequest.getServletRequest().getSession(true);
            if (null!=session){
               User user=(User)session.getAttribute("user");
               //WebSocket Session
               attributes.put("user",user);
            }
        }
        return super.beforeHandshake(request,response,wsHandler,attributes);
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        super.afterHandshake(request, response, wsHandler, ex);
    }


}

步骤四:编写SpringWebSocketHandler 

 
package com.ssm.websocket;

import com.lingdian.pojo.Message;
import com.lingdian.pojo.User;
import com.lingdian.service.MessageService;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CopyOnWriteArraySet;
/***
 * 消息处理类
 */
public class MySocketHandler extends TextWebSocketHandler {

    //使用CopyOnWriteArraySet,保证线程安全,当一个用户
    // 退出时,这边的用户查看用户列表时不会出现安全失败
    private static CopyOnWriteArraySet<WebSocketSession> users=new CopyOnWriteArraySet<WebSocketSession>();;


    @Resource
    private MessageService messageService;

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //super.handleTextMessage(session, message);
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = sd.format(new Date());
        //从 WebSocket Session中取得用户
        User user=(User) session.getAttributes().get("user");
        Message message1=new Message();
        message1.setUid(user.getId());
        message1.setMessage(message.getPayload());
        message1.setSendTime(new Date());
        //将消息保存到数据库
        messageService.insertMessage(message1);
        //封装要输出的消息到TextMessage,姓名,时间,消息
        TextMessage returnMessage =
                new TextMessage(user.getName()+":" +
                        ""+time+"<br/>"+message.getPayload());
        for (WebSocketSession session1 : users) {
            try{
                //使用sendMessage()方法输出消息到客户端
                session1.sendMessage(returnMessage);
            }catch (Exception e){
                e.printStackTrace();
                continue;
            }

        }
    }

    /**
     * 连接成功时候,会触发页面上onopen方法
     * 加入一个用户 add进集合
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        users.add(session);
        System.out.println("connect to the websocket success......当前数量:"+users.size());

    }

    /**
     * 关闭链接时触发,当用户退出时,将用户从集合remove
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        users.remove(session);
        System.out.println("剩余在线用户"+users.size());
    }

    public static CopyOnWriteArraySet<WebSocketSession> getUsers() {
        return users;
    }

    public static void setUsers(CopyOnWriteArraySet<WebSocketSession> users) {
        MySocketHandler.users = users;
    }

    public MessageService getMessageService() {
        return messageService;
    }

    public void setMessageService(MessageService messageService) {
        this.messageService = messageService;
    }
}

 

posted @ 2019-07-11 14:10  TangXinPing  阅读(1974)  评论(0编辑  收藏  举报