最近周末心血来潮写了一个晨会的机器人(每天大家轮流做主持),没想到挺受欢迎,代码执行是没问题,但放到服务器上运行时十分曲折,作为一个半桶水测试,还是第一次接触到git/或者是打jar到服务器上定时运行,所以准备在这个过程写下来,吸取教训,也积累知识吧
官网:https://open-doc.dingtalk.com/microapp/serverapi2,先看一遍文档,然后开干,下载java sdk,创建maven项目
本地解压,里面有各种封装方法,先看一遍,找出自己能用的方法名,我的代码里用到了这几个:
先贴上代码再讲:
package com.qiyue;
import com.qiyue.dingtalk.DingtalkChatbotClient;
import com.qiyue.dingtalk.SendResult;
import com.qiyue.dingtalk.message.TextMessage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class RobotClient {
private DingtalkChatbotClient client = new DingtalkChatbotClient();
// 钉钉机器人发送地址
private static final String url = "https://oapi.dingtalk.com/robot/send?access_token=";
// 钉钉机器人的token
// 测试群里机器人的token,自己先试试,不要去大群里骚扰
//private static final String token = "901489840593ad21e12e3d8074dacdc8585f8819fad7";
//正式----在小群里测试通过后,可以放大群里实行了
private static final String token = "5363b5cad4d9d9c0785cbe2457595c";
// 按星期发送时发送日期与发送人的关系
//private static Map<String, String> atUserMap;
// 轮询发送时的发送人列表
private static List<String> atUserList;
static {
// 初始化发送人数据
/* atUserMap = new HashMap<String, String>();
atUserMap.put("Sunday", "");//引号里是手机号,贴出来的时候去掉了
atUserMap.put("Monday", "");
atUserMap.put("Tuesday", "");
atUserMap.put("Wednesday", "");
atUserMap.put("Thursday", "");
atUserMap.put("Friday", "");
atUserMap.put("Saturday", "");
*/
atUserList = new ArrayList<String>();
atUserList.add("17610259"); //此处是需要被@人的dingding手机号码 ,依次往后加
}
/**
* 按星期发送消息
* @throws Exception
*/
/* public void sendWeeklyTextMessage() throws Exception {
TextMessage message = new TextMessage("test at someone");
List<String> mobiles = new ArrayList<String>();
mobiles.add(atUserMap.get(getWeekOfDate(new Date())));
message.setAtMobiles(mobiles);
SendResult result = this.client.send(url + token, message);
System.out.println(result);
}*/
/**
* 获取指定日期的星期
* @param date
* @return
*/
/* private static String getWeekOfDate(Date date) {
String[] weekDays = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (w < 0)
w = 0;
return weekDays[w];
}*/
/**
* 每天给发送人轮询发送消息
* @throws Exception
*/
public void sendDailyMsg() throws Exception {
TextMessage message = new TextMessage("今天的晨会主持人");
List<String> mobiles = new ArrayList<String>();
int day = readDay();
mobiles.add(atUserList.get(day));
message.setAtMobiles(mobiles);
SendResult result = client.send(url + token, message);
System.out.println(result);
day++;
if (day == atUserList.size()) {
day = 0;
}
modifyConfigField("day", String.valueOf(day));
}
/**
* 从配置文件中获取当前应该给第几个发送消息
* @return
*/
private int readDay() {
String propertiesPath = getPropertiesPath();
Properties properties = new Properties();
try {
InputStream in = new FileInputStream(propertiesPath);
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
return Integer.parseInt(properties.getProperty("day"));
}
/**
* 修改配置文件中在值
* @param key
* @param value
*/
private void modifyConfigField(String key, String value) {
String propertiesPath = getPropertiesPath();
Properties properties = new Properties();
try {
InputStream in = new FileInputStream(propertiesPath);
properties.load(in);
properties.setProperty(key, value);
in.close();
OutputStream os = new FileOutputStream(propertiesPath);
properties.store(os, null);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//获取服务器上的day配置文件
private String getPropertiesPath() {
String jarWholePath = RobotClient.class.getProtectionDomain().getCodeSource().getLocation().getFile();
try {
jarWholePath = java.net.URLDecoder.decode(jarWholePath, "UTF-8");
} catch (UnsupportedEncodingException e) { System.out.println(e.toString()); }
String jarPath = new File(jarWholePath).getParentFile().getAbsolutePath();
String propertiesPath = jarPath + "/day.properties";
System.out.println(propertiesPath);
return propertiesPath;
}
}
这代码猛一看有点乱,却也代表了我曲折的设计思路
一开始简单的想定个列表循环,后来一想遇到周末咋办?然后改成按星期的,结果一算,我们组有9个,一个星期不够分哇?那就写表单吧,运行是没问题了,那怎么定时运行呢,jenkins试了下,照网上的教程配置maven项目,总是失败,最多也只能做到每次重新构建代码,并没有循环运行并读取day文件;最后想到的办法是把这个项目打成jar包,直接放到服务器上去运行,把day文件单独拉出来,这样每次人员的顺序有变动时只需要更改day的key就行了;先运行一遍看下是否生效:java -jar robot.jar(你的jar文件名)运行成功后就可以设置定时任务了,我用的是crontab; 直接连接服务器后corntab -e 会展示现有的crontab 命令
最后两条定时是我的两个机器人, 00 9 那个意思是每周1-5的每天早上9点运行,通知主持人主持晨会;第二个是每周5 10点运行,通知周末值班的人员;公式 时间+jdk所在目录 +jar所在目录
代码不想多说了,整个都已经贴出来了, 照着写只需要改下机器人的token和要@人的列表即可;记得修改了代码后要重新build下项目,因为它执行的是target,否则你会发现修改不起效果~~我就是这么傻逼中箭了!!照这个流程就可以完成,以下是pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>robotxzt</groupId>
<artifactId>robotxzt</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.29</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>//这里是你的java版本
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.1</version>
<configuration>
<attach>true</attach>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.qiyue.TestSendMsg</mainClass>//这里是你的pakage+main方法名称
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
copy后记得鼠标右键在pom文件上选择maven -- reimport,将会下载这些依赖
并且导入这些插件后,maven项目打jar也会变的很容易,一开始是懵逼状态,走了很多弯路,气得吃不下饭,想咬电脑~~~
打jar包流程:先选中main方法,然后~~
在弹出的页面,先点击左上角的+号,添加Maven项目,然后如下图这么填写--jar包保存目录,最好是根目录
然后回到代码页面,点击右上角的运行按钮
运行完成后你会在target里看到生成的jar包,放在根目录是为了方便依赖读取部分配置文件,如果你放到其它路径下,相关的依赖可能获取不到会报错
然后你可以先在idea的terminal控制台上试着运行下看看,先进入到这个jar包所在的路径,小技巧就是选中jar包 鼠标右键,copy path
运行成功的话,你可把它放到服务器上,然后设置定时执行啦
本地上传文件到服务器步骤:先打开本地终端,scp /jar包所在目录.jar 服务器账号@服务器地址:/上传的目标目录,确认后会让你输入对应 的账号密码,然后就可以啦,可以登录服务器查看
再推荐一个好用的反编译工具--JDGUI ,之前不会用maven插件打包的时候,打出的包总是提示找不到 或无法添加主类,通过这个工具便能打开jar包看下里面到底有啥了,是否class文件没打成功之类的。