springboot整合netty过程详解

 更新时间:2019年12月05日 09:27:16   作者:guodaye  
这篇文章主要介绍了springboot整合netty过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了springboot整合netty过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

前言

上一篇讲了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
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();
      bootstrap.group(bossGroup, workerGroup)
          .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("传输内容是");
      System.out.println(in.toString(CharsetUtil.UTF_8));
      //这里调用service服务
      baseService.test();
    } finally {
      ReferenceCountUtil.release(msg);
    }
  }
  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    // 出现异常就关闭
    cause.printStackTrace();
    ctx.close();
  }
}

3.netty调用所需的服务类

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 run(String... args) throws Exception {
    discardServer.run(8080);
  }
}

5.测试

写一个能发送数据的socket就可以了;

发送的数据为:

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();
    }
  }

我的测试结果:

传输内容是
$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托管对象);这也算是一个常识性的问题了,只是自己现在才遇到这样的问题,还是要踩坑才能遇涨记性啊;这些问题困扰了我两三天,还是要有经验的人带,如果有经验的人带的话,说不几分钟就搞定了;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Springboot内嵌SQLite配置使用详解

    Springboot内嵌SQLite配置使用详解

    这篇文章主要介绍了Springboot内嵌SQLite配置使用详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • JAVA中重写(Override)与重载(Overload)的相关示例

    JAVA中重写(Override)与重载(Overload)的相关示例

    这篇文章主要给大家介绍了关于JAVA中重写(Override)与重载(Overload)的相关示例,重写(override)和重载(overload)是两种不同的方法重用技术,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • RabbitMQ单机版部署安装过程

    RabbitMQ单机版部署安装过程

    RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现,在实现过程中需要注意由于rabbitmq是基于erlang语言开发的,所以必须先安装erlang,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2022-03-03
  • Java中的throws关键字处理异常的最佳实践记录

    Java中的throws关键字处理异常的最佳实践记录

    在Java编程中,异常处理是保证程序健壮性和稳定性的重要手段,除了使用try-catch块捕获异常外,Java还提供了throws关键字,允许我们将异常抛给调用者处理,本文介绍Java中的throws关键字处理异常的最佳实践记录,感兴趣的朋友一起看看吧
    2025-01-01
  • 详解SpringBoot如何实现多环境配置

    详解SpringBoot如何实现多环境配置

    在实际的软件开发过程中,一个应用程序通常会有多个环境,pring Boot 提供了一个非常灵活和强大的方式来管理这些环境配置,下面就跟随小编一起学习一下吧
    2023-07-07
  • Java接口方法默认静态实现代码实例

    Java接口方法默认静态实现代码实例

    这篇文章主要介绍了Java接口方法默认静态实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • java如何防止表单重复提交的注解@RepeatSubmit

    java如何防止表单重复提交的注解@RepeatSubmit

    @RepeatSubmit是一个自定义注解,用于防止表单重复提交,它通过AOP和拦截器模式实现,结合了线程安全和分布式环境的考虑,注解参数包括interval(间隔时间)和message(提示信息),使用时需要注意并发处理、用户体验、性能和安全性等方面,失效原因是多方面的
    2024-11-11
  • 一文吃透Spring Cloud gateway自定义错误处理Handler

    一文吃透Spring Cloud gateway自定义错误处理Handler

    这篇文章主要为大家介绍了一文吃透Spring Cloud gateway自定义错误处理Handler方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • 解读maven项目启动tomcat不报错但是启动不起来,tomcat启动到警告log4j就停止了

    解读maven项目启动tomcat不报错但是启动不起来,tomcat启动到警告log4j就停止了

    这篇文章主要介绍了maven项目启动tomcat不报错但是启动不起来,tomcat启动到警告log4j就停止了问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Eclipse将Maven项目打成jar包的方法

    Eclipse将Maven项目打成jar包的方法

    这篇文章主要介绍了Eclipse将Maven项目打成jar包的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2007-09-09

最新评论