Web扩展

Web扩展

1.文件上传

需要的jar包:commons-fileuploa和commons-io

可以使用

表单来实现,必须在里面加上enctype=“multipart/form-data” 这段代码;

<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
    上传用户:<input type="text" name="username"/> <br/>
    <input type="file" name="file1">    <br/>
    <input type="file" name="file2">    <br/>
    <input type="submit" value="提交"> | <input type="reset" value="重置">
</form>

 (1) ServletFileUpload类

ServletFileUpload类具有处理上传的文件数据,并将表单中每个输入项封装成一个FIleItem对象中,使用其中的parseRequest(HttpServletRequest)方法通过表单中每一个HTML标签提交的数据封装成一个FIleItem对象.然后以LIst列表的形式返回。

常用方法介绍:

boolean isFormField();
//isFormField方法用于判断FileItem类对象封装的数据是一个普通文本还是文件,如果是普通文本则返回true,否则返回false。

String getFieldName();
//用于返回表单name的属性的值
String getString();
//用于将FileItem对象中保存的数据流内容以一个字符串返回

String getName();
//用于获得文件上传字段中的文件名

InputStream getInputStream();
//以流的形式返回上传的数据内容

void delete();
//delete方法用来清空FileItem类对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时文件

需要导入的jar包:commons-fileupload

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

具体实现:

package com.vxzx.file;

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 FileServletf extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //判断上传文件是否为普通表单:
        if (!ServletFileUpload.isMultipartContent(req)){
            return;
        }//通过这个判断,证明这个文件时带文件的

        //创建上传文件的保存路径:
        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File file = new File(uploadPath);
        //如果uploadPath里面没有upload文件夹,则会新建一个:
        if (!file.exists()){
            file.mkdirs();
        }

        //临时文件:如果文件超了预期大小,就把他放到一个临时文件中:
        String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
        File file1 = new File("tmpPath");
        //如果tmpPath里面没有tmp文件夹,则会新建一个:
        if (!file1.exists()){
            file1.mkdirs();
        }

        //1、创建DiskFileItemFactory对象,处理文件上传路径或大小限制。
        DiskFileItemFactory factory = getDiskFileItemFactory(file);
        //2、获取ServletFileUpload
        ServletFileUpload upload = getServletFileUpload(factory);
        //3、处理文件上传:
        String msg = null;
        try {
            msg = uploadParseRequest(upload,req,uploadPath);
            //Servlet请求发送信息:
            req.setAttribute("msg",msg);
            req.getRequestDispatcher("/file/info.jsp").forward(req,resp);
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }
    //1、创建DiskFileItemFactory对象,处理文件上传路径或大小限制。
    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //通过这个工厂设置一个缓冲区,当上传文件大于这个缓冲区时,将他放到临时区域中。
        factory.setSizeThreshold(1024 * 1024); //缓冲区大小为1M
        factory.setRepository(file);          //临时保存的目录
        return factory;
    }
    //2、获取ServletFileUpload
    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        ServletFileUpload upload = new ServletFileUpload(factory);
        //监听文件上传进度:
        upload.setProgressListener(new ProgressListener() {
            @Override
            //pBytesRead:已经读取到的文件大小
            //pContentLength:文件大小
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
            }
        });
        //处理乱码问题:
        upload.setHeaderEncoding("UTF-8");
        //设置单个文件的最大值:
        upload.setFileSizeMax(1024 * 1024);
        //设置总文件的最大值:
        upload.setSizeMax(1024 * 1024 *10);
        return upload;
    }

    //3、处理文件上传:
    public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest req, String uploadPath)
        throws FileUploadException, IOException {
        String msg = "";
        //把前端请求解析,封装成一个FileItem对象:从获取ServletFileUpload对象中获取。
        List<FileItem> fileItems = upload.parseRequest(req);
        //遍历前端拿到的数据:
        for (FileItem fileItem : fileItems) {
            //判断表单是普通表单还是带文件的表单:
            if (fileItem.isFormField()){
                //普通表单:
                String name = fileItem.getFieldName(); //获取前端控件的name
                String value = fileItem.getString("UTF-8"); //处理乱码
                System.out.println(name + ":" + value);
            }else { //如果为带文件的表单:
                //                    ----1、处理文件----
                //获取文件名字:
                String uploadFileName = fileItem.getName();
                System.out.println("上传的文件名:" + uploadFileName);
                //可能存在文件不合法情况:
                if (uploadFileName.trim().equals("") || uploadFileName == null){
                    continue;
                }
                //获取上传的文件名, **img/***.jpg
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                //获取上传文件的后缀名:
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
                /*
                     * 如果文件后缀名 fileExtName不是我们需要的,直接return;
                     * */

                //可以使用UUID(唯一识别的通用码),保证文件的唯一性;
                //格式:UUID.randomUUID(),随机生成一个唯一识别的通用码;

                //网络传输东西都需要序列化:
                //传输一般都需要序列化:implements Serializable
                String uuidPath = UUID.randomUUID().toString();

                //存储路径: uploadPath
                //文件真实存储的路径: realPath
                String realPath = uploadPath + "/" + uuidPath;
                //给每个文件创建一个对应的文件:
                File realPathFile = new File(realPath);
                if (!realPathFile.exists()){
                    realPathFile.mkdir();
                }
                //                    ----3、文件传输----
                //获得文件上传流:
                InputStream is = fileItem.getInputStream();

                //创建一个文件输出流:
                //realPath 真实文件夹;
                //加上输出文件的名字: + "/" + uuidFileName
                FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
                //创建一个缓冲区:
                byte[] buffer = new byte[1024 * 1024];
                //判断数据是否读取完毕:
                int len = 0;
                //大于0说明还有数据,输出数据:
                while ((len = is.read(buffer)) >0 ){
                    fos.write(buffer,0,len);
                }
                fos.close();
                is.close();

                msg = "文件上传成功!";
                //清除临时文件:
                fileItem.delete();
            }
        }
        return msg;
    }
}

前端页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>File</title>
    </head>
    <body>
        <%--上传文件:  get:上传大小有限制
    post:上传大小无限制
    form必须设置:enctype="multipart/form-data"
    --%>
        <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
            上传用户:<input type="text" name="username"/> <br/>
            <input type="file" name="file1">    <br/>
            <input type="file" name="file2">    <br/>
            <input type="submit" value="提交"> | <input type="reset" value="重置">
        </form>
    </body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h1>${msg}</h1>
    </body>
</html>

配置xml:

<servlet>
    <servlet-name>FileServletf</servlet-name>
    <servlet-class>com.vxzx.file.FileServletf</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>FileServletf</servlet-name>
    <url-pattern>/upload.do</url-pattern>
</servlet-mapping>

2、邮件发送

需要使用到的Jar包:JavaMail API 和 activation API

注意:如果MailSSLSocketFactory爆红,可以下载JavaMail API (compat)兼容jar包

电子邮件:

SMTP服务器地址:一般是smtp.xxx.com;比如:163邮箱的smtp.163.com;qq邮箱的smtp.qq.com。

电子邮箱的获得需要在服务器上进行申请。例如:qq邮箱使用,需要先开通它。

邮件的分类:

  • 简单邮件:没有附件和图片,纯文本文件;
  • 复杂邮件:有附件和图片;

传输协议:

  • SMTP协议

发送邮件: 我们通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。

  • POP3协议

接收邮件:我们通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。

邮件收发原理:

image-20210606115511025

主要有四个核心:只要记住这个四个核心来编写Java邮件处理程序就Ok了。

image-20210606004950198

普通邮件发送的具体实现:

package com.vxzx;

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 SendEmail {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException {
        //固定写法:
        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发送邮件需要五个步骤:

        //1、创建定义整个程序所需的环境信息的session对象:QQ特有的授权码:
        Session session = Session.getDefaultInstance(prop, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("573114781@qq.com","mkhevqvhvdavbeji");
            }
        });
        //开启Session的debug模式,可以查看程序发送时的所有信息:
        session.setDebug(true);

        //2、通过session得到transport对象:
        Transport ts = session.getTransport();

        //3、使用邮箱用户名和授权码连上邮件服务器:
        ts.connect("smtp.qq.com","573114781@qq.com","mkhevqvhvdavbeji");

        //4、创建邮件:
        //创建邮件对象:
        MimeMessage message = new MimeMessage(session);
        //指明邮件的发件人;
        message.setFrom(new InternetAddress("573114781@qq.com"));
        //指明邮件的收件人,发件人和收件人一样,即自己给自己发邮件;
        message.setRecipient(Message.RecipientType.TO, new InternetAddress("573114781@qq.com"));
        //邮件标题:
        message.setSubject("这是一个简单的邮件!");
        //邮件的内容:
        message.setContent("你好!这是一个简单邮件发送测试","text/html;charset=utf-8");

        //5、发送邮件:
        ts.sendMessage(message, message.getAllRecipients());
        //关闭连接:
        ts.close();
    }
}

3、复杂的邮件发送

MIME(多用途互联网邮件扩展类型)

MimeBodyPart类:表示一个MIME消息,和MimeMessage类一样都是从Part接口继承过来的。

MimeMultipart类:抽象类Multipart实现子类,用来组合多个MIME消息;一个MimeMultipart对象可以包含多个 代表MIME消息的MimeBodyPart对象。

image-20210606195209178

3.1 发送带有图片的邮件:

//准备图片数据:
MimeBodyPart image = new MimeBodyPart();
//图片需要数据处理。 DataHandler:数据处理
DataHandler dh = new DataHandler(new FileDataSource("图片路径"));
//在Body中放入处理好的图片数据:
image.setDataHandler(dh);
//给图片设置一个ID,后续可以使用:
image.setContentID("自定义图片ID");
//准备正文数据:
MimeBodyPart text = new MimeBodyPart();
text.setContent("这个一封带有图片的邮件<img src='cid:设置的图片ID'>的邮件","text/html;charset=UTF-8");
//描述数据关系:
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");
//设置到消息中,保存修改:
message.setContent(mm);		//把最后编辑好的邮件放到消息中
message.saveChanges();		//保存并修改!

3.2 添加带有附加的邮件:

//添加附件:
MimeBodyPart body3 = new MimeBodyPart();
body1.setDataHandler(new FileDataSource("文件路径"));
//设置附件名字:
body1.setFileName("定义文件的名字");

最后需要将文本、图片、文件一起拼接起来:

//拼接邮件正文内容:
MimeMultipart multipart1 = new MimeMultipart();
multipart1.addBodyPart(body1);
multipart1.setSubType("related");	//文本和图片内嵌成功
//new MimeBodyPart().setContent(multipart);		将拼接好的正文内容设置为主体内容
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(multipart1);
//拼接附件:
MimeMultipart allFile = new MimeMultipart();
allFile.addBodyPart(body3);			//添加附件
allFile.addBodyPart(contentText);	//添加正文
allFile.setSubType("mixed"); 		//正文和附件都存在邮件中,所有类型设置为mixed
//放消息到Message中:
mimeMessage.setcontent(allFile);
mimeMessage.saveChanges();			//保存修改
return mimeMessage;

LOMBOK

4、JavaWeb发送邮件

用户注册功能,但你注册成功时,会收到服务器发送的一条邮件,邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账户的超链接等信息。

实现步骤:

1、新建一个WEB项目;

2、编写User类代码:

package com.vxzx.Servlet;

public class User {
    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 + '\'' +
            '}';
    }
}

2、编写前端注册页面:(两个页面)

<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>
<body>
    <h1>${message}</h1>
</body>

3、编写工具类Sendmail:

package com.vxzx.util;

import com.sun.mail.util.MailSSLSocketFactory;
import com.vxzx.Servlet.User;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

public class Sendmail extends Thread {
    //用户给用户发送邮件的邮箱:
    private String from = "573114781@qq.com";
    //邮箱的用户名:
    private String username = "573114781@qq.com";
    //邮箱的密码:
    private String password = "mkhevqvhvdavbeji";
    //发送邮件的服务器地址:
    private  String host = "smtp.qq.com";

    private User user;
    public Sendmail(User user) {
        this.user = user;
    }

    //重写run方法实现,在run方法中发送邮件给指定的用户:
    @Override
    public void run() {
        Transport ts = null;
        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发送邮件需要五个步骤:
            //1、创建定义整个程序所需的环境信息的session对象:QQ特有的授权码:
            Session session = Session.getDefaultInstance(prop, new Authenticator() {
                @Override
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("573114781@qq.com","mkhevqvhvdavbeji");
                }
            });
            //开启Session的debug模式,可以查看程序发送时的所有信息:
            session.setDebug(true);

            //2、通过session得到transport对象:
            ts = session.getTransport();

            //3、使用邮箱用户名和授权码连上邮件服务器:
            ts.connect(host,username,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 = "恭喜你注册成功," + user.getUsername() + ",你的密码是:" + user.getPassword();
            message.setContent(info,"text/html;charset=UTF-8");
            message.saveChanges();

            //5、发送邮件:
            ts.sendMessage(message, message.getAllRecipients());

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭连接:
            try {
                if (ts != null){
                    ts.close();
                }
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }

    }
}

4、编写Servlet类RegisterServlet类:

package com.vxzx.Servlet;

import com.vxzx.util.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 {
        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();

        //实现注册用户:
        req.setAttribute("message","注册成功,我们已经发了一封带了注册信息的电子邮件,请查收!如网络不稳定,可能过会儿才能收到!!");
        req.getRequestDispatcher("info.jsp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

5、配置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.vxzx.Servlet.RegisterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegisterServlet</servlet-name>
        <url-pattern>/RegisterServlet.do</url-pattern>
    </servlet-mapping>
</web-app>
posted @ 2021-06-09 22:57  VXZX  阅读(156)  评论(0)    收藏  举报