最近在搞自动化监控,有一项功能就是监测到异常情况时自动创建jira工单,于是乎对JIRA REST API 做了一些调研,其提供两种使用方式,一种是在项目中引入客户端封装包jira-rest-java-client-2.0.0-m2.jar,另一种是直接使用JIRA REST API 提供的curl命令行方式处理。
参考资料:https://docs.atlassian.com/jira/REST/7.0-SNAPSHOT
一。第一种方式jira-rest-java-client-2.0.0-m2.jar:
<repositories>
<repository>
<id>central</id>
<name>Atlassian Public Repository</name>
<layout>default</layout>
<url>https://maven.atlassian.com/content/groups/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependency> <groupId>com.atlassian.jira</groupId> <artifactId>jira-rest-java-client</artifactId> <version>2.0.0-m2</version> </dependency>
这种方式参考资料不好找,我基本是通过查看api一点点摸索的,而且需要引入许多第三方依赖包,相对第二种方式过于繁琐,这里只做了常用的方法封装,相关jar包见附件:
package com.nq.common; import java.net.URI; import java.net.URISyntaxException; import com.atlassian.jira.rest.client.JiraRestClient; import com.atlassian.jira.rest.client.JiraRestClientFactory; import com.atlassian.jira.rest.client.domain.BasicIssue; import com.atlassian.jira.rest.client.domain.Issue; import com.atlassian.jira.rest.client.domain.IssueType; import com.atlassian.jira.rest.client.domain.SearchResult; import com.atlassian.jira.rest.client.domain.Transition; import com.atlassian.jira.rest.client.domain.User; import com.atlassian.jira.rest.client.domain.input.IssueInput; import com.atlassian.jira.rest.client.domain.input.IssueInputBuilder; import com.atlassian.jira.rest.client.domain.input.TransitionInput; import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory; /** * jira java工具类 * jira-rest-java-client-2.0.0-m2.jar * @author hanqunfeng * */ public class JiraUtil { public static void main(String[] args) { // TODO Auto-generated method stub try { // JiraUtil.getIssue("NQCP-35"); // JiraUtil.createIssue("NQCP", 1l, "工单详细信息<br>工单详细信息", // "工单主题", "username"); // JiraUtil.printAllIssueType(); // JiraUtil.changeIssueStatus("NQCP-35", 2); // JiraUtil.getUser("username"); //查询用户负责的所有工单 JiraUtil.searchIssues("assignee=username"); System.out.println("*****************************"); JiraUtil.searchIssues("assignee=username order by duedate"); System.out.println("*****************************"); JiraUtil.searchIssues("assignee=username order by issueType"); System.out.println("*****************************"); //从0开始数,从第5条开始,取两条 // JiraUtil.searchIssues("assignee=username",5,2); // // System.out.println("*****************************"); // JiraUtil.searchIssues("project=NQCP"); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } } static JiraRestClientFactory factory = new AsynchronousJiraRestClientFactory(); static String uri = "http://jira.local.com/jira"; static String user = "username"; static String pwd = "password"; static JiraRestClient restClient; /** * 获得jira的客户端 * * @return JiraRestClient * @throws URISyntaxException */ static JiraRestClient getJiraRestClient() throws URISyntaxException { if (restClient == null) { URI jiraServerUri = new URI(uri); restClient = factory.createWithBasicHttpAuthentication( jiraServerUri, user, pwd); } return restClient; } /** * 获得工单信息 * * @param issueKey * 工单key,比如:NQCP-5 * @throws URISyntaxException */ public static Issue getIssue(String issueKey) throws URISyntaxException { Issue issue = null; JiraRestClient restClient = getJiraRestClient(); // get issue through issueKey try { issue = restClient.getIssueClient().getIssue(issueKey).claim(); // 打印工单后续的工作流 Iterable<Transition> iter = restClient.getIssueClient() .getTransitions(issue).claim(); for (Transition transition : iter) { System.out.println(transition); } } catch (Exception e) { e.printStackTrace(); } // 打印工单明细 System.out.println(issue); return issue; } /** * 检索工单 * @param jql * * @return * @throws URISyntaxException */ public static Iterable<BasicIssue> searchIssues(String jql) throws URISyntaxException{ JiraRestClient restClient = getJiraRestClient(); SearchResult searchResutl = restClient.getSearchClient().searchJql(jql).claim(); Iterable<BasicIssue> iter = searchResutl.getIssues(); for (BasicIssue baseIssue : iter) { System.out.println(baseIssue); } return iter; } /** * 检索工单 * @param jql * @param startIndex * @param maxResults * @return * @throws URISyntaxException */ public static Iterable<BasicIssue> searchIssues(String jql,int startIndex, int maxResults) throws URISyntaxException{ JiraRestClient restClient = getJiraRestClient(); SearchResult searchResutl = restClient.getSearchClient().searchJql(jql,maxResults,startIndex).claim(); Iterable<BasicIssue> iter = searchResutl.getIssues(); for (BasicIssue baseIssue : iter) { System.out.println(baseIssue); } return iter; } /** * 打印jira系统中已经创建的全部issueType * issuetype/ * * @throws URISyntaxException */ public static Iterable<IssueType> printAllIssueType() throws URISyntaxException { JiraRestClient restClient = getJiraRestClient(); Iterable<IssueType> iter = restClient.getMetadataClient() .getIssueTypes().claim(); for (IssueType issueType : iter) { System.out.println(issueType); } return iter; } /** * 创建一个新工单 * * @param projectKey * 项目key,比如:NQCP * @param issueType * 工单类型,来源于printAllIssueType()的id * @param description * 工单描述 * @param summary * 工单主题 * @param assignee * 工单负责人 * @throws URISyntaxException */ public static BasicIssue createIssue(String projectKey, Long issueType, String description, String summary, String assignee) throws URISyntaxException { JiraRestClient restClient = getJiraRestClient(); IssueInputBuilder issueBuilder = new IssueInputBuilder(projectKey, issueType); issueBuilder.setDescription(description); issueBuilder.setSummary(summary); if (getUser(assignee) != null) { issueBuilder.setAssigneeName(assignee); } IssueInput issueInput = issueBuilder.build(); BasicIssue bIssue = null; try { bIssue = restClient.getIssueClient().createIssue(issueInput) .claim(); } catch (Exception e) { e.printStackTrace(); } System.out.println(bIssue); return bIssue; } /** * 获取用户信息 * * @param username * @return * @throws URISyntaxException */ public static User getUser(String username) throws URISyntaxException { JiraRestClient restClient = getJiraRestClient(); User user = null; try { user = restClient.getUserClient().getUser(username).claim(); } catch (Exception e) { e.printStackTrace(); } System.out.println(user); return user; } /** * 改变工单workflow状态 issue的workflow是不可以随便改变的,必须按照流程图的顺序进行改变,具体如下: * * 当前状态 :说明 变更流程id:说明 >> 变更后状态 1:open,开放 1)4:start progress >> in progerss 2)5:resolve issue >> resolved 3)2:close issue >> closed 3:in progerss 正在处理 1)301:stop progress >> open 2)5:resolve issue >> resolved 3)2:close issue >> closed 4:resolved 已解决 1)701:close issue >> closed 2)3:reopen issue >> reopened 5:reopened 重新打开 1)4:start progress >> in progerss 2)5:resolve issue >> resolved 3)2:close issue >> closed 6:closed 已关闭 1)3:reopen issue >> reopened * * * 可通过如下方式查看当前工单的后续工作流程: Iterable<Transition> iter = * restClient.getIssueClient().getTransitions(issue).claim(); * * for (Transition transition : iter) { System.out.println(transition); } * * 输出结果:当前工单状态是 5:reopened 重新打开 Transition{id=4, name=Start Progress, * fields=[]} Transition{id=5, name=Resolve Issue, * fields=[Field{id=fixVersions, isRequired=false, type=array}, * Field{id=resolution, isRequired=true, type=resolution}]} Transition{id=2, * name=Close Issue, fields=[Field{id=fixVersions, isRequired=false, * type=array}, Field{id=resolution, isRequired=true, type=resolution}]} * * * @param issuekey * 工单key * @param statusId * 变更流程id * @param fields * 随状态需要传递的参数,可以为空 * @throws URISyntaxException */ public static void changeIssueStatus(String issuekey, int statusId) throws URISyntaxException { JiraRestClient restClient = getJiraRestClient(); Issue issue = getIssue(issuekey); if (issue != null) { TransitionInput tinput = new TransitionInput(statusId); restClient.getIssueClient().transition(issue, tinput); } // try { // Thread.sleep(3000);//因为是异步处理,所以状态是延迟变更的,暂停一下可以看到状态已经变更了 // issue = getIssue(issuekey); // System.out.println(issue.getStatus()); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } } }
二。JIRA REST API
这种方式使用curl命令进行处理,几乎涵盖了所有的jira处理,这里也只对常用的功能进行的封装。
接口中的 2 可以使用 latest 替代。http://localhost:9080/rest/api/latest/issue/ORCM-1 《==》 http://localhost:9080/rest/api/2/issue/ORCM-1
package com.nq.common; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; /** * JIRA REST API 工具类 * https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials * https://docs.atlassian.com/jira/REST/7.0-SNAPSHOT/ * @author hanqunfeng * */ public class JiraAPIUtil { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub // JiraAPIUtil.getIssue("NQCP-35"); // Map<String, String> map = new HashMap<String, String>(); // map.put("assignee", "{\"name\":\"username\"}"); // JiraAPIUtil.createIssue("NQCP", "Bug", "哈哈哈啊哈哈", "测试01", map); // Map<String,String> map = new HashMap<String,String>(); // map.put("assignee", "{\"name\":\"username\"}"); // map.put("summary", "\"summary00002\""); // JiraAPIUtil.editIssue("NQCP-38", map); // JiraAPIUtil.searchIssues("assignee=username"); // System.out.println("*****************************"); // JiraAPIUtil.searchIssues("assignee=username+order+by+duedate"); // System.out.println("*****************************"); // JiraAPIUtil.addComments("NQCP-39", "123456哈哈哈哈"); // JiraAPIUtil.deleteIssueByKey("NQCP-38"); JiraAPIUtil.addAttachment("NQCP-39", "d://myfile01.txt"); //linux路径: /home/boss/myfile.txt } static String uri = "http://jira.local.com/jira"; static String user = "username"; static String pwd = "password"; static String osname = System.getProperty("os.name").toLowerCase(); /** * 执行shell脚本 * * @param command * @return * @throws IOException */ private static String executeShell(String command) throws IOException { StringBuffer result = new StringBuffer(); Process process = null; InputStream is = null; BufferedReader br = null; String line = null; try { if (osname.indexOf("windows") >= 0) { process = new ProcessBuilder("cmd.exe", "/c", command).start(); System.out.println("cmd.exe /c " + command); //安装Cygwin,使windows可以执行linux命令 } else { process = new ProcessBuilder("/bin/sh", "-c", command).start(); System.out.println("/bin/sh -c " + command); } is = process.getInputStream(); br = new BufferedReader(new InputStreamReader(is, "UTF-8")); while ((line = br.readLine()) != null) { System.out.println(line); result.append(line); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { br.close(); process.destroy(); is.close(); } return result.toString(); } /** * 活动工单信息 * * @param issueKey * 工单key * @return * @throws IOException */ public static String getIssue(String issueKey) throws IOException { String command = "curl -D- -u " + user + ":" + pwd + " -X GET -H \"Content-Type: application/json\" \"" + uri + "/rest/api/2/issue/" + issueKey + "\""; String issueSt = executeShell(command); return issueSt; } /** * 创建工单 * * @param projectKey * 项目key * @param issueType * 工单类型 name * @param description * 工单描述 * @param summary * 工单主题 * @param assignee * 工单负责人 * @param map * 工单参数map,key为参数名称,value为参数值,参数值必须自带双引号 比如: map.put("assignee", * "{\"name\":\"username\"}"); map.put("summary", * "\"summary00002\""); * @return * @throws IOException */ public static String createIssue(String projectKey, String issueType, String description, String summary, Map<String, String> map) throws IOException { String fields = ""; if (map != null && map.size() > 0) { StringBuffer fieldsB = new StringBuffer(); for (Map.Entry<String, String> entry : map.entrySet()) { fieldsB.append(",\"").append(entry.getKey()).append("\":") .append(entry.getValue()); } fields = fieldsB.toString(); } String command = "curl -D- -u " + user + ":" + pwd + " -X POST --data '{\"fields\": {\"project\":{ \"key\": \"" + projectKey + "\"},\"summary\": \"" + summary + "\",\"description\": \"" + description + "\",\"issuetype\": {\"name\": \"" + issueType + "\"}" + fields + "}}' -H \"Content-Type: application/json\" \"" + uri + "/rest/api/2/issue/\""; String issueSt = executeShell(command); return issueSt; } /** * 更新工单 * * @param issueKey * 工单key * @param map * 工单参数map,key为参数名称,value为参数值,参数值必须自带双引号 比如: map.put("assignee", * "{\"name\":\"username\"}"); map.put("summary", * "\"summary00002\""); * @return * @throws IOException */ public static String editIssue(String issueKey, Map<String, String> map) throws IOException { StringBuffer fieldsB = new StringBuffer(); for (Map.Entry<String, String> entry : map.entrySet()) { fieldsB.append("\"").append(entry.getKey()).append("\":") .append(entry.getValue()).append(","); } String fields = fieldsB.toString(); fields = fields.substring(0, fields.length() - 1); String command = "curl -D- -u " + user + ":" + pwd + " -X PUT --data '{\"fields\": { " + fields + "}}' -H \"Content-Type: application/json\" \"" + uri + "/rest/api/2/issue/" + issueKey + "\""; String issueSt = executeShell(command); return issueSt; } /** * 查询工单 * @param jql * assignee=username * assignee=username&startAt=2&maxResults=2 * assignee=username+order+by+duedate * project=projectKey+order+by+duedate&fields=id,key * @return * @throws IOException */ public static String searchIssues(String jql) throws IOException{ String command = "curl -D- -u " + user + ":" + pwd + " -X GET -H \"Content-Type: application/json\" \"" + uri + "/rest/api/2/search?jql=" + jql + "\""; String issueSt = executeShell(command); return issueSt; } /** * 为工单增加注释说明 * @param issueKey 工单key * @param comment 注释说明 * @return * @throws IOException */ public static String addComments(String issueKey,String comments) throws IOException{ String command = "curl -D- -u " + user + ":" + pwd + " -X PUT --data '{\"update\": { \"comment\": [ { \"add\": { \"body\":\""+comments+"\" } } ] }}' -H \"Content-Type: application/json\" \"" + uri + "/rest/api/2/issue/" + issueKey + "\""; String issueSt = executeShell(command); return issueSt; } /** * 删除工单 * @param issueKey 工单key * @return * @throws IOException */ public static String deleteIssueByKey(String issueKey) throws IOException{ String command = "curl -D- -u " + user + ":" + pwd + " -X DELETE -H \"Content-Type: application/json\" \"" + uri + "/rest/api/2/issue/" + issueKey + "\""; String issueSt = executeShell(command); return issueSt; } /** * 上传附件 * @param issueKey 工单key * @param filepath 文件路径 * @return * @throws IOException */ public static String addAttachment(String issueKey,String filepath) throws IOException{ String command = "curl -D- -u " + user + ":" + pwd + " -X POST -H \"X-Atlassian-Token: nocheck\" -F \"file=@"+filepath+"\" \"" + uri + "/rest/api/2/issue/" + issueKey + "/attachments\""; String issueSt = executeShell(command); return issueSt; } }
相关推荐
**JIRA REST Java Client**是Atlassian官方提供的一款用于与JIRA进行交互的Java库,它使得开发人员能够轻松地通过RESTful API访问和操作JIRA系统。这个库提供了丰富的功能,包括创建、更新、查询问题(issues)、...
Atlassian的Java JIRA REST API实现。 jira-rest-client取决于, , , 。 JIRA REST API文档可以在找到 安装 从Maven Central Repository检查最新发布的工件版本( ) 将此依赖项片段添加到pom.xml中。 ...
在导入这些Jar包后,开发者可以通过Jira的REST API或SOAP API来执行各种操作,例如: - 创建、更新、删除Jira问题。 - 查询问题的详细信息,如状态、优先级、指派者等。 - 搜索和过滤问题,基于不同的条件和过滤器...
大多数 Jira REST API 由(官方?) 基本用法 以最简单的形式,您可以: JiraApi api = JiraClient.create("url"); 每次调用api导致 HTTP(s) 调用。 JiraClient 是 Jira API 的直接包装器,没有任何美化。 按照...
Jira Rest Java Client Library 编译所需要的所有依赖包整合,同时包括了FLex的BlazeDS所需依赖包。 此为分卷一。
使用Atlassian的jira Java客户端的示例项目外部链接最近的jira Java rest api使用情况: : 获取所有项目和票证: : 快速教程baeldung: ://www.baeldung.com/jira-rest-api 吉拉休息Java客户端库: & Maven: : ...
这个工具利用了 `jira-rest-java-client-re` 库,这是一个官方的 JIRA REST 客户端,允许开发者通过 REST API 与 JIRA 服务器进行通信。以下是对该应用程序及其核心功能的详细解释: 1. **JIRA REST API 集成**: ...
`jira-client-api` 是一个用于与 Atlassian Jira 进行交互的 Java 库,它提供了一个简洁的构建者模式,使得开发者可以更方便地调用 Jira 的 REST API。这个库简化了与 Jira 服务器的集成过程,减少了编写大量 HTTP ...
为了实现Excel与JIRA的交互,可以利用JIRA的REST API或插件如JIRA Importers Plugin,将Excel数据导入JIRA,或反之将JIRA数据导出到Excel。这样,团队成员可以在Excel中进行高级数据分析,同时保持与JIRA中的实时...
Jira Rest Java Client Library 编译所需要的所有依赖包整合,同时包括了FLex的BlazeDS所需依赖包。 此为分卷二。
总之,Java-JIRA的jar包集合是一个强大的工具,它使得开发人员能够利用JIRA的强大功能,如问题跟踪、项目管理和报告,而无需直接与复杂的REST API交互。正确地理解和使用这些库,可以大大提高Java应用程序与JIRA集成...
jira所需jar包 atlassian-universal-plugin-manager-plugin-2.17.4.jar
6. **编程语言示例**:不同编程语言都有库或模块来方便调用JIRA API,例如Python的`jira`库,Java的`Atlassian-Jira-soap-client`,JavaScript的`axios`等。 7. **应用示例**:可能的应用场景包括自动化工作流、...
吉拉客户 jira-client是Java的简单轻量级JIRA REST客户端库。 该项目的目标是为JIRA交互提供简单,简洁的英语惯用语。 为了实现此目标,jira-client缺乏Java应用程序中经常出现的冗长而繁琐的扭曲。 而且由于该实现...
这个工具基于Java编程语言开发,利用了Atlassian JIRA的REST API来与JIRA服务器进行交互。Java作为后端开发的主流语言,有着丰富的库和框架支持,能够提供高效且稳定的性能,确保批量操作的顺利完成。 使用此工具时...
jira-实用程序JIRA Utilities 为您提供了 JIRA REST API 的代理(您可以使用简单的 JavaScript 提取您需要的所有信息)和一些有用的工具,可帮助您将某些 JIRA 数据可视化。免责声明我不是一个大的 JavaScript 专家...
客户Jira Cloud平台REST API API版本:1001.0.0-SNAPSHOT 建立日期:2021-04-16T21:45:04.339922 + 09:00 [亚洲/首尔] Jira Cloud平台REST API文档由自动生成要求构建API客户端库需要: Java 1.8+ Maven / Gradle...
- **JIRA REST API**:与 JIRA 后端通信时,使用 JIRA 提供的 REST API 进行数据交互,获取或更新数据。 - **错误处理和日志**:确保在与 JIRA 交互时有适当的错误处理机制,并记录相关日志,便于调试。 - **单元...
除了我不是一个热情的Java开发人员,而是喜欢API之外,这个工具是使用PHP创建的,并且使用了Jira REST API。 可打印的Jira卡将如下所示: 除了功能要求之外,我还有一些技术要求: 应用程序应仅运行而无需设置 ...
例如,`jira-rest-java-client-core.jar`可能是JIRA REST客户端库的一部分,帮助开发者轻松地从Java代码调用这些API。 5. **认证与授权流程**:在JIRA中,认证过程验证用户的身份,而授权决定用户能做什么。jar包...