下面就進入到真正的開發階段。
架構選用的是Spring+netty,為什麼選擇Spring來集成netty,而不是直接用netty打出來一個jar包,直接通過java –jar netty.jar命令來直接執行呢?固然通過java –jar的形式執行Java方法無須讓jvm額外的去加載其他無用的jar包,能夠讓jvm最大程度的為我們自己的netty方法服務。但是,通過java –jar的方式執行的jar包,他只是一個用戶進程可能會因為用戶登出而導致該進程失效。即使在命令中加上nohup讓其與用戶Session無關,但因為進程優先級低,也會導致心跳包失效,甚至在內存不足時優先回收該進程的內存。而如果將netty集成到Spring中,Spring本來是一個輕量級的框架,對性能的影響較小,而且Spring會被加載到Tomcat中,Tomcat本來就是一個優秀的虛擬服務器,log輸出,線程分配都非常合理,重要的是,Tomcat可以作為服務來運行,即使用戶登錄登出也絲毫不會影響Tomcat的運行。
另外,從我們需要的功能角度來講,比如我們需要讓樹莓派新增一個鬧鐘,Spring可以執行定時任務,我們僅僅需要做一下相應的配置便可讓Spring定時去執行一些任務。此外,還可以讓Spring去調用本地的一些服務,這樣一個Spring作為中轉,既可以提供對外的網頁鏈接,又可以調用本地應用,一舉兩得。
用Spring集成netty,首先還是要了解如何生成Spring項目。我的電腦採用的是Windows系統,開發使用的是eclipse,依賴管理採用的是maven(關於maven的搭建使用隨後講解),那麼,首先新建一個我們的spring應用。
Eclipse中點擊New–>Maven project–>next
點擊next,填入工程名和package名,然後Finish。
此時,如果新建的工程報錯,如下圖所示。
此時需要在pom裡新增關於servlet和spring相關的依賴。Pom新增如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
</dependency>
等待maven更新完畢後,我們便可以進行package和Class的開發了。
首先以一個demo的形式,讓Server和Client能夠運行起來相互通信。那麼,我們新建一個IOServer類,類的代碼如下:
@Component
public class IOServer {
private static final int portNumber = 13013;
@PostConstruct
public void start(){
new Thread(new Runnable() {
@Override
public void run() {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup);
b.channel(NioServerSocketChannel.class);
b.childHandler(new IOServerInitializer());
ChannelFuture f = b.bind(portNumber).sync();
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}).start();
}
}
其中,Component表示Spring的包掃描機制,要求Spring對某些類進行掃描,當掃描到Component關鍵字時,自動創建這個類的實例,然後掃描是否有PostConstruct,這個關鍵字的意思是自動執行,即掃描到這個類之後,創建實例,並自動執行PostConstuct修飾的方法。
對於詳細的代碼我會以包的形式上傳到我的服務器上,這裡我想講一下關於Spring的一些簡單應用。
Spring工程,其實本質上還是一個Tomcat(Javaweb)工程,只不過在Javaweb的基礎上新增了一些Spring的插件。程序啟動的時候,首先去尋找web.xml,web.xml的作用可以認為是一個引導,現在我們在這裡先了解一下web.xml的文件內容。
<servlet>
<servlet-name>InitEntry</servlet-name>
<servlet-class>lst.csu.common.Entry</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>InitEntry</servlet-name>
<url-pattern>/init</url-pattern>
</servlet-mapping>
在文件中有這麼幾行配置,它的意思是,我首先定義一個servlet-name是InitEntry的Servlet工程,對應的URL是http://xxxx.com/init,而對於上面的三個配置表示,InitEntry這個servlet工程,對應的類是lst.csu.common.Entry,load-on-startup表示自動啟動,10是一個優先級數字,越小優先級越高。
那麼我們根據web.xml這個配置去尋找lst.csu.common.Entry,發現這個類的作用是這樣的:
@Override
public void init() throws ServletException {
ContextUtil.getApplicationContext();
}
其實最終是為了讓Servlet讀取applicationContext.xml文件,這個文件是幹嘛呢?僅僅是一個配置文件,告知Spring需要掃描哪些文件,需要預加載哪些類等等。
我在applicationContext.xml配置的是:
<context:component-scan base-package=”lst.csu.sockcenter” />
也就是要求Spring去掃描lst.csu.sockcenter這個包。那麼問題就到了前面那個關於Commponent的解釋了,Spring就會自動去掃描註解,從而自動執行某些程序。
代碼太多了,我將demo工程以壓縮包的形式上傳到服務器,供大家下載。現在demo還沒有增加具體的邏輯,所以很簡單,僅僅用來展示如何進行新建Spring工程。所以稍安勿躁,硬件已經購回,下面樹莓派智能家居項目會不斷做下去。另外我代碼寫的不太好,也是自己在探索這些東西,所以大家見諒啦。
demo下載地址:http://lst.wting.me/wp-content/uploads/2017/09/SockServer.zip