Spring WebSocket教程(一)

admin 发表于 2017-4-4 21:53:25 | 栏目:站长教程 |分类:[其他教程]
学习背景: I, G/ G  P) {% @
很久以前就知道WebSocket,但那时不论是浏览器还是开发技术对它的支持都还很少。但是,Spring4突然发布,让我眼前一亮,Spring4直接支持WebSocket。
( \! i! R7 P. Z3 A. U对于Spring我还是很喜欢的,它让Java Web开发相当的有艺术感,这次支持的WebSocket又特别的和我的胃口,所以马上就去学习了。
' c* o; `: u$ w2 p$ N2 k前提5 \3 f2 H! f: H  t
本文的内容,是建立在懂J2EE编程,使用过Spring,听说过WebSocket上的,如果前面的3点大家不太明白,可以先去补补知识。
' o# m7 T2 s. v4 P0 s9 ]1 D0 qWebSocket还不是很普遍,对服务器和浏览器都有要求,不过使用了下面的一些技术,可以将浏览器的要求降低,但是服务器容器的要求还是比较高的,具体哪些服务器容易支持了WebSocket可以百度一下。- Q5 ?  i( G  z' X! `, a
第一步:配置Spring
3 a' k+ C4 g! f" z# p. R如果你跟我一样采用的Maven,那么只需要将下面的几个依赖,加入到pom.xml文件就可以了:
9 q$ b2 P' r& o4 {+ i# z6 c
  1. <font size="4"><properties>  6 n3 I6 ~- ~2 t7 G1 @
  2.     <spring.version>4.0.0.RELEASE</spring.version>  7 Q3 h; q* p4 [; U" ]; w: Q0 t5 M% t* I
  3. </properties>    Q3 p0 d. w, i* U
  4.   7 O0 m, l0 o  m) j+ N. @
  5. <dependencies>  
    # B( |, o$ [( m' n: |
  6.     <!--spring MVC-->  ' q3 E; \& X1 S7 Y  B% K2 R  P; A, O
  7.     <dependency>  / u0 N) ]( @5 O
  8.         <groupId>org.springframework</groupId>  * L9 ^+ S# E2 {2 v$ _' d9 U
  9.         <artifactId>spring-core</artifactId>  - |. U- e7 b0 }5 \( a) |# J
  10.         <version>${spring.version}</version>  ! z$ B6 }- i* v1 `7 y  k8 ^
  11.     </dependency>  , R, V8 a8 [& b( i' I5 x
  12.   
    ' I0 U7 l3 k6 ]0 A- ~& L) K
  13.     <dependency>  
    ( [* T# \/ ^5 J  g1 }( X7 v$ l
  14.         <groupId>org.springframework</groupId>  , r; w5 l2 @% h. `
  15.         <artifactId>spring-web</artifactId>  3 p( N: v1 ?9 V
  16.         <version>${spring.version}</version>  ! X0 f8 c! o9 z/ @$ `8 ~% `1 V) o
  17.     </dependency>  
    1 I4 L+ R; [& \/ v! i0 [
  18.   ; \8 Y2 g6 H) R1 a7 E
  19.     <dependency>  
    # x# s( N" x" F2 ?. M! i
  20.         <groupId>org.springframework</groupId>  
    0 R/ z( q! d: E/ j4 i, ^; A
  21.         <artifactId>spring-webmvc</artifactId>  
    ! s0 |9 R5 |  @  {( C  Z! ~
  22.         <version>${spring.version}</version>  
    " T( g! p" P) z
  23.     </dependency>  ) g1 ~, D6 ~7 S% Q& u0 s
  24.   0 \) v6 q- I  E5 E( i
  25.     <!-- jstl -->  7 J3 P, o3 O! e) p! ~
  26.     <dependency>  
    : L9 X2 n' S; {( U" B4 `
  27.         <groupId>jstl</groupId>  . E) x1 R' I% m3 r$ J! P
  28.         <artifactId>jstl</artifactId>  
    / h9 |) ?! \/ h5 P5 D
  29.         <version>1.2</version>  2 {" _% A6 l+ ^, i- z0 G. d. ~
  30.     </dependency>  ) c5 [) i0 C! w& n5 e1 U
  31.   
    6 l; s6 D* U7 d( q
  32.     <!--spring测试框架-->  
    % m) C1 V4 w" V3 u8 N, t
  33.     <dependency>  
    # m, D% O3 v; G5 Y, ]
  34.         <groupId>org.springframework</groupId>  - w' [! h, ?* q3 m& g- a
  35.         <artifactId>spring-test</artifactId>  
    8 L& ]' E8 R. t( I) a
  36.         <version>${spring.version}</version>  , E" h0 R) f( s, l
  37.         <scope>test</scope>  
    6 s5 W+ A7 R. l
  38.     </dependency>  . V: y. f/ p) i* ^4 ]
  39.   1 X; B4 z8 i2 `  j
  40.     <!--spring数据库操作库-->  
    0 {1 d& D7 e6 k
  41.     <dependency>  % m* b( {  E; h/ X
  42.         <groupId>org.springframework</groupId>  / S1 x' y- F2 ?" ^# l5 V; j' _( j
  43.         <artifactId>spring-jdbc</artifactId>  
    0 K# W! ?- r' F2 @& Q4 u+ ?
  44.         <version>${spring.version}</version>  
    7 p2 Y( u/ ^$ |% X. u8 m4 `
  45.     </dependency>  
    * U1 P" ]. c( r6 }, ~
  46.   7 ^$ h8 N! r- N+ A. ]
  47.     <dependency>  : r" |3 L" X* ~, c( N: r2 w( \
  48.         <groupId>junit</groupId>  
    ) n0 l5 \6 T7 D  H) f, W
  49.         <artifactId>junit</artifactId>  
    % O+ H8 v/ Q- A4 _4 v2 M% i
  50.         <version>4.8.2</version>  " N! H% ~' e  u* u/ F4 Q; Q9 F
  51.         <scope>test</scope>  
    3 P' m" a8 o. g  C7 o
  52.     </dependency>  
    4 C( W$ ?( Q6 M/ h0 T- i- K
  53.   
    - p& `+ l, b( O# T! V2 w7 f
  54.     <!--spring websocket库-->  4 J9 a: Q# J5 Z; \! g' a2 M
  55.     <dependency>  ; Z- `1 _5 E2 F0 g& H
  56.         <groupId>org.springframework</groupId>  
    , d- A" E/ U2 j0 D, z- ]
  57.         <artifactId>spring-websocket</artifactId>  4 f! x% V. V2 y7 F! o; l
  58.         <version>${spring.version}</version>  
    7 Z4 W5 u7 e! _  {0 d
  59.     </dependency>  ! T6 Q7 n& {! g9 ]; d/ `4 a+ D
  60.     <dependency>  6 [' V: k! l7 D5 [5 s) i
  61.         <groupId>org.springframework</groupId>  
    4 P, y, p! c, X6 L
  62.         <artifactId>spring-messaging</artifactId>  # _. S+ w0 H6 m% m7 X" i
  63.         <version>${spring.version}</version>  
    " _/ D1 d4 C/ c- S7 o
  64.     </dependency>  ) h) ~9 d7 O. d, G9 T
  65.     z5 i+ I9 S/ D- V
  66.     <!--jackson用于json操作-->  
    6 j% ]5 u% l& m7 ~0 a
  67.     <dependency>  
    # I1 j0 z/ q3 D4 d0 Q* M1 h
  68.         <groupId>com.fasterxml.jackson.core</groupId>  8 P9 j/ y/ ]" n6 I7 }4 h$ a4 b
  69.         <artifactId>jackson-databind</artifactId>  
    9 p+ |4 O. s  I) M' |% W4 l
  70.         <version>2.3.0</version>  
    , C% _, n3 v1 t* f; a6 i3 _7 v8 [5 ^
  71.     </dependency>  
    ) f; B5 [' v- u7 n9 F+ T% E5 d) R6 u
  72.   ; t. g& j- P3 X) I6 ^8 O/ v
  73.     <dependency>  3 y  {' _7 d8 `3 }. D& B3 s
  74.         <groupId>commons-fileupload</groupId>  ; B6 v# G, u: L0 Z& r* Z+ e3 t
  75.         <artifactId>commons-fileupload</artifactId>  
    , J) l  v: {; z2 k9 t8 D
  76.         <version>1.2.2</version>  & J2 U8 C5 Y& I( f9 h" }+ t
  77.     </dependency>  ( Z  o' E8 \1 F! K- {; ^5 l3 r* e
  78.     <dependency>  
    ) X4 ^! \' P: `# h
  79.         <groupId>commons-io</groupId>  # F0 a% P/ e! w
  80.         <artifactId>commons-io</artifactId>  " ~+ T! A2 U: x9 B, u5 N
  81.         <version>2.2</version>  
    ' ^& d. I  o- M" J0 V) ?
  82.     </dependency>  # V, O1 Z2 b6 y6 U  }( N
  83.     <!--使用阿里的连接池-->  
    $ ?! d% D4 Y. p3 I0 x* h
  84.     <dependency>  7 H6 U; Z6 ~: S6 p6 s$ A0 V5 @
  85.         <groupId>com.alibaba</groupId>  
    ' h- E+ N8 `) i  `2 s
  86.         <artifactId>druid</artifactId>  
    # B6 ?" }4 ?+ J+ V! U$ v+ g
  87.         <version>1.0.4</version>  0 ]3 I7 i- e# J" A
  88.     </dependency>  $ r3 ]' m" x  d; e& W- y
  89.     <!--mysql connector-->  0 V+ y( R: S6 b( W$ k
  90.     <dependency>  
    8 z1 q! d/ Q2 `0 K, J
  91.         <groupId>mysql</groupId>  ! N1 M/ R9 Y3 M' w
  92.         <artifactId>mysql-connector-java</artifactId>  $ j3 _) H5 M0 B# g# I
  93.         <version>5.1.29</version>  
    2 w2 M# W" a6 V6 j
  94.     </dependency>  $ ~/ ?& U: c9 n, h/ j: D. I
  95.   
    : k# Q2 i- K  x5 {( r+ u  ~
  96. </dependencies>  </font>
复制代码
Spring的配置我就不一一贴出来了,可以去github看,地址我会贴在下面。0 W* s0 J. q7 T, g! m% q/ W
第二步:配置WebSocket
: M5 c2 e/ g! ~! k/ |我采用的是使用Configurer类和 Annotation来进行WebSocket配置。! S+ s9 D9 j/ A/ V- B, X6 |6 V) y3 N+ [
首先要创建一个类,继承WebSocketMessageBrokerConfigurer,并且在类上加上annotation:@Configuration和@EnableWebSocketMessageBroker。这样,Spring就会将这个类当做配置类,并且打开WebSocket。
  1. <font size="4">@Configuration% D5 S$ v  W' Y
  2. @EnableWebSocketMessageBroker
    * z1 r2 O' f, @; X' V
  3. public class WebSocketConfig implements WebSocketMessageBrokerConfigurer{
    2 g) q' g0 a$ Y8 H0 s6 @( H
  4.     @Override
    7 M9 r! e1 H2 O3 s9 Q+ g
  5.     public void registerStompEndpoints(StompEndpointRegistry registry) {
    / P! u5 S5 l/ F
  6.         //添加这个Endpoint,这样在网页中就可以通过websocket连接上服务了
    - S# D, Z% ?0 f/ O
  7.         registry.addEndpoint("/coordination").withSockJS();. ^' @9 g) \0 c7 M% I: O/ V% A
  8.     }* i) h1 c* u/ s+ p0 Z

  9. " c0 [6 K, L+ D* `4 \* j
  10.     @Override
    . u) s+ y; h  I) {) K
  11.     public void configureMessageBroker(MessageBrokerRegistry config) {
    4 i& R; ?  |! `- E" r  G
  12.         System.out.println("服务器启动成功");) k- u! z4 R$ |; Q1 d8 ?
  13.         //这里设置的simple broker是指可以订阅的地址,也就是服务器可以发送的地址
    9 e8 Z9 {7 y. w/ z3 Q
  14.         /**# q8 g6 N3 l  e( E" D: |, T
  15.          * userChat 用于用户聊天- q7 J& k9 L8 K
  16.          */) q; F: m) d  ?. B! R5 h2 C! o
  17.         config.enableSimpleBroker("/userChat");. S, C6 @1 D+ b6 X; B: \. S: f
  18.         config.setApplicationDestinationPrefixes("/app");
    / x8 y: e: t+ i  N2 j
  19.     }
    8 L* b0 ]0 J" o# ?  P
  20. * F4 q5 g' f' T- n+ c# ~/ A  E
  21.     @Override
    ( A. Z* d* @& n+ D5 J+ H/ n
  22.     public void configureClientInboundChannel(ChannelRegistration channelRegistration) {/ G  ?% n, k6 ]3 N% y- p
  23.     }
    ; ]% s; b9 O0 |; }+ y+ y1 E% B, }- ^/ h

  24. 0 b. L8 }; w% @" M1 @( `
  25.     @Override
    ! K/ X( l/ `! ]
  26.     public void configureClientOutboundChannel(ChannelRegistration channelRegistration) {
    / h/ X  D- Q% {. w  ^
  27.     }
    $ G4 n7 Q3 U. o, o% _
  28. }</font>
复制代码
可以看到,在类中必须实现这四个方法。暂且只需要用到前两个,所以我来介绍一下,前两个方法中代码的意义。
& |4 H; I" Z# Y$ U1 n第一个方法,是registerStompEndpoints,大意就是注册消息连接点(我自己的理解),所以我们进行了连接点的注册:
4 l1 a1 L- y3 A* k9 y
  1. <font size="4">registry.addEndpoint("/coordination").withSockJS();  </font>
复制代码
我们加了一个叫coordination的连接点,在网页上我们就可以通过这个链接来和服务器的WebSocket连接了。但是后面还有一句withSockJs,这是什么呢?SockJs是一个WebSocket的通信js库,Spring对这个js库进行了后台的自动支持,也就是说,我们如果使用SockJs,那么我们就不需要对后台进行更多的配置,只需要加上这一句就可以了。
7 V$ D, G# O! ~第二个方法,configureMessageBroker,大意是设置消息代理,也就是页面上用js来订阅的地址,也是我们服务器往WebSocket端接收js端发送消息的地址。

7 B4 F) f: Z/ y; X
  1. <font size="4">config.enableSimpleBroker("/userChat");  2 S% Q0 r/ s* ?$ |
  2. config.setApplicationDestinationPrefixes("/app");  </font>
复制代码

1 J3 X7 Y* K0 w3 }首先,定义了一个连接点叫userChat,从名字可以看的出,最后我会做一个聊天的例子。然后,设置了一个应用程序访问地址的前缀,目的估计是为了和其他的普通请求区分开吧。也就是说,网页上要发送消息到服务器上的地址是/app/userChat。5 q2 J: x  o. {& u8 T
说了这么多地址,估计大家都绕晕了,因为项目的整个雏形还没有出来,所以很混乱。所以接下来就配置js端。0 J  f* a9 }" e) D/ o6 z
第三步:配置Browser端
) K3 H' J  d" k) D7 i1 G说了这么多地址,估计大家都绕晕了,因为项目的整个雏形还没有出来,所以很混乱。所以接下来就配置js端。9 ?  r; U4 ?9 O
首先我们要使用两个js库,一个是之前说过的SockJs,一个是stomp,这是一种通信协议,暂时不介绍它,只需要知道是一种更方便更安全的发送消息的库就行了。8 P8 U8 |+ S6 D! d( _! ~
需要连接服务端的WebSocket:
' j; r5 J, l% n0 N$ Z; e# a; h
  1. <font size="4">var socket = new SockJS('/coordination');  
    ' c! }) G; ?" o* z- ~4 Z
  2. var stompClient = Stomp.over(socket);  
    ; S$ g6 ]. w9 {) E6 p) l3 A6 b1 O
  3. stompClient.connect('', '', function (frame) {});  </font>
复制代码
+ e/ h# d$ D4 a- e+ i5 o! f
没错,就只需要两句话。有了这三句话,我们就已经可以连接上了服务器。( K) {' }# l9 o6 P8 Z' A, C
使用SockJs还有一个好处,那就是对浏览器进行兼容,如果是IE11以下等对WebSocket支持不好的浏览器,SockJs会自动的将WebSocket降级到轮询(这个不知道的可以去百度一下),之前也说了,Spring对SockJs也进行了支持,也就是说,如果之前加了withSockJs那句代码,那么服务器也会自动的降级为轮询。(怎么样,是不是很兴奋,Spring这个特性太让人舒服了)
; Z4 z. v+ K' F' g& c! _/ b  g但是连接上了服务器,却没有进行任何的操作,所以下一步,我们要在服务器端撰写响应和数据处理代码,在Browser端撰写消息发送和接收代码。当然,这是下一篇的内容了。3 H% `4 ~  j2 x
结语" ^7 f/ o9 T) T# z. C8 s
这是我的毕业设计,我的毕业设计是一个在线协同备课系统,其中包含了聊天这个小功能,所以使用它来讲解一下Spring WebSocket的使用。
  i8 W7 c. A. \4 W; d1 y# F我将代码放到了github上,有兴趣的朋友可以去看看代码,因为涉及到了很多协同操作,所以代码比较复杂,如果仅仅想了解Spring WebSocket的朋友,还是等我的下一篇文章吧。0 A! k1 X( V' @% M& A% f& m! r
github地址:https://github.com/xjyaikj/OnlinePreparation$ w9 L; Q9 \8 p5 X- Z; q, _+ ]
转自:http://blog.csdn.net/xjyzxx/article/details/24182677
$ F+ J4 l5 f8 K4 y7 v' Q0 I5 |8 }. p5 c

1 h- N, s  M: {) d
$ E. @, @( t2 H& T4 F/ z1 V9 G
*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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