经过前面的netty学习,大概了解了netty各个组件的概念和作用,开始自己瞎鼓捣netty和我们常用的项目的整合(很简单的整合)
项目准备
  1. 工具:IDEA2017
  2. jar包导入:maven
  3. 项目框架:springboot+netty
项目操作

右键创建一个maven项目,项目名称: hetangyuese-netty-03(项目已上传github)

项目完整结构

maven导包

  1. <!-- netty start -->
  2. <dependency>
  3. <groupId>io.netty</groupId>
  4. <artifactId>netty-all</artifactId>
  5. <version>4.1.15.Final</version>
  6. </dependency>
  7. <!-- netty end -->
  1. <!-- springboot start -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-web</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.springframework.boot</groupId>
  12. <artifactId>spring-boot-devtools</artifactId>
  13. <optional>true</optional>
  14. <!-- 热部署 -->
  15. </dependency>
  16. <!-- springboot end -->
  17. // 之所以没版本,我是在parent项目中配置了maven的全局版本,只能在顶级项目中配置
  18. <parent>
  19. <groupId>org.springframework.boot</groupId>
  20. <artifactId>spring-boot-starter-parent</artifactId>
  21. <version>1.5.6.RELEASE</version>
  22. </parent>
  1. <!-- 日志 slf4j及logback包 start -->
  2. <dependency>
  3. <groupId>org.slf4j</groupId>
  4. <artifactId>slf4j-api</artifactId>
  5. <version>1.7.7</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>ch.qos.logback</groupId>
  9. <artifactId>logback-core</artifactId>
  10. <version>1.1.7</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>ch.qos.logback</groupId>
  14. <artifactId>logback-classic</artifactId>
  15. <version>1.1.7</version>
  16. </dependency>
  17. <!-- 日志 slf4j及logback包 end -->

编码

  1. springboot启动类 HetangyueseApplication
  2. 因为需要集成netty启动类不再是继承SpringBootServletInitializer类修改为实现CommandLineRunnerCommandLineRunner项目启动后执行)
  1. package com.hetangyuese.netty;
  2. import com.hetangyuese.netty.controller.HtServer;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.boot.CommandLineRunner;
  5. import org.springframework.boot.SpringApplication;
  6. import org.springframework.boot.autoconfigure.SpringBootApplication;
  7. /**
  8. * @program: netty-root
  9. * @description: 启动类
  10. * @author: hetangyuese
  11. * @create: 2019-10-28 16:47
  12. **/
  13. @SpringBootApplication
  14. public class HetangyueseApplication implements CommandLineRunner {
  15. @Autowired
  16. private HtServer htServer; // Netty服务端类
  17. public static void main(String[] args) {
  18. SpringApplication.run(HetangyueseApplication.class, args);
  19. }
  20. @Override
  21. public void run(String... strings) throws Exception {
  22. // 调用netty服务端启动方法
  23. htServer.start(9000);
  24. }
  25. }

Netty启动类

  1. package com.hetangyuese.netty.controller;
  2. import com.hetangyuese.netty.channel.HtServerChannel;
  3. import io.netty.bootstrap.ServerBootstrap;
  4. import io.netty.channel.ChannelFuture;
  5. import io.netty.channel.ChannelHandler;
  6. import io.netty.channel.ChannelOption;
  7. import io.netty.channel.EventLoopGroup;
  8. import io.netty.channel.nio.NioEventLoopGroup;
  9. import io.netty.channel.socket.nio.NioServerSocketChannel;
  10. import io.netty.handler.logging.LoggingHandler;
  11. import org.slf4j.Logger;
  12. import org.slf4j.LoggerFactory;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.stereotype.Component;
  15. /**
  16. * @program: netty-root
  17. * @description: ht服务类
  18. * @author: hetangyuese
  19. * @create: 2019-10-28 17:28
  20. **/
  21. @Component
  22. public class HtServer {
  23. private Logger log = LoggerFactory.getLogger(HtServer.class);
  24. /**
  25. * Netty服务端启动类
  26. */
  27. private ServerBootstrap serverBootstrap;
  28. /**
  29. * 服务通道
  30. */
  31. @Autowired
  32. private HtServerChannel htServerChannel;
  33. /**
  34. * Netty日志处理类,可以打印出入站出站的日志,方便排查
  35. * 需搭配 channelPipeline.addLast(new LoggingHandler(LogLevel.INFO));
  36. * 使用
  37. */
  38. private ChannelHandler logging = new LoggingHandler();
  39. /**
  40. *
  41. * @param port 启动端口号
  42. */
  43. public void start(int port) {
  44. log.debug("htServer start port:{}", port);
  45. // 主线程组 用于处理连接
  46. EventLoopGroup boss = new NioEventLoopGroup(1);
  47. // 工作线程组用于处理业务逻辑
  48. EventLoopGroup work = new NioEventLoopGroup();
  49. try {
  50. serverBootstrap = getServerBootstrap();
  51. // 配置服务端启动类
  52. serverBootstrap.group(boss, work)
  53. .channel(NioServerSocketChannel.class)
  54. .option(ChannelOption.SO_BACKLOG, 1024)
  55. .childOption(ChannelOption.SO_REUSEADDR, true)
  56. .handler(logging)
  57. .childHandler(htServerChannel);
  58. // 服务端绑定端口并持续等待
  59. ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
  60. // 通道持续阻塞等待直到关闭了服务
  61. channelFuture.channel().closeFuture().sync();
  62. } catch (Exception e) {
  63. // 输出错误日志
  64. log.error("netty server start happened exception e:{}", e);
  65. } finally {
  66. // 关闭线程组
  67. boss.shutdownGracefully();
  68. work.shutdownGracefully();
  69. }
  70. }
  71. /**
  72. * 初始化启动类
  73. * @return
  74. */
  75. public ServerBootstrap getServerBootstrap() {
  76. if (null == serverBootstrap) {
  77. serverBootstrap = new ServerBootstrap();
  78. }
  79. return serverBootstrap;
  80. }
  81. }

管道类(channel、pipeline)

  1. package com.hetangyuese.netty.channel;
  2. import com.hetangyuese.netty.handler.HtServerHandler;
  3. import io.netty.channel.Channel;
  4. import io.netty.channel.ChannelInitializer;
  5. import io.netty.channel.ChannelPipeline;
  6. import io.netty.handler.codec.string.StringDecoder;
  7. import io.netty.handler.logging.LogLevel;
  8. import io.netty.handler.logging.LoggingHandler;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.stereotype.Service;
  11. /**
  12. * @program: netty-root
  13. * @description: 配置管道
  14. * @author: hetangyuese
  15. * @create: 2019-10-28 17:35
  16. **/
  17. @Service
  18. public class HtServerChannel extends ChannelInitializer {
  19. @Autowired
  20. private HtServerHandler htServerHandler;
  21. @Override
  22. protected void initChannel(Channel ch) throws Exception {
  23. // 通道流水线 管理channelHandler的有序执行
  24. ChannelPipeline channelPipeline = ch.pipeline();
  25. // netty日志
  26. channelPipeline.addLast(new LoggingHandler(LogLevel.INFO));
  27. // 字符串解码器 接收到数据直接转为string 这里没有弄自定义和其他的解码器
  28. channelPipeline.addLast(new StringDecoder());
  29. // 业务逻辑处理类
  30. channelPipeline.addLast(htServerHandler);
  31. }
  32. }

业务逻辑类(handler)

服务端ChannelPipeline中有许多的ChannelHandler, 如果每个都实例化一个ChannelHandler,在大量的客户端连接的时候将会产生大量的ChannelHandler实例,为了解决这个问题netty中可以通过@ChannelHandler.Sharable注解实现共享实例,由这一个实例去处理客户端连接

  1. package com.hetangyuese.netty.handler;
  2. import io.netty.buffer.Unpooled;
  3. import io.netty.channel.ChannelHandler;
  4. import io.netty.channel.ChannelHandlerContext;
  5. import io.netty.channel.ChannelInboundHandlerAdapter;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import org.springframework.stereotype.Service;
  9. /**
  10. * @program: netty-root
  11. * @description: 处理类
  12. * @author: hetangyuese
  13. * @create: 2019-10-28 17:39
  14. **/
  15. @ChannelHandler.Sharable
  16. @Service
  17. public class HtServerHandler extends ChannelInboundHandlerAdapter {
  18. private Logger log = LoggerFactory.getLogger(HtServerHandler.class);
  19. @Override
  20. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  21. log.debug("channel已注册");
  22. ctx.writeAndFlush(Unpooled.copiedBuffer("xixixix".getBytes()));
  23. }
  24. /**
  25. * 服务端接收到的数据
  26. * @param ctx
  27. * @param msg
  28. * @throws Exception
  29. */
  30. @Override
  31. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  32. log.debug("htServer receive" + (String)msg);
  33. }
  34. /**
  35. * 服务端接收完毕事件
  36. * @param ctx
  37. * @throws Exception
  38. */
  39. @Override
  40. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  41. ctx.writeAndFlush(Unpooled.copiedBuffer("Htserver readComplete".getBytes()));
  42. }
  43. /**
  44. * 异常捕获事件
  45. * @param ctx
  46. * @param cause
  47. * @throws Exception
  48. */
  49. @Override
  50. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  51. cause.printStackTrace();
  52. ctx.close();
  53. }
  54. }

配置文件(application.yml、logback.xml)

  1. application.yml文件
  2. spring:
  3. profiles:
  4. active: prod
  5. -----------------------------------------------------------
  6. application-prod.yml
  7. server:
  8. port: 8081
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration>
  3. <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
  4. <property name="LOG_HOME" value="log" />
  5. <!-- 控制台输出日志 -->
  6. <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
  7. <encoder>
  8. <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n
  9. </pattern>
  10. </encoder>
  11. </appender>
  12. <!-- 文件输出指定项目日志 -->
  13. <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
  14. <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  15. <fileNamePattern>${LOG_HOME}/netty03.%d{yyyy-MM-dd}.log</fileNamePattern>
  16. <maxHistory>30</maxHistory>
  17. </rollingPolicy>
  18. <encoder>
  19. <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
  20. </pattern>
  21. </encoder>
  22. </appender>
  23. <!-- 异步输出指定项目日志 -->
  24. <appender name="async" class="ch.qos.logback.classic.AsyncAppender">
  25. <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
  26. <discardingThreshold>0</discardingThreshold>
  27. <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
  28. <queueSize>512</queueSize>
  29. <!-- 添加附加的appender,最多只能添加一个 -->
  30. <appender-ref ref="file" />
  31. </appender>
  32. <logger name="org.apache" level="info">
  33. <appender-ref ref="async" />
  34. <appender-ref ref="stdout"/>
  35. </logger>
  36. <logger name="org.springframework" level="info">
  37. <appender-ref ref="async" />
  38. <appender-ref ref="stdout"/>
  39. </logger>
  40. <logger name="com.hetangyuese" level="debug">
  41. <appender-ref ref="async" />
  42. <appender-ref ref="stdout"/>
  43. </logger>
  44. </configuration>

启动(客户端我就不贴代码了)

  1. // 服务端
  2. 2019-10-29 16:10:20 [restartedMain] DEBUG com.hetangyuese.netty.controller.HtServer -htServer start port:9000
  3. 2019-10-29 16:10:48 [nioEventLoopGroup-3-1] DEBUG com.hetangyuese.netty.handler.HtServerHandler -channel已注册
  4. 2019-10-29 16:10:48 [nioEventLoopGroup-3-1] DEBUG com.hetangyuese.netty.handler.HtServerHandler -htServer receivehello!_My name is hanleilei !_What is your name !_How are you? !_
  5. // 客户端
  6. 服务端返回str xixixix
  7. 服务端返回str Htserver readComplete

总结

  1. 学习了netty的基础知识后,了解到很多rpc框架都运用了netty,看了下dubbonetty源码部分,也能明白每一步的用途,接下来自己琢磨写个rpc框架试试,学无止境!!!

Netty学习篇③--整合springboot的更多相关文章

  1. Netty学习篇⑤--编、解码

    前言 学习Netty也有一段时间了,Netty作为一个高性能的异步框架,很多RPC框架也运用到了Netty中的知识,在rpc框架中丰富的数据协议及编解码可以让使用者更加青睐: Netty支持丰富的编解 ...

  2. 小书MybatisPlus第1篇-整合SpringBoot快速开始增删改查

    Mybatis Plus官方文档已经很完善了,为什么还要写一个这样的文档? 官方文档注重知识结构的整理,没有注重学习者的学习顺序 官方文档中的案例注重API描述,比较适合学会mybatis plus之 ...

  3. Java-Dubbo学习及整合SpringBoot

    Dubbo架构 Dubbo是Java的RPC框架,具有三大核心功能:面向接口的远程方法调用,智能容错和负载均衡,以及服务的自动注册和发现 Dubbo架构图: 节点角色说明: 节点 说明 Provide ...

  4. Netty学习篇④-心跳机制及断线重连

    心跳检测 前言 客户端和服务端的连接属于socket连接,也属于长连接,往往会存在客户端在连接了服务端之后就没有任何操作了,但还是占用了一个连接:当越来越多类似的客户端出现就会浪费很多连接,netty ...

  5. Netty学习篇⑥--ByteBuf源码分析

    什么是ByteBuf? ByteBuf在Netty中充当着非常重要的角色:它是在数据传输中负责装载字节数据的一个容器;其内部结构和数组类似,初始化默认长度为256,默认最大长度为Integer.MAX ...

  6. Netty学习篇②

    Channel.ChannelPipeline.ChannelHandlerContent发送数据的不同 // channel往回写数据 Channel channel = ctx.channel() ...

  7. Netty学习篇①

    什么是netty Netty封装了JDK自带的NIO,运用起来更加简单快速,Netty是一个异步事件驱动的网络应用框架,让开发更加简便 Netty相比JDK自带的NIO的优点 Netty的api调用简 ...

  8. jackson学习之十(终篇):springboot整合(配置类)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  9. Netty学习——Netty和Protobuf的整合(二)

    Netty学习——Netty和Protobuf的整合(二) 这程序是有瑕疵的,解码器那里不通用,耦合性太强,有两个很明显的问题,但是要怎么解决呢?如:再加一个内部类型 Person2,之前的代码就不能 ...

随机推荐

  1. CAZAC序列

    定义: CAZAC(Const Amplitude Zero Auto-Corelation),即为恒包络零自相关序列. 性质: 1,恒包络特性:任意长度的CAZAC序列幅值恒定. 2,理想的周期自相 ...

  2. Linq to JSON/Json.NET

    Can I LINQ a JSON? http://stackoverflow.com/questions/18758361/can-i-linq-a-json Json.NET https://js ...

  3. 在Vue中使用TypeScript

    TypeScript基础学习 初始化TS项目 Vue装饰器 vue-typescript-admin框架 1.TypeScript基础学习 2.初始化TS项目 3.Vue装饰器 Vue装饰器常用的有下 ...

  4. Noip2012 提高组 Day1 T1 Vigenère 密码

    题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南 ...

  5. 转:关于C++ const 的全面总结

    转自:https://www.cnblogs.com/xkfz007/articles/2419518.html    如有侵权请联系博主,立即删除. C++中的const关键字的用法非常灵活,而使用 ...

  6. ICP、MRR、BKA等特性

    一.Index Condition Pushdown(ICP) Index Condition Pushdown (ICP)是 mysql 使用索引从表中检索行数据的一种优化方式,从mysql5.6开 ...

  7. 实战 Prometheus 搭建监控系统

    实战 Prometheus 搭建监控系统 Prometheus 是一款基于时序数据库的开源监控告警系统,说起 Prometheus 则不得不提 SoundCloud,这是一个在线音乐分享的平台,类似于 ...

  8. MySQL数据分析(7)-试着使用SQL

    (一) 1.1 启动服务器 Windows版命令: net start mysql 或者 C:\mysql-5.5.20-winx64\mysql-5.5.20-winx64\mysql Mac版命令 ...

  9. kali系统firefox浏览器默认语言改为中文设置方法

    kali中的Firefox浏览器默认为英文,这对英语不够好的我来讲,自然是很麻烦的,下面讲一下如何将语言设置为中文. 1.打开终端,输入 apt -y install firefox-esr-l10n ...

  10. varnish web cache服务

    varnish介绍 缓存开源解决方案: - varnish - 充分利用epoll机制(能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率),并发量大,单连接资源较轻 - squid ...