java拦截socket_Java WebSocket 基于spring + sockjs + 拦截 + 握手支持IE9

简述:支持发送公告、发送指定用户及异地登录。

,标签需要加入true

该标签支持异步处理,例如WebSocket。

定义收发消息实体类:

package com.test.springWebsocket;

public class WebMessage {

/**

* 用户id

*/

private Long userId;

/**

* 用户名

*/

private String username;

/**

* 客户端标记

*/

private String clientMark;

/**

* 内容

*/

private String contents;

/**

* 消息类型,1.公告,2.点对点发消息,3.检查异地登录

*/

private String type;

public Long getUserId() {

return userId;

}

public void setUserId(Long userId) {

this.userId = userId;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getClientMark() {

return clientMark;

}

public void setClientMark(String clientMark) {

this.clientMark = clientMark;

}

public String getContents() {

return contents;

}

public void setContents(String contents) {

this.contents = contents;

}

public String getType() {

return type;

}

public void setType(String type) {

this.type = type;

}

}

定义WebSocket用户实体类:

package com.test.springWebsocketTwo;

public class WsUser {

/**

* 用户id

*/

private Long userId;

/**

* 用户名

*/

private String username;

/**

* 客户端标记

*/

private String clientMark;

public Long getUserId() {

return userId;

}

public void setUserId(Long userId) {

this.userId = userId;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getClientMark() {

return clientMark;

}

public void setClientMark(String clientMark) {

this.clientMark = clientMark;

}

}

定义握手拦截器类:

package com.test.springWebsocketTwo;

import org.springframework.http.server.ServerHttpRequest;

import org.springframework.http.server.ServerHttpResponse;

import org.springframework.http.server.ServletServerHttpRequest;

import org.springframework.web.socket.WebSocketHandler;

import org.springframework.web.socket.server.HandshakeInterceptor;

import java.util.Map;

/**

* 拦截用户登录信息,并将用户登录信息交给WebSocket的WebSocketSession来管理

*/

public class ImplHandshakeInterceptor implements HandshakeInterceptor {

/**

* 握手之前

*

* @param request ServerHttpRequest

* @param response ServerHttpResponse

* @param wsHandler WebSocketHandler

* @param attributes Map

* @return boolean

* @throws Exception Exception

*/

@Override

public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception {

if (request instanceof ServletServerHttpRequest) {

ServletServerHttpRequest req = (ServletServerHttpRequest) request;

Long userId = Long.parseLong(req.getServletRequest().getParameter("userId"));

String username = req.getServletRequest().getParameter("username");

String clientMark = req.getServletRequest().getParameter("clientMark");

WsUser wsUser = new WsUser();

wsUser.setUserId(userId);

wsUser.setUsername(username);

wsUser.setClientMark(clientMark);

attributes.put("wsUser", wsUser);

}

return true;

}

/**

* 握手之后

*

* @param request ServerHttpRequest

* @param response ServerHttpResponse

* @param wsHandler WebSocketHandler

* @param exception Exception

*/

@Override

public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {

}

}

定义WebSocket处理类:

package com.test.springWebsocketTwo;

import com.google.gson.Gson;

import com.test.springWebsocket.WebMessage;

import org.springframework.web.socket.*;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

/**

* 消息处理类

*/

public class ImplWebSocketHandler implements WebSocketHandler {

private static List sessionList = new ArrayList<>();

private synchronized void addWebSocketSession(WebSocketSession session) {

sessionList.add(session);

}

private synchronized void removeWebSocketSession(WebSocketSession session) {

sessionList.remove(session);

}

/**

* 给所有的用户发送消息

*

* @param webMsg WebMessage

*/

public void sendToAllMsg(WebMessage webMsg) {

String jsonStr = new Gson().toJson(webMsg);

TextMessage textMsg = new TextMessage(jsonStr);

for (WebSocketSession session : sessionList) {

WsUser wsUser = (WsUser) session.getAttributes().get("wsUser");

try {

//isOpen()在线就发送

if (session.isOpen()) {

session.sendMessage(textMsg);

}

} catch (IOException e) {

System.out.println(String.format("用户发送消息失败|消息体", wsUser.getUsername(), jsonStr));

e.printStackTrace();

}

}

}

/**

* 发送消息给指定的用户

*

* @param webMsg WebMessage

*/

public void sendToUserMsg(WebMessage webMsg) {

String jsonStr = new Gson().toJson(webMsg);

TextMessage textMsg = new TextMessage(jsonStr);

for (WebSocketSession session : sessionList) {

WsUser wsUser = (WsUser) session.getAttributes().get("wsUser");

if (wsUser.getUserId().equals(webMsg.getUserId())) {

try {

//isOpen()在线就发送

if (session.isOpen()) {

session.sendMessage(textMsg);

}

} catch (IOException e) {

System.out.println(String.format("用户发送消息失败|消息体", wsUser.getUsername(), jsonStr));

e.printStackTrace();

}

}

}

}

/**

* 连接建立之后

*

* @param session WebSocketSession

* @throws Exception Exception

*/

@Override

public void afterConnectionEstablished(WebSocketSession session) throws Exception {

WsUser wsUser = (WsUser) session.getAttributes().get("wsUser");

WebMessage webMsg = new WebMessage();

webMsg.setUserId(wsUser.getUserId());

webMsg.setUsername(wsUser.getUsername());

webMsg.setClientMark(wsUser.getClientMark());

webMsg.setType("3");

sendToUserMsg(webMsg);

addWebSocketSession(session);

System.out.println(String.format("用户打开WebSocket连接...", wsUser.getUsername()));

}

/**

* 处理消息

*

* @param session WebSocketSession

* @param webSocketMsg WebSocketMessage>

* @throws Exception Exception

*/

@Override

public void handleMessage(WebSocketSession session, WebSocketMessage> webSocketMsg) throws Exception {

String jsonStr = (String) webSocketMsg.getPayload();

WebMessage webMsg = new Gson().fromJson(jsonStr, WebMessage.class);

if (webMsg.getUserId() == null) {

sendToAllMsg(webMsg);

} else {

sendToUserMsg(webMsg);

}

}

/**

* 处理传输错误

*

* @param session WebSocketSession

* @param error Throwable

* @throws Exception Exception

*/

@Override

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

error.printStackTrace();

}

/**

* 连接关闭之后

*

* @param session WebSocketSession

* @param closeStatus CloseStatus

* @throws Exception Exception

*/

@Override

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

WsUser wsUser = (WsUser) session.getAttributes().get("wsUser");

if (session.isOpen()) {

session.close();

}

removeWebSocketSession(session);

System.out.println(String.format("用户关闭WebSocket连接...", wsUser.getUsername()));

}

/**

* WebSocketHandler是否处理部分消息.

* 如果此标志设置为 true并且基础WebSocket服务器支持部分消息,

* 则可能会拆分大型WebSocket消息或其中一个未知大小的消息,

* 并可能通过多次调用接收消息 handleMessage(WebSocketSession, WebSocketMessage).

* 该标志 WebSocketMessage.isLast()指示该消息是否部分以及它是否是最后一部分.

*

* @return boolean

*/

@Override

public boolean supportsPartialMessages() {

return false;

}

}

定义WebSocket配置:

package com.test.springWebsocketTwo;

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;

/**

* @Bean 相当于spring xml里面的bean标签

* @Configuration 等价于xml中配置beans标签

* @EnableWebSocket 对WebSocket的支持

*/

@Configuration

@EnableWebSocket

public class ImplWebSocketConfigurer implements WebSocketConfigurer {

@Override

public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

//WebSocket的支持

registry.addHandler(WebSocketPushHandler(), "/web-socket-server").addInterceptors(new ImplHandshakeInterceptor());

//sock js的支持

registry.addHandler(WebSocketPushHandler(), "/sock-js/web-socket-server").addInterceptors(new ImplHandshakeInterceptor()).withSockJS();

}

@Bean

public WebSocketHandler WebSocketPushHandler() {

return new ImplWebSocketHandler();

}

}

定义页面RequestMapping:

/**

* spring WebSocket two 页面

*

* @param request HttpServletRequest

* @return String

*/

@RequestMapping("/spring-websocket-two.xhtm")

public String springWebsocketTwo(HttpServletRequest request) {

String clientMark = (String) request.getSession().getAttribute("clientMark");

if (clientMark == null) {

clientMark = GenerateUtil.getUUID();

request.getSession().setAttribute("clientMark", clientMark);

}

Admin admin = (Admin) request.getSession().getAttribute("admin");

request.setAttribute("userId", admin.getId());

request.setAttribute("username", admin.getAdmin());

request.setAttribute("clientMark", clientMark);

return "springWebsocketTwo/springWebsocketTwo";

}

定义jsp页面:

String rootPath = request.getContextPath();

String wsBasePath = "ws://" + request.getServerName() + ":" + request.getServerPort() + rootPath + "/";

String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + rootPath + "/";

%>

Spring WebSocket Two

var userId = "${userId}";

var username = "${username}";

var clientMark = "${clientMark}";

var wsBasePath = "";

var basePath = "";

.c_box {

width: 800px;

height: 300px;

border: 1px solid;

overflow: auto;

}

用户id:${userId}
用户名:${username}

公告:

用户id:

消息:

公告列表:
消息列表:

定义JavaScript脚本:

var ws = null;

var wsParams = "?userId=" + userId + "&username=" + username + "&clientMark=" + clientMark;

if ('WebSocket' in window) {

ws = new WebSocket(wsBasePath + "web-socket-server" + wsParams);

} else if ('MozWebSocket' in window) {

ws = new MozWebSocket(wsBasePath + "web-socket-server" + wsParams);

} else {

//兼容低版本浏览器

ws = new SockJS(basePath + "sock-js/web-socket-server" + wsParams);

}

ws.onopen = function (event) {

console.log("WebSocket连接成功");

};

ws.onmessage = function (event) {

showMsg(JSON.parse(event.data));

};

ws.onerror = function (event) {

console.log("WebSocket连接错误");

};

ws.onclose = function (event) {

console.log("WebSocket连接关闭");

};

function closeSocket() {

if (ws == null || ws.readyState == 2 || ws.readyState == 3) {

return true;

}

ws.close();

}

//监听窗口关闭事件,当窗口关闭时,主动去关闭WebSocket连接,防止连接还没断开就关闭窗口,server端会抛异常.

window.onbeforeunload = function () {

closeSocket();

};

function showMsg(webMsg) {

switch (webMsg['type']) {

//公告

case '1': {

var noticeHtm = '

' + webMsg['contents'] + '
';

$('#noticeList').append(noticeHtm);

$("#noticeList").scrollTop($("#noticeList")[0].scrollHeight);

break;

}

//点对点发消息

case '2': {

var msgHtm = '

' + webMsg['contents'] + '
';

$('#msgList').append(msgHtm);

$("#msgList").scrollTop($("#msgList")[0].scrollHeight);

break;

}

//检查异地登录

case '3': {

if (webMsg['clientMark'] != clientMark) {

closeSocket();

alert('您的账号在另一处登录');

}

break;

}

default: {

alert("WebSocket接收到未知消息...");

break;

}

}

}

$("#sendNotice").on("click", function () {

if (ws == null) {

alert('WebSocket连接未打开');

return true;

}

if (ws.readyState == 0) {

alert('WebSocket正在连接中,请稍后再发送消息');

return true;

}

if (ws.readyState == 2) {

alert('WebSocket连接正在关闭中,无法发送消息');

return true;

}

if (ws.readyState == 3) {

alert('WebSocket连接已关闭,无法发送消息');

return true;

}

var notice = $("#notice").val();

if (notice.length > 0) {

var webMsg = {

'contents': notice,

'type': '1'

};

ws.send(JSON.stringify(webMsg));

}

});

$("#sendToUser").on("click", function () {

if (ws == null) {

alert('WebSocket连接未打开');

return true;

}

if (ws.readyState == 0) {

alert('WebSocket正在连接中,请稍后再发送消息');

return true;

}

if (ws.readyState == 2) {

alert('WebSocket连接正在关闭中,无法发送消息');

return true;

}

if (ws.readyState == 3) {

alert('WebSocket连接已关闭,无法发送消息');

return true;

}

var toUserId = $("#toUserId").val();

var toUserMsg = $("#toUserMsg").val();

if (toUserId.length > 0 && toUserMsg.length > 0) {

var webMsg = {

'userId': toUserId,

'username': username,

'contents': toUserMsg,

'type': '2'

};

ws.send(JSON.stringify(webMsg));

}

});

如果想要在service发送消息,如下:

/**

* 发送消息

*/

public void sendMsg() {

WebMessage toAllMsg = new WebMessage();

toAllMsg.setType("1");

toAllMsg.setContents("发送公告...");

getImplWebSocketHandler().sendToAllMsg(toAllMsg);

WebMessage toUserMsg = new WebMessage();

toUserMsg.setType("2");

toUserMsg.setUserId(2L);

toUserMsg.setUsername("Jane");

toUserMsg.setContents("发送消息给指定用户...");

getImplWebSocketHandler().sendToUserMsg(toUserMsg);

}

/**

* 注入消息处理类

*

* @return ImplWebSocketHandler

*/

@Bean

public ImplWebSocketHandler getImplWebSocketHandler() {

return new ImplWebSocketHandler();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值