新网创想网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
今天就跟大家聊聊有关SpringBoot中怎么利用WebSocket实现即时消息,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
成都创新互联从2013年创立,是专业互联网技术服务公司,拥有项目网站建设、网站制作网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元湘乡做网站,已为上家服务,为湘乡各地企业和个人服务,联系电话:028-86922220
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-websocket
抽象消息对象
public class AbstractMessage { /** * 消息类型 */ protected String type ; /** * 消息内容 */ protected String content ; /** * 消息日期 */ protected String date ; }
消息对象子类
1、Ping检查消息
public class PingMessage extends AbstractMessage { public PingMessage() {} public PingMessage(String type) { this.type = type ; } }
2、系统消息
public class SystemMessage extends AbstractMessage { public SystemMessage() {} public SystemMessage(String type, String content) { this.type = type ; this.content = content ; } }
3、点对点消息
public class PersonMessage extends AbstractMessage { private String fromName ; private String toName ; }
消息类型定义
public enum MessageType { /** * 系统消息 0000;心跳检查消息 0001;点对点消息2001 */ SYSTEM("0000"), PING("0001"), PERSON("2001") ; private String type ; private MessageType(String type) { this.type = type ; } public String getType() { return type; } public void setType(String type) { this.type = type; } }
该类作用就是定义客户端连接的地址
@ServerEndpoint(value = "/message/{username}", encoders = {WsMessageEncoder.class}, decoders = {WsMessageDecoder.class}, subprotocols = {"gmsg"}, configurator = MessageConfigurator.class) @Component public class GMessageListener { public static ConcurrentMapsessions = new ConcurrentHashMap<>(); private static Logger logger = LoggerFactory.getLogger(GMessageListener.class) ; private String username ; @OnOpen public void onOpen(Session session, EndpointConfig config, @PathParam("username") String username){ UserSession userSession = new UserSession(session.getId(), username, session) ; this.username = username ; sessions.put(username, userSession) ; logger.info("【{}】用户进入, 当前连接数:{}", username, sessions.size()) ; } @OnClose public void onClose(Session session, CloseReason reason){ UserSession userSession = sessions.remove(this.username) ; if (userSession != null) { logger.info("用户【{}】, 断开连接, 当前连接数:{}", username, sessions.size()) ; } } @OnMessage public void pongMessage(Session session, PongMessage message) { ByteBuffer buffer = message.getApplicationData() ; logger.debug("接受到Pong帧【这是由浏览器发送】:" + buffer.toString()); } @OnMessage public void onMessage(Session session, AbstractMessage message) { if (message instanceof PingMessage) { logger.debug("这里是ping消息"); return ; } if (message instanceof PersonMessage) { PersonMessage personMessage = (PersonMessage) message ; if (this.username.equals(personMessage.getToName())) { logger.info("【{}】收到消息:{}", this.username, personMessage.getContent()); } else { UserSession userSession = sessions.get(personMessage.getToName()) ; if (userSession != null) { try { userSession.getSession().getAsyncRemote().sendText(new ObjectMapper().writeValueAsString(message)) ; } catch (JsonProcessingException e) { e.printStackTrace(); } } } return ; } if (message instanceof SystemMessage) { logger.info("接受到消息类型为【系统消息】") ; return ; } } @OnError public void onError(Session session, Throwable error) { logger.error(error.getMessage()) ; } }
WsMessageEncoder.java类
该类的主要作用是,当发送的消息是对象时,该如何转换
public class WsMessageEncoder implements Encoder.Text{ private static Logger logger = LoggerFactory.getLogger(WsMessageDecoder.class) ; @Override public void init(EndpointConfig endpointConfig) { } @Override public void destroy() { } @Override public String encode(AbstractMessage tm) throws EncodeException { String message = null ; try { message = new ObjectMapper().writeValueAsString(tm); } catch (JsonProcessingException e) { logger.error("JSON处理错误:{}", e) ; } return message; } }
WsMessageDecoder.java类
该类的作用是,当接收到消息时如何转换成对象。
public class WsMessageDecoder implements Decoder.Text{ private static Logger logger = LoggerFactory.getLogger(WsMessageDecoder.class) ; private static Set msgTypes = new HashSet<>() ; static { msgTypes.add(MessageType.PING.getType()) ; msgTypes.add(MessageType.SYSTEM.getType()) ; msgTypes.add(MessageType.PERSON.getType()) ; } @Override @SuppressWarnings("unchecked") public AbstractMessage decode(String s) throws DecodeException { AbstractMessage message = null ; try { ObjectMapper mapper = new ObjectMapper() ; Map map = mapper.readValue(s, Map.class) ; String type = map.get("type") ; switch(type) { case "0000": message = mapper.readValue(s, SystemMessage.class) ; break; case "0001": message = mapper.readValue(s, PingMessage.class) ; break; case "2001": message = mapper.readValue(s, PersonMessage.class) ; break; } } catch (JsonProcessingException e) { logger.error("JSON处理错误:{}", e) ; } return message ; } // 该方法判断消息是否可以被解码(转换) @Override @SuppressWarnings("unchecked") public boolean willDecode(String s) { Map map = new HashMap<>() ; try { map = new ObjectMapper().readValue(s, Map.class); } catch (JsonProcessingException e) { e.printStackTrace(); } logger.debug("检查消息:【" + s + "】是否可以解码") ; String type = map.get("type") ; if (StringUtils.isEmpty(type) || !msgTypes.contains(type)) { return false ; } return true ; } @Override public void init(EndpointConfig endpointConfig) { } @Override public void destroy() { } }
MessageConfigurator.java类
该类的作用是配置服务端点,比如配置握手信息
public class MessageConfigurator extends ServerEndpointConfig.Configurator { private static Logger logger = LoggerFactory.getLogger(MessageConfigurator.class) ; @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { logger.debug("握手请求头信息:" + request.getHeaders()); logger.debug("握手响应头信息:" + response.getHeaders()); super.modifyHandshake(sec, request, response); } }
WebSocke配置类
@Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter (){ return new ServerEndpointExporter(); } }
当以jar包形式运行时需要配置该bean,暴露我们配置的@ServerEndpoint;当我们以war独立tomcat运行时不能配置该bean。
WebSocket
当前用户:
用户:
内容:
到此所有的代码完毕,接下来测试
打开两个标签页,以不同的用户进入。
输入对方用户名发送消息
看完上述内容,你们对SpringBoot中怎么利用WebSocket实现即时消息有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注创新互联行业资讯频道,感谢大家的支持。