Day12 学习JavaWeb基础

Day12 学习JavaWeb基础

  1. 使用Tomcat服务器学习javaweb,本质是学习Jsp和Servlet
  2. 最好使用Maven,进行jar包的管理,不需要每次导入jar包
  3. pom.xml 是maven 项目的核心配置文件 , 用来导入jar 包
<!-- maven创建的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">
</web-app>

个人理解
在这里插入图片描述

第一个使用Maven创建的JavaWeb项目

  1. 下载好Tomcat和Maven并在IDEA进行配置
  2. 使用IDEA新建一个Maven工程的项目(可以选模板,也可以不选):
  3. maven项目需要指定的项目结构:
    在这里插入图片描述
  4. 在pom.xml文件中导入需要的jar包
<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
    </dependency>
</dependencies>
  1. 编写程序
// 编写servlet 需要实现Servlet接口, HttpServlet已经实现了Servlet 接口并进行扩展 所以只需要继承重写doGet,doPost方法就行了
public class helloservlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().print("Hello javaweb");  // 在网页上显示Hello javaweb
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  1. 在web.xml中配置路由,将Url地址映射到servlet程序
<servlet>
  <servlet-name>hello</servlet-name>
  <servlet-class>com.xxx.helloservlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>hello</servlet-name>
  <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. 给项目配置tomcat的虚拟目录,端口号
    如果 Idea配置 Tomcat Deployment添加时没有Artifact 参考

https://blog.csdn.net/tj867182298/article/details/83308483

在这里插入图片描述
在这里插入图片描述

  1. 运行项目进行测试

个人理解
在这里插入图片描述

ServletContext对象

  1. 该对象的全局对象,可以跨servlet进行传输
public class setServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        servletContext.setAttribute("name","李斯");    // 设置值
        System.out.println("设置好了。。");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
public class readServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();  // 该servletContext对象与上面的是同一个对象
        String name = (String) servletContext.getAttribute("name");  // 读取值
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf8");    // 设置编码 防止浏览器解析中文乱码
        resp.getWriter().print("name: "+ name);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!-- 将自己编写的servlet进行注册,配置路由 -->
<servlet>
  <servlet-name>read</servlet-name>
  <servlet-class>com.xxx.readServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>read</servlet-name>
  <url-pattern>/read</url-pattern>
</servlet-mapping>
<servlet>
  <servlet-name>set</servlet-name>
  <servlet-class>com.xxx.setServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>set</servlet-name>
  <url-pattern>/set</url-pattern>
</servlet-mapping>
  1. 可以利用ServletContext对象进行资源的读取
// web 项目会被打包成target文件夹   其中标红框的表示ServletContext对象的当前目录    
InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(resourceAsStream);
String name = prop.getProperty("name");

在这里插入图片描述

HttpServletResponse对象

  1. response对象用来设置响应头和响应消息
resp.setContentType("text/html");      // 设置响应的类型   resp.setContentType("image/png"); 显示图片
resp.setCharacterEncoding("utf8");     // 设置响应的字符编码
resp.setHeader("refresh","3");         // 每隔3s刷新一下页面
  1. 文件下载的代码
InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/123.png");
ServletOutputStream outputStream = resp.getOutputStream();
// 向浏览器传输文件 需要设置这个响应头 Content-Disposition:attachment; 表示是附件
// 还需要指定文件名 filename 但是如果文件名是中文 可能会出现乱码 URLEncoder.encode("分析.png","utf-8")
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("分析.png","utf-8"));
int len;
byte[] bytes = new byte[1024];
// 进行读写操作实现文件的传输
while ((len=resourceAsStream.read(bytes))!=-1){
    outputStream.write(bytes,0,len);
}
  1. 显示数字验证码图片
public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	// 设置浏览器 2s 刷新一次
        resp.setHeader("refresh","2");
        // 告诉浏览器传输的是图片
        resp.setContentType("image/png");
        // 告诉浏览器不缓存
        resp.setHeader("expire","-1");
        // 在内存中创建图片
        BufferedImage bufferedImage = new BufferedImage(150, 40, BufferedImage.TYPE_INT_RGB);
        // 创建画笔
        Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
        // 画背景颜色
        graphics.setColor(Color.white);
        graphics.fillRect(0,0,150,40);
        // 在图片中写数字
        graphics.setColor(Color.green);
        graphics.setFont(new Font("宋体",Font.BOLD,30));
        graphics.drawString(mkNum(),0,30);
        // 给浏览器传输图片
        ImageIO.write(bufferedImage,"png",resp.getOutputStream());
    }
    // 产生8位的随机数
    private String mkNum(){
        Random random = new Random();
        String num = random.nextInt(99999999)+"";
        // 不足8位 填充0
        for(int i=0;i<8-num.length();i++){
            num += '0';
        }
        return num;
    }
}
  1. 重定向 sendRedirect("/hello")
resp.sendRedirect("/hello");
// 等价于
resp.setHeader("Location","/hello");
resp.setStatus(302);

HttpServletRequest对象

  1. 获取请求的参数 http://www.baidu.com?username=xxx&pwd=123456
// 获取单个参数
String name = req.getParameter("username");
String pwd= req.getParameter("pwd");
// 获取参数数组
String[] hobbys = req.getParameterValues("hobbys")
  1. 请求转发
req.getRequestDispatcher("/success.jsp").forward(req,resp);
  1. 转发和重定向的区别
    转发不会改变Url地址,转发的时候不需要 项目的虚拟目录 是同一个请求 可以共享req , resp
    重定向会改变Url地址,重定向是发起另一个请求,需要虚拟目录,不是同一个请求

Cookie

  1. 保存在客户端浏览器上,每次请求携带cookie
  2. cookie默认浏览器关闭失效,可以设置失效时间
  3. cookie由response对象返回,由request对象获取
  4. cookie只能保存String类型,一个cookie是一个键值对,cookie大小有限4kb,一个网站最多存20个,一个浏览器最多存300个
  5. 给客户端设置cookie
// 设置cookie
Cookie cookie = new Cookie("isuser","yes");
cookie.setMaxAge(60);  // 设置过期时间 60秒   默认浏览器关闭过期
resp.addCookie(cookie);  // 通过响应给客户端设置cookie

// 读取浏览器传送的cookie
Cookie[] cookies = req.getCookies();    // 得到的是一个cookie对象的数组
for (Cookie cookie : cookies) {
	// cookie.getName() 获取键   cookie.getValue() 获取值
    if("isuser".equals(cookie.getName())&&"yes".equals(cookie.getValue())){
        resp.getWriter().write("欢迎再次浏览");
    }

Session

  1. session默认打开浏览器连接服务器就存在,而且不同的浏览器获得的sessionid不一样,在request对象中获得的session对象也不同
  2. session保存在服务端,但是会返回sessionid一般保存在cookie中Jsessionid,服务端根据sessionid进行创建对应的session对象,
  3. session由request对象获得,可以设置内容,
  4. session还可以保存对象,session也可以设置过期时间,删除键,注销session
  5. session保存的内容大小,数目理论上没有限制
  6. session的设置值 取值
// 设置值
HttpSession session = req.getSession();     // 每个sessionid 对应一个session对象
session.setAttribute("name","小潇洒");     // session还可以保存对象  session.setAttribute("time", new Date()); 
System.out.println("set ok");

// 取值
HttpSession session = req.getSession();
String name = (String) session.getAttribute("name");
System.out.println("name: "+name);

// 移除该session的键以及对应的值
session.removeAttribute("key");
// 手动注销该session
session.invalidate();

还可以在web.xml中配置session的过期时间

<session-config>
	<!-- 过期时间以分钟为单位 -->
  <session-timeout>1</session-timeout>
</session-config>

JSP

  1. 需要导入的jar包:servlet依赖,jsp依赖,jstl表达式依赖,standard标签库依赖
  2. 浏览器第一次访问JSP文件时,将其转化为xxx_jsp.java文件,所以JSP本质还是一个Servlet,继承了HttpJspBase
  3. 基础语法: <%-- XXX --%>,<% XXX %>,<%= XXX %>,<%! XXX %>
<%-- 注释 --%>

<%=  变量或者表达式 %>    <%--  用来展示输出的值  --%>
<%= 123456 %>

<%
	java代码
%>

<%
    for (int i = 0; i < 5; i++) {
        out.write("<h3>i:"+i+"</h3>");
    }
%>
<%-- =============================================================== --%>
<%--  还可以分开写,在xxx_jsp.java文件的servlet中会进行拼接 --%>
<%
    for (int i = 0; i < 5; i++) {
%>
    <h1>hesad<%= i %></h1>
<%
    }
%>

<%-- jsp声明,可以定义全局变量,静态代码块,方法, 在xxx_jsp.java代码的类中,service方法外 --%>
<%!  
		static{
		...
		}
		private int num =0;
		public void show(){...}
  %>
  1. JSP 指令
    <%@ page %>
<%-- 导包 --%>
<%@ page import="" %> 
<%-- 设置错误页面 --%>
<%@ page errorPage="" %>

还可以在xml中定制错误页面

<error-page>
  <error-code>404</error-code>
  <location>/errors/404error.jsp</location>
</error-page>

<% @include file=" 导入其他页面,会进行页面的整合,本质都会将代码写到service方法中,不同文件定义相同变量有报错风险 "%>

<% @include file=“commom/login.jsp”%>
<jsp:include page="/commom/login.jsp"/> 不进行代码整合,直接导入页面,不同页面不影响
在这里插入图片描述
<%@ taglib prefix="" %>

  1. JSP 页面存在9个内置对象,可以直接使用,加粗的4个对象用来存东西,但是他们的作用域不同,可以使用el表达式获取
    1. PageContext
    2. Request
    3. Response
    4. Session
    5. config (ServletConfig)
    6. page
    7. Application (ServletContext)
    8. out
    9. exception
<%
// 在4个不同的作用域中存值  
        pageContext.setAttribute("name1","11111");      // 当前页面有效
        request.setAttribute("name2","22222");			// 同一个request请求中有效
        session.setAttribute("name3","33333");			// 一次会话中有效
        application.setAttribute("name4","44444");		// 服务器启动中有效
%>
<%-- 使用el表达式读取值 默认从最小的域中开始读取  --%>
<h2>name1:${name1}</h2>
<h2>name2:${name2}</h2>
<h2>name3:${name3}</h2>
<h2>name4:${name4}</h2>
<h2>name5:${name5}</h2>

<%-- 可以指定域中获取值 --%>
<h2>name1:${pageScope.name1}</h2>
<h2>name2:${requestScope.name2}</h2>
<h2>name3:${sessionScope.name3}</h2>
<h2>name4:${applicationScope.name4}</h2>

Jsp标签,JSTL标签,EL表达式

EL表达式:${} 能从四个作用域中取值,默认不指定,变量存在page当前页面的作用域

  1. 获取数据
  2. 执行运算
  3. 获取web开发 的常用对象
${param.xxx}  等价于 <%= request.getparameter("xxx") %>

jstl 标签 需要引入
<%@taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>

// 常用方法
<c:if test="布尔判断,一般使用el表达式 ${param.xxx == "admin"}" var="isFlag   test中的布尔结果值">
	<c:out value="输出的值" />
</c:if>
// 设置值
<c:set var="键" value="值" scope="作用域"/>
// 
<c:choose>
    <c:when test="">
   		     
    </c:when>
    <c:when test="">

    </c:when>
</c:choose>
//
<c:forEach var="item1" items="需要遍历的对象" >
    ${item1}
</c:forEach>

过滤器

  1. 需要实现filter接口,重点重写dofilter方法,
  2. 需要在web.xml中配置,filter
  3. 过滤器一般作用是:乱码问题,身份验证问题
    乱码过滤器:
public class filterServlet implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("filter 启动了");
    }
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        // 通过过滤,
        filterChain.doFilter(servletRequest,servletResponse);
    }
    public void destroy() {
        System.out.println("filter 销毁了");
    }
}
public class showServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("今天天气真好。");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!-- 对同一个servlet有两个请求,直接/show访问会乱码,通过/char/show访问会先过过滤器,不会乱码 -->
 <servlet>
    <servlet-name>show</servlet-name>
    <servlet-class>com.xyy.showServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>show</servlet-name>
    <url-pattern>/show</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>show</servlet-name>
    <url-pattern>/char/show</url-pattern>
  </servlet-mapping>
<!-- 过滤器注册 -->
  <filter>
    <filter-name>charset</filter-name>
    <filter-class>com.xyy.filterServlet</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>charset</filter-name>
    <url-pattern>/char/*</url-pattern>
  </filter-mapping>

身份验证过滤器:

public class loginUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        if("xxx".equals(name)){
            HttpSession session = req.getSession();
            session.setAttribute("isUser","true");
            req.setAttribute("name",name);
            req.getRequestDispatcher("/identity/success.jsp").forward(req,resp);
        }else {
            resp.sendRedirect("/hh/loginUser.jsp");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
public class identityFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        // 获取session 进行身份的识别
        HttpSession session = req.getSession();
        String isUser = (String)session.getAttribute("isUser");
        if(isUser==null || "true".equals(isUser) ){
        	// 没有登录返回登录页面
            resp.sendRedirect("/hh/loginUser.jsp");
        }
        // 否则通过过滤
        filterChain.doFilter(req,resp);
    }
    public void destroy() {}
}

监听器

  1. 需要实现listen接口,不同的事件监听需要实现不同的接口
  2. 需要在web.xml中配置,listen
  3. 常见作用:统计在线人数
    统计在线人数
public class sessionListen implements HttpSessionListener {
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
        Integer count = (Integer)servletContext.getAttribute("count");
        System.out.println(httpSessionEvent.getSession().getId());
        if(count==null){
            servletContext.setAttribute("count",1);
        }else {
            servletContext.setAttribute("count",count+1);
        }
    }
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
        Integer count = (Integer)servletContext.getAttribute("count");
        if(count==null){
            servletContext.setAttribute("count",0);
        }else {
            servletContext.setAttribute("count",count-1);
        }
    }
}
<listener>
  <listener-class>com.xyy.sessionListen</listener-class>
</listener>

MVC三层架构

  1. M:Model 模型(做业务,向数据库进行连接,做增删改查的具体业务)
  2. V:View 视图(页面,展示数据)
  3. C:Controller 控制器(对浏览器的请求业务进行调度,先访问Model获取对应的数据,在把数据交给View视图展示)

简单使用ajax,json

resp.setContentType("application/json;charset=utf-8");  // 返回json字符串需要设置的类型  application/json
resp.getWriter().write("{\"asd\":\"速度埃塞\"}");   // 自己拼接的json字符串要有双引号  {"asd":"速度埃塞"}
$('#name').on("blur",function () {
         $.ajax({
             type:"GET",			// 访问的类型
             url:"/hh/json",		// 访问的地址
             data:{method:"123"},  // 传递的参数
             dataType:"json",      // 设置返回的数据类型
             success:function (data) {  // 访问成功,data为返回的参数 为json对象
                 alert(data.asd);
             },
             error:function (date) {
                 alert(false)
             }
        })
})

文件上传

  1. 需要设置文件上传需要的表单类型 method=“post” , enctype=“multipart/form-data” , type="file"
<form action="" method="post" enctype="multipart/form-data">
    上传文件:<input type="file" name="file1">
    <input type="submit">
</form>
  1. 使用现有的工具类,否则通过req.getInputStream(),进行解析读取,比较麻烦
  2. 使用工具类需要的jar包:commons-fileUpload.jar , commons-io.jar
    在这里插入图片描述
    在这里插入图片描述
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>
  1. fileupload的核心类:DiskFileItemFactory、ServletFileUpload、FileItem
  2. 步骤固定,但是可以在不同的类中添加不同的属性,
    使用fileUpload固定步骤:
    1. 创建工厂类(可以设置临时文件的位置,内存缓冲区大小(超过放在临时文件中)。。):DiskFileItemFactory factory=new DiskFileItemFactory();
    2. 创建解析器(设置上传单个文件的大小,总大小,文件上传监听。。):ServletFileUpload upload=new ServletFileUpload(factory);
    3. 使用解析器解析request对象:List list=upload.parseRequest(request);
  3. 得到List为每个input的传送的数据封装为一个FileItem对象,需要进行判断是否是文件,还是普通input字段
    FileItem类有如下方法:
    1. String getFieldName():获取表单项的name的属性值。
    2. String getName():获取文件字段的文件名。如果是普通字段,则返回null
    3. String getString():获取字段的内容。如果是普通字段,则是它的value值;如果是文件字段,则是文件内容。
    4. String getContentType():获取上传的文件类型,例如text/plain、image。如果是普通字段,则返回null。
    5. long getSize():获取字段内容的大小,单位是字节。
    6. boolean isFormField():判断是否是普通表单字段,若是,返回true,否则返回false。
    7. InputStream getInputStream():获得文件内容的输入流。如果是普通字段,则返回value值的输入流。
// 创建磁盘文件项目工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 根据工厂创建文件上传解析器
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        // 使用解析器 , 解析request对象
        try {
            // 每一个 fileItem 都对应一个input
            List<FileItem> fileItems = fileUpload.parseRequest(req);
            for(FileItem fileItem:fileItems){
                // 判断是否是文件类型的input
                if(fileItem.isFormField()){  // 普通字段直接输出
                    String fieldName = fileItem.getFieldName();
                    String value = fileItem.getString();
                    System.out.println("fileName: "+ fieldName+ "value: "+value);
                }else { // 是文件类型
                    String name = fileItem.getName(); // 获得文件名称
                    System.out.println(name);
                    InputStream is = fileItem.getInputStream(); // 获得文件输入流
                    File file = new File("/upload");
                    if(!file.exists()){
                        file.mkdirs();
                    }
                    FileOutputStream fileOutputStream = new FileOutputStream(new File("/upload",  UUID.randomUUID().toString()+name));
                    byte[] bytes = new byte[1024];
                    int len;
                    while ((len=is.read(bytes))!=-1){
                        fileOutputStream.write(bytes,0,len);
                    }
                    System.out.println("文件上传结束。。。");
                    fileOutputStream.close();
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }

邮件发送

在这里插入图片描述

  1. 简单文本邮件发送
Properties properties = new Properties();
properties.setProperty("mail.host","smtp.qq.com");
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);


//创建一个session对象
Session session = Session.getDefaultInstance(properties, new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("xxxx@qq.com","xxxx");
    }
});

//开启debug模式, 可以观测邮件发送的状态
session.setDebug(true);

//获取连接对象
Transport transport = session.getTransport();
//连接服务器
transport.connect("smtp.qq.com","xxxx@qq.com","xxxx");

//创建邮件对象
MimeMessage mimeMessage = new MimeMessage(session);
//邮件发送人
mimeMessage.setFrom(new InternetAddress("xxxx@qq.com"));
//邮件接收人
mimeMessage.setRecipient(Message.RecipientType.TO,new InternetAddress("xxxx@foxmail.com"));
//邮件标题
mimeMessage.setSubject("Hello Mail");
//邮件内容
mimeMessage.setContent("邮件","text/html;charset=UTF-8");


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

//关闭连接
transport.close();
  1. 带图片和附件的邮件
public class emailAttachmentTest {
    public static void main(String[] args) throws GeneralSecurityException, MessagingException, UnsupportedEncodingException {
        Properties properties = new Properties();
        properties.setProperty("mail.host","smtp.qq.com");
        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);
        //创建一个session对象
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("xxxx@qq.com","xxxx");
            }
        });
        //开启debug模式
        session.setDebug(true);

        //获取连接对象
        Transport transport = session.getTransport();
        //连接服务器
        transport.connect("smtp.qq.com","xxxx@qq.com","xxxx");
        //4、创建邮件,传入session对象
        MimeMessage mimeMessage = complexEmail(session);
        //发送邮件
        transport.sendMessage(mimeMessage,mimeMessage.getAllRecipients());
        //关闭连接
        transport.close();

    }

    private static MimeMessage complexEmail(Session session) throws MessagingException, UnsupportedEncodingException {

        //消息的固定信息
        MimeMessage mimeMessage = new MimeMessage(session);
        //发件人
        mimeMessage.setFrom(new InternetAddress("xxxx@qq.com"));
        //收件人
        mimeMessage.setRecipient(Message.RecipientType.TO,new InternetAddress("xxxx@foxmail.com"));
        //邮件标题
        mimeMessage.setSubject("带图片和附件的邮件");

        //邮件内容
        //准备图片数据
        MimeBodyPart image = new MimeBodyPart();
        DataHandler handler = new DataHandler(new FileDataSource("C:\\Users\\Administrator\\Desktop\\commio.png"));
        image.setDataHandler(handler);
        image.setFileName(MimeUtility.encodeText("a.png"));   // 防止变为bin文件
        image.setContentID("test.png"); //设置图片id

        //准备文本
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("这是一段文本<img src='cid:test.png'>","text/html;charset=utf-8"); // html 代码  引用图片id

        //附件
//        MimeBodyPart appendix = new MimeBodyPart();
//        appendix.setDataHandler(new DataHandler(new FileDataSource("F:\\Office 2013-2019 C2R Install v6.3\\readme_en.txt")));
//        appendix.setFileName("test.txt");

        //拼装邮件正文
        MimeMultipart mimeMultipart = new MimeMultipart();
        mimeMultipart.addBodyPart(image);
        mimeMultipart.addBodyPart(text);
//        mimeMultipart.setSubType("related");//文本和图片内嵌成功
        mimeMultipart.setSubType("mixed");

        //将拼装好的正文内容设置为主体
//        MimeBodyPart contentText = new MimeBodyPart();
//        contentText.setContent(mimeMultipart);
        //拼接附件
//        MimeMultipart allFile = new MimeMultipart();
//        allFile.addBodyPart(appendix);//附件
//        allFile.addBodyPart(contentText);//正文
//        allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed
        //放到Message消息中
//        mimeMessage.setContent(allFile);
        mimeMessage.setContent(mimeMultipart);
        mimeMessage.saveChanges();//保存修改
        return mimeMessage;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值