当前位置: 首页 > news >正文

内嵌服务器Netty Http Server

内嵌式服务器不需要我们单独部署,列如SpringBoot默认内嵌服务器Tomcat,它运行在服务内部。使用Netty 编写一个 Http 服务器的程序,类似SpringMvc处理http请求那样。举例:xxl-job项目的核心包没有SpringMvc的Controller层,客户端却可以发送http请求,好奇怪!!!其实xxl-job-core 内部使用Netty做了HttpServer。

package com.xxl.job.executor.test.dto;import lombok.Getter;
import lombok.Setter;/*** User: ldj* Date: 2024/10/11* Time: 11:23* Description: No Description*/
@Getter
@Setter
public class RequestDTO<T> {/*** 请求ur*/private String uri;/*** 请求参数*/private T param;
}

package com.xxl.job.executor.test.netty;import com.xxl.job.executor.test.handler.NettyHttpServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.timeout.IdleStateHandler;import java.util.concurrent.TimeUnit;/*** User: ldj* Date: 2024/10/11* Time: 10:57* Description: Netty Http服务*/
public class NettyHttpServer {public static void main(String[] args) {// 服务端口int port = 9990;// 接收请求线程池EventLoopGroup bossGroup = new NioEventLoopGroup();// 处理请求线程池EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childOption(ChannelOption.SO_KEEPALIVE, true).childHandler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel channel) throws Exception {channel.pipeline().addLast(new IdleStateHandler(0, 0, 30 * 3, TimeUnit.SECONDS)).addLast(new HttpServerCodec()).addLast(new HttpObjectAggregator(5 * 1024 * 1024)).addLast(new NettyHttpServerHandler(new BaseService())); // 自定义handler}});// bind 绑定端口,启动服务ChannelFuture future = bootstrap.bind(port).sync();System.out.println("remote server started!");future.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {try {// 关闭 EventLoopGroupworkerGroup.shutdownGracefully();bossGroup.shutdownGracefully();} catch (Exception e) {System.out.println(e.getMessage() + e);}}}
}
package com.xxl.job.executor.test.netty;/*** User: ldj* Date: 2024/10/11* Time: 12:55* Description: No Description*/
public class BaseService {public String test(String param) {return "netty http test--> " + param;}
}
package com.xxl.job.executor.test.handler;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxl.job.executor.test.dto.RequestDTO;
import com.xxl.job.executor.test.netty.BaseService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** User: ldj* Date: 2024/10/11* Time: 11:11* Description: 处理请求逻辑*/
public class NettyHttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {private static final Logger logger = LoggerFactory.getLogger(NettyHttpServerHandler.class);private BaseService baseService;public NettyHttpServerHandler(BaseService baseService) {this.baseService = baseService;}private static ThreadPoolExecutor executor = new ThreadPoolExecutor(200,300,5,TimeUnit.SECONDS,new LinkedBlockingQueue<>(2000),new DefaultThreadFactory("netty-http-server"),new ThreadPoolExecutor.AbortPolicy());@Overrideprotected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) throws Exception {RequestDTO<String> requestDTO = parseReqParam(fullHttpRequest);executor.execute(() -> {String response = getResponse(requestDTO);boolean keepAlive = HttpUtil.isKeepAlive(fullHttpRequest);writeToClient(channelHandlerContext, keepAlive, response);});}private void writeToClient(ChannelHandlerContext channel, boolean keepAlive, String response) {ByteBuf byteBuf = Unpooled.copiedBuffer(response, StandardCharsets.UTF_8);DefaultFullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,byteBuf);HttpHeaders headers = fullHttpResponse.headers();headers.set(HttpHeaderNames.CONTENT_TYPE,HttpHeaderValues.TEXT_HTML);headers.set(HttpHeaderNames.CONTENT_LENGTH,fullHttpResponse.content().readableBytes());if(keepAlive){headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);}channel.writeAndFlush(fullHttpResponse);}private String getResponse(RequestDTO<String> requestDTO) {String uri = requestDTO.getUri();String param = requestDTO.getParam();try {// 硬编码!更好的做法可参考SpringMvc的解析注解的value放进一个Map<url,Method>switch (uri){case "/test":return baseService.test(param);default:return "请求路径不存在!";}} catch (Exception e) {e.printStackTrace();return e.getMessage();}}private RequestDTO<String> parseReqParam(FullHttpRequest fullHttpRequest) throws JsonProcessingException {String uri = fullHttpRequest.uri();String param = null;logger.info("有参数uri:{}", uri);HttpMethod method = fullHttpRequest.method();if (HttpMethod.GET.equals(method)) {QueryStringDecoder decoder = new QueryStringDecoder(uri);Map<String, List<String>> parameters = decoder.parameters();param = new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(parameters);logger.info("parameters -> {}", param);uri = decoder.rawPath();logger.info("不带参数uri:{}", uri);}if (HttpMethod.POST.equals(method)) {String contentTypeValue = fullHttpRequest.headers().getAsString(HttpHeaderNames.CONTENT_TYPE);if(contentTypeValue.contains(HttpHeaderValues.APPLICATION_JSON.toString())){param = fullHttpRequest.content().toString(StandardCharsets.UTF_8);}}RequestDTO<String> reqData = new RequestDTO<>();reqData.setUri(uri);reqData.setParam(param);return reqData;}
}

相关文章:

内嵌服务器Netty Http Server

内嵌式服务器不需要我们单独部署&#xff0c;列如SpringBoot默认内嵌服务器Tomcat,它运行在服务内部。使用Netty 编写一个 Http 服务器的程序&#xff0c;类似SpringMvc处理http请求那样。举例&#xff1a;xxl-job项目的核心包没有SpringMvc的Controller层&#xff0c;客户端却…...

Maven打包运行,引入三方jar及打包,不导入本地库的方法

Maven打包运行&#xff0c;引入三方jar及打包&#xff0c;不导入本地库的方法 maven、打包、springboot、jar、本地、引入背景 业务系统要对接某硬件&#xff0c;需要用到其三方jar&#xff0c;maven官方仓库没有这个&#xff0c;我也没有maven&#xff0c;又不想mvn install…...

02复写零

复写零 我们先进行异地复写&#xff1a;代码如下 public class Test {public static void main(String[] args) {int []array {1,0,2,3,0,4};duplicateZeros(array);}public static void duplicateZeros(int[] arr) {int [] elemnew int[arr.length];for(int cur0,dest0;des…...

01-gcc编译c++过程

当然&#xff0c;可以为您简要概述GCC编译C程序的各个步骤及其对应的具体命令。 GCC编译C的四个主要步骤 预处理&#xff08;Preprocessing&#xff09;编译&#xff08;Compilation&#xff09;汇编&#xff08;Assembly&#xff09;链接&#xff08;Linking&#xff09; 1…...

互动式教育技术:Spring Boot师生共评作业管理系统

3系统分析 3.1可行性分析 通过对本师生共评的作业管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本师生共评的作业管理系统采用JAVA作为开发语言&…...

【云从】三、计算机网络基础

文章目录 1、网络2、网络通信2.1 IP地址2.2 子网掩码2.3 网关2.4 私有地址和公有地址2.5 NAT网络地址转换 3、网络架构及设备 1、网络 网络&#xff0c;即通过通信线路&#xff08;如光纤、网线&#xff09;和通信设备&#xff08;如路由器、光猫&#xff09;&#xff0c;将各…...

读书笔记《向上生长》关于记忆、链接的一些思考

摘录 NOTES 1.大脑非常低效&#xff0c;记性不好&#xff0c;还会自圆其说。很多成绩不好的学生绝大部分不记笔记&#xff0c;记了也不看。 2.注意力和肌肉一样&#xff0c;存在耗损&#xff0c;也可以通过锻炼来加强。 3. 所有知识必须链接到已经有的知识&#xff0c;到用的时…...

Kubesphere4.1版本创建应用Mysql并实现外网访问

目前Kubesphere4.1版本可查创建应用资料较少&#xff0c;特此记录作为参考。 目标 使用Kubesphere4.1完成Mysql服务部署并实现外网访问。 具体流程如下&#xff1a; 1.创建企业空间 2.创建项目 3.创建应用仓库 4.创建应用&#xff08;mysql&#xff09; 5.配置外网访…...

小猿口算跟风版——没想到吧,这也能暴力

前言 “接口也是口&#xff0c;算法也是算”&#xff0c;综合来看就是口算&#xff01; 看到全网都在炸鱼也忍不住来玩一玩… 参考了大佬的OCR版&#xff0c;试用后发现影响速度的最大卡点并不是识别速度等&#xff0c;而是““由于检测异常导致的等待”。 基于体验几局的感受…...

【RabbitMQ——消息应答机制——分布式事务解决方式】

1. RabbitMQ高级-消息确认机制的配置 NONE值是禁用发布确认模式&#xff0c;是默认值 CORRELATED值是发布消息成功到交换器后会触发回调方法&#xff0c;如1示例SIMPLE值经测试有两种效果&#xff0c;其一效果和CORRELATED值一样会触发回调方法&#xff0c;其二在发布消息成功…...

Android Studio Koala中Kotlin引入序列化Parcelable

找了一堆资料没有新构建序列化的方法&#xff0c;踩坑经历如下&#xff1a; 前提是使用Kotlin创建的项目 之前的build.gradle版本写法如下&#xff1a; 但是新版Android Studio Koala使用序列化模式发生了改变&#xff0c;如下&#xff1a; 测试成功如下&#xff1a; 发出来…...

安装postgresql和对应wal2json和pg_tm_aux插件避坑

1、安装原则&#xff1a;要用源码都用源码&#xff0c;要用yum都用yum 安装wal2json避坑 涉及的yum源&#xff0c;可以解决安装postgresql缺少依赖导致的wal2json和pg_tm_aux的报错问题 [centos-sclo-rh] nameCentOS-7 - SCLo rh baseurlhttps://mirrors.aliyun.com/centos/7/…...

OneDrive 全新时代:AI、生产力和回忆触手可及

OneDrive&#xff0c;无人不知&#xff0c;无人不晓。 无论您是在公司、家庭还是在通勤的路上&#xff0c;OneDrive 都能让您无缝管理文件、照片和回忆。OneDrive 受到 94% 的财富 500 强公司、数百万小型企业和无数个人的信赖&#xff0c;它正在改变世界协作、存储和连接的方…...

List子接口

1.特点&#xff1a;有序&#xff0c;有下标&#xff0c;元素可以重复 2.方法&#xff1a;包含Collection中的所有方法&#xff0c;还包括自己的独有的方法&#xff08;API中查找&#xff09; 还有ListIterator&#xff08;迭代器&#xff09;&#xff0c;功能更强大。 包含更多…...

快来了解 Java 内存数据库 H2,不要错过哦

H2 是一个用 Java 编写的开源关系型数据库管理系统&#xff0c;它具有小巧、快速、易于嵌入等特点。 H2 数据库可以以多种模式运行&#xff0c;包括嵌入式模式、服务器模式和内存模式。 在嵌入式模式下&#xff0c;H2 数据库直接嵌入到应用程序中&#xff0c;就像一个本地的库…...

基于Java的可携宠物酒店管理系统的设计与实现(论文+源码)_kaic

摘 要 随着社会经济的不断发‎‏展&#xff0c;现如今出行并住酒店的人越来越多&#xff0c;与之而来的是酒店行业的工作量日益增加&#xff0c;酒店的管理效率亟待提升。此外很多人出门旅游时会有携带宠物的情况&#xff0c;但是现如今酒店对宠物的限制&#xff0c;导致许多…...

吸毛效果好的宠物空气净化器分享,希喂、霍尼韦尔、米家实测

说起宠物空气净化器&#xff0c;几年前我可能会一脸鄙夷&#xff1a;为啥要花这种智商税冤枉钱&#xff1f; 直到之前养了一只猫&#xff0c;被家中乱飞的浮毛和滂臭的异味搞到头晕&#xff0c;于是作为i一个养宠的家电测评博主&#xff0c;索性对宠物空气净化器这玩意做了超级…...

Sqlite3入门看这一篇就够(超级详细,从零学起)

Sqlite3入门看这一篇就够(超级详细,从零学起) 一、SQLite3 基础1.1 SQLite3 的特点1.2 SQLite3 安装与使用1.2.1 debian操作系统安装SQLite31.2.2 window操作系统安装SQLite3二、下载 SQLite3三、配置 SQLite 环境四、使用 SQLite34.1. **创建数据库**:4.2. **常用命令**:…...

搭建知识库:助力大健康零售电商的快速发展

一、大健康零售电商行业的快速发展及其对知识库的需求 随着互联网技术的飞速发展和人们对健康意识的显著提升&#xff0c;大健康零售电商行业迎来了前所未有的发展机遇。这一行业不仅涵盖了传统零售业的商品销售&#xff0c;还融入了健康管理、健康咨询、健康数据分析等多元化…...

纠删码参数自适应匹配问题ECP-AMP实验方案(中)

6.方法设计 6.1.数据获取 为了收集不同的文件大小和纠删码参数对性能指标的影响&#xff0c;本文在Hadoop平台上进行了模拟实验。Hadoop是一种开源的分布式存储和计算框架&#xff0c;它可以支持不同类型的纠删码&#xff0c;并提供了一些应用程序接口和工具来测试和评估纠删…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...