springboot整合netty(二)
本文内容纲要:
-前言
-正文
-代码
-1.新建一个springboot项目,在pom文件中添加netty依赖:
-2.新建netty服务
-3.netty调用所需的服务类
-4springboot启动类
-5.测试
-我在整合过程中遇到的问题
-总结
目录
-
前言
-
正文
-
代码
-
- 新建一个springboot项目,在pom文件中添加netty依赖:
- 2.新建netty服务
- 3.netty调用所需的服务类
- 4springboot启动类
- 5.测试
-
-
我在整合过程中遇到的问题
-
-
总结
前言
上一篇讲了netty的一个入门的demo;项目上我也把数据处理做好了,就要开始存数据库了;我用的mybatis框架,如果单独使用还是觉得比较麻烦,所以就用了springboot+mybatis+netty;本篇主要讲netty与springboot的整合,以及我在这个过程中遇到的问题,又是怎么去解决的;
正文
我在做springboot与netty整合的时候在谷歌,百度找了无数文章,都没有一篇是自己想要的,也达不到自己所想的目的;
代码
1.新建一个springboot项目,在pom文件中添加netty依赖:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha1</version>
</dependency>
2.新建netty服务
其实可以复制上一篇文章的netty的三个服务类,做一些稍微的修改就行了;这里为了方便演示,且修都是改好了的,就直接贴出来了;
-
DiscardServer类:
@Component publicclassDiscardServer{ @Resource privateChildChannelHandlerchildChannelHandler; publicvoidrun(intport)throwsException{ EventLoopGroupbossGroup=newNioEventLoopGroup(); EventLoopGroupworkerGroup=newNioEventLoopGroup(); System.out.println("准备运行端口:"+port); try{ ServerBootstrapbootstrap=newServerBootstrap(); bootstrap.group(bossGroup,workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG,128) .childHandler(childChannelHandler); //绑定端口,同步等待成功 ChannelFuturef=bootstrap.bind(port).sync(); //等待服务监听端口关闭 f.channel().closeFuture().sync(); }finally{ //退出,释放线程资源 workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }
-
ChildChannelHandler类
@Component publicclassChildChannelHandlerextendsChannelInitializer
{ @Resource privateDiscardServerHandlerdiscardServerHandler; publicvoidinitChannel(SocketChannelsocketChannel)throwsException{ socketChannel.pipeline().addLast(discardServerHandler); }
}
3.DiscardServerHandler类
特别注意DiscardServerHandler类上需要加@Sharable注解,如果不加的话会报错;
@Component
@Sharable
publicclassDiscardServerHandlerextendsChannelHandlerAdapter{
@Resource
privateBaseServicebaseService;
@Override
publicvoidchannelRead(ChannelHandlerContextctx,Objectmsg){
try{
ByteBufin=(ByteBuf)msg;
System.out.println("传输内容是");
System.out.println(in.toString(CharsetUtil.UTF_8));
//这里调用service服务
baseService.test();
}finally{
ReferenceCountUtil.release(msg);
}
}
@Override
publicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause)throwsException{
//出现异常就关闭
cause.printStackTrace();
ctx.close();
}
}
3.netty调用所需的服务类
1.BaseService接口
publicinterfaceBaseService{
/**
*测试接口
*/
voidtest();
}
2.接口实现类BaseServiceImpl:
@Service
publicclassBaseServiceImplimplementsBaseService{
@Override
publicvoidtest(){
System.out.println("调用service服务");
}
}
4springboot启动类
- 由于main方法是静态方法,netty服务启动类不是静态类,在main方法里面需要用new的方式启动;
- 也可以将netty服务启动类改为静态类,然后调用其他非静态的类时就得用new方法来构造其他类了;
我也百度到了几篇文章说实现CommandLineRunner接口,所以我用了springboot启动类实现CommandLineRunner接口的run方法,然后在run方法里启动netty服务
@SpringBootApplication
publicclassDemoApplicationimplementsCommandLineRunner{
@Resource
privateDiscardServerdiscardServer;
publicstaticvoidmain(String[]args){
SpringApplication.run(DemoApplication.class,args);
}
@Override
publicvoidrun(String...args)throwsException{
discardServer.run(8080);
}
}
5.测试
写一个能发送数据的socket就可以了;
发送的数据为:
publicstaticvoidmain(String[]args){
try{
Socketsocket=newSocket("localhost",8080);
OutputStreamoutputStream=socket.getOutputStream();
PrintWriterprintWriter=newPrintWriter(outputStream);
printWriter.write("$tmb00035ET3318/08/2211:5804029.94,027.25,20.00,20.00$");
printWriter.flush();
socket.shutdownOutput();
socket.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
我的测试结果:
传输内容是
$tmb00035ET3318/08/2211:5804029.94,027.25,20.00,20.00$
aaaaa
到这里,netty与springboot的整合就完成了;
我在整合过程中遇到的问题
我使用springboot结合netty的流程
springboot启动类中启动netty启动类(DiscardServer),netty启动类(DiscardServer)再调用初始化channel类(ChildChannelHandler),然后初始化channel类再调用(DiscardServerHandler)类;然后DiscardServerHandler类再调用service服务;如下示例图:
问题:
- springboot启动类我并没有实现CommandLineRunner接口,直接在main方法通过new的方式启动netty服务
- 我实现了CommandLineRunner接口,但是我在run方法中用的new的方式启动的netty服务或者我在run方法使用注入的方式启动netty,但是在其他某个地方调用另一个类使用了new的方式;
- DiscardServerHandler类上为标记@Sharable类,会报错误;
以上总结起来的问题就是我在springboot整合netty的过程中有其中一处的调用其他类时使用的方式是new构造的,这样虽然springboot能启动,netty也能启动,但是netty服务中使用new构造的那个类中无法依赖注入,会报空指针异常;
举个栗子:在图中的过程中,我在ChildChannelHandler类中通过new的方式调用DiscardServerHandler类,其他的过程都是使用注入的方式调用,就会出现上边的问题;
在遇到空指针的时候,我把spring托管的bean打印了出来,所有的类都在spring的托管中,但是就是无法注入,我也一直没有明白怎么回事,最后用了一个极端的方法,就是在调用服务时,获取spring的上下文,然后再根据名字来获取bean,你谷歌或百度:非托管类调用spring托管类,就能找到很多文章了;虽然用这个方式能解决上述的问题,但总是不好的;
最后的解决办法:所以类之间的调用都使用spring的依赖注入,别用new的方式来调用或者静态方法的方式调用
总结
既然项目中用到了spring,那么类与类之间的调用就用依赖注入,不然会报空指针的问题(就是非托管对象调用spring托管对象);这也算是一个常识性的问题了,只是自己现在才遇到这样的问题,还是要踩坑才能遇涨记性啊;这些问题困扰了我两三天,还是要有经验的人带,如果有经验的人带的话,说不几分钟就搞定了;
netty的文章到这里就告一段落了,接下来就是赶项目了;哈哈;
GitHub项目地址:
本文内容总结:前言,正文,代码,1.新建一个springboot项目,在pom文件中添加netty依赖:,2.新建netty服务,3.netty调用所需的服务类,4springboot启动类,5.测试,我在整合过程中遇到的问题,总结,
原文链接:https://www.cnblogs.com/guoyuchuan/p/9581283.html