前后端实现webSocket
自己尝试学习webSocket实现,若有好的意见请指出。
新建一个测试客户端jsp:
<script type="text/javascript">
var ws = null;
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window) {
ws = new WebSocket("ws://192.168.2.123:8085/fushan/api/webSocket");
}else{
alert('当前浏览器 Not support websocket');
}
/*
*监听三种状态的变化js会回调
*/
ws.onopen = function(message) {
// 连接回调
};
ws.onclose = function(message) {
// 断开连接回调
};
ws.onmessage = function(message) {
// 消息监听
var obj = JSON.parse(message.data);
$('#testValue').val(obj.data);
};
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
ws.close();
};
//关闭连接
function closeWebSocket() {
ws.close();
}
</script>
<body>
<div class="form-group">
<label for="testValue" class="col-sm-2 control-label">数据值</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="testValue">
</div>
</div>
</body>
后台服务端部分:
@ServerEndpoint(value = "/api/webSocket")
public class WebSocket {
static private Logger logger = Logger.getLogger(WebSocket.class);
private static int onlineCount = 0;
private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
private Session session;
@OnOpen
public void onOpen(Session session) throws IOException {
InetSocketAddress as = getRemoteAddress(session);
this.session = session;
String key = as.toString();
String makey = key.substring(1, key.length());
addOnlineCount();
clients.put(makey, this);
logger.info("新建连接客户端:" + makey);
}
@OnClose
public void onClose(Session session) throws IOException {
InetSocketAddress as = getRemoteAddress(session);
String key = as.toString();
String makey = key.substring(1, key.length());
clients.remove(makey);
subOnlineCount();
logger.info("关闭连接客户端:" + makey);
}
@OnMessage
public void onMessage(String message) throws IOException {
sendMessage(message);
}
@OnError
public void onError(Session session, Throwable error) {
logger.error("error:" + error);
}
public static void sendMessage(String message) throws IOException {
for (WebSocket item : clients.values()) {
item.session.getAsyncRemote().sendText(message);
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocket.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocket.onlineCount--;
}
public static synchronized Map<String, WebSocket> getClients() {
return clients;
}
public static InetSocketAddress getRemoteAddress(Session session) {
if (session == null) {
return null;
}
Async async = session.getAsyncRemote();
// 在Tomcat 8.0.x版本有效
InetSocketAddress addr = (InetSocketAddress) getFieldInstance(async,"base#sos#socketWrapper#socket#sc#remoteAddress");
// 在Tomcat 8.5以上版本有效
//InetSocketAddress addr = (InetSocketAddress) getFieldInstance(async,"base#socketWrapper#socket#sc#remoteAddress");
return addr;
}
private static Object getFieldInstance(Object obj, String fieldPath) {
String fields[] = fieldPath.split("#");
for (String field : fields) {
obj = getField(obj, obj.getClass(), field);
if (obj == null) {
return null;
}
}
return obj;
}
private static Object getField(Object obj, Class<?> clazz, String fieldName) {
for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
try {
Field field;
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
} catch (Exception e) {
}
}
return null;
}
}
编写一个测试接口,再用postman工具发送所想要显示的内容
@RequestMapping(value = "test/api/websocket", method = RequestMethod.POST, produces = {"application/json;charset=utf-8"})
@ResponseBody
public String webSocketTest(HttpServletRequest request, HttpServletResponse response) throws Exception{
JSONObject json = new JSONObject();
String testData = request.getParameter("testData");
json.put("data", testData);
json.put("success", true);
WebSocket.sendMessage(json.toString());
return json.toString();
}