spring boot整合netty的实现方法

作者:三不猴子 时间:2021-11-17 04:28:03 

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

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


   <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,否则启动报异常: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<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.初始化的相关配置


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服务的配置


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<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)当客户机有消息发送过来时会调用这个方法,这个方法的名字叫的是真的差,所以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实战时候画的思维导图

spring boot整合netty的实现方法

来源:https://www.jianshu.com/p/222fe9f2a564

标签:spring,boot,netty
0
投稿

猜你喜欢

  • SpringBoot中并发定时任务的实现、动态定时任务的实现(看这一篇就够了)推荐

    2023-01-21 13:58:45
  • Java如何将字符串String转换为整型Int

    2023-11-10 21:40:19
  • 详解IDEA多module项目maven依赖的一些说明

    2023-07-21 06:09:05
  • Java项目实现寻找迷宫出路

    2022-10-05 14:08:46
  • springboot如何读取配置文件到静态工具类

    2023-11-28 04:44:54
  • Java实现word/pdf转html并在线预览

    2022-09-09 09:16:49
  • 解决SpringBoot框架因post数据量过大没反应问题(踩坑)

    2023-11-28 11:59:30
  • SpringCloud全面解析@FeignClient标识接口的过程

    2023-08-05 12:34:44
  • 详解Java线程-守护线程与用户线程

    2023-11-25 00:17:29
  • Java 实战图书管理系统的实现流程

    2023-12-19 05:11:13
  • 举例讲解Java编程中this关键字与super关键字的用法

    2023-03-09 01:46:02
  • Java文件断点续传实现原理解析

    2022-08-21 02:05:39
  • JAVA判断空值方法原理解析

    2021-09-28 14:37:34
  • Java编程实现五子棋人人对战代码示例

    2021-12-27 12:58:51
  • C# WPF后台动态添加控件实战教程

    2022-07-29 18:52:51
  • spring cglib 与 jdk 动态代理

    2021-07-19 20:28:43
  • SpringBoot请求处理之常用参数注解介绍与源码分析

    2023-11-10 10:38:12
  • SpringBoot集成EasyExcel的步骤

    2023-07-19 09:59:17
  • SpringBoot打jar包遇到的xml文件丢失的解决方案

    2023-04-11 23:39:06
  • 图解JVM垃圾内存回收算法

    2023-10-13 17:24:35
  • asp之家 软件编程 m.aspxhome.com