springboot整合netty过程详解
这篇⽂章主要介绍了springboot整合netty过程详解,⽂中通过⽰例代码介绍的⾮常详细,对⼤家的学习或者⼯作具有⼀定的参考学习价值,需要的朋友可以参考下
前⾔
讲了netty的⼀个⼊门的demo;项⽬上我也把数据处理做好了,就要开始存数据库了;我⽤的mybatis框架,如果单独使⽤还是觉得⽐较⿇烦,所以就⽤了springboot+mybatis+netty;本篇主要讲netty与springboot的整合,以及我在这个过程中遇到的问题,⼜是怎么去解决的;
正⽂
我在做springboot与netty整合的时候在⾕歌,百度了⽆数⽂章,都没有⼀篇是⾃⼰想要的,也达不到⾃⼰所想的⽬的;
代码
1. 新建⼀个springboot项⽬,在pom⽂件中添加netty依赖:
<dependency>
<groupId>ioty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha1</version>
</dependency>
2.新建netty服务
其实可以复制上⼀篇⽂章的netty的三个服务类,做⼀些稍微的修改就⾏了;这⾥为了⽅便演⽰,且修都是改好了的,就直接贴出来了;
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("准备运⾏端⼝:" + port);
try {
ServerBootstrap bootstrap = new ServerBootstrap();
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.childHandler(childChannelHandler);
//绑定端⼝,同步等待成功
ChannelFuture f = bootstrap.bind(port).sync();
//等待服务监听端⼝关闭
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注解,如果不加的话会报错;
@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("传输内容是");spring启动流程面试回答
System.out.String(CharsetUtil.UTF_8));
//这⾥调⽤service服务
} finally {
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// 出现异常就关闭
cause.printStackTrace();
ctx.close();
}
}
3ty调⽤所需的服务类
1.BaseService接⼝
public interface BaseService {
/**
* 测试接⼝
*/
void test();
}
2.接⼝实现类BaseServiceImpl:
@Service
public class BaseServiceImpl implements BaseService {
@Override
public void test() {
System.out.println("调⽤service服务");
}
}
4 springboot启动类
由于main⽅法是静态⽅法,netty服务启动类不是静态类,在main⽅法⾥⾯需要⽤new的⽅式启动;
也可以将netty服务启动类改为静态类,然后调⽤其他⾮静态的类时就得⽤new⽅法来构造其他类了;
我也百度到了⼏篇⽂章说实现CommandLineRunner接⼝,所以我⽤了springboot启动类实现CommandLineRunner接⼝的run ⽅法,然后在run⽅法⾥启动netty服务
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Resource
private DiscardServer discardServer;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void args) throws Exception {
discardServer.run(8080);
}
}
5.测试
写⼀个能发送数据的socket就可以了;
发送的数据为:
public static void main(String[] args){
try {
Socket socket=new Socket("localhost",8080);
OutputStream outputStream = OutputStream();
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();
}
}
我的测试结果:
传输内容是
$tmb00035ET3318/08/22 11: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托管对象);这也算是⼀个常识性的问题了,只是⾃⼰现在才遇到这样的问题,还是要踩坑才能遇涨记性啊;这些问题困扰了我两三天,还是要有经验的⼈带,如果有经验的⼈带的话,说不⼏分钟就搞定了;
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。