标签:
<properties> <spring.version>4.0.0.RELEASE</spring.version> </properties> <dependencies> <!--spring MVC--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- jstl --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--spring测试框架--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <!--spring数据库操作库--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> <scope>test</scope> </dependency> <!--spring websocket库--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.version}</version> </dependency> <!--jackson用于json操作--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.2</version> </dependency> <!--使用阿里的连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.4</version> </dependency> <!--mysql connector--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.29</version> </dependency> </dependencies>
Spring的配置我就不一一贴出来了,可以去github看,地址我会贴在下面。
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer{ @Override public void registerStompEndpoints(StompEndpointRegistry registry) { //添加这个Endpoint,这样在网页中就可以通过websocket连接上服务了 registry.addEndpoint("/coordination").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry config) { System.out.println("服务器启动成功"); //这里设置的simple broker是指可以订阅的地址,也就是服务器可以发送的地址 /** * userChat 用于用户聊天 */ config.enableSimpleBroker("/userChat"); config.setApplicationDestinationPrefixes("/app"); } @Override public void configureClientInboundChannel(ChannelRegistration channelRegistration) { } @Override public void configureClientOutboundChannel(ChannelRegistration channelRegistration) { } }
可以看到,在类中必须实现这四个方法。暂且只需要用到前两个,所以我来介绍一下,前两个方法中代码的意义。
registry.addEndpoint("/coordination").withSockJS();
我们加了一个叫coordination的连接点,在网页上我们就可以通过这个链接来和服务 器的WebSocket连接了。但是后面还有一句withSockJs,这是什么呢?SockJs是一个WebSocket的通信js库,Spring对 这个js库进行了后台的自动支持,也就是说,我们如果使用SockJs,那么我们就不需要对后台进行更多的配置,只需要加上这一句就可以了。
config.enableSimpleBroker("/userChat"); config.setApplicationDestinationPrefixes("/app");
首先,定义了一个连接点叫userChat,从名字可以看的出,最后我会做一个聊天的例子。然后,设置了一个应用程序访问地址的前缀,目的估计是为了和其他的普通请求区分开吧。也就是说,网页上要发送消息到服务器上的地址是/app/userChat。
var socket = new SockJS(‘/coordination‘); var stompClient = Stomp.over(socket); stompClient.connect(‘‘, ‘‘, function (frame) {});
但是连接上了服务器,却没有进行任何的操作,所以下一步,我们要在服务器端撰写响应和数据处理代码
public class UserChatCommand { private String name; private String chatContent; private String coordinationId; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getChatContent() { return chatContent; } public void setChatContent(String chatContent) { this.chatContent = chatContent; } public String getCoordinationId() { return coordinationId; } public void setCoordinationId(String coordinationId) { this.coordinationId = coordinationId; } @Override public String toString() { return "UserChatCommand{" + "name=‘" + name + ‘\‘‘ + ", chatContent=‘" + chatContent + ‘\‘‘ + ", coordinationId=‘" + coordinationId + ‘\‘‘ + ‘}‘; } }
通过这个bean来接收到web端发送的消息,然后在服务端转发,接下来就是转发的逻辑了,不过首先需要介绍一下Spring WebSocket的一个annotation。
/** * WebSocket聊天的相应接收方法和转发方法 * * @param userChat 关于用户聊天的各个信息 */ @MessageMapping("/userChat") public void userChat(UserChatCommand userChat) { //找到需要发送的地址 String dest = "/userChat/chat" + userChat.getCoordinationId(); //发送用户的聊天记录 this.template.convertAndSend(dest, userChat); }
怎么这么简单?呵呵,能够这么简单的实现后台代码,全是Spring的功劳。首先,我们约定好发送地址的规则,就是chat后面跟上之前发送过来的id, 然后通过这个“template”来进行转发,这个“template”是Spring实现的一个发送模板 类:SimpMessagingTemplate,在我们定义controller的时候,可以在构造方法中进行注入:
@Controller public class CoordinationController { ...... //用于转发数据(sendTo) private SimpMessagingTemplate template; <pre name="code" class="java"> @Autowired public CoordinationController(SimpMessagingTemplate t) { template = t; } ..... }
现在就已经将用户发送过来的聊天信息转发到了一个约定的空间内,只要web端的用户订阅的是这个空间的地址,那么就会收到转发过来的json。现在来看看web端需要做什么吧。
//发送聊天信息 function sendName() { var input = $(‘#chat_input‘); var inputValue = input.val(); input.val(""); stompClient.send("/app/userChat", {}, JSON.stringify({ ‘name‘: encodeURIComponent(name), ‘chatContent‘: encodeURIComponent(inputValue), ‘coordinationId‘: coordinationId })); }
其中,name和coordinationId是相应的用户信息,可以通过ajax或者jsp获取,这里就不多说了。
根据之前的约定,可以得到订阅的地址是‘/coordination /coordination‘ + coordinationId,所以我们订阅这个地址就可以了,当订阅成功后,只要后台有转发消息,就会调用第二个方法,并且,将后台传过来的消息体作为 参数。所以订阅的方法如下
//用户聊天订阅 stompClient.subscribe(‘/userChat/chat‘ + coordinationId, function (chat) { showChat(JSON.parse(chat.body)); });
将消息体转为json,再写一个显示聊天信息的方法就可以了,显示聊天信息的方法不再解释,如下:
//显示聊天信息 function showChat(message) { var response = document.getElementById(‘chat_content‘); response.value += decodeURIComponent(message.name) + ‘:‘ + decodeURIComponent(message.chatContent) + ‘\n‘; }
因为之前处理中文问题,所以发到后台的数据是转码了的,从后台发回来之后,也需要将编码转回来。
标签:
原文地址:http://www.cnblogs.com/liangjiahao/p/4303281.html