美文网首页bugstac...
spring boot整合netty

spring boot整合netty

作者: 三不猴子 | 来源:发表于2018-01-22 13:58 被阅读15919次
    spring boot整合netty

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

    1. 在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>
    
    1. 在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实战时候画的思维导图


    netty实战.png

    图片还会更新,这个思维导图还没画完

    相关文章

      网友评论

        本文标题:spring boot整合netty

        本文链接:https://www.haomeiwen.com/subject/ytplaxtx.html