总共是三个步骤
一、创建webSocketHandler处理器继承TextWebSocketHandler
@component
public class MyWebSocketHandler extends TextWebSocketHandler
1.定义一个成员变量,保存用户与对应的WebSocketSession对应关系
public static final Map<String, WebSocketSession> userSocketSessionMap;
初始化
static {
userSocketSessionMap = new HashMap<String, WebSocketSession>();
}
2.建立连接之后就保存每个用户和webSocketSession
/**
* 建立连接后
*/
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
Long uid = (Long) session.getAttributes().get("uid");
if (userSocketSessionMap.get(uid) == null) {
userSocketSessionMap.put(uid, session);
}
}
3.
/**
* 消息处理,在客户端通过Websocket API发送的消息会经过这里,然后进行相应的处理,在这里可以进行消息的推送
不在这里面推送就直接就调用父类方法
/**
* js调用websocket.send时候,会调用该方法
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
super.handleTextMessage(session, message);
}
*/
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
if(message.getPayloadLength()==0)return;
Message msg=new Gson().fromJson(message.getPayload().toString(),Message.class);
msg.setDate(new Date());
sendMessageToUser(msg.getTo(), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
}
4.消息传输错误处理
/**
* 消息传输错误处理
*/
public void handleTransportError(WebSocketSession session,
Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
Iterator<Entry<Long, WebSocketSession>> it = userSocketSessionMap
.entrySet().iterator();
// 移除Socket会话
while (it.hasNext()) {
Entry<Long, WebSocketSession> entry = it.next();
if (entry.getValue().getId().equals(session.getId())) {
userSocketSessionMap.remove(entry.getKey());
System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
break;
}
}
}
5.关闭连接
/**
* 关闭连接后
*/
public void afterConnectionClosed(WebSocketSession session,
CloseStatus closeStatus) throws Exception {
System.out.println("Websocket:" + session.getId() + "已经关闭");
Iterator<Entry<Long, WebSocketSession>> it = userSocketSessionMap
.entrySet().iterator();
// 移除Socket会话
while (it.hasNext()) {
Entry<Long, WebSocketSession> entry = it.next();
if (entry.getValue().getId().equals(session.getId())) {
userSocketSessionMap.remove(entry.getKey());
System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
break;
}
}
}
6.给指定的用户推送信息
/**
* 给某个用户发送消息
*
* @param userName
* @param message
* @throws IOException
*/
public void sendMessageToUser(Long uid, TextMessage message)
throws IOException {
WebSocketSession session = userSocketSessionMap.get(uid);
if (session != null && session.isOpen()) {
session.sendMessage(message);
}
}
二、websocket拦截器HandShakeInterceptor,建立连接握手和断开
01在握手之前执行该方法,继续握手返回true中断返回false
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
System.out.println("Websocket:用户[ID:" + ((ServletServerHttpRequest) request).getServletRequest().getSession(false).getAttribute("uid") + "]已经建立连接");
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpSession session = servletRequest.getServletRequest().getSession(false);
// 标记用户
Long uid = (Long) session.getAttribute("uid");
if(uid!=null){
attributes.put("uid", uid);
}else{
return false;
}
}
return true;
}
02握手之后执行的方法,无论握手成功都会指明了响应状态码和响应头,这个方法一般都是空实现
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
三、WebSocket配置处理器,在这里面把处理器和拦截器都注册进来
/**
* WebScoket配置处理器
* @author Goofy
* @Date 2015年6月11日 下午1:15:09
*/
@Component
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer
01定义一个handler成员变量用@Autowired注入进来
@Autowired
private SpringWebSocketHandler springWebSocketHandler;
02添加handler和拦截器
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(springWebSocketHandler, "/websocket/socketServer").addInterceptors(new SpringWebSocketHandlerInterceptor());
registry.addHandler(springWebSocketHandler, "/sockjs/socketServer").addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();
}
四、创建一个Controller进行测试
@Controller
public class WebsocketController {
@Bean//这个注解会从Spring容器拿出Bean
public SpringWebSocketHandler infoHandler() {
return new SpringWebSocketHandler();
}
登录,保存用户到session
@RequestMapping("/websocket/login")
@ResponseBody
public String login(HttpServletRequest request, ModelMap model) throws Exception {
String username = request.getParameter("username");
System.out.println(username+"登录");
request.getSession().setAttribute("WEBSOCKET_USERNAME", username);
return "websocket";
}
消息推送,也可以在消息处理handleTextMessage中去做
@RequestMapping("/websocket/send")
@ResponseBody
public String send(HttpServletRequest request, ModelMap model) {
//String username = model.get
try {
System.out.println("session===" + request.getSession().getAttribute("WEBSOCKET_USERNAME"));
infoHandler().sendMessageToUser("zhangsan", new TextMessage("你好,测试!!!!"));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}