实现简单的Http服务器+SpringMvc,集成到Spring

实现简单的Http服务器+SpringMvc,集成到Spring
1、Http协议
1.1、HTTP 协议请求格式
方法 + 空格 + URL + 空格 + 版本 + 回车符 + 换行符

头部域名称:头部域值                 + 回车符 + 换行符

...

头部域名称:头部域值                 + 回车符 + 换行符

回车符 + 换行符

请求数据

利用Tcp接收一条Http请求数据如下:

GET /task/findAll?a=b HTTP/1.1
Host: localhost:8081
Connection: keep-alive
sec-ch-ua: "Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9


完全符合上面的http协议的格式,反过来,可以根据上面的协议格式,解析Http的参数和需要的字段。

解析完后的实体如下:

{
    "headers": {
        "Accept": " text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "Connection": " keep-alive",
        "User-Agent": " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
        "Sec-Fetch-Site": " none",
        "Sec-Fetch-Dest": " document",
        "Host": " localhost",
        "Accept-Encoding": " gzip, deflate, br",
        "content-Type": "application/x-www-form-urlencoded",
        "Sec-Fetch-Mode": " navigate",
        "sec-ch-ua": " \"Google Chrome\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"",
        "sec-ch-ua-mobile": " ?0",
        "Cache-Control": " max-age=0",
        "Upgrade-Insecure-Requests": " 1",
        "sec-ch-ua-platform": " \"Windows\"",
        "Sec-Fetch-User": " ?1",
        "Accept-Language": " zh-CN,zh;q=0.9"
    },
    "methodName": "GET",
    "protocol": "HTTP",
    "queryString": {
        "a": "b"
    },
    "uri": "/task/findAll",
    "version": "1.1"
}
1.2、http协议相应格式
版本 + 空格 + 状态码 + 空格 + 原因短句 + 回车符 + 换行符

头部域名称:头部域值                             + 回车符 + 换行符

...

头部域名称:头部域值                             + 回车符 + 换行符

回车符 + 换行符

相应正文
1.3、请求及相应
public class Test {

    public static void main(String[] args) {
        HttpInvoke httpInvoke = new HttpInvoke() {
            @Override
            public Object invoke(RequestEntity entity) {
                return "hello";
            }
        };

        BootstrapServer bootstrapServer = new BootstrapServer(8081, httpInvoke);
    }
}
// HttpInvoke作为请求的回调,这里只做简单的回应"hello",启动8081

在这里插入图片描述

传送门(在httptest包下)

2、SpringMvc
2.1、扫描组件包

扫描组件包,将每个接口请求封装成MethodHandler

Properties prop = PropertyUtils.getClassPathProperties(MVC_CLASSPATH_NAME);
packageScanner = new GenericPackagesScanner(ctx.getPackages());
// 1、找到被controller注解标记的类
Set<Class<?>> classes = packageScanner.getFullyQualifiedClassNameList();
Set<Class<?>> webSet = new HashSet<>();
Iterator<Class<?>> iterator = classes.iterator();
while (iterator.hasNext()) {
    Class<?> next = iterator.next();
    if(AnnotationUtils.containsAnyAnnotation(next, ControllerVax.class)) {
        webSet.add(next);
    }
}
// 2、解析处理方法
Iterator<Class<?>> controller = webSet.iterator();
List<MethodHandler> handlers = new ArrayList<>();
while (controller.hasNext()) {
    Class<?> next = controller.next();
    String commonUrl = AnnotationUtils.get(next, UrlMapping.class);
    List<Method> methods = ClassUtils.getMarkedMethod(next, UrlMapping.class);
    Iterator<Method> methodIt = methods.iterator();
    while (methodIt.hasNext()) {
        Method method = methodIt.next();
        String subUri = AnnotationUtils.get(method, UrlMapping.class);
        MethodHandler methodHandler = new MethodHandler();
        methodHandler.setMethod(method);
        methodHandler.setMethodURL(subUri);
        methodHandler.setClazz(next);
        methodHandler.setClazzUrl(commonUrl);
        methodHandler.setObj(ctx.getBean(next));
        methodHandler.setUrl(PathUtils.merge(commonUrl, subUri));
        methodHandler.setParameters(ClassUtils.getMethodParameters(method));
        if(handlers.contains(methodHandler)) {
        throw new MappingExistsException("method mapping exists");
        }
        handlers.add(methodHandler);
    }
}
2.2、匹配请求

遍历所有的MethodHandler,如果接口上的uri和请求中的uri一直,则将参数带进去执行,并将结果返回。

Iterator<MethodHandler> iterator = handlers.iterator();
        while (iterator.hasNext()) {
            // 接口方法
            MethodHandler handler = iterator.next();
            if(StringUtils.equals(handler.getUrl(), entity.getUri())) {
                // controller实例
                Object bean = ctx.getBean(handler.getClazz());
                Method method = handler.getMethod();
                List<String> parameters = handler.getParameters();
                List<Parameter> parameterType = Arrays.asList(method.getParameters());
                Object[] parameterVal = new Object[parameters.size()];
                for (int i = 0; i < parameters.size(); i++) {
                    // 1、queryString
                    Map<String, String> queryString = entity.getQueryString();
                    if(queryString != null && queryString.size() > 0) {
                        parameterVal[i] = ObjectUtils.firstNotNull(queryString.get(parameters.get(i)));
                    }
                    // 2、body-json/form-data
                    Map<String, String> body = (Map<String, String>) entity.getBody();
                    if(body != null && body.size() > 0) {
                        parameterVal[i] = ObjectUtils.firstNotNull(body.get(parameters.get(i)));
                    }
                    if(!ObjectUtils.isSimpleType(parameterType.get(i).getType()) && StringUtils.equalsIgnore(entity.getContentType(), Constants.JSON_CONTENT_TYPE_VAL)) {
                        parameterVal[i] = JSON.parseObject(entity.getBody().toString(), parameterType.get(i).getType());
                    }
                }
                return ObjectUtils.invoke(bean, method, parameterVal);
            }
        }
3、Spring集成Mybatis

mybatis的代理对象,作为Spring组件,注入到容器中

JdbcManager jdbcManager = new JdbcManager(getJdbcProperties());
packageScanner.setPackages(ctx.getPackages());
this.classes = packageScanner.getFullyQualifiedClassNameList();
Iterator<Class<?>> iterator = this.classes.iterator();
// 2、移除没有被注解标记的类
while (iterator.hasNext()) {
    Class<?> clazz = iterator.next();
    if(!AnnotationUtils.containsAnyAnnotation(clazz, GlobalConstants.MAPPER_ANNOTATIONS)) {
        iterator.remove();
        continue;
    }
    ctx.registry(clazz.getSimpleName(), ProxyUtils.getProxy(clazz, new MapperProxyFactory(jdbcManager)));
}
ctx.refresh(false);
4、运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
传送门

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/219270.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【部署】Deploying Trino on linux

文章目录 一. Requirements1. Linux operating system2. Java 环境3. Python 二. Installing Trino三. Configuring Trino1. 节点配置2. JVM 配置3. Config properties4. Log levels5. Catalog properties 四. Running Trino 一. Requirements 1. Linux operating system 64位…

鸿蒙Harmony开发初探

一、背景 9月25日华为秋季全场景新品发布会&#xff0c;余承东宣布鸿蒙HarmonyOS NEXT蓄势待发&#xff0c;不再支持安卓应用。网易有道、同程旅行、美团、国航、阿里等公司先后宣布启动鸿蒙原生应用开发工作。 二、鸿蒙Next介绍 HarmonyOS是一款面向万物互联&#xff0c;全…

查询绑定了所有id的name

1、如图&#xff0c;绑定了所有id的有A,B两个name 2、第一种Sql及效率 explain SELECT name,count(id) as count from test GROUP BY name HAVING count(id)(SELECT count(DISTINCT id) from test); 3、第二种sql及效率 explain select * from (SELECT name,count(id) as co…

软著项目推荐 深度学习的智能中文对话问答机器人

文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分&#xff1a;4.2 损失函数&#xff1a;4.3 搭建seq2seq框架&#xff1a;4.4 测试部分&#xff1a;4.5 评价NLP测试效果&#xff1a;4.6 梯度截断…

柔性线路板市场分析:预计2028年将达到221亿美元

柔性电路板又称“软板”&#xff0c;是用柔性的绝缘基材制成的印刷电路。柔性电路提供优良的电性能&#xff0c;能满足更小型和更高密度安装的设计需要&#xff0c;也有助于减少组装工序和增强可靠性。柔性电路板是满足电子产品小型化和移动要求的惟一解决方法。可以自由弯曲、…

360公司-2019校招笔试-Windows开发工程师客观题合集解析

360公司-2019校招笔试-Windows开发工程师客观题合集 API无法实现进程间数据的相互传递是PostMessage2.以下代码执行后,it的数据为(异常) std::list<int> temp; std::list<int>::iterator it = temp.begin(); it = --it; 3.API在失败时的返回值跟其他不一样是 …

会话 cookie 及隐私的那些事

什么是会话 Cookie? 会话 Cookie 的概念非常简单。 会话 Cookie,也称为临时 Cookie 或内存 Cookie,是网站在浏览会话期间存储在用户计算机或设备上的小数据片段。 它是由网站生成并由您的浏览器存储和使用的多种 Cookie 之一。 常规 Cookie 或“持久”Cookie 是通常在您的…

Ant Design Vue 年选择器

文章目录 参考文档效果展示实现过程 参考文档 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; DatePicker 日期选择框 大佬&#xff1a;搬砖小匠&#xff08;Ant Design vue 只选择年&#xff09; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案…

Django宠物之家平台

摘 要 随着互联网的快速发展&#xff0c;利用网络的管理系统也逐渐发展起来。在线管理模式快速融入了众多用户的眼球&#xff0c;从而产生了各种各样的平台管理系统。 关于本django宠物的家庭平台管理系统的设计来说&#xff0c;系统开发主要采纳Python技术、B/S框架&#xff…

几何对象的凸点集

// 引入VTK并初始化 #include "vtkAutoInit.h" VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkActor.h> #include <vtkCamera.h> #include <vtkConvexPointSet.h> #include <vtkDataSetMapper.h&g…

工程化使用React

安装 首先全局安装 npm install create-react-app -g创建项目 create-react-app proName最基本的一个react工程化创建完成 项目目录

zabbix的自动发现机制:

zabbix的自动发现机制: zabbix客户端主动的和服务端联系&#xff0c;将自己的地址和端口发送给服务端&#xff0c;实现自动添加监控主机 客户端是主动的一方 缺点&#xff1b;如果自定义网段中主机数量太多&#xff0c;等级耗时会很久&#xff0c;而且这个自动发现机制不是很…

从图片或PDF文件识别表格提取内容的简单库img2table

img2table是一个基于OpenCV 图像处理的用于 PDF 和图像的表识别和提取 Python库。由于其设计基于神经网络的解决方案&#xff0c;提供了一种实用且更轻便的替代方案&#xff0c;尤其是在 CPU 上使用时。 该库的特点&#xff1a; 识别图像和PDF文件中的表格&#xff0c;包括在表…

RabbitMQ 详解

文章目录 MQ 简介1、简介2、MQ优缺点3、MQ应用场景4、AMQP 和 JMS5、常见的 MQ 产品 RabbitMQ 工作原理Linux 环境安装 RabbitMQ1、rmp安装法1.1 安装1.2 开启管理界面1.3 启动与停止1.4 创建新用户 2、docker安装法2.1 安装2.2 下载rabbitmq_delayed_message_exchange插件 Rab…

学习pytorch17 pytorch模型保存及加载

pytorch模型保存及加载 代码 import torch import torchvisionvgg16 torchvision.models.vgg16(pretrainedFalse)# 1. save model 1 保存模型结构及模型参数 torch.save(vgg16, ./vgg16_save1.model)# 2. save model 2 只保存模型参数 比第一种保存方法保存的文件要小 t…

微信小程序云开发报错

微信小程序云开发报错 起因是云开发报了个错误&#xff1a; fail: Error: cloud.callFunction:fail Error: errCode: -501000 | errMsg: [100003] env not exists (f8c78dea-9f77-43cf-9e7f-88c85f2a0795) (callId: 1701747734223-0.895078767368265) (trace: 11:42:14 star…

在eclipse中安装python插件:PyDev

在eclipse中安装插件PyDev&#xff0c;就可以在eclipse中开发python了。 PyDev的官网&#xff1a;https://www.pydev.org/ 不过可以直接在eclipse中用Marketplace安装&#xff08;备注&#xff1a;有可能一次安装不成功&#xff0c;是因为下载太慢了&#xff0c;多试几次&…

golang开发之个微机器人开发

请求URL&#xff1a; http://域名地址/sendFile 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wId是string登录实例标识wcId是string接收…

InST论文复现

论文地址&#xff1a;https://arxiv.org/abs/2211.13203 论文git&#xff1a;https://github.com/zyxElsa/InST 遇到的问题&#xff1a; 1.requests.exceptions.SSLError: HTTPSConnectionPool(hosthuggingface.co, port443): Max retries exceeded with url: /openai/clip-…

万兆光模块:单模光纤和多模光纤的选择指南

随着网络技术的不断发展&#xff0c;数据传输的速度也越来越快。在这样的背景下&#xff0c;万兆光模块逐渐成为了数据中心和网络设备的必备组件。而在选择万兆光模块时&#xff0c;用户通常会面临一个难题&#xff1a;选择单模还是多模&#xff1f;本文易天光通信将为您解析。…