HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。

    1. package com.programb.jwt;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. import org.springframework.scheduling.annotation.EnableScheduling;
    5. @EnableScheduling
    6. @SpringBootApplication
    7. public class Application {
    8. public static void main(String[] args) {
    9. SpringApplication.run(Application.class, args);
    10. }
    11. }
    1. package com.programb.jwt.commons;
    2. import com.fasterxml.jackson.core.JsonProcessingException;
    3. import com.fasterxml.jackson.core.type.TypeReference;
    4. import com.fasterxml.jackson.databind.ObjectMapper;
    5. import java.io.IOException;
    6. public class JacksonUtil {
    7. private static ObjectMapper mapper = new ObjectMapper();
    8. public static String bean2Json(Object obj) {
    9. try {
    10. return mapper.writeValueAsString(obj);
    11. } catch (JsonProcessingException e) {
    12. e.printStackTrace();
    13. return "";
    14. }
    15. }
    16. public static <T> T json2Bean(String jsonStr, TypeReference<T> typeReference) {
    17. try {
    18. return mapper.readValue(jsonStr, typeReference);
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. return null;
    22. }
    23. }
    24. }
    1. package com.programb.jwt.config;
    2. import org.springframework.context.annotation.Configuration;
    3. import org.springframework.web.socket.config.annotation.EnableWebSocket;
    4. import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
    5. import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
    6. import com.programb.jwt.handler.SocketHandler;
    7. import com.programb.jwt.interceptor.WebSocketInterceptor;
    8. @Configuration
    9. @EnableWebSocket
    10. public class WebSocketConfig implements WebSocketConfigurer {
    11. public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    12. registry.addHandler(new SocketHandler(), "/app")
    13. .addInterceptors(new WebSocketInterceptor())
    14. .setAllowedOrigins("*");
    15. }
    16. }
    1. package com.programb.jwt.config;
    2. import org.springframework.context.annotation.Configuration;
    3. import org.springframework.messaging.simp.config.MessageBrokerRegistry;
    4. import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
    5. import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
    6. import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
    7. @Configuration
    8. @EnableWebSocketMessageBroker
    9. public class WebSocketStompConfig extends AbstractWebSocketMessageBrokerConfigurer {
    10. @Override
    11. public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
    12. stompEndpointRegistry.addEndpoint("/simple")
    13. .setAllowedOrigins("*") //解决跨域问题
    14. .withSockJS();
    15. }
    16. @Override
    17. public void configureMessageBroker(MessageBrokerRegistry registry) {
    18. registry.enableSimpleBroker("/topic");
    19. }
    20. }
    1. package com.programb.jwt.controller;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.messaging.handler.annotation.MessageMapping;
    4. import org.springframework.messaging.handler.annotation.SendTo;
    5. import org.springframework.messaging.simp.SimpMessagingTemplate;
    6. import org.springframework.scheduling.annotation.Scheduled;
    7. import org.springframework.stereotype.Controller;
    8. import com.programb.jwt.model.RequestMessage;
    9. import com.programb.jwt.model.ResponseMessage;
    10. import java.text.DateFormat;
    11. import java.text.SimpleDateFormat;
    12. import java.util.Date;
    13. @Controller
    14. public class WsController {
    15. private final SimpMessagingTemplate messagingTemplate;
    16. @Autowired
    17. public WsController(SimpMessagingTemplate messagingTemplate) {
    18. this.messagingTemplate = messagingTemplate;
    19. }
    20. @MessageMapping("/welcome")
    21. @SendTo("/topic/say")
    22. public ResponseMessage say(RequestMessage message) {
    23. System.out.println(message.getName());
    24. return new ResponseMessage("welcome," + message.getName() + " !");
    25. }
    26. @Scheduled(fixedRate = 1000)
    27. public void callback() {
    28. // 发现消息
    29. DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    30. messagingTemplate.convertAndSend("/topic/callback", "定时推送消息时间: " + df.format(new Date()));
    31. }
    32. }
    1. package com.programb.jwt.handler;
    2. import com.fasterxml.jackson.core.type.TypeReference;
    3. import com.programb.jwt.commons.JacksonUtil;
    4. import com.programb.jwt.model.WsParam;
    5. import com.programb.jwt.model.WsResponse;
    6. import org.slf4j.Logger;
    7. import org.slf4j.LoggerFactory;
    8. import org.springframework.stereotype.Component;
    9. import org.springframework.web.socket.CloseStatus;
    10. import org.springframework.web.socket.TextMessage;
    11. import org.springframework.web.socket.WebSocketSession;
    12. import org.springframework.web.socket.handler.TextWebSocketHandler;
    13. import java.io.IOException;
    14. import java.util.List;
    15. import java.util.Map;
    16. import java.util.concurrent.CopyOnWriteArrayList;
    17. @Component
    18. public class SocketHandler extends TextWebSocketHandler {
    19. private Logger logger = LoggerFactory.getLogger(this.getClass());
    20. List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
    21. @Override
    22. public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
    23. logger.info("handleTextMessage start");
    24. String msg = message.getPayload();
    25. logger.info("msg = " + msg);
    26. WsParam<String> wsParam = JacksonUtil.json2Bean(msg, new TypeReference<WsParam<String>>(){});
    27. if ("list".equals(wsParam.getMethod())) {
    28. logger.info("call list method...");
    29. WsResponse<String> response = new WsResponse<>();
    30. response.setResult("hello list");
    31. sendMessageToUser(session, new TextMessage(JacksonUtil.bean2Json(response)));
    32. }
    33. logger.info("handleTextMessage end");
    34. }
    35. @Override
    36. public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    37. logger.info("Connected ... " + session.getId());
    38. sessions.add(session);
    39. }
    40. @Override
    41. public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    42. if (session.isOpen()) {
    43. session.close();
    44. }
    45. sessions.remove(session);
    46. logger.info(String.format("Session %s closed because of %s", session.getId(), status.getReason()));
    47. }
    48. @Override
    49. public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {
    50. logger.error("error occured at sender " + session, throwable);
    51. }
    52. public void sendMessagesToUsers(TextMessage message) {
    53. for (WebSocketSession user : sessions) {
    54. try {
    55. if (user.isOpen()) {
    56. user.sendMessage(message);
    57. }
    58. } catch (IOException e) {
    59. e.printStackTrace();
    60. }
    61. }
    62. }
    63. private void sendMessageToUser(WebSocketSession user, TextMessage message) {
    64. try {
    65. if (user.isOpen()) {
    66. user.sendMessage(message);
    67. }
    68. } catch (IOException e) {
    69. logger.error("发送消息给指定的用户出错", e);
    70. }
    71. }
    72. }
    1. package com.programb.jwt.interceptor;
    2. import javax.servlet.http.HttpServletRequest;
    3. import org.slf4j.Logger;
    4. import org.slf4j.LoggerFactory;
    5. import org.springframework.http.server.ServerHttpRequest;
    6. import org.springframework.http.server.ServerHttpResponse;
    7. import org.springframework.http.server.ServletServerHttpRequest;
    8. import org.springframework.web.socket.WebSocketHandler;
    9. import org.springframework.web.socket.server.HandshakeInterceptor;
    10. import java.util.Map;
    11. public class WebSocketInterceptor implements HandshakeInterceptor {
    12. private Logger logger = LoggerFactory.getLogger(this.getClass());
    13. @Override
    14. public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse arg1,
    15. WebSocketHandler arg2, Map<String, Object> arg3) throws Exception {
    16. if (request instanceof ServletServerHttpRequest) {
    17. ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
    18. HttpServletRequest httpRequest = servletRequest.getServletRequest();
    19. }
    20. logger.info("programb");
    21. return true;
    22. }
    23. @Override
    24. public void afterHandshake(ServerHttpRequest arg0, ServerHttpResponse arg1, WebSocketHandler arg2, Exception arg3) {
    25. logger.info("programb");
    26. }
    27. }
    1. package com.programb.jwt.model;
    2. public class RequestMessage {
    3. private String name;
    4. public String getName() {
    5. return name;
    6. }
    7. }
    1. package com.programb.jwt.model;
    2. public class ResponseMessage {
    3. private String responseMessage;
    4. public ResponseMessage(String responseMessage) {
    5. this.responseMessage = responseMessage;
    6. }
    7. public String getResponseMessage() {
    8. return responseMessage;
    9. }
    10. }
    1. package com.programb.jwt.model;
    2. public class WsParam<T> {
    3. private String method;
    4. private T param;
    5. public String getMethod() {
    6. return method;
    7. }
    8. public void setMethod(String method) {
    9. this.method = method;
    10. }
    11. public T getParam() {
    12. return param;
    13. }
    14. public void setParam(T param) {
    15. this.param = param;
    16. }
    17. }
    1. package com.programb.jwt.model;
    2. public class WsResponse<T> {
    3. private T result;
    4. public T getResult() {
    5. return result;
    6. }
    7. public void setResult(T result) {
    8. this.result = result;
    9. }
    10. }
    1. spring:
    2. profiles:
    3. active: dev
    4. server:
    5. port: 8092
    6. spring:
    7. profiles: dev
    8. logging:
    9. level:
    10. ROOT: INFO
    11. com:
    12. xncoding: DEBUG
    13. file: D:/programb/logs/app.log
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0</modelVersion>
    6. <groupId>com.programb</groupId>
    7. <artifactId>springboot-websocket</artifactId>
    8. <version>1.0.0-SNAPSHOT</version>
    9. <packaging>jar</packaging>
    10. <name>springboot-websocket</name>
    11. <description>WebScoket</description>
    12. <parent>
    13. <groupId>org.springframework.boot</groupId>
    14. <artifactId>spring-boot-starter-parent</artifactId>
    15. <version>2.0.4.RELEASE</version>
    16. </parent>
    17. <properties>
    18. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    19. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    20. <java.version>1.8</java.version>
    21. <netty.version>4.1.19.Final</netty.version>
    22. </properties>
    23. <dependencies>
    24. <dependency>
    25. <groupId>org.springframework.boot</groupId>
    26. <artifactId>spring-boot-starter-websocket</artifactId>
    27. <exclusions>
    28. <exclusion>
    29. <groupId>org.springframework.boot</groupId>
    30. <artifactId>spring-boot-starter-tomcat</artifactId>
    31. </exclusion>
    32. </exclusions>
    33. </dependency>
    34. <dependency>
    35. <groupId>org.springframework.boot</groupId>
    36. <artifactId>spring-boot-starter-jetty</artifactId>
    37. </dependency>
    38. </dependencies>
    39. <build>
    40. <plugins>
    41. <plugin>
    42. <groupId>org.apache.maven.plugins</groupId>
    43. <artifactId>maven-compiler-plugin</artifactId>
    44. <version>3.6.1</version>
    45. <configuration>
    46. <source>1.8</source>
    47. <target>1.8</target>
    48. </configuration>
    49. </plugin>
    50. <plugin>
    51. <groupId>org.apache.maven.plugins</groupId>
    52. <artifactId>maven-surefire-plugin</artifactId>
    53. <version>2.20</version>
    54. <configuration>
    55. <systemPropertyVariables>
    56. <swaggerOutputDir>${project.basedir}/src/main/resources/swagger</swaggerOutputDir>
    57. <asciiDocOutputDir>${project.basedir}/src/main/resources/swagger/swagger</asciiDocOutputDir>
    58. </systemPropertyVariables>
    59. <skip>true</skip>
    60. </configuration>
    61. </plugin>
    62. <plugin>
    63. <groupId>org.springframework.boot</groupId>
    64. <artifactId>spring-boot-maven-plugin</artifactId>
    65. <executions>
    66. </executions>
    67. </plugin>
    68. </plugins>
    69. <resources>
    70. <resource>
    71. <directory>src/main/resources</directory>
    72. </resource>
    73. <resource>
    74. <directory>src/main/java</directory>
    75. <includes>
    76. <include>**/*.xml</include>
    77. </includes>
    78. </resource>
    79. </resources>
    80. </build>
    81. </project>