Skip to content

michaelwang123/odata

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OData Java 学习示例项目

这是一个使用 Java 和 Apache Olingo 实现的 OData 服务示例项目,包含详细的中文注释,帮助理解 OData 的核心概念。

什么是 OData?

OData(Open Data Protocol,开放数据协议)是一种基于 REST 的协议,用于构建和使用数据 API。

OData 的核心概念

  1. Entity Type(实体类型)

    • 定义数据的结构,类似于数据库中的表结构
    • 例如:Car 实体类型定义了汽车的数据结构
  2. Entity Set(实体集)

    • 实体类型的集合,类似于数据库中的表
    • 例如:Cars 实体集包含多个 Car 实体
  3. Property(属性)

    • 实体的字段,如 Car 的 id、model、manufacturer 等
  4. Key(键)

    • 唯一标识实体的属性,如 Car 的 id
  5. EDM(Entity Data Model,实体数据模型)

    • OData 的元数据模型,描述了服务的数据结构
    • 客户端可以通过 /$metadata 端点获取 EDM 定义

项目结构

odata/
├── pom.xml                                    # Maven 配置文件
├── README.md                                  # 项目说明文档
└── src/
    └── main/
        ├── java/
        │   └── com/
        │       └── odata/
        │           └── demo/
        │               ├── model/
        │               │   └── Car.java                    # 实体模型类
        │               ├── provider/
        │               │   └── CarEdmProvider.java         # EDM 元数据提供者
        │               ├── processor/
        │               │   ├── CarEntityCollectionProcessor.java  # 实体集合处理器
        │               │   ├── CarEntityProcessor.java            # 实体处理器
        │               │   └── CarPrimitiveProcessor.java         # 原始值处理器
        │               ├── service/
        │               │   └── CarService.java             # 业务逻辑层
        │               ├── servlet/
        │               │   └── ODataServlet.java           # Servlet 入口
        │               └── util/
        │                   └── ODataUtil.java              # 工具类
        └── webapp/
            └── WEB-INF/
                └── web.xml                    # Web 应用配置(可选)

技术栈

  • Java 8+ - 编程语言
  • Apache Olingo 4.7.1 - OData 服务实现库
  • Maven 3.x - 项目构建工具
  • Servlet API 3.1+ - Web 服务 API
  • Jetty - 嵌入式 Web 服务器(用于测试)

快速开始

1. 环境要求

  • JDK 8 或更高版本
  • Maven 3.x

2. 编译项目

mvn clean compile

3. 运行项目

使用 Jetty Maven 插件运行:

mvn jetty:run

服务将在 http://localhost:8080 启动。

4. 访问服务

获取服务元数据

GET http://localhost:8080/odata/$metadata

返回服务的 EDM 元数据定义(XML 格式)。

重要说明:

  • 根据 OData V4 规范,$metadata 端点主要支持 XML 格式
  • JSON 格式的元数据在 OData V4 中并不是标准格式
  • 如果请求 JSON 格式,Apache Olingo 可能返回服务文档(Service Document)而不是元数据文档
  • 服务文档只包含实体集的列表,不包含完整的元数据信息(实体类型、属性定义等)
  • 因此,$metadata 端点始终返回 XML 格式,确保返回完整的元数据信息

XML 格式的元数据包含:

  • 实体类型定义(Entity Type)
  • 属性定义(Property)
  • 键定义(Key)
  • 实体集定义(Entity Set)
  • 命名空间(Namespace)

如果需要 JSON 格式的数据,请使用数据端点:

  • GET /odata/Cars - 返回 JSON 格式的汽车数据
  • GET /odata/Cars('1') - 返回 JSON 格式的单个汽车数据

获取所有汽车

GET http://localhost:8080/odata/Cars

返回所有汽车的 JSON 数据。

注意:

  • 浏览器直接访问时,默认返回 JSON 格式(已配置)
  • 如果使用工具(如 Postman),可以通过设置 Accept: application/json 明确指定 JSON 格式
  • 如果设置 Accept: application/xml,则返回 XML 格式

获取单个汽车

GET http://localhost:8080/odata/Cars('1')

返回 ID 为 '1' 的汽车的 JSON 数据。

响应格式说明:

  • 默认返回 JSON 格式(当 Accept 头为 */* 或未指定时)
  • 可以通过设置 Accept: application/json 明确请求 JSON 格式
  • 可以通过设置 Accept: application/xml 请求 XML 格式

前端和 RESTful API 使用:

  • 可以直接使用:OData URL 格式完全符合 RESTful 规范
  • 前端使用:JavaScript、React、Vue 等都可以直接调用
  • RESTful API 调用:curl、Postman、HttpClient 等都支持
  • 📖 详细使用指南:请参考 FRONTEND_USAGE.md

快速示例:

// JavaScript / React
fetch("http://localhost:8080/odata/Cars('1')")
  .then(response => response.json())
  .then(data => console.log(data));

// 使用 axios
axios.get("http://localhost:8080/odata/Cars('1')")
  .then(response => console.log(response.data));

获取汽车的属性值

GET http://localhost:8080/odata/Cars('1')/Model

返回 ID 为 '1' 的汽车的 Model 属性值。

OData 查询选项

OData 提供了丰富的查询选项,用于过滤、排序、分页等操作。

$filter - 过滤

只返回满足条件的实体:

GET http://localhost:8080/odata/Cars?$filter=manufacturer eq 'Tesla'

支持的运算符:

  • eq - 等于
  • ne - 不等于
  • gt - 大于
  • ge - 大于等于
  • lt - 小于
  • le - 小于等于
  • and - 逻辑与
  • or - 逻辑或
  • not - 逻辑非

$orderby - 排序

按指定属性排序:

GET http://localhost:8080/odata/Cars?$orderby=price asc
GET http://localhost:8080/odata/Cars?$orderby=price desc

$top 和 $skip - 分页

限制返回的记录数和跳过记录数:

GET http://localhost:8080/odata/Cars?$top=5&$skip=2

返回第 3-7 条记录。

$select - 选择属性

只返回指定的属性:

GET http://localhost:8080/odata/Cars?$select=id,model,manufacturer

$count - 计数

返回实体总数:

GET http://localhost:8080/odata/Cars/$count

CRUD 操作示例

Create(创建)

创建新汽车:

POST http://localhost:8080/odata/Cars
Content-Type: application/json

{
  "Id": "9",
  "Model": "Model X",
  "Manufacturer": "Tesla",
  "Year": 2023,
  "Price": 99990.0,
  "Color": "White"
}

Read(读取)

读取汽车:

GET http://localhost:8080/odata/Cars('1')

Update(更新)

部分更新汽车(PATCH):

PATCH http://localhost:8080/odata/Cars('1')
Content-Type: application/json

{
  "Price": 89990.0
}

完全更新汽车(PUT):

PUT http://localhost:8080/odata/Cars('1')
Content-Type: application/json

{
  "Id": "1",
  "Model": "Model S",
  "Manufacturer": "Tesla",
  "Year": 2021,
  "Price": 89990.0,
  "Color": "Red"
}

Delete(删除)

删除汽车:

DELETE http://localhost:8080/odata/Cars('1')

代码说明

1. Car.java - 实体模型

定义了 Car 实体类,包含汽车的属性(id、model、manufacturer 等)。

2. CarEdmProvider.java - EDM 提供者

定义了 OData 服务的元数据,包括:

  • 实体类型(Entity Type)定义
  • 实体集(Entity Set)定义
  • 属性(Property)定义
  • 键(Key)定义

3. CarService.java - 业务逻辑层

提供数据的 CRUD 操作和查询功能。

4. Processor 类 - 请求处理器

  • CarEntityCollectionProcessor: 处理实体集合请求(GET /Cars)
  • CarEntityProcessor: 处理单个实体请求(GET /Cars('1')、POST、PATCH、DELETE)
  • CarPrimitiveProcessor: 处理属性请求(GET /Cars('1')/Model)

5. ODataServlet.java - Servlet 入口

处理所有 OData 请求,初始化 OData 框架,注册处理器。

学习要点

  1. 理解 EDM 模型

    • EDM 是 OData 的核心,定义了服务的数据结构
    • 通过 CarEdmProvider 了解如何定义实体类型和实体集
  2. 理解请求处理流程

    • Servlet 接收请求 → 创建 Handler → 调用 Processor → 返回响应
    • 通过 ODataServlet 了解请求处理流程
  3. 理解数据转换

    • Java 对象(Car)↔ OData Entity
    • 通过 ODataUtil 了解数据转换方法
  4. 理解查询选项

    • $filter、$orderby、$top、$skip、$select 等
    • 通过 CarEntityCollectionProcessor 了解查询选项的处理
  5. 理解 CRUD 操作

    • Create、Read、Update、Delete
    • 通过 CarEntityProcessor 了解 CRUD 操作的实现
  6. 理解响应格式控制

    • OData 服务根据 Accept 请求头决定返回 JSON 或 XML
    • 浏览器默认 Accept: */*,本示例已配置为默认返回 JSON
    • 使用 Olingo Client 时会自动设置 Accept: application/json

扩展学习

  1. 添加更多实体类型

    • 例如:添加 Owner(车主)实体类型
    • 添加 Navigation Property(导航属性)关联 Car 和 Owner
  2. 实现复杂的查询

    • 实现完整的 $filter 解析
    • 支持嵌套查询和关联查询
  3. 添加认证和授权

    • 实现 OAuth 2.0 认证
    • 实现基于角色的访问控制
  4. 连接真实数据库

    • 使用 JPA/Hibernate 连接数据库
    • 实现数据持久化

前端和 RESTful API 使用

可以直接使用吗?

答案:✅ 完全可以!

OData URL 格式(如 Cars('1'))完全符合 RESTful 规范,可以:

  1. 前端直接使用

    • JavaScript、TypeScript、React、Vue、Angular 等都支持
    • 使用 fetchaxios 等 HTTP 客户端即可
    • 注意 URL 中的单引号在 JavaScript 字符串中需要转义
  2. RESTful API 调用

    • curl、Postman、HttpClient、requests(Python)等都支持
    • 标准的 HTTP GET/POST/PUT/DELETE 请求
    • 完全符合 RESTful API 规范

详细使用指南和代码示例请参考: FRONTEND_USAGE.md

快速示例

JavaScript:

// 获取单个实体
fetch("http://localhost:8080/odata/Cars('1')")
  .then(response => response.json())
  .then(data => console.log(data));

// 获取实体集合
fetch("http://localhost:8080/odata/Cars")
  .then(response => response.json())
  .then(data => console.log(data.value));

curl:

curl "http://localhost:8080/odata/Cars('1')"
curl -H "Accept: application/json" "http://localhost:8080/odata/Cars"

Python:

import requests
response = requests.get("http://localhost:8080/odata/Cars('1')")
print(response.json())

Olingo Client vs Olingo Server

核心区别

Olingo Server(本项目):

  • 作用:提供 OData 服务,接收和处理 OData 请求
  • 依赖odata-server-coreodata-server-api
  • 职责:定义 EDM 元数据、处理请求、序列化响应

Olingo Client:

  • 作用:调用 OData 服务,发送请求并解析响应
  • 依赖odata-client-coreodata-client-api
  • 职责:构建 OData URL、发送请求、解析响应

为什么公司项目分离 Server 和 Client?

  1. 架构分离:Server 提供数据,Client 消费数据,职责清晰
  2. 独立部署:可以独立开发、测试、部署
  3. 避免依赖冲突:Server 不需要 Client 依赖,Client 不需要 Server 依赖
  4. 微服务架构:符合微服务架构的最佳实践
  5. 团队协作:不同团队可以并行开发

Olingo Client 的优势

  • 简化调用:自动构建 URL、处理编码、解析响应
  • 类型安全:提供类型安全的 API
  • 代码复用:封装了 OData 协议的细节
  • 易于维护:统一的调用方式

详细说明和示例代码请参考:

参考资源

许可证

本项目仅用于学习目的。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages