准备工作
由于平时都懒得看学校的教务网站,不知道会不会漏掉重要的通知信息,所以想做一个简单的Java程序,可以在学校有新通知发布的时候给我发一封邮件,内容是文章的标题。
要得到文章的标题就要从网站爬取标题数据,通过jsoup实现
而邮件发送通过QQ邮箱 设置–>账户 开启开启 POP3/SMTP 服务(默认关闭),然后获取16位授权码
maven依赖
新建一个空的maven项目,在pom.xml中添加两个依赖:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
</dependency>
编写代码
邮件发送
package com.pickinstars.Util;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.security.GeneralSecurityException;
import java.util.Properties;
public class EmailManager {
public void sendMail(String content) throws GeneralSecurityException, MessagingException {
//创建一个配置文件并保存,固定内容
Properties properties = new Properties();
properties.setProperty("mail.host","smtp.qq.com");
properties.setProperty("mail.transport.protocol","smtp");
properties.setProperty("mail.smtp.auth","true");
//QQ存在一个特性设置SSL加密
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
//创建一个session对象
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("115420xx@qq.com","xxx");
}
});
//开启debug模式
session.setDebug(true);
//获取连接对象
Transport transport = session.getTransport();
//连接服务器
transport.connect("smtp.qq.com","1154205999@qq.com","xxx");
//创建邮件对象
MimeMessage mimeMessage = new MimeMessage(session);
//邮件发送人
mimeMessage.setFrom(new InternetAddress("115420xx@qq.com"));
//邮件接收人
mimeMessage.setRecipient(Message.RecipientType.TO,new InternetAddress("115420xx@qq.com"));
//邮件标题
mimeMessage.setSubject("星宿助手");
//邮件内容
mimeMessage.setContent(content,"text/html;charset=UTF-8");
//发送邮件
transport.sendMessage(mimeMessage,mimeMessage.getAllRecipients());
//关闭连接
transport.close();
}
}
爬取网站数据
打开学校的教务处网站,在通知栏可以看到标题和日期,通过审查元素得到对应的标签class
package com.pickinstars.Util;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import javax.mail.MessagingException;
import java.io.IOException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
public class Inquire {
public static void main(String[] args) throws IOException, InterruptedException, GeneralSecurityException, MessagingException {
String url = "http://jwc.xxx.edu.cn/"; //学校网站
ArrayList<String> sendList = new ArrayList<String>(); //存放同一天的通知
String latestTime = "[2020.09.11]"; //设置初始日期
EmailManager emailManager = new EmailManager();
while (true){
Document document = Jsoup.parse(new URL(url),3000); //解析网站的页面,返回HTML
Elements times = document.getElementsByClass("fr list-date-a"); //日期的class
for (Element t:times){
String title = t.parent().attr("title"); //标题
if (t.text().compareTo(latestTime) == 0){ //如果是同一天的信息
if (!(sendList.contains(title))){
sendList.add(title); //加入数组防止重复发送
emailManager.sendMail(title);
}
}else if (t.text().compareTo(latestTime) > 0){ //如果最新的日期更新了
latestTime = t.text(); //更新标志到最新时间
sendList.clear(); //清空数组
sendList.add(title);
emailManager.sendMail(title);
}
}
TimeUnit.HOURS.sleep(1); //一个小时查询一次
}
}
}
部署到服务器
最后将项目打包成jar文件,上传到服务器上,在文件所在的目录,输入以下指令可以在后台一直运行jar包
nohup java -jar xxx.jar > logs.txt &
用"&"符号结尾表示让程序在后台运行。
这样的话,命令窗口就不会被锁定,而可以发送其他指令,但是当窗口关闭时,后台运行的程序依然会被停止。
nohup命令:nohup 命令运行由 Command参数和任何相关的 Arg参数指定的命令,忽略所有挂断信号。要运行后台中的 nohup 命令,添加 & ( 表示“and”的符号)到命令的尾部。
简单地说就是,nohup命令可以阻止窗口关闭是的挂断信号,使程序继续运行。
至此,这个简易的功能就实现啦~~
遇到的坑
Error: Invalid or corrupt jarfile jar
打包成jar文件后,在命令行通过java -jar
运行jar包时报错
Error: Invalid or corrupt jarfile jar
原因:IDEA中,在File\Project Structure\Artifacts\添加artifacts的时候,默认会在src/main/java/META_INF/下创建目录,但是此目录(src/main/java/)已标记为Sources Root,只编译;
解决方案:设置META-INF文件夹位置,这里选择项目的根目录
JDK版本不一致
打成的jar包在本地运行没有问题,而放在阿里云的服务器上运行的时候,通过输出日志看到产生了错误,部分信息如下:
java.lang.UnsupportedClassVersionError:
has been compiled by a more recent version of the Java Runtime (class file version 51.0)
看报错信息,是因为使用的jar包版本不对。这个51.0是什么呢?
在服务器命令行输入Java -version
,可以看到版本是1.7。而本地打包的时候是JDK12。
更新JDK
yum -y update #首先更新一下YUM源
yum list Java* #列出所有的JDK
yum install java-11.0-openjdk* -y #由于没看到jdk12,就选择安装11
最后验证JDK是否安装成功,输入Java -version
,可以看到版本变成了11。
在项目属性设置JDK版本
为了能在服务器上运行,在项目的属性里设置jdk版本,打开setting,搜索jdk,更改版本号到11,与服务器同步,重新打包jar即可