增加 spring websocket 用例

This commit is contained in:
luoxiang 2018-12-27 21:33:02 +08:00
parent 71daa7857e
commit a80afab862
29 changed files with 655 additions and 51 deletions

1
.gitignore vendored
View File

@ -33,6 +33,7 @@ manifest.yml
overridedb.*
settings.xml
target
classes
out
transaction-logs
.flattened-pom.xml

View File

@ -31,15 +31,15 @@ spring-cloudFinchley.SR2
| [spring-jdbc](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-jdbc)<br/>[spring-jdbc-annotation](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-jdbc-annotation) | spring jdbc-template 的使用 | [Using JdbcTemplat](https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/data-access.html#jdbc-JdbcTemplate) |
| [spring-mybatis](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-mybatis)<br/>[spring-mybatis-annotation](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-mybatis-annotation) | spring 整合 mybatis | [mybatis-spring中文文档](http://www.mybatis.org/spring/zh/index.html) |
| [spring-druid-mybatis](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-druid-mybatis)<br/>[spring-druid-mybatis-annotation](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring/spring-druid-mybatis-annotation) | spring 整合druid、mybatis | [alibaba druid](https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) |
| spring-redis<br/>spring-redis-annotation | spring 整合 redis 单机、集群jedis客户端<br/>spring 整合 redis 单机、集群redisson客户端 | [redisson中文文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) |
| spring-redis<br/>spring-redis-annotation | spring 整合 redis 单机、集群jedis客户端<br/>spring 整合 redis 单机、集群redisson客户端 | [redisson官方中文文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) |
| spring-mongodb<br/>spring-mongodb-annotation | spring 整合 mongodb | [Spring Data MongoDB](https://docs.spring.io/spring-data/mongodb/docs/2.1.3.RELEASE/reference/html/#mongo.mongo-db-factory-java) |
| spring-memcached<br/>spring-memcached-annotation | spring 整合 memcached(单机、集群) | [Xmemcached中文文档](https://github.com/killme2008/xmemcached/wiki/Xmemcached%20%E4%B8%AD%E6%96%87%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97) |
| spring-rabbitmq<br/>spring-rabbitmq-annotation | spring 整合 rabbitmq | |
| spring-memcached<br/>spring-memcached-annotation | spring 整合 memcached(单机、集群) | [Xmemcached官方中文文档](https://github.com/killme2008/xmemcached/wiki/Xmemcached%20%E4%B8%AD%E6%96%87%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97) |
| spring-rabbitmq<br/>spring-rabbitmq-annotation | spring 整合 rabbitmq、消息序列化与反序列化 | [rabbitmq 官方文档](http://www.rabbitmq.com/getstarted.html)<br>[spring amqp](https://docs.spring.io/spring-amqp/docs/2.1.3.BUILD-SNAPSHOT/reference/html/) |
| spring-kafka<br/>spring-kafka-annotation | spring 整合 kafka | |
| spring-dubbo<br/>spring-dubbo-annotation | spring 整合 dubbo | |
| spring-websocket<br/>spring-websocket-annotation | spring 整合 websocket | |
| spring-netty<br/>spring-netty-annotation | spring 整合 netty | |
| spring-scheduled<br/>spring-scheduled-annotation | spring 定时任务 | |
| spring-dubbo<br/>spring-dubbo-annotation | spring 整合 dubbo | [duboo 官方中文文档](http://dubbo.apache.org/zh-cn/docs/user/quick-start.html) |
| spring-websocket<br/>spring-websocket-annotation | spring 整合 websocket | [spring websocket](https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/web.html#websocket) |
| spring-mail<br/>spring-mail-annotation | spring 普通文本邮件、附件邮件、模板邮件 | [spring email](https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/integration.html#mail) |
| spring-scheduled<br/>spring-scheduled-annotation | spring 定时任务 | [Task Execution and Scheduling](https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/integration.html#scheduling) |
<br/>
@ -83,8 +83,6 @@ spring-cloudFinchley.SR2
| spring-cloud-zuul | spring cloud 网关限流、权限验证 | |
| spring-cloud-sleuth-Zipkin | spring cloud 服务追踪 | |
推荐课程:[Spring Cloud微服务实战](https://coding.imooc.com/class/187.html) 廖大神结合实战很详细的介绍spring cloud各个组件的使用。
<br/>
## 4.参考资料

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.heibaiying</groupId>
<artifactId>spring-websocket</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<spring-base-version>5.1.3.RELEASE</spring-base-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-base-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring-base-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-base-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-base-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-base-version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<!--spring webSocket 的依赖包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,11 @@
package com.heibaiying.constant;
/**
* @author : 罗祥
* @description :
* @date :create in 2018/12/27
*/
public interface Constant {
String USER_NAME="username";
}

View File

@ -0,0 +1,23 @@
package com.heibaiying.controller;
import com.heibaiying.constant.Constant;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
/**
* @author : 罗祥
* @description : 简单登录
* @date :create in 2018/12/27
*/
@Controller
public class LoginController {
@PostMapping("login")
public String login(String username, HttpSession session){
session.setAttribute(Constant.USER_NAME,username);
return "chat";
}
}

View File

@ -0,0 +1,23 @@
package com.heibaiying.webconfig;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
* @author : 罗祥
* @description : 等价于 web.xml 中配置前端控制器
* @date :create in 2018/12/27
*/
public class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
protected Class<?>[] getServletConfigClasses() {
return new Class[]{ServletConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
}

View File

@ -0,0 +1,42 @@
package com.heibaiying.webconfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
/**
* @author : 罗祥
* @description : 主配置类
* @date :create in 2018/12/27
*/
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.heibaiying.*"})
public class ServletConfig implements WebMvcConfigurer {
/**
* 配置视图解析器
*/
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
internalResourceViewResolver.setSuffix(".jsp");
internalResourceViewResolver.setExposeContextBeansAsAttributes(true);
return internalResourceViewResolver;
}
/**
* 配置静态资源处理器
*/
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}

View File

@ -0,0 +1,21 @@
package com.heibaiying.webconfig;
import org.springframework.web.filter.CharacterEncodingFilter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
/**
* @author : 罗祥
* @description : 编码过滤器 防止乱码
* @date :create in 2018/12/27
*/
@WebFilter(filterName = "characterEncodingFilter", urlPatterns = "/*",
initParams = {
@WebInitParam(name = "encoding", value = "UTF-8"),
@WebInitParam(name = "forceEncoding", value = "true")
}
)
public class characterEncodingFilter extends CharacterEncodingFilter {
}

View File

@ -0,0 +1,32 @@
package com.heibaiying.websocket;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Map;
/**
* @author : heibaiying
* @description : 可以按照需求实现权限拦截等功能
*/
public class CustomHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> 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);
}
}

View File

@ -0,0 +1,60 @@
package com.heibaiying.websocket;
import com.heibaiying.constant.Constant;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author : heibaiying
* @description : 自定义消息处理类
*/
public class CustomerHandler extends TextWebSocketHandler {
private Map<String, WebSocketSession> 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<String, Object> attributes = session.getAttributes();
return (String) attributes.get(Constant.USER_NAME);
}
}

View File

@ -0,0 +1,21 @@
package com.heibaiying.websocket;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
/**
* @author : 罗祥
* @description :websocket 配置
* @date :create in 2018/12/27
*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new CustomerHandler(), "/socket").addInterceptors(new CustomHandshakeInterceptor());
}
}

View File

@ -0,0 +1,38 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>${sessionScope.get("username")}您好!欢迎进入群聊大厅!</title>
</head>
<body>
<input id="message" type="text">
<button id="btn">发送消息</button>
<div id="show">
</div>
<script>
let btn = document.getElementById("btn");
let message = document.getElementById("message");
let show = document.getElementById("show");
let ws = new WebSocket("ws://localhost:8080/socket");
ws.onmessage = function (evt) {
let node = document.createElement("div");
node.innerHTML = "<h5>" + evt.data + "</h5>";
show.appendChild(node);
};
btn.addEventListener("click", function () {
let data = message.value;
console.log(data);
if (data) {
ws.send(encodeURI(data));
} else {
alert("请输入消息后发送");
}
message.value = "";
});
// 关闭页面时候关闭ws
window.addEventListener("beforeunload", function(event) {
ws.close();
});
</script>
</body>
</html>

View File

@ -0,0 +1,12 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login" method="post">
<input name="username" type="text">
<button id="btn">输入临时用户名后登录!</button>
</form>
</body>
</html>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<!-- 开启注解包扫描-->
<context:component-scan base-package="com.heibaiying.*"/>
<!--使用默认的Servlet来响应静态文件 -->
<mvc:default-servlet-handler/>
<!-- 开启注解驱动 -->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
<!--配置webSocket-->
<bean id="customerHandler" class="com.heibaiying.websocket.CustomerHandler"/>
<websocket:handlers>
<!--指定webSocket 地址-->
<websocket:mapping path="/socket" handler="customerHandler"/>
<!--webSocket握手-->
<websocket:handshake-interceptors>
<bean class="com.heibaiying.websocket.CustomHandshakeInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
</beans>

View File

@ -0,0 +1,38 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>${sessionScope.get("username")}您好!欢迎进入群聊大厅!</title>
</head>
<body>
<input id="message" type="text">
<button id="btn">发送消息</button>
<div id="show">
</div>
<script>
let btn = document.getElementById("btn");
let message = document.getElementById("message");
let show = document.getElementById("show");
let ws = new WebSocket("ws://localhost:8080/socket");
ws.onmessage = function (evt) {
let node = document.createElement("div");
node.innerHTML = "<h5>" + evt.data + "</h5>";
show.appendChild(node);
};
btn.addEventListener("click", function () {
let data = message.value;
console.log(data);
if (data) {
ws.send(encodeURI(data));
} else {
alert("请输入消息后发送");
}
message.value = "";
});
// 关闭页面时候关闭ws
window.addEventListener("beforeunload", function(event) {
ws.close();
});
</script>
</body>
</html>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--配置spring前端控制器-->
<servlet>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springApplication.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

View File

@ -0,0 +1,12 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login" method="post">
<input name="username" type="text">
<button id="btn">输入临时用户名后登录!</button>
</form>
</body>
</html>

View File

@ -57,6 +57,11 @@
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<!--spring webSocket 的依赖包 -->
<dependency>
<groupId>org.springframework</groupId>

View File

@ -0,0 +1,11 @@
package com.heibaiying.constant;
/**
* @author : 罗祥
* @description :
* @date :create in 2018/12/27
*/
public interface Constant {
String USER_NAME="username";
}

View File

@ -0,0 +1,23 @@
package com.heibaiying.controller;
import com.heibaiying.constant.Constant;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
/**
* @author : 罗祥
* @description : 简单登录
* @date :create in 2018/12/27
*/
@Controller
public class LoginController {
@PostMapping("login")
public String login(String username, HttpSession session){
session.setAttribute(Constant.USER_NAME,username);
return "chat";
}
}

View File

@ -5,24 +5,27 @@ import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Map;
/**
* @author : heibaiying
* @description : 握手拦截器
* @description : 可以按照需求实现权限拦截等功能
*/
public class CustomHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
/*@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
InetSocketAddress remoteAddress = request.getRemoteAddress();
System.out.println(remoteAddress);
return true;
}*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> 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);
}
}

View File

@ -1,21 +1,61 @@
package com.heibaiying.websocket;
import com.heibaiying.constant.Constant;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.time.LocalDateTime;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author : heibaiying
* @description : 自定义消息处理
* @description : 自定义消息处理
*/
public class CustomerHandler extends TextWebSocketHandler {
private Map<String, WebSocketSession> 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 stringMessage = new String(message.asBytes());
System.out.println("服务端收到消息:" + stringMessage);
session.sendMessage(new TextMessage(stringMessage+LocalDateTime.now()));
// 防止中文乱码
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<String, Object> attributes = session.getAttributes();
return (String) attributes.get(Constant.USER_NAME);
}
}

View File

@ -0,0 +1,38 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>${sessionScope.get("username")}您好!欢迎进入群聊大厅!</title>
</head>
<body>
<input id="message" type="text">
<button id="btn">发送消息</button>
<div id="show">
</div>
<script>
let btn = document.getElementById("btn");
let message = document.getElementById("message");
let show = document.getElementById("show");
let ws = new WebSocket("ws://localhost:8080/socket");
ws.onmessage = function (evt) {
let node = document.createElement("div");
node.innerHTML = "<h5>" + evt.data + "</h5>";
show.appendChild(node);
};
btn.addEventListener("click", function () {
let data = message.value;
console.log(data);
if (data) {
ws.send(encodeURI(data));
} else {
alert("请输入消息后发送");
}
message.value = "";
});
// 关闭页面时候关闭ws
window.addEventListener("beforeunload", function(event) {
ws.close();
});
</script>
</body>
</html>

View File

@ -21,4 +21,22 @@
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--处理乱码-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

View File

@ -4,34 +4,9 @@
<title>Title</title>
</head>
<body>
<input id="message" type="text">
<button id="btn">发送消息</button>
<div id="show">
</div>
<script>
let btn = document.getElementById("btn");
let message = document.getElementById("message");
let show = document.getElementById("show");
let ws = new WebSocket("ws://localhost:8080/socket");
ws.onopen = function () {
alert("websocket已经连接");
};
ws.onmessage = function (evt) {
let node = document.createElement("div");
node.innerHTML = "<h5>" + evt.data + "</h5>";
show.appendChild(node);
};
btn.addEventListener("click", function () {
let data = message.value;
if (data) {
ws.send(data);
} else {
alert("请输入消息后发送");
}
message.value = "";
});
</script>
<form action="${pageContext.request.contextPath}/login" method="post">
<input name="username" type="text">
<button id="btn">输入临时用户名后登录!</button>
</form>
</body>
</html>