maven构建spring4 WebSocket应用, 不使用Spring MVC

本文介绍了如何在不使用Spring MVC的情况下,利用Spring4构建WebSocket应用程序。虽然Spring WebSocket参考指南通常建立在Spring MVC之上,但实际可以独立实现。不过,这种做法存在一些不便,如需要手动管理客户端连接、广播消息以及创建WebSocket处理和拦截器对象。最后,建议使用SpringMVC结合WebSocket以简化开发流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring4 reference中websocket的使用是建立在Spring MVC之上的,其实spring websocket并不依赖于Spring MVC。

The above is for use in Spring MVC applications and should be included 
in the configuration of a DispatcherServlet. 
However, Spring’s WebSocket support does not depend on Spring MVC. 
It is relatively simple to integrate a WebSocketHandler into other HTTP serving environments 
with the help of WebSocketHttpRequestHandler.


这篇文章我们就看下,如何在不引入Spring MVC的情况下,使用Spring Websocket。整个项目的目录结构如下:



pom.xml配置如下:

<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/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>net.aty.websocket</groupId>
	<artifactId>SpringWebsocketDemo</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>SpringWebsocketDemo Maven Webapp</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>4.2.4.RELEASE</spring.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-websocket</artifactId>
			<version>${spring.version}</version>
		</dependency>
		
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<finalName>SpringWebsocketDemo</finalName>
	</build>
</project>


web.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<servlet>
		<servlet-name>websocket</servlet-name>
		<servlet-class>net.aty.websocket.MyServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>websocket</servlet-name>
		<url-pattern>/websocket.connection</url-pattern>
	</servlet-mapping>

</web-app>


root-context.xml配置如下:

<?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"
	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.xsd">

	<bean id="myHandler" class="net.aty.websocket.MyHandler" />
	
	<bean id="myInterceptor" class="net.aty.websocket.MyWebSocketHandshakeInterceptor" />

</beans>



MyHandler.java代码如下:
package net.aty.websocket;

import java.util.Map;

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;

public class MyHandler extends TextWebSocketHandler {

	@Override
	public void afterConnectionEstablished(WebSocketSession session)
			throws Exception {
		System.out.println("connection established");
		WebSocketSessionUtil.add(getUserNameFromSession(session), session);
	}

	@Override
	public void handleTextMessage(WebSocketSession session, TextMessage message)
			throws Exception {
		System.out.println("receive a message." + message);

		WebSocketSessionUtil.broadcast(message);
	}

	@Override
	public void handleTransportError(WebSocketSession session,
			Throwable exception) throws Exception {
		WebSocketSessionUtil.remove(getUserNameFromSession(session));
	}

	@Override
	public void afterConnectionClosed(WebSocketSession session,
			CloseStatus closeStatus) throws Exception {
		System.out.println("conection closed." + closeStatus);

		WebSocketSessionUtil.add(getUserNameFromSession(session), session);
	}

	@Override
	public boolean supportsPartialMessages() {
		return false;
	}

	private String getUserNameFromSession(WebSocketSession session) {
		Map<String, Object> params = session.getAttributes();

		return params.get("userName").toString();
	}

}


MyWebSocketHandshakeInterceptor.java代码如下:
package net.aty.websocket;

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 MyWebSocketHandshakeInterceptor extends
		HttpSessionHandshakeInterceptor {

	@Override
	public boolean beforeHandshake(ServerHttpRequest serverHttpRequest,
			ServerHttpResponse serverHttpResponse, WebSocketHandler wsHandler,
			Map<String, Object> attributes) throws Exception {

		System.out.println("hi get request.");

		ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) serverHttpRequest;
		HttpServletRequest request = servletRequest.getServletRequest();

		String userName = request.getParameter("userName");
		attributes.put("userName", userName);

		System.out.println("a client userName=" + userName);

		super.beforeHandshake(serverHttpRequest, serverHttpResponse, wsHandler,
				attributes);

		return true;
	}

	@Override
	public void afterHandshake(ServerHttpRequest request,
			ServerHttpResponse response, WebSocketHandler wsHandler,
			Exception ex) {
		super.afterHandshake(request, response, wsHandler, ex);
	}

}


WebSocketSessionUtil.java代码如下:
package net.aty.websocket;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

public class WebSocketSessionUtil {

	private static Map<String, WebSocketSession> clients = new ConcurrentHashMap<>();

	public static void add(String userName, WebSocketSession session) {
		clients.put(userName, session);
	}

	public static WebSocketSession get(String userName) {
		return clients.get(userName);
	}

	public static void remove(String userName) {
		clients.remove(userName);
	}

	public static void broadcast(TextMessage message)
			throws Exception {

		Set<String> allUsers = clients.keySet();

		for (String name : allUsers) {
			WebSocketSession session = clients.get(name);
			session.sendMessage(message);
		}
	}
}


MyServlet.java代码如下:
package net.aty.websocket;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;

public class MyServlet extends HttpServlet {

	private static final long serialVersionUID = 1954401864181530442L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		ApplicationContext context = WebApplicationContextUtils
				.getWebApplicationContext(req.getServletContext());

		WebSocketHttpRequestHandler handler = new WebSocketHttpRequestHandler(
				context.getBean("myHandler", MyHandler.class));

		List<HandshakeInterceptor> interceptors = new ArrayList<HandshakeInterceptor>();
		interceptors.add(context.getBean("myInterceptor",
				MyWebSocketHandshakeInterceptor.class));

		handler.setHandshakeInterceptors(interceptors);

		handler.handleRequest(req, resp);
	}
}


这个Servlet使用了Spring中的WebSocketHttpRequestHandler,和客户端建立websocket连接。


websocket.html代码如下:

<head>
<script src="js/jquery-1.11.1.js"></script>
<script>
	$(function() {

		// 浏览器上的websocket对象,用来和服务端通信.
		var socket = null;

		$("#login").click(
				function() {
					var userName = $("#userName").val();
					if ($.trim(userName) == "") {
						return;
					}

					// 创建websocket对象
					socket = new WebSocket(
							'ws://localhost:8080/SpringWebsocketDemo/websocket.connection?userName='
									+ userName);
					registerEvent();
				});

		$("#logout").click(function() {
			socket.close();
		});

		$("#send").click(function() {
			socket.send($("#message").val());
		});

		function registerEvent() {
			socket.onopen = function(event) {
				$("#messagePanel").append(
						"<div>websocket open successfully.</div>");
			}

			socket.onmessage = function(event) {
				$("#messagePanel").append("<div>msg=" + event.data + "</div>");
			};

			socket.onclose = function(event) {
				$("#messagePanel").append(
						"<div>websocket close successfully.</div>");
			};
		}

	});
</script>
<style>
.card {
	margin: 20px;
}
</style>
</head>
<body>
	<div class="card">
		userName:<input id="userName" value="" placeholder="input your name" />
		<button id="login">login</button>
		<button id="logout">logout</button>
	</div>
	<div class="card">
		message:<input id="message" value="" placeholder="input your message" />
		<button id="send">send</button>
	</div>

	<div class="card" id="messagePanel"></div>
</body>



war包部署到Tomcat7.0.62下,可以看到2个chrome客户端能够收到彼此的信息。





后台的Tomcat也打印出了相应的日志:




我们在没有引入Spring MVC的情况下,实现了Spring WebSocket编程,但是却比较麻烦体现在2个方面:

1.我们必须记录所有的websocket客户端,然后将消息广播给所有客户端。

2.必须手动创建WebSocketHandler和HandshakeInterceptor等对象,无法在spring.xml中配置。


所以我们还是使用SpringMVC+Websocket吧,会给编程带来很大的便利。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值