JavaWeb笔记-程序员宅基地

技术标签: JavaEE开发  java  前端  服务器  

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("[email protected]","qpszlppmatiweiaa");
            }
        });
        //开启session的debug模式,这样可以查看到程序发送Email的运行状态
        session.setDebug(true);
        //2.通过session得到transport对象
        Transport ts=session.getTransport();

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

        //4.创建邮件:写文件
        //注意需要传递session
        MimeMessage message=new MimeMessage(session);
        //指明邮件的发件人
        message.setFrom(new InternetAddress("[email protected]"));
        //指明邮件的收件人
        message.setRecipient(Message.RecipientType.TO,new InternetAddress("[email protected]"));
        //邮件标题
        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("[email protected]","qpszlppmatiweiaa");
            }
        });

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


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

        //3.连接服务器,需要抛出异常;
        tp.connect("smtp.qq.com","[email protected]","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("[email protected]"));
        //邮件接收人,可以同时发送给很多人,我们这里只发给自己;
        mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
        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>
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_50195602/article/details/125006637

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文