文件传输原理及介绍
1.准备工作
对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的
—般选择采用apache的开源工具common-fileupload这个文件上传组件。
common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
文件上传依赖这两的包,这两个包的作用?
- common-io
- 通过一个io操作,把大量的工具类封装到这个包里边,拿来即用
- 相当于网站的常用工具类打包,拿来即用
- common-fileupload
- 针对于文件上传,做的包
jar包
-
本质是zip压缩包,后缀名是.jar
-
压缩的是就java代码,编译后的
jar包如何导入项目?
-
项目发布之后,会把里边的东西全部打包,包括jdk里的东西,
-
导包,两种方式
- 1、要把jar添加到类库里边 Add as Libray
- 2、项目结构中,项目目录的图书馆中添加问题:lib目录没有放到最后项目发布里边
2.使用类介绍(了解)
【文件上传的注意事项】
文件上传调优
文件上传的注意事项
1. 为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,**比如放在WEB-INF目录下**
2. 为防止文件能覆盖的现象的发生,要为上传文件产生一个唯一的文件名
3. 要限制上传文件的最大值
4. 可以限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法
-
为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
-
为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
如:1.txt 1.txt 文件重名,解决方案:
1. 加,时间戳(最常见)
* 不安全,两个人不能在同一时间上传
2. uuid
* 生成一段随机的,不会重复的,数字
3. md5
* 加密码
4. 位运算算法
* 如,上传东西:二进制流,左移一位……
3. 要限制上传文件的最大值。
* 服务器要钱
四个类
-
ServletFileUpload:文件上传
-
Fileltem:文件遍历
-
DiskFileltemFactory:磁盘文件遍历一个迭代系统
-
fileltemFactory:文件工厂,
- 对应的设计模式:工厂模式
- 为了偷懒,不去new对象,用工厂生产对象
- 对应的设计模式:工厂模式
流程
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个Fileltem对象,在使用ServletFilelpload对象(上传)解析请求时,需要DiskFileltemFactory对象。所以,我们需要在进行解析工作前构造好DiskFileltemFactory对象,通过SevletFileUpload对象的构造方法或setFileltemFactory()方法设置ServletFileUpload对象的fileltemFactory属性。
ServletFileUpload这个类专门负责:上传文件的数据,
ServletFileUpload这个类会把表单(上传文件的表单)中的每一项封装成一个对象Fileltem,
再使用ServletFileUpload对象(上传)解析请求时,需要DiskFileltemFactory对象。
我们再把它解析到磁盘的时候(放到网站,或服务器中),会需要它(ServletFileUpload)的构造方法,一个fileltemFactory属性
Fileltem类
在HTML页面input必须有name
在页面中必须有一个包含file的表单
第一步
让表单支持文件上传需要加属性
表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data
<form action="" enctype="multipart/form-data" method="post">
ServletFileUpload类
ServletFileUpload:== 负责处理上传的文件数据,并将表单中每个输入项封装成一个Fileltem对象中==,使用其**parseRequest(HttpServletRequest)**方法可以将通过表单中每一个HTML标签提交的数据封装成—个Fileltem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。
代码实现
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
上传用户:<input type="text" name="username"><br/>
<p><input type="file" name="file1"></p>
<p><input type="file" name="file2"></p>
<p><input type="submit"> | <input type="reset"></p>
</form>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<servlet>
<servlet-name>FileServlet</servlet-name>
<servlet-class>com.home.servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>
</web-app>
FileServlet.java
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;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
public class FileServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//判断上传的表单是普通表单还是文件表单
if (!ServletFileUpload.isMultipartContent(request)) {
//终止方法运行,说明这是一个普通的表单,直接返回
return;
}
//创建上传文件的保存路径,建议在web-inf路径下,安全,用户无法直接访问上传的文件
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {
uploadFile.mkdir();//创建这个目录
}
//临时文件
//临时路径,假如文件超过了预期的大小,我们就把他放到一个临时文件中,过几天自助删除,或者提醒用户转存为永久
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tempFile = new File(tempPath);
if (!tempFile.exists()) {
tempFile.mkdir();//创建这个临时目录
}
//处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
//但是我们都是建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于commons-io组件
//1.创建DiskFileItemFactory对象,处理文件路径上传或者大小限制的
DiskFileItemFactory factory = createDiskFileItemFactory(tempFile);
//2.获取ServletFileUpload
ServletFileUpload upload = creatServletFileUpload(factory);
//3.处理上传的文件
String msg = uploadFile(request, uploadPath, upload);
//转发
request.setAttribute("msg", msg);
request.getRequestDispatcher("/info.jsp").forward(request, response);
}
private String uploadFile(HttpServletRequest request, String uploadPath, ServletFileUpload upload) throws IOException {
String msg = "";
//把前端请求解析,封装成一个FileItem对象,需要从ServletFileUpload对象中获取
try {
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()) {
String fieldName = fileItem.getFieldName();
//处理乱码
String value = fileItem.getString("UTF-8");
System.out.println(fieldName + ":" + value);
} else {
//文件
//===========处理文件============
String uploadFileName = fileItem.getName();
System.out.println("uploadFileName:" + uploadFileName);
//可能存在文件名不合法的情况
if (uploadFileName == null || "".equals(uploadFileName.trim())) {
continue;
}
//获取上传的文件名
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
//获取文件的后缀名
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
//如果文件后缀名fileExtName不是我们所需要的,就直接return,不处理,告诉用户文件类型不对
//可以使用UUID(统一识别的通用码),保证文件名唯一
//UUID.randomUUID() 随机生一个唯一识别的通用码
//网络从传输中的东西,都需要序列化
//JNI = Java Native interface
//implements java.io.Serializable 标记接口 JVM--> 本地方法栈--> native -->C++
String uuidPath = UUID.randomUUID().toString();
//===========存放地址============
String realPath = uploadPath + "/" + uuidPath;
File realPathFile = new File(realPath);
if (!realPathFile.exists()) {
realPathFile.mkdir();
}
//===========文件传输============
InputStream inputStream = fileItem.getInputStream();
FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
byte[] buffer = new byte[1024 * 1024];
int len = 0;
while ((len = inputStream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
inputStream.close();
msg = "上传成功~";
}
}
} catch (FileUploadException e) {
e.printStackTrace();
msg = "上传失败~";
}
return msg;
}
private ServletFileUpload creatServletFileUpload(DiskFileItemFactory factory) {
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener(new ProgressListener() {
/**
*
* @param pBytesRead 已经读取到的文件大小
* @param pContentLength 文件总大小
* @param pItems
*/
@Override
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("总大小:" + pContentLength + "已经上传:" + pBytesRead);
}
});
//处理乱码问题
upload.setHeaderEncoding("UTF-8");
//设置单个文件的最大值
upload.setFileSizeMax(1020 * 1024 * 10);
//设置总共能够上传文件的大小
//1020 = 1kb * 1024 = 1M * 10 = 10M
upload.setSizeMax(1020 * 1024 * 10);
return upload;
}
private DiskFileItemFactory createDiskFileItemFactory(File tempFile) {
DiskFileItemFactory factory = new DiskFileItemFactory();
//通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中
//缓冲区大小为1M
factory.setSizeThreshold(1024 * 1024);
//临时目录的保存目录
factory.setRepository(tempFile);
return factory;
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
注意点:使用Maven创建注意artifacts中lib中commons的jar是否导入,
17、邮件发送原理及实现
以下邮件的实现在spring框架可以用JavaMailSenderImpl实现
学习原生态的可以方便使用框架
邮件收发
要在网络上实现邮件功能,必须要有专门的邮件服务器。
这些邮件服务器类似于现实生活中的邮局,
- 它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
- 对应:接收和发送
- 接收:POP3协议
- 发送:SMTP协议
SMTP服务器地址:一般是smtp.xxx.com,每一个网站都有自己的服务器地址(固定的)
- 比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com。
电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。
- 比如我们要使用QQ邮箱,就需要开通邮箱功能。
SMTP服务器地址
例如:QQ邮箱
传输协议
SMTP协议
发送邮件:
我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
POP3协议
接收邮件:
我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
邮件发送原理图
- 张三通过smtp协议连接到Smtp服务器,然后发送一封邮件给网易的邮件服务器
- 网易分析发现需要去QQ的邮件服务器,通过smtp协议将邮件转投给QQ的Smtp服务器
- QQ将接收到的邮件存储在周旺@qq.com这个邮件账号的空间中
- 李四通过Pop3协议连接到Pop3服务器收取邮件
- 从周旺@qq.com这个邮件账号的空间中取出邮件
- Pop3服务器将取出来的邮件送到李四手中
【注意】
有可能你收件人地址,发件人地址等信息都正确了,控制台也打印了正确的信息,但是在收件箱就是收不到信息。
这是因为可能收件箱服务器拒收了你发的邮件(比如认为你的邮件是广告),这时候可能在垃圾箱里能找到,可能找不到。
解决办法是重复的邮件内容不要多次发送,或者更换收件箱试试
Java发送邮件
概述
我们将用代码完成邮件的发送,这在实际项目中应用的非常广泛。
- 比如注册需要发送邮件进行账号激活,
- 再比如OA项目中利用邮件进行任务提醒等等。
使用Java发送 E-mail 十分简单,但是首先你应该准备
- JavaMail API
- Java Activation Framework 。(发送邮件的支持包)
得到两个jar包:网络协议的
- mail.jar
- activation.jar
JavaMail 是sun公司(现以被甲骨文收购)为方便Java开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发包,
它支持一些常用的邮件协议,如前面所讲的SMTP,POP3,IMAP,还有MIME(附件和图片)等。
我们在使用JavaMail API 编写邮件时,无须考虑邮件的底层实现细节,只要调用JavaMail 开发包中相应的API类就可以了。
我们可以先尝试发送一封简单的邮件,确保电脑可以连接网络。
-
创建包含邮件服务器的网络连接信息的Session对象。
-
创建代表邮件内容的Message对象
-
创建Transport对象,连接服务器,发送Message,关闭连接
主要有四个核心类,我们在编写程序时,记住这四个核心类,就很容易编写出Java邮件处理程序。
Session:定义整个程序,所有的信息。比如:smtp.qq.com、邮箱账号、密码
Transport:发送邮件
Message:信息的内容。对应:收件人、主题、正文
纯文本邮件
导包
先在项目中导入jar包
权限
QQ邮箱中获取对应的权限
QQ邮箱需要安全验证,我们需要获取他对应的权限;
QQ邮箱–>邮箱设置–>账户
点击开启,获得16位的授权码:
总结
- 简单邮件:没有附件和图片,纯文本图片
- 复杂邮件:有附件和图片
- 要发送邮件,需要获得协议和支持!开启服务POP3/SMTP服务
- QQ授权码:……
步骤
1、准备消息
2、发送到哪里去
代码实现
package com.home;
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 MailDemo01 {
public static void main(String[] args) throws Exception {
//Properties中 设置属性
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加密,原因:大厂。其他邮箱不需要 ----- 2022年12月、目前不需要加密了
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");//使用安全的连接为true
prop.put("mail.smtp.ssl.socketFactory",sf);//socket工厂,使用自己的socket工厂*/
//使用javaMail发送邮件的5个步骤
//1.创建定义整个应用程序所需要的环境信息的session对象
//QQ才有!其他邮箱就不用
Session session= Session.getDefaultInstance(prop, new Authenticator() {//获取默认的实例
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮箱、授权码
return new PasswordAuthentication("707748528@qq.com","cyiffgtkbxvjbcjg");
}
});
//开启session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2.通过session得到transport对象
Transport ts = session.getTransport();
//3.使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com","777777777@qq.com","cyiffgtkbxvjbcjg");
//4.创建邮件:写邮件
//需要传递session
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("777777777@qq.com"));
//指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
message.setRecipient(Message.RecipientType.TO, new InternetAddress("777777777@qq.com"));
//邮件的标题 只包含文本的简单邮件
message.setSubject("发送的标题");
//邮件的文本内容
message.setContent("你好","text/html;charset=UTF-8");
//5.发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6.关闭连接,一切网络都需要关闭
ts.close();
}
}
带图片和附件的邮件
两个类
先认识两个类一个名词:
MIME(多用途互联网邮件扩展类型)
- MimeBodyPart类 (内容的主体)
- javax.mail.internet.MimeBodyPart类
- 表示的是一个MIME消息,它和MimeMessage类一样都是从Part接口继承过来。
- MimeMultipart类 (内容的封装)
- javax.mail.internet.MimeMultipart是抽象类
- Multipart的实现子类,它用来组合多个MIME消息。
- 一个MimeMultipart对象可以包含多个代表MIME消息的MimeBodyPart对象。
流程图
在MimeBodyPart中有三个属性
- mixed:附件
- related:内嵌资源
- alternative:超文本正文
代码实现
package com.home;
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中 设置属性
Properties prop=new Properties();
prop.setProperty("mail.host","smtp.qq.com");///设置QQ邮件服务器
prop.setProperty("mail.transport.protocol","smtp");///邮件发送协议
prop.setProperty("mail.smtp.auth","true");//需要验证用户密码
//使用javaMail发送邮件的5个步骤
//1.创建定义整个应用程序所需要的环境信息的session对象
//QQ才有!其他邮箱就不用
Session session= Session.getDefaultInstance(prop, new Authenticator() {//获取默认的实例
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮箱、授权码
return new PasswordAuthentication("777777777@qq.com","cyiffgtkbxvjbcjg");
}
});
//开启session的debug模式,这样可以查看到程序发送Email的运行状态
session.setDebug(true);
//2.通过session得到transport对象
Transport ts = session.getTransport();
//3.使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com","777777777@qq.com","cyiffgtkbxvjbcjg");
//4.创建邮件:写邮件
//需要传递session
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("707748528@qq.com"));
//指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
message.setRecipient(Message.RecipientType.TO, new InternetAddress("777777777@qq.com"));
//邮件的标题 只包含文本的简单邮件
message.setSubject("发送的标题");
//邮件的文本内容
message.setContent("你好","text/html;charset=UTF-8");
/*==================图片和附件的邮件=========================*/
//=================================准备图片数据
MimeBodyPart image = new MimeBodyPart();
//图片需要经过数据化的处理 DataHandler:数据处理 FileDataSource:加载文件的资源
DataHandler dh = new DataHandler(new FileDataSource("F:\\JAVA\\代码\\JavaWeb\\功能扩展\\mail-java\\src\\1.png"));
//在part中放入这个处理的图片数据
image.setDataHandler(dh);
//给这个part设置一个ID名字,我们在后面可以使用
image.setContentID("bz.jpg");
//=================================准备正文数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一张正文<img src='cid:bz.jpg'>","text/html;charset=UTF-8");
//=================================准备附件数据
MimeBodyPart body1= new MimeBodyPart();
body1.setDataHandler(new DataHandler(new FileDataSource("F:\\JAVA\\代码\\JavaWeb\\功能扩展\\mail-java\\src\\a.txt")));
body1.setFileName("a.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();
}
}
JavaWeb发送邮件(网站注册发送邮件实现)
现在很多的网站都提供有用户注册功能, 通常我们注册成功之后就会收到一封来自注册网站的邮件。邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账户的超链接等信息。今天我们也来实现一个这样的功能,用户注册成功之后,就将用户的注册信息以Email的形式发送到用户的注册邮箱当中,实现发送邮件功能就得借助于JavaMail了。
思路:把收件人地址改成从前端接收过来的参数
代码实现:
1.先搭建框架
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
邮箱:<input type="text" name="email"><br/>
<input type="submit" value="注册">
</form>
</body>
</html>
RegisterServlet类
package com.yin.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
脚手架
通过这个框架,可以往里边不断添加功能
*/
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("password");
String email = req.getParameter("email");
System.out.println(username);
System.out.println(password);
System.out.println(email);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
======
123
1233123
12312
配置:Web.xml
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.yin.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/RegisterServlet,do</url-pattern>
</servlet-mapping>
2.实体类
package com.home.pojo;
import java.io.Serializable;
/*
实体类
要序列化,为了安全
*/
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;
}
public String toString() {
return "User{username = " + username + ", password = " + password + ", email = " + email + "}";
}
}
3.工具类
package com.home.util;
import com.home.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;
/*
网站3秒原则:用户体验
让用户不等待,事情也还做?
用户执行完这个方法,它还走它的东西,我走我的页面
通过多线程,实现用户体验!(异步处理)
*/
public class SendMail extends Thread{
//用于给用户发送邮件的邮箱
private String from = "777777777@qq.com" ;
//邮箱的用户名
private String username = " 777777777@qq.com" ;
//邮箱的密码
private String password = "cyiffgtkbxvjbcjg";
//发送邮件的服务器地址
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");//需要验证用户密码
//使用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,username,password);
//4.创建邮件:写文件
//注意需要传递session
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress(from));
//指明邮件的收件人
message.setRecipient(Message.RecipientType.TO,new InternetAddress(user.getEmail()));//从前端接收的
//邮件标题
message.setSubject("注册通知");
//邮件的文本内容
String info = "恭喜你("+user.getUsername()+")成功注册!"+"密码:"+user.getPassword();
message.setContent(info,"text/html;charset=UTF-8");
message.saveChanges();//保存更改
//5.发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6.关闭连接
ts.close();
}catch (Exception e){
System.out.println(e);
}
}
}
4.Servlet类
package com.yin.servlet;
import com.yin.pojo.User;
import com.yin.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;
/*
脚手架
通过这个框架,可以往里边不断添加功能
*/
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("password");
String email = req.getParameter("email");
//把用户的请求封装成一个对象
User user = new User(username,password,email);
//启动线程,重定向页面
/*
用户注册成功后,给用户发送一封邮件
我们使用线程来专门发送邮件,防止出现耗时、白屏和网站注册人数过多的情况
*/
SendMail send = new SendMail(user);
send.start();
//注册用户
req.setAttribute("message","注册成功,我们已经发了一封要了注册信息的电子邮件,请查收!如网络不稳定,等稍等");
req.getRequestDispatcher("info.jsp").forward(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
5.提示页面
info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>网站温馨提示</h1>
${message}
</body>
</html>
流程
从index.jsp进入页面,点击提交的时候,走RegisterServlet.do
RegisterServlet.do通过web.xml找到RegisterServlet
RegisterServlet
- 接收用户
- 收成一个对象
- 通过线程发送
- 发送成功跳转回info.jsp页面
项目环境上的问题:
- Project Structure:项目结构
效果