技术分享 | 跨平台API对接(Java)

76 阅读4分钟

本章介绍基于 Jenkins API 调用的跨平台 API 对接。

基于Jenkins实现跨平台API对接

Jenkins 提供了远程访问应用编程接口(Remote Access API),能够通过 Http 协议远程调用相关命令操作 Jenkins 进行 Jenkins 视图、任务、插件、构建信息、任务日志信息、统计信息等,非常容易与其配合更好的完成 CI/CD 工作。 Jenkins API 总共有三种格式,分别为:

  • XML API 可以使用 xml 方式进行 API 的使用,这种方式的优势在于可以使用强大的 xpath 特性进行相关的访问控制。如我们下文将要介绍的 Jenkins 客户端底层就是基于 XML API 实现的。
  • JSON API 使用 JSON 方式进行操作,因为 json 基本上已经是应用之间数据交换的准标准格式之一,这种方式比较方便 Javascript 或者和其他应用的集成。
  • Python API 可以通过 python-jenkins 库对 Jenkins 进行控制操作。此库对 Jenkins 的 API 进行了进一步的包装,使用起来更加方便,但是一般需要安装 python-jenkins,并通过 python 脚本的执行来达到集成的方式。

为什么基于Jenkins API对接

  • 频繁创建 Job 时,降低手工错误的概率 在工作中,如果需要创建的 Jenkins 的 Job 非常多,而大多又呈现有规律的方式时,Job 的创建成为了一个繁琐而又需要频繁操作的任务。在这种场景下,使用 API 结合脚本进行自动化可以提高效率,降低手工错误的几率。
  • 满足特定条件时自动触发 Jenkins 如果需要动态的创建 Jenkins Job ,如根据中间结果在某个触发点自动生成,再如生成的 Job 需要使用的参数也是动态运行阶段才能取到值的场景下。
  • 基于 Jenkins 自研产品或工具 如果产品或工具相关的功能,需要基于 Jenkins 进行研发,而且不希望用户直接使用 Jenkins,仅将 Jenkins 作为背后的执行引擎的场景,这种情况下也需要使用 Jenkins API 才能完成。

快速开始

下面我们通过实战学习下如何将 Spring Boot 和 Jenkins 进行集成,实现跨平台 API 对接。

<dependency>
    <groupId>com.offbytwo.jenkins</groupId>
        <artifactId>jenkins-client</artifactId>
            <version>0.3.8</version>
            </dependency>
            
            ```
            
            我们先引入 Jenkins-client 用于和 Jenkins 进行交互。而 Jenkins-client 的底层实现其实就是调用 Jenkins XML API 来完成操作 Jenkins 的,如下表部分示例所示。
            
            ![](https://ceshiren.com/uploads/default/original/3X/3/7/377192077682f782b3648d242cfd209f6a827dce.png)
            
            
            - JenkinsHttpClient:封装了调用 JenkinsAPI 的底层方法JenkinsHttpClient(URI uri, String username, String password)
            
            ![](https://ceshiren.com/uploads/default/original/3X/b/0/b08b56f84c375845d34af6ed1dd4f626a348c6d3.png)
            - JenkinsServer:封装了调用 JenkinsAPI 的语义级别的方法,其本质调用的是 JenkinsHttpClient 类中的方法,只是根据操作 Jenkins 的功能进行了语义级别的封装JenkinsServer(JenkinsHttpConnection client)
            
            ![](https://ceshiren.com/uploads/default/original/3X/c/7/c7a33e689ff122553da02c461612d1f352bf713a.png)
            ![](https://ceshiren.com/uploads/default/original/3X/0/2/024fe96ccff0236036997fe931a19f10b2feacc3.png)
            - Job:Jenkins 中 job 对应的实体类,有很多实用的语义级别的方法,如构建等。
            Job(String name, String url)
            
            ![](https://ceshiren.com/uploads/default/original/3X/2/f/2f486c4c3e56067f5780a9d0868ce278f31e01f4.png)
            
            - 创建新 Job
            ![](https://ceshiren.com/uploads/default/original/3X/a/f/afc7ea0a8919f90139ec62c4e2fd6e59fb5bddfe.png)
            - 进入 Job 配置
            - 将 Job/Job 名称/ Configure 改为 Job/Job 名称/ Config.xml 并回车
            
            
            - 在 resources 目录下,jenkinsDir ,并添加 hogwarts_test_mini_start_test.xml 文件,此时我们为了测试命令可以正常被执行,需要在测试命令前加 eval 关键字,并将${testCommand}放在英文双引号括内部,如图中红框部分。
            - JenkinsUtil 示例代码
            ```
            import com.offbytwo.jenkins.JenkinsServer;
            import com.offbytwo.jenkins.client.JenkinsHttpClient;
            import com.offbytwo.jenkins.model.Job;
            import org.springframework.core.io.ClassPathResource;
            
            import java.io.IOException;
            import java.io.InputStream;
            import java.net.URI;
            import java.net.URISyntaxException;
            import java.util.HashMap;
            import java.util.Map;
            
            /**
             * @Author tlibn
              * @Date 2020/8/11 15:21
               **/
               public class JenkinsUtil {
               
                   //调试使用
                       public static void main(String[] args) throws IOException, URISyntaxException {
                               build("hogwarts_test_mini_start_test_100","12","token","pwd");
                                   }
                                   
                                       public static void build(String jobName, String userId, String remark,String testCommand) throws IOException, URISyntaxException {
                                       
                                               System.out.println("========== 执行开始 ===========");
                                               
                                                       // 1. 通过 ClassPathResource 获取 Jenkins 的 JenkinsJob 请求参数数据
                                                               ClassPathResource classPathResource = new ClassPathResource("JenkinsConfigDir/hogwarts_jenkins_test_start.xml");
                                                                       InputStream inputStream = classPathResource.getInputStream();
                                                                               String jobConfigXml = FileUtil.getText(inputStream);
                                                                               
                                                                                       // 2. 获取 Jenkins 信息
                                                                                               String baseUrl = JenkinsInfo.baseUrl;
                                                                                                       String userName = JenkinsInfo.userName;
                                                                                                               String password = JenkinsInfo.password;
                                                                                                               
                                                                                                                       // 3. 根据 Jenkins 信息创建 JenkinsHttpClient 对象
                                                                                                                               JenkinsHttpClient jenkinsHttpClient = new JenkinsHttpClient(new URI(baseUrl),userName,password);
                                                                                                                               
                                                                                                                                       // 4. 根据 Jenkins 客户端创建 JenkinsServer 对象
                                                                                                                                               JenkinsServer jenkinsServer = new JenkinsServer(jenkinsHttpClient);
                                                                                                                                               
                                                                                                                                                       // 5. 创建 Job,如果Job已经存在,可以改为更新 Job 方法
                                                                                                                                                               jenkinsServer.createJob(jobName,jobConfigXml,true);
                                                                                                                                                               
                                                                                                                                                                       // 6. 获取 Jenkins 服务器中所有的 Job 信息
                                                                                                                                                                               Map<String, Job> jobMap = jenkinsServer.getJobs();
                                                                                                                                                                               
                                                                                                                                                                                       // 7. 获取 Jenkins 服务器中我们创建的单个 Job 信息
                                                                                                                                                                                               Job job = jobMap.get(jobName);
                                                                                                                                                                                               
                                                                                                                                                                                                       // 8. 组装 Jenkins 服务器的构建参数
                                                                                                                                                                                                               Map<String,String> map = new HashMap<>();
                                                                                                                                                                                                                       map.put("userId",userId);
                                                                                                                                                                                                                               map.put("remark",remark);
                                                                                                                                                                                                                                       map.put("testCommand",testCommand);
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                               // 9. 构建 Jenkins Job
                                                                                                                                                                                                                                                       job.build(map,true);
                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                               System.out.println("========== 执行完毕 ===========");
                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                   ```
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                   - 创建新 Job 并构建成功
                                                                                                                                                                                                                                                                   - 构建参数页面查看参数数据
                                                                                                                                                                                                                                                                   - 构建日志页面查看 pwd 命令执行情况
                                                                                                                                                                                                                                                                   ![](https://ceshiren.com/uploads/default/original/3X/c/e/ce3063fe45704b1b2406ac71121755c18492a0b4.png)
                                                                                                                                                                                                                                                                   数据持久化技术就先讲到这里啦,下面留两个思考给大家,希望大家能用心练习一下哦~
                                                                                                                                                                                                                                                                   1.尝试更新 Jenkins Job 配置信息,并在构建参数中新增用户名称字段
                                                                                                                                                                                                                                                                   2.将 Jenkins API 调用和 Spring Boot 结合在一起,通过 postman 发送以下数据进行 Jenkins Job 的创建和更新操作
                                                                                                                                                                                                                                                                   ```
                                                                                                                                                                                                                                                                   {
                                                                                                                                                                                                                                                                     "jobName": "hogwarts_test_mini_start_test_100",
                                                                                                                                                                                                                                                                       "testCommand": "pwd",
                                                                                                                                                                                                                                                                         "remark": "token",
                                                                                                                                                                                                                                                                           "userId": "12"
                                                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                           ```
                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                           [原文链接](https://mp.weixin.qq.com/s?__biz=MzU3NDM4ODEzMg==&mid=2247500793&idx=1&sn=c882066fa38f5b466799ad23ec791b1c&chksm=fd31a132ca46282475d8f04a71d15709c677d3937be4d0652005a1090b503ef8ea4c080e6b28#rd) 
                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                           [更多技术文章](https://qrcode.ceba.ceshiren.com/link?name=article&project_id=qrcode&from=juejin&timestamp=1655019100&author=QY)