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

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

(0)

相关推荐

  • spring+netty服务器搭建的方法

    游戏一般是长连接,自定义协议,不用http协议,BIO,NIO,AIO这些我就不说了,自己查资料 我现在用spring+netty搭起简单的游戏服 思路:1自定义协议和协议包:2spring+netty整合:3半包粘包处理,心跳机制等:4请求分发(目前自己搞的都是单例模式) 下个是测试用的,结构如下 首先自定义包头 Header.java package com.test.netty.message; /** * Header.java * 自定义协议包头 * @author janehuang

  • Spring Boot集成netty实现客户端服务端交互示例详解

    前言 Netty 是一个高性能的 NIO 网络框架,本文主要给大家介绍了关于SpringBoot集成netty实现客户端服务端交互的相关内容,下面来一起看看详细的介绍吧 看了好几天的netty实战,慢慢摸索,虽然还没有摸着很多门道,但今天还是把之前想加入到项目里的 一些想法实现了,算是有点信心了吧(讲真netty对初学者还真的不是很友好......) 首先,当然是在SpringBoot项目里添加netty的依赖了,注意不要用netty5的依赖,因为已经废弃了 <!--netty--> <

  • Netty与Spring Boot的整合的实现

    ​ 最近有朋友向我询问一些Netty与SpringBoot整合的相关问题,这里,我就总结了一下基本整合流程,也就是说,这篇文章 ,默认大家是对netty与Spring,SpringMVC的整合是没有什么问题的.现在,就进入正题吧. Server端: 总的来说,服务端还是比较简单的,自己一共写了三个核心类.分别是 NettyServerListener:服务启动监听器 ServerChannelHandlerAdapter:通道适配器,主要用于多线程共享 RequestDispatcher:请求分

  • Netty学习教程之基础使用篇

    什么Netty? Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 也就是说,Netty 是一个基于NIO的客户.服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用.Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发. 我们下面编写四个类 1.用于接收数据的服务器端Socket

  • Java NIO框架Netty简单使用的示例

    之前写了一篇文章:Java 网络IO编程总结(BIO.NIO.AIO均含完整实例代码),介绍了如何使用Java原生IO支持进行网络编程,本文介绍一种更为简单的方式,即Java NIO框架. Netty是业界最流行的NIO框架之一,具有良好的健壮性.功能.性能.可定制性和可扩展性.同时,它提供的十分简单的API,大大简化了我们的网络编程. 同Java IO介绍的文章一样,本文所展示的例子,实现了一个相同的功能. 1.服务端 Server: package com.anxpp.io.calculat

  • Spring Boot实战之netty-socketio实现简单聊天室(给指定用户推送消息)

    网上好多例子都是群发的,本文实现一对一的发送,给指定客户端进行消息推送 1.本文使用到netty-socketio开源库,以及MySQL,所以首先在pom.xml中添加相应的依赖库 <dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>1.7.11</version&

  • 通过入门demo简单了解netty使用方法

    这篇文章主要介绍了通过入门demo简单了解netty使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言 最近做一个项目: 大概需求: 多个温度传感器不断向java服务发送温度数据,该传感器采用socket发送数据:该数据以$符号开头和结尾,最后将处理的数据存入数据库: 我想到的处理方式:采用netty来接收和处理数据,然后用mybatis将处理后的数据存入数据库: 我在这之前从来没使用过netty,在网上倒是看到不少关于netty的文

  • spring boot整合netty的实现方法

    之前花了几天去研究怎么使用netty做一个网关服务器,虽然最后还是没能用上我做的网关,但是呢netty是会用了,总结一下netty和spring boot整合.感觉不用spring boot都不会写代码了.哈哈哈 在pom文件中添加相关的依赖,这里主要的就是netty的依赖,spring boot的相关依赖本文不提 <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artif

  • springboot整合netty过程详解

    这篇文章主要介绍了springboot整合netty过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言 上一篇讲了netty的一个入门的demo:项目上我也把数据处理做好了,就要开始存数据库了:我用的mybatis框架,如果单独使用还是觉得比较麻烦,所以就用了springboot+mybatis+netty:本篇主要讲netty与springboot的整合,以及我在这个过程中遇到的问题,又是怎么去解决的: 正文 我在做springbo

  • springboot整合mybatis流程详解

    目录 1.mybatis是什么 2.整合 2.1 导入依赖 2.2 创建包和类 2.3 在application.yaml配置mybatis 3.使用注解版mybaits 4.实战过程 1.mybatis是什么 MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射.MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作.MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型.接口和 Java POJO(Plain Old Java

  • SpringBoot实现国际化过程详解

    这篇文章主要介绍了SpringBoot实现国际化过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 实现方法:thymeleaf模板引擎加上BootStrap 准备工作: 1.将准备好的Bootstrap模板放在templates下让SpringBoot进行自动配置 SpringBoot自动配置会自动到(idea的shif键连按两下进入全局搜索) 2.Bootstrp的引入(这里是maven以depency的方式引入) <!--引入boot

  • spring整合struts2过程详解

    这篇文章主要介绍了spring整合struts2过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 首先将以下jar包加入到lib文件夹中: 基础目录: Person.java package com.gong.spring.struts2.beans; public class Person { private String username; public void setUsername(String username) { this

  • SpringBoot Redis安装过程详解

    这篇文章主要介绍了SpringBoot Redis安装过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Redis 1.安装配置Redis服务,可以官网或GitHub下载安装,这里不做介绍. Ps:安装后可查看环境变量,将Redis配置到环境变量中,非必须. 2.在pom.xml中添加Redis的依赖,如下: Ps:springboot版本不同,填写的依赖存在差异. 3.编写Redis的工具类,代码如下: @Component publi

  • SpringBoot使用Log4j过程详解

    这篇文章主要介绍了SpringBoot使用Log4j过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 log4j.logback.Log4j2简介 log4j是apache实现的一个开源日志组件 logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j的原生实现 Log4j2是log4j 1.x和logback的改进版,采用了一些新技术(无锁异步.等等),使得日志的吞吐量.性能比lo

  • SpringBoot对接Spark过程详解

    本文主要介绍 SpringBoot 与 Spark 如何对接,具体使用可以参考文章SpringBoot 使用 Spark pom 文件添加 maven 依赖 spark-core:spark 的核心库,如:SparkConf spark-sql:spark 的 sql 库,如:sparkSession janino: Janino 是一个极小.极快的 开源Java 编译器,若不添加,spark 获取 MySQL 或 JSON 数据时会报错 org.springframework.web.util

  • SSM框架中测试单元的使用 spring整合Junit过程详解

    测试类中的问题和解决思路 问题 在测试类中,每个测试方法都有以下两行代码: ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); IAccountService as = ac.getBean("accountService",IAccountService.class); 这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常.所以又不能轻易删掉. 解决思路分析 针对

  • springboot配置redis过程详解

    在springboot中,默认继承好了一套完好的redis包,可以直接使用,但是如果使用中出了错不容易找到错误的原因,因此这里使用自己配置的redis: 需要使用的三个主要jar包: <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>

  • springBoot 创建定时任务过程详解

    前言 好几天没写了,工作有点忙,最近工作刚好做一个定时任务统计的,所以就将springboot 如何创建定时任务整理了一下. 总的来说,springboot创建定时任务是非常简单的,不用像spring 或者springmvc 需要在xml 文件中配置,在项目启动的时候加载.spring boot 使用注解的方式就可以完全支持定时任务. 不过基础注解的话,可能有的需求定时任务的时间会经常变动,注解就不好修改,每次都得重新编译,所以想将定时时间存在数据库,然后项目读取数据库执行定时任务,所以就有了基

随机推荐