Spring WebSocket教程(一)

admin 发表于 2017-4-4 21:53:25 | 栏目:站长教程 |分类:[其他教程]
学习背景
5 C9 B5 V  {9 U) l- p/ }+ W很久以前就知道WebSocket,但那时不论是浏览器还是开发技术对它的支持都还很少。但是,Spring4突然发布,让我眼前一亮,Spring4直接支持WebSocket。5 I1 \+ K8 h( q
对于Spring我还是很喜欢的,它让Java Web开发相当的有艺术感,这次支持的WebSocket又特别的和我的胃口,所以马上就去学习了。5 j: F3 Y6 Z* p# D2 C. {. N
前提
% Q  N) v% X+ l+ C- B本文的内容,是建立在懂J2EE编程,使用过Spring,听说过WebSocket上的,如果前面的3点大家不太明白,可以先去补补知识。
; ?3 H  R7 |. X1 |WebSocket还不是很普遍,对服务器和浏览器都有要求,不过使用了下面的一些技术,可以将浏览器的要求降低,但是服务器容器的要求还是比较高的,具体哪些服务器容易支持了WebSocket可以百度一下。# n9 v4 j% t$ J4 D
第一步:配置Spring
, H" _  e$ |- H; x: w3 `如果你跟我一样采用的Maven,那么只需要将下面的几个依赖,加入到pom.xml文件就可以了:% _8 A9 x7 |% g% c+ Y, \- h- n
  1. <font size="4"><properties>  
    % g. H" C4 z( p' B' I, j! t' @
  2.     <spring.version>4.0.0.RELEASE</spring.version>  & }" a  s) @& i. c) T9 i
  3. </properties>  
    * u1 @! L. q! b# {9 e
  4.   / m  [' C+ w9 ?7 H; a) E5 F1 }
  5. <dependencies>  
    ( E: |8 d, Y# S4 ?& ?
  6.     <!--spring MVC-->  
    6 E& I) |+ `; f4 P4 n) {
  7.     <dependency>  
    & G: H- @1 M6 X9 d- z$ D% K7 a
  8.         <groupId>org.springframework</groupId>  : l, j4 r3 q' f9 L) D9 A
  9.         <artifactId>spring-core</artifactId>  
    . F, a$ K4 T6 }& n9 B& L
  10.         <version>${spring.version}</version>  9 t: ]  y! ~% m
  11.     </dependency>  
    2 X. u6 X1 y5 }0 c; l
  12.   
    # G% P  S2 s& B' f+ j
  13.     <dependency>  
    # P! y3 R/ X; s& i% _2 ]) ~
  14.         <groupId>org.springframework</groupId>  
    * f6 Q! n. {; ~3 S* K0 R
  15.         <artifactId>spring-web</artifactId>  4 L- b3 J: B- x. d
  16.         <version>${spring.version}</version>  * O. T/ S' x9 {$ \. \6 z4 C
  17.     </dependency>  
    0 o; k. t% |4 j! A
  18.   " Y$ U# G0 E* \+ K9 N1 ]
  19.     <dependency>  
    9 G8 U2 D% e3 H& u! T- @8 A
  20.         <groupId>org.springframework</groupId>  
    8 G9 s6 W4 N6 P- E( Q
  21.         <artifactId>spring-webmvc</artifactId>  
    ! b3 d8 B2 p$ \8 ^2 n5 b% N  J1 g) u
  22.         <version>${spring.version}</version>  
    & Z: L& f2 @- z7 H
  23.     </dependency>  + p5 f( b& D! _& O$ t5 V4 B6 n  l$ H1 M
  24.   
    - l# k, M9 g1 `; J+ Q( `" k
  25.     <!-- jstl -->  
    3 O  l# _5 o  o" M2 l
  26.     <dependency>  
      @1 \! X6 A# v2 d0 o& E
  27.         <groupId>jstl</groupId>  
    , X5 o" O: `" b3 Y
  28.         <artifactId>jstl</artifactId>  
    0 v+ Z' G9 L- A9 t) U. h# W( v
  29.         <version>1.2</version>  
    / M. |! A) g) |) g/ X
  30.     </dependency>  
    & U5 i! ]  G; f2 E
  31.   
    1 ]- z/ E* f; H# m: B: \
  32.     <!--spring测试框架-->  7 ^' }! k  S6 [0 r" C7 H
  33.     <dependency>  3 I" s& P- f& F" W' }7 S0 j  i
  34.         <groupId>org.springframework</groupId>  ) b" I1 b4 u6 \* i/ X
  35.         <artifactId>spring-test</artifactId>  
    + X' J# P0 [) i
  36.         <version>${spring.version}</version>  
    9 l" I" X4 Q/ D$ }8 E
  37.         <scope>test</scope>  
    7 }0 Z1 f" z7 I1 c  s4 ^5 _
  38.     </dependency>  : S9 L8 d9 J: L- Z3 @; S
  39.   
    " T9 s$ S. ]' j% [8 t! {" q
  40.     <!--spring数据库操作库-->  
    # |8 R6 y! Q1 y. ^# [: {$ ~
  41.     <dependency>  1 G9 l& ]% {( G) z
  42.         <groupId>org.springframework</groupId>  
    & E& u- R9 |$ I& ]6 z  q" [6 j
  43.         <artifactId>spring-jdbc</artifactId>    ^/ Y4 n  g% a- m: V
  44.         <version>${spring.version}</version>  
    % a8 A4 s8 A8 W! O" s
  45.     </dependency>  " z& Y/ W+ ^- d  x! H5 w. u
  46.   / E; w* L8 Q+ s6 \' G
  47.     <dependency>  # t' C- ~8 \* I- W9 k7 K
  48.         <groupId>junit</groupId>  
    , B- j3 L% n3 [5 B/ I* h1 D; k
  49.         <artifactId>junit</artifactId>  
    % G2 a+ }# S* w& Y8 b$ d9 M
  50.         <version>4.8.2</version>  
    . ^) ^6 k& |0 A9 g$ `% u
  51.         <scope>test</scope>  
    7 t) k  e7 ~! b+ t$ @9 U
  52.     </dependency>    ^7 ?$ N9 B9 m+ l
  53.   
    6 i  L8 z: c: h  k
  54.     <!--spring websocket库-->  ) d5 q' d% c# ~( C! X7 r* t
  55.     <dependency>  0 u$ m. o! }" U3 o2 o6 H
  56.         <groupId>org.springframework</groupId>  
    0 b1 m5 {/ F: |
  57.         <artifactId>spring-websocket</artifactId>  
    1 I  O4 q! }" z1 Q3 E, t; Y; G
  58.         <version>${spring.version}</version>  
    2 q3 [0 s* z2 p6 z3 P
  59.     </dependency>  2 I1 N9 V* ]( p4 r( {  ~! l) l
  60.     <dependency>  , `6 x* t  f1 c9 i& ]: q3 |
  61.         <groupId>org.springframework</groupId>  + r4 W) u8 x7 f4 X
  62.         <artifactId>spring-messaging</artifactId>  
    , t0 G8 l; [2 p7 E& c
  63.         <version>${spring.version}</version>  
    6 H6 J" j$ j# S- H1 Y6 \: c
  64.     </dependency>  5 t/ `' x7 M/ q4 b2 Y) I
  65.   
    0 q2 ?6 k& d" S6 U$ @/ w4 k
  66.     <!--jackson用于json操作-->  ; u7 i7 M4 J% e0 `3 L
  67.     <dependency>  
    ) Z- t& l( F) E) ^3 K& Y
  68.         <groupId>com.fasterxml.jackson.core</groupId>  
    5 N3 U& T. {! L; K- Z  G
  69.         <artifactId>jackson-databind</artifactId>  
    7 D/ e1 _/ n, Q2 m7 v1 V) v9 Q
  70.         <version>2.3.0</version>  
    : A2 M# {! k5 v1 E* q
  71.     </dependency>  
    1 {- l3 \# l( ?3 t3 S4 R4 z7 b
  72.   9 J! Q2 ]7 U8 E5 L# r, O
  73.     <dependency>  , D: s) I1 |, s
  74.         <groupId>commons-fileupload</groupId>  
    7 I; I' T0 A2 A
  75.         <artifactId>commons-fileupload</artifactId>  
    , D7 m* b  q5 C, ^
  76.         <version>1.2.2</version>  
    7 w/ T2 s) W" |% k
  77.     </dependency>  # w+ b; b. d4 d, V3 H/ r! B
  78.     <dependency>  
    1 D2 b2 k" }5 H
  79.         <groupId>commons-io</groupId>  * W0 H. t7 k; _' X' [0 Z
  80.         <artifactId>commons-io</artifactId>  
    " |# \5 B8 O' F& q0 T4 L- k% A5 E- W
  81.         <version>2.2</version>  ( s9 q% b0 n0 y7 U2 A$ |8 V, J$ t
  82.     </dependency>  
    - C9 a( h* x9 D* ?: f
  83.     <!--使用阿里的连接池-->  
    % [1 ^- v5 V5 a2 s& |
  84.     <dependency>  
      G. o& U' a$ T" U% l3 g
  85.         <groupId>com.alibaba</groupId>  
    5 F1 c  t% I0 `" x/ J
  86.         <artifactId>druid</artifactId>  
    # w$ E2 j' L( [- \" L
  87.         <version>1.0.4</version>  9 _8 f* V! F: C. w9 R$ Y7 ~
  88.     </dependency>  
    % o, L, _( R8 ]6 @. p% V$ F
  89.     <!--mysql connector-->  
    - Q3 X7 K- R/ o( s" j
  90.     <dependency>  7 B: i1 ~0 e6 T7 j6 x6 k4 m
  91.         <groupId>mysql</groupId>  8 v; E8 T" T5 V1 S2 N, o
  92.         <artifactId>mysql-connector-java</artifactId>  % v7 q7 G# J! E8 G
  93.         <version>5.1.29</version>  
    " m4 T  z$ ]6 |! j$ }
  94.     </dependency>  5 N: m; [; r8 ^3 U3 u# ]. \4 `
  95.   
    * R; g' ^; J7 V
  96. </dependencies>  </font>
复制代码
Spring的配置我就不一一贴出来了,可以去github看,地址我会贴在下面。+ ^( ^; k6 f' U: O/ C4 ?
第二步:配置WebSocket2 K; A. }$ _# D; m  L6 W4 b2 Y; n5 d& q
我采用的是使用Configurer类和 Annotation来进行WebSocket配置。
5 \$ m  D6 L  P0 d* \首先要创建一个类,继承WebSocketMessageBrokerConfigurer,并且在类上加上annotation:@Configuration和@EnableWebSocketMessageBroker。这样,Spring就会将这个类当做配置类,并且打开WebSocket。
  1. <font size="4">@Configuration
    ' ~  B8 G* G- Z. E
  2. @EnableWebSocketMessageBroker( y4 n1 F) l5 [
  3. public class WebSocketConfig implements WebSocketMessageBrokerConfigurer{
    $ U" U5 o! {4 p
  4.     @Override
    . M% d9 e# B& l: n) @: A
  5.     public void registerStompEndpoints(StompEndpointRegistry registry) {
    8 N, W( s( P- k: t( {$ @2 m9 \( X! j
  6.         //添加这个Endpoint,这样在网页中就可以通过websocket连接上服务了4 L. e7 w3 u9 \  \. N
  7.         registry.addEndpoint("/coordination").withSockJS();
    6 U" ?" \) {) s( t- J& R2 M$ z
  8.     }% |/ _/ B6 U" O9 o8 ^; k8 l" u

  9. 2 b# X/ a7 ]) R$ V9 H0 `) ~2 y7 Q
  10.     @Override! t# e9 n8 h- }1 M' u2 d! `
  11.     public void configureMessageBroker(MessageBrokerRegistry config) {
    , g- t8 X4 q- K- d" T& }
  12.         System.out.println("服务器启动成功");# z! y* Y/ G' [# O3 X1 T1 d
  13.         //这里设置的simple broker是指可以订阅的地址,也就是服务器可以发送的地址
    * o  \9 `7 g7 S! O+ m
  14.         /**
    , G& L5 O+ T$ G' n
  15.          * userChat 用于用户聊天$ w9 q: o" n+ f/ n  A
  16.          */
    * |' B0 j! v3 L( G. |, [
  17.         config.enableSimpleBroker("/userChat");* E' Q; ~# b- P% ^
  18.         config.setApplicationDestinationPrefixes("/app");
    ! u3 k0 k* Y) p: N) Y2 r* \4 H
  19.     }
    " k) a2 T# u0 F3 K  P: t
  20. ) _: f+ F9 b% C, K4 j! g
  21.     @Override3 \8 R* b- a% m) k  {( U( V3 x
  22.     public void configureClientInboundChannel(ChannelRegistration channelRegistration) {0 Y- n( K9 J& N; H  Q1 E+ Y6 {& u
  23.     }
    " w) h% _: t) y

  24. $ t! l1 P" n* v' A1 j- j
  25.     @Override
    ! W  [4 |# q9 I' ^/ B8 l7 m
  26.     public void configureClientOutboundChannel(ChannelRegistration channelRegistration) {
      l% b3 e' F; ?" X' y0 w
  27.     }
    ' p* j2 k2 y/ ^2 f& v
  28. }</font>
复制代码
可以看到,在类中必须实现这四个方法。暂且只需要用到前两个,所以我来介绍一下,前两个方法中代码的意义。
( L( S6 V! H: B- A第一个方法,是registerStompEndpoints,大意就是注册消息连接点(我自己的理解),所以我们进行了连接点的注册:

& @- J$ Q; p) u7 Q
  1. <font size="4">registry.addEndpoint("/coordination").withSockJS();  </font>
复制代码
我们加了一个叫coordination的连接点,在网页上我们就可以通过这个链接来和服务器的WebSocket连接了。但是后面还有一句withSockJs,这是什么呢?SockJs是一个WebSocket的通信js库,Spring对这个js库进行了后台的自动支持,也就是说,我们如果使用SockJs,那么我们就不需要对后台进行更多的配置,只需要加上这一句就可以了。
( i4 ]* u* [! M$ k, H5 [5 e第二个方法,configureMessageBroker,大意是设置消息代理,也就是页面上用js来订阅的地址,也是我们服务器往WebSocket端接收js端发送消息的地址。

' J5 i: g  b2 G3 H' J( r8 K
  1. <font size="4">config.enableSimpleBroker("/userChat");  
    ( n$ ?- F* R+ D# D' q& j
  2. config.setApplicationDestinationPrefixes("/app");  </font>
复制代码

8 V4 \, ]* K4 m2 p首先,定义了一个连接点叫userChat,从名字可以看的出,最后我会做一个聊天的例子。然后,设置了一个应用程序访问地址的前缀,目的估计是为了和其他的普通请求区分开吧。也就是说,网页上要发送消息到服务器上的地址是/app/userChat。
) d' ^! @( A: J6 u- W* q说了这么多地址,估计大家都绕晕了,因为项目的整个雏形还没有出来,所以很混乱。所以接下来就配置js端。" Q. r0 a2 v% ]" H4 t4 H" [
第三步:配置Browser端: D2 {8 a$ V& `3 T( L# u& }9 }3 p$ |& u
说了这么多地址,估计大家都绕晕了,因为项目的整个雏形还没有出来,所以很混乱。所以接下来就配置js端。, I: Y& M1 }% k# ~- J+ I/ b  n0 [
首先我们要使用两个js库,一个是之前说过的SockJs,一个是stomp,这是一种通信协议,暂时不介绍它,只需要知道是一种更方便更安全的发送消息的库就行了。
, I  z1 M% f4 w* x$ f, d  u需要连接服务端的WebSocket:
" B6 i0 g+ [" {
  1. <font size="4">var socket = new SockJS('/coordination');  & w1 q! ~) h; O
  2. var stompClient = Stomp.over(socket);  ! n3 F( S* g# A$ m
  3. stompClient.connect('', '', function (frame) {});  </font>
复制代码
4 g, [4 l( N2 O9 B/ ^
没错,就只需要两句话。有了这三句话,我们就已经可以连接上了服务器。0 a% }7 F# W4 g+ o
使用SockJs还有一个好处,那就是对浏览器进行兼容,如果是IE11以下等对WebSocket支持不好的浏览器,SockJs会自动的将WebSocket降级到轮询(这个不知道的可以去百度一下),之前也说了,Spring对SockJs也进行了支持,也就是说,如果之前加了withSockJs那句代码,那么服务器也会自动的降级为轮询。(怎么样,是不是很兴奋,Spring这个特性太让人舒服了)
& q( K" K! e! r6 S但是连接上了服务器,却没有进行任何的操作,所以下一步,我们要在服务器端撰写响应和数据处理代码,在Browser端撰写消息发送和接收代码。当然,这是下一篇的内容了。/ q5 v; F# E, P% ^5 Y3 _
结语% c5 T! Q! E/ C* F/ U) M5 A
这是我的毕业设计,我的毕业设计是一个在线协同备课系统,其中包含了聊天这个小功能,所以使用它来讲解一下Spring WebSocket的使用。
  k% o2 V' \2 [) m* k* y我将代码放到了github上,有兴趣的朋友可以去看看代码,因为涉及到了很多协同操作,所以代码比较复杂,如果仅仅想了解Spring WebSocket的朋友,还是等我的下一篇文章吧。, L( A* f) v7 ?( ~' j/ O/ I: D, _
github地址:https://github.com/xjyaikj/OnlinePreparation2 A: G, X' C- R$ ?
转自:http://blog.csdn.net/xjyzxx/article/details/24182677- J  u9 `0 R& E* u* q% |
  |+ V+ R, M; D% f  j

  [. R7 e% o* K
*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

qq
收缩
快速回复 返回顶部 返回列表