Серия Netty (1): Springboot интегрирует Netty и реализует собственные протоколы.
Серия Netty (1): Springboot интегрирует Netty и реализует собственные протоколы.

Netty — это Java-фреймворк с открытым исходным кодом, предоставляемый JBOSS. Githubнезависимые проекты по。NettyОбеспечивает асинхронный、Платформа и инструменты для веб-приложений, управляемых событиями, для быстрой разработки высокопроизводительных、Высоконадежный веб-сервер и клиентские программы.

Другими словами, Netty — это среда программирования на стороне клиента и сервера, основанная на NIO. Использование Netty может гарантировать, что вы сможете быстро и легко разработать сетевое приложение, например приложение на стороне клиента или на стороне сервера, которое реализует определенное. протокол. Netty упрощает и оптимизирует процесс программирования и разработки сетевых приложений.

Springboot интегрирует Netty

Создайте новый проект Springboot, импортируйте в него пакет netty и используйте пакет fastjson для обработки jsonStr.

Язык кода:javascript
копировать
		<!-- netty -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.42.Final</version>
        </dependency>

        <!-- Обработка Json -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.16</version>
        </dependency>

Создайте файлы с информацией о конфигурации, связанные с Netty.

  1. ymlКонфигурациядокумент——application.yml
Язык кода:javascript
копировать
# netty Конфигурация
netty:
  # Количество потоков босса
  boss: 4
  # Количество рабочих потоков
  worker: 2
  # тайм-аут
  timeout: 6000
  # Основной порт сервера
  port: 18023
  # Резервный порт сервера
  portSalve: 18026
  # Адрес сервера
  host: 127.0.0.1
  1. nettyКонфигурация Класс сущности——NettyPropertiesиymlКонфигурациядокументобязательность проходить@ConfigurationProperties(prefix = "netty")Интерпретация аннотации КонфигурациядокументвnettyКонфигурация,Внедрение значений посредством отражения,В классе сущности должны быть предусмотрены соответствующие методы установки и получения.

@ConfigurationProperties(prefix = "netty")Соответствующий Класс сущности Имена атрибутов не обязательно должны быть одинаковыми.,Просто убедитесь, что атрибуты файла склейки строк «set» и имя метода установки совпадают.

Язык кода:javascript
копировать
@Configuration
@ConfigurationProperties(prefix = "netty")
public class NettyProperties {

    /**
     * Количество потоков босса
     */
    private Integer boss;

    /**
     * Количество рабочих потоков
     */
    private Integer worker;

    /**
     * тайм-аут
     */
    private Integer timeout = 30000;

    /**
     * Основной порт сервера
     */
    private Integer port = 18023;

    /**
     * Резервный порт сервера
     */
    private Integer portSalve = 18026;

    /**
     * Адрес сервера По умолчанию локально
     */
    private String host = "127.0.0.1";
	
	// setter、getter 。。。。
}
  1. Конфигурация в нетте,Привязка, связанная с netty. Настройки конфигурации Netty обычно запускается с Bootstrap.,Основная функция — Конфигурация всей программы Netty.,Соедините компоненты последовательно,Класс Bootstrap в Netty — это класс начальной загрузки клиентских программ.,ServerBootstrap — это класс начальной загрузки на стороне сервера.
Язык кода:javascript
копировать
@Configuration
@EnableConfigurationProperties
public class NettyConfig {
    final NettyProperties nettyProperties;

    public NettyConfig(NettyProperties nettyProperties) {
        this.nettyProperties = nettyProperties;
    }

    /**
     * пул потоков босса - для подключения клиента
     *
     * @return
     */
    @Bean
    public NioEventLoopGroup boosGroup() {
        return new NioEventLoopGroup(nettyProperties.getBoss());
    }

    /**
     * Пул рабочих потоков — для бизнес-обработки
     *
     * @return
     */
    @Bean
    public NioEventLoopGroup workerGroup() {
        return new NioEventLoopGroup(nettyProperties.getWorker());
    }

    /**
     * Лаунчер сервера, прослушивание подключения клиента
     *
     * @return
     */
    @Bean
    public ServerBootstrap serverBootstrap() {
        ServerBootstrap serverBootstrap = new ServerBootstrap()
                // Укажите группу потоков для использования
                .group(boosGroup(), workerGroup())
                // Укажите канал для использования
                .channel(NioServerSocketChannel.class)
                // обозначениетайм-аут
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, nettyProperties.getTimeout())
                // Укажите рабочий процессор
                .childHandler(new NettyServerHandler());
        return serverBootstrap;
    }
}
  1. рабочий процессор, канал инициализации и процессор конфигурации, соответствующий конвейеру Индивидуальные##@##сепаратор,проходитьDelimiterBasedFrameDecoderДля решения проблемы распаковки и окрашивания; проходитьMessageDecodeHandlerДекодируйте и обрабатывайте полученные сообщения в экземпляры объектов.; проходитьMessageEncodeHandlerДобавить сообщение для отправкисепараторобъединить позжекодирование; наконецпроходитьServerListenerHandlerв соответствии с Тип сообщения Соответствующая обработка различных сообщений。
Язык кода:javascript
копировать
public class NettyServerHandler extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        // данныесепаратор        String delimiterStr = "##@##";
        ByteBuf delimiter = Unpooled.copiedBuffer(delimiterStr.getBytes());
        ChannelPipeline pipeline = socketChannel.pipeline();
        // Используйте специальную обработку распаковки/погружения и максимальную длину 1024 байта на поиск.
        pipeline.addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
        // Перекодируйте данные, декодированные на предыдущем шаге, в экземпляр сообщения.
        pipeline.addLast(new MessageDecodeHandler());
        // Закодируйте данные отправляющего клиента и добавьте разделитель данных.
        pipeline.addLast(new MessageEncodeHandler(delimiterStr));
        // Окончательная обработка данных
        pipeline.addLast(new ServerListenerHandler());
    }
}
  1. декодирование данных, декодирование и кодирование данных в формате UTF8.
Язык кода:javascript
копировать
public class MessageDecodeHandler extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) throws Exception {
        ByteBuf frame = in.retainedDuplicate();
        final String content = frame.toString(CharsetUtil.UTF_8);
        Message message = new Message(content);
        list.add(message);
        in.skipBytes(in.readableBytes());
    }
}
  1. данные Пример преобразования декодирования Класс Message используется для передачи сообщений и их преобразования в JsonString.
Язык кода:javascript
копировать
public class Message {
    /**
     * данныедлина     */
    private Integer len;

    /**
     * Информационные бюллетени, полученные databody
     */
    private String content;

    /**
     * Тип сообщения
     */
    private Integer msgType;

    public Message(Object object) {
        String str = object.toString();
        JSONObject jsonObject = JSONObject.parseObject(str);
        msgType = Integer.valueOf(jsonObject.getString("msg_type"));
        content = jsonObject.getString("body");
        len = str.length();
    }

    public String toJsonString() {
        return "{" +
                "\"msg_type\": " + msgType + ",\n" +
                "\"body\": " + content +
                "}";
    }
	// setter、getter 。。。。
}
  1. данныекодирование Когда сервер Netty отвечает на сообщение, он добавляет к сообщению разделитель и кодирует его в JsonString.
Язык кода:javascript
копировать
public class MessageEncodeHandler extends MessageToByteEncoder<Message> {
    // данныесепаратор    String delimiter;

    public MessageEncodeHandler(String delimiter) {
        this.delimiter = delimiter;
    }

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Message message, ByteBuf out) throws Exception {
        out.writeBytes((message.toJsonString() + delimiter).getBytes(CharsetUtil.UTF_8));
    }
}
  1. данныепроцессор,Классифицированная обработка для разных типов данных. Перечислимые типы используются при обработке разных типов полученных данных.,При использовании переключателя вы можете сделать следующее,Конкретный ссылочный код,Здесь мы только демонстрируем, как работать,Бизнес-класс обработки данных не реализован.
Язык кода:javascript
копировать
public class ServerListenerHandler extends SimpleChannelInboundHandler<Message> {
    private static final Logger log = LoggerFactory.getLogger(ServerListenerHandler.class);

    /**
     * Обрабатывается, когда устройство подключено к сети
     *
     * @param ctx
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        log.info("Появились новые соединения: [{}]",ctx.channel().id().asLongText());
    }

    /**
     * данные не указаны
     *
     * @param ctx
     * @param сообщение
     */
    @Override
    защищенный недействительный каналRead0 (ChannelHandlerContext ctx, Message msg) {
        // Получить тело сообщения в экземпляре сообщения
        String content = msg.getContent();
        // к другому типу сообщения для обработки
        MessageEnum type = MessageEnum.getStructureEnum(msg);
        switch (type) {
            case CONNECT:
                // TODO Обработка сообщений Heartbeat
            case STATE:
                // TODO Статус устройства
            default:
                System.out.println(type.content + «Содержимое сообщения» + content);
        }
    }

    /**
     * Автономная обработка оборудования
     *
     * @param ctx
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        log.info("Устройство не в сети: {}", ctx.channel().id().asLongText());
    }

    /**
     * Устройство поддерживает обработку исключений
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Исключение печати
        log.info("Исключение: {}", cause.getMessage());
        // закрытиесоединять        ctx.close();
    }
}
  1. Класс перечисления типов данных
Язык кода:javascript
копировать
public enum MessageEnum {
    CONNECT(1, «Сердцевое сообщение»),
    STATE(2, "Статус устройства");

    public final Integer type;
    public final String content;

    MessageEnum(Integer type, String content) {
        this.type = type;
        this.content = content;
    }

    // Используйте суждение в случае
    public static MessageEnum getStructureEnum(Message msg) {
        Integer type = Optional.ofNullable(msg)
                .map(Message::getMsgType)
                .orElse(0);
        if (type == 0) {
            return null;
        } else {
            List<MessageEnum> objectEnums = Arrays.stream(MessageEnum.values())
                    .filter((item) -> item.getType() == type)
                    .distinct()
                    .collect(Collectors.toList());
            if (objectEnums.size() > 0) {
                return objectEnums.get(0);
            }
            return null;
        }
    }
	// setter、getter。。。。
}

На этом этапе вся настройка Netty завершена, но если вы хотите запустить ее с помощью Springboot, вам все равно потребуется выполнить некоторую настройку.

  1. класс запуска netty Конфигурация
Язык кода:javascript
копировать
@Component
public class NettyServerBoot {
    private static final Logger log = LoggerFactory.getLogger(NettyServerBoot.class);
    @Resource
    NioEventLoopGroup boosGroup;
    @Resource
    NioEventLoopGroup workerGroup;
    final ServerBootstrap serverBootstrap;
    final NettyProperties nettyProperties;

    public NettyServerBoot(ServerBootstrap serverBootstrap, NettyProperties nettyProperties) {
        this.serverBootstrap = serverBootstrap;
        this.nettyProperties = nettyProperties;
    }


    /**
     * Запустить нетти
     *
     * @throws InterruptedException
     */
    @PostConstruct
    public void start() throws InterruptedException {
        // Привязать начало порта
        serverBootstrap.bind(nettyProperties.getPort()).sync();
        // Альтернативный порт
        serverBootstrap.bind(nettyProperties.getPortSalve()).sync();
        log.info("Запустите Netty: {},{}", nettyProperties.getPort(), nettyProperties.getPortSalve());
    }

    /**
     * Закрыть нетти
     */
    @PreDestroy
    public void close() {
        log.info("Закрыть Netty");
        boosGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

После добавления конфигурации NettyServerBoot при запуске приложения сервер Netty будет запущен вместе.

В то же время служба netty будет уничтожена до закрытия Springboot.

Полный исходный код

github.com/BerBai/Java…

boy illustration
Учебное пособие по Jetpack Compose для начинающих, базовые элементы управления и макет
boy illustration
Код js веб-страницы, фон частицы, код спецэффектов
boy illustration
【новый! Суперподробное】Полное руководство по свойствам компонентов Figma.
boy illustration
🎉Обязательно к прочтению новичкам: полное руководство по написанию мини-программ WeChat с использованием программного обеспечения Cursor.
boy illustration
[Забавный проект Docker] VoceChat — еще одно приложение для мгновенного чата (IM)! Может быть встроен в любую веб-страницу!
boy illustration
Как реализовать переход по странице в HTML (html переходит на указанную страницу)
boy illustration
Как решить проблему зависания и низкой скорости при установке зависимостей с помощью npm. Существуют ли доступные источники npm, которые могут решить эту проблему?
boy illustration
Серия From Zero to Fun: Uni-App WeChat Payment Practice WeChat авторизует вход в систему и украшает страницу заказа, создает интерфейс заказа и инициирует запрос заказа
boy illustration
Серия uni-app: uni.navigateЧтобы передать скачок значения
boy illustration
Апплет WeChat настраивает верхнюю панель навигации и адаптируется к различным моделям.
boy illustration
JS-время конвертации
boy illustration
Обеспечьте бесперебойную работу ChromeDriver 125: советы по решению проблемы chromedriver.exe не найдены
boy illustration
Поле комментария, щелчок мышью, специальные эффекты, js-код
boy illustration
Объект массива перемещения объекта JS
boy illustration
Как открыть разрешение на позиционирование апплета WeChat_Как использовать WeChat для определения местонахождения друзей
boy illustration
Я даю вам два набора из 18 простых в использовании фонов холста Power BI, так что вам больше не придется возиться с цветами!
boy illustration
Получить текущее время в js_Как динамически отображать дату и время в js
boy illustration
Вам необходимо изучить сочетания клавиш vsCode для форматирования и организации кода, чтобы вам больше не приходилось настраивать формат вручную.
boy illustration
У ChatGPT большое обновление. Всего за 45 минут пресс-конференция показывает, что OpenAI сделал еще один шаг вперед.
boy illustration
Copilot облачной разработки — упрощение разработки
boy illustration
Микросборка xChatGPT с низким кодом, создание апплета чат-бота с искусственным интеллектом за пять шагов
boy illustration
CUDA Out of Memory: идеальное решение проблемы нехватки памяти CUDA
boy illustration
Анализ кластеризации отдельных ячеек, который должен освоить каждый&MarkerгенетическийВизуализация
boy illustration
vLLM: мощный инструмент для ускорения вывода ИИ
boy illustration
CodeGeeX: мощный инструмент генерации кода искусственного интеллекта, который можно использовать бесплатно в дополнение к второму пилоту.
boy illustration
Машинное обучение Реальный бой LightGBM + настройка параметров случайного поиска: точность 96,67%
boy illustration
Бесшовная интеграция, мгновенный интеллект [1]: платформа больших моделей Dify-LLM, интеграция без кодирования и встраивание в сторонние системы, более 42 тысяч звезд, чтобы стать свидетелями эксклюзивных интеллектуальных решений.
boy illustration
LM Studio для создания локальных больших моделей
boy illustration
Как определить количество слоев и нейронов скрытых слоев нейронной сети?
boy illustration
[Отслеживание целей] Подробное объяснение ByteTrack и детали кода