springboot实现添加邮件发送及压缩功能
这次本来只讲讲邮件发送功能的,惮于内容比较贫乏,故加了点儿文件压缩的功能讲解。
首先邮件发送,邮件功能在springboot里面是有对应的依赖组件,这个:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid> spring-boot-starter-mail</artifactid> </dependency>
邮件功能开发在springboot里面相当简单,这里我大致总结下开发内容:
a>添加依赖包
b>配置mail基本参数(ymal或propertie里面)
c>service中注入javamailsender,调用相关方法即可
但是这里面可能会有个问题,就是在具体服务器部署的时候服务器会封堵邮件服务端口,以及普通邮件安全问题,这里讲解的时候我会顺道给出解决之道。
首先,需要在工程的pom.xml中引入邮件组件,组件的版本需对应springboot的版本(可不写,这里我略去):
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-mail</artifactid> </dependency>
接下来就是在配置文件中配置邮件的基本参数:
spring: mail: host: smtp.exmail.qq.com username: username@hostname.com password: 密码 default-encoding: utf-8 ssl: trust: smtp.exmail.qq.com properties: mail: smtp: auth: true #是否需要认证 socketfactory: class: javax.net.ssl.sslsocketfactory #ssl证书socket工厂 port: 465 #使用smtp465端口
配置参数的时候一定要注意缩进,因为我给的是yaml的配置格式,若是properties配置,大致是这样子(例子):spring.mail.host:smtp.exmail.qq.com,每一个子项都是完整的格式,一开始我是省略了properties项以下的配置(是否认真,ssl,端口),后来发现服务器将邮件的25端口封了,所以在本地可以但是在服务器就行不通了,所以需要指定邮件服务端口为465,我这里使用的是qq邮箱,如果使用163或其他邮箱需自行查阅服务商支持的端口,至于邮件安全问题,在这里需要声明两个,一个是ssl信任,以及mail的socket工厂,具体请见以上红色部分,以上配置仅对qq邮箱有效,不保证其他邮箱也适用。
ok,配置完成,这里就开始写具体的实现类:
import xxx.common.util.dateutil; import org.apache.commons.lang3.stringutils; import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springframework.beans.factory.annotation.autowired; import org.springframework.beans.factory.annotation.value; import org.springframework.mail.simplemailmessage; import org.springframework.mail.javamail.javamailsender; import org.springframework.mail.javamail.mimemessagehelper; import org.springframework.stereotype.service; import javax.mail.internet.mimemessage; import java.util.date; import java.util.list; import java.util.map; @service public class mailservice { private static final logger log = loggerfactory.getlogger(mailservice.class); @value("${spring.mail.username}") private string send_user_addr; @autowired private javamailsender mailsender; /** * 发送简单邮件 * @param receive 收件人 * @param obj 发送主题 * @param content 邮件内容 */ public void sendsimplemail(string receive,string obj,string content) { if(!stringutils.isnotblank(content) || !stringutils.isnotblank(receive)) return;//不发送空邮件 simplemailmessage message = new simplemailmessage(); message.setfrom(send_user_addr); if(receive.contains(";")) message.setto(receive.split(";")); else message.setto(receive); message.setsubject(obj); message.settext(content); try { mailsender.send(message); log.info("simple mail send success!"); } catch (exception e) { log.error("sendsimplemail error!", e); } } private stringbuilder strbuilder; /** * 发送html邮件 多列表单的形式 * @param receive 收件人 * @param obj 发送主题(题目) * @param content 邮件内容 */ public void sendhtmlmailbylist(string receive,string obj,list<map> content){ if(content.isempty() || !stringutils.isnotblank(receive) || null==obj) return; mimemessage msg = mailsender.createmimemessage(); try { mimemessagehelper helper = new mimemessagehelper(msg, true, "utf-8"); //解决乱码问题 helper.setfrom(send_user_addr); if(receive.contains(";")) helper.setto(receive.split(";")); else helper.setto(receive); helper.setsubject(obj); strbuilder=new stringbuilder(); strbuilder.append("<!doctype html><html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"></head><body style=\"padding:3% 2%;\">"); strbuilder.append("<h2>this message is automatically sent to the system.</h2>"); strbuilder.append("<h2>send date by "+dateutil.getdateformat(new date(),dateutil.datetime_default_format) +"</h2>"); strbuilder.append("<h2>the following is the details:</h2>"); strbuilder.append("<table border=\"2px solid red\" width=\"100%\">"); //头 strbuilder.append("<thead style=\"background-color: #aea2e2;\">"); strbuilder.append("<tr>"); object[] st=content.get(0).keyset().toarray(); for(int i=0;i<st.length;i++) strbuilder.append("<th>"+st[i]+"</th>"); strbuilder.append("</tr>"); strbuilder.append("</thead>"); //体 strbuilder.append("<tbody>"); for(map item:content){ strbuilder.append("<tr>"); for(object str:st) strbuilder.append("<td>"+item.get(str)+"</td>"); strbuilder.append("</tr>"); } strbuilder.append("</tbody>"); strbuilder.append("</table>"); strbuilder.append("<h3 style=\"text-align:right\">best wishes</h3>"); strbuilder.append("</body></html>"); //log.info(strbuilder.tostring()); helper.settext(strbuilder.tostring(),true); }catch (exception e){ log.error("sendhtmlmail error:",e); } mailsender.send(msg); } /** * 发送html邮件 单列记录形式 * @param receive 收件人 * @param obj 发送主题(题目) * @param content 邮件内容 */ public void sendhtmlmailbyitem(string receive,string obj,list<string> content){ if(content.isempty() || !stringutils.isnotblank(receive) || null==obj) return; mimemessage msg = mailsender.createmimemessage(); try { mimemessagehelper helper = new mimemessagehelper(msg, true, "utf-8"); //解决乱码问题 helper.setfrom(send_user_addr); if(receive.contains(";")) helper.setto(receive.split(";")); else helper.setto(receive); helper.setsubject(obj); strbuilder=new stringbuilder(); strbuilder.append("<!doctype html><html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"></head><body style=\"padding:3% 2%;\">"); strbuilder.append("<h3>this message is automatically sent to the system.</h3>"); strbuilder.append("<h3>send date by "+dateutil.getdateformat(new date(),dateutil.datetime_default_format) +"</h3>"); strbuilder.append("<h3>the following is the details:</h3>"); strbuilder.append("<table border=\"2px solid red\" width=\"100%\">"); //头 strbuilder.append("<thead style=\"background-color: #aea2e2;\">"); strbuilder.append("<th>"+obj.touppercase()+" detail</th>"); strbuilder.append("</thead>"); //体 strbuilder.append("<tbody>"); for(string item:content){ strbuilder.append("<tr><td>"+item+"</td></tr>"); } strbuilder.append("</tbody>"); strbuilder.append("</table>"); strbuilder.append("<h3 style=\"text-align:right;font-weight:normal;\">best wishes</h3>"); strbuilder.append("</body></html>"); log.info(strbuilder.tostring()); helper.settext(strbuilder.tostring(),true); }catch (exception e){ log.error("sendhtmlmail error:",e); } mailsender.send(msg); } }
以上我是将邮件功能封装成一个服务类,使用的时候只需要将当前类注入 然后直接调用即可,以上封装了两个方法:一个是简单邮件发送,一个是带html table的邮件,如果需要发送附件,需将附件放入到mimemessagehelper里面(调用addattachment("文件名", 文件))方法即可,这里因为无实际需求,遂就略去了,好了,邮件发送功能已经完成,这里看下实际效果:
邮件功能实现完毕,现在我讲讲文件压缩功能,压缩功能的实现大致有四种,分别是:
a>利用java.util.zip提供的api压缩
b>利用apache的ant包提供的api压缩(org.apache.tools.ant.taskdefs.zip)
c>使用zip4j提供的api压缩(net.lingala.zip4j)
d>调用宿主机的shell命令压缩
这里需要特别提到三个问题:
a>普通邮件压缩中文乱码(不支持中文)
b>压缩后无法解压(解压错误)
c>文件压缩添加压缩密码问题
实际开发过压缩功能,以上三点儿对于新手来说尤其的头痛,这里我分享下以前在开发压缩功能中碰到的问题。
使用原生java.util包提供的压缩,如果被压缩文件使用到中文,则会乱码(据说是jdk的一个bug),而且压缩实现的代码较为复杂(尤其是设置密码),尤其是对于跨目录压缩和多文件压缩尤其麻烦。
使用apache提供的zip工具虽避免了以上会出现的问题,但是需要提醒一点儿的是这个ant包与weblogic冲突(部署的时候会报错)且无法实现压缩设置密码,如果使用的是weblogic而不是tomocat的情况下,一定要注意到这个问题。
使用java调用宿主机的shell命令也是个不错的选择,但是,需要编写shell命令,同时对于部署在windows平台就不太友好了,移植比较麻烦。
最后,对于以上问题,我这里推荐zip4j,以下也是针对zip4j的压缩实现做讲解。
先,需要引入依赖包:
<!--压缩:支持加密压缩--> <dependency> <groupid>net.lingala.zip4j</groupid> <artifactid>zip4j</artifactid> <version>1.3.2</version> </dependency>
再,封装一个压缩/解压缩工具类以方便使用:
import net.lingala.zip4j.core.zipfile; import net.lingala.zip4j.exception.zipexception; import net.lingala.zip4j.model.zipparameters; import net.lingala.zip4j.util.zip4jconstants; import org.springframework.util.stringutils; import java.io.file; /** * 本工具类使用zip4j来进行压缩以及解压缩 */ public class ziputil { //声明压缩对象 private static zipparameters parameters; //解压文件对象 private static zipfile zipfile; /** * * @param sourcefilepath 被压缩的文件的路径(单文件,文件夹) * @param zipfilepath 压缩文件路径 * @param password 压缩密码 * @return 压缩成功:true ,压缩失败:false */ public static boolean singlefilecompress(string sourcefilepath,string zipfilepath,string password){ parameters = new zipparameters(); parameters.setcompressionmethod(zip4jconstants.comp_deflate); // 压缩方式(默认方式) parameters.setcompressionlevel(zip4jconstants.deflate_level_normal); // 压缩级别(默认级别) //压缩加密设置 if (!stringutils.isempty(password)) { parameters.setencryptfiles(true);//是否设置文件加密(默认为否) parameters.setencryptionmethod(zip4jconstants.enc_method_standard); // 加密方式(此处是标准压缩) parameters.setpassword(password.tochararray()); } try { zipfile zipfile = new zipfile(zipfilepath); //如果是文件则直接压缩,若是文件夹,遍历文件全部压缩 if(new file(sourcefilepath).isfile()) { zipfile.setfilenamecharset("gbk"); zipfile.addfile(new file(sourcefilepath), parameters); return true; } //file ff=new file(sourcefilepath); file[] flst=new file(sourcefilepath).listfiles(); system.out.println("文件个数=>"+flst.length); for(file f:flst){ zipfile.setfilenamecharset("gbk"); zipfile.addfile(f, parameters); } return true; } catch (zipexception e) { e.printstacktrace(); return false; }catch (exception id){ id.printstacktrace(); return false; } } public static boolean unzip(string zipfile,string unzipdir){ try { ziputil.zipfile = new zipfile(zipfile); ziputil.zipfile.setfilenamecharset("gbk");//设置编码格式 //用自带的方法检测一下zip文件是否合法,包括文件是否存在、是否为zip文件、是否被损坏等 if (!ziputil.zipfile.isvalidzipfile()) { throw new zipexception("文件不合法或不存在"); } // 跟java自带相比,这里文件路径会自动生成,不用判断 ziputil.zipfile.extractall(unzipdir); return true; }catch(zipexception e){ return false; } } }
以上压缩方法自带密码压缩功能,可以压缩单文件也可以压缩目录文件,相对于原生的实现,一下子清爽了许多,这里唯一需要说明的是,压缩的目标文件在压缩前一定不能穿件,否则会报错!另外对于解压缩一定要注意文件编码和判断文件是否存在。
总结
以上所述是小编给大家介绍的springboot实现添加邮件发送及压缩功能 ,希望对大家有所帮助