springboot集成netty

1.pom引入依赖

        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.70.Final</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.80</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.8</version>
        </dependency>

2.application.yml配置

server:
  port: 8095
  servlet:
    context-path: /netty
netty:
  url: 0.0.0.0  #0.0.0.0表示绑定任意ip
  port: 20004

3.启动类配置



import com.example.demo.server.NioNettyServer;
import io.netty.channel.ChannelFuture;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.scheduling.annotation.EnableAsync;


@EnableAsync
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    public static void main(String[] args) {
        ConfigurableApplicationContext context =  SpringApplication.run(DemoApplication.class, args);
        context.getBean(NioNettyServer.class).start();
    }

    @Override
    public void run(String... args) throws Exception {

    }
}

4.创建netty服务

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ipfilter.IpFilterRule;
import io.netty.handler.ipfilter.IpFilterRuleType;
import io.netty.handler.ipfilter.IpSubnetFilterRule;
import io.netty.handler.ipfilter.RuleBasedIpFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.net.InetSocketAddress;


@Slf4j
@Component
public class NioNettyServer {
    @Value("${netty.port}")
    private int port;
    @Value("${netty.url}")
    private String url;

    private final EventLoopGroup bossGroup = new NioEventLoopGroup();
    private final EventLoopGroup workerGroup = new NioEventLoopGroup();
    private Channel channel;
//把Netty交给spring托管,不然读不到application.yml的值
    @Autowired
    private ClientMessageHandler clientMessageHandler;

    @Async
    public void start() {
        final ClientMessageHandler serverHandler = clientMessageHandler;
        ChannelFuture f = null;
        // 接收连接
        EventLoopGroup boss = new NioEventLoopGroup();
        // 处理信息
        EventLoopGroup worker = new NioEventLoopGroup();
        try {
            // 定义server
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            // 添加分组
            serverBootstrap.group(bossGroup, workerGroup)
                    // 添加通道设置非阻塞
                    .channel(NioServerSocketChannel.class)
                    // 服务端可连接队列数量
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .localAddress(new InetSocketAddress(url,port))
                    // 开启长连接
                    .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
//                            为监听客户端read/write事件的Channel添加用户自定义的ChannelHandler
                            socketChannel.pipeline().addLast(serverHandler);

                   //--------------------- 以下代码用了设置黑名单,白名单过滤ip,没有需求可以注释掉  (58.61.0.1,16)表示模糊匹配前两位,8表示匹配IP第一位,16表示匹配IP一,二位,以此类推-------------------------------------------------------
                   //  32表示全匹配
                            //白名单
                     //       IpSubnetFilterRule rule1 = new IpSubnetFilterRule("127.0.0.1", 32, IpFilterRuleType.ACCEPT);
                            //黑名单
                     //       IpSubnetFilterRule rule2 = new IpSubnetFilterRule("127.0.0.1", 32, IpFilterRuleType.REJECT);
                      //      IpFilterRule rejectAll = new IpFilterRule() {
                      //          @Override
                        //        public boolean matches(InetSocketAddress remoteAddress) {
                      //              return true;
                      //          }
                      //          @Override
                      //          public IpFilterRuleType ruleType() {
                     //               return IpFilterRuleType.REJECT;
                     //           }
                     //       };
                     //       RuleBasedIpFilter filter = new RuleBasedIpFilter(rule1, rejectAll );
                    //        socketChannel.pipeline().addLast("ipFilter", filter);
                     //       socketChannel.pipeline().addLast("encoder", new StringEncoder());
                     //       socketChannel.pipeline().addLast("decoder", new StringDecoder());
                     //----------------------------------------------------------以上为ip过滤-----------------------------------------------------------

                       }

                    });
            // 绑定端口
            f = serverBootstrap.bind().sync();
            channel = f.channel();
            log.info("-------------netty启动成功--------端口{}", port);
        } catch (Exception e) {
            log.error("connection error",e.getMessage(), e);
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}

4.创建netty客户端信息接收器



import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import io.netty.channel.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


@Component
@Slf4j
@ChannelHandler.Sharable
public class ClientMessageHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //把数据解析转成字符串
        ByteBuf in = (ByteBuf) msg;
        String str= in.toString(CharsetUtil.UTF_8);
        log.info("接收到数据: "+str);
//         返回请求结果
        Channel channel = ctx.channel();
        channel.writeAndFlush(JSONUtil.toJsonStr(str));
    }
    
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
    }
    
//只要Netty抛出错误就会执行,Netty断会开连接会抛出连接超时的错误
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.info("关闭通道");
        cause.printStackTrace();
        ctx.close();
    }

}

5.启动项目用main方法测试

 public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 20004);
    socket.getOutputStream().write("[netty,2022-10-21 14:12:09]".getBytes("UTF-8"));
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值