# spring websocket(xml配置方式)
## 一、说明
### 1.1 项目结构说明
1. 项目模拟一个简单的群聊功能,为区分不同的聊天客户端,登录时候用临时用户名作为session的id;
2. CustomHander为消息的自定义处理器;
3. CustomHandershakerInterceptor为自定义的 websocket 的握手拦截器;
4. 项目以web的方式构建。

### 1.2 依赖说明
除了基本的spring 依赖外,还需要导入webSocket的依赖包
```xml
org.springframework
spring-websocket
5.1.3.RELEASE
```
## 二、spring websocket
#### 2.1 创建消息处理类,继承自TextWebSocketHandler
```java
/**
* @author : heibaiying
* @description : 自定义消息处理类
*/
public class CustomHandler extends TextWebSocketHandler {
private Map nameAndSession = new ConcurrentHashMap<>();
// 建立连接时候触发
@Override
public void afterConnectionEstablished(WebSocketSession session) {
String username = getNameFromSession(session);
nameAndSession.putIfAbsent(username, session);
}
// 关闭连接时候触发
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
String username = getNameFromSession(session);
nameAndSession.remove(username);
}
// 处理消息
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// 防止中文乱码
String msg = URLDecoder.decode(message.getPayload(), "utf-8");
String username = getNameFromSession(session);
// 简单模拟群发消息
TextMessage reply = new TextMessage(username + " : " + msg);
nameAndSession.forEach((s, webSocketSession)
-> {
try {
webSocketSession.sendMessage(reply);
} catch (IOException e) {
e.printStackTrace();
}
});
}
private String getNameFromSession(WebSocketSession session) {
Map attributes = session.getAttributes();
return (String) attributes.get(Constant.USER_NAME);
}
}
```
#### 2.2 创建websocket 握手拦截器(如果没有权限拦截等需求,这一步不是必须的)
```java
/**
* @author : heibaiying
* @description : 可以按照需求实现权限拦截等功能
*/
public class CustomHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception {
InetSocketAddress remoteAddress = request.getRemoteAddress();
InetAddress address = remoteAddress.getAddress();
System.out.println(address);
/*
* 最后需要要显示调用父类方法,父类的beforeHandshake方法
* 把ServerHttpRequest 中session中对应的值拷贝到WebSocketSession中。
* 如果我们没有实现这个方法,我们在最后的handler处理中 是拿不到 session中的值
* 作为测试 可以注释掉下面这一行 可以发现自定义处理器中session的username总是为空
*/
return super.beforeHandshake(request, response, wsHandler, attributes);
}
}
```
#### 2.3 配置websocket
```xml
```
#### 2.4 前端 websocket 的实现
```jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
${sessionScope.get("username")}您好!欢迎进入群聊大厅!
```
#### 2.5 简单登录的实现
```java
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
```
```java
@Controller
public class LoginController {
@PostMapping("login")
public String login(String username, HttpSession session){
session.setAttribute(Constant.USER_NAME,username);
return "chat";
}
}
```