您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)如何在springboot中整合netty,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
1. 新建一個(gè)springboot項(xiàng)目,在pom文件中添加netty依賴:
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>5.0.0.Alpha1</version> </dependency>
2.新建netty服務(wù)
其實(shí)可以復(fù)制上一篇文章的netty的三個(gè)服務(wù)類,做一些稍微的修改就行了;這里為了方便演示,且修都是改好了的,就直接貼出來(lái)了;
DiscardServer類:
@Component public class DiscardServer { @Resource private ChildChannelHandler childChannelHandler; public void run(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); System.out.println("準(zhǔn)備運(yùn)行端口:" + port); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 128) .childHandler(childChannelHandler); //綁定端口,同步等待成功 ChannelFuture f = bootstrap.bind(port).sync(); //等待服務(wù)監(jiān)聽(tīng)端口關(guān)閉 f.channel().closeFuture().sync(); } finally { //退出,釋放線程資源 workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }
ChildChannelHandler類
@Component public class ChildChannelHandler extends ChannelInitializer<SocketChannel> { @Resource private DiscardServerHandler discardServerHandler; public void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(discardServerHandler); } }
3.DiscardServerHandler類
特別注意DiscardServerHandler類上需要加@Sharable注解,如果不加的話會(huì)報(bào)錯(cuò);
@Component @Sharable public class DiscardServerHandler extends ChannelHandlerAdapter { @Resource private BaseService baseService; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { try { ByteBuf in = (ByteBuf) msg; System.out.println("傳輸內(nèi)容是"); System.out.println(in.toString(CharsetUtil.UTF_8)); //這里調(diào)用service服務(wù) baseService.test(); } finally { ReferenceCountUtil.release(msg); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // 出現(xiàn)異常就關(guān)閉 cause.printStackTrace(); ctx.close(); } }
3.netty調(diào)用所需的服務(wù)類
1.BaseService接口
public interface BaseService { /** * 測(cè)試接口 */ void test(); }
2.接口實(shí)現(xiàn)類BaseServiceImpl:
@Service public class BaseServiceImpl implements BaseService { @Override public void test() { System.out.println("調(diào)用service服務(wù)"); } }
4 springboot啟動(dòng)類
由于main方法是靜態(tài)方法,netty服務(wù)啟動(dòng)類不是靜態(tài)類,在main方法里面需要用new的方式啟動(dòng);
也可以將netty服務(wù)啟動(dòng)類改為靜態(tài)類,然后調(diào)用其他非靜態(tài)的類時(shí)就得用new方法來(lái)構(gòu)造其他類了;
我也百度到了幾篇文章說(shuō)實(shí)現(xiàn)CommandLineRunner接口,所以我用了springboot啟動(dòng)類實(shí)現(xiàn)CommandLineRunner接口的run方法,然后在run方法里啟動(dòng)netty服務(wù)
@SpringBootApplication public class DemoApplication implements CommandLineRunner { @Resource private DiscardServer discardServer; public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Override public void run(String... args) throws Exception { discardServer.run(8080); } }
5.測(cè)試
寫一個(gè)能發(fā)送數(shù)據(jù)的socket就可以了;
發(fā)送的數(shù)據(jù)為:
public static void main(String[] args){ try { Socket socket=new Socket("localhost",8080); OutputStream outputStream = socket.getOutputStream(); PrintWriter printWriter=new PrintWriter(outputStream); printWriter.write("$tmb00035ET3318/08/22 11:5804029.94,027.25,20.00,20.00$"); printWriter.flush(); socket.shutdownOutput(); socket.close(); } catch (IOException e) { e.printStackTrace(); } }
我的測(cè)試結(jié)果:
傳輸內(nèi)容是 $tmb00035ET3318/08/22 11:5804029.94,027.25,20.00,20.00$ aaaaa
到這里,netty與springboot的整合就完成了;
我在整合過(guò)程中遇到的問(wèn)題
我使用springboot結(jié)合netty的流程
springboot啟動(dòng)類中啟動(dòng)netty啟動(dòng)類(DiscardServer),netty啟動(dòng)類(DiscardServer)再調(diào)用初始化channel類(ChildChannelHandler),然后初始化channel類再調(diào)用(DiscardServerHandler)類;然后DiscardServerHandler類再調(diào)用service服務(wù);如下示例圖:
問(wèn)題:
springboot啟動(dòng)類我并沒(méi)有實(shí)現(xiàn)CommandLineRunner接口,直接在main方法通過(guò)new的方式啟動(dòng)netty服務(wù)
我實(shí)現(xiàn)了CommandLineRunner接口,但是我在run方法中用的new的方式啟動(dòng)的netty服務(wù)或者我在run方法使用注入的方式啟動(dòng)netty,但是在其他某個(gè)地方調(diào)用另一個(gè)類使用了new的方式;
DiscardServerHandler類上為標(biāo)記@Sharable類,會(huì)報(bào)錯(cuò)誤;
以上總結(jié)起來(lái)的問(wèn)題就是我在springboot整合netty的過(guò)程中有其中一處的調(diào)用其他類時(shí)使用的方式是new構(gòu)造的,這樣雖然springboot能啟動(dòng),netty也能啟動(dòng),但是netty服務(wù)中使用new構(gòu)造的那個(gè)類中無(wú)法依賴注入,會(huì)報(bào)空指針異常;
舉個(gè)栗子:在圖中的過(guò)程中,我在ChildChannelHandler類中通過(guò)new的方式調(diào)用DiscardServerHandler類,其他的過(guò)程都是使用注入的方式調(diào)用,就會(huì)出現(xiàn)上邊的問(wèn)題;
在遇到空指針的時(shí)候,我把spring托管的bean打印了出來(lái),所有的類都在spring的托管中,但是就是無(wú)法注入,我也一直沒(méi)有明白怎么回事,最后用了一個(gè)極端的方法,就是在調(diào)用服務(wù)時(shí),獲取spring的上下文,然后再根據(jù)名字來(lái)獲取bean,你谷歌或百度:非托管類調(diào)用spring托管類,就能找到很多文章了;雖然用這個(gè)方式能解決上述的問(wèn)題,但總是不好的;
最后的解決辦法:所以類之間的調(diào)用都使用spring的依賴注入,別用new的方式來(lái)調(diào)用或者靜態(tài)方法的方式調(diào)用
上述就是小編為大家分享的如何在springboot中整合netty了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。