普通servlet方式和spring方式实现websocket
- 普通servlet,依赖如下
-
<dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--jsp --> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency>
-
服务器端创建:
@ServerEndpoint("/chat")
public class EchoEndpoint {
private static int onlineCount = 0;
private static CopyOnWriteArraySet<EchoEndpoint> webSocketSet = new CopyOnWriteArraySet<EchoEndpoint>();
private Session session;
synchronized void addOnlineCount(){
onlineCount++;
}
int getOnlineCount(){
return onlineCount;
}
synchronized void subOnlineCount(){
onlineCount--;
}
@OnOpen
public void onOpen(Session session){
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在线数加1
System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
}
@OnClose
public void onClose(){
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来自客户端的消息:" + message);
//群发消息
for(EchoEndpoint item: webSocketSet){
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
@OnError
public void onError(Session session, Throwable error){
System.out.println("发生错误");
error.printStackTrace();
}
public void sendMessage(String message) throws IOException{
this.session.getBasicRemote().sendText(message);
}
}
注意注解也是不能少的。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML>
<html>
<head>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<base href="<%=basePath%>">
<title>My WebSocket</title>
</head>
<body>
Welcome<br/>
<input id="text" type="text" />
<button id="login" >登录</button>
<button id="send" onclick="send()">发送</button>
<button id="close" onclick="closeWebSocket()">关闭</button>
<div id="message">
</div>
</body>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window){
$("#login").click(function(){
websocket = new WebSocket("ws://localhost:80/chat");
//连接发生错误的回调方法
websocket.onerror = function(){
setMessageInnerHTML("error");
};
//连接成功建立的回调方法
websocket.onopen = function(event){
setMessageInnerHTML("open");
$("#login").hide(); //隐藏登录按钮
};
//接收到消息的回调方法
websocket.onmessage = function(){
setMessageInnerHTML(event.data);
};
//连接关闭的回调方法
websocket.onclose = function(){
setMessageInnerHTML("close");
$("#login").show(); //显示登录按钮
$("#send").hide(); //显示登录按钮
$("#close").hide(); //显示登录按钮
};
});
}
else{
alert('Not support websocket');
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function(){
websocket.close();
};
//将消息显示在网页上
function setMessageInnerHTML(innerHTML){
document.getElementById('message').innerHTML += innerHTML + '<br/>';
}
//关闭连接
function closeWebSocket(){
websocket.close();
}
//发送消息
function send(){
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</html>
页面如上。不需要配置web.xml也没有其他配置,启动服务器就可以了。
2.springWebsocket
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp -->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.websocket/javax.websocket-api -->
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
配置文件:
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="Springsocket"></context:component-scan>
<context:annotation-config />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
写一个类集成此类,方法名字写的很形象:
public class WebSocketHandler extends TextWebSocketHandler {
//用于保存连接的用户
private List<WebSocketSession>list =new ArrayList<WebSocketSession>();
@Override //连接创建完成的意思吗
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("一位客户连接上来");
list.add(session);
}
@Override //处理text消息
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("收到消息:"+message);
for (WebSocketSession webSocketSession : list) {
webSocketSession.sendMessage(message);
}
}
@Override //发生错误的意思吗
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
list.remove(session);
System.out.println("出错");
exception.printStackTrace();
}
@Override //连接关闭
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
list.remove(session);
System.out.println("连接关闭");
}
}
写一个配置类,将上面的handler类注册进去,注意注解:
@Configuration
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
String url ="/socket";
registry.addHandler(webSocketHandler(),url);
}
@Bean
public TextWebSocketHandler webSocketHandler(){
return new WebSocketHandler();
}
}
index.jsp上面修改这个地址:
启动服务器即可。
其他,websocket连接还可以添加拦截器,方法是:
写一个类实现此接口:
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
@Override //之前
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
return false;
}
@Override //之后
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
}
在上面配置handler时顺便配置拦截器即可:
@Configuration
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
String url ="/socket";
registry.addHandler(webSocketHandler(),url).addInterceptors(handshakeInterceptor());
}
@Bean
public TextWebSocketHandler webSocketHandler(){
return new WebSocketHandler();
}
@Bean
public HandshakeInterceptor handshakeInterceptor(){
return new WebSocketHandshakeInterceptor();
}
}