springboot基本使用筆記----新增socket服務及獲取spring bean
(一)新增socket服務
因為專案基於 springboot 框架,要提供 socket 服務,網上查資料好多說是要新增 websocket 元件,感覺挺麻煩就沒去看,直接使用原始的方式寫個 socket 服務類,然後在 springboot 啟動類的 main 方法中,新增 socket 服務啟動方法。
1.socket服務類程式碼如下(網上有好多例子,隨便拿了個模板略作修改):
2.在 springboot 啟動類 main 方法中新增 socket 服務端啟動程式碼import java.io.*; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Set; /** * nio socket服務端 */ public class SocketServer { //解碼buffer private Charset cs = Charset.forName("UTF-8"); //接受資料緩衝區 private static ByteBuffer sBuffer = ByteBuffer.allocate(1024); //傳送資料緩衝區 private static ByteBuffer rBuffer = ByteBuffer.allocate(1024); //選擇器(叫監聽器更準確些吧應該) private static Selector selector; /** * 啟動socket服務,開啟監聽 * @param port * @throws IOException */ public void startSocketServer(int port){ try { //開啟通訊通道 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //設定為非阻塞 serverSocketChannel.configureBlocking(false); //獲取套接字 ServerSocket serverSocket = serverSocketChannel.socket(); //繫結埠號 serverSocket.bind(new InetSocketAddress(port)); //開啟監聽器 selector = Selector.open(); //將通訊通道註冊到監聽器 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //監聽器會一直監聽,如果客戶端有請求就會進入相應的事件處理 while (true){ selector.select();//select方法會一直阻塞直到有相關事件發生或超時 Set<SelectionKey> selectionKeys = selector.selectedKeys();//監聽到的事件 for (SelectionKey key : selectionKeys) { handle(key); } selectionKeys.clear();//清除處理過的事件 } }catch (Exception e){ e.printStackTrace(); } } /** * 處理不同的事件 * @param selectionKey * @throws IOException */ private void handle(SelectionKey selectionKey) throws IOException { ServerSocketChannel serverSocketChannel = null; SocketChannel socketChannel = null; String requestMsg = ""; int count = 0; if (selectionKey.isAcceptable()) { //每有客戶端連線,即註冊通訊通道為可讀 serverSocketChannel = (ServerSocketChannel)selectionKey.channel(); socketChannel = serverSocketChannel.accept(); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); } else if (selectionKey.isReadable()) { socketChannel = (SocketChannel)selectionKey.channel(); rBuffer.clear(); count = socketChannel.read(rBuffer); //讀取資料 if (count > 0) { rBuffer.flip(); requestMsg = String.valueOf(cs.decode(rBuffer).array()); } String responseMsg = "已收到客戶端的訊息:"+requestMsg; //返回資料 sBuffer = ByteBuffer.allocate(responseMsg.getBytes("UTF-8").length); sBuffer.put(responseMsg.getBytes("UTF-8")); sBuffer.flip(); socketChannel.write(sBuffer); socketChannel.close(); } } }
(二 )獲取 spring beanimport org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.xxx.mapper") public class PlatformApplication { public static void main(String[] args) { SpringApplication.run(PlatformApplication.class, args); //起socket服務 SocketServer server = new SocketServer(); server.startSocketServer(8088); } }
因為沒使用 websocket 元件,在 SocketServer 類中使用註解方式注入到 spring 容器中的 Service 會存在問題,舉個例子:
資料持久層使用了 mybatis 框架,如果實現資料持久化,需要如下檔案
1.實體類 entity.java
2.sql 對映檔案 mapper.xml
3.mapper 介面類 mapper.java
4.service 介面類 service.java
5.service 實現類 serviceimpl,java
現在需要做個查詢,通常情況下是呼叫注入的 service 的 find 方法,過程應該是先獲取 注入的 service(即 serviceimpl 的例項),再獲取注入到 service 的 mapper ,
最後通過 mapper.xml 配置檔案獲取相應的 sql 到資料庫查詢。
SocketServer 作為普通類是無法將 servcie 注入進來的,那通過 new 一個例項的方法可以嗎?不可以! new 出來的 serviceimpl 的例項中 mapper 是 null 。所以我們只能從 spring 容器中獲取 serviceimpl bean ,得到的 bean 中 mapper 就不是 null 了。
首先,建立從 spring 容器中獲取 bean 的工具類:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Created by
*/
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
//獲取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通過name獲取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通過class獲取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通過name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
然後在使用的時候呼叫下:
Service service = SpringUtil.getBean(ServiceImpl.class);
這樣,就能在普通類中獲取註解方式注入到 spring 容器中的 bean 了。