java调tapd-api获取Bug并发企微通知

需求

线上报障定时推送

定时任务:每天上午9点半、下午5点半 基于企微机器人做推送

  1. 未处理线上报障

判断条件: 【tapd】项目(workspace_id): 68331031 (用户产品部(C端))、61792590
(渠道厂商)、30892271 (互动营销与销售单产品线) 【tapd】标题:线上报障 【tapd】迭代: 线上问题
【tapd】状态:新、重新打开 【tapd】优先级:高、紧急 (2022-11-23新增需求) 【tapd】创建时间:最近10天
推送内容(基于企微机器人): 【线上报障】近10天内优先级高且预计修复时间近5天共有*个未处理报障: 【线上报障_汽车论坛】2个:
详情请查看: 1)
https://www.tapd.cn/68331031/bugtrace/bugs/view?bug_id=1168331031001029887
(预计修复时间:2022-11-30)
2)https://www.tapd.cn/68331031/bugtrace/bugs/view?bug_id=1168331031001028789
(预计修复时间: 无) 【线上报障_车商家】3个:

  1. 已处理但未回复的报障

判断条件: 【tapd】项目(workspace_id): 68331031 (汽车网用户产品部(C端))、61792590
(汽车网渠道厂商)、30892271 (互动营销与销售单产品线) 【tapd】标题:线上报障 【tapd】迭代: 线上问题
【tapd】状态: not in (新、重新打开、解决中) 【tapd】是否已回复: 否 、 空 【tapd】创建时间:最近10天

推送内容(基于企微机器人): 【线上报障_解决方案】近10天共有*个已处理但未回复的报障: 【线上报障_汽车论坛】2个: 详情请查看: 1)
https://www.tapd.cn/68331031/bugtrace/bugs/view?bug_id=1168331031001029887

附录:
项目BUG链接
https://www.tapd.cn/tapd_fe/68331031/bug/list?confId=1168331031001041454&page=1&queryToken=e2a58359f427e340d050df7f85f9bf1f

需求分析

tapd提供api可供分析

//查询bug详情
https://api.tapd.cn/bugs? 
//查询bug数量
https://api.tapd.cn/bugs/count 

详情请参考tapd-api帮助文档

代码

企微通知公共服务

package com.auto.qyapi.twoutil;import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.Base64;
import java.util.concurrent.TimeUnit;/*** 微信群机器人*/
public class WeChatBotUtils {private Logger log = LoggerFactory.getLogger(this.getClass());// 配置的群机器人Webhook地址private String botUrl;// 配置代理服务器private String hostname;private int port;// 需要使用代理时调用的构造函数public WeChatBotUtils(String botUrl, String hostname, int port) {this.botUrl = botUrl;this.hostname = hostname;this.port = port;}// 直接从配置中获取代理信息public WeChatBotUtils(String botUrl, boolean byProxy) {this.botUrl = botUrl;if (byProxy==false) {hostname = "192.168.11.254";port = 8080;}}/*** 发送文字消息** @param msg 需要发送的消息* @return* @throws Exception*/public String sendTextMsg(String msg) throws Exception {JSONObject text = new JSONObject();text.put("content", msg);JSONObject reqBody = new JSONObject();reqBody.put("msgtype", "text");reqBody.put("text", text);reqBody.put("safe", 0);return callWeChatBot(reqBody.toString());}/*** 发送图片消息,需要对图片进行base64编码并计算图片的md5值** @param path 需要发送的图片路径* @return* @throws Exception*/public String sendImgMsg(String path) throws Exception {String base64 = "";String md5 = "";// 获取Base64编码try {FileInputStream inputStream = new FileInputStream(path);byte[] bs = new byte[inputStream.available()];inputStream.read(bs);base64 = Base64.getEncoder().encodeToString(bs);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}// 获取md5值try {FileInputStream inputStream = new FileInputStream(path);byte[] buf = new byte[inputStream.available()];inputStream.read(buf);md5 = DigestUtils.md5Hex(buf);} catch (IOException e) {e.printStackTrace();}JSONObject image = new JSONObject();image.put("base64", base64);image.put("md5", md5);JSONObject reqBody = new JSONObject();reqBody.put("msgtype", "image");reqBody.put("image", image);reqBody.put("safe", 0);return callWeChatBot(reqBody.toString());}/*** 发送MarKDown消息** @param msg 需要发送的消息* @return* @throws Exception*/public String sendMarKDownMsg(String msg) throws Exception {JSONObject markdown = new JSONObject();markdown.put("content", msg);JSONObject reqBody = new JSONObject();reqBody.put("msgtype", "markdown");reqBody.put("markdown", markdown);reqBody.put("safe", 0);return callWeChatBot(reqBody.toString());}/*** 发送文件消息,需要先将文件上传到企业微信临时素材,再根据获取的media_id调用群机器人** @param path 需要发送的文件路径* @return* @throws Exception*/public String sendFileMsg(String path) throws Exception {File file = new File(path);// 构造RequestBody对象,用来携带要提交的数据;需要指定MediaType,用于描述请求/响应 body 的内容类型MediaType contentType = MediaType.parse("application/form-data; boundary");RequestBody body = RequestBody.create(contentType, file);RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("file", file.getName(), body).build();// 上传到临时素材String key = botUrl.substring(botUrl.indexOf("key="));System.out.println(key);String mediaUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?type=file&"+key;log.info("将文件" + path+ "上传到临时素材:" + mediaUrl);String respMsg = okHttp(requestBody, mediaUrl);// 获取临时素材idJSONObject result = JSONObject.parseObject(respMsg);String media_id = result.getString("media_id");JSONObject fileJson = new JSONObject();fileJson.put("media_id", media_id);JSONObject reqBody = new JSONObject();reqBody.put("msgtype", "file");reqBody.put("file", fileJson);reqBody.put("safe", 0);// 调用群机器人发送消息return callWeChatBot(reqBody.toString());}/*** 调用群机器人** @param reqBody 接口请求参数* @throws Exception 可能有IO异常*/public String callWeChatBot(String reqBody) throws Exception {log.info("请求参数:" + reqBody);// 构造RequestBody对象,用来携带要提交的数据;需要指定MediaType,用于描述请求/响应 body 的内容类型MediaType contentType = MediaType.parse("application/json; charset=utf-8");RequestBody body = RequestBody.create(contentType, reqBody);// 调用群机器人String respMsg = okHttp(body, botUrl);if ("0".equals(respMsg.substring(11, 12))) {log.info("向群发送消息成功!");} else {log.info("请求失败!");// 发送错误信息到群sendTextMsg("群机器人推送消息失败,错误信息:\n" + respMsg);}return respMsg;}/**** @param body 携带需要提交的数据* @param url 请求地址* @return* @throws Exception*/public String okHttp(RequestBody body, String url) throws Exception {// 构造和配置OkHttpClientOkHttpClient client;if(hostname != null && port != 0){client = new OkHttpClient.Builder().proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostname, port))) // 内网使用代理,不需要可注释.connectTimeout(10, TimeUnit.SECONDS) // 设置连接超时时间.readTimeout(20, TimeUnit.SECONDS) // 设置读取超时时间.build();} else{client = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS) // 设置连接超时时间.readTimeout(20, TimeUnit.SECONDS) // 设置读取超时时间.build();}// 构造Request对象Request request = new Request.Builder().url(url).post(body).addHeader("cache-control", "no-cache") // 响应消息不缓存.build();// 构建Call对象,通过Call对象的execute()方法提交异步请求Response response = null;try {response = client.newCall(request).execute();} catch (IOException e) {e.printStackTrace();}// 请求结果处理byte[] datas = response.body().bytes();String respMsg = new String(datas);log.info("返回结果:" + respMsg);return respMsg;}}

tapd-api

package com.auto.qyapi.twoutil;import com.alibaba.fastjson.JSONObject;import java.util.HashMap;
import java.util.Map;public class TapdApiTool {static int pageSize = 200;//得出BUG总数public  int getbugtotalCount(String workspaceid, String iteration_id) {int totalCount = getbugscount(workspaceid, iteration_id);return totalCount;}//得出bug总页数public  int getbugtotlePages(String workspaceid, String iteration_id) {int totalPage = 0;int totalCount = getbugtotalCount(workspaceid, iteration_id);if (totalCount % pageSize == 0) {totalPage = totalCount / pageSize;} else {totalPage = totalCount / pageSize + 1;}return totalPage;}/**Authorization Basic Auth认证信息,在tapd管理中心处获取**/public static Map getheadermap() {Map<String, String> headerMap = new HashMap<String, String>();headerMap.put("Authorization", "Basic ................");return headerMap;}/*** 获取bug数量** @return*/public  JSONObject gettapdbugs(String workspaceid) {SendRuquest sendRuquest = new SendRuquest();String url = "https://api.tapd.cn/bugs";Map<String, String> params = new HashMap<String, String>();params.put("workspace_id", workspaceid);params.put("limit", "100");JSONObject result = null;try {result = JSONObject.parseObject(sendRuquest.sendGetList(url, params, getheadermap()));} catch (Exception e) {e.printStackTrace();}return result;}/*** 汽车tapd获取线上报障问题分页* https://api.tapd.cn/bugs?workspace_id=68331031&iteration_id=1168331031001028936* https://api.tapd.cn/bugs?workspace_id=61792590&iteration_id=1161792590001000446* https://api.tapd.cn/bugs?workspace_id=30892271&iteration_id=1130892271001000738* 获取bug数量* @return*/public   JSONObject getautobugslist(String workspaceid, String iteration_id, String page) {SendRuquest sendRuquest = new SendRuquest();String url = "https://api.tapd.cn/bugs";Map<String, String> params = new HashMap<String, String>();params.put("workspace_id", workspaceid);params.put("iteration_id", iteration_id);params.put("limit", Integer.toString(pageSize));params.put("page", page);JSONObject result = null;try {result = JSONObject.parseObject(sendRuquest.sendGetList(url, params, getheadermap()));} catch (Exception e) {e.printStackTrace();}return result;}/*** 统计缺陷数量*/public static int getbugscount(String workspaceid, String iteration_id) {SendRuquest sendRuquest = new SendRuquest();String url = "https://api.tapd.cn/bugs/count";Map<String, String> params = new HashMap<String, String>();params.put("workspace_id", workspaceid);params.put("iteration_id", iteration_id);params.put("title", "【线上报障");int bugcount = 0;try {JSONObject jsonObject = JSONObject.parseObject(sendRuquest.sendGetList(url, params, getheadermap()));bugcount = jsonObject.getJSONObject("data").getInteger("count");} catch (Exception e) {e.printStackTrace();}return bugcount;}}

业务代码

处理需求的代码

package com.auto.qyapi.twoutil;import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;/*** 核心业务类*/
public class TapdApiBusiness {public static TapdApiTool tapdApiTool=new TapdApiTool();/*** 得到总的线上故障的所有应用名称*/public static List<String> getprojectname(String workspaceid, String iteration_id) {//System.out.println("开始getprojectname===============");List<String> allname = new ArrayList<>();//得出总页数int totalPage = tapdApiTool.getbugtotlePages(workspaceid, iteration_id);//循环限每一页数据for (int i = 1; i <= totalPage; i++) {JSONObject jsonObject =tapdApiTool.getautobugslist(workspaceid, iteration_id, Integer.toString(i));JSONArray array = jsonObject.getJSONArray("data");for (int j = 0; j < array.size(); j++) {//解析每页的bug数据JSONObject bugs = array.getJSONObject(j);String title = bugs.getJSONObject("Bug").getString("title");//标题获取包括线上报障字眼的才算if (title.contains("【线上报障_")) {// System.out.println("原title==" + title);String rightname = title.split("_")[1].split("】")[0];allname.add(rightname);}if (title.contains("【线上报障-")) {//System.out.println("原title==" + title);String rightname = title.split("-")[1].split("】")[0];allname.add(rightname);}}}//System.out.println("去重前的数据:====" + allname);//名称的list去重归类List<String> vector = new Vector<String>();Set<String> set = new HashSet<String>(allname);vector = new Vector<String>(set);//System.out.println("去重之后的数据:" + vector);return vector;}/*** 【统计时间】:当天* 【tapd】迭代: 线上问题* 【统计状态】新、解决中、待测试、重新打开* 【线上报障】今天共有*个待处理:* 【线上报障_汽车论坛】2个;【线上报障_汽车APP】3个* 【tapd链接】列表*/public List<ResultEntity> getbugsByday(String workspaceid, String iteration_id,int beforeDays ) {List<ResultEntity> resultEntityList=new ArrayList<>();int totalPage = tapdApiTool.getbugtotlePages(workspaceid, iteration_id);DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");IsIntenDay isIntenDay=new IsIntenDay();//循环每一页for (int i = 1; i <= totalPage; i++) {JSONObject jsonObject = tapdApiTool.getautobugslist(workspaceid, iteration_id, Integer.toString(i));JSONArray array = jsonObject.getJSONArray("data");//循环一页里每一个BUGfor (int j = 0; j < array.size(); j++) {//处理每一个BUGJSONObject bugs = array.getJSONObject(j);String title = bugs.getJSONObject("Bug").getString("title");//标题获取包括线上报障字眼的才算if (title.contains("线上报障_")||title.contains("线上报障-")) {String created = bugs.getJSONObject("Bug").getString("created");//如果大于今天的开始日期,小于今天的结束日期if (isIntenDay.getDayDiffFromToday1(created,beforeDays)) {//如果是当天的BUGString status = bugs.getJSONObject("Bug").getString("status");if ((status.equals("new") || status.equals("reopened"))) {String priority = bugs.getJSONObject("Bug").getString("priority");//优先级高或紧急if(priority.equals("high")||priority.equals("urgent")){ResultEntity resultEntity=new ResultEntity();;String id = bugs.getJSONObject("Bug").getString("id");//得到应用名String projectname = title.split("_")[1].split("】")[0];String  url = "https://www.tapd.cn/"+workspaceid+"/bugtrace/bugs/view?bug_id="+id;String custom_field_7 = bugs.getJSONObject("Bug").getString("custom_field_7");//预计修复时间String current_owner = bugs.getJSONObject("Bug").getString("current_owner");//处理人//预计修复时间不为空if(custom_field_7 ==null || custom_field_7.equals("") || custom_field_7.length()==0){resultEntity.setProjectName(projectname);resultEntityList.add(resultEntity);resultEntity.setUrl("["+title.split("_")[1].split("】")[1]+"]"+"("+url+")"+" "+"(预计修复时间:暂无), "+"<font color=\"warning\">"+current_owner+"</font>");}else {//预计修复时间不为空//预计修复时间近5天if (isIntenDay.getDayDiffFromToday2(custom_field_7,5)) {resultEntity.setProjectName(projectname);resultEntityList.add(resultEntity);resultEntity.setUrl("["+title.split("_")[1].split("】")[1]+"]"+"("+url+")"+" "+"(预计修复时间:"+custom_field_7+"), "+"<font color=\"warning\">"+current_owner+"</font>");}}}}}}}}return resultEntityList;}/*本周线上报障关键字段【tapd】标题:线上报障【tapd】迭代: 线上问题【tapd】状态:not in (新、重新打开、解决中)【tapd】是否已回复: 否 、 空【tapd】创建时间:本周 (本周一 到 当前时间)*/public List<ResultEntity> getbugsByweek(String workspaceid, String iteration_id,int beforeDays){List<ResultEntity> resultEntityList=new ArrayList<>();IsIntenDay isIntenDay=new IsIntenDay();System.out.println("开始统计每周bug分布情况===============");int totalPage = tapdApiTool.getbugtotlePages(workspaceid, iteration_id);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");StringBuffer urls=new StringBuffer();//循环所有名称来找bug数量try {for (int i = 1; i <= totalPage; i++) {JSONObject jsonObject = tapdApiTool.getautobugslist(workspaceid, iteration_id, Integer.toString(i));JSONArray array = jsonObject.getJSONArray("data");for (int j = 0; j < array.size(); j++) {JSONObject bugs = array.getJSONObject(j);String title = bugs.getJSONObject("Bug").getString("title");//标题获取包括线上报障字眼的才算if (title.contains("线上报障_") || title.contains("线上报障-")) {String created = bugs.getJSONObject("Bug").getString("created");//判断bug创建时间是否为本周一至当前执行任务时间,即本周,改为10天之内System.out.println(created+"是否为近10天内:"+isIntenDay.isten(created,beforeDays));if (isIntenDay.getDayDiffFromToday1(created,beforeDays)) {String status = bugs.getJSONObject("Bug").getString("status");if (!(status.equals("new") || !(status.equals("in_progress")) || !(status.equals("reopened")))) {//是否已回复String reply = bugs.getJSONObject("Bug").getString("custom_field_10");//统计 “否”和空if (!(reply.equals("是"))) {ResultEntity resultEntity=new ResultEntity();String projectname = title.split("_")[1].split("】")[0];String id=bugs.getJSONObject("Bug").getString("id");String custom_field_7 = bugs.getJSONObject("Bug").getString("custom_field_7");String url="https://www.tapd.cn/"+workspaceid+"/bugtrace/bugs/view?bug_id="+id;resultEntity.setUrl("["+title.split("_")[1].split("】")[1]+"]"+"("+url+")");resultEntity.setProjectName(projectname);resultEntityList.add(resultEntity);System.out.println("近10天内:"+id+title);}}}}}}}catch (Exception e){e.printStackTrace();}return resultEntityList;}/* public static void main(String[] args) {TapdApiBusiness tapdApi=new TapdApiBusiness();List<ResultEntity> cmap = tapdApi.getbugsByday("68331031", "1168331031001000392",31);for (ResultEntity r:cmap){System.out.println(r.getProjectName()+"=="+r.getUrl());}}*/}

发送通知的代码

package com.auto.qyapi.twoutil;import org.springframework.stereotype.Service;import javax.activation.MailcapCommandMap;
import java.util.*;
import java.util.stream.Collectors;/**
* @author 作者
* @version 创建时间:2019年3月20日 下午4:27:36
* 类说明
*/
@Service
public class Qyapi {/*** (一) 待处理线上报障*/public  void senmsgByday(String key,int beforeDays) {/*3220bd0d-7415-475c-8116-0a7ac8deba5e*/String botUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + key;WeChatBotUtils weChatBot = new WeChatBotUtils(botUrl, true);TapdApiBusiness tapdApi = new TapdApiBusiness();List<ResultEntity> cmap = tapdApi.getbugsByday("68331031", "1168331031001000392",beforeDays);List<ResultEntity> qudaomap = tapdApi.getbugsByday("61792590", "1161792590001000446",beforeDays);List<ResultEntity> bbsmap = tapdApi.getbugsByday("30892271", "1130892271001000738",beforeDays);StringBuffer cname=new StringBuffer();StringBuffer qudaoname=new StringBuffer();StringBuffer bbsname=new StringBuffer();//处理1个大项目空间if(cmap.size()>0){Map<String, List<ResultEntity>> corderGroupMap = cmap.stream().collect(Collectors.groupingBy(ResultEntity::getProjectName));Set cset = corderGroupMap.keySet();for (Object o : cset) {cname.append("    ><font color=\"info\">[线上报障_" + o + "]</font>" + corderGroupMap.get(o).size() + "个\n");cname.append("详情查看:\n");for(ResultEntity one:corderGroupMap.get(o)){System.out.println(one.getUrl());cname.append(corderGroupMap.get(o).indexOf(one)+1 +") "+one.getUrl()+" \n");}}}if (qudaomap.size()>0){//处理2个大项目空间Map<String, List<ResultEntity>> qudaoorderGroupMap = qudaomap.stream().collect(Collectors.groupingBy(ResultEntity::getProjectName));Set qudaoset = qudaoorderGroupMap.keySet();for (Object o : qudaoset) {qudaoname.append("    ><font color=\"info\">[线上报障_" + o + "]</font>" + qudaoorderGroupMap.get(o).size() + "个\n");qudaoname.append("详情查看:\n");for(ResultEntity one:qudaoorderGroupMap.get(o)){System.out.println(qudaoorderGroupMap.get(o).indexOf(one));qudaoname.append(qudaoorderGroupMap.get(o).indexOf(one)+1 +") "+one.getUrl()+" \n");}}}if (bbsmap.size()>0){//处理1个大项目空间Map<String, List<ResultEntity>> bbsorderGroupMap = bbsmap.stream().collect(Collectors.groupingBy(ResultEntity::getProjectName));Set bbsset = bbsorderGroupMap.keySet();for (Object o : bbsset) {bbsname.append("    ><font color=\"info\">[线上报障_" + o + "]</font>" + bbsorderGroupMap.get(o).size() + "个\n");bbsname.append("详情查看:\n");for(ResultEntity one:bbsorderGroupMap.get(o)){bbsname.append(bbsorderGroupMap.get(o).indexOf(one)+1 +") "+one.getUrl()+" \n");}}}try {int totalcount=cmap.size()+qudaomap.size()+bbsmap.size();if (totalcount>0){String markdownMsg ="[线上报障]近"+(beforeDays-1)+"天内,优先级高的未安排修复或者5天内需修复的故障共有"+totalcount+"个未处理的故障:\n" +cname.toString()+qudaoname.toString() +bbsname.toString();weChatBot.sendMarKDownMsg(markdownMsg);}}catch (Exception e){e.printStackTrace();}}public  void senmsgByweek(String key,int beforeDays) {/*3220bd0d-7415-475c-8116-0a7ac8deba5e*/String botUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + key;WeChatBotUtils weChatBot = new WeChatBotUtils(botUrl, true);TapdApiBusiness tapdApi = new TapdApiBusiness();List<ResultEntity> cmap = tapdApi.getbugsByweek("68331031", "1168331031001000392",beforeDays);List<ResultEntity> qudaomap = tapdApi.getbugsByweek("61792590", "1161792590001000446",beforeDays);List<ResultEntity> bbsmap = tapdApi.getbugsByweek("30892271", "1130892271001000738",beforeDays);StringBuffer cname=new StringBuffer();StringBuffer qudaoname=new StringBuffer();StringBuffer bbsname=new StringBuffer();if(cmap.size()>0){//处理1个大项目空间Map<String, List<ResultEntity>> corderGroupMap = cmap.stream().collect(Collectors.groupingBy(ResultEntity::getProjectName));Set cset = corderGroupMap.keySet();for (Object o : cset) {cname.append("    ><font color=\"info\">[线上报障_" + o + "]</font>" + corderGroupMap.get(o).size() + "个\n");cname.append("详情查看:\n");for(ResultEntity one:corderGroupMap.get(o)){cname.append(corderGroupMap.get(o).indexOf(one)+1 +") "+one.getUrl()+" \n");}}}if(qudaomap.size()>0){//处理2个大项目空间Map<String, List<ResultEntity>> qudaoorderGroupMap = qudaomap.stream().collect(Collectors.groupingBy(ResultEntity::getProjectName));Set qudaoset = qudaoorderGroupMap.keySet();for (Object o : qudaoset) {System.out.println(o+":");qudaoname.append("    ><font color=\"info\">[线上报障_" + o + "]</font>" + qudaoorderGroupMap.get(o).size() + "个\n");qudaoname.append("详情查看:\n");for(ResultEntity one:qudaoorderGroupMap.get(o)){qudaoname.append(qudaoorderGroupMap.get(o).indexOf(one)+1  +") "+one.getUrl()+" \n");}}}if(bbsmap.size()>0){//处理1个大项目空间Map<String, List<ResultEntity>> bbsorderGroupMap = bbsmap.stream().collect(Collectors.groupingBy(ResultEntity::getProjectName));Set bbsset = bbsorderGroupMap.keySet();for (Object o : bbsset) {System.out.println(o+":");bbsname.append("    ><font color=\"info\">[线上报障_" + o + "]</font>" + bbsorderGroupMap.get(o).size() + "个\n");bbsname.append("详情查看:\n");for(ResultEntity one:bbsorderGroupMap.get(o)){System.out.println(bbsorderGroupMap.get(o).indexOf(one));bbsname.append(bbsorderGroupMap.get(o).indexOf(one)+1 +") "+one.getUrl()+" \n");}}}try {int totalcount=cmap.size()+qudaomap.size()+bbsmap.size();if (totalcount>0){String markdownMsg ="[线上报障]近"+(beforeDays-1)+"天共有"+totalcount+"个已处理但未回复报障人员:\n" +cname.toString()+qudaoname.toString()+bbsname.toString();weChatBot.sendMarKDownMsg(markdownMsg);}}catch (Exception e){e.printStackTrace();}}/*public static void main(String[] args) {Qyapi qyapi=new Qyapi();qyapi.senmsgByday("3220bd0d-7415-475c-8116-0a7ac8deba5e",31);*//*qyapi.senmsgByweek("3220bd0d-7415-475c-8116-0a7ac8deba5e",31);TapdApiBusiness tapdApi = new TapdApiBusiness();List<ResultEntity> bbsmap = tapdApi.getbugsByweek("30892271", "1130892271001000738",11);*//*}
*/}

接口

package com.auto.qyapi.controller;import com.auto.qyapi.pchouse.QQ;
import com.auto.qyapi.twoutil.Qyapi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class SendMsgController {@Autowiredprivate Qyapi qyapi;@Autowiredprivate QQ qq;@RequestMapping("/sendmsg/{key}/{day}")public String security_send(@PathVariable("key") String key,@PathVariable("day") int day){qyapi.senmsgByday(key,day);qyapi.senmsgByweek(key,day);return "发送成功";}@RequestMapping("/housemsg/{workspaces_id}/{iteration_id}/{key}")public String house_send(@PathVariable("workspaces_id") String workspaces_id,@PathVariable("iteration_id") String iteration_id,@PathVariable("key") String key){qq.sendmsg(workspaces_id,iteration_id,key);return "发送成功";}
}

可以利用接口,配置定时任务
接口接口I like interface

查看全文

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/2182066.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章:

java调tapd-api获取Bug并发企微通知

需求
线上报障定时推送:
定时任务:每天上午9点半、下午5点半 基于企微机器人做推送
未处理线上报障 判断条件: 【tapd】项目(workspace_id): 68331031 (用户产品部(C端&#xff0……

MyEclipse映射hibernate的错误 An internal error occurred during: Generating Artifacts解决方案

今天用myeclipse对数据库进行hibernate自动映射的时候有几张表一直出现这个错误,在网上搜了一下,大部分都说有两种可能:一是myeclipse与jboss的一个插件不兼容,二是驱动的问题. 通过三个小时的分析,其实出现这个错误有很多种可能,例如我的错误就不是上面两种原因,我的错误是对数……

postgresql与mysql简单的性能测试

一篇关于指针的精典的文章(转)

转载述: 这是一篇比较老的关于指针的文章,作者站在初学者的角度对指针作了深入的剖析。如果你在学习指针的时候有什么问题,看一看这篇文章定有收获。
一。指针的概念 1。指针的类型 2。指针所指向的类型 3。指针的值二。指针的算术……

dwr(ajax),hibernate结合使用出现的bug

客户端用dwr调用服务端函数实现ajax.
若服务端的java bean (这是假定是Personinfo,后面方便引用)中的变量中出现了java.util.Set 类型的变量 ,而你用dwr调用的服务端的那个函数的返回值(也可能是参数,这没试过)是Personinfo,那么就会出现错误
failed to lazily initialize a ……

postgresql易出的错误及解决

postgresql对于大小写是敏感的,
当你用EMS之类的工具连接postgresql时,在建表的时候你若用了大写,那么在你的程序运行中都会出现找不到那些名称用大写的字段,即使你在映射文件中大小写都是写正确的.我估计是postgresql在进行数据查寻的时候是先把数据库里面的字段全部转换为小……

hibernate易出的错误及解决方法

public int getCountJsql(String pojo) { Query q getSession().createQuery("select count(*) from " pojo); List cc q.list(); Long a (Long) cc.get(0); return a.intValue(); }
cc.get(0)返回的是Long型,如果写成Integer就会报错…

浅谈spring对hibernate的封装

spring对hibernate的封装使用对数据库的操作更方便,spring进一步简化了hibernate的函数.用spring进行操作无须显式的打开session,显式的开始事务,关闭事务,关闭session
基于依赖注入的SessionFactory管理机制.SessionFactory是执行持久化操作的核心组件,传统Hibernate应用中,S……

struts,spring,hibernate浅谈–我之理解

这三个框架在国内国外都特别流行,学习这三个框架半年有余,写心得于此
首先得搞清楚这三个东西是三个框架.它们并不是用来直接解决某些问题的函数库,它们只是把一些现有的知识,技术进行了某种程序上的封装,达到某种效果,也许这种效果是你想要的,也许并不是,所以并不是它们是万油……

endall–失败的男人

时间洗涤旧迹,仅使留下淡红的血色和微漠的哀悼,在这淡红的血色和微漠的哀悼中又使人苟且偷生. 生于忧患,死于安乐….

Pandas入门实践2 -数据处理

为了准备数据进行分析,我们需要执行数据处理。在本节中,我们将学习如何清理和重新格式化数据(例如,重命名列和修复数据类型不匹配)、对其进行重构/整形,以及对其进行丰富(例如,离散化……

一、lua基础知识1

一、lua 的数据类型
–类型 a1; –number print(type(a)) –number b"HelloWorld"; print(type(b)) –string 两种数据类型 ctrue; print(type(c)) –boolean true 或者 false d print; d("HelloWorld"); print(type(d)); –function类型 ……

二、lua语言基础2

1.lua的类型有哪些?答:lua的数据类型有:number,string,nil function,table,thread,userdata(用户自定义的类型),boolean(布尔类型) 2.什么是尾调用,尾调用有什么优点尾调用:在一个函数的最后一步开始调用另……

quick-cocos2dx-luaUI控件讲解

–MyApp部分 require("config") require("cocos.init") require("framework.init") local MyApp class("MyApp", cc.mvc.AppBase) function MyApp:ctor() MyApp.super.ctor(self) end function MyApp:run() cc.FileUti……

quick-cocos2dx lua语言讲解 (动作,定时器,触摸事件,工程的类的讲解)

–MainScene部分
— display.newScene 创建一个场景 — 在quick里面我们的控件、精灵 一般是加载到场景上的 local MainScene class("MainScene", function() return display.newScene("MainScene") end) function MainScene:ctor() –创……

使用quick-cocos2dx-lua 实现的小游戏(包含碰撞检测,触屏发子弹)

–主界面local MainScene class("MainScene", function()return display.newScene("MainScene")end)ON true;function MainScene:ctor()local bg cc.Sprite:create("main_background.png");bg:setScale(2);bg:setPosition(display.cx,display……

cocos2d-js 中scrollview详解

/****
开头的一些废话:
1、多思考,善于思考
2、懂得变通
3、多多查询API首先复制一段 API中的源码:(UIScrollView.js)这段代码可以看出 scrollview
中的容器是一个node,并且他的位置是:代码最后……

cocos2d-js中的回调函数中世界坐标系和节点坐标系的相互转换

世界坐标系和节点坐标系都是OPENGL 坐标系 1、世界坐标系原点就是屏幕的左下角; 2、节点坐标系的原点就是一个节点的左下角; 3、两个坐标系可以通过已经写好的cocosAPI进行想换转换; 4、所有的节点需要转为一个节点上或者是统一的世界坐标系……

通过JavaScript实现漂浮

<html>
<head><meta http-equiv"Content-Type" content"text/html"; charset"gb2312" /><title>漂浮广告</title><style type"text/css">div{position:absolute;}</style>
</head>
&……

序列动画和图片内存问题

一、帧动画问题 /*** 帧动画总结:* 1、如果精灵进行新建时,加载了纹理,那么setRestoreOriginalFrame可以设置为false或者true* 2、如果精灵新建时,没有加载纹理的话,那么setRestoreOriginalFrame需要设置为false&#……

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注