There are three main steps in this article
1. After the user logs in, establish a websocket connection. The default selection is selected. If the browser does not support it, use sockjs to simulate the connection.
2. After establishing a connection, the server returns the unread message of the user.
3. After the server performs related operations, push new messages to a certain user or all users. Spring 4.0.6 (select 4.0+), tomcat7.0.55
Websocet server implementation
WebSocketConfig.java
@Configuration@EnableWebMvc@EnableWebSocketpublic class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor());registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor()).withSockJS();}@Beanpublic WebSocketHandler systemWebSocketHandler(){return new SystemWebSocketHandler();}}Don't forget to configure automatic scanning of this class in springmvc's configuration file
<context:component-scan base-package="com.ldl.origami.websocket" />
@Configuration
@EnableWebMvc
@EnableWebSocket
These three roughly mean that this class supports loading beans in the @Bean mode, and supports springmvc and websocket. It is not very accurate. I tried @EnableWebMvc without adding it, and @Configuration originally supports automatic scanning of springmvc
registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor())
Used to register the websocket server implementation class. The second parameter is to access the websocket address.
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);}@Autowiredprivate WebSocketService webSocketService;@Overridepublic 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 + ""));}}@Overridepublic void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {//sendMessageToUsers();}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {if(session.isOpen()){session.close();}logger.debug("websocket connection closed......");users.remove(session);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {logger.debug("websocket connection closed...");users.remove(session);}@Overridepublic boolean supportsPartialMessages() {return false;}/*** Send message 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;}}}}}}You can understand the relevant content at a glance, so I won't explain it much
Then WebSocketHandshakeInterceptor.java
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {private static Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);@Overridepublic 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 distinguish WebSocketHandler in order to send messages in a directional manner String userName = (String) session.getAttribute(Constants.SESSION_USERNAME); attributes.put(Constants.WEBSOCKET_USERNAME,userName);}}return true;}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {}}The main function of this is to obtain the user name in the current request and save it to the current WebSocketHandler to determine the corresponding user to the WebSocketHandler. For details, please refer to HttpSessionHandshakeInterceptor
User login to establish a 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>Be careful when using sockjs
1. How to write these two
<script type="text/javascript" src="http://localhost:8080/Origami/websocket/sockjs-0.3.min.js"></script>websocket = new SockJS(http://localhost:8080/Origami/sockjs/webSocketServer);
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 must be 3.0+
Then add it in this 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 filters are added
<async-supported>true</async-supported>
3. Add related 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><artifa ctId>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>
OK, now the websocket can be established normally
Returns the unread message of the user
After the connection is established, the afterConnectionEstablished method of SystemWebSocketHandler will be entered. Look at the code above and take out the username saved in WebSocketHandshakeInterceptor
After querying information, use session.sendMessage(new TextMessage(count + "")); to return it to the user, and go back and go.
Push messages to users on the server
@Controllerpublic class AdminController {static Logger logger = LoggerFactory.getLogger(AdminController.class);@Autowired(required = false)private AdminService adminService;@Beanpublic SystemWebSocketHandler systemWebSocketHandler() {return new SystemWebSocketHandler();}@RequestMapping("/auditing")@ResponseBodypublic String auditing(HttpServletRequest request){//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 you can use sendMessageToUsers to push information to all users.