There are three main steps in this paper.
1. Build a websocket connection after the user logs in, and choose the websocket connection by default. If the browser does not support it, use sockjs to simulate the connection.
2. After establishing the connection, the server returns the unread message of the user.
3. After relevant operation, the server pushes Spring 4.0.6 (to choose 4.0+), Tomcat 7.0.55 to a user or all users'new message-related environment.
Web ocet server implementation
WebSocketConfig.java
@Configuration @EnableWebMvc @EnableWebSocket public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor()); registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor()) .withSockJS(); } @Bean public WebSocketHandler systemWebSocketHandler(){ return new SystemWebSocketHandler(); } }
Don't forget to configure automatic scanning of this type in the configuration file of spring MVC
<context:component-scan base-package="com.ldl.origami.websocket" />
@Configuration
@EnableWebMvc
@EnableWebSocket
These three basically mean that this class supports loading beans in the way of @bean, and spring MVC and websocket. It's not very accurate. Just try @Enable WebMvc without adding it. Configuration already supports automatic scanning of spring mvc.
registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor())
To register the websocket server implementation class, the second parameter is to access the address of the websocket
registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor()) .withSockJS(); }
This is the registration method using Sockjs
First, SystemWebSocketHandler.java
public class SystemWebSocketHandler implements WebSocketHandler { private static final Logger logger; private static final ArrayList<WebSocketSession> users; static { users = new ArrayList<>(); logger = LoggerFactory.getLogger(SystemWebSocketHandler.class); } @Autowired private WebSocketService webSocketService; @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.debug("connect to the websocket success......"); users.add(session); String userName = (String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME); if(userName!= null){ //Query unread messages int count = webSocketService.getUnReadNews((String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME)); session.sendMessage(new TextMessage(count + "")); } } @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { //sendMessageToUsers(); } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { if(session.isOpen()){ session.close(); } logger.debug("websocket connection closed......"); users.remove(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { logger.debug("websocket connection closed......"); users.remove(session); } @Override public boolean supportsPartialMessages() { return false; } /** * Send messages to all online users * * @param message */ public void sendMessageToUsers(TextMessage message) { for (WebSocketSession user : users) { try { if (user.isOpen()) { user.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } } } /** * Send a message to a user * * @param userName * @param message */ public void sendMessageToUser(String userName, TextMessage message) { for (WebSocketSession user : users) { if (user.getAttributes().get(Constants.WEBSOCKET_USERNAME).equals(userName)) { try { if (user.isOpen()) { user.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } break; } } } }
As soon as you look at the relevant content, you will understand it, but you will not explain it much.
Then WebSocketHandshakeInterceptor.java
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor { private static Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class); @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object > attributes) throws Exception { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; HttpSession session = servletRequest.getServletRequest().getSession(false); if (session != null) { //Use userName to differentiate WebSocketHandler for directional messaging String userName = (String) session.getAttribute(Constants.SESSION_USERNAME); attributes.put(Constants.WEBSOCKET_USERNAME,userName); } } return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { } }
The main function of this is to get the user name in the current request and save it in the current WebSocket Handler to determine the corresponding user of WebSocket Handler, referring specifically to HttpSession Handshake Interceptor.
User login to establish websocket connection
index.jsp
<script type="text/javascript" src="http://localhost:8080/Origami/websocket/sockjs-0.3.min.js"></script> <script> var websocket; if ('WebSocket' in window) { websocket = new WebSocket("ws://localhost:8080/Origami/webSocketServer"); } else if ('MozWebSocket' in window) { websocket = new MozWebSocket("ws://localhost:8080/Origami/webSocketServer"); } else { websocket = new SockJS("http://localhost:8080/Origami/sockjs/webSocketServer"); } websocket.onopen = function (evnt) { }; websocket.onmessage = function (evnt) { $("#msgcount").html("(<font color='red'>"+evnt.data+"</font>)") }; websocket.onerror = function (evnt) { }; websocket.onclose = function (evnt) { } </script>
Note when using sockjs
1. Writing of the two
<script type="text/javascript" src="http://localhost:8080/Origami/websocket/sockjs-0.3.min.js"></script> websocket = new SockJS(<a href="http://localhost:8080/Origami/sockjs/webSocketServer">http://localhost:8080/Origami/sockjs/webSocketServer</a>);
2. In web.xml
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd">
version
web-app_3_1.xsd
Both versions are 3.0+
Then add it to the servlet
<async-supported>true</async-supported> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet>
Then all filter s are added.
<async-supported>true</async-supported>
3. Adding Relevant Dependencies
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.3.3</version> </dependency>
Okay, now websocket can be set up properly
Returns unread messages for users
When the connection is established, it enters the system WebSocketHandler's after Connection Established method. The code looks up and takes out the user name saved in the WebSocketHandshake Interceptor.
Use session.sendMessage(new TextMessage(count + "") after querying information; return to the user, from where to where
Server pushes messages to users
@Controller public class AdminController { static Logger logger = LoggerFactory.getLogger(AdminController.class); @Autowired(required = false) private AdminService adminService; @Bean public SystemWebSocketHandler systemWebSocketHandler() { return new SystemWebSocketHandler(); } @RequestMapping("/auditing") @ResponseBody public String auditing(HttpServletRequest request){ //Irrelevant code is omitted int unReadNewsCount = adminService.getUnReadNews(username); systemWebSocketHandler().sendMessageToUser(username, new TextMessage(unReadNewsCount + "")); return result; } }
Here you can use sendMessageToUser to push information to a user or sendMessageToUsers to push information to all users.