热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

springboot整合netty的实现方法

这篇文章主要介绍了springboot整合netty的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

之前花了几天去研究怎么使用netty做一个网关服务器,虽然最后还是没能用上我做的网关,但是呢netty是会用了,总结一下netty和spring boot整合。感觉不用spring boot都不会写代码了。哈哈哈

在pom文件中添加相关的依赖,这里主要的就是netty的依赖,spring boot的相关依赖本文不提

    
      io.netty
      netty-all
      4.1.19.Final
    
    
     
      SpringBoot-Netty
      SpringBoot-Netty
      1.0-SNAPSHOT
    

在application.yml文件中配置

#不能用localhost,否则启动报异常:Unresolved address
#tcp监听的端口
tcp:
 port: 8090
# bossGroup的线程数
boss:
 thread:
  count: 2
# worker的线程数
worker:
 thread:
  count: 2
#是否使用长连接
so:
 keepalive: true
 backlog: 100

3.编写NettyConfig netty的配置。

package com.advsun.netty.config;

import com.advsun.netty.handlers.StringProtocolInitalizer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author 杨红星
 * @version 1.0.0
 */
@Configuration
public class NettyConfig {
  
  //读取yml中配置 
  @Value("${boss.thread.count}")
  private int bossCount;

  @Value("${worker.thread.count}")
  private int workerCount;

  @Value("${tcp.port}")
  private int tcpPort;

  @Value("${so.keepalive}")
  private boolean keepAlive;

  @Value("${so.backlog}")
  private int backlog;

  @Autowired
  @Qualifier("springProtocolInitializer")
  private StringProtocolInitalizer protocolInitalizer;
//bootstrap配置
  @SuppressWarnings("unchecked")
  @Bean(name = "serverBootstrap")
  public ServerBootstrap bootstrap() {
    ServerBootstrap b = new ServerBootstrap();
    b.group(bossGroup(), workerGroup())
        .channel(NioServerSocketChannel.class)
        .childHandler(protocolInitalizer);
    Map, Object> tcpChannelOptiOns= tcpChannelOptions();
    Set> keySet = tcpChannelOptions.keySet();
    for (@SuppressWarnings("rawtypes")
        ChannelOption option : keySet) {
      b.option(option, tcpChannelOptions.get(option));
    }
    return b;
  }

  @Bean(name = "bossGroup", destroyMethod = "shutdownGracefully")
  public NioEventLoopGroup bossGroup() {
    return new NioEventLoopGroup(bossCount);
  }

  @Bean(name = "workerGroup", destroyMethod = "shutdownGracefully")
  public NioEventLoopGroup workerGroup() {
    return new NioEventLoopGroup(workerCount);
  }

  @Bean(name = "tcpSocketAddress")
  public InetSocketAddress tcpPort() {
    return new InetSocketAddress(tcpPort);
  }

  @Bean(name = "tcpChannelOptions")
  public Map, Object> tcpChannelOptions() {
    Map, Object> optiOns= new HashMap, Object>();
    options.put(ChannelOption.SO_KEEPALIVE, keepAlive);
    options.put(ChannelOption.SO_BACKLOG, backlog);
    return options;
  }

  @Bean(name = "stringEncoder")
  public StringEncoder stringEncoder() {
    return new StringEncoder();
  }

  @Bean(name = "stringDecoder")
  public StringDecoder stringDecoder() {
    return new StringDecoder();
  }

  /**
   * Necessary to make the Value annotations work.
   *
   * @return
   */
  @Bean
  public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
  }
}

4.初始化的相关配置

package com.advsun.netty.handlers;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

/**
 * @author 杨红星
 * @version 1.0.0
 */
@Component
@Qualifier("springProtocolInitializer")
public class StringProtocolInitalizer extends ChannelInitializer {

  @Autowired
  StringDecoder stringDecoder;

  @Autowired
  StringEncoder stringEncoder;

  @Autowired
  ServerHandler serverHandler;

  @Override
  protected void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline pipeline = ch.pipeline();
    pipeline.addLast("decoder", stringDecoder);
    pipeline.addLast("handler", serverHandler);
    pipeline.addLast("encoder", stringEncoder);
  }

  public StringDecoder getStringDecoder() {
    return stringDecoder;
  }

  public void setStringDecoder(StringDecoder stringDecoder) {
    this.stringDecoder = stringDecoder;
  }

  public StringEncoder getStringEncoder() {
    return stringEncoder;
  }

  public void setStringEncoder(StringEncoder stringEncoder) {
    this.stringEncoder = stringEncoder;
  }

  public ServerHandler getServerHandler() {
    return serverHandler;
  }

  public void setServerHandler(ServerHandler serverHandler) {
    this.serverHandler = serverHandler;
  }

}

5.tcp服务的配置

package com.advsun.netty.config;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetSocketAddress;

/**
 * @author 杨红星
 * @version 1.0.0
 */
@Component
public class TCPServer {
  @Autowired
  @Qualifier("serverBootstrap")
  private ServerBootstrap b;

  @Autowired
  @Qualifier("tcpSocketAddress")
  private InetSocketAddress tcpPort;

  private ChannelFuture serverChannelFuture;

  @PostConstruct
  public void start() throws Exception {
    System.out.println("Starting server at " + tcpPort);
    serverChannelFuture = b.bind(tcpPort).sync();
  }

  @PreDestroy
  public void stop() throws Exception {
    serverChannelFuture.channel().closeFuture().sync();
  }

  public ServerBootstrap getB() {
    return b;
  }

  public void setB(ServerBootstrap b) {
    this.b = b;
  }

  public InetSocketAddress getTcpPort() {
    return tcpPort;
  }

  public void setTcpPort(InetSocketAddress tcpPort) {
    this.tcpPort = tcpPort;
  }
}

6.serverHandler配置这里是实现业务逻辑的地方

package com.advsun.netty.handlers;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.net.InetAddress;

/**
 * @author 杨红星
 * @version 1.0.0
 */
@Component
@Qualifier("serverHandler")
@ChannelHandler.Sharable
public class ServerHandler extends SimpleChannelInboundHandler {
  private static final Logger log = LoggerFactory.getLogger(ServerHandler.class);

  @Override
  public void channelRead0(ChannelHandlerContext ctx, String msg)
      throws Exception {
    log.info("client msg:"+msg);
    String clientIdToLOng= ctx.channel().id().asLongText();
    log.info("client long id:"+clientIdToLong);
    String clientIdToShort= ctx.channel().id().asShortText();
    log.info("client short id:"+clientIdToShort);
    if(msg.indexOf("bye")!=-1){
      //close
      ctx.channel().close();
    }else{
      //send to client
      ctx.channel().writeAndFlush("Yoru msg is:"+msg);

    }

  }

  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {

    log.info("RamoteAddress : " + ctx.channel().remoteAddress() + " active !");

    ctx.channel().writeAndFlush( "Welcome to " + InetAddress.getLocalHost().getHostName() + " service!\n");

    super.channelActive(ctx);
  }


  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    cause.printStackTrace();
    ctx.close();
  }

  @Override
  public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    log.info("\nChannel is disconnected");
    super.channelInactive(ctx);
  }
}

这里的 channelRead0(ChannelHandlerContext ctx, String msg)当客户机有消息发送过来时会调用这个方法,这个方法的名字叫的是真的差,所以netty5.0之后取消了这个名字, 5.0之后叫messageReceived。官方都说这名字叫的傻逼

channelRead0() → messageReceived()
I know. It was a silly mistake. If you are using SimpleChannelInboundHandler, you have to rename channelRead0() to messageReceived().

最后在贴一张自己在看netty实战时候画的思维导图

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


推荐阅读
  • Netty源代码分析服务器端启动ServerBootstrap初始化
    本文主要分析了Netty源代码中服务器端启动的过程,包括ServerBootstrap的初始化和相关参数的设置。通过分析NioEventLoopGroup、NioServerSocketChannel、ChannelOption.SO_BACKLOG等关键组件和选项的作用,深入理解Netty服务器端的启动过程。同时,还介绍了LoggingHandler的作用和使用方法,帮助读者更好地理解Netty源代码。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文介绍了如何找到并终止在8080端口上运行的进程的方法,通过使用终端命令lsof -i :8080可以获取在该端口上运行的所有进程的输出,并使用kill命令终止指定进程的运行。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • iOS Swift中如何实现自动登录?
    本文介绍了在iOS Swift中如何实现自动登录的方法,包括使用故事板、SWRevealViewController等技术,以及解决用户注销后重新登录自动跳转到主页的问题。 ... [详细]
  • Java学习笔记之使用反射+泛型构建通用DAO
    本文介绍了使用反射和泛型构建通用DAO的方法,通过减少代码冗余度来提高开发效率。通过示例说明了如何使用反射和泛型来实现对不同表的相同操作,从而避免重复编写相似的代码。该方法可以在Java学习中起到较大的帮助作用。 ... [详细]
  • 原理:dismiss再弹出,把dialog设为全局对象。if(dialog!null&&dialog.isShowing()&&!(Activity.)isFinishing()) ... [详细]
  • LVS实现负载均衡的原理LVS负载均衡负载均衡集群是LoadBalance集群。是一种将网络上的访问流量分布于各个节点,以降低服务器压力,更好的向客户端 ... [详细]
  • 本文详细介绍了在Centos7上部署安装zabbix5.0的步骤和注意事项,包括准备工作、获取所需的yum源、关闭防火墙和SELINUX等。提供了一步一步的操作指南,帮助读者顺利完成安装过程。 ... [详细]
  • 大坑|左上角_pycharm连接服务器同步写代码(图文详细过程)
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了pycharm连接服务器同步写代码(图文详细过程)相关的知识,希望对你有一定的参考价值。pycharm连接服务 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了markdown[软件代理设置]相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 现在比较流行使用静态网站生成器来搭建网站,博客产品着陆页微信转发页面等。但每次都需要对服务器进行配置,也是一个重复但繁琐的工作。使用DockerWeb,只需5分钟就能搭建一个基于D ... [详细]
  • 本文介绍了多因子选股模型在实际中的构建步骤,包括风险源分析、因子筛选和体系构建,并进行了模拟实证回测。在风险源分析中,从宏观、行业、公司和特殊因素四个角度分析了影响资产价格的因素。具体包括宏观经济运行和宏经济政策对证券市场的影响,以及行业类型、行业生命周期和行业政策对股票价格的影响。 ... [详细]
author-avatar
benbowujixian
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有