JIRA Rest JAVA Client API实现问题管理及自定义字段(原创)
JIRA是一个缺陷跟踪管理系统,被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域,当我们需要把第三方业务系统集成进来时,可以调用他的API。
JIRA本身的API非常强大,但它是一个底层的API体系,并不是一个易用的接口,如果要开发和拓展,所以需要我们二次包装。
jira官方为解决这个问题,推出了方便强大的java client library(目前只有java客户端库,没有.Net类库)
jira的Rest API 最新文档官网.
JIRA 6.4.12 REST API documentation
https://docs.atlassian.com/jira/REST/latest/
JIRA REST API Tutorials:
https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials
如果是编写java桌面或web应用,jira提供了更方便的方式(Client类库),JIRA REST Java Client is a Java library (usable from any JVM language) which allows to easily talk to any JIRA 4.2+ instance using new (and still evolving) REST API.
JIRA Java Client library
https://ecosystem.atlassian.net/wiki/display/JRJC/Home
如果使用Client类库,可以方便应用各种现成的jira实体类(如项目、问题、备注、自定义字段......),不需要再重复造轮子,大幅提升效率。
首先,必须要了解JIRA api的接口结构,其中<resource-name>可以理解成api的方法,比如project,就是项目信息,user就是用户信息,issue就是问题信息....
- http://hostname/rest/<api-name>/<api-version>/<resource-name>
/rest/
. Hence, if your JIRA site is running at:还先要搞清楚jira api的 认证体系,摘自官网:
the first step in using the JIRA REST API is to authenticate a user account with your JIRA site. For the purposes of this tutorial we will use HTTP BASIC Authentication, but any authentication that works against JIRA will work against the REST API. This includes:
- OAuth
- HTTP Cookies
- Trusted Applications
- os_username/os_password query parameters
为方便使用,我们采用Basic Auth
Basic Auth headers
If you need to you may construct and send basic auth headers yourself. To do this you need to perform the following steps:
- Build a string of the form username:password
- Base64 encode the string
- Supply an "Authorization" header with content "Basic " followed by the encoded string. For example, the string "fred:fred" encodes to "ZnJlZDpmcmVk" in base64, so you would make the request as follows.
- 一个curl的例子,注意红色字符串是对“username:password”的Base64编码
curl -D- -X GET -H "Authorization: Basic ZnJlZDpmcmVk" -H "Content-Type: application/json" "http://kelpie9:8081/rest/api/2/issue/QA-31"
JAVA Client类库实现的API DEMO
- package jiraTEST;
- import java.net.URI;
- import java.net.URISyntaxException;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import java.util.concurrent.ExecutionException;
- import org.apache.commons.codec.binary.Base32;
- import org.joda.time.DateTime;
- import com.atlassian.jira.rest.client.IssueRestClient;
- import com.atlassian.jira.rest.client.JiraRestClient;
- import com.atlassian.jira.rest.client.SearchRestClient;
- import com.atlassian.jira.rest.client.domain.BasicIssue;
- import com.atlassian.jira.rest.client.domain.BasicProject;
- import com.atlassian.jira.rest.client.domain.BasicUser;
- import com.atlassian.jira.rest.client.domain.Comment;
- import com.atlassian.jira.rest.client.domain.Field;
- import com.atlassian.jira.rest.client.domain.Issue;
- import com.atlassian.jira.rest.client.domain.Project;
- import com.atlassian.jira.rest.client.domain.SearchResult;
- import com.atlassian.jira.rest.client.domain.Transition;
- import com.atlassian.jira.rest.client.domain.input.ComplexIssueInputFieldValue;
- import com.atlassian.jira.rest.client.domain.input.FieldInput;
- import com.atlassian.jira.rest.client.domain.input.IssueInput;
- import com.atlassian.jira.rest.client.domain.input.IssueInputBuilder;
- import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
- import com.atlassian.util.concurrent.Promise;
- import com.google.common.collect.Lists;
- public class CvteJiraDemo {
- public static String BaseURL = "http://jira-test:8080/";
- public static String User = "admin";
- public static String Password = "admin";
- private static URI jiraServerUri = URI
- .create("http://jira-test:8080/rest/api/2/");
- private static boolean quiet = false;
- private static final long BUG_TYPE_ID = 1L; // JIRA magic value
- private static final long TASK_TYPE_ID = 3L; // JIRA magic value
- private static final DateTime DUE_DATE = new DateTime();
- private static final String PRIORITY = "Trivial";
- private static final String DESCRIPTION = "description";
- public static void main(String[] args) throws InterruptedException,
- ExecutionException {
- final AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
- URI jiraServerUri;
- try {
- jiraServerUri = new URI(BaseURL);
- final JiraRestClient restClient = (JiraRestClient) factory
- .createWithBasicHttpAuthentication(jiraServerUri, User,
- Password);
- getAllProjects(restClient);
- getProject(restClient, "DEMO");
- getIssue(restClient, "FEEDBACK-14");
- getIssueFields(restClient, "FEEDBACK-27");
- addIssue(restClient, "FEEDBACK", "AAAAB");
- addIssueComplex(restClient, "FEEDBACK",DUE_DATE.toString());
- } catch (URISyntaxException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- }
- }
- private static void println(Object o) {
- if (!quiet) {
- System.out.println(o);
- }
- }
- private static void parseArgs(String[] argsArray) throws URISyntaxException {
- final List<String> args = Lists.newArrayList(argsArray);
- if (args.contains("-q")) {
- quiet = true;
- args.remove(args.indexOf("-q"));
- }
- if (!args.isEmpty()) {
- jiraServerUri = new URI(args.get());
- }
- }
- private static Transition getTransitionByName(
- Iterable<Transition> transitions, String transitionName) {
- for (Transition transition : transitions) {
- if (transition.getName().equals(transitionName)) {
- return transition;
- }
- }
- return null;
- }
- // 得到所有项目信息
- private static void getAllProjects(final JiraRestClient restClient)
- throws InterruptedException, ExecutionException {
- try {
- Promise<Iterable<BasicProject>> list = restClient
- .getProjectClient().getAllProjects();
- Iterable<BasicProject> a = list.get();
- Iterator<BasicProject> it = a.iterator();
- while (it.hasNext()) {
- System.out.println(it.next());
- }
- } finally {
- }
- }
- // 得到单一项目信息
- private static void getProject(final JiraRestClient restClient,
- String porjectKEY) throws InterruptedException, ExecutionException {
- try {
- Project project = restClient.getProjectClient()
- .getProject(porjectKEY).get();
- System.out.println(project);
- } finally {
- }
- }
- // 得到单一问题信息
- private static void getIssue(final JiraRestClient restClient,
- String issueKEY) throws InterruptedException, ExecutionException {
- try {
- Promise<Issue> list = restClient.getIssueClient()
- .getIssue(issueKEY);
- Issue issue = list.get();
- System.out.println(issue);
- } finally {
- }
- }
- // 创建问题
- public static BasicIssue createIssue(final JiraRestClient jiraRestClient,
- IssueInput newIssue) {
- BasicIssue basicIssue = jiraRestClient.getIssueClient()
- .createIssue(newIssue).claim();
- return basicIssue;
- }
- //添加备注到问题
- public static void addCommentToIssue(final JiraRestClient jiraRestClient,Issue issue, String comment) {
- IssueRestClient issueClient = jiraRestClient.getIssueClient();
- issueClient.addComment(issue.getCommentsUri(), Comment.valueOf(comment)).claim();
- }
- //删除问题,目前找不到对应API
- public static void deleteIssue(final JiraRestClient jiraRestClient, Issue issue) {
- IssueRestClient issueClient = jiraRestClient.getIssueClient();
- //issueClient.deleteIssue(issue.getKey(), false).claim();
- }
- //通过标题获取问题
- public static Iterable findIssuesByLabel(final JiraRestClient jiraRestClient, String label) {
- SearchRestClient searchClient = jiraRestClient.getSearchClient();
- String jql = "labels%3D"+label;
- com.atlassian.jira.rest.client.domain.SearchResult results = ((SearchRestClient) jiraRestClient).searchJql(jql).claim();
- return results.getIssues();
- }
- //通过KEY获取问题
- public static Issue findIssueByIssueKey(final JiraRestClient jiraRestClient, String issueKey) {
- SearchRestClient searchClient = jiraRestClient.getSearchClient();
- String jql = "issuekey = \"" + issueKey + "\"";
- SearchResult results = searchClient.searchJql(jql).claim();
- return (Issue) results.getIssues().iterator().next();
- }
- // 创建问题 :仅有简单问题名称
- private static void addIssue(final JiraRestClient restClient,
- String porjectKEY, String issueName) throws InterruptedException,
- ExecutionException {
- try {
- IssueInputBuilder builder = new IssueInputBuilder(porjectKEY,
- TASK_TYPE_ID, issueName);
- builder.setDescription("issue description");
- final IssueInput input = builder.build();
- try {
- // create issue
- final IssueRestClient client = restClient.getIssueClient();
- final BasicIssue issue = client.createIssue(input).claim();
- final Issue actual = client.getIssue(issue.getKey()).claim();
- System.out.println(actual);
- } finally {
- if (restClient != null) {
- // restClient.close();
- }
- }
- } finally {
- }
- }
- // 创建问题 :包含自定义字段
- private static void addIssueComplex(final JiraRestClient restClient,
- String porjectKEY, String issueName) throws InterruptedException,
- ExecutionException {
- try {
- IssueInputBuilder builder = new IssueInputBuilder(porjectKEY,
- TASK_TYPE_ID, issueName);
- builder.setDescription("issue description");
- // builder.setFieldValue("priority", ComplexIssueInputFieldValue.with("name", PRIORITY));
- //单行文本
- builder.setFieldValue("customfield_10042", "单行文本测试");
- //单选字段
- builder.setFieldValue("customfield_10043", ComplexIssueInputFieldValue.with("value", "一般"));
- //数值自定义字段
- builder.setFieldValue("customfield_10044", 100.08);
- //用户选择自定义字段
- builder.setFieldValue("customfield_10045", ComplexIssueInputFieldValue.with("name", "admin"));
- //用户选择自定义字段(多选)
- Map<String, Object> user1 = new HashMap<String, Object>();
- user1.put("name", "admin");
- Map<String, Object> user2 = new HashMap<String, Object>();
- user2.put("name", "wangxn");
- ArrayList peoples = new ArrayList();
- peoples.add(user1);
- peoples.add(user2);
- builder.setFieldValue("customfield_10047", peoples);
- //设定父问题
- Map<String, Object> parent = new HashMap<String, Object>();
- parent.put("key", "FEEDBACK-25");
- FieldInput parentField = new FieldInput("parent", new ComplexIssueInputFieldValue(parent));
- builder.setFieldInput(parentField);
- final IssueInput input = builder.build();
- try {
- final IssueRestClient client = restClient.getIssueClient();
- final BasicIssue issue = client.createIssue(input).claim();
- final Issue actual = client.getIssue(issue.getKey()).claim();
- System.out.println(actual);
- } finally {
- if (restClient != null) {
- // restClient.close();
- }
- }
- } finally {
- }
- }
- //获取问题的所有字段
- private static void getIssueFields(final JiraRestClient restClient,
- String issueKEY) throws InterruptedException, ExecutionException {
- try {
- Promise<Issue> list = restClient.getIssueClient()
- .getIssue(issueKEY);
- Issue issue = list.get();
- Iterable<Field> fields = issue.getFields();
- Iterator<Field> it = fields.iterator();
- while (it.hasNext()) {
- System.out.println(it.next());
- }
- } finally {
- }
- }
- }
JIRA Rest JAVA Client API实现问题管理及自定义字段(原创)的更多相关文章
- JIRA REST java client API实际应用
[本文出自天外归云的博客园] 前提 1.需要安装maven环境: 2.在本地创建maven项目并修改maven配置文件“pom.xml”,添加如下内容: <dependency> < ...
- Memcached Java Client API详解
针对Memcached官方网站提供的java_memcached-release_2.0.1版本进行阅读分析,Memcached Java客户端lib库主要提供的调用类是SockIOPool和MemC ...
- ES系列十五、ES常用Java Client API
一.简介 1.先看ES的架构图 二.ES支持的客户端连接方式 1.REST API http请求,例如,浏览器请求get方法:利用Postman等工具发起REST请求:java 发起httpClien ...
- Java 9 揭秘(14. HTTP/2 Client API)
Tips 做一个终身学习的人. 在此章中,主要介绍以下内容: 什么是HTTP/2 Client API 如何创建HTTP客户端 如何使HTTP请求 如何接收HTTP响应 如何创建WebSocket的e ...
- Elasticsearch Java Rest Client API 整理总结 (一)——Document API
目录 引言 概述 High REST Client 起步 兼容性 Java Doc 地址 Maven 配置 依赖 初始化 文档 API Index API GET API Exists API Del ...
- Elasticsearch Java Rest Client API 整理总结 (二) —— SearchAPI
目录 引言 Search APIs Search API Search Request 可选参数 使用 SearchSourceBuilder 构建查询条件 指定排序 高亮请求 聚合请求 建议请求 R ...
- Elasticsearch Java Rest Client API 整理总结 (三)——Building Queries
目录 上篇回顾 Building Queries 匹配所有的查询 全文查询 Full Text Queries 什么是全文查询? Match 全文查询 API 列表 基于词项的查询 Term Term ...
- JAVA HDFS API Client 连接HA
如果Hadoop开启HA,那么用Java Client连接Hive的时候,需要指定一些额外的参数 package cn.itacst.hadoop.hdfs; import java.io.FileI ...
- Kafka 0.9+Zookeeper3.4.6集群搭建、配置,新Client API的使用要点,高可用性测试,以及各种坑 (转载)
Kafka 0.9版本对java client的api做出了较大调整,本文主要总结了Kafka 0.9在集群搭建.高可用性.新API方面的相关过程和细节,以及本人在安装调试过程中踩出的各种坑. 关于K ...
随机推荐
- part1:9-windows与Linux文件共享
1.winSCP 它是一个windows环境下使用SSH的开源图形化SFTP客户端.同时支持SCP协议.它主要功能就是在本地与远程计算机间安全的复制文件. 前提:Linux与windows能相互pin ...
- eclipse 配置动态web项目在servers中运行
第一步: window->preferences:Server->Runtime Environments窗口,add. 第二步: window->preferences:Proje ...
- c++中如何定义编译期间常量,即这个常量可以用于定义数组下标
在c++中,类里面的成员变量不仅仅可以被const修饰,还可以被static const修饰,此时一个内建类型(如int ,char ,long等)的static const 可以看做是一个编译期间的 ...
- 2018.10.21 codeforces1071B. Minimum path(dp+贪心+bfs)
传送门 唉考试的时候写错了两个细节调了一个多小时根本没调出来. 下来又调了半个小时才过. 其实很简单. 我们先dpdpdp出最开始最多多少个连续的aaa. 然后对于没法继续连续下去的用贪心+bfsbf ...
- 2018.09.27 bzoj2118: 墨墨的等式(最短路+背包)
传送门 好题啊. 首先找到最小的一个非零系数记做a1a_1a1,然后如果WWW modmodmod a1=W′a_1=W'a1=W′ modmodmod a1a_1a1,且WWW是方程的一个可行 ...
- 2018.09.09 bzoj4403: 序列统计(Lucas定理)
传送门 感觉单调不降序列什么的不好做啊. 于是我们序列中下标为i的元素的值加上i,这样就构成了一个单调递增的序列. 问题就变成了: 求出构造长度分别为1 ~ n且每个元素的值在l+1 ~ r+n之间的 ...
- HDU 1050 Moving Tables (贪心)
题意:在一个走廊两边都有对称分布的连续房间,现在有n张桌子需要从a移动到b房间.每次移动需要10分钟, 但是如果两次移动中需要经过相同的走廊位置,则不能同时进行,需要分开移动.最后求最少需要多长时间移 ...
- (最小生成树 Prim) Highways --POJ --1751
链接: http://poj.org/problem?id=1751 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 1150 ...
- 结对编程--四则运算(Java)梅进鹏 欧思良
结对编程--四则运算(Java)梅进鹏 欧思良 Github项目地址:https://github.com/MeiJinpen/Arithmetic 功能要求 题目:实现一个自动生成小学四则运算题目的 ...
- AME
http://wenku.baidu.com/view/a9dbebc789eb172ded63b7f4.htmlhttp://wenku.baidu.com/view/dde6eb040740be1 ...