netty(五) --netty与springBoot整合

简介

通常在项目中我们都是结合spring或者springboot使用netty,本章节介绍springboot整合netty。项目源码地址:https://github.com/itwwj/netty-learn.git中的netty-day06-boot项目。

一、依赖导入

    <properties>
        <netty_version>4.1.24.Final</netty_version>
    </properties>
 <dependencies>
         <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>${netty_version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.0.4.RELEASE</version>
        </dependency>
        <!-- test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.0.4.RELEASE</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

二、代码

netty启动类:

/**
 * netty服务端启动类
 *
 * @author jie
 */
@Data
@Slf4j
@Component
public class NettyServer {


    private EventLoopGroup boosGroup = new NioEventLoopGroup();
    private EventLoopGroup workerGroup = new NioEventLoopGroup();
    private Channel channel;

    @Autowired
    private ChannelInitializer initializer;

    public ChannelFuture init(int port) {
        ChannelFuture f=null;
        try {
            //用于启动NIO服务端的辅助启动类,目的是降低服务端的开发复杂度
            ServerBootstrap b = new ServerBootstrap();
            b.group(boosGroup, workerGroup)
                    //对应JDK NIO类库中的ServerSocketChannel
                    .channel(NioServerSocketChannel.class)
                    //配置NioServerSocketChannel的TCP参数
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //绑定I/O的事件处理类
                    .childHandler(initializer);
            //调用它的bind操作监听端口号,调用同步阻塞方法sync等待绑定操作完成
            f = b.bind(port).sync();
            channel = f.channel();
        } catch (InterruptedException e) {
            log.error(e.getMessage());
        }
        return f;
    }

    /**
     * 关闭
     */
    public void close() {
        if (null == channel) {
            return;
        }
        channel.close();
        boosGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

事件处理类:

/**
 * MyChannelInitializer的主要目的是为程序员提供了一个简单的工具,用于在某个Channel注册到EventLoop后,对这个Channel执行一些初始
 * 化操作。ChannelInitializer虽然会在一开始会被注册到Channel相关的pipeline里,但是在初始化完成之后,ChannelInitializer会将自己
 * 从pipeline中移除,不会影响后续的操作。
 *
 * @author jie
 */
@Slf4j
@Component
public class MyServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    /**
     * 这个方法在Channel被注册到EventLoop的时候会被调用
     *
     * @param socketChannel
     * @throws Exception
     */
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        log.info("=========有客户端连接服务器=========");
        log.info("ip:" + socketChannel.localAddress().getHostString() + "         port:" + socketChannel.localAddress().getPort());
        // 基于换行符号
        socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024));
        // 解码转String,注意调整自己的编码格式GBK、UTF-8
        socketChannel.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
        // 解码转String,注意调整自己的编码格式GBK、UTF-8
        socketChannel.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
        socketChannel.pipeline().addLast(new MyServerHandler());

    }
}

事件操作类:

/**
 * 操作类
 *
 * @author jie
 */
@Slf4j
public class MyServerHandler extends ChannelInboundHandlerAdapter {
    /**
     * 当客户端主动连接服务端,通道活跃后触发
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //在接收到客户端连接的时候通知客户端连接成功
        String msg = "与服务端建立连接成功" + new Date();
        ByteBuf buf = Unpooled.buffer(msg.getBytes().length);
        buf.writeBytes(msg.getBytes(CharsetUtil.UTF_8));
    }

    /**
     * 通道有消息触发
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "接收到消息:");
        log.info(msg.toString());
        ctx.writeAndFlush(msg);
    }

    /**
     * 当客户端主动断开连接,通道不活跃触发
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("===================客户端:" + ctx.channel().localAddress().toString() + " 断开连接===================");
    }

    /**
     * 当连接发生异常时触发
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //在发生异常时主动关掉连接
        ctx.close();
        log.error("发现异常:\r\n" + cause.toString());
    }
}

springboot启动类:

/**
 * @author jie
 */
@SpringBootApplication
public class NettyApplication implements CommandLineRunner {


    public static void main(String[] args) {
        SpringApplication.run(NettyApplication.class, args);
    }

    @Value("${netty.port}")
    private int port;
    @Autowired
    private NettyServer nettyServer;

    @Override
    public void run(String... args) throws Exception {
        ChannelFuture init = nettyServer.init(port);
        Runtime.getRuntime().addShutdownHook(new Thread(() -> nettyServer.close()));
        init.channel().closeFuture().syncUninterruptibly();
    }
}

web监控类:

/**
 * @author jie
 */
@Slf4j
@RestController
@RequestMapping("/netty")
public class NettyController {

    @Autowired
    private NettyServer nettyServer;

    @RequestMapping("/localAddress")
    public String localAddress() {
        return "tcp服务端地址:" + nettyServer.getChannel().localAddress();
    }

    @RequestMapping("/isOpen")
    public String isOpen() {
        if (nettyServer.getChannel().isOpen()){
            return "tcp服务已启动";
        }else {
            return "tcp服务未启动";
        }
    }

    @RequestMapping("/close")
    public String close() {
        if (nettyServer.getChannel().isOpen()) {
            nettyServer.close();
        }
        return "服务端关闭成功";
    }
}

配置文件application.yml:

netty:
  port: 1100
server:
  port: 5320

三 、测试

在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Spring Boot是一个非常流行的Java开发框架,而Netty-socketio是一个基于Netty框架的WebSocket实现,提供了方便的实时通信解决方案。将它们结合起来,可以实现高效的WebSocket通信服务。 下面是整合的步骤: 1. 添加依赖 在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>1.7.16</version> </dependency> ``` 2. 编写Netty-socketio服务 创建一个类,继承自SpringBoot的ApplicationListener接口,用于启动Netty-socketio服务。 ``` import com.corundumstudio.socketio.Configuration; import com.corundumstudio.socketio.SocketIOServer; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; @Component public class NettySocketIoServer implements ApplicationListener<ApplicationReadyEvent> { @Value("${socketio.host}") private String host; @Value("${socketio.port}") private Integer port; private SocketIOServer server; @Override public void onApplicationEvent(ApplicationReadyEvent event) { Configuration config = new Configuration(); config.setHostname(host); config.setPort(port); server = new SocketIOServer(config); server.start(); } } ``` 其中,@Value注解用于从配置文件中读取host和port的值,SocketIOServer是Netty-socketio提供的服务类,用于启动和管理WebSocket服务。 3. 配置WebSocket处理器 创建一个类,继承自Spring Boot的WebSocketHandler接口,用于处理WebSocket连接和消息。 ``` import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.SocketIOServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; @Component public class SocketIoHandler extends TextWebSocketHandler { @Autowired private SocketIOServer server; @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { super.afterConnectionEstablished(session); SocketIOClient client = server.getClient(session.getId()); if (client == null) { client = server.addClient(session); } } @Override public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { super.handleTextMessage(session, message); SocketIOClient client = server.getClient(session.getId()); if (client != null) { client.sendEvent("message", message.getPayload()); } } } ``` 其中,@Autowired注解用于从Spring容器中获取SocketIOServer实例,afterConnectionEstablished方法用于处理WebSocket连接建立时的逻辑,handleTextMessage方法用于处理WebSocket消息。 4. 配置WebSocket处理器映射 创建一个WebSocketHandlerRegistry类,用于配置WebSocket处理器的映射关系。 ``` import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Autowired private SocketIoHandler socketIoHandler; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(socketIoHandler, "/ws").setAllowedOrigins("*"); } } ``` 其中,@EnableWebSocket注解用于开启WebSocket支持,registerWebSocketHandlers方法用于配置WebSocket处理器映射关系。 5. 配置application.yml 在application.yml文件中添加以下配置: ``` socketio: host: localhost port: 8080 ``` 其中,host和port的值应与Netty-socketio服务的配置一致。 6. 运行程序 现在,可以运行程序,并访问http://localhost:8080/ws,即可建立WebSocket连接。发送消息时,可以使用socket.emit()方法,接收消息时,可以使用socket.on()方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值