spring boot整合netty的实现方法

之前花了几天去研究怎么使用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实战时候画的思维导图

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

(0)

相关推荐

  • Netty与Spring Boot的整合的实现

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

  • 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&

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

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

  • spring boot整合netty的实现方法

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

  • spring boot整合Cucumber(BDD)的方法

    本文介绍了spring boot整合Cucumber(BDD)的方法,分享给大家,具体如下: 1.新建一个springboot工程工程结构如下: 2.添加pom依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLS

  • spring boot整合quartz实现多个定时任务的方法

    最近收到了很多封邮件,都是想知道spring boot整合quartz如何实现多个定时任务的,由于本人生产上并没有使用到多个定时任务,这里给个实现的思路. 1.新建两个定时任务,如下: public class ScheduledJob implements Job{ @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("sched

  • Spring Boot 整合mybatis 使用多数据源的实现方法

    前言 本篇教程偏向实战,程序猿直接copy代码加入到自己的项目中做简单的修修改改便可使用,而对于springboot以及mybatis不在此进行展开介绍,如有读者希望了解可以给我留言,并持续关注,我后续会慢慢更新.(黑色区域代码部分,安卓手机可手动向左滑动,来查看全部代码) 整合 其实整合很简单,如果是用gradle的话,在build.gradle文件里加入 compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1')

  • Spring Boot整合JPA使用多个数据源的方法步骤

    介绍 JPA(Java Persistence API)Java 持久化 API,是 Java 持久化的标准规范,Hibernate 是持久化规范的技术实现,而 Spring Data JPA 是在 Hibernate 基础上封装的一款框架. 第一次使用 Spring JPA 的时候,感觉这东西简直就是神器,几乎不需要写什么关于数据库访问的代码一个基本的 CURD 的功能就出来了.在这篇文章中,我们将介绍 Spring Boot 整合 JPA 使用多个数据源的方法. 开发环境: Spring B

  • Spring Boot 整合 JWT的方法

    1.JWT 是什么? JWT 是一个开放标准,它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法.JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名. 简单来说,就是通过一定规范来生成 token,然后可以通过解密算法逆向解密 token,这样就可以获取用户信息. 优点: 1)生产的 token 可以包含基本信息,比如 id.用户昵称.头像等信息,避免再次查库 2)存储在客户端,不占用服务端的内存资源 缺点: token 是经过 base6

  • Spring Boot整合mybatis使用注解实现动态Sql、参数传递等常用操作(实现方法)

    前面介绍了Spring Boot 整合mybatis 使用注解的方式实现数据库操作,介绍了如何自动生成注解版的mapper 和pojo类. 接下来介绍使用mybatis 常用注解以及如何传参数等数据库操作中的常用操作. 其实,mybatis 注解方式 和 XML配置方式两者的使用基本上相同,只有在构建 SQL 脚本有所区别,所以这里重点介绍两者之间的差异,以及增删改查,参数传递等注解的常用操作. 详解SpringBoot 快速整合Mybatis(去XML化+注解进阶)已经介绍过了,不清楚的朋友可

  • Spring Boot整合Lombok的方法详解

    上篇文章给大家介绍了,喜欢的朋友点击查看下. SpringBoot 开发提速神器 Lombok+MybatisPlus+SwaggerUI Lombok为啥这么牛逼?SpringBoot和IDEA官方都要支持它 一.Lombok简介 Lombok 是一种 Java 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO).它通过注释实现这一目的.通过在开发环境中实现  Lombok,开发人员可以节省构建诸如 hashCode() 和 equals() 这样

  • spring boot整合mybatis利用Mysql实现主键UUID的方法

    前言 本文主要给大家介绍了关于spring boot整合mybatis利用Mysql实现主键UUID的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 实现 基础项目的pom.xml部分代码如下 <properties> <java.version>1.8</java.version> </properties> <!-- Inherit defaults from Spring Boot --> <parent&

  • spring boot整合jsp及设置启动页面的方法

    前言 这几天在集中学习Spring boot+Shiro框架,因为之前view层用jsp比较多,所以想在spring boot中配置jsp,但是spring boot官方不推荐使用jsp,因为jsp相对于一些模板引擎,性能都比较低,官方推荐使用thymeleaf,但是Spring boot整合jsp的过程已经完成,在这里记录一下. 本文基于springboot2.0.4最新版本 spring官方推荐Thymeleaf但是还是有很多javaweb朋友习惯使用jsp虽然现在jsp有点out.本节教程

随机推荐