亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot如何集成Netty

 更新時(shí)間:2024年06月17日 17:01:19   作者:Sea-Man  
這篇文章主要介紹了SpringBoot如何集成Netty問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

一、pom依賴

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.77.Final</version>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.5.8</version>
</dependency>

二、配置yml文件

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

三、服務(wù)端

package com.tlxy.lhn.controller.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;

public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
        //創(chuàng)建兩個(gè)線程組bossGroup和workerGroup,含有的子線程N(yùn)ioEventLoop的個(gè)數(shù)默認(rèn)是CPU的兩倍
        //bossGroup只是處理連接請(qǐng)求,真正的和客戶端業(yè)務(wù)處理,會(huì)交給workerGroup完成
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup(1);

        try {
            //創(chuàng)建服務(wù)器端的啟動(dòng)對(duì)象
            ServerBootstrap bootstrap = new ServerBootstrap();
            //使用鏈?zhǔn)骄幊虂砼渲脜?shù)
            bootstrap.group(bossGroup, workerGroup)//設(shè)置兩個(gè)線程組
                    .channel(NioServerSocketChannel.class)//使用NioServerSocketChannel作為服務(wù)器的通道實(shí)現(xiàn)
                    //初始化服務(wù)器連接隊(duì)列大小,服務(wù)端處理客戶端連接請(qǐng)求是順序處理的,所以同一時(shí)間只能處理一個(gè)客戶端連接
                    //多個(gè)客戶端同時(shí)來的時(shí)候,服務(wù)端將不能處理的客戶端連接請(qǐng)求放在隊(duì)列中等待處理
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel channel) throws Exception {
                            //對(duì)workerGroup的SocketChannel設(shè)置處理器
                            channel.pipeline().addLast(new NettyServerHandler());
                        }
                    });

            System.out.println("netty server start..");

            //綁定一個(gè)端口并且同步生成一個(gè)ChannelFuture異步對(duì)象,通過isDone()等方法可以判斷異步事件的執(zhí)行情況
            //啟動(dòng)服務(wù)器(并綁定的端口),bind是異步操作,sync方法是等待異步操作執(zhí)行完畢
            ChannelFuture cf = bootstrap.bind(9000).sync();

            //給cf注冊(cè)監(jiān)聽器,監(jiān)聽我們關(guān)心的事件
            cf.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    if (cf.isSuccess()) {
                        System.out.println("監(jiān)聽端口9000成功");
                    } else {
                        System.out.println("監(jiān)聽端口9000失敗");
                    }
                }
            });
            //等待服務(wù)端監(jiān)聽端口關(guān)閉,closeFuture是異步操作
            //通過sync方法同步等待通道關(guān)閉處理完畢,這里會(huì)阻塞等待通道關(guān)閉完成,內(nèi)部調(diào)用的是Object的wait()方法
            cf.channel().closeFuture().sync();

        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }


    }
}

NettyServer類中的

channel.pipeline().addLast(new NettyServerHandler());

對(duì)應(yīng)以下的處理器。

package com.tlxy.lhn.controller.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("客戶端發(fā)送消息是:" + buf.toString(CharsetUtil.UTF_8));
        // 讀取byteBuf
        // 業(yè)務(wù)處理
        // 回消息給客戶端
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ByteBuf buf = Unpooled.copiedBuffer("HelloClient".getBytes(CharsetUtil.UTF_8));
        ctx.writeAndFlush(buf);
    }

    //只要Netty拋出錯(cuò)誤就會(huì)執(zhí)行,Netty斷會(huì)開連接會(huì)拋出連接超時(shí)的錯(cuò)誤
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.info("關(guān)閉通道");
        cause.printStackTrace();
        ctx.close();
    }
}

四、客戶端

package com.tlxy.lhn.controller.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class NettyClient {
    public static void main(String[] args) throws InterruptedException {
        //客戶端需要一個(gè)事件循環(huán)組
        NioEventLoopGroup group = new NioEventLoopGroup();

        try {
            //創(chuàng)建客戶端啟動(dòng)對(duì)象
            //注意客戶端使用的不是SocketBootstrap而是Bootstrap
            Bootstrap bootstrap = new Bootstrap();

            // 設(shè)置相關(guān)參數(shù)
            bootstrap.group(group) //設(shè)置線程組
                    .channel(NioSocketChannel.class)// 使用NioSocketChannel作為客戶端的通道實(shí)現(xiàn)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new NettyClientHandler());
                        }
                    });

            System.out.println("netty client start..");
            ChannelFuture cf = bootstrap.connect("127.0.0.1", 9000).sync();
            cf.channel().closeFuture().sync();
        }finally {
            group.shutdownGracefully();
        }


    }
}

NettyClient類中

ch.pipeline().addLast(new NettyClientHandler());

為處理器。

package com.tlxy.lhn.controller.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class NettyClientHandler extends ChannelInboundHandlerAdapter {

    /**
     * 客戶端連接標(biāo)識(shí)
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ByteBuf buf = Unpooled.copiedBuffer("HelloServer".getBytes(CharsetUtil.UTF_8));
        ctx.writeAndFlush(buf);
    }

    //當(dāng)通道建立后有事件時(shí)會(huì)觸發(fā),即服務(wù)端發(fā)送數(shù)據(jù)給客戶端
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("收到服務(wù)端的消息是:" + buf.toString(CharsetUtil.UTF_8));
        System.out.println("服務(wù)端地址是:" + ctx.channel().remoteAddress());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("關(guān)閉通道");
        cause.printStackTrace();
        ctx.close();
    }

}

五、粘包和拆包問題

客戶端和服務(wù)端都是固定的框架,我們只需寫處理器。

粘包和拆包問題,可以自己手寫通過固定長度發(fā)送數(shù)據(jù),或者使用Google的Protostuff。

<dependency>
    <groupId>com.dyuproject.protostuff</groupId>
    <artifactId>protostuff-api</artifactId>
    <version>1.0.8</version>
</dependency>
<dependency>
    <groupId>com.dyuproject.protostuff</groupId>
    <artifactId>protostuff-core</artifactId>
    <version>1.0.8</version>
</dependency>
<dependency>
    <groupId>com.dyuproject.protostuff</groupId>
    <artifactId>protostuff-runtime</artifactId>
    <version>1.0.8</version>
</dependency>
package com.tlxy.lhn.controller.netty;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ProtostuffUtil {
    private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<Class<?>, Schema<?>>();

    private static <T> Schema<T> getSchema(Class<T> clazz) {
        @SuppressWarnings("unchecked")
        Schema<T> schema = (Schema<T>) cachedSchema.get(clazz);
        if (schema == null) {
            schema = RuntimeSchema.getSchema(clazz);
            if (schema != null) {
                cachedSchema.put(clazz, schema);
            }
        }
        return schema;
    }

    /**
     * 序列化
     *
     * @param obj
     * @return
     */
    public static <T> byte[] serializer(T obj) {
        @SuppressWarnings("unchecked")
        Class<T> clazz = (Class<T>) obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema<T> schema = getSchema(clazz);
            return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
    }

    /**
     * 反序列化
     *
     * @param data
     * @param clazz
     * @return
     */
    public static <T> T deserializer(byte[] data, Class<T> clazz) {
        try {
            T obj = clazz.newInstance();
            Schema<T> schema = getSchema(clazz);
            ProtostuffIOUtil.mergeFrom(data, obj, schema);
            return obj;
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 關(guān)于jpa?querydsl嵌套查詢demo

    關(guān)于jpa?querydsl嵌套查詢demo

    這篇文章主要介紹了關(guān)于jpa?querydsl?嵌套查詢demo,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • SpringBoot快速設(shè)置攔截器并實(shí)現(xiàn)權(quán)限驗(yàn)證的方法

    SpringBoot快速設(shè)置攔截器并實(shí)現(xiàn)權(quán)限驗(yàn)證的方法

    本篇文章主要介紹了SpringBoot快速設(shè)置攔截器并實(shí)現(xiàn)權(quán)限驗(yàn)證的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • Javaweb實(shí)現(xiàn)完整個(gè)人博客系統(tǒng)流程

    Javaweb實(shí)現(xiàn)完整個(gè)人博客系統(tǒng)流程

    這篇文章主要介紹了怎樣用Java來實(shí)現(xiàn)一個(gè)完整的個(gè)人博客系統(tǒng),我們通過實(shí)操上手的方式可以高效的鞏固所學(xué)的基礎(chǔ)知識(shí),感興趣的朋友一起來看看吧
    2022-03-03
  • springboot2.0?@Slf4j?log?彩色日志配置輸出到文件

    springboot2.0?@Slf4j?log?彩色日志配置輸出到文件

    這篇文章主要介紹了springboot2.0 @Slf4j log日志配置輸出到文件(彩色日志),解決方式是使用了springboot原生自帶的一個(gè)log框架,結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • SpringBoot學(xué)習(xí)系列之MyBatis Plus整合封裝的實(shí)例詳解

    SpringBoot學(xué)習(xí)系列之MyBatis Plus整合封裝的實(shí)例詳解

    MyBatis-Plus是一款MyBatis的增強(qiáng)工具(簡稱MP),為簡化開發(fā)、提高效率,這篇文章給大家介紹MyBatis Plus整合封裝的實(shí)例詳解,感興趣的朋友跟隨小編一起看看吧
    2020-08-08
  • Spring中的編程式事務(wù)和聲明式事務(wù)

    Spring中的編程式事務(wù)和聲明式事務(wù)

    Spring框架中,事務(wù)管理可以通過編程式事務(wù)和聲明式事務(wù)兩種方式實(shí)現(xiàn),編程式事務(wù)通過手動(dòng)編碼控制事務(wù)的開始、提交和回滾,允許開發(fā)者精確控制事務(wù),但增加了代碼復(fù)雜度,聲明式事務(wù)則通過@EnableTransactionManagement注解啟用事務(wù)管理
    2024-11-11
  • 記一次線程爆滿導(dǎo)致服務(wù)器崩潰的問題排查及解決

    記一次線程爆滿導(dǎo)致服務(wù)器崩潰的問題排查及解決

    這篇文章主要介紹了記一次線程爆滿導(dǎo)致服務(wù)器崩潰的問題排查及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • JavaSE系列基礎(chǔ)包裝類及日歷類詳解

    JavaSE系列基礎(chǔ)包裝類及日歷類詳解

    這篇文章主要介紹的是JavaSE中常用的基礎(chǔ)包裝類以及日歷類的使用詳解,文中的示例代碼簡潔易懂,對(duì)我們學(xué)習(xí)JavaSE有一定的幫助,感興趣的小伙伴快來跟隨小編一起學(xué)習(xí)吧
    2021-12-12
  • 深入了解Java中的過濾器Filter和監(jiān)聽器Listener

    深入了解Java中的過濾器Filter和監(jiān)聽器Listener

    這篇文章主要為大家詳細(xì)介紹了Java中的過濾器Filter和監(jiān)聽器Listener的使用以及二者的區(qū)別,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2022-06-06
  • 解決Shiro 處理ajax請(qǐng)求攔截登錄超時(shí)的問題

    解決Shiro 處理ajax請(qǐng)求攔截登錄超時(shí)的問題

    這篇文章主要介紹了解決Shiro 處理ajax請(qǐng)求攔截登錄超時(shí)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評(píng)論