# Camel Vert.x RESTful API 演示 这是一个使用Apache Camel和Vert.x开发的响应式RESTful API示例项目,采用MyBatis与PostgreSQL进行数据访问。本项目充分利用Camel REST DSL来实现API端点,避免直接使用Vert.x Router。 ## 特性 - 使用Apache Camel最新版本(4.4.0)结合Vert.x构建响应式API - 充分使用Camel REST DSL定义RESTful API端点 - 使用MyBatis纯XML方式进行数据库操作,无实体类和Mapper接口 - 扁平化结构设计,无Service层,减少代码量 - 完整的用户CRUD操作和分页查询 - 强大的通用参数验证机制 - 全局统一异常处理 - 响应式编程模型 ## 技术栈 - Apache Camel 4.11.0 - camel-vertx-http:Camel与Vert.x HTTP集成 - camel-rest:Camel REST DSL支持 - camel-jackson:JSON序列化支持 - Vert.x 4.5.14(核心组件) - MyBatis 3.5.19 - PostgreSQL - HikariCP ## 项目结构 ``` src/main/java/com/example/ ├── config/ # 配置类 │ ├── AppConfig.java # 应用配置 │ └── DatabaseConfig.java # 数据库配置 ├── exception/ # 异常类 │ ├── ApiException.java # 异常基类 │ ├── BusinessException.java # 业务异常 │ ├── GlobalExceptionHandler.java # 全局异常处理器 │ ├── ResourceNotFoundException.java # 资源未找到异常 │ └── ValidationException.java # 验证异常 ├── route/ # Camel路由和REST定义 │ └── UserRoute.java # 用户API路由和数据库操作 ├── validation/ # 参数验证 │ ├── RequestValidator.java # 通用验证器 │ └── ValidationExample.java # 验证器使用示例 └── Application.java # 主应用类 ``` ## 代码优化 本项目采用了以下优化策略减少代码量并提高开发效率: 1. **扁平化结构**:移除传统的Service层,将数据库操作直接集成到路由处理中 2. **直接使用MyBatis**:在路由处理器中直接使用SqlSession进行数据库操作 3. **链式验证API**:简化参数验证,通过链式调用提高代码可读性 4. **纯XML映射**:不使用Java实体类和Mapper接口,完全依赖XML配置减少代码量 ## 全局异常处理 项目实现了统一的全局异常处理机制,可以处理多种类型的异常: ```java // 配置全局异常处理 GlobalExceptionHandler exceptionHandler = new GlobalExceptionHandler(); // 处理各种异常类型 onException(ValidationException.class) .handled(true) .process(exceptionHandler); onException(ResourceNotFoundException.class) .handled(true) .process(exceptionHandler); onException(BusinessException.class) .handled(true) .process(exceptionHandler); onException(SecurityException.class) .handled(true) .process(exceptionHandler); onException(TimeoutException.class) .handled(true) .process(exceptionHandler); ``` ### 支持的异常类型 - **ValidationException**: 参数验证失败 - **ResourceNotFoundException**: 资源未找到 - **BusinessException**: 业务逻辑错误 - **SecurityException**: 安全/权限错误 - **TimeoutException**: 操作超时 - **IllegalArgumentException**: 参数错误 - 其他未捕获的异常 ### 错误响应格式 ```json { "error": true, "status": 400, "message": "用户数据验证失败", "errors": { "username": ["用户名不能为空"], "email": ["邮箱格式不正确"] } } ``` ## API 端点 | 方法 | URL | 描述 | |--------|-----------------------|---------------------| | GET | /api/users | 获取所有用户 | | GET | /api/users/page?page=1&size=10 | 分页获取用户| | GET | /api/users/{id} | 根据ID获取用户 | | POST | /api/users | 创建新用户 | | PUT | /api/users/{id} | 更新用户 | | DELETE | /api/users/{id} | 删除用户 | ## 通用参数验证 项目实现了强大的通用参数验证机制,支持链式调用和多种验证规则: ```java // 链式调用验证示例 RequestValidator.validate() .field("username", json.getString("username", "")) .notEmpty("用户名不能为空") .length(3, 50, "用户名长度必须在3-50个字符之间") .field("email", json.getString("email", "")) .notEmpty("邮箱不能为空") .email("邮箱格式不正确") .field("password", json.getString("password", "")) .notEmpty("密码不能为空") .passwordStrength("密码必须至少8位,包含大小写字母、数字和特殊字符") // 自定义验证规则 .field("confirmPassword", json.getString("confirmPassword", "")) .notEmpty("确认密码不能为空") .custom(value -> value.equals(json.getString("password", "")), "两次输入的密码不一致") .validate("验证失败"); ``` ### 内置验证规则 - `notEmpty`: 非空验证 - `length`: 长度范围验证 - `email`: 电子邮箱格式验证 - `phone`: 手机号格式验证 - `passwordStrength`: 密码复杂度验证 - `idCard`: 身份证号验证 - `matches`: 正则表达式匹配 - `custom`: 自定义验证规则 ## Camel路由 本项目使用Camel的REST DSL来定义API端点,并使用Direct组件(direct:xxx)处理具体业务逻辑。主要路由包括: - direct:getAllUsers - 获取所有用户 - direct:getUsersByPage - 分页获取用户 - direct:getUserById - 根据ID获取用户 - direct:createUser - 创建用户 - direct:updateUser - 更新用户 - direct:deleteUser - 删除用户 ## 快速开始 ### 前提条件 - JDK 17+ - Maven 3.6+ - PostgreSQL ### 数据库设置 1. 创建PostgreSQL数据库: ```sql CREATE DATABASE userdb; ``` 2. 运行初始化脚本 `src/main/resources/db/init.sql` ### 构建和运行 ```bash # 克隆项目 git clone cd camel-vertx-demo # 构建 mvn clean package # 运行 java -jar target/camel-vertx-demo-1.0-SNAPSHOT.jar ``` ## 配置 应用程序配置在 `src/main/resources/application.properties` 文件中: ```properties # 服务器配置 server.port=8080 server.host=localhost # 数据库配置 db.host=localhost db.port=5432 db.name=userdb db.username=postgres db.password=postgres db.pool.maxSize=10 ``` ## 与Camel集成的优势 - **声明式路由定义**: 使用Camel REST DSL可以更清晰地定义API端点 - **强大的错误处理机制**: Camel提供了丰富的异常处理功能 - **组件化设计**: 可以轻松集成其他Camel组件(如JMS、AMQP等) - **更高层次的抽象**: 减少样板代码,专注于业务逻辑 ## 角色管理API接口 ### 1. 获取所有角色 **请求** ``` GET /api/roles ``` **响应** ```json { "roles": [ { "id": 1, "name": "管理员", "code": "ADMIN", "description": "系统管理员,拥有所有权限", "createdAt": "2023-07-15T10:30:20.123Z", "updatedAt": "2023-07-15T10:30:20.123Z" }, { "id": 2, "name": "普通用户", "code": "USER", "description": "普通用户,拥有基本权限", "createdAt": "2023-07-15T10:30:20.123Z", "updatedAt": "2023-07-15T10:30:20.123Z" } ] } ``` ### 2. 分页获取角色 **请求** ``` GET /api/roles/page?page=1&size=10 ``` **参数说明** | 参数名 | 类型 | 必填 | 说明 | 默认值 | |--------|--------|------|--------------------------|--------| | page | int | 否 | 页码,从1开始 | 1 | | size | int | 否 | 每页大小,最大值为100 | 10 | **响应** ```json { "content": [ { "id": 1, "name": "管理员", "code": "ADMIN", "description": "系统管理员,拥有所有权限", "createdAt": "2023-07-15T10:30:20.123Z", "updatedAt": "2023-07-15T10:30:20.123Z" }, { "id": 2, "name": "普通用户", "code": "USER", "description": "普通用户,拥有基本权限", "createdAt": "2023-07-15T10:30:20.123Z", "updatedAt": "2023-07-15T10:30:20.123Z" } ], "page": 1, "size": 10, "total": 5, "totalPages": 1 } ``` ### 3. 根据ID获取角色 **请求** ``` GET /api/roles/{id} ``` **参数说明** | 参数名 | 类型 | 必填 | 说明 | |--------|--------|------|------------| | id | long | 是 | 角色ID | **响应** ```json { "id": 1, "name": "管理员", "code": "ADMIN", "description": "系统管理员,拥有所有权限", "createdAt": "2023-07-15T10:30:20.123Z", "updatedAt": "2023-07-15T10:30:20.123Z" } ``` ### 4. 创建角色 **请求** ``` POST /api/roles Content-Type: application/json ``` **请求体** ```json { "name": "运营管理员", "code": "OPERATION_ADMIN", "description": "负责内容运营和审核的管理员" } ``` **参数说明** | 参数名 | 类型 | 必填 | 说明 | |-------------|--------|------|-------------------------------------| | name | string | 是 | 角色名称,长度在2-50个字符之间 | | code | string | 是 | 角色编码,大写字母和下划线组合,长度在2-50个字符之间 | | description | string | 否 | 角色描述 | **响应** ```json { "id": 6, "name": "运营管理员", "code": "OPERATION_ADMIN", "description": "负责内容运营和审核的管理员", "createdAt": "2023-07-15T10:30:20.123Z", "updatedAt": "2023-07-15T10:30:20.123Z" } ``` ### 5. 更新角色 **请求** ``` PUT /api/roles/{id} Content-Type: application/json ``` **参数说明** | 参数名 | 类型 | 必填 | 说明 | |--------|--------|------|------------| | id | long | 是 | 角色ID | **请求体** ```json { "name": "运营总监", "code": "OPERATION_DIRECTOR", "description": "负责全站内容运营和审核的管理员" } ``` **参数说明** | 参数名 | 类型 | 必填 | 说明 | |-------------|--------|------|-------------------------------------| | name | string | 是 | 角色名称,长度在2-50个字符之间 | | code | string | 是 | 角色编码,大写字母和下划线组合,长度在2-50个字符之间 | | description | string | 否 | 角色描述 | **响应** ```json { "id": 6, "name": "运营总监", "code": "OPERATION_DIRECTOR", "description": "负责全站内容运营和审核的管理员", "createdAt": "2023-07-15T10:30:20.123Z", "updatedAt": "2023-07-15T11:25:15.456Z" } ``` ### 6. 删除角色 **请求** ``` DELETE /api/roles/{id} ``` **参数说明** | 参数名 | 类型 | 必填 | 说明 | |--------|--------|------|------------| | id | long | 是 | 角色ID | **响应** ``` 状态码: 204 No Content ``` ### 错误响应 #### 验证错误 (400 Bad Request) ```json { "error": true, "status": 400, "message": "角色数据验证失败", "errors": { "name": ["角色名称不能为空", "角色名称长度必须在2-50个字符之间"], "code": ["角色编码必须是大写字母和下划线组合"] } } ``` #### 资源不存在 (404 Not Found) ```json { "error": true, "status": 404, "message": "角色 ID: 999 不存在" } ``` #### 服务器错误 (500 Internal Server Error) ```json { "error": true, "status": 500, "message": "服务器内部错误,请稍后重试" } ``` ## Nacos服务注册集成 本项目已集成Nacos服务注册中心,支持服务的自动注册和发现。 ### 配置Nacos 在`application.properties`中配置Nacos相关参数: ```properties # Nacos服务注册配置 nacos.server-addr=127.0.0.1:8848 nacos.service.name=camel-vertx-service nacos.service.group=DEFAULT_GROUP nacos.namespace=public nacos.cluster-name=DEFAULT ``` ### 配置说明 | 参数名 | 说明 | 默认值 | |--------|------|--------| | nacos.server-addr | Nacos服务器地址,格式为host:port | 127.0.0.1:8848 | | nacos.service.name | 服务名称 | camel-vertx-service | | nacos.service.group | 服务分组 | DEFAULT_GROUP | | nacos.namespace | 命名空间 | public | | nacos.cluster-name | 集群名称 | DEFAULT | ### 服务注册 服务启动时会自动注册到Nacos服务中心,注册信息包括: - 服务名称:配置文件中的`nacos.service.name` - 服务分组:配置文件中的`nacos.service.group` - 服务地址:应用程序主机地址和端口 - 元数据: - application.name: camel-vertx-demo - version: 1.0.0 - hostname: 主机名 - preserved.register.source: CAMEL_VERTX ### 服务注销 应用程序关闭时会自动从Nacos注销服务。 ### Nacos心跳机制 Nacos客户端会自动为注册的实例创建和维护心跳,确保服务的健康状态被正确报告到Nacos服务器。心跳机制的主要配置参数包括: ```properties # Nacos心跳配置 nacos.naming.client.beat.thread.count=1 # 心跳线程数 nacos.naming.client.beat.interval=5000 # 心跳间隔,单位毫秒 nacos.naming.client.max.retry.times=3 # 最大重试次数 nacos.naming.client.timeout=3000 # 请求超时时间,单位毫秒 ``` 心跳机制工作流程: 1. 服务实例注册后,Nacos客户端会自动创建心跳任务 2. 客户端按照配置的间隔周期性地向Nacos服务器发送心跳包 3. 如果心跳发送失败,客户端会重试,最多重试配置的次数 4. 如果Nacos服务器在一定时间内未收到心跳,会将该实例标记为不健康 您可以通过以下方法检查服务的健康状态: ```java boolean isHealthy = NacosConfig.isServiceHealthy("camel-vertx-service"); if (isHealthy) { logger.info("服务健康状态正常"); } else { logger.warn("服务可能不健康,请检查"); } ``` ### 手动启动Nacos服务器 在使用本应用前,请确保Nacos服务器已经启动。如果没有安装Nacos,可以按照以下步骤快速启动: 1. 下载Nacos服务器: [https://github.com/alibaba/nacos/releases](https://github.com/alibaba/nacos/releases) 2. 解压下载的压缩包 3. 启动服务器: - Windows: 执行 `bin\startup.cmd -m standalone` - Linux/Mac: 执行 `sh bin/startup.sh -m standalone` 4. 访问控制台: [http://localhost:8848/nacos](http://localhost:8848/nacos) (默认用户名/密码: nacos/nacos) ### 服务发现 其他服务可以通过Nacos API发现并调用本服务: ```java // 获取命名服务 Properties properties = new Properties(); properties.setProperty("serverAddr", "127.0.0.1:8848"); NamingService naming = NacosFactory.createNamingService(properties); // 发现服务实例 List instances = naming.selectInstances("camel-vertx-service", true); // 使用服务实例 if (!instances.isEmpty()) { Instance instance = instances.get(0); String url = "http://" + instance.getIp() + ":" + instance.getPort() + "/api/users"; // 使用该URL调用服务 } ``` ## 后续扩展 本项目可以进一步扩展以支持更多功能: 1. 集成Spring Cloud Alibaba,实现与Spring Cloud生态的无缝对接 2. 添加Nacos配置中心功能,实现配置的集中管理和动态更新 3. 集成Sentinel进行服务限流和熔断 4. 添加OpenAPI/Swagger支持,自动生成API文档