首先声明不是在开车 事情是这样的,那天我的姐姐给我分享了一个博客 使用前端的一些技术来给女友定时发送一些情话啊什么的,点进去一看 emmm作为一个虽然学过前端但只留在js的我压根看不懂 之后就不想在看了就像这玩意前端都可以做 后端有啥理由不可以呢?虽然我也是1个后端小菜鸡但是就动手做了一个基于java发送邮件的功能并每日推送 然后女友就每天被感动(骚扰)的受不了
因为考虑到多用一些最近学到的知识 所以有些地方可能会有更简单的方法
1. 目前的邮件的内容
- 获取当天的日期
- 获取和女友相恋的时间
- 获取当天的天气
- 爬取网上的情话
emmm目前就这些功能等以后有空了可以想想在加一些功能 (你们觉得还可以有啥功能呢?)
2.代码的实现
1.这里我将要发送的内容封装成一个Messages 要发送时 调用toString()方法 设置内容
public class Messages {
//接收方的邮箱地址
private String toEmail;
//发送方的邮箱地址
private String formEmail;
//发件人邮件用户名
private String userName;
//发件邮箱授权码
private String passWord;
//邮件标题
private String title;
//收件人姓名
private String name;
//这里是 --- 的天数
private Long data;
//设置天气
private Weather Weather;
//设置情话
private String loversPrattle;
/*
这里省略了一些get set方法
。。。。。
*/
@Override
public String toString(){
return "<body> " +
"<div style=\"background-color: pink;margin:0 auto; color: rgb(64, 10, 241);\">" +
" <div> " +
" <p>"+ name+"宝宝早上好!这是我们相恋的"+data +"天</p>" +
" <p>下面为你推送今天的天气哦!</p>" +
"城市: "+ Weather.getCity()+
"<br>天气状况: "+Weather.getWea()+
"<br>当前温度: "+Weather.getTem()+"°C"+
"<br>平均温度: "+Weather.getTem_day()+"°C"+
"<br>夜晚温度: "+Weather.getTem_night()+"°C"+
"<br>风: "+Weather.getWin()+
"<br><br>每日土味:"+loversPrattle+
" </div>" +
"</div>"+
"</body>";
}
}
toString这里注意 发送邮件的是可以选择发送HTML格式 但是想要设置一些样式 只能在标签内部添加 在外部添加识别不了 我这里就没有咋写样式
2.Weather是一个天气对象的封装, 我调用的API中返回这些字段 并没有全部用上
public class Weather {
private String tem_day;
private String update_time;
private String wea;
private String win_meter;
private String city;
private String wea_img;
private String tem_night;
private String win_speed;
private String cityid;
private String air;
private String tem;
private String win;
}
3.WeatherUtil是获取天气的工具类 使用的接口是 https://tianqiapi.com 我使用的免费的 appid 和 appsecret是需要注册用户之后获取的
public class WeatherUtil {
public String appid="******";
public String appsecret="******";
public String version="v6";
//这里把天气写死了 后期可能会改成调用QQ提供的接口来获取对方的定位
public String url="https://tianqiapi.com/free/day?"+appid+"&"+appsecret+"&city=阜阳&unescape=1";
/**
* 向指定URL发送GET方法的请求
*
* 发送请求的URL
* @return URL 所代表远程资源的响应结果
*/
public Weather getWeather() throws IllegalAccessException, InstantiationException {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream(),"UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
Gson gson = new Gson();
Map<String, String> map = new HashMap<String, String>();
map = gson.fromJson(result, map.getClass());
//通过反射将map中的数据封装到对象中
//将得到实体类中的所有的方法
Method[] methods = Weather.class.getDeclaredMethods();
Object s = Weather.class.newInstance();
map.forEach((k, v)->{
String name = "set" + k;//setstuid
for (Method method : methods) {
if (method.getName().equalsIgnoreCase(name)) {
try {
method.invoke(s, v);//执行了对应的set方法
} catch (IllegalAccessException e) {
System.out.println("在获取天气的时候出现问题");
e.printStackTrace();
} catch (InvocationTargetException e) {
System.out.println("在获取天气的时候出现问题");
e.printStackTrace();
}
break;
}
}
});
return (Weather) s;
}
}
4.EmaliUtil是对发送邮件的一些功能封装、我是通过QQ邮箱 发送的 需要在QQ邮箱的设置里开通 smtp 协议
emmm我把Messages的封装放在了这个类中 (因为我感觉邮件内容也应该算在邮件里)
public class EmailUtil {
// 收件人电子邮箱
private String to = "***@qq.com";
// 发件人电子邮箱
private String from = "***@qq.com";
private String userName="****@qq.com";
//该密码是开通协议时给你的密码
private String passWord="****";
//获取相恋的天数
public Long getTime() {
String str1 = "2021-7-27";
DateFormat fmtDateTime = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = null;
try {
date1 = fmtDateTime.parse(str1.toString());
} catch (ParseException e) {
e.printStackTrace();
}
Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(date1);
Calendar today = Calendar.getInstance();
Long days= (today.getTimeInMillis() - calendar1.getTimeInMillis()) / (1000 * 60 * 60 * 24);
return days;
}
//设置消息体
public Messages setMessages(String name, Weather weather, String loversPrattle){
Messages messages = new Messages();
messages.setToEmail(to);
messages.setFormEmail(from);
messages.setUserName(userName);
messages.setPassWord(passWord);
Date date =new Date();
SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd");
messages.setTitle(format.format(date)+"日,早啊宝");
messages.setData(getTime());
messages.setName(name);
messages.setWeather(weather);
messages.setLoversPrattle(loversPrattle);
return messages;
}
public void sendEmail(Messages messages){
String host = "smtp.qq.com"; //QQ 邮件服务器
// 获取系统属性
Properties properties = System.getProperties();
// 设置邮件服务器
properties.setProperty("mail.smtp.host", host);
properties.put("mail.smtp.auth", "true");
// 获取默认session对象
properties.setProperty("mail.transport.protocol", "smtp");
properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.smtp.socketFactory.port", "465");
properties.setProperty("mail.smtp.port", "465");
Session session = Session.getDefaultInstance(properties,new Authenticator(){
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(messages.getUserName(), messages.getPassWord()); //发件人邮件用户名、授权码
}
});
try{
// 创建默认的 MimeMessage 对象
MimeMessage message = new MimeMessage(session);
// Set From: 头部头字段
message.setFrom(new InternetAddress(messages.getFormEmail()));
// Set To: 头部头字段
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(messages.getToEmail()));
// Set Subject: 头部头字段
message.setSubject(messages.getTitle());
// 设置消息体
//message.setText(text);
message.setContent(messages.toString(),
"text/html;charset=UTF-8" );
// 发送消息
Transport.send(message);
}catch (MessagingException mex) {
mex.printStackTrace();
}
}
}
5.LoversPrattleUtil是爬取网页的情话 并处理成一个集合并随机返回一个 因为本人的爬虫技术相当于空白 只能爬取一些非常易于爬取的网页 所以找了很久 http://www.qunzou.com/shenghuo/2515.html 可以看到这里的网页内容都在P 标签中那么我们只需要请求这个网页地址 然后 根据p标签做一些分割就行了 这里因为知道了一个非常nice的工具类 就试着使用了一次 非常nice 方便简洁 可以百度搜一下 Hutool
public class LoversPrattleUtil {
//使用 Hutool 包
public String getLoversPrattle(){
//请求列表页
String listContent = HttpUtil.get("http://www.qunzou.com/shenghuo/2515.html");
//使用正则获取所有文本
List<String> text = ReUtil.findAll("<p>(.*?)</p>", listContent, 1);
Random df = new Random();
//引用nextInt()方法
int number = df.nextInt(text.size()+1);
//从爬取的数据中随机选一天条 并去掉开头 数字符号 如: 1、
return text.get(number).replaceFirst(".[0-9]+、", "");
}
}
6.App类实现的发送邮件的功能 这里使用定长周期线程池ScheduledExecutorService 来实现每天定时发送
**
* 对发送内容等封装
*/
public class App {
int i = 0;
private WeatherUtil weatherUtil =new WeatherUtil();
private LoversPrattleUtil prattleUtil =new LoversPrattleUtil();
public void sendEmail() {
System.out.println("开始启动");
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
try{
service.scheduleAtFixedRate(()->{
EmailUtil emailUtil = new EmailUtil();
try {
//对消息体赋值
Messages messages = emailUtil.setMessages("name", weatherUtil.getWeather(), prattleUtil.getLoversPrattle());
emailUtil.sendEmail(messages);
//这里主要是用在服务器查看日志 看看有没有错
System.out.println("第"+i++ +"次发送成功 :"+messages.toString());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}, getMillis(),60*60*24, TimeUnit.SECONDS);
}catch (Exception e){
System.out.println("程序出错了");
System.out.println(e.toString());
}
}
//获取 服务启动到第一次发送要等待的时间
public static Long getMillis(){
Calendar calendar1 = Calendar.getInstance();
Calendar calendar=Calendar.getInstance();
calendar.set(5,(calendar.get(5)+1));
calendar.set(11,5);
calendar.set(12,20);
calendar.set(13,00);
long i = calendar.getTimeInMillis();
long time = calendar1.getTimeInMillis();
return (i-time)/1000;
}
}
7.Main类用来调用发送邮件的功能 这样做的目的是想着以后可以还会加一些新的功能省的到时候在改代码了
public class Main {
public static void main(String [] args) {
App app = new App();
app.sendEmail();
}
}
部署到云
好了 ,加入在本地测试通过后就可以打包在云服务器上部署了 那么怎么把这个程序部署到云服务器上呢?
我想有两个方法 一种就是改成web 打成war包部署到云服务器 通过url访问启动程序 另一种就是打成jar 通过jar启动 我选择的是打成 jar,通过idea自带打包工具
在点击确定后 回到写代码的界面 在头工具栏里选择Build —> BuildArtiface ----->Build 如果打过jar需要删掉相关文件哦 要不然会报错 之后通过文件夹打开工程文件夹 在out目录里就会有一个 ***.jar 了
如何上传到云服务器就不说了 可以百度一下 百度比我说的好 哦 对 这样有两个重要的 命令
nohup java -jar 名称.jar & ---------------------意思是启动jar 并且不会随着控制台的关闭而停止 并且将日志打印当jar文件夹下的nohup.out(没有则会自动创建)
ps -aux|grep 名称.jar| ---------------查看后台进程
面 在头工具栏里选择Build —> BuildArtiface ----->Build 如果打过jar需要删掉相关文件哦 要不然会报错 之后通过文件夹打开工程文件夹 在out目录里就会有一个 ***.jar 了
如何上传到云服务器就不说了 可以百度一下 百度比我说的好 哦 对 这样有两个重要的 命令
nohup java -jar 名称.jar & ---------------------意思是启动jar 并且不会随着控制台的关闭而停止 并且将日志打印当jar文件夹下的nohup.out(没有则会自动创建)
ps -aux|grep 名称.jar| ---------------查看后台进程
好了文章到这里就结束了 如有错误还请指出 对了大家觉得还可以添加那些功能呢?