设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间20 现在时间20 缓存数据 和聪明人交流,和靠谱的人恋爱,和进取的人共事,和幽默的人随行。晚安!

和聪明人交流,和靠谱的人恋爱,和进取的人共事,和幽默的人随行。晚安!

查看: 739|回复: 1

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:204
  • 打卡月天数:0
  • 打卡总奖励:3089
  • 最近打卡:2023-08-27 04:12:22
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
379
主题
355
精华
0
金钱
4221
积分
760
注册时间
2022-12-23
最后登录
2025-8-28

发表于 2025-8-28 02:38:19 | 显示全部楼层 |阅读模式

概述

  1. ODataSpringBootService.processODataRequest()
复制代码
方法中,OData框架核心组件初始化是整个请求处理流程的关键步骤。这个过程包含两个核心组件的创建:OData实例ServiceMetadata服务元数据

  1. // OData framework initialization - same pattern as CarsServlet
  2. OData odata = OData.newInstance();ServiceMetadata serviceMetadata = odata.createServiceMetadata(
  3. new SpringBootEdmProvider(),
  4. new ArrayList<>()
  5. );
复制代码

第一步:OData实例创建

1.1 OData.newInstance() 详细分析

  1. OData odata = OData.newInstance();
复制代码

核心作用

  • 工厂方法模式:通过静态工厂方法创建OData框架的核心入口点
  • 单例保证:确保OData实例的统一性和资源管理
  • 框架初始化:初始化Apache Olingo OData框架的核心组件

内部机制

  1. // Apache Olingo框架内部实现逻辑(简化版)
  2. public static OData newInstance() {
  3. return new ODataImpl();
  4. }
复制代码

提供的核心能力

1.1.1 序列化器工厂

  1. // JSON序列化器
  2. ODataSerializer jsonSerializer = odata.createSerializer(ContentType.JSON);
  3. // XML序列化器
  4. ODataSerializer xmlSerializer = odata.createSerializer(ContentType.APPLICATION_XML);
  5. // ATOM序列化器
  6. ODataSerializer atomSerializer = odata.createSerializer(ContentType.APPLICATION_ATOM_XML);
复制代码

1.1.2 反序列化器工厂

  1. // 请求体反序列化
  2. ODataDeserializer deserializer = odata.createDeserializer(ContentType.JSON);
复制代码

1.1.3 URI解析器

  1. // OData URI解析和验证
  2. UriInfo uriInfo = odata.createUriHelper().parseUri(uri, serviceMetadata);
复制代码

1.1.4 HTTP处理器工厂

  1. // HTTP请求处理器创建
  2. ODataHttpHandler handler = odata.createHandler(serviceMetadata);
复制代码

第二步:ServiceMetadata服务元数据创建

2.1 createServiceMetadata() 方法分析

  1. ServiceMetadata serviceMetadata = odata.createServiceMetadata(
  2. new SpringBootEdmProvider(), // EDM提供者
  3. new ArrayList<>() // 引用列表
  4. );
复制代码

参数详解

2.1.1 SpringBootEdmProvider - 实体数据模型提供者

核心职责

  • 定义OData服务的数据结构(Schema)
  • 描述实体类型(EntityType)
  • 配置实体集合(EntitySet)
  • 建立实体容器(EntityContainer)

继承关系

  1. SpringBootEdmProvider extends CsdlAbstractEdmProvider
复制代码

2.1.2 引用列表 - new ArrayList<>()

作用

  • 用于复杂场景下的元数据引用管理
  • 支持跨服务的元数据引用
  • 在简单场景下为空列表

2.2 SpringBootEdmProvider 深度解析

1.jpeg

2.2.1 命名空间和标识符定义

  1. public static final String NAMESPACE = "org.apache.olingo.sample.springboot";
  2. public static final String CONTAINER_NAME = "SpringBootContainer";
  3. public static final FullQualifiedName CONTAINER = new FullQualifiedName(NAMESPACE, CONTAINER_NAME);
  4. // 实体类型
  5. public static final String ET_CAR_NAME = "Car";
  6. public static final FullQualifiedName ET_CAR_FQN = new FullQualifiedName(NAMESPACE, ET_CAR_NAME);
  7. // 实体集合
  8. public static final String ES_CARS_NAME = "Cars";
复制代码

设计意义

  • 全局唯一性:通过命名空间避免名称冲突
  • 类型安全:使用FullQualifiedName确保类型引用正确
  • 可维护性:集中管理所有标识符常量

2.2.2 核心方法实现分析

A. getEntityType() - 实体类型定义
  1. @Override
  2. public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException {
  3. if (entityTypeName.equals(ET_CAR_FQN)) {
  4. return getCarEntityType();
  5. }
  6. return null;
  7. }
复制代码

执行流程

  1. 类型匹配:检查请求的实体类型是否为Car
  2. 委托处理:调用私有方法构建具体的实体类型
  3. 返回结果:返回完整的CSDL实体类型定义

Car实体类型的详细构建

  1. private CsdlEntityType getCarEntityType() {
  2. // 1. 定义属性
  3. CsdlProperty id = new CsdlProperty().setName("Id")
  4. .setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName());
  5. CsdlProperty brand = new CsdlProperty().setName("Brand")
  6. .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName());
  7. CsdlProperty model = new CsdlProperty().setName("Model")
  8. .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName());
  9. CsdlProperty color = new CsdlProperty().setName("Color")
  10. .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName());
  11. CsdlProperty year = new CsdlProperty().setName("Year")
  12. .setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName());
  13. CsdlProperty price = new CsdlProperty().setName("Price")
  14. .setType(EdmPrimitiveTypeKind.Double.getFullQualifiedName());
  15. // 2. 定义主键
  16. CsdlPropertyRef propertyRef = new CsdlPropertyRef();
  17. propertyRef.setName("Id");
  18. // 3. 组装实体类型
  19. CsdlEntityType entityType = new CsdlEntityType();
  20. entityType.setName(ET_CAR_NAME);
  21. entityType.setProperties(Arrays.asList(id, brand, model, color, year, price));
  22. entityType.setKey(Collections.singletonList(propertyRef));
  23. return entityType;
  24. }
复制代码

属性映射对照表

属性名OData类型Java类型说明
IdInt32Integer主键,唯一标识
BrandStringString品牌名称
ModelStringString车型型号
ColorStringString颜色信息
YearInt32Integer生产年份
PriceDoubleDouble价格信息
B. getEntitySet() - 实体集合定义
  1. @Override
  2. public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) throws ODataException {
  3. if (entityContainer.equals(CONTAINER)) {
  4. if (entitySetName.equals(ES_CARS_NAME)) {
  5. return getCarEntitySet();
  6. }
  7. }
  8. return null;
  9. }
复制代码

执行逻辑

  1. 容器验证:确认请求来自正确的实体容器
  2. 集合匹配:检查实体集合名称是否为"Cars"
  3. 构建集合:创建Car实体集合定义

实体集合构建

  1. private CsdlEntitySet getCarEntitySet() {
  2. CsdlEntitySet entitySet = new CsdlEntitySet();
  3. entitySet.setName(ES_CARS_NAME); // 集合名称:Cars
  4. entitySet.setType(ET_CAR_FQN); // 集合类型:Car实体类型
  5. return entitySet;
  6. }
复制代码
C. getEntityContainer() - 实体容器定义
  1. @Override
  2. public CsdlEntityContainer getEntityContainer() throws ODataException {
  3. // 创建实体容器
  4. CsdlEntityContainer entityContainer = new CsdlEntityContainer();
  5. entityContainer.setName(CONTAINER_NAME);
  6. // 添加实体集合
  7. List<CsdlEntitySet> entitySets = new ArrayList<>();
  8. entitySets.add(getEntitySet(CONTAINER, ES_CARS_NAME));
  9. entityContainer.setEntitySets(entitySets);
  10. return entityContainer;
  11. }
复制代码

容器作用

  • 集合管理:管理所有实体集合
  • 服务入口:作为OData服务的根容器
  • URL映射:建立URL路径与实体集合的映射关系
D. getSchemas() - 模式定义
  1. @Override
  2. public List<CsdlSchema> getSchemas() throws ODataException {
  3. List<CsdlSchema> schemas = new ArrayList<>();
  4. CsdlSchema schema = new CsdlSchema();
  5. schema.setNamespace(NAMESPACE);
  6. // 添加实体类型
  7. List<CsdlEntityType> entityTypes = new ArrayList<>();
  8. entityTypes.add(getEntityType(ET_CAR_FQN));
  9. schema.setEntityTypes(entityTypes);
  10. // 添加实体容器
  11. schema.setEntityContainer(getEntityContainer());
  12. schemas.add(schema);
  13. return schemas;
  14. }
复制代码

模式结构

  1. Schema: org.apache.olingo.sample.springboot
  2. ├── EntityTypes
  3. │ └── Car (Id, Brand, Model, Color, Year, Price)
  4. └── EntityContainer: SpringBootContainer
  5. └── EntitySets
  6. └── Cars -> Car
复制代码

2.3 ServiceMetadata的内部构建过程

2.3.1 元数据验证

  1. ServiceMetadata serviceMetadata = odata.createServiceMetadata(edmProvider, references);
复制代码

内部验证步骤

  1. 模式验证:检查EDM模式的完整性和一致性
  2. 类型检查:验证所有实体类型定义的正确性
  3. 引用解析:处理跨模式的引用关系
  4. 约束检查:验证主键、外键等约束定义

2.4 生成的元数据结构

2.4.1 $metadata端点响应示例

当访问

  1. http://localhost:8080/cars.svc/$metadata
复制代码
时,会返回:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
  3. <edmx:DataServices>
  4. <Schema Namespace="org.apache.olingo.sample.springboot"
  5. xmlns="http://docs.oasis-open.org/odata/ns/edm">
  6. <!-- 实体类型定义 -->
  7. <EntityType Name="Car">
  8. <Key>
  9. <PropertyRef Name="Id"/>
  10. </Key>
  11. <Property Name="Id" Type="Edm.Int32"/>
  12. <Property Name="Brand" Type="Edm.String"/>
  13. <Property Name="Model" Type="Edm.String"/>
  14. <Property Name="Color" Type="Edm.String"/>
  15. <Property Name="Year" Type="Edm.Int32"/>
  16. <Property Name="Price" Type="Edm.Double"/>
  17. </EntityType>
  18. <!-- 实体容器定义 -->
  19. <EntityContainer Name="SpringBootContainer">
  20. <EntitySet Name="Cars" EntityType="org.apache.olingo.sample.springboot.Car"/>
  21. </EntityContainer>
  22. </Schema>
  23. </edmx:DataServices>
  24. </edmx:Edmx>
复制代码

2.4.2 服务文档结构

访问

  1. http://localhost:8080/cars.svc/
复制代码
时的服务文档:

  1. {
  2. "@odata.context": "$metadata",
  3. "value": [
  4. {
  5. "name": "Cars",
  6. "kind": "EntitySet",
  7. "url": "Cars"
  8. }
  9. ]
  10. }
复制代码

错误处理和调试

1. 常见错误类型

1.1 EDM提供者错误

  1. // 错误示例:实体类型未定义
  2. @Override
  3. public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) {
  4. // 忘记实现返回null,导致"Entity type not found"错误
  5. return null;
  6. }
复制代码

1.2 类型不匹配错误

  1. // 错误示例:类型引用错误
  2. CsdlProperty id = new CsdlProperty().setName("Id")
  3. .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); // 应该是Int32
复制代码

总结

2.jpeg

OData框架核心组件初始化是整个OData服务的基础,它完成了以下关键任务:

  1. 框架初始化:创建OData核心实例,提供序列化、URI解析等基础能力
  2. 元数据构建:通过EDM提供者定义完整的数据模型结构
  3. 服务配置:建立URL路径与数据操作的映射关系
  4. 类型系统:建立强类型的实体定义和验证机制

这个过程为后续的HTTP处理器创建和请求处理奠定了坚实的基础,是OData服务能够正确响应各种请求的前提条件。

参考代码

  • https://github.com/f304646673/odata/tree/main/java/Olingo-OData-5.0.0/samples/spring-boot-odata

到此这篇关于Olingo分析和实践之OData框架核心组件初始化的文章就介绍到这了,更多相关Olingo OData框架内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

  • 打卡等级:即来则安
  • 打卡总天数:27
  • 打卡月天数:0
  • 打卡总奖励:333
  • 最近打卡:2025-11-30 11:55:45
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
379
积分
56
注册时间
2023-1-21
最后登录
2025-11-30

发表于 1 小时前 | 显示全部楼层
路过,支持一下
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表