# 服务分发阶段说明

## 阶段概述
服务分发阶段是网关调度的核心环节，负责将已验证权限的请求分发到相应的业务服务。通过IApiSMO和IApiServiceSMO接口实现多层次的请求转发和员工权限校验。

## 核心组件
- **IApiSMO**: 服务调用入口接口
- **ApiSMOImpl**: 服务调用实现类
- **IApiServiceSMO**: 最终服务分发接口
- **ApiServiceSMOImpl**: 最终服务分发实现类

## 处理流程

### 1. 员工权限校验
- ApiSMOImpl校验员工与商户的关系权限
- 验证员工在当前商户中的访问权限
- 重写用户ID和商户ID到请求头

### 2. 请求头重写
```java
// 重写用户和商户信息
headers.put(CommonConstant.HTTP_USER_ID, userId);
headers.put(CommonConstant.HTTP_STORE_ID, storeId);
```

### 3. 服务分发调用
- 调用IApiServiceSMO进行最终服务分发
- 传递请求体和头信息到下游处理

## 代码示例

### IApiSMO接口定义
```java
public interface IApiSMO {
    ResponseEntity<String> doApi(String body, Map<String, String> headers, HttpServletRequest request);
}
```

### ApiSMOImpl实现类
```java
@Component
public class ApiSMOImpl implements IApiSMO {
    
    @Autowired
    private IApiServiceSMO apiServiceSMOImpl;
    
    @Override
    public ResponseEntity<String> doApi(String body, Map<String, String> headers, HttpServletRequest request) {
        // 1. 校验员工与商户的关系权限
        String userId = headers.get(CommonConstant.HTTP_USER_ID);
        String storeId = headers.get(CommonConstant.HTTP_STORE_ID);
        validateEmployeePermission(userId, storeId);
        
        // 2. 重写用户ID和商户ID
        headers.put(CommonConstant.HTTP_USER_ID, getActualUserId(userId));
        headers.put(CommonConstant.HTTP_STORE_ID, getActualStoreId(storeId));
        
        // 3. 调用最终服务分发
        return apiServiceSMOImpl.service(body, headers);
    }
    
    private void validateEmployeePermission(String userId, String storeId) {
        // 实现员工权限校验逻辑
        // 验证员工是否属于当前商户
        // 验证员工是否有访问权限
    }
}
```

### IApiServiceSMO接口定义
```java
public interface IApiServiceSMO {
    ResponseEntity<String> service(String reqJson, Map<String, String> headers);
}
```

### 在网关中的调用
```java
// 在AppController中调用服务分发
@RequestMapping(path = "/{service:.+}", method = RequestMethod.POST)
public ResponseEntity<String> servicePost(@PathVariable String service,
                                         @RequestBody String postInfo,
                                         HttpServletRequest request) {
    
    // 请求接收和权限验证阶段...
    
    // 服务分发阶段
    ResponseEntity<String> responseEntity = apiSMOImpl.doApi(postInfo, headers, request);
    
    return responseEntity;
}
```

## 关键配置

### 请求头常量
```java
public final static String HTTP_USER_ID = "USER_ID";      // 用户ID
public final static String HTTP_STORE_ID = "STORE_ID";    // 商户ID
public final static String HTTP_APP_ID = "APP_ID";        // 应用ID
```

### 服务编码传递
```java
// 服务编码通过头信息传递
headers.put(CommonConstant.HTTP_SERVICE, service);
```

## 服务分发机制

### 1. 员工权限验证
- 验证员工与商户的关联关系
- 检查员工在当前商户中的状态
- 验证员工的业务操作权限

### 2. 请求头重写策略
- 根据实际业务需求重写用户ID
- 确保下游服务获取正确的商户信息
- 维护请求链路的完整性

### 3. 服务路由逻辑
- 基于服务编码进行服务发现
- 动态路由到对应的业务服务
- 支持服务版本管理

## 异常处理

### 员工权限异常
```java
try {
    validateEmployeePermission(userId, storeId);
} catch (NoEmployeePermissionException e) {
    logger.error("员工权限验证失败", e);
    return ResultVo.error("员工没有访问权限", HttpStatus.FORBIDDEN);
}
```

### 服务分发异常
```java
try {
    return apiServiceSMOImpl.service(body, headers);
} catch (ServiceNotFoundException e) {
    logger.error("服务未找到", e);
    return ResultVo.error("服务不存在", HttpStatus.NOT_FOUND);
}
```

## 技术要点

1. **权限继承**: 在网关权限基础上增加员工权限校验
2. **请求头传递**: 通过请求头传递上下文信息
3. **服务发现**: 基于服务编码的动态服务路由
4. **责任链模式**: 多层次的服务分发架构

## 性能优化
- 员工权限信息缓存
- 服务路由信息预加载
- 请求头信息复用
- 连接池管理