JavaWeb-cnblog
javaweb基础
HTML和CSS
<font color="" size="" face=""></font>
<br>
//换行 <hr>
- //无序
-
var 变量名=new Objject();
-
var 变量名={
-
var patt=new RegExp(pattern,modifiers)
-
var patt=/pattern/modifiers/
- HTML,css
- 提供给所有人看的数据始终不会变化
-
淘宝,几乎所有网站
-
提供给所有人的数据都会发生变化,不同时间不同地点看到的数据也不同
-
技术栈:serviet/isp,asp,php
- 微软:国内最早流行的就是ASP
- 在HTML中嵌入了VB脚本,ASP+COM
- //有序
//超链接
//Javaweb相对路径
表
//表格//行//列1.1 | 1.2.. |
tr 行标签 th表头标签 td单元格标签 b加粗 cellspacing单元格间距
colspan=“ #” 表跨#列合并 rowspan="#"表跨#行合并
iframe的作用以及使用
<iframe src="" name="abc">
</if...>在页面开辟一个小区域,单独显示一个页面
<a href=“” target=“abc">//target使用iframe
表单
表单格式化
表单提交细节:
action="":提交服务器地址 method="":get/post设置提交方式
表提交的时候,数据没有发送给服务器的原因:
1.表单项没有name属性
2.单选,复选(下拉列表中option)都需要添加value属性
3.表单不在提交的form标签中
GET请求特点:
1.浏览器地址栏中的地址是:action属性+?+请求参数(name+value&name+valu)
2.不安全,有数据长度的限制
POST特点:
1.浏览器地址栏中的地址是:只有action属性
2.安全,没有数据长度限制
CSS其他标签
div:默认独占一行
span:长度是封装数据的长度
p标签:段落标签
JS
声明函数
函数声明1:function 函数名(可以带参,也可以不带){ 函数体 }
函数声明2:var 函数名=function(形参列表){函数体}
注意:js函数不允许重载,否则原先函数将会被覆盖
object自定义对象
属性名:值,
属性名:值,
函数名:function(){}
};
事件
点击事件(onclick)
静态注册:
Onload="被调用的函数"//浏览器解析完页面之后就会自动触发的事件
动态注册:
<button id="b1">
按钮2</button>
window.onload=function(){
var btnobj =document.getElementById("b1")
btnobj.onclick=function(){函数体}
}
失去焦点事件(onblur)
静态注册
function onblurFun(){
console.log("静态注册失去焦点事件")//console是控制平台对象,向浏览器的控制台打印输出,用于测试。.log用于打印输出
}
动态注册
window.onload=function(){
var passworldobj=doucment.getElementById(" ");
passworldobj.onblur=function(){函数体}
}
内容发生改变事件(onchang)
静态
<select onchange="f1"
>
<option>..</option>
</selec
>
动态
<select id="f1"
>
<option>..</option>
</selec
>
动态:与前面相似
DOM模型
正则表达式
document对象查询优先顺序:id>name>tagname
节点(标签对象)常用属性和方法:
.基本概念
web开发:
静态web
动态web
2.1静态web
*.html, *.htm这些都是网页后缀,如果服务器上存在这些东西,我们可以直接读取
缺点:无法动态更新,无法和数据库交互
2.2动态web
缺点:如果服务器动态web资源出现了错误,我们需要重新编写我们的后台程序
优点:可以动态更新,与数据库交互(数据持久化)
.web服务器
ASP:
php:
优点:开发速度快,功能强大,跨平台,代码简单
局限性:无法承载大访问量的情况
JAP/Serviet:
B/S:浏览和服务器
C/S:客户端和服务器
Jquery
引入jquery库:
jquery核心函数$
$()就是调用$这个函数
1.当传入参数是一个函数时,即【函数】,表示页面加载完成之后自动调用该函数,相当于window.onload=function(){}
2.当传入参数是一个html字符串时,会根据这个字符串创建元素节点对象
eg:$("
<span>div-span1</span>
"+"3.当传入参数为【选择器字符串时】,表示根据id/标签名/类选择权查询标签对象
eg:$("#id属性值");//id选择器 , $(“标签名”);//标签名选择器
$(".class属性值");类选择器
jquery对象:
jquery对象是dom对象数组+jquery提供的一系列功能函数
jquery对象与dom对象区别
jquery对象不能使用dom对象的属性和方法,dom对象也不能使用jquery对象的属性和方法
jquery对象是dom对象互转
dom对象转为jquery对象:$(dom对象)
jquery对象转为dom对象:jquery对象【下标】取出相应的dom对象
基础选择器
$("#id名"),$("*")//所有, $(".class名"), $("div,span")
层级选择器
$("form input")//找出表单所有input元素
$("form >input")//找出表单所有的子集input元素
$("label+input")//匹配所有跟在label后面的input元素
$("form~input")//找到所有与表单同辈的input元素
基本过滤选择器
$("li(标签元素,可变):first/last");//获取匹配的第一个/最后一个元素
$("··:not(select)")//去除所有给定..选择器匹配的元素 :not(select)
$("tr:even")//查找表格中所有偶数行(tr) :even
$("tr:eq(2)")//查找第二行 :eq(index)
$("tr:gt(0)")//查找下标比0大的行,即从第二行查找 :gt(index)
$("tr:lt(2)")//查找下标比2小的行,即从第一行查找 到第二行 :lt(index)
$("h1:header")//查找h1标签 $(":header")
$(":animated")//匹配所有正在执行动画的元素
内容过滤器
$(":contains(text)")//找出某个元素下包含的文本元素
$(":empty")//匹配所有不包含子元素或者文本的空元素
$(":parent")//匹配所有包含子元素或者文本的空元素
$("div:has(p)")//匹配包含p元素的div元素 $(":has(selector)")
属性过滤器
$("div[id]")//查找含有id属性的div属性
$("input[name="dsm"]")//查找name为dsm的input属性
$("input[name^="dsm"]")//查找name以dsm开始的的input属性
$("input[name$="dsm"]")//查找name以dsm结束的的input属性
....
表单选择器
xml
作用:
1用来保存拥有自我描述性数据
2.可以作为项目或者模块的配置文件
3.可以作为网络传输数据的格式(现在以json为主)
构造一个xml文件
<?xml version="1.0" encoding="utf-8" ?>
eg:
...
.....
xml元素
xml命名:名称可以含字母,数字以及其他字符,不能以数字,xml或者标点符号开始,不能包含空格
文本区域:
.Tomcat
初始Tomcat:
下载,启动,配置环境
例题:网站如何进行访问的
输入域名,先检查本机的c:\windows\system32\drivers\etc\hosts配置文件下有没有这个域名映射
1.有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
2.没有:去DNS服务器找,找到的话就返回,找不到就返回找不到
发布一个web网站
将自己写的网站放到服务器(Tomcat中)指定的web应用文件夹(webapps)下,就可以直接访问了
网站该有的结构
自己尝试用tomcat发布一个静态网站:
第二种部署web:
找到目录:conf\catalina\localhost下,创建一个.xml文件,写入如下内容:
//path:工程访问路径 docBase:工程目录地址
手托浏览器和手动输入地址访问浏览器区别:
手托浏览器:使用的协议是file://协议,浏览器直接读取file后面路径
手动输入地址访问浏览器:使用http协议
ROOT,index.html工程的默认访问
在浏览器地址栏中输入访问地址(http://ip:port),默认访问ROOT工程
在浏览器地址栏中输入访问地址(http://ip:port/工程名),默认访问index.html页面
servlet
servlet是运行在服务器上一个java小程序,是javaee规范(接口)之一,是javaweb三大组件(servlet程序,filter过滤器,listener监听器)之一。它可以接受客户端发送的请求,并且作出响应给客户端。
手动实现一个servlet工程
1.写一个类实现servlet接口
2.重写servlet中所有方法,其中实现servic方法,此方法是接受请求并作出响应的
3.配置web.xml中servlet程序
mapping路径的优先级问题:
指定了固有的映射路径优先级高,没有此固有映射路径则选择其他路由如通配符的映射路径“/*''
************使用注解代替xml的servlet配置(经常用,很方便)
URL解析
Servlet周期
1.执行Serviet构造器方法
2.执行init初始方法
(仅在第一次访问的时候,第一,二步执行)
3.执行servic方法
(第三步每次访问都会被执行)
4.执行destroy销毁方法
(在web工程停止的时候,第四步才会停止)
servlet请求的分发处理
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3");
HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
//获取请求的方式
String method= httpServletRequest.getMethod();
if("GET".equals(method)){
doget();
}
else{
dopost();
}
}
public void doget(){
System.out.println("使用了get方法");
System.out.println("使用了get方法");
System.out.println("使用了get方法");
}
public void dopost(){
System.out.println("使用了post方法");
System.out.println("使用了post方法");
System.out.println("使用了post方法");
}
通过继承httpservlet实现servlet程序
(实际开发中,都是使用此方法来实现servlet程序)
1.写一个类继承Httpservlet类
2.根据业务需要重写doget或者dopost方法
3.到web.xml中的配置servlet 程序的访问地址
可以为一个dervlet设置多个url路径(2021版本的idea不加/):
GenericServlet
servlet程序创建时如果继承servlet类则必须实现init,service,destory等方法,较为笨拙。即如果仅继承servlet的子类GenericServlet,则不必实现servlet全部解口,较为方便,但依然不经常使用,后面会学习HttpServlet类是较为常用的
servlet继承体系
doget()和dopost封装了请求方式的获取
servletConfig类
作用:
1.获取servlet程序的别名servlet-name
servletConfig.getServletName();
2.获取初始化参数init-param
servletConfig.getInitParameter(name)//获取xml的初始化参数init-param,需要配置xml
3.获取servietContaxt对象
servletConfig.getservietContaxt();
ServletContext类
1.servletcontext是一个接口,表示servlet上下文对象
2.一个web工程,只有一个.servletcontext对象实例
3..servletcontext对象是一个域对象(像map一样可以存取数据的对象)
4.servletContext在web工程部署启动的时候的时候创建,在web工程停止的时候销毁
四个作用:
1.获取web.xml中配置的上下文参数表context-param
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext=getServletConfig().getServletContext();
servletContext.getInitParameter("")
}
-
init-param只能由 servletconfig获取(servletconfig.getinit-param()😉
-
context-param只能由servletcontext对象获取
ServletContext c=getServletConfig().getServletContext();
c.getInitParameter("")
2.获取当前工程路径,格式:/工程路径
ServletContext c=getServletConfig().getServletContext();
c.getConttextPath();
3.获取工程部署后在服务器上的绝对路径
ServletContext c=getServletConfig().getServletContext();
c.getRealPath("/");//"/"表示http://ip:port/工程名/
eg:工程下css目录的绝对路径:...c.getRealPath("/css")
4.像map一样存数据
ServletContext c=getServletContext();//直接调用getServletContext();
c.setAttribute(key,value);//保存数据
c.getAttribute(key);
5.获取文件资源
seervlet请求的http协议格式
get请求
1.请求行
(1)请求方式 GET
(2)请求资源路径[+?+请求参数]
(3)请求的协议的版本号 HTTP/1.1
2.请求头
key :value组成,不同键值对表示不同含义
post请求
1.请求行
(1)请求方式 POST
(2)请求资源路径[+?+请求参数]
(3)请求的协议的版本号 HTTP/1.1
2.请求头
key :value组成,不同键值对表示不同含义
---------------空行----------------
3.请求体------>发送给服务器的数据
区分GET请求和POST请求
1.get请求
- form标签 method=get
- a标签
- link标签引入css
- script标签引入js
- img标签引入图片
- iframe引入html页面
- 在浏览器中输入地址后敲回车
2.post请求
form标签 method=post
响应的HTTP格式
1.响应行
(1)响应的协议和版本号
(2)响应状态码
(3)响应状态描述符
2.响应头
key :value组成,不同响应,表示不同含义
————空行————
3.响应体——>>回传给客户的数据
常用响应码:
HttpServletRequest类
HttpServletRequest类的常用方法
设置请求体的字符集为UTF-8解决请求中午乱码问题(在获取请求参数之前调用)
red.setCharacterEncoding("UTF-8");
请求转发
请求是指,一个服务器收到请求后,从一个服务器资源跳到另一个服务器资源的操作
req.getRequestDispatcher("路径地址").forward(req,resq);
servlet1:
servlet2:
特点:
baseb标签
作用:base标签可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转
(最后的c.html可以省略)
HttpServletResponse类
此类与HttpServletrequest类相似,每次请求进来,tomcat服务器都会创建一个Response对象传递给Servlet程序使用。HttpServletrequest表示请求过来的信息,HttpServletResponse表示所有响应的信息。
我们如果需要设置返回给客户的信息,可以通过HttpServletResponse对象进行回应
两个输出流响应信息给客户端
1.字节流
getoutputStream();//常用于下载(传递二进制数据)
2.字符流
getWriter();常用于回传字符串(常用)
俩流不能同时使用
Response中文乱码问题
resp.setCharacterEncoding("UTF-8");
resp.setHeader("Content-Type","text/html;charset=UTF-8");
请求重新定向
xml:
response1:
response2:
设置response第二种方法
response文件下载:
//获取下载路径
String path=" ..../1.pang";
// 获取下载文件名称
String name=path.substring(path.lastIndexOf("//"+1));
// 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西
resp.setHeader("Content-Disposition","attachment;filename="+name);
// 获取下载输入流
FileInputStream in = new FileInputStream(path);
// 创建缓冲区
int len=0;
byte[] buffer = new byte[1024];
// 获取输出流对象
ServletOutputStream out = resp.getOutputStream();
// 将fileoutputstream流写入buff缓冲区,使用outputstream将缓冲区的数据传出给客户端
while ((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
in.close();
out.close();
JSP(java server pages)
jsp即服务器页面,主要作用是用来代替servlet程序回传html页面的数据
由于servlet程序回传html 页面数据繁琐,开发和维护成本高
1.jsp本质
就是一个servlet程序
当我们第一次访问jsp页面时,tomcat服务器会帮我们把jsp页面翻译成一个java源文件,并且对它进行编译成为.class字节码程序。jsp翻译出来的java类间接继承了Httpservlet,即翻译出来的是一个servlet类。
底层代码也是通过输出流,把html回传给客户端
2.page指令
1.language属性 表示翻译后是什么语言文件,暂时只支持java
2.contentTyp属性 表示jsp返回的数据类型是什么,源码中response.contenttype()参数值
3.pageEncoding属性 表示当前jsp文件本身的字符集
4.import属性 导包,导类
————以下是给out输出流使用————
3.autoFlush属性 设置当out输出流缓冲区满了之后,是否自动刷新缓冲区,默认值是true
4.buffer属性 设置out缓冲区的大小,默认是8kb
————————
5.errorPage属性 设置jsp运行出错时,自动跳转的页面路径
6.isErorPage属性 设置当前jsp页面是否是错误的信息页面,默认是fale
7.session属性 设置访问当前jsp页面是否会创建HttpSession对象,默认是true
8.extends属性 设置jsp翻译出来的java类默认继承
eg:<%@ page language=" ..." contentType="..." pageEncoging="..."%>
3.jsp脚本
声明脚本(很少用)
格式:<%! 声明脚本%>
作用:
声明类的属性:
<%!
privat Integer id;
privat String name;
private static Map;
%>
声明static 静态代码块
<%!
static{
map= new HashMap<String,Object>;
map.put("key","value");
}
%>
声明类的方法
<%!
public int abc(){}
%>
声明内部类
<%!
public class abc{
privat Integer id=12;
privat String name;
}
%>
表达脚本(常用)
表达式:<%= 表达式 %>
作用:在jsp页面上输出数据(整型,浮点型,字符串,对象)
eg:<%=12%>...<%=12.12%>...<%="我是字符串"%>...<%=map%>
特点:
1.所有表达式脚本都会被翻译到_jspservice方法中
2.表达式脚本都会被翻译成为out.print()输出到页面上
3.由于所有表达式脚本都会被翻译到__jspservice方法中,所以_jspservice方法对象可以直接使用
4.表达式脚本中的表达式不能用分号“;”结束
代码脚本
格式:<% 代码 %>
作用:在jsp文件中编写我们自己所需要的功能
代码脚本特点:
1.代码脚本翻译之后都在_jspservic方法中
2.代码脚本都会被翻译到__jspservice方法中,所以_jspservice方法对象可以直接使用
3.可以由多个代码脚本完成一个完整的Java语句
4.代码脚本还可以和表达式脚本一起组合使用,在jsp页面完成数据输出
4.jsp三种注释
1.html注释
2.Java注释
//单行注释
/* 多行注释 */
3.jsp注释
<%--多行注释--%>
可以注释掉jsp页面所有代码
注意:
jsp注释不会显示在客户端,html注释会显示
5.jsp九大内置对象
jar包源码展示
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
6.四大域对象
四个域都可以像map一样存数据,不同的是他们对数据的存取范围
使用的优先顺序为从小到大,即:pagContext-->request-->session-->application
7.out和response区别
jar包源码展示:
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true); //page
_jspx_page_context = pageContext;
application = pageContext.getServletContext(); //application
config = pageContext.getServletConfig();
session = pageContext.getSession(); //session
out = pageContext.getOut();
_jspx_out = out;
总是先输出response,再输出out内容,原因如下:
当jsp页面中所有代码执行完成之后会做以下两个操作:
1.执行out.flush()操作 ,会把out缓冲区的数据写入到response缓冲区末尾
2.执行response的刷新操作,即把全部数据写给客户端
由于jsp翻译之后,底层源代码都是使用out进行输出,所以一般情况下,我们都是统一在jsp页面中使用out输出,避免打乱页面输出顺序
注意out.write 与out.print()区别
out.write()输出字符串没问题(其他数据例如整型数据等输出就会有问题,关于ASCLL转换问题)
out.print()输出任何数据都没有问题(都转换成字符串后调用write输出)
8.jsp常用标签
静态包含
<%@ include file="你要包含的jsp页面路径"%>
特点:
静态包含不会翻译被包含的jsp页面
静态包含其实是把包含的jsp页面代码拷贝到包含的位置执行输出,将两个页面合二为一,本质是一个页面上的
动态包含
<jsp:include page="++指定++你要包含的jsp路径">< /jsp:include>
特点:
动态包含会把包含的jsp页面翻译成java代码,通过引用的方式,将两个文件拼接在一起,本质还是多个页面
动态包含可以传递参数
<jsp:name="abc" value="qwe"/>
<%=request.getParameter("abc")%>
<%@ include file="header.jsp"%>
<h1>我是body</h1>
<%@ include file="foot.jsp"%>
<br>
<jsp:include page="header.jsp"></jsp:include>
<h1>我是body</h1>
<jsp:include page="foot.jsp"></jsp:include>
动态代码底层原理:
请求转发
<jsp:forward page="请求转发的路径"></jsp:forward>
转发带参数:
<jsp:forward page="header.jsp">
<jsp:param name="name" value="谭振飞"/>
<jsp:param name="age" value="18"/>
</jsp:forward>
获取参数
<h2>我是header</h2>
<%=request.getParameter("name")%>
<%=request.getParameter("age")%>
9.jsp listener监听器
作用:监听某种事物变化,然后通过回调函数,反馈给客户(程序)做一些处理
ServletContextListener监听器
1.它可以监听ServletContext对象的创建和销毁
2.ServletContext对象在web工程启动的时候创建,在web工程停止时销毁,此过程调用ServletContextListener两个方法:
public interface ServletContextListener extends EventListener {
default void contextInitialized(ServletContextEvent sce) {
}
//ServletContext创建的时候调用
default void contextDestroyed(ServletContextEvent sce) {
}
}
//ServletContext销毁的时候调用
使用ServletContextListener监听器来监听ServletContext对象
1.编写一个类来实现ServletContextListener
2.实现两个回调方法
3.到web.xml配置监听器
EL表达式
JSTL
jsp标准标签库,为了弥补html标签的不足
核心标签:
例子:
<%
ArrayList<String> people=new ArrayList<>();
people.add("1");
people.add("2");
people.add("3");
people.add("4");
request.setAttribute("list",people);
%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"></c:out>
</c:forEach>
if标签
choose标签
foreach标签
COOKIE
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话
状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学曾经来过,称之为有状态会话
一个网站怎么证明你来过:
1.客户端给客户一个信件,客户端下次来访问服务器端带上信件就可以了;cookie
2.服务器登记你来过了,下次你来的时候我来匹配你;seesion
服务器通知客户端保存键值对的一种技术
客户端有了cookie后,每次请求都发送给了服务器
每个cookie的大小不能超过4kb
cookie的创建(保存在客户端)
1.创建cookie对象:Cookie cookie=new Cookie("key","value");
2.通知客户端保存Cookie:resp.addCookie(cookie);//此过程不可省略
解决响应中文乱码问题:resp.setContentType("text/html;charset="UTF-8");
cookie创建的底层原理:
cookie的获取
服务器获取cookie:req.getcookies();//返回cookie数组
获取指定单个cookie:
Cookie c1=null;
for(Cookie cookie:cookies){
if("key".equals(cookie.getName()))
c1=cookie;
}
if(c1!=null){
response.getWriter().write("找到了需要的cookie");
}
cookie值的修改
方案一:
1.先创建一个要修改的同名的cookie对象
2.在构造器,同时赋予新的cookie值
3.调用response.addcookie(cookie);
Cookie cookie=new Cookie("key1","newvalue");
response.addCookie(cookie);
方案二:
1.先查找到需要修改的cookie对象
2.调用setValue()方法赋予新的cookie值
3.调用response.addcookie(cookie);通知客户端保存修改
注意:cookie的value值不能为空格,方括号,等号,逗号,双引号,斜杠,问好,汉字等,如果要使用,要是有base64编码。
cookie生命配置
指的是如何管理cookie什么时候被销毁(删除)
方法:setMaxAge(index);
当index为正数,表示在指定的秒数后过期
当index为负数,表示浏览器一关,cookie就会被删除//默认为-1
当index为零,表示立刻删除cookie
cookie的有效路径path的设置
path属性可以有效地过滤哪些cookie可以发送给服务器,哪些不能
path是通过请求的地址来进行有效的过滤
Cookie cookie=new Cookie("path","path");
cookie.setPath(request.getContextPath()+"/abc");
response.addCookie(cookie);
response.getWriter().write("创建了带有path路径的cookie");
Cookie值是汉字时解决乱码问题
1.先对cookie编码:
new Cookie("tzf", URLEncoder.encode("谭振飞","utf-8"));
2.再对cookie解码:
URLDecoder.decode(cookie.getValue(),"utf-8");
Session(服务器端,重点)
会话,是一个接口,用来维护一个客户端和服务器之间关联的一种技术
每个客户端都有自己的一个session会话
session会话中,我们经常用来保存用户登陆之后的信息
1.创建session和获取(id号,是否为新)
request.getSession();
第一次调用,表示创建session会话;
之后调用都是获取前面创建好的会话对象
判断request.getSession();是否为第一次调用:
isNew();
true 表示刚创建(第一次)
false 表示获取之前创建好的会话
注意:每一个会话都有一个独一无二的id
getid();
方法用来得到该方法id;
2.session域数据的存储
request.getSession().setAttribute("key","value");
request.getSession().getAttribute("key");
//得到session
HttpSession session = req.getSession();
String id = session.getId();
person person = new person("谭振飞", "20");
session.setAttribute("name",person);
if(session.isNew()){
resp.getWriter().write("session创建成功,id是:"+id);
}
else {
resp.getWriter().write("session已经存在,id是:"+id);
}
session.removeAttribute("name");
// 手动注销
session.invalidate();
3.session生命周期控制
public void setMaxlnactivelnterval(int interval)
设置session的超时时长(以秒为单位),超过指定时长(默认时长30分钟),session就会被销毁
正数设置超时时长(两次点击间隔时长)
负数表示永不超时(很少用)
如果为零,使用此会话无效,然后取消对任何绑定到它的对象绑定
public void getMaxlnactivelnterval(int interval)
获取session的超时时长
如果想要修改个别session的超时时长,可以用session.getMaxlnactivelnterval(int interval)单独设置
session注销
(1)手动注销:
public void invalidate();
让当前的session会话超时无效,即注销session
(2)配置生命周期自动注销:
<session-config>
<!--以分钟为单位,设置15分钟自动失效-->
<session-timeout>15</session-timeout>
</session-config>
4.浏览器和session 之间的关联
session技术,底层是基于cookie技术来实现的
5.Session和Cookie的区别
- cookie是把用用户数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session把用户的数据写到独占Session中,服务器端保存(保存重要信息,减少服务器资源的浪费)
- Session对象由服务创建
session使用场景:
- 保存一个登录用户信息
- 购物车信息
- 在整个网站中经常会使用的数据,我们将它保存在Session中
Filter过滤拦截
javaee接口
作用:拦截请求,过滤响应
filter中dofilter方法专门拦截请求的
拦截请求底层原理:
filter基本使用
1.编写一个类实现filter接口
2.实现过滤方法dofilter();
3.到web.xml中配置filter的拦截路径
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
HttpSession session=httpServletRequest.getSession();
Object user=session.getAttribute("user");
if(user!=null){
//如果没有登录,跳转登录页面
servletRequest.getRequestDispatcher("/dsm.jsp").forward(servletRequest,servletResponse);
}
else{
//已经登录,放行继续访问资源
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
<filter>
<filter-name>getfilter</filter-name>
<filter-class>dsm.dsm.Getfilter</filter-class>
</filter>
<filter-mapping>
<filter-name>getfilter</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
filter生命周期
1.构造器方法
public class Getfilter implements Filter {
public Getfilter() {
}
2.init初始化方法
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
第一二步在web工程启动的时候执行(filter已经创建)
3.dofilter过滤方法
每次拦截到请求就会执行
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
// HttpSession session=httpServletRequest.getSession();
// Object user=session.getAttribute("user");
// if(user!=null){
// //如果没有登录,跳转登录页面
// servletRequest.getRequestDispatcher("/dsm.jsp").forward(servletRequest,servletResponse);
// }
// else{
// //已经登录,放行继续访问资源
// filterChain.doFilter(servletRequest,servletResponse);
// }
}
4.destroy销毁
停止web工程的时候,就会执行(停止web工程,也会销毁web工程)
@Override
public void destroy() {
}
filterConfig类
filter过滤器的配置文件类,tomcat每次创建filter的时候都会创建filterconfig类
作用:
1.获取filter-nameneir
filterconfig.getfiltername();
2.获取在filter中配置的init-param初始化参数
filterconfig.getInitParamter();
3.获取servletcontent对象
filterconfig.getServletContext();
filterchan
过滤器链(多个过滤器同时执行)
特点:
1.所有filter和目标为资源默认都执行在一个线程中
- 多个filter共同执行的时候,他们都使用同一个request对象
filter的拦截路径
--精确匹配
<url-pattern>/hello</url-pattern>
--目录匹配
<url-pattern>/admin/*</url-pattern>
--后缀名匹配
<url-pattern>/*.html</url-pattern>
listener监听器
1.实体类:
ServletContext ctx = se.getSession().getServletContext();
System.out.println(se.getSession().getId());
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);
2.web.xml中注册配置信息
<listener>
<listener-class>com.dsm.listener.listener</listener-class>
</listener>
3.看惊恐
JSON
(待学)
Ajax
- Ajax=异步JavaAcript+XML
- Ajax是一种用于创建快速动态网页的技术,通过在后台与服务器进行少数数据交换,Ajax可以使网页实现异步更新,这意味着可以不断重复加载整个网页的情况下,对网页的莫部分进行更新
- 传统网页(不使用Ajax)如果需要更新内容,必须重载整个网页
- Ajax不是一门新的编程语言,而是一种用于创建更快以及交互性更强的web应用程序的技术
使用jQuery需要导入jQuery,使用Vue导入Vue,两个都用,自己原生态实现
三部曲
1.编写对应处理的Controller,返回消息或者json格式的数据;
2.编写ajax请求
- url:Controller请求
- data:键值对
- success:回调函数
3.给Ajax绑定事件,点击.click,失去焦点onblur,键盘弹起keyup
.Http
http(超文本传输协议)是一个简单的请求响应协议,他通常运行在TCP之上
- http1.0:客户端可以与web服务器连接后,只获取一个web资源,断开连接
- http2.0:客户端可以与web服务器连接后,可以获取多个web资源
http相对路径和绝对路径:
web中"/"(表示绝对路径)不同的意义
浏览器中"/"被解析成:http://ip:port/
服务器中"/"被解析成:http://ip:port/工程路径
eg:
servletContext.getRealPath("/");
request.getRequestDispatcher("/");
特殊情况:
request.sendRediect("/");虽然此时在服务器内,仍然把斜杠发送给浏览器,解析成http://ip:port/
http请求
客户端--发请求--服务器
eg百度:
1.请求行
- 请求方式:get,post,head,delete,put,tract...
get:请求能够携带的参数比较少,大小写有限,会在浏览器的URL地址栏显示数据内容,不安全,但高效
post:请求能够携带的参数没有限制,大小写没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效
-
消息头
http响应
- 服务器--响应--客户端
eg百度:
1.响应体
2.响应状态码
200:请求响应成功 200
3--:请求重定向(重新到--位置去)
4--:找不到资源 404
5--:服务器代码错误 500(服务器错误) 502(网关错误)
Maven
. Maven是专门用于管理和构建Java项目的工具,它的主要功能有:
- 提供了一套标准化的项目结构
- 提供了一套标准化的构建流程(编译,测试,打包,发布...….)
- 提供了一套依赖管理机制
在Javaweb开发者,需要手动导入大量jar包,而maven(项目架构管理工具)就可以帮助我们导入jar包
Maven核心思想:约定大于配置
下载安装maven
环境配置变量
(未完---------------------)
jdbc
jdbc原理解释图 :
Java DataBase Connectivity
主要在java语言中编写sql语句,对mysql数据库中的数据进行CRUD操作,是sun公司指定好的接口,降低了程序的耦合度,可以连接任意一个数据库
jar包实际就是jdbc接口的实现类,其中mysql-connector-java-5.1.23的jar包专业术语,mysql的驱动
jdbc编程六步
首先需要导入数据库依赖:
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
1.注册驱动(通知java程序我们即将要连接的是哪个品牌的数据库)
方式一:
Driver driver=new com.mysql.jdbc.Driver();
DriverManager.registerDriver(driver);
方式二(类加载):
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2.获取数据库连接(java进程和mysql进程,两个进程之间的通道开启了)
方式一:
String url="jdbc:mysql://localhost:3306/bjpowernode";
String user="root";
String password="123456";
conn=DriverManager.getConnection(url,user,password);
方式二(资源绑定器):
配置文件资源包resources下的bd包:
driver:...
url:...
user:...
passworld:...
java类:
ResourceBundle bundle=ResourceBundle.getbundle("resources/db")
String driver=bundle.getString("driver");
String url=bundle.getSrting("url")
String user=bundle.getString("user")
String password=bundle.getString("password")
优点:配置文件改变时,不用动代码
3.获取数据库操作对象(用这个对象执行sql)
stmt =conn.createStatement();
4.执行sql操作语句(执行crud)
//增
String insert="insert into user_info(deptno,dname,loc)value(50,'销售部','北京')";
int count=stmt.executeUpdate(insert);
//改
String updataSql="updata deptno set dname='人事部',loc='天津' where deptno=50";
int count1=stmt.executeUpdate(updataSql);
//删
String deleteSql="delete from user_info where deptno=50";
int count3=stmt.executeUpdate(deleteSql);
//查
String str="select * from user_info order by id";
rs= stmt.executeQuery(str);
while (rs.next()){
String empno= rs.getString(1);
String empname= rs.getString(2);
String sal= rs.getString(3);
System.out.println(empname+","+empno+"," +sal);
5.处理查询结果集(如果第四步是select语句,才有第五步)
//根据下标取值
// int empno1=rs.getInt(1);
// String ename=rs.getString(2);
//根据查询结果的列名取值,健壮,username不是表中字段的名字,是查询结果的列名即select 后的名字
// int empno1=rs.getInt("id");
// String ename=rs.getString("username");
6.释放资源(关闭资源)
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
DriverManger.registerdriver(new com.mysql.jdbc.driver)
conn=DriverManager.getConnection(......)
ste=conn.creatStement()
String str=''
re=ste.executeQuery(str)
sql注入
java.sql.Statement接口特点:先进行字符串拼接,然后再进行sql语句的传值
优点:使用Statement可以在sql语句的拼接
缺点:由于拼接的存在,导致可能给不法分子机会。导致sql注入()
java.sql.PrepareStatement(预编译数据库操作对象)接口特点:先进行sql语句的编译,然后再进行sql语句的传值。
优点:避免sql注入
缺点:没有办法进行sql语句的拼接,只能给sql语句赋值
避免sql注入方法
prepareStatement对字符进行转义和预编译,来预防SQL注入问题
jdbc事物
要么成功,要么失败
ACID原则:保证数据的安全
- 开启事务
- 事务提交
- 事务回滚
- 关闭事物
junit
单元测试,可以用注解@test来代替main方法,来实现不需要main方法就可运行class类
1.先导入Junit包
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
2.使用@test注解
@test注解只在方法上有效
public class test {
@Test
public void test(){
}
}
jdbc默认情况支持自动提交,在实际开发中必须将jdbc的自动提交机制关掉,改成手动提交,当一个完整的事物结束之后,再提交
解决方法:
conn.setAutoCommit(false);关闭自动提交机制
conn.commmit();手动提交
conn.rollback();手动回滚
javabean
java写的可重用组件,减少代码的冗余,相同代码的功能不必重写
实体类
javabean特定的写法:
- 属性必须有一个无参构造
- 属性必须私有化
- 必须有对应的get/set法
一般用来和数据库的字段做·映射
- 表-->类
- 字段-->属性
- 行记录-->对象
<jsp:useBean id="people" class="com.dsm.jsp01.people"/>
<jsp:setProperty name="people" property="age" value="18"/>
<jsp:setProperty name="people" property="name" value="tzf"/>
姓名:<jsp:getProperty name="people" property="name"/>
年龄:<jsp:getProperty name="people" property="age"/>
mvc开发模式
演变历史:
文件上传与下载
1、准备工作
采用Apache的开源工具common-fileupload这个文件上传组件。
common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
(https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload/1.3.3)
<!--maven相关jar包导入-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
(https://mvnrepository.com/artifact/commons-io/commons-io)
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
2、使用类介绍
【文件上传注意事项】
1、为保证服务器的安全,上传的文件应放在外界无法访问的目录下,如WEN-INF。
2、为防止同名文件产生覆盖现象,要为文件指定一个唯一的文件名。(-时间戳 -uuid -md5 -位运算算法 )
3、要对上传文件的大小进行限制。
4、限制上传文件的类型,收到文件时,判断文件名十分合法。
HTML中
表单中如果包含一个文件上传项的话,这个表单的entype属性必须设置为multipart/form-data
<form action="${pageContext.request.contextPath}/upload.do" method="post"enctype="multipart/form-data">
<p>用户名:<input type="text" name="username" placeholder="请填写用户名"></p>
<p>上传文件:<input type="file" name="filename"></p>
<p><input type="submit" value="提交"><input type="reset" value="重置"></p>
【需要用到的类详解】
ServletFileUpload负责处理上传的文件数据,并将表单中的每个输入项封装成一个FileItem对象,在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileItem对象的构造方法或setFileItemFactory()设置ServletFileUpload对象的fileItemFactory属性。
public class UploadFileServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException {
//判断上传的表单是普通表单还是带文件的表单,是返回true,否返回false;
if (!ServletFileUpload.isMultipartContent(request)){
return;//如果这是一个普通文件我们直接返回
}//如果通过了这个if,说明我们的表单是带文件上传的
//创建上传文件的保存目录,为了安全建议在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 file = new File(tmppath);
if (!file.exists()){
file.mkdir();//如果目录不存在就创建这样临时目录
}
//处理上传的文件一般需要通过流来获取,我们可以通过request.getInputstream(),原生态文件上传流获取,十分麻烦
//但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于common-io组件;
try {
//1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小
DiskFileItemFactory factory = gteDiskFileItemFactory(file);
//2、获取ServletFileUpload
ServletFileUpload upload = getServletFileUpload(factory);
//3、处理上传文件
String msg = uploadParseRequest(upload,request,uploadpath);
//Servlet请求转发消息
request.setAttribute("msg",msg);
request.getRequestDispatcher("/info.jsp").forward(request,response);
}catch (FileUploadException e){
e.printStackTrace();
}
}
public static DiskFileItemFactory gteDiskFileItemFactory(File file){
//1、创建DiskFileItemFactory对象,处理文件上传路径或限制文件大小
DiskFileItemFactory factory = new DiskFileItemFactory();
//通过这个工厂设置一个缓冲区,当上传的文件大小大于缓冲区的时候,将它放到临时文件中;
factory.setSizeThreshold(1024 * 1024);//缓冲区大小为1M
factory.setRepository(file);
return factory;
}
public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
//2、获取ServletFileUpload
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener(new ProgressListener() {
@Override
public void update(long pBytesRead, long lpContentLenght, int i) {
//pBytesRead:已读取到的文件大小
//pContentLenght:文件大小
System.out.println("总大小:"+lpContentLenght+"已上传:"+pBytesRead);
}
});
//处理乱码问题
upload.setHeaderEncoding("UTF-8");
//设置单个文件的最大值
upload.setFileSizeMax(1024 * 1024 * 10);
//设置总共能够上传文件的大小
//1024 = 1kb * 1024 = 1M * 10 = 10M
upload.setSizeMax(1024 * 1024 * 10);
return upload;
}
public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadpath) throws IOException, FileUploadException {
String msg = "";
//3、处理上传文件
//把前端的请求解析,封装成一个FileItem对象
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()){ //判断是普通表单还是带文件的表单
//getFieldName指的是前端表单控件的name
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("")) continue;
//获得上传的文件名,例如/img/girl/ooa.jpg,只需要ooa,其前面的后面的都不需要
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
//获得文件的后缀名
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
/*
* 如果后缀名 fileExtName 不是我们需要的
*就直接return,不处理,告诉用户类型不对
* */
System.out.println("文件信息【文件名:"+fileName+"文件类型:"+fileExtName+"】");
//可以使用UUID(唯一通用识别码)来保证文件名的统一
String uuidFileName = UUID.randomUUID().toString();
//=======================传输文件=========================//
//获得文件上传的流
InputStream inputStream = fileItem.getInputStream();
//创建一个文件输出流
FileOutputStream fos = new FileOutputStream(uploadpath + "/" + uuidFileName +"."+ fileExtName);
//创建一个缓冲区
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();//上传成功,清除临时文件
}
}
return msg;
}
}
3、其他
重点了解HashMap和线程底层源码
uuid是如何实现的
邮件发送
1、传输协议:
-
SMTP协议
处理用户邮件发送的请求。
-
POP3协议
处理用户邮件接收请的求。
2、导包:
mail-1.4.7.jar
activation-1.1.1.jar
3、过程:
4、代码:
[](javascript:void(0)😉
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
public class sendMail01 {
//简单邮件:纯文本内容
//复杂邮件:文本+图片+附件
//要发送邮件需要获取协议,开启POP3和SMTP服务
public static void main(String[] args) throws Exception {
Properties prop = new Properties();//创建一封邮件
//以下三项的Key的值都是固定的
prop.setProperty("mail.host","smtp.qq.com");//设置邮件服务器
prop.setProperty("mail.transport.protocol","smtp");//设置邮件发送协议
prop.setProperty("mail.smtp.auth","true");//需要验证用户名和密码
//如果是QQ邮箱,还要设置SSL加密,加上以下代码即可
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");
prop.put("mail.smtp.ssl.socketFactory",sf);
//==========使用JavaMail发送邮件的6个步骤======
//1、创建定义整个应用程序所需要的环境信息的Session对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication(){
//发件人邮箱的用户名和授权码(只有qq是授权码,其它的是密码)
return new PasswordAuthentication("1612893803@qq.com","授权码");
}
});
//开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过Session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("SMTP.qq.com","1612893803@qq.com","授权码");
//4、创建邮件
//创建邮件对象
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("1612893803@qq.com"));
//指明邮件的收件人
message.setRecipient(Message.RecipientType.TO,new InternetAddress("212694926@qq.com"));
//邮件的标题
message.setSubject("只是一个普通的纯文本邮件");
//邮件的文本内容
message.setContent("你好哇,我来了!","text/html;charset=UTF-8");
//5、发送邮件
ts.sendMessage(message,message.getAllRecipients());
//6、关闭连接
ts.close();
}
}
[](javascript:void(0)😉
5、带附件:
附件格式包含关系:
[](javascript:void(0)😉
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;
public class sendMail02 {
//简单邮件:纯文本内容
//复杂邮件:文本+图片+附件
/*
*MimeMessage类表示整封邮件。
*MimeBodyPart类表示邮件的一个MIME消息。
*MimeMultipart类表示一个由多个MIME消息组合成的组合MIME消息。
*/
//要发送邮件需要获取协议,开启POP3和SMTP服务
public static void main(String[] args) throws Exception {
Properties prop = new Properties();//创建一封邮件
//以下三项的Key的值都是固定的
prop.setProperty("mail.host","smtp.qq.com");//设置邮件服务器
prop.setProperty("mail.transport.protocol","smtp");//设置邮件发送协议
prop.setProperty("mail.smtp.auth","true");//需要验证用户名和密码
//如果是QQ邮箱,还要设置SSL加密,加上以下代码即可
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable","true");
prop.put("mail.smtp.ssl.socketFactory",sf);
//==========使用JavaMail发送邮件的6个步骤======
//变量名字定义的有点乱,不想改了。将就下吧
//1、创建定义整个应用程序所需要的环境信息的Session对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication(){
//发件人邮箱的用户名和授权码
return new PasswordAuthentication("1612893803@qq.com","授权码");
}
});
//开启Session的debug模式,这样就可以查看到程序发送Email的运行状态
session.setDebug(true);
//2、通过Session得到transport对象
Transport ts = session.getTransport();
//3、使用邮箱的用户名和授权码连上邮件服务器
ts.connect("SMTP.qq.com","1612893803@qq.com","授权码");
//4、创建邮件
//创建邮件对象
MimeMessage message = new MimeMessage(session);
//指明邮件的发件人
message.setFrom(new InternetAddress("1612893803@qq.com"));
//指明邮件的收件人
message.setRecipient(Message.RecipientType.TO,new InternetAddress("212694926@qq.com"));
//邮件的标题
message.setSubject("这是一个有文本、图片、附件的邮件");
//邮件的内容
//=================================================
//准备图片数据 DataHandler:处理除文本外的数据
MimeBodyPart image = new MimeBodyPart();
DataHandler dh = new DataHandler(new FileDataSource("C:\\Users\\Think\\Documents\\image-20200220200136289.png"));
image.setDataHandler(dh);
image.setContentID("xx.png");//设置图片ID
//ContentID用于为“multipart/related”组合消息中的内嵌资源指定一个唯一标识号,在HTML格式的正文中可以使用这个唯一标识号来引用该内嵌资源。
//注意,在引用Content-ID头字段标识的内嵌资源时,要在资源的唯一标识号前面加上“cid:”,以说明要采用唯一标识号对资源进行引用。
//准备正文数据
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一个带图片、文本、附件<img src='cid:xx.png'>的邮件","text/html;charset=UTF-8");
//准备附件数据
MimeBodyPart accessory = new MimeBodyPart();
DataHandler dh2 = new DataHandler(new FileDataSource("C:\\Users\\Think\\Pictures\\Saved Pictures\\illust_70110900_20191209_012234.jpg"));
accessory.setDataHandler(dh2);
accessory.setFileName(MimeUtility.encodeText("yan"));//给附件一个名字,发过去显示的就是这个设定的名字||MimeUtility.encodeText("")解决附件发送过去乱码;
//*****************************!!!!!!!**********************
/*
MimeBodyPart:表示复杂邮件的一个组成部分,它可以表示文本,附件,图片
DataHandler:表示可以读取图片或附件
MimeMultipart:表示二个邮件组成部分的关系,文本和图片的关系是"related"关系
Content-ID:表示图片的编号
related:图片|| mixed:附件
*/
//*****************************!!!!!!!**********************
//拼接图片和文本
MimeMultipart mm = new MimeMultipart();
mm.addBodyPart(text);
mm.addBodyPart(image);
mm.setSubType("related");
//将文本+图片封装成邮件的组成部分,即将关系看作成一个部分
MimeBodyPart context = new MimeBodyPart();
context.setContent(mm);
//把附件也加上
MimeMultipart file = new MimeMultipart();
file.addBodyPart(context);
file.addBodyPart(accessory);
file.setSubType("mixed");
//放到消息中
message.setContent(file);//把编辑好的内容放入消息中
message.saveChanges();//保存修改!
//=================================================
//5、发送邮件
ts.sendMessage(message,message.getAllRecipients());//message:发送的消息||message.getAllRecipients():获取保存在里面的地址
//6、关闭连接
ts.close();
}
//对于,复杂类型的邮件,位置关系特别注意和加入的顺利要一致
}
[](javascript:void(0)😉