在spring中配置一个websocket服务
1.一种基于tcp的长连接,为了兼容http协议保留了握手
pom
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>4.2.2.RELEASE</version> </dependency>
nginx
location /basic/ { proxy_set_header Upgrade $http_upgrade; #这是webSocket的配置 proxy_set_header Connection "Upgrade"; #这是webSocket的配置 proxy_http_version 1.1; #这两个最好也设置 proxy_read_timeout 6000s; #超时 proxy_pass http://127.0.0.1:8098/; }
@EnableWebMvc @EnableWebSocket public class MyConfigurerAdapter extends WebMvcConfigurerAdapter implements WebSocketConfigurer { @Inject private MySocketHandler mySocketHandler; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { //前台:可以使用websocket环境 registry.addHandler(mySocketHandler, "/my/console").setAllowedOrigins("*").addInterceptors(new HandshakeInterceptor()); //前台:不可以使用websocket环境,则使用sockjs进行模拟连接 registry.addHandler(mySocketHandler, "/sockjs/my/console").setAllowedOrigins("*").addInterceptors(new HandshakeInterceptor()).withSockJS(); } }
@Service public class MySocketHandler implements WebSocketHandler { private Map<String, WebSocketSession> mySession = new Hashtable<>(); @Inject private MyService myService; //自己个人实现的类 private static Logger logger = Logger.getLogger(MySocketHandler.class); //webscoket建立连接之后的处理行数 @Override public void afterConnectionEstablished( WebSocketSession session) throws Exception { logger.info("----------webscoket已连接"); } //客户端发送服务器的消息时的处理函数,在这里收到消息之后可以发送消息给前端 @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { logger.info("----------服务器已接收到消息"); //前端发送的消息只能是字符串格式(可以理解成前端的传参),后台需要解析字符串 String params = (String) message.getPayload(); ObjectMapper mapper = new ObjectMapper(); HashMap<String, Object> map = mapper.readValue(params, HashMap.class); String name = (String) map.get("name"); String id = (String) map.get("id"); Map<String, Object> result = myServer.selectReportData(name,id); TextMessage reply = new TextMessage(JSONObject.toJSONString(result)); //结果转成JSONObject字符串,放在TextMessage对象中 try{ session.sendMessage(reply); //把数据发送给前端 }catch(IOException e){ logger.debug("----------发送信息给前端出错"); } } //处理传输错误 @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { logger.info("----------出现传输错误"); } //websocket关闭连接 @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { logger.info("----------关闭Websocket连接"); } //支持部分消息,默认return false @Override public boolean supportsPartialMessages() { logger.info("----------支持部分信息"); return false; } }
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor { // 握手前 @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { //在访问接口时候需要带apiKey,如:XXXX链接?apiKey=xxx String apiKey = ((ServletServerHttpRequest) request).getServletRequest().getParameter("apiKey"); attributes.put("apiKey", apiKey); return super.beforeHandshake(request, response, wsHandler, attributes); } // 握手后 @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { super.afterHandshake(request, response, wsHandler, ex); } }