07SpringMVC--文件上传和下载 邮件发送 【工具类】
目录
JavaWeb
文件上传
jar
【文件上传的注意事项】
【需要用到的类详解】
文件上传需要使用到的3个类+1个属性
Fileltem类
常用方法介绍:
ServletFileUpload 类
代码实现:
jsp页面
servlet
下载文件
SpringMVC 文件上传下载 方式 【工具类】
导入jar包
web.xml
applicatinContext.xml
注册lib
index.jsp 表单
enctype="multipart/form-data" 一定要配置
applicatinContext.xml 添加文件上传配置
方式二:
邮件发送
传输协议
4个核心类
发送简单邮件
复杂邮件: 有附件和图片 MIMIE
复杂邮件 : 图片
复杂邮件 : 附件
邮件发送实战
1.index.JSP
2 实体类 序列化Serializable
3 servlet
4.servlet(绑定路径)
5.发送邮件核心类
JavaWeb
文件上传
jar
commons-fileupload commons-fileupload 1.4 commons-io commons-io 2.11.0
【文件上传的注意事项】
1.为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
2.为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
【时间戳、加密算法MD5、UUID、位运算】
3.要限制上传文件的最大值。
4.可以限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
【需要用到的类详解】
文件上传需要使用到的3个类+1个属性
- ServletFileUpload:在后端获取文件上传的文件数据,并将上传文件数据的表单中的每个输入项都封装为一个FileItem对象
- FileItem
- DiskFileItemFactory:使用ServletFileUpload解析前端表单传过来的文件数据时需要使用到DiskFileItemFactory对象,所以在获取ServletFileUpload对象之前我们需要先获取DiskFileItemFactory对象
- fileItemFactory属性:ServletFileUpload对象的一个属性
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个Fileltem对象,在使用ServletFileUpload对象解析请求时需要DiskFileltemFactory对象。所以,我们需要在进行解析工作前构造好DiskFileltemFactory对象,通过ServletFileUpload对象的构造方法或setFileltem Factory()方法设置ServletFileUpload对象的fileltemFactory属性。
Fileltem类
1、在HTML页面input必须有name
表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data 【必须】
上传用户:
常用方法介绍:
//isFormFile方法用于判断FileItem类对象封装的数据是一个普通文本表单//还是一个文件表单,如果时普通表单字段则返回true,否则返回falseboolean isField();//getFieldName方法用于返回表单标签name属性的值String getFieldName();//getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回String getString();//getName方法用于获得文件上传字段中的文件名。String getName();//以流的形式返回上传文件的数据内容。InputStream getInputStream();//delete方法用来清空FileItem类对象中存放的主体内容//如果主体内容被保存在临时文件中,delete方法将删除该临时文件void delete();
ServletFileUpload 类
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中 . 使用其parseRequest(HttpServletRequest) 方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回,使用该方法处理上传文件简单易用
代码实现:
package com.gh.servlet;/** * @author gh Email:@2495140780qq.com * @Description * @date 2022-01-06-下午 10:19 */import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.List;import java.util.UUID;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.ProgressListener;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;/** * Servlet implementation class FileSerlvet */public class FileSerlvet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException { //判断上传的表单是普通表单还是带文件的表单,是返回true,否返回false; if (!ServletFileUpload.isMultipartContent(request)){ return;//如果这是一个普通文件我们直接返回 }//如果通过了这个if,说明我们的表单是带文件上传的 //创建上传文件的保存目录,为了安全建议在WEB-INF目录下,用户无法访问 String uploadpath = this.getServletContext().getRealPath("WEB-INF/Upload");//获取上传文件的保存路径 File uploadfile = new File(uploadpath); if (!uploadfile.exists()){ uploadfile.mkdir();//如果目录不存在就创建这样一个目录 } //临时文件 //临时路径,如果上传的文件超过预期的大小,我们将它存放到一个临时目录中,过几天自动删除,或者提醒用户转存为永久 String tmppath = this.getServletContext().getRealPath("WEB-INF/tmp"); File file = new File(tmppath); if (!file.exists()){ file.mkdir();//如果目录不存在就创建这样临时目录 } //处理上传的文件一般需要通过流来获取,我们可以通过request.getInputstream(),原生态文件上传流获取,十分麻烦 //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于common-io组件; try { //1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小 DiskFileItemFactory factory = gteDiskFileItemFactory(file); //2、获取ServletFileUpload ServletFileUpload upload = getServletFileUpload(factory); //3、处理上传文件 String msg = uploadParseRequest(upload,request,uploadpath); //Servlet请求转发消息 request.setAttribute("msg",msg); request.getRequestDispatcher("/info.jsp").forward(request,response); }catch (FileUploadException e){ e.printStackTrace(); } } public static DiskFileItemFactory gteDiskFileItemFactory(File file){ //1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小 DiskFileItemFactory factory = new DiskFileItemFactory(); //通过这个工厂设置一个缓冲区,当上传的文件大小大于缓冲区的时候,将它放到临时文件中; factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1M factory.setRepository(file); return factory; } public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){ //2、获取ServletFileUpload ServletFileUpload upload = new ServletFileUpload(factory); //监听文件上传进度 upload.setProgressListener(new ProgressListener() { public void update(long pBytesRead, long lpContentLenght, int i) { //pBytesRead:已读取到的文件大小 //pContentLenght:文件大小 System.out.println("总大小:"+lpContentLenght+"已上传:"+pBytesRead); } }); //处理乱码问题 upload.setHeaderEncoding("UTF-8"); //设置单个文件的最大值 upload.setFileSizeMax(1024 * 1024 * 10); //设置总共能够上传文件的大小 //1024 = 1kb * 1024 = 1M * 10 = 10M upload.setSizeMax(1024 * 1024 * 10); return upload; } public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadpath) throws IOException, FileUploadException { String msg = ""; //3、处理上传文件 //把前端的请求解析,封装成一个FileItem对象 List fileItems = upload.parseRequest(request); for (FileItem fileItem : fileItems) { if (fileItem.isFormField()){ //判断是普通表单还是带文件的表单 //getFieldName指的是前端表单控件的name String name = fileItem.getFieldName(); String value = fileItem.getString("UTF-8");//处理乱码 System.out.println(name+":"+value); }else {//判断它是带文件的表单 //======================处理文件=======================// //拿到文件的名字 String uploadFileName = fileItem.getName(); System.out.println("上传的文件名:"+uploadFileName); if (uploadFileName.trim().equals("") || uploadFileName == null){ continue; } //获得上传的文件名,例如/img/girl/ooa.jpg,只需要ooa,其前面的后面的都不需要 String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1); //获得文件的后缀名 String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1); /* 如果文件后缀名fileExtName不是我们所需要的 就直接return,不处理,告诉用户文件类型不对*/ //可以使用UUID(唯一识别的通用码),保证文件名唯一 //UUID.randomUUID,随机生一个唯一识别的通用码 //网络传输中的东西,都需要序列化 //pojo,实体类,如果想要在多个电脑运行,传输--->需要吧对象都序列化了 //JNI=java Native Interface //implements Serializable :标记接口,JVM--->java栈 本地方法栈 native-->c++ String uuidPath= UUID.randomUUID().toString(); System.out.println("文件信息【文件名:"+fileName+"文件类型:"+fileExtName+"】"); //可以使用UUID(唯一通用识别码)来保证文件名的统一 String uuidFileName = UUID.randomUUID().toString(); //=======================传输文件=========================// //获得文件上传的流 InputStream inputStream = fileItem.getInputStream(); //创建一个文件输出流 FileOutputStream fos = new FileOutputStream(uploadpath + "/" + uuidFileName +"."+ fileExtName); //创建一个缓冲区 byte[] buffer = new byte[1024 * 1024]; //判断是否读取完毕 int len = 0; //如果大于0,说明还存在数据 while ((len=inputStream.read(buffer))>0){ fos.write(buffer,0,len); } //关闭流 fos.close(); inputStream.close(); msg = "文件上传成功!"; fileItem.delete();//上传成功,清除临时文件 } } return msg; }}
jsp页面
Title 上传用户:
|
info.jsp
Title ${msg}
servlet
FileServlet com.hao.servlet.FileServlet FileServlet /upload.do
下载文件
-
向浏览器输出消息
-
下载文件
-
要获取下载文件的路径
-
下载的文件名是啥?
-
设置想办法让浏览器(Content-Disposition)能够支持下载我们需要的东西
-
获取下载文件的输入流
Io
-
创建缓冲区
-
获取OutputStream对象
-
将FileOutputStream流写入到buffer缓冲区
-
使用OutputStream将缓冲区中的数据输出到客户端!
-
public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1. 要获取下载文件的路径 String realPath = "/G:\\JavaWeb-Servlet\\03-response\\target\\03-response\\WEB-INF\\classes\\1.jpg"; //2. 下载的文件名是啥 //方法:截取路径 / 后面的文件名 String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1); //3. 设置想办法让浏览器(Content-Disposition)能够支持下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码 //网上搜索:web下载文件的头 resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8")); //4. 获取下载文件的输入流 FileInputStream in = new FileInputStream(realPath); //5. 创建缓冲区 int len = 0; byte[] buffer = new byte[1024]; //6. 获取OutputStream对象 ServletOutputStream out = resp.getOutputStream(); //7. 将FileOutputStream流写入到buffer缓冲区 //8. 使用OutputStream将缓冲区中的数据输出到客户端 while((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); } in.close(); out.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); }}
SpringMVC 文件上传下载 方式 【工具类】
只需要更改下载的文件的位置即可
创建项目
导入jar包
commons-fileupload commons-fileupload 1.4 javax.servlet javax.servlet-api 4.0.1
web.xml
springmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc-servlet.xml 1 springmvc / encoding org.springframework.web.filter.CharacterEncodingFilter encoding utf-8 encoding /*
applicatinContext.xml
注册lib
index.jsp 表单
enctype="multipart/form-data" 一定要配置
$Title$
applicatinContext.xml 添加文件上传配置
CommonsMultipartFile 的 常用方法:
-
String getOriginalFilename():获取上传文件的原名
-
InputStream getInputStream():获取文件流
-
void transferTo(File dest):将上传文件保存到一个目录文件中
方式一
@Controllerpublic class FileController { //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象 //批量上传CommonsMultipartFile则为数组即可 @RequestMapping("/upload") public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException { //获取文件名 : file.getOriginalFilename(); String uploadFileName = file.getOriginalFilename(); //如果文件名为空,直接回到首页! if ("".equals(uploadFileName)){ return "redirect:/index.jsp"; } System.out.println("上传文件名 : "+uploadFileName); //上传路径保存设置 String path = request.getServletContext().getRealPath("/upload"); //如果路径不存在,创建一个 File realPath = new File(path); if (!realPath.exists()){ realPath.mkdir(); } System.out.println("上传文件保存地址:"+realPath); InputStream is = file.getInputStream(); //文件输入流 OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流 //读取写出 int len=0; byte[] buffer = new byte[1024]; while ((len=is.read(buffer))!=-1){ os.write(buffer,0,len); os.flush(); } os.close(); is.close(); return "redirect:/index.jsp"; }}
方式二 【推荐】
采用file.Transto 来保存上传的文件
/** 采用file.Transto 来保存上传的文件*/@RequestMapping("/upload2")public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException { //上传路径保存设置 String path = request.getServletContext().getRealPath("/upload"); File realPath = new File(path); if (!realPath.exists()){realPath.mkdir(); } //上传文件地址 System.out.println("上传文件保存地址:"+realPath); //通过CommonsMultipartFile的方法直接写文件(注意这个时候) file.transferTo(new File(realPath +"/"+ file.getOriginalFilename())); return "redirect:/index.jsp";}
文件下载步骤:
方式一:
1、设置 response 响应头
2、读取文件 -- InputStream
3、写出文件 -- OutputStream
4、执行操作
5、关闭流 (先开后关)
代码实现:
/* * 文件下载 * */ @RequestMapping(value="/download") public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{ //要下载的图片地址 String path = request.getServletContext().getRealPath("/upload"); String fileName = "基础语法.jpg"; //1、设置response 响应头 response.reset(); //设置页面不缓存,清空buffer response.setCharacterEncoding("UTF-8"); //字符编码 response.setContentType("multipart/form-data"); //二进制传输数据 //设置响应头 response.setHeader("Content-Disposition", "attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8")); File file = new File(path,fileName); //2、 读取文件--输入流 InputStream input=new FileInputStream(file); //3、 写出文件--输出流 OutputStream out = response.getOutputStream(); byte[] buff =new byte[1024]; int index=0; //4、执行 写出操作 while((index= input.read(buff))!= -1){ out.write(buff, 0, index); out.flush(); } out.close(); input.close(); return null; }
前端
点击下载
方式二:
a链接设置请求头
点击下载
邮件发送
要在网络上实现邮件功能,必须要有专门的邮件服务器
传输协议
SMTP协议
发送邮件:
我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
POP3协议
接收邮件:
我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
使用Java发送E-mail十分简单,但是首先你应该准备JavaMail API和Java Activation Framework。
得到两个jar包:
• mail.jar
• activation.jar
javax.mail mail 1.4.7 javax.activation activation 1.1.1
4个核心类
1.创建session对象
2.创建Transport对象
3.使用邮箱的用户名和授权码连上邮件服务器
4.创建一个Message对象(需要传递session)
message需要指明发件人、收件人以及文件内容
5.发送邮件
6.关闭连接
发送简单邮件
package com.gh;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;/** * @author gh Email:@2495140780qq.com * @Description * @date 2022-01-20-下午 8:36 *///发送简单邮件public class MailDemo01 { public static void main(String[] args) throws Exception { Properties prop=new Properties(); prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器 prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议 prop.setProperty("mail.smtp.auth","true");//需要验证用户密码 //QQ邮箱需要设置SSL加密 其他邮箱不需要 大厂 MailSSLSocketFactory sf=new MailSSLSocketFactory(); sf.setTrustAllHosts(true); prop.put("mail.smtp.ssl.enable","true"); prop.put("mail.smtp.ssl.socketFactory",sf); //使用javaMail发送邮件的5个步骤 //1.创建定义整个应用程序所需要的环境信息的session对象 // qq才有 其他邮箱没有 Session session=Session.getDefaultInstance(prop, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("XXXX@qq.com","授权码"); } }); //开启session的debug模式,这样可以查看到程序发送Email的运行状态 【可选】 session.setDebug(true); //2.通过session得到transport对象 Transport ts=session.getTransport(); //3.使用邮箱的用户名和授权码连上邮件服务器 ts.connect("smtp.qq.com","XXXX@qq.com","授权码"); //4.创建邮件:写邮件 //注意需要传递session MimeMessage message=new MimeMessage(session); //指明邮件的发件人 message.setFrom(new InternetAddress("XXXX@qq.com")); //指明邮件的收件人 message.setRecipient(Message.RecipientType.TO,new InternetAddress("XXXX@qq.com")); //邮件标题 message.setSubject("发送的标题"); //邮件的文本内容 message.setContent("内容","text/html;charset=UTF-8"); //5.发送邮件 ts.sendMessage(message,message.getAllRecipients()); //6.关闭连接 ts.close(); }}
复杂邮件: 有附件和图片 MIMIE
MIME(多用途互联网邮件扩展类型)
MimeBodyPart类
javax.mail.internet.MimeBodyPart类表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
MimeMultipart类
javax.mail.internet.MimeMultipart是抽象类Multipart的实现子类,它用来组合多个MIME消息。一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。
复杂邮件 : 图片
import com.sun.mail.util.MailSSLSocketFactory;import javax.activation.DataHandler;import javax.activation.FileDataSource;import javax.mail.*;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;import java.util.Properties;//复杂邮件 : 图片public class MailDemo02 { public static void main(String[] args) throws Exception { Properties prop=new Properties(); prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器 prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议 prop.setProperty("mail.smtp.auth","true");//需要验证用户密码 //QQ邮箱需要设置SSL加密 其他邮箱不需要 大厂 MailSSLSocketFactory sf=new MailSSLSocketFactory(); sf.setTrustAllHosts(true); prop.put("mail.smtp.ssl.enable","true"); prop.put("mail.smtp.ssl.socketFactory",sf); //使用javaMail发送邮件的5个步骤 //1.创建定义整个应用程序所需要的环境信息的session对象 // qq才有 其他邮箱没有 Session session=Session.getDefaultInstance(prop, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("XXXX@qq.com","授权码"); } }); //开启session的debug模式,这样可以查看到程序发送Email的运行状态 【可选】 session.setDebug(true); //2.通过session得到transport对象 Transport ts=session.getTransport(); //3.使用邮箱的用户名和授权码连上邮件服务器 ts.connect("smtp.qq.com","XXXX@qq.com","授权码"); //4.创建邮件:写邮件 //注意需要传递session MimeMessage message=new MimeMessage(session); //指明邮件的发件人 message.setFrom(new InternetAddress("XXXX@qq.com")); //指明邮件的收件人 message.setRecipient(Message.RecipientType.TO,new InternetAddress("XXXX@qq.com")); //邮件标题 message.setSubject("发送的标题"); /* * 邮件的文本内容 扩充 * message.setContent("内容","text/html;charset=UTF-8"); */ //=================================准备图片数据======================================= MimeBodyPart image = new MimeBodyPart(); //图片需要经过数据化的处理 DataHandler 数据处理 DataHandler dh = new DataHandler(new FileDataSource("G:\\JavaWeb-Servlet\\10-mail\\src\\4.png")); //在part中放入这个处理过图片的数据 image.setDataHandler(dh); //在我们的body 中放入这个处理的图片数据 //给这个part设置一个ID名字 image.setContentID("bz.jpg"); //准备正文的数据 MimeBodyPart text = new MimeBodyPart(); //src='cid:bz.jpg' 固定 对应上面 image.setContentID("bz.jpg"); 中setContentID text.setContent("这是一张正文", "text/html;charset=UTF-8"); //描述数据关系 MimeMultipart mm = new MimeMultipart(); mm.addBodyPart(text); mm.addBodyPart(image); mm.setSubType("related"); //设置到消息中,保存修改 message.setContent(mm); //把最后编辑好的邮件放到消息当中 message.saveChanges(); //保存修改 //======================================================================== //5.发送邮件 ts.sendMessage(message, message.getAllRecipients()); //6.关闭连接 ts.close(); }}
复杂邮件 : 附件
import com.sun.mail.util.MailSSLSocketFactory;import javax.activation.DataHandler;import javax.activation.FileDataSource;import javax.mail.*;import javax.mail.internet.*;import java.util.Properties;复杂邮件 : 附件public class MailDemo03 { public static void main(String[] args) throws Exception { Properties prop=new Properties(); prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器 prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议 prop.setProperty("mail.smtp.auth","true");//需要验证用户密码 //QQ邮箱需要设置SSL加密 MailSSLSocketFactory sf=new MailSSLSocketFactory(); sf.setTrustAllHosts(true); prop.put("mail.smtp.ssl.enable","true"); prop.put("mail.smtp.ssl.socketFactory",sf); //使用javaMail发送邮件的5个步骤 //1.创建定义整个应用程序所需要的环境信息的session对象 Session session=Session.getDefaultInstance(prop, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("1192XXXX@qq.com","授权码"); } }); //开启session的debug模式,这样可以查看到程序发送Email的运行状态 session.setDebug(true); //2.通过session得到transport对象 Transport ts=session.getTransport(); //3.使用邮箱的用户名和授权码连上邮件服务器 ts.connect("smtp.qq.com","1192XXXX@qq.com","授权码"); //4.创建邮件:写文件 //注意需要传递session MimeMessage message=new MimeMessage(session); //指明邮件的发件人 message.setFrom(new InternetAddress("1192XXXX@qq.com")); //指明邮件的收件人 message.setRecipient(Message.RecipientType.TO,new InternetAddress("1192XXXX@qq.com")); //邮件标题 message.setSubject("java发出"); //邮件的文本内容 //=================================准备图片数据 MimeBodyPart image=new MimeBodyPart(); //图片需要经过数据化的处理 DataHandler dh = new DataHandler(new FileDataSource("G:\\JavaWeb-Servlet\\10-mail\\src\\4.png")); //在part中放入这个处理过图片的数据 image.setDataHandler(dh); //给这个part设置一个ID名字 image.setContentID("bz.jpg"); //=================================准备正文数据 MimeBodyPart text=new MimeBodyPart(); text.setContent("这是一张正文","text/html;charset=UTF-8"); //=================================准备附件数据 MimeBodyPart body1= new MimeBodyPart(); body1.setDataHandler(new DataHandler(new FileDataSource("G:\\JavaWeb-Servlet\\10-mail\\src\\1.txt"))); body1.setFileName("1.txt"); //描述数据关系 MimeMultipart mm=new MimeMultipart(); mm.addBodyPart(body1); mm.addBodyPart(text); mm.addBodyPart(image); mm.setSubType("mixed"); //设置到消息中,保存修改 message.setContent(mm); message.saveChanges(); //5.发送邮件 ts.sendMessage(message,message.getAllRecipients()); //6.关闭连接 ts.close(); }}
邮件发送实战
1.index.JSP
Hello World!
用户名: 密码: 邮箱:
2 实体类 序列化Serializable
import java.io.Serializable;/** * @author gh Email:@2495140780qq.com * @Description * @date 2022-01-20-下午 9:53 */public class User implements Serializable { private String username; private String password; private String email; public User() { } public User(String username, String password, String email) { this.username = username; this.password = password; this.email = email; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + ", email='" + email + '\'' + '}'; }}
3 servlet
import com.gh.pojo.User;import com.gh.utils.Sendmail;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * @author gh Email:@2495140780qq.com * @Description * @date 2022-01-20-下午 10:00 */public class RegisterServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //接收用户数据,封装成对象 String username=req.getParameter("username"); String password=req.getParameter("pwd"); String email=req.getParameter("email"); User user=new User(username,password,email); //用户注册成功之后,给用户发送一封邮件 //我们使用线程来专门发送邮件。防止出现耗时,和网站注册人数过多的情况 Sendmail send=new Sendmail(user); //启动线程,线程启动之后就会执行run方法来发送邮件 send.start(); //祖册用户 req.setAttribute("message", "注册成功,我们已经发送了一封邮件,请查收!网络不稳定,可能过会才能收到!!!"); req.getRequestDispatcher("info.jsp").forward(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); }}
4.servlet(绑定路径)
RegisterServlet com.gh.servlet.RegisterServlet RegisterServlet /RegisterServlet.do
5.发送邮件核心类
package com.gh.utils;import com.gh.pojo.User;import com.sun.mail.util.MailSSLSocketFactory;import javax.mail.*;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeMessage;import java.util.Properties;/** * @author gh Email:@2495140780qq.com * @Description * @date 2022-01-20-下午 10:00 */// 网址3秒原则 : 用户体验// 多线程实现用户体验 (异步处理)public class Sendmail extends Thread { //用于给用户发送邮件的邮箱 private String from = "XXXX@qq.com"; //邮箱的用户名 private String username = "XXX@qq.com"; // 邮箱的密码 授权码 private String password = "XXX"; //发送邮件的服务器地址 private String host="smtp.qq.com"; private User user; public Sendmail(User user){ this.user=user; } //重写run实现方法的实现,在run方法中实现邮件给制定的用户 @Override public void run() { try { Properties prop=new Properties(); prop.setProperty("mail.host",host);///设置QQ邮件服务器 prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议 prop.setProperty("mail.smtp.auth","true");//需要验证用户密码 //QQ邮箱需要设置SSL加密 MailSSLSocketFactory sf=new MailSSLSocketFactory(); sf.setTrustAllHosts(true); prop.put("mail.smtp.ssl.enable","true"); prop.put("mail.smtp.ssl.socketFactory",sf); //使用javaMail发送邮件的5个步骤 //1.创建定义整个应用程序所需要的环境信息的session对象 Session session= Session.getDefaultInstance(prop, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(from,password);//授权码 } }); //开启session的debug模式,这样可以查看到程序发送Email的运行状态 session.setDebug(true); //2.通过session得到transport对象 Transport ts=session.getTransport(); //3.使用邮箱的用户名和授权码连上邮件服务器 ts.connect(host,from,password);//授权码 //4.创建邮件:写文件 //注意需要传递session MimeMessage message=new MimeMessage(session); //指明邮件的发件人 message.setFrom(new InternetAddress(from)); //指明邮件的收件人 message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getEmail())); //邮件标题 message.setSubject("注册通知"); //邮件的文本内容 message.setContent("恭喜你("+user.getUsername()+")成功注册!"+"密码:"+user.getPassword() + "请妥善保管你的密码,不要让他人知道" ,"text/html;charset=UTF-8"); //5.发送邮件 ts.sendMessage(message,message.getAllRecipients()); //6.关闭连接 ts.close(); }catch (Exception e){ System.out.println(e); } }}
这里引入多线程的目的是为了提高用户的体验,防止因发送文件时间过长,导致前端响应过久,因此这里采用异步响应。