websoket在项目中的使用

       项目中要求用户A发起终止申请请求后,对应的相关权限的用户B、用户C等即时收到终止的请求,针对这个需求在项目中加入了websoket功能,下面是具体的使用过程。

1.在maven中添加jar引用

1 <dependency>
2 <groupId>org.springframework</groupId>
3 <artifactId>spring-websocket</artifactId>
4  <version>5.0.9.RELEASE</version>
5 </dependency>
View Code

2.在xml的配置,在websocket-context.xml的配置,在service-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:p="http://www.springframework.org/schema/p" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.1.xsd
    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-4.1.xsd
    http://www.springframework.org/schema/websocket
    http://www.springframework.org/schema/websocket/spring-websocket-4.1.xsd">
<!--
    <aop:aspectj-autoproxy proxy-target-class="true" />
     Enables the Spring MVC @Controller programming model -->
     
    <bean id="userWebsocket" class="com.gta.scm.websocket.UserWebsocket">
    </bean>
     
    <bean id="websocket" class="com.gta.scm.websocket.WebsocketEndPoint"> 
        <property name="list">  
            <list>  
                <ref bean="userWebsocket" />  
            </list>  
        </property>  
    </bean> 
  
    <websocket:handlers allowed-origins="*">  
        <websocket:mapping path="/websocket.do" handler="websocket"/>  
        <websocket:handshake-interceptors>  
        <bean class="com.gta.scm.websocket.HandshakeInterceptor">  
            <property name="list">  
                <list>  
                    <ref bean="userWebsocket" />  
                </list>  
            </property>  
        </bean> 
        </websocket:handshake-interceptors>  
    </websocket:handlers> 
</beans>
View Code

 <import resource="websocket-context.xml"/>

3.在后台拦截器和处理类

 

会话拦截器

 1 import java.util.List;
 2 import java.util.Map;
 3 
 4 import org.springframework.http.server.ServerHttpRequest;
 5 import org.springframework.http.server.ServerHttpResponse;
 6 import org.springframework.stereotype.Component;
 7 import org.springframework.web.socket.WebSocketHandler;
 8 import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
 9 
10 import com.gta.scm.websocket.intercept.ServiceHandshakeInterceptor;
11 
12 
13 @Component
14 public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor{
15     public static final String JSESSIONID = "JSESSIONID";
16     private List<ServiceHandshakeInterceptor> list;
17     /**
18      * 当用户连接ServerSocket时执行
19      * 通过request获取用户登陆的jsessionId的值,放入到集合attributes中
20      */
21     @Override  
22     public boolean beforeHandshake(ServerHttpRequest request,  
23             ServerHttpResponse response, WebSocketHandler wsHandler,  
24             Map<String, Object> attributes) throws Exception {  
25  
26         if(list!=null){
27             for (ServiceHandshakeInterceptor serviceHandshakeInterceptor : list) {
28                 serviceHandshakeInterceptor.beforeHandshake(request, response, wsHandler, attributes);
29             }
30         }
31         return super.beforeHandshake(request, response, wsHandler, attributes);  
32     }  
33     
34  
35   
36     /**
37      * 当用户连接完ServerSocket时执行
38      */
39     @Override  
40     public void afterHandshake(ServerHttpRequest request,  
41             ServerHttpResponse response, WebSocketHandler wsHandler,  
42             Exception ex) {  
43         if(list!=null){
44             for (ServiceHandshakeInterceptor serviceHandshakeInterceptor : list) {
45                 serviceHandshakeInterceptor.afterHandshake(request, response, wsHandler, ex); 
46             }
47         }
48         super.afterHandshake(request, response, wsHandler, ex);  
49     }
50 
51 
52 
53     public List<ServiceHandshakeInterceptor> getList() {
54         return list;
55     }
56 
57 
58 
59     public void setList(List<ServiceHandshakeInterceptor> list) {
60         this.list = list;
61     }  
62 
63 }
View Code
 1 import java.util.Map;
 2 
 3 import org.springframework.http.server.ServerHttpRequest;
 4 import org.springframework.http.server.ServerHttpResponse;
 5 import org.springframework.web.socket.WebSocketHandler;
 6 
 7 public interface ServiceHandshakeInterceptor {
 8     public void beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
 9             Map<String, Object> attributes);
10 
11     public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
12             Exception ex);
13 }
View Code

websokect处理器

 1 import org.springframework.web.socket.CloseStatus;
 2 import org.springframework.web.socket.TextMessage;
 3 import org.springframework.web.socket.WebSocketSession;
 4 
 5 public interface ServiceTextWebSocketHandler {
 6     public void handleTextMessage(WebSocketSession session, TextMessage message) ;
 7     public void afterConnectionEstablished(WebSocketSession session);
 8     public void handleTransportError(WebSocketSession session, Throwable exception) ;
 9     public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) ; 
10         
11 }
View Code
 1 import java.util.List;
 2 
 3 import org.springframework.stereotype.Component;
 4 import org.springframework.web.socket.CloseStatus;
 5 import org.springframework.web.socket.TextMessage;
 6 import org.springframework.web.socket.WebSocketSession;
 7 import org.springframework.web.socket.handler.TextWebSocketHandler;
 8 
 9 import com.gta.scm.websocket.intercept.ServiceTextWebSocketHandler;
10 @Component
11 public class WebsocketEndPoint extends TextWebSocketHandler {
12     // 所有连接用户的WebSocketSession,键是用户的jsessionID,值是连接的会话对象
13     private List<ServiceTextWebSocketHandler> list;
14     /**
15      * 该方法在用户前端进行发送消息后进行业务处理的行为
16      */
17     @Override
18     public void handleTextMessage(WebSocketSession session, TextMessage message) {
19 
20         if (list!=null) {
21             for (ServiceTextWebSocketHandler serviceTextWebSocketHandler : list) {
22                 serviceTextWebSocketHandler.handleTextMessage(session, message);
23             }
24         }
25     }
26 
27     /**
28      * 该方法是连接生效后进行的处理业务行为,每个用户和服务端建立websocket链接时调用
29      */
30     @Override
31     public void afterConnectionEstablished(WebSocketSession session) throws Exception {
32         // 与客户端完成连接后调用
33         if (list!=null) {
34             for (ServiceTextWebSocketHandler serviceTextWebSocketHandler : list) {
35                 serviceTextWebSocketHandler.afterConnectionEstablished(session);
36             }
37         }
38     }
39 
40     @Override
41     public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
42         // 消息传输出错时调用
43         if (list!=null) {
44             for (ServiceTextWebSocketHandler serviceTextWebSocketHandler : list) {
45                 serviceTextWebSocketHandler.handleTransportError(session,exception);
46             }
47         }
48     }
49 
50     @Override
51     public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
52         if (list!=null) {
53             for (ServiceTextWebSocketHandler serviceTextWebSocketHandler : list) {
54                 serviceTextWebSocketHandler.afterConnectionClosed(session,closeStatus);
55             }
56         }
57     }
58 
59     @Override
60     public boolean supportsPartialMessages() {
61         return false;
62     }
63 
64     public List<ServiceTextWebSocketHandler> getList() {
65         return list;
66     }
67 
68     public void setList(List<ServiceTextWebSocketHandler> list) {
69         this.list = list;
70     }
71     
72  
73     
74 
75 }
View Code
  1 import java.io.IOException;
  2 import java.util.HashMap;
  3 import java.util.Iterator;
  4 import java.util.List;
  5 import java.util.Map;
  6 import java.util.Map.Entry;
  7 import java.util.Set;
  8 
  9 import javax.servlet.http.Cookie;
 10 
 11 import org.apache.commons.lang.StringUtils;
 12 import org.slf4j.Logger;
 13 import org.slf4j.LoggerFactory;
 14 import org.springframework.http.server.ServerHttpRequest;
 15 import org.springframework.http.server.ServerHttpResponse;
 16 import org.springframework.http.server.ServletServerHttpRequest;
 17 import org.springframework.stereotype.Component;
 18 import org.springframework.web.socket.CloseStatus;
 19 import org.springframework.web.socket.TextMessage;
 20 import org.springframework.web.socket.WebSocketHandler;
 21 import org.springframework.web.socket.WebSocketSession;
 22 import org.springframework.web.socket.handler.TextWebSocketHandler;
 23 
 24 import com.gta.scm.common.constant.CommonConstant;
 25 import com.gta.scm.common.login.UserLoginRsp;
 26 import com.gta.scm.websocket.intercept.ServiceHandshakeInterceptor;
 27 import com.gta.scm.websocket.intercept.ServiceTextWebSocketHandler;
 28 
 29 @Component
 30 public class UserWebsocket  implements ServiceTextWebSocketHandler,ServiceHandshakeInterceptor{
 31     Logger logger = LoggerFactory.getLogger(UserWebsocket.class);
 32     public static final String JSESSIONID = "JSESSIONID";
 33     private static final Map<String,WebSocketSession> users = new HashMap<String,WebSocketSession>();
 34     
 35     /**
 36      * 该方法在用户前端进行发送消息后进行业务处理的行为
 37      */
 38     @Override
 39     public void handleTextMessage(WebSocketSession session, TextMessage message) {
 40         logger.debug("handleTextMessage...");    
 41          try {
 42             sendMsgToUsers(message.getPayload(), session.getId()) ;
 43         } catch (Exception e) {
 44             e.printStackTrace();
 45         }
 46     }
 47 
 48     /**
 49      * 该方法是连接生效后进行的处理业务行为,每个用户和服务端建立websocket链接时调用
 50      */
 51     @Override
 52     public void afterConnectionEstablished(WebSocketSession session) {
 53         logger.debug("afterConnectionEstablished...");    
 54         Map<String, Object> m = session.getAttributes();
 55         UserLoginRsp user = (UserLoginRsp) m.get(CommonConstant.LOGIN_USER);
 56         users.put(user.getUserInfoId().toString(), session);
 57         logger.debug("put "+user.getUserAccount()+" in sessions");    
 58     }
 59     
 60     private String getJsessionId(WebSocketSession session){
 61         Object jsessionIdObj = session.getAttributes().get(HandshakeInterceptor.JSESSIONID);
 62         if (jsessionIdObj != null) {
 63             return jsessionIdObj.toString();
 64         }
 65         return null;
 66     }
 67     
 68     @Override
 69     public void handleTransportError(WebSocketSession session, Throwable exception) {
 70         logger.debug("handleTransportError...");    
 71          if(session.isOpen()){
 72             try {
 73                 session.close();
 74             } catch (IOException e) {
 75                 logger.debug("handleTransportError...",e);    
 76             }
 77         }
 78         logger.debug("connection closed......");
 79         Map<String, Object> m = session.getAttributes();
 80         UserLoginRsp user = (UserLoginRsp) m.get(CommonConstant.LOGIN_USER);
 81         if(user!=null && users.get(user.getUserInfoId().toString())!=null) {
 82             users.remove(user.getUserInfoId().toString(), session);
 83         }
 84         logger.debug("remove user success......");
 85     }
 86     // 一个客户端连接断开时关闭
 87     @Override
 88     public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
 89         logger.debug("afterConnectionClosed...");    
 90         Map<String, Object> m = session.getAttributes();
 91         UserLoginRsp user = (UserLoginRsp) m.get(CommonConstant.LOGIN_USER);
 92         if(user!=null && users.get(user.getUserInfoId().toString())!=null) {
 93             users.remove(user.getUserInfoId().toString(), session);
 94         }
 95         
 96     }
 97     /**向所有用户发送 信息
 98      * @param message
 99      * @throws Exception
100      */
101     public void sendMsgToAllUsers(String message) throws Exception{
102         logger.debug("sendMsgToAllUsers...");    
103         Entry<String,WebSocketSession> entry = null;
104         Iterator<Entry<String,WebSocketSession>> entryIt = users.entrySet().iterator();
105         while(entryIt.hasNext()) {
106             entry = entryIt.next();
107             entry.getValue().sendMessage(new TextMessage(message.getBytes()));
108         }
109     }
110     
111     /**向Set<String> jsessionSet 中设置的用户发送信息
112      * @param message
113      * @param jsessionSet
114      * @throws Exception
115      */
116     public void sendMsgToUsers(String message,Set<String> jsessionSet) throws Exception{
117         logger.debug("sendMsgToUsers...");    
118         for(String jessionId : jsessionSet) {
119             if (users.containsKey(jessionId)) {
120                 users.get(jessionId).sendMessage(new TextMessage(message.getBytes()));
121                 
122 //                ShiroAuthorizationHelper.clearAuthenticationInfo(users.get(jessionId).getId());
123             }
124         }
125     }
126     public void sendMsgToUsers(String message,String jessionId) throws Exception{
127         logger.debug("sendMsgToUsers...");    
128         if (users.containsKey(jessionId)) {
129                 users.get(jessionId).sendMessage(new TextMessage(message.getBytes()));
130             }
131     }
132     /**
133      * 当用户连接ServerSocket时执行
134      * 通过request获取用户登陆的jsessionId的值,放入到集合attributes中
135      */
136     @Override// 
137     public void beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
138             Map<String, Object> attributes) {
139         logger.debug("beforeHandshake...");
140           
141                 if (request instanceof ServletServerHttpRequest) {  
142                     ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;  
143                     Cookie cookies[] = servletRequest.getServletRequest().getCookies();
144                     String jsessionId = this.getTicket(cookies);
145                     if (!StringUtils.isNotEmpty(jsessionId)) {
146                         attributes.put(JSESSIONID, this.getTicket(cookies));
147                     }
148                 }  
149              
150             
151     }
152     private String getTicket(Cookie cookies[]){
153         String jsessionId = null;
154         if(cookies != null){
155             for(Cookie ck: cookies){
156                 if(ck.getName().trim().equals(JSESSIONID)){
157                     jsessionId = ck.getValue();
158                     break;
159                 }
160             }
161         }
162         return jsessionId;
163     }
164     /**
165      * 当用户连接完ServerSocket时执行
166      */
167     @Override
168     public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
169             Exception ex) {
170         
171         logger.debug("afterHandshake...");
172     }
173 
174     public void sendMsgToUsers(String message, List<String> idList) throws Exception{
175         logger.debug("sendMsgToUsers...");    
176         for(String jessionId : idList) {
177             if (users.containsKey(jessionId)) {
178                 logger.debug("sendMsgToUsers..."+jessionId);    
179                 users.get(jessionId).sendMessage(new TextMessage(message.getBytes()));
180                 
181             }
182         }
183         
184     }
185 }
View Code

4.在具体业务的地方调用

1     //向学生端发通知强制退出到首页
2             List<String> userList=sysMessageBaseService.getTrainingUser(usp.getTrainingId());
3             String[] idStr = (String[])userList.toArray(new String[userList.size()]);
4             Set<String> set = new HashSet<String>(Arrays.asList(idStr));
5             userWebsocket.sendMsgToUsers("signOut", set);
View Code
 1 String[] idStr = new String[userAccount.size()];
 2         String[] ownId = new String[userAccount.size()];
 3         for (int i = 0; i < userAccount.size(); i++) {
 4             String str = GsonUtils.parseJson(userAccount.get(i));
 5             JSONObject object = JSONObject.fromObject(str);
 6             if (object.getString("organizationCode").equals(partyCode))// 自己方人员
 7             {
 8                 ownId[i] = object.getString("userId");
 9             } else {
10                 idStr[i] = object.getString("userId");
11             }
12 
13         }
14         String strMessage = "";
15         String myMessage = "1";
16         if (stateType == CommonEnum.TradingContractStatus.SEND_TERMINATION.getTypeCode()) // 发送终止
17         {
18             strMessage="apply;"+contractCode;
19             //strMessage = "对方申请终止" + contractCode + "(合同号),请尽快处理!";
20         } else if (stateType == CommonEnum.TradingContractStatus.CONFIRMED.getTypeCode())// 终止不同意
21         {
22             strMessage="disagree;"+contractCode;
23             //strMessage = "对方不同意终止" + contractCode + "(合同号),请尽快处理!";
24         } else if (stateType == CommonEnum.TradingContractStatus.TERMINATION.getTypeCode())// 终止不同意
25         {
26             strMessage="agree;"+contractCode;
27             //strMessage = "对方同意终止" + contractCode + "(合同号),请尽快处理!";
28         } else if (stateType == 5)// 终止取消
29         {
30             strMessage="cancel;"+contractCode;
31             //strMessage = "对方取消终止" + contractCode + "(合同号),请尽快处理!";
32         }
33         infoAndOut(idStr, strMessage); // 对方操作
34         infoAndOut(ownId, myMessage); // 我方刷新数据
View Code

5.websoket.js的引入与在具体页面的实现

 1 /**
 2  *  
 3  * @param $
 4  */
 5 (function($) {//每页开始直接复制
 6     $.websocket = {//外部可以直接访问的对象, 要导入该文件 调用对象$.devfrw.base.demo
 7         connect : function(urlPath,initOpt) {//外部可以直接访问的对象的方法, 要导入该文件 调用方法$.devfrw.base.demo.pub
 8                 setUrl(urlPath);
 9                 var opt={onopen:function(){},onmessage:function(event){},onclose:function(event){}};
10                 if(initOpt){
11                     opt= $.extend(opt, initOpt);
12                 };
13                 if (!url) {  
14                     alert('websocket url 未设置!');  
15                     return;  
16                 }  
17                 ws =new WebSocket(url);  
18                 ws.onopen = function () {  
19                 //    console.log('打开链接');
20                     opt.onopen();
21                 };  
22                 ws.onmessage = function (event) {  
23                 //    console.log('消息接收');
24                     opt.onmessage(event);
25                 };  
26                 ws.onclose = function (event) {  
27                 //    console.log('关闭链接');
28                     opt.onclose(event);
29                 };  
30         },
31         setUrl:function(urlPath){
32             setUrl(urlPath);
33         },
34         send:function(message){
35               if (ws != null) {  
36                     ws.send(message);  
37                 } else {  
38                     alert('websocket链接不存在!');  
39                 }  
40         },
41         disconnect:function(){
42             if (ws != null) {  
43                 ws.close();  
44                 ws = null;  
45             }  
46         }
47     };
48     var ws = null;  
49     var url = null;  
50     function setUrl(urlPath) {  
51           if (window.location.protocol == 'http:') {  
52               url = 'ws://' + window.location.host + urlPath;  
53           } else {  
54               url = 'wss://' + window.location.host + urlPath;  
55           }  
56     }  
57 })(jQuery);//直接复制 一定要;号
View Code
 1 $.websocket.connect('/portal/websocket.do', {
 2         onmessage : function(event) {//接收数据 
 3             if(event.data!=""&&event.data!=null)
 4             {
 5             if (contains(event.data, "clear")) {
 6                 $(".pay").each(function() {
 7                     var id = $(this).parent().attr("id");
 8                     var salescode = $(this).parent().attr("salescode");
 9                     if (contains(event.data, id + ";")) {                        
10                         $("#send" + id).removeClass("disabled");
11                         $("#send" + id).addClass("send");
12                         $("#pay" + id).removeClass("pay");
13                         $("#pay" + id).addClass("disabled");
14                         $("#delete" + id).removeClass("disabled");
15                         $("#delete" + id).attr("onclick","del("+salescode+")");
16                     }
17                 });
18             }
19             if (contains(event.data, "signOut")) {
20                  layer.msg("轮次结束请返回首页!", {
21                         time: 5000,
22                         shade: 0.6,
23                         success: function (layero, index) {
24                             var msg = layero.text();
25                             var i = 5;
26                             var timer = null;
27                             var fn = function () {
28                                 layero.find(".layui-layer-content").text(msg + '(倒计时' + i + '秒)');
29                                 if (!i) {
30                                     layer.close(index);
31                                     clearInterval(timer);
32                                 }
33                                 i--;
34                             };
35                             timer = setInterval(fn, 1000);
36                             fn();
37                         },
38                     }, function () {
39                         window.location.href="${basePath}student/main/index";
40                     });
41                 
42             }
43             }
44 
45         },
46         onclose : function(event) {    
47                 $.websocket.disconnect();
48         }
49     });
View Code

 

posted @ 2019-06-14 11:37  水中的空气  阅读(332)  评论(0编辑  收藏  举报