HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。
package com.programb.jwt;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.scheduling.annotation.EnableScheduling;@EnableScheduling@SpringBootApplicationpublic class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}
package com.programb.jwt.commons;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.core.type.TypeReference;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.IOException;public class JacksonUtil {private static ObjectMapper mapper = new ObjectMapper();public static String bean2Json(Object obj) {try {return mapper.writeValueAsString(obj);} catch (JsonProcessingException e) {e.printStackTrace();return "";}}public static <T> T json2Bean(String jsonStr, TypeReference<T> typeReference) {try {return mapper.readValue(jsonStr, typeReference);} catch (IOException e) {e.printStackTrace();return null;}}}
package com.programb.jwt.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import com.programb.jwt.handler.SocketHandler;import com.programb.jwt.interceptor.WebSocketInterceptor;@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer {public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(new SocketHandler(), "/app").addInterceptors(new WebSocketInterceptor()).setAllowedOrigins("*");}}
package com.programb.jwt.config;import org.springframework.context.annotation.Configuration;import org.springframework.messaging.simp.config.MessageBrokerRegistry;import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;import org.springframework.web.socket.config.annotation.StompEndpointRegistry;@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketStompConfig extends AbstractWebSocketMessageBrokerConfigurer {@Overridepublic void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {stompEndpointRegistry.addEndpoint("/simple").setAllowedOrigins("*") //解决跨域问题.withSockJS();}@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {registry.enableSimpleBroker("/topic");}}
package com.programb.jwt.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.messaging.handler.annotation.MessageMapping;import org.springframework.messaging.handler.annotation.SendTo;import org.springframework.messaging.simp.SimpMessagingTemplate;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Controller;import com.programb.jwt.model.RequestMessage;import com.programb.jwt.model.ResponseMessage;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;@Controllerpublic class WsController {private final SimpMessagingTemplate messagingTemplate;@Autowiredpublic WsController(SimpMessagingTemplate messagingTemplate) {this.messagingTemplate = messagingTemplate;}@MessageMapping("/welcome")@SendTo("/topic/say")public ResponseMessage say(RequestMessage message) {System.out.println(message.getName());return new ResponseMessage("welcome," + message.getName() + " !");}@Scheduled(fixedRate = 1000)public void callback() {// 发现消息DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");messagingTemplate.convertAndSend("/topic/callback", "定时推送消息时间: " + df.format(new Date()));}}
package com.programb.jwt.handler;import com.fasterxml.jackson.core.type.TypeReference;import com.programb.jwt.commons.JacksonUtil;import com.programb.jwt.model.WsParam;import com.programb.jwt.model.WsResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.TextWebSocketHandler;import java.io.IOException;import java.util.List;import java.util.Map;import java.util.concurrent.CopyOnWriteArrayList;@Componentpublic class SocketHandler extends TextWebSocketHandler {private Logger logger = LoggerFactory.getLogger(this.getClass());List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();@Overridepublic void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {logger.info("handleTextMessage start");String msg = message.getPayload();logger.info("msg = " + msg);WsParam<String> wsParam = JacksonUtil.json2Bean(msg, new TypeReference<WsParam<String>>(){});if ("list".equals(wsParam.getMethod())) {logger.info("call list method...");WsResponse<String> response = new WsResponse<>();response.setResult("hello list");sendMessageToUser(session, new TextMessage(JacksonUtil.bean2Json(response)));}logger.info("handleTextMessage end");}@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {logger.info("Connected ... " + session.getId());sessions.add(session);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {if (session.isOpen()) {session.close();}sessions.remove(session);logger.info(String.format("Session %s closed because of %s", session.getId(), status.getReason()));}@Overridepublic void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {logger.error("error occured at sender " + session, throwable);}public void sendMessagesToUsers(TextMessage message) {for (WebSocketSession user : sessions) {try {if (user.isOpen()) {user.sendMessage(message);}} catch (IOException e) {e.printStackTrace();}}}private void sendMessageToUser(WebSocketSession user, TextMessage message) {try {if (user.isOpen()) {user.sendMessage(message);}} catch (IOException e) {logger.error("发送消息给指定的用户出错", e);}}}
package com.programb.jwt.interceptor;import javax.servlet.http.HttpServletRequest;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.http.server.ServletServerHttpRequest;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.server.HandshakeInterceptor;import java.util.Map;public class WebSocketInterceptor implements HandshakeInterceptor {private Logger logger = LoggerFactory.getLogger(this.getClass());@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse arg1,WebSocketHandler arg2, Map<String, Object> arg3) throws Exception {if (request instanceof ServletServerHttpRequest) {ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;HttpServletRequest httpRequest = servletRequest.getServletRequest();}logger.info("programb");return true;}@Overridepublic void afterHandshake(ServerHttpRequest arg0, ServerHttpResponse arg1, WebSocketHandler arg2, Exception arg3) {logger.info("programb");}}
package com.programb.jwt.model;public class RequestMessage {private String name;public String getName() {return name;}}
package com.programb.jwt.model;public class ResponseMessage {private String responseMessage;public ResponseMessage(String responseMessage) {this.responseMessage = responseMessage;}public String getResponseMessage() {return responseMessage;}}
package com.programb.jwt.model;public class WsParam<T> {private String method;private T param;public String getMethod() {return method;}public void setMethod(String method) {this.method = method;}public T getParam() {return param;}public void setParam(T param) {this.param = param;}}
package com.programb.jwt.model;public class WsResponse<T> {private T result;public T getResult() {return result;}public void setResult(T result) {this.result = result;}}
spring:profiles:active: devserver:port: 8092spring:profiles: devlogging:level:ROOT: INFOcom:xncoding: DEBUGfile: D:/programb/logs/app.log
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.programb</groupId><artifactId>springboot-websocket</artifactId><version>1.0.0-SNAPSHOT</version><packaging>jar</packaging><name>springboot-websocket</name><description>WebScoket</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.4.RELEASE</version></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><netty.version>4.1.19.Final</netty.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.6.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.20</version><configuration><systemPropertyVariables><swaggerOutputDir>${project.basedir}/src/main/resources/swagger</swaggerOutputDir><asciiDocOutputDir>${project.basedir}/src/main/resources/swagger/swagger</asciiDocOutputDir></systemPropertyVariables><skip>true</skip></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions></executions></plugin></plugins><resources><resource><directory>src/main/resources</directory></resource><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource></resources></build></project>
