首页 技术 正文
技术 2022年11月12日
0 收藏 918 点赞 2,587 浏览 5126 个字

一、前提

Jira Software、钉钉群、RESTful服务、LDAP服务

二、流程图

三、对接步骤

1、创建项目群,把相关人员拉入群

2、钉钉群的智能群助手里添加自定义机器人

3、设置机器人,安全设置里建议勾选IP地址段,将RESTful服务所在的机器IP填入

4、注意创建完成后的Webhook地址,RESTful服务用这个地址发送通知消息,后面步骤要用上

5、RESTful服务新增一个POST接口,并部署到服务器

 1 @ApiOperation(value = "JIRA网络钩子")
2 @PostMapping("/jiraWebHook")
3 @ResponseBody
4 public Result<Boolean> jiraWebHook(HttpServletRequest request) {
5 BufferedReader br = null;
6 String str, wholeStr = "";
7 try {
8 br = request.getReader();
9
10 while ((str = br.readLine()) != null) {
11 wholeStr += str;
12 }
13 log.info("jiraWebHook body: {}", wholeStr);
14 } catch (Exception e) {
15 log.error("jiraWebHook error", e);
16 } finally {
17 if (br != null) {
18 try {
19 br.close();
20 } catch (Exception e) {
21 }
22 }
23 }
24 return Result.success(JiraWebHookUtil.hook(JSONObject.parseObject(wholeStr, JiraPostData.class)));
25 }

  1 @Slf4j
2 public class JiraWebHookUtil {
3
4 private static final String DING_TALK_ROBOT_URL = "https://oapi.dingtalk.com/robot/send" +
5 "?access_token=xxxxxx";
6 private static final String JIRA_BASE_URL = "http://xxx.xxx.xxx.xxx:38080/browse/";
7 private static RestTemplate restTemplate = new RestTemplate();
8
9 public static boolean hook(JiraPostData postData){
10 try {
11 if(postData != null){
12 if(StringUtils.equals(postData.getWebhookEvent(), "jira:issue_updated")){
13 //更新事件
14 List<Item> items = postData.getChangelog().getItems();
15 String toUserId = Strings.EMPTY;
16 String fromUserId = Strings.EMPTY;
17 for(Item item : items){
18 if(StringUtils.equals(item.getField(), "assignee")){
19 toUserId = item.getTo();
20 fromUserId = item.getFrom();
21 break;
22 }
23 }
24 if(StringUtils.isNotBlank(toUserId) && StringUtils.isNotBlank(fromUserId)){
25 String toMobile = getUserMobile(toUserId);
26 String fromMobile = getUserMobile(fromUserId);
27 if(StringUtils.isNotBlank(toMobile) && StringUtils.isNotBlank(fromMobile)){
28 String issueKey = postData.getIssue().getKey();
29 String issueSummary = postData.getIssue().getFields().getSummary();
30 DingTalkMarkdownMessage msg = new DingTalkMarkdownMessage();
31 msg.setMsgtype("markdown");
32 Markdown markdown = new Markdown();
33 markdown.setTitle(postData.getIssue().getKey());
34 markdown.setText("### @" + fromMobile + " 【转移任务给】@" + toMobile
35 + "\n>任务编号:[" + issueKey + "](" + JIRA_BASE_URL + issueKey + ")"
36 + " \n任务标题:" + issueSummary);
37 msg.setMarkdown(markdown);
38 At at = new At();
39 at.setAtMobiles(Arrays.asList(toMobile, fromMobile));
40 msg.setAt(at);
41 return sendMsgToDingTalk(JSONObject.toJSONString(msg));
42 }
43 }
44 }else if(StringUtils.equals(postData.getWebhookEvent(), "jira:issue_created")){
45 //创建事件
46 String fromUserId = postData.getUser().getKey();
47 String toUserId = postData.getIssue().getFields().getAssignee().getKey();
48 if(StringUtils.isNotBlank(toUserId) && StringUtils.isNotBlank(fromUserId)){
49 String toMobile = getUserMobile(toUserId);
50 String fromMobile = getUserMobile(fromUserId);
51 if(StringUtils.isNotBlank(toMobile) && StringUtils.isNotBlank(fromMobile)){
52 String issueKey = postData.getIssue().getKey();
53 String issueSummary = postData.getIssue().getFields().getSummary();
54 DingTalkMarkdownMessage msg = new DingTalkMarkdownMessage();
55 msg.setMsgtype("markdown");
56 Markdown markdown = new Markdown();
57 markdown.setTitle(postData.getIssue().getKey());
58 markdown.setText("### @" + fromMobile + " 【指派任务给】@" + toMobile
59 + "\n>任务编号:[" + issueKey + "](" + JIRA_BASE_URL + issueKey + ")"
60 + " \n任务标题:" + issueSummary);
61 msg.setMarkdown(markdown);
62 At at = new At();
63 at.setAtMobiles(Arrays.asList(toMobile, fromMobile));
64 msg.setAt(at);
65 return sendMsgToDingTalk(JSONObject.toJSONString(msg));
66 }
67 }
68 }
69 }
70
71 }catch (Exception e) {
72 log.error("触发JIRA网络钩子失败", e);
73 }
74 return false;
75 }
76
77 private static boolean sendMsgToDingTalk(String msg){
78 JSONObject postData = JSONObject.parseObject(msg);
79 JSONObject result = restTemplate.postForObject(DING_TALK_ROBOT_URL, postData, JSONObject.class);
80 if(result != null
81 && result.getIntValue("errcode") == 0
82 && StringUtils.equals(result.getString("errmsg"), "ok")){
83 return true;
84 }
85 return false;
86 }
87
88 private static String getUserMobile(String userId){
89 String mobile = Strings.EMPTY;
90
91 Hashtable<String, String> env = new Hashtable<String, String>();
92 env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
93 env.put(Context.PROVIDER_URL, "ldap://xxxxxx:389");
94 env.put(Context.SECURITY_AUTHENTICATION, "simple");
95 env.put(Context.SECURITY_PRINCIPAL, "cn=xxx,dc=xxx,dc=xxx,dc=com");
96 env.put(Context.SECURITY_CREDENTIALS, "xxxxxx");
97 DirContext ctx = null;
98 try{
99 ctx = new InitialDirContext(env);
100 }catch(Exception e){
101 log.error("连接LDAP失败", e);
102 }
103
104 // 设置过滤条件
105 String filter = "(&(objectClass=top)(objectClass=inetOrgPerson)(cn=" + userId + "))";
106 // 限制要查询的字段内容
107 String[] attrPersonArray = {"cn", "mobile"};
108 SearchControls searchControls = new SearchControls();
109 searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
110 // 设置将被返回的Attribute
111 searchControls.setReturningAttributes(attrPersonArray);
112 // 三个参数分别为:
113 // 上下文;
114 // 要搜索的属性,如果为空或 null,则返回目标上下文中的所有对象;
115 // 控制搜索的搜索控件,如果为 null,则使用默认的搜索控件
116 try {
117 NamingEnumeration<SearchResult> answer = ctx.search(
118 "ou=People,dc=xxx,dc=xxx,dc=xxx", filter, searchControls);
119 // 输出查到的数据
120 while (answer.hasMore()) {
121 SearchResult result = answer.next();
122 Attribute attr = result.getAttributes().get("mobile");
123 mobile = attr.get().toString();
124 break;
125 }
126 }catch (Exception e){
127 log.error("查询LDAP用户信息失败", e);
128 }
129 return mobile;
130 }
131
132 }

6、Jira Software配置网络钩子,使用第5步的接口地址

四、验证效果

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,135
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,603
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,447
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,221
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,855
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,941