设计初衷是通过websocket实现网页实时通讯聊天。

工程环境:tomcat8+jdk1.7+maven+eclipse

设计思路:客户端登录网页建立socket连接,后台记录用户连接信息并做标识;当用户在网页端发送聊天消息至后台,后台收到信息后将消息发送至接收者,同时后端对消息进行持久保存。

简要代码实现demo如下:

1、pom.xml主要配置

<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>

<!-- AspectJ -->
<!-- <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency> -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>

2、spring核心配置信息
<context:component-scan base-package="com.milanosoft.RCS.web.webSocket.config" />

<context:component-scan base-package="com.milanosoft.RCS.web.webSocket.hndler">
</context:component-scan>

<context:component-scan base-package="com.milanosoft.RCS.web.webSocket.interceptor">
</context:component-scan>

3、websocket服务端实现
package com.milanosoft.RCS.web.webSocket.config;

import com.milanosoft.RCS.web.webSocket.hndler.SystemWebSocketHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
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 com.milanosoft.RCS.web.webSocket.interceptor.HandshakeInterceptor;
import org.springframework.context.annotation.Bean;

@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements
WebSocketConfigurer {

public WebSocketConfig() {
}

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(systemWebSocketHandler(), "/websck").addInterceptors(new HandshakeInterceptor());

System.out.println("registed!");
registry.addHandler(systemWebSocketHandler(), "/sockjs/websck").addInterceptors(new HandshakeInterceptor())
.withSockJS();

}

@Bean
public WebSocketHandler systemWebSocketHandler() {
//return new InfoSocketEndPoint();
return new SystemWebSocketHandler();
}

}

4、websocket连接前后的事件类
package com.milanosoft.RCS.web.webSocket.interceptor;

import java.util.Map;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

@Component
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {

@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {

//解决The extension [x-webkit-deflate-frame] is not supported问题
if(request.getHeaders().containsKey("Sec-WebSocket-Extensions")) {
request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
}

System.out.println("Before Handshake");
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);
}

}

//解决The extension [x-webkit-deflate-frame] is not supported问题
        if(request.getHeaders().containsKey("Sec-WebSocket-Extensions")) {
            request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
        }

其中标红色的代码是为了解决下面的错误,可能是ios手机safari浏览器版本问题引起的。

org.springframework.web.socket.server.HandshakeFailureException: Uncaught failure for request http://localhost:8080/spring4/myHandler; nested exception is java.lang.IllegalArgumentException: The extension [x-webkit-deflate-frame] is not supported

5、websocket消息处理类

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.milanosoft.RCS.web.webSocket.hndler;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

/**
*
* @author lzk
*/
@Component
public class SystemWebSocketHandler implements WebSocketHandler {

@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("connect to the websocket success......");
session.sendMessage(new TextMessage("Server:connected OK!"));
}

@Override
public void handleMessage(WebSocketSession wss, WebSocketMessage<?> wsm) throws Exception {
TextMessage returnMessage = new TextMessage(wsm.getPayload()
+ " received at server");
System.out.println(wss.getHandshakeHeaders().getFirst("Cookie"));
wss.sendMessage(returnMessage);
}

@Override
public void handleTransportError(WebSocketSession wss, Throwable thrwbl) throws Exception {
if(wss.isOpen()){
wss.close();
}
System.out.println("websocket connection closed......");
}

@Override
public void afterConnectionClosed(WebSocketSession wss, CloseStatus cs) throws Exception {
System.out.println("websocket connection closed......");
}

@Override
public boolean supportsPartialMessages() {
return false;
}

}

6、客户端页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<%session.setAttribute("user", "lzk"); %>
<title>WebSocket/SockJS Echo Sample (Adapted from Tomcat's echo sample)</title>
<style type="text/css">
#connect-container {
float: left;
width: 400px
}

#connect-container div {
padding: 5px;
}

#console-container {
float: left;
margin-left: 15px;
width: 400px;
}

#console {
border: 1px solid #CCCCCC;
border-right-color: #999999;
border-bottom-color: #999999;
height: 170px;
overflow-y: scroll;
padding: 5px;
width: 100%;
}

#console p {
padding: 0;
margin: 0;
}
</style>

<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>

<script type="text/javascript">
var ws = null;
var url = null;
var transports = [];

function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('echo').disabled = !connected;
}

function connect() {
//alert(url);
//console.log(url);
if (!url) {
alert('Select whether to use W3C WebSocket or SockJS');
return;
}

//ws = (url.indexOf('sockjs') != -1) ?new SockJS(url, undefined, {protocols_whitelist: transports}) : new WebSocket(url);
if ('WebSocket' in window) {
ws= new WebSocket("ws://192.168.1.104:8080/SpringWebSocketPush/websck");
console.log("ws://192.168.1.104:8080/SpringWebSocketPush/websck");
}else {
ws = new SockJS("http://192.168.1.104:8080/SpringWebSocketPush/sockjs/websck");
console.log("http://192.168.1.104:8080/SpringWebSocketPush/sockjs/websck");
}
//websocket = new SockJS("http://localhost:8080/SpringWebSocketPush/sockjs/websck");
ws.onopen = function () {
alert('open');
setConnected(true);
//log('Info: connection opened.');
};
ws.onmessage = function (event) {
alert('Received:' + event.data);
log('Received: ' + event.data);
};
ws.onclose = function (event) {
setConnected(false);
log('Info: connection closed.');
log(event);
};
}

function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
setConnected(false);
}

function echo() {
if (ws != null) {
var message = document.getElementById('message').value;
log('Sent: ' + message);
ws.send(message);
} else {
alert('connection not established, please connect.');
}
}

function updateUrl(urlPath) {
if (urlPath.indexOf('sockjs') != -1) {
url = urlPath;
document.getElementById('sockJsTransportSelect').style.visibility = 'visible';
}
else {
if (window.location.protocol == 'http:') {
url = 'ws://' + window.location.host + urlPath;
} else {
url = 'wss://' + window.location.host + urlPath;
}
document.getElementById('sockJsTransportSelect').style.visibility = 'hidden';
}
}

function updateTransport(transport) {
alert(transport);
transports = (transport == 'all') ? [] : [transport];
}

function log(message) {
var console = document.getElementById('console');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(message));
console.appendChild(p);
while (console.childNodes.length > 25) {
console.removeChild(console.firstChild);
}
console.scrollTop = console.scrollHeight;
}
</script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets
rely on Javascript being enabled. Please enable
Javascript and reload this page!</h2></noscript>
<div>
<br>
<div id="connect-container">
<input id="radio1" type="radio" name="group1" οnclick="updateUrl('/SpringWebSocketPush/websck');">
<label for="radio1">W3C WebSocket</label>
<br>
<input id="radio2" type="radio" name="group1" οnclick="updateUrl('/SpringWebSocketPush/sockjs/websck');">
<label for="radio2">SockJS</label>
<div id="sockJsTransportSelect" style="visibility:hidden;">
<span>SockJS transport:</span>
<select οnchange="updateTransport(this.value)">
<option value="all">all</option>
<option value="websocket">websocket</option>
<option value="xhr-polling">xhr-polling</option>
<option value="jsonp-polling">jsonp-polling</option>
<option value="xhr-streaming">xhr-streaming</option>
<option value="iframe-eventsource">iframe-eventsource</option>
<option value="iframe-htmlfile">iframe-htmlfile</option>
</select>
</div>
<div>
<button id="connect" οnclick="connect();">Connect</button>
<button id="disconnect" disabled="disabled" οnclick="disconnect();">Disconnect</button>
</div>
<div>
<textarea id="message" style="width: 350px">Here is a message!</textarea>
</div>
<div>
<button id="echo" οnclick="echo();" disabled="disabled">Echo message</button>
</div>
</div>
<div id="console-container">
<div id="console"></div>
</div>
</div>
</body>

</html>

这个例子也是在别人的代码基础上进行了一些修改,修复了一些BUG。

Spring+WebSocket+SockJS实现实时聊天的更多相关文章

  1. Spring Websocket实现简易在线聊天功能

    针对Spring Websocket的实现,我参照了其他博主的文章https://www.cnblogs.com/leechenxiang/p/5306372.html 下面直接给出实现: 一.引入相 ...

  2. 学习WebSocket(二):使用Spring WebSocket做一个简单聊天室

    聊天室高频率.低延时完全符合websocket的特点,所以聊天室使用websocket再适合不过了. 聊天室的功能并没有比上一节代码多多少,主要在握手阶段对用户的session做处理,对用户的消息进行 ...

  3. web即时通讯2--基于Spring websocket达到web聊天室

    如本文所用,Spring4和websocket要构建web聊天室,根据框架SpringMVC+Spring+Hibernate的Maven项目,后台使用spring websocket进行消息转发和聊 ...

  4. Spring 学习——基于Spring WebSocket 和STOMP实现简单的聊天功能

    本篇主要讲解如何使用Spring websocket 和STOMP搭建一个简单的聊天功能项目,里面使用到的技术,如websocket和STOMP等会简单介绍,不会太深,如果对相关介绍不是很了解的,请自 ...

  5. 网页实时聊天之PHP实现websocket

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  6. vue+websocket+express+mongodb实战项目(实时聊天)

    继上一个项目用vuejs仿网易云音乐(实现听歌以及搜索功能)后,发现上一个项目单纯用vue的model管理十分混乱,然后我去看了看vuex,打算做一个项目练练手,又不想做一个重复的项目,这次我就放弃颜 ...

  7. vue+websocket+express+mongodb实战项目(实时聊天)(二)

    原项目地址:[ vue+websocket+express+mongodb实战项目(实时聊天)(一)][http://blog.csdn.net/blueblueskyhua/article/deta ...

  8. php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室)

    php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室) 一.总结 1.ajax长轮询和websocket都可以时间网络聊天室 ...

  9. 网页实时聊天之PHP如何实现websocket

    网页实时聊天之PHP如何实现websocket 一.总结 一句话总结: 应用 PHP 的 socket 函数库:PHP 的 socket 函数库跟 C 语言的 socket 函数非常类似 PHP 实现 ...

随机推荐

  1. 简易商城 [ html + css ] 练习

    1. 前言 通过使用 HTML + CSS 编写一个简易商城首页. 如图: 2. 布局思路 通过页面分析,大致可以决定页面的布局分为 5 大板块. 接下来,可以先定义页面的布局: <!DOCTY ...

  2. [LeetCode] 801. Minimum Swaps To Make Sequences Increasing 最少交换使得序列递增

    We have two integer sequences A and B of the same non-zero length. We are allowed to swap elements A ...

  3. mac的brew安装tomcat以及idea设置

    Tomcat安装 brew search tomat 有tomcat@7. tomcat@8. tomcat最新版本(即tomcat9)三个版本 brew install tomcat 启动tomca ...

  4. python:当文件中出现特定字符串时执行robot用例

    #coding:utf-8 import os import datetime import time def execute_rpt_db_full_effe_cainiao_city(): fla ...

  5. UE4 window打包ios备忘

    1.生成SHH key 2.安装证书 *.cer,*.p12 以下转自:http://wangjie.rocks/2017/11/30/ue4-ios-build-on-windows/ 问题一 12 ...

  6. Metricbeat 轻量型指标采集器

    一.介绍 用于从系统和服务收集指标.从 CPU 到内存,从 Redis 到 Nginx,Metricbeat 能够以一种轻量型的方式,输送各种系统和服务统计数据. 1.系统级监控,更简洁(轻量型指标采 ...

  7. VS2019/VS2017设置默认管理员权限启动

    找到vs安装目录下的:C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\devenv.exe 右键- ...

  8. (转)JVM原理讲解和调优

    背景:jvm实际调优在面试时候经常被问到,所以有必要认真总结一番. 转自:JVM原理讲解和调优 四.JVM内存调优 首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存 ...

  9. appium 弹窗处理

    测试过程中遇到两类弹窗: 系统权限弹窗具体业务弹窗系统权限弹窗Android系统权限弹窗一般出现在安装 app 后首次打开,如:定位权限.电话权限等.我们可以按顺序执行测试用例,将该类操作放到 Ini ...

  10. SpringBoot + Mybatis搭建完整的项目架构

    准备工作: Java开发环境 已安装 springboot 插件(STS)的 Eclipse MySQL服务  一. 创建 springboot 项目 1. 打开Eclipse  --> 左上角 ...