JavaWeb

笔记备忘

1、Web基本概念

web开发:

  • web:网页

  • 静态web

    • html,css
    • 提供给所有人看内容不会变化
  • 动态web

    • 淘宝等几乎所有网站
    • 内容会根据不同的人发生变化
    • 技术栈:Servlet/JSP,ASP,PHP

在java中,动态web资源开发中的技术统称为JavaWeb;

2、Servlet

2.1、Servlet简介

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。

2.2、Servlet原理

Servlet是由Web服务器调用,web服务器收到浏览器的请求之后,会:

在这里插入图片描述

2.3、Mapping问题
  1. 一个servlet可以指定一个映射路径

    <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  2. 一个servlet可以指定多个映射路径

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello1</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    
  3. 一个servlet可以指定通用映射路径

    <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
    

    *----->在正则表达式中表示通配符

  4. 指定一些后缀或前缀

    <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    

    这里的.do是后缀,后缀可以设置成任意值,但是*前不能加反斜杠

  5. 默认请求路径(不建议使用)

    <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
  6. 优先级问题

    指定了固有的路径优先级最高如果找不到会走默认的处理请求。

2.4、ServletContext

web容器启动时,它会为每个web程序创建一个ServletContext对象,它代表了当前的web应用;

应用:

1、共享数据

在此servlet中存放的数据,可以在另一个servlet中得到

2、获取初始化参数

getInitParam

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String jdbcurl = context.getInitParameter("jdbcurl");
        resp.getWriter().print(jdbcurl);

    }
3、请求转发

在这里插入图片描述

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        context.getRequestDispatcher("/getp").forward(req,resp);
    }
4、读取资源文件

Properties

  • 在java目录下新建properties
  • 在resources目录下新建properties

发现:都被打包到同一个路径下:classes,我们称此路径为类路径

思路:需要一个文件流

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        //读取资源文件
        InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
        Properties prop = new Properties();
        prop.load(is);
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        resp.getWriter().println(username);
        resp.getWriter().println(password);

    }
2.5、HttpServletResponse

web服务器收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletResponse。

  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要客户端的一些信息,找HttpServletResponse
常见应用
1、向浏览器输出消息
2、下载文件
  1. 获取下载文件的路径
  2. 下载的文件名
  3. 设置想办法让浏览器能够支持下载我们需要的东西
  4. 获取下载文件的输入流
  5. 创建缓冲区
  6. 获取OutputStream对象
  7. 将FileOutputStream流写入buffer缓冲区
  8. 使用OutputStream将缓冲区的数据输出到客户端

java下载文件

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //  1. 获取下载文件的路径
        //String realPath = this.getServletContext().getRealPath("/1.png");
        String realPath = "D:\\Project\\Java-learn-all\\Response\\src\\main\\resources\\1.png";
        //resp.getWriter().print("下载的文件名为:"+realPath);
        System.out.println("下载的文件名为:"+realPath);
        //  2. 下载的文件名
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        //  3. 设置想办法让浏览器能够支持下载我们需要的东西--下载中文文件名文件时,使用URLEncoder,否则中文文件名可能无法显示
        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. 将ServletOutputStream流写入buffer缓冲区
        while((len=in.read(buffer)) > 0)
        {
            out.write(buffer,0,len);
        }
        out.close();
        in.close();
    }
3、验证码功能
  • 前端实现
  • 后端实现:需要用到java的图片类来生成图片
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //验证码功能
        //浏览器每三秒刷新一次
        resp.setHeader("refresh","0.5");
        //在内存中创建一个图片
        BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
        //设置背景颜色
        Graphics2D g = (Graphics2D) image.getGraphics();
        g.setColor(Color.white);
        g.setFont(new Font(null,Font.BOLD,20));
        g.drawString(makeNum(),0,20);
        //告诉浏览器这个请求的打开方式
        resp.setContentType("image/jpeg");
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");
        //图片写进浏览器
        ImageIO.write(image,"jpg",resp.getOutputStream());
    }
    private String makeNum()
    {
        Random random = new Random();
        String num = random.nextInt(9999999)+"";
        StringBuffer sb = new StringBuffer();
        for(int i = 0;i < 7-num.length();i++)
        {
            sb.append("0");
        }
        num = sb.toString()+num;
        return num;
    }
4、实现重定向

在这里插入图片描述

重定向定义:一个web资源收到客户端请求之后,会通知客户端去访问另一个web资源,这个过程叫做重定向。

void sendRedirect(String var1) throws IOException;
resp.sendRedirect("/此处写路径")

常见场景

  • 用户登录

面试题:请聊聊重定向和转发的区别?

相同点

  • 页面都会跳转

不同点

  • 请求转发时,url不会产生变化 307
  • 重定向时候,url地址栏会发生变化 302
2.6、HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http中请求的信息会被封装到HttpServletRequest中,通过此HttpServletRequest方法,可以获得客户端的所有信息。

1、获取前端参数
getParameter
2、请求转发–注意与ServletContext的请求转发的区别
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("utf-8");
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println("----------------------------------------");
        System.out.println(Arrays.toString(hobbies));
        System.out.println(username+" : "+password);
        System.out.println("----------------------------------------");

        //这里的 / 代表当前web应用---不用加项目路径的/r
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
        
    }

3、Cookie和Session

3.1、会话

会话:用户打开一个浏览器,访问多个web资源,关闭浏览器的过程称为会话。

有状态会话

网站如何证明有人访问过

客户端 服务端

  1. 服务器给客户端一个证明,客户端下次访问时只要带上证明即可;cookie
  2. 服务器已登记,下次同一用户再次访问时,直接匹配。
3.2、保存会话的两种技术

cookie

  • 客户端技术(响应,请求)

session

  • 服务器技术,利用此技术,保存会话信息,把信息和数据放在Session中。

网站登陆过后,下次再访问自动登录。

3.3、Cookie

1.从请求中得到cookie信息

2.服务器响应客户端的cookie

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
		resp.setHeader("content-type","text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();

        //从请求中获取cookie
        Cookie[] cookies = req.getCookies();
        if(cookies != null)
        {
            out.print("上一次访问的时间为:");
            for(int i = 0;i < cookies.length;i++)
            {
                if(cookies[i].getName().equals("lastlogintime"))
                {
                    long time = Long.parseLong(cookies[i].getValue());
                    Date date = new Date(time);
                    out.write(date.toGMTString());
                }
            }
        }
        else{
            out.print("this is the first time you access this web");
        }

        //服务器给客户端响应一个cookie
        Cookie cookie = new Cookie("lastlogintime",System.currentTimeMillis()+"");
        //设置cookie的有效期
        cookie.setMaxAge(48*60*60);
        resp.addCookie(cookie);
    }

cookie:一般存在本地用户目录下的Appdata中

一个网站的Cookie是否存在上限

  • 一个cookie只能存放一个信息
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
  • cookie大小有限制4kb
  • 300个cookie浏览器上限

删除cookie

  • 不设置有效期,关闭浏览器,自动失效;
  • 设置有效时间为0;

编码解码

URLEncoder.encode(string,"utf-8")
URLDecoder.decode(    ,"utf-8")

在这里插入图片描述

3.4、Session(重点)

Session:服务器会给每一个用户(浏览器)创建一个Session对象。可以保存信息。一个浏览器对应一个Session,只要不关闭浏览器。

Session和Cookie的区别

  • Cookie可以把用户的数据写给浏览器,让用户的浏览器保存(可以保存多个)
  • Session把用户的数据写到独占Session中,服务器端保存(保存重要的信息,减小服务器的资源的浪费)
  • Session对象由服务器创建。

使用场景:

  • 保存一个登录的信息
  • 购物车信息
  • 在整个网站中经常会使用的数据,保存在Session中。

过期时间:可以在web.xml中设置,

在这里插入图片描述

在这里插入图片描述

4、JSP

4.1 含义

JSP:Java Server Pages

JSP与HTML的区别:

  • HTML只给用户提供静态数据
  • JSP中可以嵌入JAVA代码,为用户提供动态数据
4.2 JSP原理

执行的过程是什么

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!

JSP最终也会被转化为一个JAVA类

JSP本质上就是一个Servlet

在这里插入图片描述

4.3 JSP的基本语法

支持java所有语法,即可以嵌入java代码。

jsp脚本片段:<% java代码 %>

jsp表达式: <%=变量或者等式%>

jsp声明: <%! %>—会被编译到jsp对应的java文件的类中,其他的就会生成到jspService的方法中。

JSP的注释在客户端不显示,HTML注释会显示。

4.4 JSP指令
<%@page args.... %>
<%@include file="" %> ---->公有信息可以这么导入,比如网页的头部和脚部,相当于吧代码导入

JSP标签

<jsp:include page="">  本质是拼接页面,所以其他文件中的变量与本文件有重名也可以
4.5 9大内置对象
  • PageContext
  • Request
  • Resopnse
  • Session
  • Application(ServletContext)
  • config(ServletConfig)
  • out
  • page
  • exception
4.6、JSP标签,JSTL标签,EL表达式

依赖

<!-- JSTL依赖   -->
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
    <dependency>
      <groupId>javax.servlet.jsp.jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/taglibs/standard -->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>

EL表达式:${ }

  • 取数据
  • 执行运算
  • 获取web前端开发常用对象
JSP标签
<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="小名"/>
    <jsp:param name="age" value="19"/>
</jsp:forward>
JSTL标签

参考:https://www.runoob.com/jsp/jsp-jstl.html

  • 核心标签
  • 格式化标签
  • SQL 标签
  • XML 标签

在tomcat中也需要引入jstl的包

5、JavaBean

实体类

JavaBean有特定的写法:

  • 必须有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法

一般用来和数据库的字段做映射ORM

ORM:对象关系映射

6、MVC三层架构

MVC:Model view Controller 模型、视图、控制器

6.1、早些年

在这里插入图片描述

用户直接访问控制层,控制层可以直接操作数据库

弊端:程序臃肿,不利于维护

6.2、MVC三层

在这里插入图片描述

Model

  • 业务处理:业务逻辑(Service)
  • 数据持久层:CRUD(Dao)

View

  • 展示数据
  • 提供连接发起Servlet请求

Controller

  • 接收用户请求
  • 交给业务层处理相应的代码
  • 控制视图跳转

7、Filter(重点)

Filter:过滤器,过滤网站数据

  • 处理中文乱码
  • 登录验证

在这里插入图片描述

1、导包

2、编写过滤器

public class CharacterEncodingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter启动");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=UTF-8");
            chain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }
}

在web.xml中配置

<filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.future.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>

8、监听器

实现监听器

  • 实现接口
  • web.xml中配置监听器
public class OnlineCountLisener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if(onlineCount == null)
        {
            onlineCount = new Integer(1);
        }else{
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }
       ctx.setAttribute("OnlineCount",onlineCount);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if(onlineCount == null)
        {
            onlineCount = new Integer(0);
        }else{
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }
        ctx.setAttribute("onlineCount",onlineCount);
    }
}

9、JDBC

jdbc:java连接数据库
在这里插入图片描述

jar包支持

  • java.sql
  • javax.sql
  • mysql-conneter-java 连接驱动,必须要导入

maven中导入jar包

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.22</version>
</dependency>

mysql连接,参考https://www.runoob.com/java/java-mysql-connect.html

mysql8.0版本和5.X版本有些许不同

步骤

String url = "jdbc:mysql://localhost:3306/database?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
String username = "root";
String password = "*******";

//1、加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2、连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3、向数据库发送sql对象
Statement statement = connection.createStatement();
//4、编写sql语句
String sql = "select * from student";
//5、执行查询sql
ResultSet rs = statement.executeQuery(sql);
while(rs.next())
{
    System.out.println("rank = "+rs.getObject("rank"));
    System.out.println("class = "+rs.getObject("class"));
    System.out.println("name = "+rs.getObject("name"));
    System.out.println("score = "+rs.getObject("score"));
}

//6、关闭资源,先开后关
rs.close();
statement.close();
connection.close();
事物

要么都成功,要么都失败

ACID原则:保证数据的安全

开启事物
事物提交 commit()
事物回滚 rollback()
关闭事物
//开启事物
connection.setAutoCommit(false);
Junit:单元测试

简单使用

@Test注解只有在方法上有效,只要加了这个注解就可以直接运行。

————----————JavaWeb完结——————————

拓展

10、文件上传

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(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();
        }

        //处理上传的文件,一般用流来获取,但是比较麻烦,这里使用Apache的文件上传组件来实现,common-fileupload

        try {
            //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制
            DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
            //2.获取ServletFileUpload
            ServletFileUpload upload = getServletFileUpload(factory);
            //3.处理上传文件
            String msg = uploadParseRequest(upload,req,uploadPath);

            //servlet请求转发消息
            req.setAttribute("msg",msg);
            req.getRequestDispatcher("info.jsp").forward(req,resp);
        } catch (FileUploadException e) {
            e.printStackTrace();
        }


    }

    public static DiskFileItemFactory getDiskFileItemFactory(File file){
        DiskFileItemFactory factory = new DiskFileItemFactory();

        //通过这个工厂设置一个缓冲区,当上传文件大于这个缓冲区的时候,将它放入临时文件
        factory.setSizeThreshold(1024*1024);//设置缓冲区的大小为1M;
        factory.setRepository(file);

        return factory;
    }

    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
        ServletFileUpload upload = new ServletFileUpload(factory);

        //监听上传的进度
        upload.setProgressListener(new ProgressListener() {
            @Override
            public void update(long l, long l1, int i) {
                System.out.println("总大小:"+l1+" 已上传:"+l);
            }
        });

        //处理乱码
        upload.setHeaderEncoding("UTF-8");
        //设置单个文件的最大值
        upload.setFileSizeMax(1024*1024*10);
        //设置总共能够上传文件的大小
        upload.setSizeMax(1024*1024*100);

        return upload;
    }
    public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest req,String uploadPath) throws FileUploadException,IOException{
        String msg = "";
        //3.处理上传文件
        //前端请求解析。封装成一个FileItem对象,需要从ServletFileUpload获取
        try {
            List<FileItem> fileItems = upload.parseRequest(req);
            for(FileItem fileItem : fileItems){
                //判断上传的文件是普通的表单还是带文件的表单
                if(fileItem.isFormField()){
                    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;
                    }
                    //获得上传文件名
                    String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/")+1);
                    //获取后缀名
                    String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);
                    System.out.println("文件信息[件名: " + fileName + " ---文件类型" + fileExtName + "]");
                    //使用UUID(唯一识别通用码)保证文件名的唯一
                    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 = "文件上传成功";
                    fileItem.delete();
                }
            }

        } catch (Exception e) {
            msg = "文件上传失败";
            e.printStackTrace();
        }

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

利用maven创建的项目,保存的文件在Tomcat目录下的webapps中。普通的web项目,保存的文件在target目录下/out目录下。

11、邮件发送

11.1、普通邮件发送

纯文本邮件发送

mport com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.*;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

public class SendMail {
    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);

        //使用Java发送邮件的5个步骤
        //1.创建定义整个应用程序所需的环境信息的Session对象
        //QQ才有!其他邮箱就不用
        Session session=Session.getDefaultInstance(prop, new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                //发件人邮件用户名、授权码
                return new PasswordAuthentication("xxx@.com","qpszlppmatiweiaa");
            }
        });
        //开启session的debug模式,这样可以查看到程序发送Email的运行状态
        session.setDebug(true);
        //2.通过session得到transport对象
        Transport ts=session.getTransport();

        //3.使用邮箱的用户名和授权码连上邮件服务器
        ts.connect("smtp.qq.com","xxx@foxmail.com","qpszlppmatiweiaa");

        //4.创建邮件:写文件
        //注意需要传递session
        MimeMessage message=new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("mrneo@foxmail.com"));
        //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("mrneo@foxmail.com"));
        //邮件标题
        message.setSubject("发送的标题");
        //邮件的文本内容
        message.setContent("内容","text/html;charset=UTF-8");

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

        //6.关闭连接
        ts.close();
    }
}
11.2、复杂邮件发送

带有附件的邮件发送

public class SendMail3 {
    public static void main(String[] args) throws Exception {
        //包含文件的发送
        //创建一个配置文件保存并读取信息
        Properties properties = new Properties();

        //设置qq邮件服务器
        properties.setProperty("mail.host","smtp.qq.com");
        //设置发送的协议
        properties.setProperty("mail.transport.protocol","smtp");
        //设置用户是否需要验证
        properties.setProperty("mail.smtp.auth", "true");


        //=================================只有QQ存在的一个特性,需要建立一个安全的链接
        // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.smtp.ssl.enable", "true");
        properties.put("mail.smtp.ssl.socketFactory", sf);

        //=================================准备工作完毕

        //1.创建一个session会话对象;
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("mrneo@foxmail.com","qpszlppmatiweiaa");
            }
        });

        //可以通过session开启Dubug模式,查看所有的过程
        session.setDebug(true);


        //2.获取连接对象,通过session对象获得Transport,需要捕获或者抛出异常;
        Transport tp = session.getTransport();

        //3.连接服务器,需要抛出异常;
        tp.connect("smtp.qq.com","mrneo@foxmail.com","qpszlppmatiweiaa");

        //4.连接上之后我们需要发送邮件;
        MimeMessage mimeMessage = imageMail(session);

        //5.发送邮件
        tp.sendMessage(mimeMessage,mimeMessage.getAllRecipients());

        //6.关闭连接
        tp.close();

    }


    public static MimeMessage imageMail(Session session) throws MessagingException {

        //消息的固定信息
        MimeMessage mimeMessage = new MimeMessage(session);

        //邮件发送人
        mimeMessage.setFrom(new InternetAddress("mrneo@foxmail.com"));
        //邮件接收人,可以同时发送给很多人,我们这里只发给自己;
        mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("mrneo@foxmail.com"));
        mimeMessage.setSubject("我也不知道是个什么东西就发给你了"); //邮件主题


        /*
        编写邮件内容
        1.图片
        2.附件
        3.文本
         */

        //图片
        MimeBodyPart body1 = new MimeBodyPart();
        body1.setDataHandler(new DataHandler(new FileDataSource("src/resources/1.png")));
        body1.setContentID("yhbxb.png"); //图片设置ID

        //文本
        MimeBodyPart body2 = new MimeBodyPart();
        body2.setContent("请注意,我不是广告<img src='cid:yhbxb.png'>","text/html;charset=utf-8");

        //附件
        MimeBodyPart body3 = new MimeBodyPart();
        body3.setDataHandler(new DataHandler(new FileDataSource("src/resources/log4j.properties")));
        body3.setFileName("log4j.properties"); //附件设置名字

        MimeBodyPart body4 = new MimeBodyPart();
        body4.setDataHandler(new DataHandler(new FileDataSource("src/resources/1.txt")));
        body4.setFileName(""); //附件设置名字

        //拼装邮件正文内容
        MimeMultipart multipart1 = new MimeMultipart();
        multipart1.addBodyPart(body1);
        multipart1.addBodyPart(body2);
        multipart1.setSubType("related"); //1.文本和图片内嵌成功!

        //new MimeBodyPart().setContent(multipart1); //将拼装好的正文内容设置为主体
        MimeBodyPart contentText =  new MimeBodyPart();
        contentText.setContent(multipart1);

        //拼接附件
        MimeMultipart allFile =new MimeMultipart();
        allFile.addBodyPart(body3); //附件
        allFile.addBodyPart(body4); //附件
        allFile.addBodyPart(contentText);//正文
        allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed;


        //放到Message消息中
        mimeMessage.setContent(allFile);
        mimeMessage.saveChanges();//保存修改

        return mimeMessage;
    }
}

JavaWeb实现邮件发送:https://blog.csdn.net/qq_54897873/article/details/118557180

使用多线程,防止出现耗时,和网站注册人数过多的情况;

12、Maven

maven的常见问题,资源导出失败

	<!--在build中配置resources,防止资源导出失败的问题-->
	<resources>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
    </resources>
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐