JIRA REST API ---- JAVA

最近在搞自动化监控,有一项功能就是监测到异常情况时自动创建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;
	}

}

 

 

 

 

 

 

猜你喜欢

转载自hanqunfeng.iteye.com/blog/2245848