El siguiente tutorial es un sistema CRM de la compañía que participé en el desarrollo de una empresa y resolví información relevante. Hay muchas funciones de empuje de mensajes en el sistema, y la tecnología WebSocket se utiliza en él. El siguiente editor lo compiló y lo compartió en la plataforma de red Wulin para su referencia
1. Dependencia de Maven
<Spendency> <ProupId> javax.servlet </groupid> <artifactid> javax.servlet-api </artifactid> <versión> 3.1.0 </versión> </pendency> <ependency> <proupid> com.fasterxml.jackson.core </proupid> <artifactid> jackson-core </artifactid> <lother> <lother> <lother> n. 0 </Version> </Dependency> <Spendency> <MoupRid> com.fasterxml.jackson.core </groupid> <artifactid> jackson-core </artifactid> <versions> 2.3.0 </versión> </pendency> <pendency> <proupid> com.fasterxml.jackson.core </groupid> <artifactid> jackson -databind </artifactid> <versión> 2.3.0 </versewer> </pendency> <pendency> <uproupid> org.springframework </groupid> <artifactid> spring-websocket </arfactid> <versión> 4.0.1. Release </Version> </Dependency> <Spendency> <ProupId> org.springframework </groupid> <artifactID> spring-mesing </artifactid> <versión> 4.0.1.release </versión> </pendency>
2. Configuración de servicio de resorte
<? xml versión = "1.0" encoding = "utf-8"?> <frijoles xmlns = "http://www.springframework.org/schema/beans" xmlns: context = "http://www.springframework.org/schema/cont Ext "xmlns: mvc =" http://www.springframework.org/schema/mvc "xmlns: tx =" http://www.springframework.org/schema/tx " xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" xmlns: webSocket = "http://www.springframework.org/schema/websocket" xsi: schemalocation = "http: // www .springframework.org/schema/Beansshttp: //www.springframework.org/schema/Beans/spring-Beans-3.1.xsdhttp: //www.springframework.org/schema/context/spring -context-3.1.xsdhttp: //www.springframework.org/schema/mvchttp: //www.springframework.o rg/schema/mvc/spring-mvc-3.1.xsdhttp: //www.springframework.org/schema/txhttp: //www.spr ingframework.org/schema/tx/spring-tx-3.1.xsdhttp://www.springframework.org/schema/websocketthttp://www.springframework.org/schema/websockocockococococet.-Websockocockococococet.xsd">......... id = "WebSocket"/> <WebSocket: Handlers> <WebSocket: Mapping Path = "/WebSocket" Handler = "WebSocket"/> <WebSocket: Handshake-Interceptors> <Bean/> <WebSocket: Handshake-Interceptors> </WebSocket: Handlers> </ Beans>
Entre ellos, la ruta correspondiente a la ruta es la ruta de la interfaz que se sintonizó a través del protocolo WS en la sección anterior.
3. Implementación de HandshakeInterceptor
paquete cn.bridgeli.websocket; import cn.bridgeli.utils.usermanager; import cn.bridgeli.util.dateutil; import cn.bridgeli.sharesession.userinfo; import org.apache.commons.lang.stringutils; import org.slf4j.loggerFactory; import org.springframework.http.server.serverhttpRequest; import org.springframework.http.server.serverhtttttttponse; import org.springframework.web.context.request.servletRequestTributes; import org.springframework.web.socket.websockethandler; importar org.springframework.web.socket.server.support.httpsessionsessionshakeinterceptor; import java.util.date; importar; import java.util.map;/*** @Description: cree una interfaz de apretón de manos*@date: 16-3-3*/public class HandShakeinterceptors extiende httpsessionHandshakeinterceptor {private static final logger = loggerFactory.getLogger (handshakeInterceptor.class); @overidepublic boolean antes Solicitud, Respuesta de serverhttPonse, WebSockethandler wshandler, map <string, object> atributes) lanza la excepción {logger.info ("antes de crear handshake ..."); servletRequestattributes attrs = (servletRequestatTributes) requestContexTholderLe.getRequestattributes (); userInfo curruser = = Usermanager.getSessionUser (attrs.getRequest ()); UssocketVo UssocketVo = new UssOustsockEvo (); String Correo electrónico = ""; if (null! = Curruser) {Correo electrónico = Curruser.getEmail ();} if (stringUtils.isblank (correo electrónico)) {correo electrónico = datautil.date2string (neweN Date ());} Usersocketvo.setUserEmail (correo electrónico); attributes.put ("session_user", Ussersocketvo); return super.beforeHandShake (solicitud, respuesta, wshandler, atributos);}@overridePublic void AfterHandHake (serverHttpRequest Solicitud, serverhttTtTpResponse Respuesta, WebSocketHandler wshandler, excepción ex) {logger.info ("Después de crear handshake ..."); super.afterhandshake (solicitud, respuesta, wshandler, ex);};};};};};};};};}Como no entiendo muy bien, mantengo el código original en la medida máxima. En realidad, esto es para sacar al usuario de inicio de sesión actual desde el inicio de sesión único, convertirlo en un objeto Usersocketvo y ponerlo en el mapa. Así que echemos un vistazo a la definición del objeto UserSocketvo
4. Definición de UserSocketvo
paquete cn.bridgeli.websocket; import org.springframework.web.socket.websocketsession; import java.util.date;/*** @Description: usuark Socket Entidad de conexión*@Date: 16-3-3-7*/Class pública UsersocketVo {String String String Useremail; // Correo electrónico del usuario Fecha privada de conexión a la fecha; // Tiempo de conexión exitoso Fecha privada Prerrequesttime; // Última hora Tiempo de solicitud Fecha privada NewRequestTime; // Tiempo de solicitud nuevo Fecha privada dasttime = new Date (); // La última hora de envío del mensaje de eliminación de la fecha privada lasttasksendtime = new Date (); // El último tiempo de envío de la tarea pendiente WebSocketSession WebSocketSession; // El wssession correspondiente al usuario solo almacena uno de forma predeterminada // getxx y setxx}La más importante es la propiedad WebSocketSession, que usaremos más tarde
5. Implementación de WebSocketEndpoint
paquete cn.bridgeli.websocket; import org.slf4j.logger; import org.slf4j.loggerFactory; import org.springframework.beans.factory.annotation.aUtoWired; import org.springframework.web.socket.closestatus; import orge.springfraywork.web.web.weB.wexsocket; org.springframework.web.socket.websocketSession; import org.springframework.web.socket.handler.textwebsockethandler;/*** @description: websocket processock class*@date: 16-3-3*/public classocketendPoint extiende textwebsockethandler {logger final de logger final de logger final = privado = LoggerFactory.getLogger (WebSocketEndpoint.class);@AutowiredPrivate NewsListenerImpl NewsListener; @OverrideProtected void HandletExtMessage (Session de WebSocketSession, TextMessage Mensaje) Lanza excepción {super.handlextMessage (sesión, mensaje); TextMessage returnmessage = New TextMessage (Mensaje. servidor "); session.sendMessage (returnMessage);}/*** @Description: después de establecer la conexión* @param session* @throws excepción*/ @overridePublic void afroConnectionSableBedlished (websocketsession session) lanza la excepción {UssersoneSockvo Ussocketvo = (Ussersocketvo) session.getTributes (). if (null! = Ussersocketvo) {Ussersocketvo.setWebSocketSession (sesión); if (wssessionLocalcache.exists (usersocketvo.getUserEmail ())) {wssessionLocalcache.remove (Ussersocketvo.getUserEmail ());} wssessionLocalcache.put (usersocketvo.getUserEmail (),,,,,,,, Usersocketvo); NewsListener.AfterConnectionSableBised (UssersocketVo.getUserEmail ());} logger.info ("Socket Conexión establecida con éxito ..."); Super.afterConnectionSableBlised (session);}@overRidePublic Void AfterConnectionCleed (Session WebSocketSession Session, Status) lanza la excepción {OutsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsockEnsocket = = (UsersocketVo) session.getAttributes (). Get ("session_user"); if (null! = Ussersocketvo) {wssessionLocalcache.remove (usersocketvo.getUserEmail ());} logger.info ("Socket cerró con éxito la conexión ..."); superconnectionClised (session, status);}}}6. Implementación de WSSessionLocalCache
paquete cn.bridgeli.websocket; import java.io.Serializable; import java.util.arrayList; import java.util.hashmap; import java.util.list; import java.util.map;/*** @Description: Instancia de WebSocketSesion local*@Date: 16-3-7*/public Classessessionlocal Serializable {private static map <String, Usersocketvo> wssessionCache = new Hashmap <> (); public static static boolean existe (string usereMail) {if (! Wssessioncache.containskey (userEmail)) {return false;} else {return true;}} public static noid (String UserEmail, UserEnsopeSockVoChockVoChockvoSoChoneSoCketVo Usersocketvo) {wssessionCache.put (UserEmail, Ussersocketvo);} public static UsersocketVo get (String UserEmil) {return wssessionCache.get (userEmail);} public static void remo ArrayList <> (wssessionCache.values ());}}Después de mirar su implementación, el efecto es más obvio. Almacena los últimos datos de cada UserSocketvo. De hecho, nuestra implementación de WebSocket se ha calculado aquí, pero todavía hay una clase central (la clase de Charlie sobre Business Logic) que no se ha implementado. En el siguiente artículo, Ejemplo de aplicación WebSocket de Spring Integrated (Parte 2), veremos cómo implementar esta clase.
Introducción al protocolo de WebSocket
El protocolo WebSocket es una función importante en el campo web definido por la especificación RFC-6455: Dúplex completo, es decir, comunicación bidireccional entre el cliente y el servidor. Es una característica emocionante. La industria ha estado explorando este campo durante mucho tiempo. Las tecnologías utilizadas incluyen Java Applet, XMLHTTPRequest, Adobe Flash, ActiveXObject, varias tecnologías de cometa, eventos de envío del lado del servidor, etc.
Debe entenderse que antes de usar el protocolo WebSocket, debe usar el protocolo HTTP para construir el apretón de manos inicial. Esto se basa en un mecanismo: establecer HTTP y solicitar actualizaciones de protocolo (o conversiones de protocolo). Cuando el servidor está de acuerdo, responderá al código de estado HTTP 101, lo que indica que acepta cambiar el protocolo. Suponiendo que se pasa un apretón de manos exitoso a través de los enchufes TCP y la solicitud de actualización del protocolo HTTP, entonces tanto el cliente como el servidor pueden enviarse mensajes entre sí.
Spring Framework 4.0 y arriba introdujo un nuevo módulo, a saber, el módulo Spring-Websocket. Proporciona soporte para la comunicación de WebSocket. Es compatible con la especificación API de Java WebSocket JSR-356, al tiempo que proporciona funcionalidad adicional.
¿En qué escenario debe usar WebSocket?
En las aplicaciones web, cuando el cliente y el servidor necesitan intercambiar eventos con mayor frecuencia y menor latencia, es adecuado para WebSocket. Por lo tanto, WebSocket es adecuado para escenarios de aplicación como finanzas, juegos y colaboración.
Puede que no sea adecuado para otros escenarios de aplicación. Por ejemplo, una suscripción de noticias requiere que se muestren noticias de última hora, y también está bien usar una larga encuesta de varios minutos de diferencia, y el retraso aquí es aceptable.
Incluso en aplicaciones donde se requiere baja latencia, si el número de mensajes transmitidos es muy bajo (como las que monitorean las fallas de la red), se debe considerar una larga tecnología de encuesta.
Solo en escenarios con baja latencia y comunicación de mensajes de alta frecuencia, elegir el protocolo WebSocket es muy adecuado. Incluso en este escenario de aplicación, ¿aún es posible elegir la comunicación de WebSocket? O elija REST HTTP Communication?
La respuesta es que dependerá de las necesidades de la aplicación. Sin embargo, también es posible utilizar estas dos tecnologías al mismo tiempo para poner datos que deben intercambiarse con frecuencia en WebSocket y utilizar la API REST como una tecnología de implementación comercial basada en procesos. Además, cuando se debe transmitir una cierta información a varios clientes en la llamada API REST, también se puede implementar a través de WebSocket Connection.
Spring Framework proporciona anotación @Controller y anotación @RestController, que se pueden utilizar para el procesamiento de solicitudes HTTP y el procesamiento de mensajes de WebSocket. Además, los métodos de procesamiento de solicitudes de Spring MVC, u otros métodos de procesamiento de solicitudes de aplicación, pueden usar fácilmente el protocolo WebSocket para transmitir mensajes a todos los clientes interesados o usuarios designados.