Java(JavaWeb07)
参考视频:38. 文件传输原理及介绍(狂神)
16. JavaWeb实现文件上传
16.1 准备工作
- 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的。
- 一般采用Apache的开源工具common-fileupload这个文件上传组件。
- common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
- common-io: https://mvnrepository.com/artifact/commons-io/commons-io/2.6
- common-fileupload: https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload/1.4
- 在JavaWeb项目中导入jar包:
16.2 使用类介绍
【文件上传注意事项】
- 为保证服务器的安全,上传的文件应放在外界无法访问的目录下,如WEN-INF。
- 为防止同名文件产生覆盖现象,要为文件指定一个唯一的文件名。
- 要对上传文件的大小进行限制。
- 限制上传文件的类型,收到文件时,判断文件名十分合法。
【需要用到的类详解】
- ServletFileUpload 负责处理上传的文件数据,并将表单中的每个输入项封装成一个 FileItem 对象,在使用ServletFileUpload 对象解析请求时需要 DiskFileItemFactory 对象。所以,我们需要在进行解析工作前构造好 DiskFileItemFactory 对象,通过 ServletFileItem 对象的构造方法或 setFileItemFactory() 设置 ServletFileUpload 对象的 fileItemFactory 属性。
FileItem类
-
在HTML页面中必须要有name
<input type="file" name="filename>"
-
表单如果包含一个文件上传输入项的话,这个表单的enctype属性就必须设置为multipart/form-data
-
问题:
- 如果new 不出Servlet,要添加Tomcat中的jar包。
- 项目可能出问题,点
Fix
修复。
16.3 文件上传代码
- info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
- index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%--通过表单上传文件
get: 上传文件大小限制
post: 没限制
--%>
<%--${pageContext.request.contextPath}获取服务器路径--%>
<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">
<servlet>
<servlet-name>FileServlet</servlet-name>
<servlet-class>com.zach.servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>
</web-app>
- FileServlet
package com.zach.servlet;
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;
/**
* @author : Zach
* @date : 2022-06-16 11:44
* @description :
* @modified by :
*/
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//判断上传的文件是普通表单还是带文件的表单
if (!ServletFileUpload.isMultipartContent(req)){
return;//终止方法运行,说明这是一个普通的表单,直接返回。
}
//创建上传文件的保存路径,建议在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 tmpFile = new File(tmpPath);
if (!tmpFile.exists()){
tmpFile.mkdir();//创建这个临时目录
}
//处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦。
//但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,他需要依赖于commons-io组件。
//以下为复制的
//1.创建DiskFileItemFactory对象,处理文件路径上传或者大小限制的
DiskFileItemFactory factory = createDiskFileItemFactory(tmpFile);
//2.获取ServletFileUpload
ServletFileUpload upload = creatServletFileUpload(factory);
//3.处理上传的文件
String msg = uploadFile(req, uploadPath, upload);
//转发
req.setAttribute("msg", msg);
req.getRequestDispatcher("/info.jsp").forward(req, resp);
}
private String uploadFile(HttpServletRequest req, String uploadPath, ServletFileUpload upload) throws IOException {
String msg = "";
//把前端请求解析,封装成一个FileItem对象,需要从ServletFileUpload对象中获取
try {
List<FileItem> fileItems = upload.parseRequest(req);
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() 随机生一个唯一识别的通用码
//网络从传输中的东西,都需要序列化
//implements java.io.Serializable 标记接口 本地方法栈--》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(1024 * 1024 * 10);
//设置总共能够上传文件的大小
//1020 = 1kb * 1024 = 1M * 10 = 10M
upload.setSizeMax(1024 * 1024 * 10);
return upload;
}
private DiskFileItemFactory createDiskFileItemFactory(File tmpFile) {
DiskFileItemFactory factory = new DiskFileItemFactory();
//通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中
//缓冲区大小为1M
factory.setSizeThreshold(1024 * 1024);
//临时目录的保存目录
factory.setRepository(tmpFile);
return factory;
}
}
17. JavaWeb实现邮件发送
17.1 介绍和原理
- 要在网络上实现邮件功能,必须要有专门的邮件服务器。
- 这些邮件服务器类似于现实生活中的邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中。
- SMTP服务器地址一般是:
smtp.xxx.com
,比如163邮箱是smtp.163.com,qq邮箱是smtp.qq.com. - 电子邮箱(E-Mail地址)的获得需要在邮件服务器上进行申请。比如我们要使用QQ邮箱,就需要开通邮箱功能。
- 传输协议
- SMTP协议
- 发送邮件:
- 我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
- POP3协议
- 接收邮件:
- 我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
- 邮件收发原理
- 大狂神通过smtp协议连接到Smtp服务器,然后发送一封邮件给网易的邮件服务器
- 网易分析发现需要去QQ的邮件服务器,通过smtp协议将邮件转投给QQ的Smtp服务器
- QQ将接收到的邮件存储在
24736743@qq.com
这个邮件账号的空间中 - 小狂神通过Pop3协议连接到Pop3服务器收取邮件
- 从
24736743@qq.com
这个邮件账号的空间中取出邮件 - Pop3服务器将取出来的邮件送到小狂神手中
- 【注意】有可能你收件人地址,发件人地址等信息都正确了,控制台也打印了正确的信息,但是在收件箱就是收不到信息。这是因为可能收件箱服务器拒收了你发的邮件(比如认为你的邮件是广告),这时候可能在垃圾箱里能找到,可能找不到。解决办法是重复的邮件内容不要多次发送,或者更换收件箱试试。
17.2 邮件发送的代码
- 导入两个jar包
- mail.jar
mail-1.4.7.jar
- activation.jar
activation-1.1.1.jar
- mail.jar
- QQ邮箱授权码在QQ邮箱设置中获取。(要开启POP3/SMTP服务)
- MailDemo01 (纯文本发送邮件)
package com.zach;
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 GeneralSecurityException, MessagingException {
Properties properties = new Properties();
properties.setProperty("mail.host", "smtp.qq.com");//设置QQ邮件服务器
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);
//使用javaMail发送邮件的5个步骤:
//1. 创建定义整个应用程序所需的环境信息的Session对象
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("525266345@qq.com", "授权码");
}
});
//--开启debug模式,这样就可以查看到程序发送email的运行状态
session.setDebug(true);
//2. 通过session得到transport对象
Transport ts = session.getTransport();
//3. 使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com", "525266345@qq.com", "授权码");
//4. 创建邮件
MimeMessage message = new MimeMessage(session);
//--邮件的发件人
message.setFrom(new InternetAddress("525266345@qq.com"));
//--邮件的收件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress("525266345@qq.com"));
//--邮件的标题
message.setSubject("Hello...");
//--邮件的文本内容
message.setContent("<h1 style='color: red'>你好...</h1>", "text/html;charset=UTF-8");
//5. 发送邮件
ts.sendMessage(message, message.getAllRecipients());
//6.关闭连接
ts.close();
}
}
- MailDemo01 (发送文本+图片)
package com.zach;
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.security.GeneralSecurityException;
import java.util.Properties;
//发送一封简单的邮件
public class MailDemo01 {
public static void main(String[] args) throws GeneralSecurityException, MessagingException {
Properties properties = new Properties();
properties.setProperty("mail.host", "smtp.qq.com");//设置QQ邮件服务器
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);
//使用javaMail发送邮件的5个步骤:
//1. 创建定义整个应用程序所需的环境信息的Session对象
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("525266345@qq.com", "授权码");
}
});
//--开启debug模式,这样就可以查看到程序发送email的运行状态
session.setDebug(true);
//2. 通过session得到transport对象
Transport ts = session.getTransport();
//3. 使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com", "525266345@qq.com", "授权码");
//4. 创建邮件
MimeMessage message = new MimeMessage(session);
//--邮件的发件人
message.setFrom(new InternetAddress("525266345@qq.com"));
//--邮件的收件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress("525266345@qq.com"));
//--邮件的标题
message.setSubject("Hello...");
//--邮件的文本内容
//message.setContent("<h1 style='color: red'>你好...</h1>", "text/html;charset=UTF-8");
//==================================================
//准备 图片 数据
MimeBodyPart image = new MimeBodyPart();
//图片需要经过数据处理... DataHandler
DataHandler dh = new DataHandler(new FileDataSource("C:\\Users\\Administrator\\IdeaProjects\\JavaWeb\\功能扩展\\mail-java\\src\\1.png"));
image.setDataHandler(dh);//在我们的Body中放入这个处理的图片数据
//给图片设置一个id
image.setContentID("bz.jpg");
//准备 文本 数据
MimeBodyPart text = new MimeBodyPart();//ContentID=cid
text.setContent("这是一封邮件带图片<img src='cid:bz.jpg'/>的邮件","text/html;charset=UTF-8");
//描述数据关系:整合
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");//最高是mixed
//设置到消息中,保存修改
message.setContent(mm);//把最后编辑好的邮件放到消息中
message.saveChanges();//保存修改
//==================================================
//5. 发送邮件
ts.sendMessage(message, message.getAllRecipients());
//6.关闭连接
ts.close();
}
}
18. 网站注册发送邮件实现
- 简单邮件:没有附件和图片,纯文本邮件
- 复杂邮件:有附件和图片
- 要发送邮件,需要获得协议和支持!才能开启服务:POP3/SMTP服务
- 在QQ邮箱中获取授权码:
可以有多个,此处不展示。
- MailDemo01 (在非Web的Java项目中)
package com.zach;
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.security.GeneralSecurityException;
import java.util.Properties;
//发送一封简单的邮件
public class MailDemo01 {
public static void main(String[] args) throws GeneralSecurityException, MessagingException {
Properties properties = new Properties();
properties.setProperty("mail.host", "smtp.qq.com");//设置QQ邮件服务器
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);
//使用javaMail发送邮件的5个步骤:
//1. 创建定义整个应用程序所需的环境信息的Session对象
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication("525266345@qq.com", "Authorization code");
}
});
//--开启debug模式,这样就可以查看到程序发送email的运行状态
session.setDebug(true);
//2. 通过session得到transport对象
Transport ts = session.getTransport();
//3. 使用邮箱的用户名和授权码连上邮件服务器
ts.connect("smtp.qq.com", "525266345@qq.com", "Authorization code");
//4. 创建邮件
MimeMessage message = new MimeMessage(session);
//--邮件的发件人
message.setFrom(new InternetAddress("525266345@qq.com"));
//--邮件的收件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress("525266345@qq.com"));
//--邮件的标题
message.setSubject("Hello...");
//--邮件的文本内容
//message.setContent("<h1 style='color: red'>你好...</h1>", "text/html;charset=UTF-8");
//==================================================
//准备 图片 数据
MimeBodyPart image = new MimeBodyPart();
//图片需要经过数据处理... DataHandler
DataHandler dh = new DataHandler(new FileDataSource("C:\\Users\\Administrator\\IdeaProjects\\JavaWeb\\功能扩展\\mail-java\\src\\1.png"));
image.setDataHandler(dh);//在我们的Body中放入这个处理的图片数据
//给图片设置一个id
image.setContentID("bz.jpg");
//准备 文本 数据
MimeBodyPart text = new MimeBodyPart();//ContentID=cid
text.setContent("这是一封邮件带图片<img src='cid:bz.jpg'/>的邮件","text/html;charset=UTF-8");
//描述数据关系:整合
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");//最高是mixed
//设置到消息中,保存修改
message.setContent(mm);//把最后编辑好的邮件放到消息中
message.saveChanges();//保存修改
//==================================================
//5. 发送邮件
ts.sendMessage(message, message.getAllRecipients());
//6.关闭连接
ts.close();
}
}
- 如果报错如下:
javax.mail.MessagingException: Could not connect to SMTP host: smtp.qq.com, port: 465
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
- 解决方案:
- 方案一:检查JDK版本,我的是
1.8.0_301
。在JDK安装目录下,例如:C:\Program Files\Java\jdk1.8.0_301\jre\lib\security
,查找java.security
文件,打开后将jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
这条语句的SSLv3, TLSv1, TLSv1.1,
这三项删除,即可。(但一般不建议改动JDK的文件) - 方案二:将以下代码段注释掉或者删掉。原因可能是QQ邮箱已经不再需要设置SSL加密。
- 方案一:检查JDK版本,我的是
//关于QQ邮箱,还需要设置SSL加密,加上以下以下代码即可
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
- 在JavaWeb项目中启用多线程发送邮件
- pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
- 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">
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.zach.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/registerServlet.do</url-pattern>
</servlet-mapping>
</web-app>
- 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>
- info.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>xxx网站温馨提示:</h1>
${message}
</body>
</html>
- User.java
package com.zach.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;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
}
- RegisterServlet
package com.zach.servlet;
import com.zach.pojo.User;
import com.zach.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 doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
@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);
//启动线程,线程启动之后就会执行run方法来发送邮件
send.start();//如果用send.run();则并不是开启多线程,会加载完才跳转,有点慢。
//注册用户
req.setAttribute("message",
"您已注册成功,我们已经发送了一封带有注册信息的电子邮件,请注意查收!如果网络不稳定,请等待片刻再查收。");
req.getRequestDispatcher("info.jsp").forward(req,resp);
}
}
- Sendmail
package com.zach.utils;
import com.sun.mail.util.MailSSLSocketFactory;
import com.zach.pojo.User;
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 = "525266345@qq.com";
//邮箱的用户名
private String userName = "525266345@qq.com";
//邮箱的密码
private String password = "Authorization code";
//发送邮件的服务器地址
private String host = "smtp.qq.com";
//“Service层调用Dao层,Servlet层调用Service层”时,使用的方式。
private User user;
public Sendmail(User user) {
this.user = user;
}
@Override
public void run() {
try {
Properties properties = new Properties();
properties.setProperty("mail.host", host);//设置QQ邮件服务器
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);
//使用javaMail发送邮件的5个步骤:
//1. 创建定义整个应用程序所需的环境信息的Session对象
Session session = Session.getDefaultInstance(properties, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名、授权码
return new PasswordAuthentication(from, password);
}
});
//--开启debug模式,这样就可以查看到程序发送email的运行状态
session.setDebug(true);
//2. 通过session得到transport对象
Transport ts = session.getTransport();
//3. 使用邮箱的用户名和授权码连上邮件服务器
ts.connect(host, from, password);
//4. 创建邮件
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));//发件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));//收件人
message.setSubject("用户注册邮件");//标题
//--邮件的文本内容
String info = "<h1 style='color: red'>恭喜您注册成功,您的用户名:</h1>"+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) {
e.printStackTrace();
}
}
}
- 在SpringBoot中实现(拓展)
- pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<scope>test</scope>
</dependency>
- 自动生成的DemoApplication
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- 在application.properties中配置
spring.mail.username=525266345@qq.com
spring.mail.password=Authorization code
spring.mail.host=smtp.qq.com
spring.mail.properties.mail.smtp.ssl.enable=true
- 在test文件夹下测试DemoApplicationTests
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import javax.mail.internet.MimeMessage;
import java.io.File;
@SpringBootTest
class DemoApplicationTests {
@Autowired
JavaMailSenderImpl mailSender;
//这里mailSender有红色下划线:可能要在application.properties中进行对应配置。
@Test
void contextLoads() {
//发送邮件
//收件人
//内容
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("西开Java");
message.setText("Hello...");
message.setFrom("525266345@qq.com");
message.setTo("525266345@qq.com");
mailSender.send(message);
}
@Test
public void test2() throws Exception {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setSubject("西开Java");
helper.setText("<h1>Hello...<h1>",true);
//附件
helper.addAttachment("img/1.png",new File("src/main/resources/img/1.png"));
helper.addAttachment("img/2.png",new File("src/main/resources/img/2.png"));
helper.addAttachment("img/3.png",new File("src/main/resources/img/3.png"));
helper.setFrom("525266345@qq.com");
helper.setTo("525266345@qq.com");
mailSender.send(mimeMessage);
}
}
- 以上皆测试成功。
- JavaWeb到此结束。