Day12 学习JavaWeb基础
- 使用Tomcat服务器学习javaweb,本质是学习Jsp和Servlet
- 最好使用Maven,进行jar包的管理,不需要每次导入jar包
- 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项目
- 下载好Tomcat和Maven并在IDEA进行配置
- 使用IDEA新建一个Maven工程的项目(可以选模板,也可以不选):
- maven项目需要指定的项目结构:
- 在pom.xml文件中导入需要的jar包
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
- 编写程序
// 编写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);
}
}
- 在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>
- 给项目配置tomcat的虚拟目录,端口号
如果 Idea配置 Tomcat Deployment添加时没有Artifact 参考
https://blog.csdn.net/tj867182298/article/details/83308483
- 运行项目进行测试
个人理解
ServletContext对象
- 该对象的全局对象,可以跨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>
- 可以利用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对象
- response对象用来设置响应头和响应消息
resp.setContentType("text/html"); // 设置响应的类型 resp.setContentType("image/png"); 显示图片
resp.setCharacterEncoding("utf8"); // 设置响应的字符编码
resp.setHeader("refresh","3"); // 每隔3s刷新一下页面
- 文件下载的代码
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);
}
- 显示数字验证码图片
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;
}
}
- 重定向 sendRedirect("/hello")
resp.sendRedirect("/hello");
// 等价于
resp.setHeader("Location","/hello");
resp.setStatus(302);
HttpServletRequest对象
- 获取请求的参数 http://www.baidu.com?username=xxx&pwd=123456
// 获取单个参数
String name = req.getParameter("username");
String pwd= req.getParameter("pwd");
// 获取参数数组
String[] hobbys = req.getParameterValues("hobbys")
- 请求转发
req.getRequestDispatcher("/success.jsp").forward(req,resp);
- 转发和重定向的区别
转发不会改变Url地址,转发的时候不需要 项目的虚拟目录 是同一个请求 可以共享req , resp
重定向会改变Url地址,重定向是发起另一个请求,需要虚拟目录,不是同一个请求
Cookie
- 保存在客户端浏览器上,每次请求携带cookie
- cookie默认浏览器关闭失效,可以设置失效时间
- cookie由response对象返回,由request对象获取
- cookie只能保存String类型,一个cookie是一个键值对,cookie大小有限4kb,一个网站最多存20个,一个浏览器最多存300个
- 给客户端设置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
- session默认打开浏览器连接服务器就存在,而且不同的浏览器获得的sessionid不一样,在request对象中获得的session对象也不同
- session保存在服务端,但是会返回sessionid一般保存在cookie中Jsessionid,服务端根据sessionid进行创建对应的session对象,
- session由request对象获得,可以设置内容,
- session还可以保存对象,session也可以设置过期时间,删除键,注销session
- session保存的内容大小,数目理论上没有限制
- 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
- 需要导入的jar包:servlet依赖,jsp依赖,jstl表达式依赖,standard标签库依赖
- 浏览器第一次访问JSP文件时,将其转化为xxx_jsp.java文件,所以JSP本质还是一个Servlet,继承了HttpJspBase
- 基础语法: <%-- 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(){...}
%>
- 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="" %>
- 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当前页面的作用域
- 获取数据
- 执行运算
- 获取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>
过滤器
- 需要实现filter接口,重点重写dofilter方法,
- 需要在web.xml中配置,filter
- 过滤器一般作用是:乱码问题,身份验证问题
乱码过滤器:
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() {}
}
监听器
- 需要实现listen接口,不同的事件监听需要实现不同的接口
- 需要在web.xml中配置,listen
- 常见作用:统计在线人数
统计在线人数
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三层架构
- M:Model 模型(做业务,向数据库进行连接,做增删改查的具体业务)
- V:View 视图(页面,展示数据)
- 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)
}
})
})
文件上传
- 需要设置文件上传需要的表单类型 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>
- 使用现有的工具类,否则通过req.getInputStream(),进行解析读取,比较麻烦
- 使用工具类需要的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>
- fileupload的核心类:DiskFileItemFactory、ServletFileUpload、FileItem
- 步骤固定,但是可以在不同的类中添加不同的属性,
使用fileUpload固定步骤:
1. 创建工厂类(可以设置临时文件的位置,内存缓冲区大小(超过放在临时文件中)。。):DiskFileItemFactory factory=new DiskFileItemFactory();
2. 创建解析器(设置上传单个文件的大小,总大小,文件上传监听。。):ServletFileUpload upload=new ServletFileUpload(factory);
3. 使用解析器解析request对象:List list=upload.parseRequest(request); - 得到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();
}
邮件发送
- 简单文本邮件发送
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();
- 带图片和附件的邮件
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;
}
}