O tutorial a seguir é um sistema de CRM da empresa que participei do desenvolvimento de uma empresa e resolvi algumas informações relevantes. Existem muitas funções de push de mensagem no sistema, e a tecnologia WebSocket é usada nela. O seguinte editor compilou e compartilhou na plataforma de rede Wulin para sua referência
1. Dependência do Maven
<Depencency> <Puerpid> javax.servlet </frupiid> <TRATIFACTID> javax.servlet-api </artifactId> <versão> 3.1.0 </siers> </dependency> <pendency> <puperid> com.fasterxml.jackson.core </grupId> <TrAtifactId> jackson-core <fasterxml.jackson.core </grupo> <tutifactid>. 0 </versão> </dependency> <pendency> <puperid> com.fasterxml.jackson.core </groupid> <stifactId> jackson-core </stutifactId> <versão 2.3.0 </versão> </dependency> <pendency> <purbrouid> com.fasterxml.jackson.core </Grupoid> -databind </artifactId> <versão> 2.3.0 </version> </dependency> <pendence> <puperid> org.springframework </groupiD> <TRARFACTID> spring-websocket </stifactId> <versão> 4.0.1. Release </versão> </dependency> <pendency> <puperid> org.springframework </foupid> <TRarifactId> Spring-Messaging </storkactid> <versão> 4.0.1.release </sipers> </pendencency>
2. Configuração do servidor de mola
<? xml versão = "1.0" coding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: context = "http://www.springframework.org/schema/cont ext xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:websocket="http://www.springframework.org/schema/websocket"xsi:schemaLocation="http://www .springframework.org/schema/beanshttp: //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.springframeworksorg/schema/webskay-spring-wwww.springframeworksorg/schema/webskay-spring-wwwwww.springframeworksorg/schema/webskay-spring-wwwwww.springframeworksorg/schema/webskay-spring-wwwwww.springframeworksorg/schema/webskay-spring-wwwwwwwwww.springframeworksorg/schema/webskay-spring-wwww.springframeworksorg/schema/webskay-spring-ww. id = "websocket"/> <websocket: manipuladores> <websocket: mapeando path = "/websocket" handler = "websocket"/> <websocket: mann-shake-interceptors> <bean/> <websocket: handshake-interceptores> </websocket: manipuladores> </4 Beans>
Entre eles, o caminho correspondente ao caminho é o caminho da interface que foi ajustado através do protocolo WS na seção anterior.
3. Implementação do handshakeInterceptor
pacote cn.bridgeli.webSocket; importar cn.bridgeli.utils.userManager; importar cn.bridgeli.util.dateutil; importar cn.bridgeli.sharesession.userinfo; importação orgache.commons.lang.strundils; importação; org.slf4j.loggerfactory; importar org.springframework.http.server.serverhttprequest; importar org.springframework.http.server.serverhtpSponse; importrinCringFramework.web.Contet.ReverhtpSponse; importrinCringFramework.web.Contet.requestnsonse; org.springframework.web.context.request.servletRequestattributes; importar org.springframework.web.socket.websockethandler; importil.springFramework.web.socket.server.sapport.httsHorInterceptwork java.util.map;/*** @Description: Crie uma interface de handshake*@Date: 16-3-3*/classe pública HandshakeInterceptor estende httpsessionhandshakeInterceptor {private static logger logger = LoggerFactory.GetLogger (HandsHakeSector.Cllass); Solicitação, servidorhttpResponse Resposta, WebSockethandler Wshandler, mapa <string, objeto> atributos) lança exceção {logger.info ("antes de criar handshake ..."); servletRequestattributes atts = (servletRequestattributes) requestconthusher.GereQuestatRabutes; UserManager.getSessionUser (atts.getRequest ()); usersocketvo usersocketvo = new Usersocketvo (); string email = ""; if (null! = Curruser) {email = CurrUser.getEmAil ();} if (stringUtils.isblan)) {email = dateUtil.Date2 atributes.put ("session_user", UserSocketvo); retornar super.BeforeHandshake (solicitação, resposta, wshandler, atributos);}@substituir o Substitutic Void AfterHandshake (Solicitação de servidorhttPrequest, servidorhttpResponse, resposta, resposta a WebSocketHandler Wshandler, excepção ex) {Logger.info ("Criando Handshake ...");Como não entendo muito bem, mantenho o código original na extensão máxima. Na verdade, isso é para retirar o usuário de login atual do único login, convertê-lo em um objeto Usersocketvo e colocá-lo no mapa. Então, vamos dar uma olhada na definição do objeto Usersocketvo
4. Definição de UsuáriosSocketvo
pacote cn.bridgeli.webSocket; importar org.springframework.web.socket.websocketsession; importar java.util.date;/*** @Description: entidade de conexão de soquete do usuário*@date: 16-3-7*/public classuserockvo {private string userEmail; // Email de usuário Data privada Data de conexão; // Tempo de conexão bem -sucedido Data privada Pré -repercussão; // Last Solicy Time Time Private Data NewRequestTime; // novo tempo de solicitação Data privada date lastsendTime = new Date (); // o último horário de envio da mensagem de remoção Data privada lastTaskSendTime = new Date (); // O último horário de envio da tarefa pendente privado websocketSession WebSocketSession; // O WSSession correspondente ao usuário apenas armazena em cache um por padrão // getxx e setxx}O mais importante é a propriedade WebSocketSession, que usaremos mais tarde
5. Implementação do WebSockENDPoint
pacote cn.bridgeli.webSocket; importar org.slf4j.logger; importar org.slf4j.loggerFactory; importar org.springframework.beans.factory.annotation.autowired; imported org.springframework.web.eMet.Socket.Closestus; Importmport; ImportMerg.sportMsket.MportMests Org. org.springframework.web.socket.websocketSession; importar org.springframework.web.socket.handler.textwebsockethandler;/*** @Description: Websocket Class e classe de processamento*@Date: 16-3-3*/public WebsocketEnTpoint extensor LestwebEthethethLe. LoggerFactory.getLogger (websocketEngPoint.class);@AutowiredPrivate NewsListeNeRImpl NewsListener; @OverrideProtected void handleTextMessage (WebSocketSession, textMessage) lança exceção {Super.HandleTextMessage (mensagem, mensagem); textMessage revolt) servidor "); session.sendMessage (returnMessage);}/*** @Description: Depois de estabelecer a conexão* @param session* @throws Exceção*/ @ @substituir public void depoisConnectionEstabled (WebSocketsSession) lança exceção {UsersocketVo (UsersUSTUSTUSTUSTUSTUSTUSTUSTO); if (null! = usersocketvo) {usersocketvo.setWebsocketSession (sessão); if (wssionlocalcache.exists (usersocketvo.getUserEmail ())) {wssionlocalcache.remove (usersocketvo.getUsereMail ();} wssessionlocalcache.put (usersocketvo.getUseReMail (), Usersocketvo); NewsListener.AfterConnectionEstabled (Usersocketvo.getUsereMail ());} Logger.info ("Socket com sucesso conexão estabelecida ..."); Super.AfterConnectionEstabled (Sesstatsats);}@Substerpublic void AfterConnection (webocketSession, shuststatsatats; (Usersocketvo) session.getAttributes (). Get ("session_user"); if (null! = Usersocketvo) {wssionlocalcache.remove (uservaSocketvo.getUSeReMail (););} logger.info ("Sockets, encerrado com sucesso ...6. Implementação do WSSessionLocalcache
pacote cn.bridgeli.webSocket; importar java.io.Serializable; importar java.util.ArrayList; importar java.util.hashmap; importar java.util.list; importe java.util.map;/*** @Description: cache local sereias Serializável {mapa estático privado <string, usersocketvo> wssessionCache = new hashmap <> (); existe booleano estático público (string userEmail) {if (! Wssessioncache.containsKey (userEmail) {return;} else {return true;}} {public) kut (string) {return;} else {return true;}} {public) kut " UserSocketvo) {wssessionCache.put (correio de usuário, usersocketvo);} public static usersocketvo get (string usermail) {return wssessioncache.get (userEmail);} public static void (string userEmail) {wssessionCache.roMove (userMail);} ArrayList <> (wssessionCache.values ());}}Depois de analisar sua implementação, o efeito é mais óbvio. Ele armazena os dados mais recentes de cada UsuáriosSocketvo. De fato, nossa implementação do WebSocket foi calculada aqui, mas ainda existe uma classe principal (classe de Charlie sobre lógica de negócios) que não foi implementada. No próximo artigo, o Spring Integrated Websocket Application Exemplo (Parte 2), veremos como implementar esta classe.
Introdução ao protocolo WebSocket
O protocolo WebSocket é uma função importante no campo da web definido pela especificação RFC-6455: Full Duplex, ou seja, comunicação bidirecional entre o cliente e o servidor. É um recurso emocionante. A indústria explora esse campo há muito tempo. As tecnologias utilizadas incluem java applet, xmlhttprequest, adobe flash, ActiveXObject, várias tecnologias de cometa, eventos de envio do servidor, etc.
Deve -se entender que, antes de usar o protocolo Websocket, você precisa usar o protocolo HTTP para criar o aperto de mão inicial. Isso se baseia em um mecanismo - estabelecendo HTTP e solicitando atualizações de protocolo (ou conversões de protocolo). Quando o servidor concordar, ele responderá ao código de status HTTP 101, indicando que concorda em alternar o protocolo. Supondo que um aperto de mão bem -sucedido através de soquetes TCP e a solicitação de atualização do protocolo HTTP seja aprovada, o cliente e o servidor podem enviar mensagens um para o outro.
Spring Framework 4.0 e acima introduziu um novo módulo, a saber, o módulo Spring-Websocket. Ele fornece suporte para a comunicação do WebSocket. É compatível com a especificação da API Java WebSocket JSR-356, fornecendo funcionalidade adicional.
Em que cenário você deve usar o websocket
Nos aplicativos da Web, quando o cliente e o servidor precisam trocar eventos com maior frequência e menor latência, é adequado para o WebSocket. Portanto, o WebSocket é adequado para cenários de aplicação, como finanças, jogos e colaboração.
Pode não ser adequado para outros cenários de aplicação. Por exemplo, uma assinatura de notícias exige que as notícias de última hora sejam exibidas, e também não há problema em usar uma longa pesquisa de vários minutos de intervalo, e o atraso aqui é aceitável.
Mesmo em aplicações em que a baixa latência é necessária, se o número de mensagens transmitidas for muito baixo (como as falhas da rede de monitoramento), a tecnologia de pesquisa longa deve ser considerada.
Somente em cenários com baixa latência e comunicação de mensagens de alta frequência, a escolha do protocolo WebSocket é muito adequada. Mesmo nesse cenário de aplicativo, ainda é possível escolher a comunicação do WebSocket? Ou escolha a comunicação HTTP REST?
A resposta é que ele dependerá das necessidades do aplicativo. No entanto, também é possível usar essas duas tecnologias ao mesmo tempo para colocar dados que precisam ser trocados com frequência no WebSocket e usar a API REST como uma tecnologia de implementação de negócios baseada em processos. Além disso, quando uma determinada informação precisa ser transmitida para vários clientes na chamada da API REST, elas também podem ser implementadas através da WebSocket Connection.
A estrutura de primavera fornece anotação @Controller e anotação @RestController, as quais podem ser usadas para o processamento de solicitações HTTP e o processamento de mensagens do WebSocket. Além disso, os métodos de processamento de solicitação de Spring MVC ou outros métodos de processamento de solicitações de aplicativos podem usar facilmente o protocolo Websocket para transmitir mensagens para todos os clientes ou usuários designados.