首页 > 编程 > Java > 正文

spring boot整合netty的实现方法

2019-11-26 08:41:27
字体:
来源:转载
供稿:网友

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

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表