
# 代码解析
项目结构如下
![](https://support.huaweicloud.com/devg-iotedge/figure/zh-cn_image_0000001166582399.png "点击放大")
- ApiController：提供被北向应用NA调用的接口。
- Application：主启动类
- AuthFilter：鉴权过滤器。
- ConfigController：被云端调用进行配置处理。
- ConfigService：配置管理服务 。
- ItIntegrationService：向北向应用NA发送数据。
代码解释使用ModuleSDK开发it子系统集成服务时使用的主要ItClient类。
ItClient类有以下几个关键方法（具体参考JavaDoc）。
- createFromEnv(): ItClient创建时由此方法自动获取环境变量。
- syncConfigs()：IT应用启动时由此方法实现从北向应用NA同步配置。
- confirmConfigs()：向北向应用NA确认已经同步的配置。
- sign()：对于发送到APIGW的请求，需要使用此方法进行签名。
- verify()：对于来自APIGW的请求，由此方法进行鉴权。
- \*\*Json()：根据需求选择不同的方法向NA发送请求。
**片段一**
ItIntegrationService 类
```
@Scheduled(cron = "0 0/5 * * * ?")
    public void collectData() throws HttpException, CryptException {
        //TODO 采集订单数据
        String body = "{\"orders\":\"data of orders\"}";
        itClient.postJson("/nas/erp/orders", body);
    }
```
对于来自子系统erp的数据orders（此处未真正接入erp系统），采用定时任务进行发送。
注意请求的地址（demo为"/nas/erp/orders"）,erp为NA的id(创建路由管理时定义)。
最终请求地址http://sys-edge-apigw:8900/nas/erp/orders
http://sys-edge-apigw:8900为Api GW接收请求的地址，Api GW接收到此请求会查询本地存储的NA信息中的API网关地址向网关发送请求，如API网关分组下的子域名为
068b72f3b75444dda67cc6e\*\*\*\*\*\*\*\*.apic.cn-south-1.huaweicloudapis.com
则Api GW转发地址为https://068b72f3b75444dda67cc6e\*\*\*\*\*\*\*\*.apic.cn-south-1.huaweicloudapis.com/oreders
API网关再将请求转发到定义的NA地址。如如API定义的后端NA为:
请求方式:http
host地址:110.\*.\*.\*
端口号:8080
则API网关会将请求转发至http://110.\*.\*.\*:8080/orders
![](https://support.huaweicloud.com/devg-iotedge/public_sys-resources/caution_3.0-zh-cn.png)
Api GW保存NA与IA信息的位置为：/var/IoTEdge/db/sys_edge_apigw/db
Api GW无法转发请求请查看该sqlite数据库是否正确保存了NA与IA的信息。
**片段二**
AuthFilter 类
```
@Order(1)
@WebFilter(filterName = "authFilter", urlPatterns = "/*")
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        try {
            itClient.verify(request.getHeader("Authorization"));
            filterChain.doFilter(servletRequest, servletResponse);
        } catch (AuthException e) {
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            response.sendError(HttpStatus.SC_FORBIDDEN);
        }
    }
```
对于来自Api GW的请求，此过滤器会进行拦截，并由itClient.verify()方法进行鉴权。
鉴权的方式为在请求头中增加Authorization字段，值的示例如下所示：
Algorithm=HMAC_SHA_256;AK=ia_1;SignedTime=1600763045361;Signature=0A1B0C3D
其中：
Algorithm：表示签名使用的算法名称。
AK：表示客户端身份。
SignedTime：表示签名时间戳。
Signature：为使用由Algorithm指定的签名算法对以上相应字段进行签名的结果。
![](https://support.huaweicloud.com/devg-iotedge/public_sys-resources/notice_3.0-zh-cn.png)
对于发送到Api GW的请求，ItClient中提供的\*\*Json()方法已做鉴权相关处理。
**片段三**
ConfigService 类
```
//创建时运行一次
    @PostConstruct
    public void syncConfigs() {
        //TODO 先从本地加载配置项
        //从云端同步配置
        try {
            List<Config> configs = itClient.syncConfigs();
            configs.forEach(config -> configMap.put(config.getId(), config));
            //TODO 持久化保存配置
            //确认已同步的配置
            itClient.confirmConfigs(configs);
        } catch (GeneraException e) {
            System.out.println(e.getMessage());
        }
    }
```
创建时ItClient从云端ITIntegration获取配置并确认（IA\>Api GW\>云端ITIntegration）。
**片段四**
```
/**
 * 该类实现供北向应用调用的接口
 */
@RestController
@RequestMapping(value = "/api")
public class ApiController {
 private final String moduleId;
    @Autowired
    public ApiController(ItClient itClient) {
        this.moduleId = itClient.getConfig().getModuleId();
    }
    @GetMapping("/get")
    public AppResponse GetTest() {
        return AppResponse.success("GetTest Success", new ReturnDto(moduleId));
    }
    @PostMapping("/post")
    public AppResponse PostTest(@RequestBody Map<String, Object> inputArgs) {
        return AppResponse.success("PostTest Success", new ReturnDto(moduleId, inputArgs));
    }
}
```
APIGW能将来自北向NA的响应（如配置）自ITIntegration请求转发送到iT应用(NA\>ITIntegration\>Api GW\>IA)，IT应用可以由此实现对本地子系统的控制。
EdgeApiGW收到南向3rdIA的应答后，需要将应答信息构造成用于进行websocket传输的ResponseDto，并调用sendResponse接口，发送该数据到云端。
/api/\*\* 注：支持GET/POST/PUT/DELETE/PATCH五种方式。
