springboot整合netty的實(shí)現(xiàn)方法

之前花了幾天去研究怎么使用netty做一個(gè)網(wǎng)關(guān)服務(wù)器,雖然最后還是沒(méi)能用上我做的網(wǎng)關(guān),但是呢netty是會(huì)用了,總結(jié)一下netty和spring boot整合。感覺(jué)不用spring boot都不會(huì)寫(xiě)代碼了。哈哈哈

專(zhuān)注于為中小企業(yè)提供網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)西和免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上1000+企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

在pom文件中添加相關(guān)的依賴(lài),這里主要的就是netty的依賴(lài),spring boot的相關(guān)依賴(lài)本文不提

    <dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-all</artifactId>
      <version>4.1.19.Final</version>
    </dependency>
    
     <dependency>
      <groupId>SpringBoot-Netty</groupId>
      <artifactId>SpringBoot-Netty</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>

在application.yml文件中配置

#不能用localhost,否則啟動(dòng)報(bào)異常:Unresolved address
#tcp監(jiān)聽(tīng)的端口
tcp:
 port: 8090
# bossGroup的線程數(shù)
boss:
 thread:
  count: 2
# worker的線程數(shù)
worker:
 thread:
  count: 2
#是否使用長(zhǎng)連接
so:
 keepalive: true
 backlog: 100

3.編寫(xiě)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<ChannelOption<?>, Object> tcpChannelOptions = tcpChannelOptions();
    Set<ChannelOption<?>> 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<ChannelOption<?>, Object> tcpChannelOptions() {
    Map<ChannelOption<?>, Object> options = new HashMap<ChannelOption<?>, 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.初始化的相關(guān)配置

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<SocketChannel> {

  @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服務(wù)的配置

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配置這里是實(shí)現(xiàn)業(yè)務(wù)邏輯的地方

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<String> {
  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)當(dāng)客戶(hù)機(jī)有消息發(fā)送過(guò)來(lái)時(shí)會(huì)調(diào)用這個(gè)方法,這個(gè)方法的名字叫的是真的差,所以netty5.0之后取消了這個(gè)名字, 5.0之后叫messageReceived。官方都說(shuō)這名字叫的傻逼

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

最后在貼一張自己在看netty實(shí)戰(zhàn)時(shí)候畫(huà)的思維導(dǎo)圖

spring boot整合netty的實(shí)現(xiàn)方法

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

分享標(biāo)題:springboot整合netty的實(shí)現(xiàn)方法
瀏覽路徑:http://bm7419.com/article46/ijpihg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開(kāi)發(fā)全網(wǎng)營(yíng)銷(xiāo)推廣、自適應(yīng)網(wǎng)站、品牌網(wǎng)站制作、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)