日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Springboot之整合Socket連接案例

瀏覽:47日期:2023-03-26 17:10:20

Socket連接與硬件通信

一、如何讓socket隨著springboot項目一起啟動

SpringBoot中CommandLineRunner的作用:平常開發中有可能需要實現在項目啟動后執行的功能,SpringBoot提供的一種簡單的實現方案就是添加一個model并實現CommandLineRunner接口,實現功能的代碼放在實現的run方法中

具體實現

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.stereotype.Component;import java.net.ServerSocket;import java.net.Socket;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;/** * @author 易水●墨龍吟 * @Description * @create 2019-04-14 23:40 */@Componentpublic class TestRunner implements CommandLineRunner { @Autowired private SocketProperties properties; @Override public void run(String... args) throws Exception { ServerSocket server = null; Socket socket = null; server = new ServerSocket(properties.getPort()); System.out.println('設備服務器已經開啟, 監聽端口:' + properties.getPort()); ThreadPoolExecutor pool = new ThreadPoolExecutor(properties.getPoolCore(),properties.getPoolMax(),properties.getPoolKeep(),TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(properties.getPoolQueueInit()),new ThreadPoolExecutor.DiscardOldestPolicy() ); while (true) { socket = server.accept(); pool.execute(new ServerConfig(socket)); } }}

此處使用了自定義的線程池,提高對于socket的客戶端處理能力。

二、自定義配置并使用

此處將socket的端口和線程池的一些配置放到 application.yml中使用,方便使用和修改

# Socket配置socket: # 監聽端口 2323 port: 2323 # 線程池 - 保持線程數 20 pool-keep: 20 # 線程池 - 核心線程數 10 pool-core: 10 # 線程池 - 最大線程數 20 pool-max: 30 # 線程隊列容量 10 pool-queue-init: 10

import lombok.Getter;import lombok.Setter;import lombok.ToString;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import org.springframework.stereotype.Component;/** * @author 易水●墨龍吟 * @Description * @create 2019-04-18 22:35 */@Setter@Getter@ToString@Component@Configuration@PropertySource('classpath:application.yml')@ConfigurationProperties(prefix = 'socket')public class SocketProperties { private Integer port; private Integer poolKeep; private Integer poolCore; private Integer poolMax; private Integer poolQueueInit;}三、Socket對于客戶端發來的信息的處理和重發機制

當客戶端端連接之后發送信息,如果超時未發送,將會關閉,發送數據有異常將會返回給客戶端一個error,讓客戶端在發送一次數據。

import com.farm.config.socket.resolve.MessageChain;import com.farm.service.EnvironmentService;import com.farm.service.impl.EnvironmentServiceImpl;import java.io.*;import java.net.Socket;import java.net.SocketException;import java.net.SocketTimeoutException;import java.util.Map;/** * @author 易水●墨龍吟 * @Description * @create 2019-04-14 23:21 */public class ServerConfig extends Thread { private Socket socket; public ServerConfig(Socket socket) { this.socket = socket; }// 獲取spring容器管理的類,可以獲取到sevrice的類 private EnvironmentService service = SpringUtil.getBean(EnvironmentServiceImpl.class); private String handle(InputStream inputStream) throws IOException, DataFormException { byte[] bytes = new byte[1024]; int len = inputStream.read(bytes); if (len != -1) { StringBuffer request = new StringBuffer(); request.append(new String(bytes, 0, len, 'UTF-8')); System.out.println('接受的數據: ' + request); System.out.println('from client ... ' + request + '當前線程' + Thread.currentThread().getName()); Map<String, String> map = MessageChain.out(request.toString()); System.out.println('處理的數據' + map); Integer res = service.addEnvironment(map); if (res == 1) {return 'ok'; } else {throw new DataFormException('數據處理異常'); } } else { throw new DataFormException('數據處理異常'); } } @Override public void run() { BufferedWriter writer = null; try { // 設置連接超時9秒 socket.setSoTimeout(9000); System.out.println('客戶 - ' + socket.getRemoteSocketAddress() + ' -> 機連接成功'); InputStream inputStream = socket.getInputStream(); writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); String result = null; try {result = handle(inputStream);writer.write(result);writer.newLine();writer.flush(); } catch (IOException | DataFormException | IllegalArgumentException e) {writer.write('error');writer.newLine();writer.flush();System.out.println('發生異常');try { System.out.println('再次接受!'); result = handle(inputStream); writer.write(result); writer.newLine(); writer.flush();} catch (DataFormException | SocketTimeoutException ex) { System.out.println('再次接受, 發生異常,連接關閉');} } } catch (SocketException socketException) { socketException.printStackTrace(); try {writer.close(); } catch (IOException ioException) {ioException.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } finally { try {writer.close(); } catch (IOException e) {e.printStackTrace(); } } }}

在此處有一個坑,如果客戶端是用C/C++編寫的,必須使用如下方法:

byte[] bytes = new byte[1024];int len = inputStream.read(bytes);

如果使用readLine或者 DataInputStream dataInputStream =new DataInputStream(socket.getInputStream())這樣會出現使用TCP連接助手,客戶端發送數據收不到。

四、如何在普通類中使用Spring注入類

這里需要使用一個工具類。

import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;/** * @author 易水●墨龍吟 * @Description * @create 2019-04-15 0:01 */@Componentpublic class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringUtil.applicationContext == null) { SpringUtil.applicationContext = applicationContext; } } /** * 獲取applicationContext * @return */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** * 通過name獲取 Bean. * @param name * @return */ public static Object getBean(String name){ return getApplicationContext().getBean(name); } /** * 通過class獲取Bean. * @param clazz * @param <T> * @return */ public static <T> T getBean(Class<T> clazz){ return getApplicationContext().getBean(clazz); } /** * 通過name,以及Clazz返回指定的Bean * @param name * @param clazz * @param <T> * @return */ public static <T> T getBean(String name,Class<T> clazz){ return getApplicationContext().getBean(name, clazz); }}

補充:springboot下websocket前臺后端數據長連接

首先導入依賴

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-messaging</artifactId> </dependency>

spring-security-messaging 是后面繼承 AbstractSecurityWebSocketMessageBrokerConfigurer需要用到的依賴

WebSocketConfig

@Configuration@EnableWebSocketMessageBroker //此注解表示使用STOMP協議來傳輸基于消息代理的消息,此時可以在@Controller類中使用@MessageMapping public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { /** * 注冊 Stomp的端點 * addEndpoint:添加STOMP協議的端點。這個HTTP URL是供WebSocket或SockJS客戶端訪問的地址 * withSockJS:指定端點使用SockJS協議 */ registry.addEndpoint('/websocket/tracker') //物流消息通道, .setAllowedOrigins('*') //允許跨域,里面路徑可以設定 .withSockJS() //指定協議 .setInterceptors(httpSessionHandshakeInterceptor()) ; //設置攔截器() } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { /** * 配置消息代理 * 啟動簡單Broker,消息的發送的地址符合配置的前綴來的消息才發送到這個broker */ registry.enableSimpleBroker('/topic','/user'); } //攔截器 @Bean public HandshakeInterceptor httpSessionHandshakeInterceptor() { return new HandshakeInterceptor() { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {//可以在這里先判斷登錄是否合法return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { //握手成功后, } }; }}

WebsocketSecurityConfiguration

@Configurationpublic class WebsocketSecurityConfiguration extends AbstractSecurityWebSocketMessageBrokerConfigurer { @Override protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) { messages .nullDestMatcher().authenticated() .simpDestMatchers('/topic/**').authenticated() .simpDestMatchers('/user/**').authenticated() .simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).denyAll() // catch all .anyMessage().denyAll(); } /** * Disables CSRF for Websockets. */ @Override protected boolean sameOriginDisabled() { return true; }}

WebSocketResource

package com.gleam.shopmall.web.rest;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationListener;import org.springframework.messaging.handler.annotation.MessageMapping;import org.springframework.messaging.handler.annotation.SendTo;import org.springframework.messaging.simp.SimpMessageHeaderAccessor;import org.springframework.messaging.simp.SimpMessageMappingInfo;import org.springframework.messaging.simp.SimpMessageSendingOperations;import org.springframework.stereotype.Controller;import org.springframework.web.socket.messaging.SessionDisconnectEvent;@Controllerpublic class WebSocketResource { private static final Logger log = LoggerFactory.getLogger(WebSocketResource.class); @Autowired SimpMessageSendingOperations messagingTemplate; //此方法適用于網頁聊天室,從前端接收數據,返回訂閱者(前端) @MessageMapping('/welcome') //指定要接收消息的地址,類似@RequestMapping @SendTo('/topic/getResponse') //默認消息將被發送到與傳入消息相同的目的地,但是目的地前面附加前綴(默認情況下為“/topic”} public String say(String message) throws Exception { return message; } //發送指定用戶(直接從后端發送數據到前端) public void sendToUser(String login,String channel, String info) { log.debug('[ToUser]WEBSOCKET發送消息, username={}, info={}', login, info); this.messagingTemplate.convertAndSendToUser(login, channel, info); log.debug('[ToUser]WEBSOCKET發送消息:完成'); } //發送所有訂閱的(直接從后端發送數據到前端) public void send(String channel, String info) { log.debug('[ToAll]WEBSOCKET發送消息, info={}', info); // this.messagingTemplate.convertAndSend(channel, info); this.messagingTemplate.convertAndSend('/topic/getResponse', '接收到了嗎?'); log.debug('[ToAll]WEBSOCKET發送消息:完成'); }}

前端html

<!DOCTYPE html><html xmlns:th='http://www.thymeleaf.org'><head> <meta charset='UTF-8' /> <script src='http://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js'></script> <script src='https://cdn.bootcss.com/stomp.js/2.3.3/stomp.js'></script> <script src='http://code.jquery.com/jquery-1.7.2.min.js'></script> <script src='http://pv.sohu.com/cityjson?ie=utf-8'></script> <title>Spring Boot+WebSocket+廣播式</title> <script type='text/javascript'> var stompClient = null; function setConnected(connected) { document.getElementById(’connect’).disabled = connected; document.getElementById(’disconnect’).disabled = !connected; document.getElementById(’conversationDiv’).style.visibility = connected ? ’visible’ : ’hidden’; $(’#response’).html(); } function connect() { // websocket的連接地址,此值等于WebSocketConfig中registry.addEndpoint('/websocket/tracker').withSockJS()配置的地址, //這里如果是微服務或者遠端,需要全路徑 var socket = new SockJS(’/websocket/tracker’); //1 stompClient = Stomp.over(socket);//2 stompClient.connect({}, function(frame) {//3setConnected(true);console.log(’開始進行連接Connected: ’ + frame);// 客戶端訂閱消息的目的地址:此值等于WebSocketResource中@SendTo('/topic/getResponse')注解的里配置的值stompClient.subscribe(’/topic/getResponse’, function(respnose){ //4 showResponse(respnose.body);}); }); } function disconnect() { if (stompClient != null) {stompClient.disconnect(); } setConnected(false); console.log('Disconnected'); } function sendName() { var name = $(’#name’).val(); stompClient.send('/welcome', {}, returnCitySN[’cip’] +':'+name);// JSON.stringify(name) } function showResponse(message) { var response = $('#response'); response.html(message+'<br>' + response.html()); } </script></head><body onload='disconnect()'><noscript><h2 style='color: red'>貌似你的瀏覽器不支持websocket</h2></noscript><div> <div> <button onclick='connect();' style='color: red'>連接</button> <button disabled='disabled' onclick='disconnect();'>斷開連接</button> </div> <div id='conversationDiv'> <label>輸入內容</label><input type='text' /> <button onclick='sendName();'>發送</button> <p id='response'></p> </div></div></body></html>```

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。如有錯誤或未考慮完全的地方,望不吝賜教。

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久一区二区三区电影| 四虎国产精品免费观看| 蜜桃精品在线| 色88888久久久久久影院| 日韩精品dvd| 欧美日韩中文一区二区| 欧美日韩国产亚洲一区| 欧美日韩少妇| 午夜在线播放视频欧美| 日韩一区二区三区四区五区| 婷婷激情图片久久| 国产亚洲精品v| 亚洲香蕉视频| 国产精品高清一区二区| 欧美精品1区| 精品一区在线| 国产日韩欧美高清免费| 国产精品99一区二区三区| 福利在线免费视频| 激情五月综合| 玖玖精品视频| 国产精品色婷婷在线观看| 久久精品国产999大香线蕉| 手机在线电影一区| 在线一区欧美| 日本va欧美va瓶| 久久亚洲精精品中文字幕| 成人av三级| 鲁大师成人一区二区三区| 在线精品亚洲| 精品国产不卡一区二区| 亚洲国产专区校园欧美| 蜜桃视频第一区免费观看| 国产精品伦一区二区| 国产成人精品亚洲日本在线观看| 好吊日精品视频| 日韩精品欧美精品| 91视频久久| 日韩美女国产精品| 成人羞羞视频播放网站| 蜜桃91丨九色丨蝌蚪91桃色| 麻豆精品新av中文字幕| 亚洲免费在线| av高清不卡| 国产日韩欧美一区二区三区| 在线日韩欧美| 九九久久国产| 91亚洲无吗| 人人精品人人爱| 免费污视频在线一区| 欧美日韩中文| 亚洲欧美日韩精品一区二区 | 九色精品91| 97精品中文字幕| 国产精东传媒成人av电影| 蜜桃伊人久久| 免费日韩av片| 亚洲免费播放| 五月天久久网站| 欧洲一级精品| 国内在线观看一区二区三区| 69精品国产久热在线观看| 一区二区国产在线观看| 亚洲精品1区| 黄页网站一区| 美女久久一区| 中文精品在线| 男女精品网站| 综合激情在线| 日韩精品一区二区三区中文| 亚洲精品三级| 国产精品99久久免费观看| 欧美日韩国产一区二区在线观看| 日本不卡一二三区黄网| 日韩国产欧美在线视频| 国产精品一区亚洲| 精品国产中文字幕第一页 | 99国产精品| 免费日韩精品中文字幕视频在线| 99国产精品99久久久久久粉嫩| 欧美/亚洲一区| 色偷偷偷在线视频播放| 蜜桃av.网站在线观看| 伊人久久大香线蕉av超碰演员| 国产精品av一区二区| 中文字幕亚洲影视| 麻豆精品视频在线观看| 天堂av在线| 欧美精品一线| 国产精选久久| 国产精品亚洲一区二区三区在线观看| 久久久五月天| 亚洲精品无吗| 国产成人精选| 美女被久久久| 欧美日一区二区三区在线观看国产免 | 777久久精品| 中文在线免费视频| 亚洲尤物av| 国产精品久久久久久久免费观看| 欧美日一区二区| 91成人在线网站| 99久久激情| 久久国产免费看| 亚洲免费高清| 国语精品一区| 视频一区二区三区入口| 视频一区二区中文字幕| 久久99影视| 国产91一区| 国产剧情一区二区在线观看| 日韩一区亚洲二区| 欧美日韩亚洲一区二区三区在线| 极品av在线| 美腿丝袜亚洲三区| 亚州欧美在线| 日韩一级不卡| 久久国产小视频| 伊人网在线播放| 麻豆国产精品一区二区三区| 在线观看亚洲精品福利片| 蜜桃tv一区二区三区| 国产伦精品一区二区三区在线播放 | 国产精品黑丝在线播放| 亚洲资源在线| 欧美亚洲激情| 精品国产乱码久久久| 午夜久久av | 久久人人精品| 国产欧美一区二区色老头| 欧美日韩在线二区| 欧美国产中文高清| 涩涩涩久久久成人精品| www成人在线视频| 欧美aⅴ一区二区三区视频| 一区二区小说| 伊人久久国产| 久久精品国产一区二区| 91精品国产自产观看在线| 国产高清一区| 久久91视频| 国产精品成人一区二区网站软件| 视频精品一区二区| 中文精品在线| 尤物网精品视频| 国产精品99免费看| se01亚洲视频 | 欧美国产日本| 欧美亚洲一区二区三区| 激情婷婷综合| 影音先锋久久| 亚洲欧美日韩精品一区二区| 久久亚洲国产| 欧美国产91| 亚洲人www| 国产欧美日韩| 国产精品一区二区精品视频观看| 欧美中文高清| 免费精品一区| 激情久久五月| 中文字幕亚洲精品乱码| 在线国产日韩| 欧美激情99| 午夜久久中文| 蜜臀精品一区二区三区在线观看| 中文字幕成人| 亚洲精品少妇| 欧美永久精品| 黄色aa久久| 三级亚洲高清视频| 国产精品99精品一区二区三区∴ | 欧美a级一区| 91免费精品国偷自产在线在线| 国产欧美另类| 免费不卡中文字幕在线| 日本成人在线网站| 精品一区二区三区中文字幕视频 | 蜜桃精品在线| 红桃视频欧美| 日韩高清成人在线| 日韩高清中文字幕一区二区| 免费在线观看成人| 国产精品亚洲综合久久| 久久久夜精品| 国产精品**亚洲精品| 国产农村妇女精品一二区| 久久伊人久久| 欧美综合二区| 精品三级国产| 日韩中文字幕91| 成人在线视频中文字幕| 日本伊人久久| 亚洲精品2区| 精品国产精品国产偷麻豆| 日本不卡一区二区三区| 欧美日韩国产高清| 日韩中文影院| 日本久久综合| 麻豆精品新av中文字幕| 日韩区一区二|