昨天试验的内容是直接通过handler接收和发送消息。
今天继续试验。试验内容是加一个controller类,处理页面正常的http请求。
1.新建controller类
package com.test.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.socket.TextMessage;
import com.alibaba.fastjson.JSONObject;
import com.test.utils.HttpUtil;
import com.test.ws.MyWebSocketHandler;
@Controller
public class SocketController {
@Autowired
private MyWebSocketHandler myWebSocketHandler;
/**
* 此处用orderno参数做id来区分不同的广播频道(或者说聊天室频道等)
* @param session httpSession
* @param orderno 频道id
* @param request
* @param response
*/
@RequestMapping(value="/login/{orderno}")
public void login(HttpSession session, @PathVariable("orderno") String orderno, HttpServletRequest request, HttpServletResponse response){
System.out.println("orderno:" + orderno);
response.setContentType("application/json");
// 处理本次请求的相关业务,如数据库的增删改查等
// 处理完成后,向其他在同频道的人广播
// 要发送内容
JSONObject obj = new JSONObject();
obj.put("test", "test1");
obj.put("orderno", orderno);
try {
myWebSocketHandler.sendMsgToAllUsersByOrder(orderno, new TextMessage(obj.toString()));
} catch (Exception e) {
e.printStackTrace();
}
// 本次请求的处理返回内容
HttpUtil.writeJson(HttpUtil.getJsonSuccess().toString(), response);
}
}
只是一种写法,其实可以单纯的写成一般的controller类就行。
比如定义方法: public void doSomething(HttpServletRequest req, HttpServletResponse res){
}
2.修改handlerInterceptor
package com.test.ws;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
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.support.HttpSessionHandshakeInterceptor;
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
// 在握手之前执行该方法, 继续握手返回true, 中断握手返回false. 通过attributes参数设置WebSocketSession的属性
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
System.out.println(" HandshakeInterceptor: beforeHandshake "+attributes);
// 从request中取得参数,orderno作为区分不同广播频道的id,将其设置到attributes参数中,
System.out.println("request instanceof ServletServerHttpRequest");
HttpServletRequest req = ((ServletServerHttpRequest) request).getServletRequest();
String orderid= req.getParameter("orderno");
System.out.println("request get orderid:" + orderid);
attributes.put("order_id", orderid);
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}
// 握手后
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println(" HandshakeInterceptor: afterHandshake ");
super.afterHandshake(request, response, wsHandler, ex);
}
}
3.修改handler类
package com.test.ws;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
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;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class MyWebSocketHandler implements WebSocketHandler {
private static final Map<String,Set<WebSocketSession>> orderSession;
static{
orderSession = new HashMap<String,Set<WebSocketSession>>();
}
// 关闭 连接时
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus arg1)
throws Exception {
System.out.println("session:" + session.getId() + " connect websocket closed.......");
removeSession(session);
}
// 连接 就绪时
@Override
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
System.out.println("connect websocket success.......");
if (!hasSession(session)){
putSession(session);
}
}
// 处理客户端发来的信息
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message)
throws Exception {
// 无此功能需求
Gson gson = new Gson();
// 将消息JSON格式通过Gson转换成Map
// message.getPayload().toString() 获取消息具体内容
Map<String, Object> msg = gson.fromJson(message.getPayload().toString(),
new TypeToken<Map<String, Object>>() {}.getType());
System.out.println("handleMessage......."+message.getPayload()+"..........."+msg);
session.sendMessage(message);
// 处理消息 msgContent消息内容
TextMessage textMessage = new TextMessage(msg.get("msgContent").toString(), true);
String orderno = getOrderno(session);
// 调用方法(发送消息给所有人)
sendMsgToAllUsersByOrder(orderno, textMessage);
}
// 处理传输时异常
@Override
public void handleTransportError(WebSocketSession session, Throwable arg1)
throws Exception {
System.out.println("session:" + session.getId() + " handleTransportError");
}
@Override
public boolean supportsPartialMessages() {
return false;
}
// 给该orderno页面的所有用户发送 信息
public void sendMsgToAllUsersByOrder(String orderno, WebSocketMessage<?> message) throws Exception{
if(!orderSession.isEmpty() && orderSession.containsKey(orderno)){
Set<WebSocketSession> orderSet = orderSession.get(orderno);
Iterator<WebSocketSession> orderIt = orderSet.iterator();
while(orderIt.hasNext()){
WebSocketSession session = orderIt.next();
session.sendMessage(message);
}
}
}
private String getOrderno(WebSocketSession session){
return (String) session.getAttributes().get("order_id");
}
private boolean hasSession(WebSocketSession session){
if(orderSession.isEmpty()){
return false;
} else {
String orderno = getOrderno(session);
if (orderSession.containsKey(orderno)){
Set<WebSocketSession> orderSet = orderSession.get(orderno);
if(orderSet.contains(session)){
return true;
} else {
return false;
}
} else {
return false;
}
}
}
private void putSession(WebSocketSession session){
String orderno = getOrderno(session);
if (orderSession.isEmpty() || !orderSession.containsKey(orderno)){
Set<WebSocketSession> orderSet = new HashSet<WebSocketSession>();
orderSet.add(session);
orderSession.put(orderno, orderSet);
} else {
Set<WebSocketSession> orderSet = orderSession.get(orderno);
orderSet.add(session);
orderSession.put(orderno, orderSet);
}
}
private void removeSession(WebSocketSession session){
String orderno = getOrderno(session);
if (!orderSession.isEmpty() && orderSession.containsKey(orderno)){
Set<WebSocketSession> orderSet = orderSession.get(orderno);
orderSet.remove(session);
if (!orderSet.isEmpty()){
orderSession.put(orderno, orderSet);
} else {
orderSession.remove(orderno);
}
}
}
}
4.修改页面上的js
<!DOCTYPE HTML>
<html>
<head>
<title>首页</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
<!-- 引入 JQuery -->
<script type="text/javascript" src="E:\test\jquery-3.3.1.min.js"></script>
<!-- 引入 sockJS
<script type="text/javascript" src="sockjs.min.js" ></script>-->
<!-- 自定义JS文件 -->
<script type="text/javascript" >
$(function() {
var websocket;
// 正常用ajax去调用http请求
$.ajax({url:"http://localhost:8080/testSpringWebsocket/login/4",
type:"POST",
data: {'usr':'123'},
dataType:'json',
success:function(result){
// ajax处理正常时,建立websocket链接,链接成功后就可以发送消息和接收消息
if('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/testSpringWebsocket/websocket?orderno=4");
} else if('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://localhost:8080/testSpringWebsocket/websocket?orderno=4");
} else {
websocket = new SockJS("http://localhost:8080/testSpringWebsocket/sockjs/websocket?orderno=4");
}
// 打开时
websocket.onopen = function(evnt) {
console.log(" websocket.onopen ");
};
// 处理消息时
websocket.onmessage = function(evnt) {
$("#msg").append("<p>(<font color='red'>" + evnt.data + "</font>)</p>");
console.log(" websocket.onmessage ");
};
websocket.onerror = function(evnt) {
console.log(" websocket.onerror ");
};
websocket.onclose = function(evnt) {
console.log(" websocket.onclose ");
};
// 点击了发送消息按钮的响应事件
$("#TXBTN").click(function(){
// 获取消息内容
var text = $("#tx").val();
// 判断
if(text == null || text == ""){
alert(" content can not empty!!");
return false;
}
var msg = {
msgContent: text,
postsId: 1
};
// 发送消息
websocket.send(JSON.stringify(msg));
});
}});
});
</script>
</head>
<body>
<!-- 最外边框 -->
<div style="margin: 20px auto; border: 1px solid blue; width: 300px; height: 500px;">
<!-- 消息展示框 -->
<div id="msg" style="width: 100%; height: 70%; border: 1px solid yellow;overflow: auto;"></div>
<!-- 消息编辑框 -->
<textarea id="tx" style="width: 100%; height: 20%;"></textarea>
<!-- 消息发送按钮 -->
<button id="TXBTN" style="width: 100%; height: 8%;">发送数据</button>
</div>
</body>
</html>
5.spring.xml文件中
<!-- websocket处理类 -->
<bean id="myHandler" class="com.test.ws.MyWebSocketHandler"/>
目前有个疑问,用注解方式,tomcat启动报错,也不能访问。尝试过的注解有@Component和@Service。两个都不行。暂时没去解决。等有时间再看。
昨天的第一次试验的内容:https://blog.youkuaiyun.com/bengdird/article/details/79655314