javaWeb学习笔记

主要内容: HTML, CSS, JavaScript, XML, JSON, Tomcat, Servlet, Filter, Listener, 会话, JSP, MVC, AJAX/Axios, Thymeleaf, WebSocket

文章目录

网页主要由三部分组成:

结构:HTML

表现:CSS

行为:JavaScript

HTML

Chrome浏览器调试工具:右键点“检查”,或按F12

常用标签

标题标签 : < h1 > ~ < h6 >

段落标签:< p > < /p > (两段之间会插入一定的间距)

换行标签:< br >

水平分割线:< hr >

文本格式化标签:

  • 加粗:< strong >< /strong >或者 < b >< /b >
  • 倾斜:< em >< /em > 或者 < i >< /i >
  • 删除线:< del >< /del > 或者 < s >< /s >
  • 下划线:< ins >< /ins > 或者 < u >< /u >

分区标签:

  • < div > < /div > :一行只能放一个 < div > ,是大分区;
  • < span > < /span > :一行可以放多个 < span >,是小分区;

其他布局标签:(用于手机网页制作)

标签名语义
header网页头部
nav网页导航
footer网页底部
aside网页侧边栏
section网页区块
article网页文章

image-20220228195231266

图像标签:

  • < img src=“图像URL” / >

  • < img src=“图像URL” alt=“替换的文字” title=“图像提示文字”/ >

    图像标签的属性:

    属性之间不分先后顺序,但必须用空格分开

    属性采用键值对的格式:key=“value”

    属性属性值说明
    src图片路径必须属性
    alt文本替换文本,图像不能显示时出现的文字
    title文本提示文本,鼠标放到图像上会浮现的文字
    width像素设置图像的宽度
    height像素设置图像的高度
    border像素设置图像的边框粗细

相对路径: / 指下一级路径, …/ 指上一级路径

绝对路径:\

<!-- 注意最后应该有个斜杠/,以表示是目录 -->
<base href="http://localhost:8080/07_servlet/a/b/">

base标签:可以设置当前页面中所有路径工作时,参照哪个路径来进行跳转。

超链接:< a > 具体为:< a href=“跳转目标” target=“目标窗口的弹出方式” > 文本、图像、音频等(点击样式) < /a>

属性作用
href用于指定链接目标的url地址(必须属性)
target用于指定链接页面的打开方式,_self为默认值, _blank为在新窗口打开

如:< a href=“http://www.qq.com” target=“_blank”> 腾讯< /a >

内部链接:则href 后可以直接写相对路径。即两者在同一文件夹。

空链接:href 后写个 # ,即 < a href=“#”> ** < /a >

下载链接:href后写压缩文件的路径

锚点链接:在href属性中,设为 #名字 的形式,如 < a href=“#ZZC”> 哈哈 < /a >,然后在目标处,添加一个id属性=设定的名字,如 < h4 id=“ZZC” >


注释: < !-- 注释语句 – > ,快捷键 :ctrl + /

特殊字符:(只记空格符就行,所有字符后都要带个分号 ; )

特殊字符描述字符的代码
空格符&nbsp
<小于号&lt
>大于号&gt
&和号&amp
人民币&yen
©版权&copy
®注册商标&reg
°摄氏度&deg
±正负号&plusmn
×乘号&times
÷除号&divide
²平方2&sup2
³立方3&sup3


表格标签

< table>< /table>:是用于定于表格的标签

< tr >< /tr >:用于定义表格中的行,必须在< table >中

< td >< /td >:用于单元格,必须嵌套在< tr >中

< th >< /th >:表示表头单元格(文本内容居中加粗)

表格结构标签:< thead >指表格的头部区域,<tbody>指表格 的主体区域。

合并单元格(属性):跨行合并——rowspan=”合并个数“,跨列合并——colspan=“合并个数”(也可说是占了若干个单元格)

合并步骤:找到目标单元格,写上合并方式,如:< td colspan=“2” >< /td >,然后再删除多余的单元格。

表格属性:

属性属性值描述
alignlegt,center,right规定表格相对周围元素的对齐方式
border1或 ” “是否有边框,默认为” “,即无边框
cellpadding像素值规定单元边沿与内容之间的空白,默认1像素
cellspacing像素值规定单元格之间的空白,默认1像素
width像素值或百分比规定表格的宽度

如:

<table align="center" border="1" cellpadding="0">
	<tr>
    	< th>表头单元格的内容</th>
		< td>单元格中的内容</td>
	</tr>
</table>


列表

无序列表:< ul > ,列表项:< li >

有序列表:< ol >

自定义列表:< dl > ,表项头< dt >,表项:< dd >

< ul >和< ol >里只能放< li >, < li >里面可以放任意标签,< dl >里只能放< dt >和< dd >。


表单

表单域(区域):< form >

<form action="url地址" method="提交方式" name="名称">

表单域属性:

属性属性值作用
actionurl地址指定接收该表的服务器程序的url地址
methodGET/POST设置表单数据的提交方式
name名称指定表单名称

表单元素:

  • 输入元素:< input type=“属性值” / >

    input属性:

    属性属性值描述
    name自定义定义input元素的名称
    value自定义规定input元素的值
    checkedchecked规定此input首次加载时被选中
    maxlength正整数规定输入字符的最大长度

    注:name和value是每个表单元素都有的属性值,主要给后台人员使用;要求单选按钮和复选框要有相同的name值

    type属性值:

    属性描述
    button定义可点击按钮(多数情况下,用于通过 Javascript启动脚本)
    checkbox定义复选框。
    file定义输入字段和“浏览"按钮,供文件上传。和 multiple 搭配可以上传多个文件
    hidden定义隐藏的输入字段。
    image定义图像形式的提交按钮
    password定义密码字段。该字段中的字符被掩码。
    radio定义单选按钮
    reset定义重置按钮。重置按钮会清除表单中的所有数据
    submit定义提交按钮。提交按钮会把表单数据发送到服务器。
    text定义单行的输入字段,用户可在其中输入文本。默认宽度为20个字符。
    placeholder占位符,作提示,常用于需要输入的文本框

    < label > :用于绑定一个表单元素,当单击此标签内的文本时,会自动选择对应的表单元素,以增加用户体验。

    格式:< label >里的for属性 应该与相关元素的 id属性相同。如:

    <label for="zzc"> 文本</label> 
    <input type=" " id="zzc"/>
    
  • 下拉元素:< select > :定义下拉列表

    在< option >中添加selected=”selected”时,为默认选中项

    <select>
        <option> 选项 </option>
    </select>
    
  • 文本域元素:< textarea >:定义多行文本输入控件

<textarea>
	文本内容
</textarea>

CSS

CSS:层叠样式表

CSS书写顺序:

  1. 浮动 / display
  2. 盒子模型:margin border padding 宽度高度背景色
  3. 文字样式

导入方式

  1. 内联样式:在标签内使用style属性(耦合较高,较少使用)

    <div style="color: red"> HELLO CSS </div>
    
  2. 内部样式:定义 < style > 标签,在标签内定义css样式;

    (一般写在head标签里,title标签下面)

    <style>
    /*选择器 { 样式 } */
    /*给谁改样式 { 改什么样式 } */
    p {
        color: red;		/*键值对用:分开,每行用;结尾*/
        fon-size: 12px;
    }
    </style>
    
  3. 外部样式:定义link标签,引入外部的css文件

    <link rel="stylesheet" href="demo.css">
    
    /*demo.css*/
    div{
    	color: red;
    }
    

规范:

选择器、属性名、属性值统一小写;

选择器(标签)和大括号中间带空格;

冒号后带空格



选择器

  • 标签选择器:元素名称{color: red;}

    div{color: red}
    
  • id选择器:#id属性值{color: red;}

    注意:id是唯一的,一般与js配合制作动态效果

    #name{color: red;}
    <div id="name">hello css</div>
    
  • 类选择器:.class属性值{color: red;}

    .cls{color: red;}
    <div class="cls">helle css</div>
    
  • 通配符选择器:*{ color: red;}

    作用:为页面的所有标签 设置样式。

    *{
    	margin: 0;
        padding: 0; /*去除默认的外边距*/
    }
    


更多用法:

  • 后代选择器:选择器1 选择器2 { css }

    作用:根据嵌套关系,选择父元素的 后代中满足条件的元素。

    注:后代包括 儿子、孙子…

    div p{
        ....
    }   /* 选择div下的p标签 */
    
  • 子代选择器: 选择器1 > 选择器2{css}

    作用:选择父元素的子代元素。

    注:子代只包含儿子

  • 并集选择器: 选择器1,选择器2{css}

    作用:用逗号隔开,同时选择多组标签,设置相同的样式。

    注:一般写法是 每个选择器写一行,提高代码的可读性。

  • 交集选择器:选择器1选择器2 { css }

    作用:选中页面中同时满足多个选择器的标签

    注:选择器连着写,且标签选择器优先写在前面。

  • hover伪类选择器:选择器:hover {css}

    作用:在鼠标悬停在元素上时 会出现的状态样式

字体和文本样式

字体样式
  • 字体大小:font-size

    取值:数字+px

    谷歌浏览器默认文字大小是16px

    p{
        font-size: 30px
    }
    
  • 粗细:font-weight

    取值:normal,bold;(指正常和加粗)

    或取100到900的整百数,正常是400,加粗是700

  • 样式:font-style (是否倾斜)

    取值:normal,italic(正常和倾斜)

  • 类型系列:font-family

    取值:微软雅黑,黑体…等等,最后应该加sans-serif(无衬线字体)(从设置的第一种字体开始选,没有就选择下一个电脑有的字体)

  • 字体font连写:

    取值:font:style weight size family(可以省略前两个值,为默认值)

    复合属性:一个属性后面写多个值的写法

    font: italic 700 66px 宋体
    
文本样式
  • 文本缩进:text-indent

    取值:数字+px 或 数字+em(1em=当前标签的大小,推荐)

    p{
        text-indent: 2em  /*缩进两字符*/
    }
    
  • 文本水平对齐方式:text-align

    属性值:left,center,right;分别是左对齐,居中,右对齐

    注:text-align 其实是内容对齐,不仅仅用于文本, 能用于 文本、span标签、a标签、input标签、img标签 。不过需要在以上元素的父元素设置,如。

  • 文本修饰:text-decoration

    取值:underline,line-through,overline,none;分别是下划线(常用),删除线,上划线,无装饰线(常用)。


line-height行高

作用:控制一行的上下行间距

取值:数字+px 或 倍数(当前标签font-size的倍数)

注意:

如果同时设置了行高和font连写,注意覆盖问题
font:style weight size/line-height family

font:ita1ic 700 66px/2 宋体;

标签水平居中: margin:0 auto

margin:0 auto 一般用于有固定宽度的盒子,如果没有宽度,会默认占满父元素的宽度。


背景

背景色:background-color:

背景图:background-image: url(‘…’)

背景平铺:background-repeat:

取值效果
repeat默认,水平和垂直方向平铺
no-repeat不平铺
repeat-x沿水平方向平铺
repeat-y沿垂直方向平铺

背景位置:background-position:x值 y值;

方向名词

  • 水平:left,center,right
  • 垂直:top,center,bottom

数字+px(坐标)

背景相关属性连写

顺序无要求,推荐顺序:background:color image repeat position


元素显示模式

< >可以叫标签,标记,元素。

  • 块级元素

    独占一行,宽度默认是父元素的宽度,高度由内容撑开,可以设置宽高

    如:div,p,h系列,ul,li,dl,dt,dd,form,header

  • 行内元素

    一行可以显示多个,宽度和高度默认由内容撑开,不可以设置宽高

    如:a,apar,b,u,i,s,strong,ins,em,del

  • 行内块元素

    一行可以显示多个,可以设置宽高

    如:image,input,textarea,button,select

元素显示模式转换:

作用:改变元素默认的显示特点,让元素符合布局要求

语法:

属性效果
display: block转成块级元素
display: inline-block转成行内块元素
display: inline转成行内元素

元素的嵌套规范

  • 块级元素一般作为大容器,可以嵌套:文本、块级元素、行内元素、行内块元素等等…

    但是:p标签中不要嵌套div、p、h等块级元素

  • a 标签内部可以嵌套任意元素

    但是:a标签不能嵌套a标签

CSS特性

  • 继承性:子元素默认继承父元素的样式特点

    控制文字属性的都可以继承,如:

    color,font- ,text- ,line-height 。。。。

    但有例外:a标签的color有自己的蓝色,h系列的font-size有自己的字体大小,都会继承失效。

  • 层叠性:覆盖,后面的覆盖前面的

  • 优先级:

    继承 < 通配符选择器 < 标签选择器 < 类选择器 < id选择器 < 行内样式 < !important

    !important可以提升选择器的优先级到最高,写在属性值的后面,分号的前面。

    注:继承的优先级不能用 !important提高,它的优先级最低。

盒子模型

页面中的每一个标签,都可看做是一个“盒子”,通过盒子的视角更方便的进行布局。

盒子构成
  • 内容区域 content

  • 内边距区域 padding

    取值:可以四个,三个,两个,一个值

    padding: 10px 20px 30px 40px (对应上 右 下 左,即逆时针开始数)

    padding: 10px 20px 30px (对应上 左右 下,也是逆时针)

    padding: 10px 20px(对应上下 左右,也是逆时针)

  • 边框区域 border

    如:border:10px solid red ——>10像素,直线,红色(粗细,线段样式,颜色)

    如果只需要一边的边框线,则border-方向即可,如:border-left/ right/ top/ bottom

    线段:直线solid,dashed虚线,dotted点线(其他的线用不着,需要的用图片)

    快捷键:bd

  • 外边距区域 margin

自动内减

box-sizing:border-box

给盒子设置border或paddingl时,盒子会被撑大,需要再次设置参数,手动计算麻烦,所以有了自动内减,浏览器会自动计算,在内容中减去相应大小。

清除默认的内外边距

margin:0;

padding:0;

淘宝网的:

blockquote,body,button,dd,dl,dt,fieldset,form,h1,h2,h3,h4,h5,h6,hr,input,legend,li,ol,p,pre,td,textarea,th,ul{
	margin:0;
	padding:0;
}

京东的:

*{
   	margin: 0;
   	padding: 0;
}
一些问题
  • 塌陷现象:

    场景:相互嵌套的块级元素,子元素设置了margin-top,会同样作用在父元素上。致使父元素一起往下移动。

    解决:

    • 给父元素设置border-top或者padding-top(分隔父子元素的margin-top)
    • 给父元素设置 overflow: hidden
    • 转换成行内块元素
    • 设置浮动

浮动

结构伪类选择器

根据元素在HTML的结构关系查找元素。常用于查找某父级选择器的子元素。

优势:减少对HTML中类的依赖,有利于保持代码的整洁。

选择器说明
E:first-child{}匹配父元素中第一个子元素,且是E元素
E:last-child{}匹配父元素中最后一个子元素,且是E元素
E:nth-child(n){}匹配父元素中第n个子元素,且是E元素
E:nth-last-child(n){}匹配父元素中倒数第n个子元素,且是E元素

n可以写成公式,如4n+1,则会选中第5个,第9个…

伪元素

一般在页面的非主体内容可以使用伪元素。

伪元素作用
::before在父元素内容的最前添加一个伪元素
::after在父元素内容的最后添加一个伪元素

注:必须设置content属性才能生效,伪元素默认是行内元素

例:

<head>   
	<style>
        .father::before{
            content: '老鼠';
        }
        .father::after{
            content: "大米";
        }
    </style>
</head>
<body>
    <!-- 老鼠爱大米 -->
    <div class="father">爱</div>
<body>
浮动特点
  • 浮动元素会脱离标准流(简称:脱标),在标准流中不占位置

    标准流:又称文档流 ,指浏览器在渲染网页时默认采用的一套排版规则。

  • 浮动元素比标准流高半个级别,可以覆盖标准流中的元素

  • 浮动找浮动,下一个浮动元素会在上一个浮动元素后面左右浮动

  • 浮动元素有特殊的显示效果

    • 一行可以显示多个
    • 可以设置宽高

注:浮动的元素不能使用text-align: center或者margin: 0 auto 设置

清除浮动

浮动带来的问题:如果子元素浮动了,此时子元素不占位置,不能撑开标准流的块级父元素。

解决:

  1. 直接设置父元素的高度

    优点:简单

    缺点:有些布局中不能固定父元素高度

  2. 额外标签法

    在父元素内容的最后添加一个块级元素,并对其设置 clear: both。

    缺点:添加了额外标签,会使HTML结构变复杂

  3. 单伪元素清除法

    用伪元素替代了额外标签。

    /*基本写法*/
    .clearfix::after{	/*clearfix常用作需要清除浮动的元素的类名*/
    	content: '';
    	display: block;
    	clear: both;
    }
    /*补充写法*/
    .clearfix::after{
        content: '';
    	display: block;
    	clear: both;
        /*补充的部分是为了在网页中看不见伪元素*/
        height: 0;
        visibility: hidden;
    }
    
  4. 双伪元素清除法

    .clearfix::before,
    .clearfix::after{
    	content: '';
    	display: table;
    }
    .clearfix::after{
    	clear: both;
    }
    

    优点:可以在项目中直接使用,直接给标签加类clearfix即可清除浮动。

  5. 设置overflow:hidden

    直接给父元素设置overflow:hidden即可。

    优点:方便

定位

可以让元素自由的摆放在网页的任意位置,一般用于盒子之间的层叠情况

应用:定位之后的元素层级最高,可以层叠在其他盒子上面,也可以让盒子始终固定在屏幕中的某个位置。

定位种类

属性名:position:

属性值:

定位方式属性值
静态定位static(加不加效果一样)
相对定位relative
绝对定位absolute
固定定位fixed
粘性定位sticky

偏移值:水平和垂直方向各选一个即可(都写的话以left和top为准)

方向属性名属性值含义
水平left数字px距离左边的距离
水平right数字px距离右边的距离
垂直top数字px距离上边的距离
垂直bottom数字px距离下边的距离

属性值 也可以用 % 来设置,这样就是以参照物来看,如 50%就是左边界在参照物的中间。

  • 相对定位——position: relative

    相对于非静态定位的父元素进行移动。

    .box{
        position: relative;
        left: 100px;
        top: 200px;
    }
    
    • 原位置仍在页面 中占位置(没有脱标)
  • 绝对定位——position: absolute

    就近找已经定位的父级为参照进行定位,没有定位的父级,则默认相对于浏览器可视区域(即)进行移动。(子绝父相)

    • 原位置在页面中不占位置(已经脱标)

    • 绝对定位的盒子模式具备行内块特点

    例题:让元素的位置处于浏览器或参照物正中间。

    .box{
    	position: absolute;
        left: 50%;
        margin-left: -150px;/*宽的一半*/
        
        top: 20%;
        margin-top: -200px;/*高的一半*/
        /*transform:translate(-50%,-50%); 上面的margin位移也可以写成这个,位移自己的一半*/
        
        width: 300px;
        heght: 400px
    	background-color: pink;
    }
    
  • 固定定位——position: fixed

    特点:

    • 脱标,不占位置;

    • 参照浏览器窗口改变位置;

    • 具备行内块特点

  • 粘性定位——position: sticky

    可看作是相对定位和固定定位的混合,允许被定位的元素表现的像相对定位一样,直到滚动至某个阈值点为止,之后变为固定。(如:顶部导航栏最多滚动至顶部起10px,之后固定)

    必须指定 top, right, bottom, left 四个阈值其中之⼀,粘性定位才生效。

    .xxx {
        position: sticky;
        top: 30px;
        left: 30px;
    }
    
层级关系

不同布局:标准流 < 浮动 < 定位

而相对,绝对,固定三种定位方式层级相同,谁写在下就覆盖其他的。

一些应用
  • 元素居中:

    1. 先设定width或height;
    2. 将left,right 或 top,bottom 距离设置为0;
    3. 将left,right 或 top,bottom 的margin设置为auto

    绝对定位和固定定位中,margin为auto时,会自动吸收剩余空间。

  • 元素的重叠:

    设置元素的堆叠顺序: z-index

  • 绝对定位、固定定位的补充:

    • 如果没有指定宽高,默认大小是内容的大小;
    • 一定是块盒;
    • 一定不会浮动;
    • 不会发生外边距合并;
    • 会盖住下面常规流的所有内容(浮动元素只会盖住盒子,不会盖住里面的文字图片,因为浮动元素最初是做文字环绕效果的)

装饰

浏览器解析 行内 和 行内块 时当作文字,会根据基线对齐,所以导致常常图片或按钮之类的与文本框或背景对不齐。

垂直对齐

属性名:vertical-align

属性值:

属性值效果
baseline默认,基线对齐
top顶部对齐
middle中间对齐
bottom底部对齐
光标类型

设置鼠标光标在元素上时显示的样式。

属性名:cursor

属性值:

属性值效果
default默认值,通常是箭头
pointer小手,提示可以点击
text工字型,提示可以选择文字
move十字光标,提示可以移动
边框圆角

场景:让盒子四个角变得圆润,增加页面细节。

属性名:border-radius

常见取值:数字+px、百分比(指圆角半径)

赋值规则:从左上角开始,顺时针赋值,没有赋值的看对角

画一个正圆:

盒子为正方形,设置圆角为盒子宽高的一半,即 border-radius: 50%

按钮胶囊:

盒子为长方形,设置圆角为盒子 高度 的一半,即 border-radius: 50%

也可以使用clip-path属性:

clip-path: circle(45%)
溢出部分显示

溢出部分:指盒子内容部分所超出盒子范围的区域。

overflow用于控制内容溢出部分的显示效果,如:显示/隐藏滚动条。

属性名:overflow

属性值:

属性值效果
visible默认值,溢出部分可见
hidden溢出部分隐藏
scroll无论是否溢出,都显示滚动条
auto根据是否溢出,自动显示或隐藏滚动条
元素本身隐藏

让某元素本身在屏幕中不可见,如:鼠标hover之后元素隐藏,用于隐藏/显示子菜单之类的场景

属性:

  • visibility: hidden

    占位置的隐藏效果,用的不多

  • display: none

    脱标的隐藏效果(不占位置)

    display:black 显示元素

元素整体透明

让某元素(包括内容)一起变透明。

属性名:opacity

属性值:0~1之间的数字——0为完全透明

弹性盒子display:flex

flex用于 按行或按列布局元素(一维布局)。

设置容器为flex后,其子元素的 float 、 clear 、 vertical-align 属性将失效。

flex容器的属性:

  • flex-direction :主轴反向

    .box {
        flex-direction: row; /* 默认值,横向从左⾄右排列 */
        flex-direction: row-reverse; /* 横向从右⾄左排列 */
        flex-direction: column; /* 纵向从上到下排列 */
        flex-direction: column-reverse; /* 纵向从下到上排列 */
    }
    
  • flex-wrap: 超出父容器的子容器的排列方式

    flex容器 {
        flex-wrap: wrap; /* ⾥⾯的flex项溢出时会⾃动换⾏ ,第⼀⾏在上⽅*/
        flex-wrap: wrap-reverse; /* ⾥⾯的flex项溢出时会⾃动换⾏ ,第⼀⾏在下⽅*/
    }
    flex项 {
        flex: 200px
    }
    
  • flex-flow:上两者的合并写法

    {
        flex-flow: row wrap;
    }
    /* 等价于 */
    {
        flex-direction: row;
        flew-wrap: wrap;
    }
    
  • justify-content:子容器在主轴的排列方向和空间分配

    flex容器 {
        display: flex;
        justify-content: stretch; /* ⾃动⼤⼩(auto-sized)的flex项会拉伸 */
        justify-content: flex-start; /* 默认值,flex项从flex容器起始线开始排列 */
        justify-content: flex-end; /* flex项从flex容器终⽌线开始排列 */
        justify-content: center; /* flex项在flex容器中间排列 */
        justify-content: space-around; /* 每个flex项左右空间相等 */
        justify-content: space-between; /* flex项间的间隔相等,第⼀个和最后⼀个flex项靠在左右两端 */
    }
    
  • align-items:子容器在交叉轴的排列方向

    flex容器 {
        display: flex;
        align-items: stretch; /* 默认值,flex项会拉伸⾄填满flex容器交叉轴 */
        align-items: flex-start; /* flex项依flex容器的顶部对⻬ */
        align-items: flex-end; /* flex项依flex容器的底部对⻬ */
        align-items: center; /* flex项在交叉轴居中对⻬ */
    }
    
  • align-content:多主轴情况下⼦容器在交叉轴上的对齐和空间分配

    flex-item {
        align-content: stretch; /* 默认值,flex项拉伸占满整个交叉轴 */
        align-content: flex-start; /* flex项依flex容器的顶部对⻬ */
        align-content: flex-end; /* flex项依flex容器的底部对⻬ */
        align-content: center; /* flex项在交叉轴居中对⻬ */
        align-content: space-between; /* 在交叉轴两端对⻬,轴线之间的间隔平均分配 */
        align-content: space-around; /* 轴线间的间隔⽐轴线与边框的间隔⼤⼀倍 */
    }
    

flex项的属性:

  • flex-grow:flex项在可用空间中的拉伸比例(沿主轴方向增长尺寸)

  • flex-shrink:flex项超出主轴时的压缩比例

  • flex-basis:flex项在不伸缩情况下的原始尺寸(默认auto,采用元素内容的尺寸)

  • flex:flex-grow, flex-shrink, flex-basis 的简写属性

    flex项 {
        flex: initial; /* 默认值,相当于 flex: 0 1 auto; 即不可拉伸,可以收缩 */
        flex: auto; /* 相当于 flex: 1 1 auto; 即可以拉伸也可以收缩 */
        flex: none; /* 相当于 flex: 0 0 auto; 即不可拉伸也不可收缩 */
        flex: 正整数; /* 相当于 flex: 1 1 0; 即可以在 flex-basis==0的基础上伸缩
    }
    
    /* 每个flex项占用空间相等, 最小值是200px */
    flex项 {
        flex: 1 200px;
    }
    /* 第二个flex项是其他的2倍 */
    flex项:nth-of-type(2) {
        flex: 2 200px;
    }
    
  • order:flex项的排列顺序, 默认为0,值越小越靠前

    /* 第一个按钮移到主轴的末尾 */
    button:first-child {
        order: 1;
    }
    /* 第二个按钮移动到主轴的最前面 */
    button:last-child {
        order: -1;
    }
    
  • align-self:可使自己覆盖flex容器上设置的 align-items 值

    flex-item {
        align-self: auto; /* 默认值,继承flex容器的align-items值 */
        align-self: flex-start / flex-end / center / stretch; /* 与align-items值的含义类似 */
    }
    

网格布局display:grid

grid布局是二维布局,能把内容按照行与列的格式排版。

基本概念:

  • 网格容器:采用网格布局的区域;
  • 网格项:容器内的子元素;
  • 网格线:网格的水平和垂直的分界线;
  • 网格轨道:相邻两条网格线之间的空间,即行、列。
  • 网格单元格:被网格线围起来的最小单元格。
  • 网格区域:任意四条网格线组成的空间,包含若干单元格。

使用:

  • 定义:默认创建一列或一行的网格

    .container {
        display: grid; /* 设置⽹格布局,一列 */
        display: inline-grid; /* 设置⽹格布局,一行 */
    }
    
  • 设置行列:

    .container {
        display: grid;
        grid-template-columns: 200px 200px 200px;/*设置3个列,宽度各为200px*/
        grid-template-rows: 200px 200px 200px;/*设置3个行,行高各为200px*/
    }
    
    .container {
        display: grid;
        grid-template-columns: 2fr 1fr 1fr /*设置3个列,宽度比为2:1:1*/
    }
    

    可以混搭:

    container {
        display: grid;
        grid-template-columns: 100px auto 2fr;
    }
    
  • 重复构建行列:repeat()

    .container {
        display: grid;
        grid-template-columns: repeat(3, 2fr 1fr); /*相当于2fr 1fr 2fr 1fr */
    }
    
  • 自动多列填充: auto-fill

    container {
        display: grid;
        grid-template-columns: repeat(auto-fill, 100px); /*包含多个100px列宽的网格,将容器填满*/
    }
    
  • 行列最小尺寸: minmax()

    container {
        display: grid;
        grid-template-columns: 1fr 1fr minmax(200px, 1fr); /*列宽不小于200px,不大于1fr*/
    }
    
  • 网格间隙:gap

    container {
        display: grid;
        grid-template-columns: 2fr 1fr
        gap: 20px 50px; /*行间距20px,列间距50px*/
    
  • 网格区域: grid-template-areas

    • 需要填满网格的每个格子
    • 对于某个横跨多个格子的元素,重复写上那个元素grid-area属性定义的区域名字
    • 所有名字只能出现在⼀个连续的区域,不能在不同的位置出现
    • ⼀个连续的区域必须是⼀个矩形
    • 使用 . 符号,让⼀个格子留空
    .container {
        display: grid;
        grid-template-areas: /* 3⾏2列 */
        "header header"
        "sidebar content"
        "footer footer";
        grid-template-columns: 1fr 3fr;
        grid-gap:20px;
    }
        
    header {
        grid-area: header; /* 指定<header>元素的位置 */
    }
        
    article {
        grid-area: content; /* 指定<article>元素的位置 */
    }
        
    aside {
        grid-area: sidebar;
    }
        
    footer {
        grid-area: footer;
    }
    
  • 内容对齐:

    • 设置整个内容区在容器的对齐方式(在容器中设):
      • justify-content 属性是整个内容区域在容器里面的水平位置(左中右),
      • align-content 属性是整个内容 区域的垂直位置(上中下)。
      • place-content 属性是 align-content 属性和 justify-content 属性的合并简写 形式。
    • 设置所有网格项在单元格中的对齐方式(在容器中设):
      • justify-items 属性设置单元格内容的水平位置(左中右),
      • align-items 属性设置单元格内容的垂直位置 (上中下)。
      • place-items 属性是 align-items 属性和 justify-items 属性的合并简写形式。
    • 设置某个网格项在单元格中的对齐方式(在网格项中设)
      • justify-self 属性设置单元格内容的水平位置(左中右),
      • align-self 属性设置单元格内容的垂直位置(上 中下)。
      • place-self 属性是 align-self 属性和 justify-self 属性的合并简写形式。

居中方法总结

水平居中
  • 行盒:

    text-align: center;
    
  • 块盒:

    子元素宽度固定:

    • 方法1: margin: 0 auto

      .inner {
          width: 200px; /* 宽度固定 */
          margin: 0 auto; /* ⽔平居中 */
      }
      
    • 用绝对定位:

      .container {
          width: 500px;
          height: 500px;
          position: relative;
      }
      
      .inner {
          width: 200px; /* 宽度固定 */
          height: 100px;
          position: absolute;
          left: 50%;	/*定位到中线*/
          margin-left: -100px /*外边距设为宽度的一半*/
      }
      

      或者:设定元素的宽度 width ,然后设置左右两边的定位坐标为0(即: left: 0; right: 0 ),并将左右 margin 设 置为 auto 。

      div { /* 假定 div 为 p 的⽗元素 */
          position: relative;
      }
      p {
          width: 200px;
          position: absolute;
          left: 0;
          right: 0;
          margin: 0 auto;
      

    子元素宽度未知:

    • 将子元素设置为行内块元素,然后⽗元素设置 text-align: center 。

      .container {
          width: 500px;
          height: 500px;
          text-align: center; /* 内容居中 */
      }
      .inner{
          display: inline-block; /* 设置为⾏块盒 */
      }
      
  • 多个块盒元素:

    • 方法一: 使⽤ display: inline-block 和 text-align: center

      .container {
          width: 500px;
          height: 500px;
          text-align: center; /* 内容居中 */
      }
      .inner{
          display: inline-block; /* 设置为⾏块盒 */
          width: 100px;
          height: 150px;
      }
      
    • 使用flex布局:

      弹性盒⼦中的 Flex items的⽔平居中可使⽤ justify-content 属性设置,使其中的 Flex items沿主轴对⻬。

      .container {
          width: 500px;
          height: 500px;
          display: flex; 
          justify-content: center /* 在主轴上居中 */
      }
      .inner{
          width: 100px;
          height: 150px;
      }
      
垂直居中
  • 单行行内元素:

    将子元素的行高( line-height )等于高度( height )就可以了。

    .container {
        width: 500px;
        height: 500px;
    }
    .inner{
        display: inline-block; 
        height: 150px;
        line-height: 200px;
    }
    
  • 多行元素:

    • 使用绝对定位:

      .container {
          width: 500px;
          height: 500px;
          position: relative;
      }
      .inner{
          width: 100px;
          height: 100px; /*高度固定*/
          position: absolute;
          top: 50%;	/*定到中线*/
          margin-top: -100px; /*外边距设为高度的一半*/
      }
      

      或设定元素的高度 heigh ,然后设置上下两边的定位坐标为0(即: top: 0; bottom: 0 ),并将上下 margin 设置为 auto 。

      div { /* 假定 div 为 p 的⽗元素 */
          position: relative;
      }
      
      p {
          height: 50px;
          position: absolute;
          top: 0;
          bottom: 0;
          margin-top: auto 0;
      }
      
    • 使用flex布局:

      .container {
          width: 500px;
          height: 500px;
          display: flex;
          align-items: center;
      }
      .inner{
          width: 100px;
          height: 100px;
      }
      
  • 图片文字并排:

    • 使用flex布局:(与上一段代码一致)

    • 给图片设置 vertical-align: middle ,文字盒子设置为 display: inline-block

      * {
      	margin: 0;
          padding: 0;
      }
      
      .container {
          width: 500px;
          height: 500px;
          line-height: 500px;
      }
      .container img {
          display: inline-block;
          vertical-align: middle;
      }
      
      .container p {
          display: inline-block;
      }
      

JavaScript

跨平台、面向对象的脚本语言,用来控制网页行为,网页交互。

js引擎运行

分两步:预解析,再执行代码

  • 预解析:js引擎会把js里面的所有var还有function提升到当前作用域的最前面;
    • 变量预解析(变量提升):把所有的变量声明提升到当前作用域最前面,但不提升赋值操作。
    • 函数预解析(函数提升):把所有的函数声明提升到当前作用域最前面,不会调用函数。
  • 代码执行:按照代码书写顺序从上往下执行。

引入方式

内部脚本:定义在HTML页面中

<script>
	...
</script>

JS代码必须在< script >< /script >之间,可以放置在任何地方,任意数量。一般放在< body >的底部,可改善显示速度,因为脚本执行会拖慢显示。

外部脚本:作为外部JS文件引入

<script src="文件路径"></script>

外部脚本不能包含< script >标签,< script >不能自闭合


基础语法

与java相似,不过语句末的分号;可有可无。

输出语句
window.alert(" ... ")  //写入警告框
document.write(" ... ")  //写入HTML输出
console.log(" ... ")   //写入浏览器控制台
console.dir(object)  //打印元素对象,查看属性,方法
prompt(info) //弹出输入框,用户可以输入
变量

使用 var 关键字来声明变量。(variable)

  • 作用域:全局变量;
  • 变量可以重复声明;
var test = 20;
test = "张三";

JS是弱类型语言,变量可以存放不同类型的值

ES6新增 let 关键字来定义变量,其变量只在let所在的代码块内有效,且不允许重复声明。

ES6新增 const 关键字来声明一个只读的常量。

  • 全局变量 在浏览器关闭时销毁;
  • 局部变量 在程序运行完毕后就销毁;
常量

使用const声量,必须初始化,不能被修改。

const birthday = '11.22.1922'
数据类型
  • 原始类型:

    • number:数字(整数,小数,NaN(Not a Number))

      .toFixed(x) —— 格式化一个数字,x是要保留的小数点后位数。

    • string:字符,字符串,单双引号皆可

    • boolean:布尔类型

    • null:空

    • undefined:变量未初始化时的默认值

    使用typeof运算符可以获取数据类型

    typedef 变量名
    
  • 引用类型

类型转换
  • 其他类型转为number:
    • string:按字符的字面值转为数字,如果字面值不是数字,则转为NaN。一般使用正负号 或 parseInt 进行转化。
    • boolean:true 转为 1, false 转为 0.
  • 其他类型转为boolean:
    • number:0和NaN转为 false,其他转为 true
    • string:空字符串转为 false,其他转为true
    • null:转为false
    • nudefined:转为false
运算符

关系运算符

  • == :先判断类型是否一致,不一致会进行类型转换再比较两个值;
  • === :(全等于)如果类型不一致,会直接返回false,类型一致时才会比较两个值。
函数

函数通过function关键字进行定义。

function functionName(参数列表){
	......
}
//形式参数不需要类型,返回值也不需要定义类型,因为JavaScreipt是弱类型语言
function add(a,b){
    return a + b;
}
    
//定义方式二
var functionName = function(参数列表){...}
var add = function(a,b){
    return a + b;
}
//调用,JS函数调用函数,可以传递任意个参数个数
let result = add(1,2,3);
let result = add(1);
                                  
//立即执行函数,作用:立即执行,同时也独立创建了一个作用域,里面所有变量都是局部变量,避免命名冲突;
(function(){})();
(function(){}());                               //如: 
(function(a,b){
    console(a + b);
})(2,3);
(function(a,b){
    console.log(a + b);
}(2,3));

arguments

是当前函数的内置对象,存储了传递的所有实参。其展示形式是一个伪数组,可以遍历,有lenght属性,有索引,没有push,pop等方法。

内部函数可以访问外部函数的变量:采用链式查找的方式来决定取哪个值,即找最近的——作用域链。

匿名函数:没有名字的函数,通常与事件处理程序一起使用。

const myButton = document.querySelector('button');

myButton.onclick = function() { // 匿名函数
    alert('hello');
}

const textBox = document.querySelector('#text-box');

textBox.addEventListener('keydown', function(event) {
	console.log(`You pressed "${event.key}".`);
});

箭头函数: 尽量使用箭头函数(更简洁)

// 前面的匿名函数也可以写成如下的箭头函数的形式
textBox.addEventListener('keydown', (event) => {
    console.log(`You pressed "${event.key}".`);
});

// 如果函数体只有一条语句,还可以省略花括号
textBox.addEventListener('keydown', (event) => console.log(`You pressed
"${event.key}".`));

// 如果函数只有一个参数,还可以省略参数的括号
textBox.addEventListener('keydown', event => console.log(`You pressed
"${event.key}".`));

// 如果只有一个返回值,且函数体只有一条语句,可省略掉return语句
const originals = [1, 2, 3];
const doubled = originals.map((item) => item * 2);	// 将原始数组的每个元素乘以2得到新的数组

let sum = (a, b) => a + b;
alert(sum(1,3));  // 3

常用对象

Array对象

Array用于定义数组

  • 创建方法:

    • 一、var 变量名 = new Array(元素列表);
    var arr = new Array(1,2,3);
    
    • 二、var 变量名 = [元素列表];
    var arr = [1,2,3]
    
  • 属性:

    length:数组中元素的个数

    push:末尾添加一个元素; unshift:开头添加一个元素

    var arrs = [1,2,3];
    arrs.push(10);
    

    pop:末尾删除一个元素;shift:开头删除一个元素

    indexof:查找元素

    splice:删除多个元素

    arrs.splice(0,2); //参数:从0号位开始删,删2个
    
  • 遍历数组:

    const array = [1,2,3];
    for(const e of array){
        console.log(e);
    }
    
  • 字符串和数组的转化:

    const data = 'aa,bb,cc,dd';
    
    const array = data.split(',');
    
    const string = array.join(',');
    cosnt string2 = array.toString();
    
String对象
  • 创建方法:

    • var 变量名 = new String(s);

    • var 变量名 = s;

      var str = new String("hello");
      
  • 属性:

    length:字符串的长度

  • 方法:

    string[0]:查看指定下标位置的字符

    .chaAt():返回在指定位置的字符

    .indexOf():检索指定字符串

    .trim():去除字符串前后的空格

    .concat(str1,str2…):链接多个字符串,等效+,+更常用

    .substr(start,lenght):从start开始,取lenght个字符

    .splice(a,b):提取下标a到b-1的字符串,只有a下标的话,取下标a之后剩下的字符串。

    .replace(a,b):将a替换成b

    .includes(string):是否包含某字符串

    .startswith(string):是否以某字符串开头

    .endswith(string):是否以某字符串结束

Date对象

和Math不同,Date对象需要实例化后才能使用。

Date() ——(没有参数)返回系统的当前时间

使用 .valueOf() 或 getTime() 来获得总的毫秒数(时间戳),从1970年1月1日到现在。

有更常用的写法:将 +new Date() 实例化,也可获得总的毫秒数。

H5新增的获取方法: Date.now()

方法名说明
getFullYear()获取当年
getMonth()获取当月(0~11)
getDate()获取当天日期
getDay()获取星期几(周期0 到 周六6)
getHours()当前小时
getMinutes()当前分钟
getSeconds()当前秒
自定义对象

格式:

  • var 对象名 = {属性名 : 属性值,… 函数名 : function(参数){} … };

  • 或者使用:var 对象名 = new Object(); 来创造一个空的对象,再利用追加属性的方法,往里面添加数据。

  • 使用构造函数来创建对象:

    function 构造函数名(参数值){ this.属性 = 值; this.方法 = function(){} }————调用时,用“new 构造方法名” 赋值给变量。

    注:构造函数名字首字母要大写

var person = {
	name:"zhangsan",
	age:23,
	eat:function(){
		alert("干饭");
	}
};

var obj = new Object();
obj.name = "zhangsan"

function People(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sing = function(sang){
        sonsole.log(sang);
    }
}
var zhangsan = new People('刘德华'19'男');

调用属性:对象名.属性名 或者 对象名[‘属性名’]

调用方法:对象名.方法名

遍历对象属性:for…in可以对数组或对象进行遍历。

for(var k in obj){	
    console.log(k);	//k变量输出得到的是属性名
    console.log(obj[k]); //obj[k]得到的是属性值
}

JS执行机制

JS是单线程的,即同一时间只能做一件事,这意味着所有任务需要排队,如果JS执行时间过长,会导致页面渲染不流畅。

于是,HTML5提出Web Worker标准,允许JS脚本创建多个线程。于是就有了同步和异步。

  • 同步

    程序之间的执行顺序与排列顺序一致,即同步。

  • 异步

    执行某程序的同时可以执行另一个程序,即异步。

  • 同步任务

    同步任务都在主线程执行,形成一个执行栈

  • 异步任务

    JS的异步是通过回调函数实现的,一般而言,异步任务有三种:

    • 普通事件:如click,resize
    • 资源加载:如load,error
    • 定时器:如setInterval,setTimeout

    异步任务相关的回调函数会添加到任务队列(消息队列)中。

执行机制:

  1. 先执行执行栈中的同步任务;

  2. 遇到异步任务,将其回调函数放入任务队列中;

    异步任务会先交给异步进程处理,只有异步任务的事件发生,或如click点击了,setInterval的时间到了,才会把相关的回调函数放入任务队列。

  3. 等执行栈中的所有同步任务执行完毕后,系统会按次序读取任务队列中的异步任务,使其进入执行栈,开始执行。

    事件循环:主线程不断的重复获取任务,执行任务,再获取任务,反复循环。

BOM对象

Browser Object Model 浏览器对象模型,JS将浏览器的各个组成部分封装成对象:Window,Navigator,Screen,History,Location。

  • Window对象:浏览器窗口对象

    • 获取:直接使用window,其中window. 可以省略。

      window.alert();
      
    • 属性:获取其他四个BOM对象

    • 方法:

      • alert() 显示带有一段消息和一个确认的警告框
      • confirm() 显示带有一段消息和确认和取消的对话框,点确定会返回ture,点取消会返回false
      • setInterval() 按照指定的周期(毫秒计)来调用函数或计算表达式(定时器,循环执行)
      • setTimeout() 在指定的毫秒后调用函数或计算表达式(定时器,只执行一次)
  • Navigator:浏览器对象

    常用:userAgent 返回由客服端发送给服务器的user-agent头部的值。

    使用下面代码尅判断用户在那个终端打开页面,以实现跳转:

    if ((navigator.userAgent.match(/(phone|pad| pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MOOBrowser|JUC|Fennec|wosBrowser|BrowserNG|Webos|Symbian|Windows Phone)/i))){
    	window.location.href =""	//手机
    }else{
    	window.location.href =""	//电脑
    }
    
  • Screen:屏幕对象

  • History:历史记录对象

    • 获取:使用window.history获取,其中window. 可以省略。

      window.history.方法();
      history.方法();
      
    • 方法:

      • back() 后退,加载history列表的前一个url
      • forward() 前进,加载history列表的下一个url
      • go(参数) 参数为n,前进n个页面,参数为-n,后退n个页面
  • Location:地址栏对象

    • 获取:使用window.location获取,其中window. 可以省略。

      window.location.方法();
      location.方法();
      

      URL:同一资源定位符 Uniform Resource Locator

      是互联网上标准资源的地址,互联网的每个文件都有唯一的url,它包含的信息指出文件的位置,以及浏览器应该怎么处理它。

      格式:

      protocol://host[:port]/path/[?query]#fragment
      如:http:/www.baidu.cn/index.html?name=andy&age=18#link
      
      组成说明
      protocol通信协议常用的http, ftp, maito 等
      host主机(域名)
      port端口号,可选,省略时使用方案的默认端口如http的默认端口为80
      path路径,由零或多个 ‘/’ 符号隔开的字符串,一般用来表示主机上的一个目录或文件地址
      query参数,以键值对的形式,通过&符号分隔开来
      fragment片段,#后面内容,常见于链接、锚点
    • 属性:

      location.href 设置或返回完整的url

      location.host 返回主机/域名

      location.port 返回端口号,如果未写则返回空字符串

      location.pathname 返回路径

      location.search 返回参数

      location.hash 返回片段

      案例:第一页面,使用提交表单,url里的参数会携带表单的数据到另一个页面。

      <!-- 第一个页面 -->
      <form action="index.html"
            用户名: <input type="text" name="uname">
      	  <input type="submit" value="登录">
      </form>
      
      <!-- 第二个页面 url为index.html -->
      <!-- 假设表单提交的用户名输入为andy,则使用location.search得到 ?uname=andy -->
      var arr = location.search.substr(1).split('=');  <!-- 去掉问号,再根据等于号做分割,则arr[1]就是名字andy了
      
    • 方法:

      方法返回值
      location.assign(url)跟href一样,可以跳转页面/重定向页面;记录历史
      location.replace(url)替换当前页面,不记录历史,所以不能后退
      location.reload()重新加载页面,相当于刷新(部分有缓存的,从缓存获取数据);如果参数为true,为强制刷新(从服务器重新获取数据)
页面加载事件
  • onload事件是等页面内容全部加载完毕 才会开始执行。

    • document.addEventListener(‘load’, function(){ })

    • window.onload = function(){ } //传统方式只有最后一个onload生效

  • DOMContentLoaded 是只需DOM加载完毕,不包括flash, css等 就可以执行,速度比load快一些。

    • document.addEventListener(‘DOMContentLoaded’, function(){})
窗口大小调整
  • window.addEventListener(“resize”, function(){})

  • window.onreasize = function(){ }

常用于响应式布局

定时器
  • setTimeout(函数,延迟时间)

    延迟设定的时候后调用函数。

    时间单位:毫秒,省略时默认为0毫秒;

    浏览器中经常需要多个定时器,为了区分,一般把定时器赋值给一个变量,以起一个名字。

    setTimeout也称为回调函数callback。想click点击事件里的函数也叫回调函数。

    • 清除定时器:clearTimeout (定时器)
  • setInterval(函数,间隔时间)

    每隔设定的时间调用以此函数。

    • clearInterval(定时器)

DOM对象

Document Object Model,文档对象模型,JS将标记语言的各个组成部分封装为对象,分别有:Document,Element,Attribute,Text,Comment。

JS通过DOM,能对HTML进行操作:改变内容、样式,对事件做出反应,添加和删除元素。

  • Document:整个文档对象

  • Element:元素对象

    • 获取:使用document对象的方法获取(document.方法 或者 document对象.方法)

      • getElementByld

        根据id属性值取,返回一个Element对象

      • getElementsByTagName

        根据标签名称获取,返回Element对象数组

      • getElementsByName

        根据name属性值获取,返回Element对象数组

      • getElementsByClassName

        根据class属性值获取,返回Element对象数组

      • querySelector(选择器)

        返回指定选择器的第一个元素对象,选择器需要加符号以区分: .类名 #id 标签名

      • querySelectorAll (选择器)

        返回指定选择器的所有元素对象集合,选择器需要加符号以区分

      • 获取特殊元素:bod y,html

        document.body :返回body元素对象

        document.documentElement:返回html元素对象

  • Attribute:属性对象

  • Text:文本对象

  • Comment:注释对象


改变元素内容
  • 普通盒子修改,如div标签:

    • 对象.innerHTML

      可以识别html标签,保留空格和换行

      var div = document.querySelector('div');
      div.innerHTML = //修改后的内容或对象
      
    • 对象.innerText

      不识别html标签,去除空格和换行

  • 表单内容修改:

    对象**.value** = 修改内容

  • 修改样式:

    • 行内样式操作(适合样式较少的情况):

      对象.style.样式/属性 = 修改内容

    • 类名样式操作(适合样式复杂的情况):

      对象.className = 新类名(修改内容放在新类名里)

      <head>
          <style>
              .change{
                  background-color: red;
                  font-size: 25px;
              }
          </style>
      </head>
      <script>
          对象.className = 'change';//覆盖原先的类名
          对象.className = '原类名 新类名';//不会覆盖原先的类名,存在多类名
      </script>
      
  • 禁用元素:

    对象.disabled = true;


元素操作

获取属性值:

  • element.属性 —— 获取内置属性值
  • element.getAttribute(‘属性’) —— 主要获取自定义的属性

设置属性值

  • element.属性 = ‘值’ —— 设置内置属性
  • element.setAttribute(‘属性’,‘值’) —— 主要设置自定义属性

移除属性

  • element.removeAttribute(‘属性’)

H5规定:

设置自定义属性要以 data- 开头,并且赋值。如:

<div data-index = "1"></div>
element.setAttribute('data-index', 2);

H5新增的获取自定义属性的方法(ie11后支持):

使用dataset存放所有以data开头的自定义属性,通过dataset时属性名不用加 data- 前缀。

  • element.dataset.属性名
  • element.dataset[‘属性名’]

如果自定义属性中由多个 -链接的单词,获取时使用驼峰命名法,去掉 -

阻止链接跳转:添加 javascript:;

<a href='javascript:;'> </a>

节点操作

节点:网页中所有内容都是节点 (标签,属性,文本,注释),在DOM中,节点用node表示。

基本属性:

  • nodeType(节点类型)

    • 元素节点 nodeType为1
    • 属性节点 nodeType为2
    • 文本节点 nodeType为3(文本节点包括文字,空格,换行等)

    实际主要操作的是元素节点

  • nodeName(节点名称)

  • nodeValue(节点值)

节点层级:

  • 父节点: 节点 .parenNode

    返回指定节点的最近的父 节点,如果没有父节点则返回null

  • 子节点:节点 .childNodes

    返回指定节点的子节点的集合,包括元素节点,文本节点等,需要再处理后才能得到元素节点,较麻烦,一般不使用。

    可以使用 节点 .children 来获取子元素节点,虽然不是标准规定,但各浏览器2都支持。

    首个字节点和最后一个子节点:

    • 节点 .children[0] ——首个
    • 节点.children[节点.children.lenght - 1] ——最后一个
  • 下一个兄弟元素节点: 节点. nextElementSibling

    上一个兄弟元素节点: 节点. previousElementSibling

创建节点: document.createElement(‘新节点名’)

添加节点:

  • 父节点.appendChild(新建的节点) —— 添加到父节点的子节点列表的末尾
  • 父节点 .insertBefore(‘新建的节点’,指定节点) ——添加到指定子节点的前面

删除节点: 父节点.removeChild(要删除的子节点)

复制节点: 节点.cloneNode() ——如果括号里参数为空 或者为 false,则为浅拷贝,即只复制节点本身,不复制里面的内容;括号里为true,则为深拷贝,复制标签和里面的子节点。


事件

事件:HTML事件是发生在HTML元素上的"事情”。比如:按钮被点击,鼠标移动到元素之上,按下键盘按键。

对象.事件 = function(){
    事件处理
}
组成
  • **事件源:**事件被触发的对象
  • **事件类型:**如何触发/发生了什么事件
  • **事件处理程序:**通过函数赋值的方式进行

事件监听:JavaScript可以在事件被侦测到时执行代码。

事件绑定

新方式——事件监听方式:

对象. addEventListener(事件类型,处理函数,flag)

事件监听方式:

事件类型 为字符串形式,如:click,mouseover,注意不再带on

第三个参数flag,如果为false或省略,那么事件流处于冒泡阶段,如果为true,则为捕获阶段。实际开发中,很少使用事件捕获,不过有些事件没有冒泡,如:onblur,onfocus,onmouseenter,onmouseleave

传统方式:

  • 方法一:通过HTML标签中的事件属性进行绑定(耦合)

    <input type = "button" onclick='on()' >
    function on(){
    	alet("我被点了");
    }    
    
  • 方法二:通过DOM元素属性绑定(推荐)

    <input type = "button" id = "btn" >
    
    const btn = document.querySelector("#btn");
    
    btn.addEventListener('click', () => alert("我被点了"));
    
删除事件

事件监听方式:对象. removeEventListener(事件类型,处理函数)

传统方式:对象. 事件类型 = null

DOM事件流

分为3个阶段:

  1. 捕获阶段:由最顶层节点开始,然后逐级向下传播到最具体(最小)的元素。
  2. 当前目标阶段
  3. 冒泡阶段:事件开始由最具体(最小)的元素接收,然后逐级传播到最顶层阶段。

image-20220312204641336

事件对象

event 是一个事件对象,写在监听函数的小括号里当形参,事件对象只有事件发生了才会存在,是系统自动创建的,不需要传递实参进去。

事件对象:是事件的一系列相关数据的集合,跟事件相关的,如鼠标点击里就包含了鼠标坐标之类的信息。

事件对象可以自己命名,如event,evt,e

属性方法

属性/方法说明
e.target返回触发事件的对象
e.type返回事件的类型
e.preventDefault()阻止事件的默认行为,如阻止链接跳转
e.stopPropagation()阻止冒泡

在监听函数中,e.target指触发事件的对象,this指绑定该事件的对象。

阻止事件冒泡

事件对象.stopPropagation()

低版本浏览器:window.event.cancelBubble = true;

if(e && e.stopPropagation){//浏览器是否认识新特性
    e.stopPropagation();
}else{
    window.event.cancelBubble = true;
}
阻止默认行为

阻止默认行为: event.preventDefault()

事件委托

对于子节点要设置相同的事件监听,可以不用在子节点上单独设置,而是设置在其父节点上,然后利用冒泡原理影响设置的每个子节点。

作用:只操作了以此DOM,提供了程序的性能。

如果只想操作触发事件的那个子节点,可以利用e.target 得到触发事件的那个子节点

常见事件

使用传统方式window. 时,事件前要加on,如onclick,onfocus

click:对象被点击

focus:鼠标获得焦点

blur:鼠标失去焦点

mouseover:鼠标经过

mouseout:鼠标离开

mousemove:鼠标移动触发

mouseup:鼠标弹起触发

mousedown:鼠标按下触发

submit:确认按钮被点击(常用于v 表单提交)

change:域的内容被改变

keydown:某个按键被按下

keyup:某个按键被松开

keypress:某个按键被按下,但不识别ctrl shift等功能键

mouseover 和 mouseenter 区别:

mouseover 经过自身盒子会触发,经过子盒子还会触发;

mouseenter 只会经过自身盒子触发


鼠标事件对象

属性:

e.clientX / e.clientY —— 鼠标相对于浏览器窗口的X/Y坐标

e.pageX / e.pageY —— 鼠标相对于文档页面的X/Y坐标

e.screenX / e.screenY —— 鼠标相对于电脑屏幕的X/Y坐标

禁止鼠标右键菜单

document.addEventListener('contextmenu',function(e){
    e.preventDefault();
})

禁止鼠标选中

document.addEventListener('selectstart',function(e){
    e.preventDefault();
})

键盘事件对象

属性:

keyCode:识别按下的是哪个键

事件keyup和keydown不区分字母大小写,keypress区分大小写

例子:按s键,使搜索框获得焦点

var search = document.queryAelector('input');
document.addEventListener('keyup',function(e){
	if(e.keyCode === 83){
        search.focus();
    }	
})

网页特效

元素偏移量 offset
  • 获得元素距离带有定位父元素的位置

  • 获得元素自身的大小(宽度高度)

    注意:返回的数值都不带单位

常用属性:

offset系列属性作用
element.offsetParent返回该元素带有定位的父元素,如果父级都无定位则返回body
element.offsetTop返回元素相对带有定位父元素上方的偏移
element.offsetLeft返回元素相对带有定位父元素左边框的偏移
element.offsetWidth返回自身包括padding、边框、内容区的宽度,返回数值不带单位
element.offsetHeight返回自身包括padding、边框、内容区的高度,返回数值不带 单位

offset与style的区别:

offsetstyle
offset可以得到任意样式表中的样式值style只能得到行内样式表中的样式值
offset系列获得的数值是没有单位的style.width获得的是带有单位的字符串
offsetWidth包含padding+border+widthstyle.width获得不包含padding和border的值
offsetWidth等属性是只读属性,只能获取不能赋值style.width是可读写属性,可以获取也可以赋值

所以,想要获取元素大小位置,用offset更合适;想要给元素更改值,则需要用stye改变

元素可视区 client

client翻译:客户端。可以动态获取元素可视区的相关信息

client系列属性作用
element.clientTop返回元素上边框的大小
element.clientLeft返回元素左边框的大小
element.clientWidth返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位
element.clientHeight返回自身包括padding、内容区的高度,不含边框,返回数值不带单位
元素滚动 scroll

scroll翻译:滚动。可以动态的得到该元素的大小,滚动距离等

scroll系列属性作用
element.scrollTop返回被卷去的上侧距离,返回数值不带单位
element.scrollLeft返回被卷去的左侧距离,返回数值不带单位
element.scrollWidth返回自身实际的宽度,不含边框,返回数值不带单位
element.scrollHeight返回自身实际的高度,不含边框,返回数值不带单位

常用方法:window.scroll(x, y) 滚动窗口至文档的特定位置

offset系列经常用于获得元素位置 offsetLeft offsetTop

client 经常用于获取元素大小 clientWidth clientHeight

scroll 经常用于获取滚动距离 scrallTop scrollLeft

注意:页面滚动的距离通过 window.pagexoffset 获得

动画函数封装

动画实现原理:通过定时器setInterval() 不断移动盒子位置。

步骤:

  1. 获取盒子当前位置
  2. 让盒子在当前位置加上一个移动距离
  3. 利用定时器不断重复操作,并加一个结束的条件

注意 此元素需要添加定位,才能使用element.style.left

如:

//将移动效果封装成函数,调用即可
//obj是传入的对象,target是要移动的距离,callback为传入的其他函数,用于实现额外的效果
function animate(obj, target,callback){
    //防止同一对象同时开启多个定时器(只保留当前一个定时器执行)
    clearInterval(obj.timer); 	
    //将timer作为传入对象obj的属性,可以避免开辟过多空间
    obj.timer = setInterval(function(){
        var step = (target - obj.offsetLeft) / 10;	//实现缓动效果,速度从快到慢
        step = step > 0 ? Math.ceil(step) : Math.floor(step); //去掉小数点
    if(obj.offsetLeft >= target){
        cleatInterval(obj.timer); 	//停止定时器
        callback && callback;	//如果回调函数存在就执行回调函数
    }
    //步长值变化
    obj.style.left = obj.offsetLeft + s + 'px';},15);
}

var div = document.querySelector('div');
animate(div, 300);

因为动画函数经常被使用,所以可以将其单独封装到一个JS文件里面,使用的时候应用这个JS文件即可。

节流阀

作用:当上一个函数动画内容执行完毕,再取执行下一个函数动画,让事件不会连续过快触发。

思想:利用回调函数,添加一个变量来控制,所著函数和解锁函数。

var flag = true;
if(flag){
    flag = false;
    ......   //动画执行
    flag = true;
}

本地存储

本地存储特性:

  • 数据存储在用户浏览器中
  • 设置、读取方便、甚至页面刷新不丢失数据
  • 容量较大,sessionStorage约5M、localStorage约20M
  • 只能存储字符串,可以将对象 JSON.stringify0编码后存储

sessionStorage

特点:

  • 生命周期为关闭浏览器窗口
  • 在同一个窗口页面下数据可以共享
  • 以键值对的形式存储使用

方法:

  • 存储数据:

    sessionStorage.setItem(key, value)

  • 获取数据:

    sessionStorage.getItem(key)

  • 删除数据:

    sessionStorage.removeItem(key)

  • 删除所有数据

    sessionStorage.clear()


localStorage

特点:

  • 生命周期永久生效,除非手动删除否则关闭页面也会存在
  • 可以多窗口(页面)共享(同一浏览器可以共享)
  • 以键值对的形式存储使用

方法:

  • 存储数据:

    localStorage.setItem(key, value)

  • 获取数据:

    localStorage.getItem(key)

  • 删除数据:

    localStorage.removeItem(key)

  • 删除所有数据

    localStorage.clear()

jQuery

jQuery是JavaScript库,封装了JS中的DOM操作。

j 指 JavaScript,query 查询

优点:

  • 轻量级。核心文件才几十kb,不会影响页面加截速度
  • 跨浏览器兼容。基本兼容了现在主流的浏览器
  • 链式编程、隐式迭代
  • 对事件、样式、动画支持,大大简化了DOM操作
  • 支持插件扩展开发。有着丰富的第三方的插件,例如:树形菜单、日期控件、轮播图等
  • 免费、开源

入口函数

等DOM接口渲染完毕即可执行内部代码,相当于原生js中的DOMContentLoaded

$(function(){
	....  //此处是页面DOM加载完成的入口
});
对象

顶级对象 $

是 j Q u e r y 的别称,在代码中也可以使用 j Q u e r y 代替 是jQuery的别称,在代码中也可以使用jQuery代替 jQuery的别称,在代码中也可以使用jQuery代替

是 j Q u e r y 的顶级对象,相当于原生 J S 中的 w i n d o w 。把元素利用 是jQuery的顶级对象,相当于原生JS中的window。把元素利用 jQuery的顶级对象,相当于原生JS中的window。把元素利用包装成jQuery对象,就可以调用jQuery的方法。

jQuery对象 和 DOM对象

用原生JS获取过来的对象就是DOM对象。

用 jQuery 方式获取过来的对象是jQuery)对象。本质:通过$把DOM元素进行了包装

DOM对象只能使用原生的 JS 属性和方法

jQuery对象只能使用 jQuery 方法

//DOM对象
var myDiv = document.querySelect("div");
//jQuery对象
$("div");

jQuery对象 和 DOM对象 相互转换:

//DOM对象转换为jQuery对象
$(DOM对象)
//jQuery对象转换为DOM对象
$("div")[index]
$("div").get(index)
常用API
选择器操作

选择器: $(“选择器”)

**筛选选择器: **

语法用法说明
:first$(“li:first”)获取第一个li元素
:last$(“li:last”)获取最后一个li元素
:eq(index)$(“li:eq(2)”)获取的li元素中,选择下标为2的元素
:odd$(“li:odd”)获取的li元素中,选择下标为奇数的元素
:even$(“li:even”)获取的li元素中,选择下标为偶数的元素

筛选方法:

语法用法说明
parent()$(“li”).parent()查找父级
children(selector)$(“ul”).children(“li”)相当于$(“u1>li”),最近一级(亲儿子)
find(selector)$(“ul”).find(“li”);相当于$(“ul li”), 后代选择器
siblings(selector)$(“.first”).siblings(“li”);查找兄弟节点,不包括自己本身
nextAll ([expr])$(“.first”).nextAll ()查找当前元素之后所有的同辈元素
prevAll (class)$(“.last”).prevAll ()查找当前元素之前所有的同辈元素
hasClass (class)$(‘div’).hasclass(“protected”)检查当前的元素是否含有某个特定的类,如果有,则返回true
eq (index)$(“li”).eq(2);相当于$(“1i:eq(2)”), index从0开始

jQuery使用排他思想:

//例:思想点击 背景颜色跟随
$(function(){
    //隐式迭代,给所有按钮绑定点击事件
    $("button").click(function(){
        //当前元素设置背景颜色
        $(this).css("background","red");
        //其余兄弟去掉背景颜色
        $(this).siblings("button").css("background","");
    });
})

链式编程:

//原来写法
$("div").css("color","red");
$("div").siblings().css("color","");
//链式编程写法,节省代码量,比较简洁
$("div").css("color","red").siblings().css("color","");

样式操作

设置样式:

  • $(“选择器”).css(“属性”) —— 只写属性,则返回属性值

  • $(“选择器”).css(“属性”,“值”) ——设置一组样式,属性必须加引号,值如果是数字可以不用单位和引号

  • $(“选择器”).css( {color: “red”, font-size: 20}); ——参数是对象形式,可以设置多组样式,属性和值用冒号隔开,属性可以不加引号

DOM元素设置样式需要显式迭代,而jQuery对象是以伪数组形式存储,它在设置样式时会自动遍历内部DOM元素,即隐式迭代。

类操作:

  • 添加类:$(“div”).addClass(“类名”)
  • 删除类:$(“div”).removeClass(“类名”)
  • 切换类:$(“div”).toggleClass(“类名”)

可以先为某个类设置样式,需要时再通过类操作来修改样式。


效果

显示隐藏

  • **show **( [speed], [easing], [fn] ) —— 显示

    参数都可以省略,则无动画直接显示

    speed:预定字符串(“slow”,“normal”,“fast”)或动画时长的毫秒值;

    easing:用来指定切换效果,默认”swing“,可选参数“linear”;

    fn:回调函数,在动画完成时执行,每个元素执行一次。

    (一般都是不加参数直接显示隐藏的)

  • **hide **( [speed, [easing], [fn]] ) —— 隐藏

  • toggle ( [speed, [easing], [fn]] ) —— 切换显示和隐藏

滑动

  • slideDown ( [speed, [easing], [fn]] ) —— 下拉
  • slideUp ( [speed, [easing], [fn]] ) —— 上拉
  • slideToggle ( [speed, [easing], [fn]] ) ——切换上下拉动

淡入淡出

  • fadeIn ( [speed, [easing], [fn]] ) —— 淡入

  • fadeOut ( [speed, [easing], [fn]] ) —— 淡出

  • fadeToggle ( [speed, [easing], [fn]] ) —— 切换淡入淡出

  • fadeTo ( [speed, opacity, [easing], [fn]] ) —— 修改透明度

    speed速度为动画时长,必须写,

    opacity透明度必须写,

  • animate ( params, [speed], [easing], [fn] ) —— 自定义动画

    params: 样式选择,以对象形式传递,必须写

    $(function(
    	{$("button").click(function({
      		$("div").antimate({
            	legt:200
       		});
    	})
    })
    
事件切换

hover 是鼠标经过和离开的复合写法

//两个函数分别是鼠标经过和鼠标离开时分别调用的函数
$(".nav>li").hover(function(){},function(){})
//只写一个函数,则鼠标经过和离开都会调用这个函数
$(".nav>li").hover(function(){
    $(this).children("ul").slideToggle();
})
停止排队

动画效果一旦触发就会执行,如果多次触发,就会使多个动画同时执行。

停止排队:stop() —— 用于停止动画效果。可以写到动画的前面,相当于停止上一次的动画。


属性操作

获取元素固有属性的值:prop(“属性名”)

设置固有属性值: prop(“属性”,“属性值”)

元素固有属性就是元素本身自带的属性,如< a >里的href,< input > 里的type。

获取元素自定义属性的值:attr(“属性”)

设置元素自定义属性的值:attr(“属性”,“属性值”)

类似原生的getAttribute()和setAttribute()

数据缓存data():可以在指定的元素上存取数据,并不会修改DOM元素结构,一旦页面刷新,之前存放的数据都将被移除。

获取:data(“属性”) ;设置:data(“属性”,“值”)


内容文本值

普通元素内容:html(),相当于原生innerHTML。

获取:html()

设置:html(“内容”)

普通元素文本内容:text(),相当于原生innerText。

获取:text()

设置:text(“内容”)

表单的值 val() ,相当于原生value

获取:val()

设置:val(“内容”)


元素操作

jQuery隐式迭代是对同一类元素做同样的操作,如果想要给同一元素做不同操作,仍需要遍历。

$("div".each(function(index,domEle){...}))

index是每个元素的索引号,domEle是每个DOM元素对象,注意不是jquery对象,要用jquery方法,需要进行对象转化。

$.each(object, function(index, element){})

object可以是任何对象,所以$each主要用于数据处理,如数组,对象;

尺寸、位置操作

尺寸:

语法说明
width() / height()只算width / height
innerWidth() / innerHeight()包含padding
outerWidth() / outerHeight()包含padding、border
outerWidth(true) / outerHeight(true)包含padding、borde、margin

位置:

offset()

设置或返回距离文档的位置(偏移),跟父级没有关系。offset().left 获取距离文档左侧的距离, offset().top 获取距离文档顶部的距离

  • scrollTop()

设置或返回被卷去的头部。

同样有 scrollTop().left 和 scrollTop().top 两个属性。

事件
注册事件
element.事件(function(){})
//例:
$("div").click(function(){
    ...
})
事件处理

on() 绑定事件:匹配元素上绑定一个或多个事件的处理函数。

element.on(events, [selector], fn)

events:一个或多个用空格分割的事件类型;

selector:元素的子元素选择器;

fn:回调函数;

//绑定多个事件,多个处理程序
$("div").on({
    mouseenter: function(){
        $(this).css("background", "skyblue");
    },
    click: function(){
        $(this).css("background","purple")
    }
});
//如果绑定事件的处理程序相同:
$("div").in("mouseover mouseout", function(){
    $(this).toggleClass("current");
});
//可以实现事件委派,把原来加给子元素的事件绑定到父元素上。
//点击事件绑定在ul上,但触发对象是li
$("ul").on("click","li",function(){
    ....
})
//on()可以给动态生成的元素绑定事件,而原来的 $("").事件(fn)不能给动态创建的元素绑定事件
$("ul").on("click","li",function(){
    ....
})
var li = $("<li>我是后来创建的</li>");
$("ul").append(li);

one() 绑定事件,只触发一次

$("div").one("click",function(){
    ...
})

off() 解绑事件

$("div").off();  //移除div身上的所有事件
$("div").off("click");   //移除div身上的点击事件
("ul").off("click","li");	//接触li的事件委托

**trigger() 自动触发事件 ** :

element.trigger("type");
//如:
$("p").on("click", function(){
    ...
});
....    
$("p").trigger("click"); //此时自动触发事件
//触发事件,但不触发元素的默认行为
element.triggerHandler("type");

布局

数据可视化

ECharts是一个使用JavaScript实现的开源可视化库,兼容大部分浏览器,底层依赖矢量图形库ZRender。

XML

xml 是可扩展的标记性语言。

作用:

  • 主要用于存储数据,这些数据具有自我描述性;
  • 作为项目或者模块的配置文件;
  • 作为网络传输数据的格式(现在改为使用 JSON 为主了)。

语法

  • 文档声明

    xml声明:

    <?xml version="1.0" encoding="UTF-8"?>
    
    • version 是版本的意思,
    • encoding 是编码,
    • standalone=“yes/no” 表示这个 xml 文件是否是独立的 xml文件
  • 元素(标签)

    元素是指从开始标签到结束标签的内容。(与html一样)

    注意大小写敏感,元素都必须闭合,必须有根元素

    命名规则:

    • 可以包含字母,数字,其他字符(包括中文);
    • 不能以数字或标点符号开头;
    • 不能包含空格;

    元素(标签) 分 单双标签:

    • 单标签: < 标签名 属性=”值“ 属性=”值“ … />
    • 双标签:< 标签名 属性=”值“ …> 文本或子标签 </标签名>
  • xml 属性

    与html非常类似,注意属性的值要用 引号” “ 包起来。

  • 文本区域(CDATA 区)

    说明此区域是纯文本内容,不需要xml语法解析

    <![CDATA[
    	文本内容,不会被xml解析
    ]]>
    

XML解析技术

dom4j 解析技术是第三方公司的技术,需要到其官网上下载dom4j的jar包,导入到idea的库中。

// 需要分四步操作:
// 第一步,通过创建 SAXReader 对象。来读取 xml 文件,获取 Document 对象
// 第二步,通过 Document 对象。拿到 XML 的根元素对象
// 第三步,通过根元素对象。获取所有的 book 标签对象
// 第四小,遍历每个 book 标签对象。然后获取到 book 标签对象内的每一个元素,再通过 getText() 方法拿到起始标签和结束标签之间的文本内容
@Test
public void readXML() throws DocumentException {
	// 第一步,通过创建 SAXReader 对象。来读取 xml 文件,获取 Document 对象
	SAXReader reader = new SAXReader();
	Document document = reader.read("src/books.xml");
	// 第二步,通过 Document 对象。拿到 XML 的根元素对象
	Element root = document.getRootElement();
	// 打印测试
	// Element.asXML() 它将当前元素转换成为 String 对象
	// System.out.println( root.asXML() );
	// 第三步,通过根元素对象。获取所有的 book 标签对象
	// Element.elements(标签名)它可以拿到当前元素下的指定的子元素的集合
	List<Element> books = root.elements("book");
	// 第四小,遍历每个 book 标签对象。然后获取到 book 标签对象内的每一个元素,
	for (Element book : books) {
	// 测试
	// System.out.println(book.asXML());
	// 拿到 book 下面的 name 元素对象
	Element nameElement = book.element("name");
	// 拿到 book 下面的 price 元素对象
	Element priceElement = book.element("price");
	// 拿到 book 下面的 author 元素对象
	Element authorElement = book.element("author");
	// 再通过 getText() 方法拿到起始标签和结束标签之间的文本内容
	System.out.println("书名" + nameElement.getText() + " , 价格:" + priceElement.getText() + ", 作者:" + authorElement.getText());
	}
}

JSON

JSON ( JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。

JSON 采用完全独立于语言的文本格式,而且很多语言都提供了对 json 的支持(包括 C, C++, C#, Java, JavaScript, Perl, Python 等)。 使得 JSON 成为理想的数据交换格式。

  • 其语法格式简单,层次结构鲜明,现多用于作为 数据载体,在网络中进行数据传输。

轻量级是相较xml而言;

数据交换指的是客户端和服务器之间业务数据的传递格式

定义:

  • json由键值对组成,用大括号包围;
  • 每个键都用双引号包起来;
  • 键与值之间用冒号分割。
var jsonObj = {
    "key1":12,
    "key2":"abc",
    "key3":true,
    "key4":[11,"arr",false],
    "key5":{
        "key5_1" : 551,
        "key5_2" : "key5_2_value"
    },
    "key6":[{
            "key6_1_1":6611,
            "key6_1_2":"key6_1_2_value"
        },{
            "key6_2_1":6621,
            "key6_2_2":"key6_2_2_value"
        }]
};

访问:

json本身是一个对象,访问: json对象.key

alert(typeof(jsonObj));// object json 就是一个对象
alert(jsonObj.key1); //12
alert(jsonObj.key2); // abc
alert(jsonObj.key3); // true
alert(jsonObj.key4);// 得到数[11,"arr",false]
// json 中 数组值的遍历
for(var i = 0; i < jsonObj.key4.length; i++){
	alert(jsonObj.key4[i]);
}
alert(jsonObj.key5.key5_1);//551
alert(jsonObj.key5.key5_2);//key5_2_value
alert( jsonObj.key6 );// 得到 json 数组

// 取出来每一个元素都是 json 对象
var jsonItem = jsonObj.key6[0];
alert( jsonItem.key6_1_1 ); //6611
alert( jsonItem.key6_1_2 ); //key6_1_2_value

方法:

json有两种存在形式:

  • json对象:用于操作json中的数据;
  • json字符串:用于客户端和服务器之间数据交换时;

转换方法:

json.stringify()   //json对象 转换为 json字符串
json.parse()	//json字符串 转换为 json对象

解析转换:

jackson:

Spring MVC 默认采用Jackson解析Json,尽管还有一些其它同样优秀的json解析工具,例如Fast Json、GSON,但是出于最小依赖的考虑,也许Json解析第一选择就应该是Jackson。



Fastjson:

Fastjson是阿里巴巴提供的一个Java语言编写的高性能功能完善的SON库,是目前ava语言中最快的 JSON库,可以实现Java对象和 JSON字符串的相互转换。但拓展性不高。

//java对象 转 json字符串
String java对象 = JSON.toJSONString(对象);
//json字符串 转 java对象
User user = JSON.parseObject(jsonStr,User.class); //User为某一个类

gson的一些使用(还是建议使用jackson):

javaBean和json互转:

使用GSON,它是Google提供的用来在Java对象和 JSON数据之间进行映射的Java类库。

  • 创建gosn对象
  • gosn.toJson(json对象)
  • gson.fromJson(json字符串,javaBean类名.class)
public void test(){
    Person person = new Person(1,"zzc");
    // 创建 Gson 对象实例
    Gson gson = new Gson();
    // toJson 方法可以把 java 对象转换成为 json 字符串
    String personJsonString = gson.toJson(person);
    System.out.println(personJsonString);
    
    // 第一个参数是 json 字符串
    // 第二个参数是转换回去的 Java 对象类型
    Person person1 = gson.fromJson(personJsonString, Person.class);
    System.out.println(person1);
}

list和json互转:

  • 创建gosn对象
  • gosn.toJson(list)
  • gson.fromJson(json字符串,list.getclass())

map和json互转:

  • 创建gosn对象
  • gosn.toJson(map)
  • gson.fromJson(json字符串, new TypeToken<HashMap<对应类,对应类>>(){}.getType() );

Tomcat

Web服务器:是一个应用程序(软件),对HTTP协议的操作进行封装,使得程序员不必直接对协议进行操作,让Web开发更加便捷。主要功能是 “提供网上信息浏览服务”。

Tomcat :是Apache软件基金会一个核心项目,是一个开源免费的轻量级Web服务器,支持Servlet / JSP 和少量JavaEE规范。

  • 启动Tomcat服务器:

    到bin目录下,双击startup.bat启动,双击shutdown.bat关闭

  • 修改Tomcat的端口号:

    mysql默认的端口号是3306,Tomcat默认的端口号是8080,HTTP协议默认的端口号是80;

    修改:到conf目录下,修改server.xml配置文件

    <!-- 在69行附近 -->
    <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
    <!-- 修改其中的port="8080"即可 -->
    

Tomcat 部署项目:将项目放置到webapps目录下,即部署完成。

  • 一般JavaWeb项目会被打成war包,然后将war包放到webapps目录下,Tomcat会自动解压缩war文件

第二种部署方式:

项目不需要放在webapps下,可以放在任何地方;

找到 Tomcat 下的 conf 目录\Catalina\localhost\ 下,创建配置文件,如abc.xml,配置文件内容如下:

<!-- Context 表示一个工程上下文 
	path 表示工程的访问路径:/abc
	docBase 表示你的工程目录在哪里
	即url中输入path,也就是/abc,路径就会到docBase那里
-->
<Context path="/abc" docBase=" " /
  • 当浏览器地址栏输入访问地址为: http 😕/ip:port/ 时,也就是没有工程名时,默认访问webapps下的ROOT工程;
  • 当浏览器地址栏输入访问地址为: http 😕/ip:port/ 工程名/ 时,也就是没有资源名时,默认访问工程下的index.html页面;

在IDEA中创建Maven Web项目:

image-20220224192255613

  • 编译后的 java字节码文件和resources的资源文件,放到WEB-INF 下的 classes目录下;
  • pom.xml中依赖坐标对应的jar包,放入WEB-INF下的Iib目录下;
    • WEB-INF是一个受服务器保护的目录,浏览器无法直接访问此目录的内容;

创建方式:

image-20220224192858734

image-20220224193548166

WEB-INF放到webapp目录下


在IDEA中使用Tomcat:

  • 方法一:集成本地Tomcat

image-20220224194330615

  • 方法二:Tomcat Maven插件

image-20220224194749638

    <build>
        <plugins>
            <!--Tomcat插件-->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>80</port> <!--默认是8080-->
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>


Servlet

JavaWeb三大组件:Servlet、.Filter、Listener;

Servlet是 Java提供的一门 动态web资源开发技术。

Servlet是javaEE规范之一,也就是一个接口,将来我们需要定义Servlet类实现Servlet接口,并由web服务器运行Servlet。

Servlet可以接收客户端发过来的请求,并响应数据给客户端;

public interface Servlet

使用servlet:

  1. 创建Web项目,导入Servlet依赖坐标
   	<dependencies>
       <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api </artifactId>
            <version>3.1.0</version>
        	<scope>provided</scope>			<!-- Tomcat有servlet的jar包,所以这里的servlet不要带到运行环境去,因此使用provided;-->
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
  	</dependencies>
  1. 创建:定义一个类,实现Servlet接口,并重写接口中所有方法。

    public class ServletDemo1 implements Servlet{
    	public void service(){}
    	....
    }
    
  2. 配置:在类上使用@WebServlet注解,配置该Servlet的访问路径

    @WebServlet("/demo1")
    public class ServletDemo1 implements Servlet{}
    
  3. 访问:启动Tomcat,浏览器输入URL访问该Servlet

    http://localhost:8080/web-demo/demo1
    

执行流程

image-20220228110919940


生命周期

Servlet运行在Servlet容器(web服务器)中,其生命周期由容器来管理,分为4个阶段:

  1. 加载和实例化:默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象

  2. 初始化:在Servlet实例化之后,容器将调用Servlet的 init()方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次

    可以在注解中修改init()调用的时机:

    @WebServlet(urlPatterns="/demo",loadOnStartup=1)
    //负整数:第一次被访问时创建 Servlet对象
    //0或正整数:服务器启动时创建Servlet对象,数字越小优先级越高
    
  3. 请求处理/服务:每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理。

  4. 服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法完成资源的释放。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收


Servlet体系结构

image-20220228113253739

开发B/S架构的web项目,都是针对HTTP协议,所以自定义的Servlet都是继承HttpServlet。

@WebServlet("/demo1")
public class ServletDemo1 extends HttpServlet{
    @Override
    protected void doGet((HttpServletRequest req,HttpServletResponse resp){
		//TOOD Get 请求方式处理逻辑
    }
	@override
	protected void doPost(HttpServletRequest req,HttpservletResponse resp){
	//TOOD Post 清求方式处理逻辑
    }
}

ServletConfig类

ServletConfig类是Servlet程序的配置信息类。

  • Servlet程序和ServletConfig对象都是由Tomcat负责创建;
  • Servlet程序默认第一次访问时创建,而每个Servlet程序创建时都会创建一个对应的ServletConfig对象。

方法:

  • getServletName() —— 获取Servlet程序的别名 servlet-name 的值
  • getInitParameter(" ") —— 获取初始化参数 init-param (括号里写param-name的值,得到param-value值)
  • getServletContext() —— 获取ServletContext对象

注: 如果重写了HttpServlet类的init方法,一定要调用父类的init(ServletConfig),因为HttpServlet类的init方法里,保存了ServletConfig对象,不然的话,调用getInitParameter(" ")方法会报错。

web.xml配置:设置servlet程序的别名,访问路径

<!-- servlet 标签给 Tomcat 配置 Servlet 程序 -->
<servlet>
	<!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) -->
	<servlet-name>HelloServlet</servlet-name>
	<!--servlet-class 是 Servlet 程序的全类名-->
	<servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
	<!--init-param 是初始化参数-->
	<init-param>
		<!--是参数名-->
		<param-name>username</param-name>
		<!--是参数值-->
		<param-value>root</param-value>
	</init-param>
	<!--init-param 是初始化参数-->
	<init-param>
		<!--是参数名-->
		<param-name>url</param-name>
		<!--是参数值-->
		<param-value>jdbc:mysql://localhost:3306/test</param-value>
	</init-param>
</servlet>

<!--servlet-mapping 标签给 servlet 程序配置访问地址-->
<servlet-mapping>
	<!--servlet-name 标签的作用是告诉服务器,我当前配置的地址给哪个 Servlet 程序使用-->
	<servlet-name>HelloServlet</servlet-name>
<!--
	url-pattern 标签配置访问地址 <br/>
		/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径 <br/>
		/hello 表示地址为:http://ip:port/工程路径/hello <br/>
-->
	<url-pattern>/hello</url-pattern>
</servlet-mapping>

ServletContext

  • ServletContext是一个接口,它表示Servlet上下文对象
  • 一个 web工程中只有一个 ServletContext 对象实例
  • ServletContext 对象是一个域对象
  • ServletContext 是在 web工程部署启动的时候创建。在 web工程停止的时候销毁;

域对象: 是可以像Map一样存取数据的对象,这里的域指存取数据的操作范围,即整个web工程;

//获取ServletContext对象
ServletContext context = getServletConfig().getServletContext();
//直接get也可以,本质上也是调用getServletConfig().getServletContext();
ServletContext context = getServletContext();

方法:

  • getInitParameter(“…”) —— 获取 web.xml 中配置的上下文参数 context-param (括号里写param-name值,得到param-value值)

  • getContextPath() —— 获取当前的工程路径,格式: /工程路径

  • getRealPath(“/”) —— 获取工程部署后在服务器硬盘上的绝对路径

    getRealPath(“/”) —— 工程部署的路径

    getRealPath(“/css”) —— 工程下 css 目录的绝对路径

  • 像 Map 一样存取数

    存数据取数据删除数据
    Mapput()get()remove()
    域对象setAttribute()getAttribute()removeAttribute()
<!-- web.xml中相关配置信息  -->
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
	<param-name>username</param-name>
	<param-value>context</param-value>
</context-param>
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
	<param-name>password</param-name>
	<param-value>root</param-value>
</context-param>

HTTP协议

HTTP协议是 客户端和服务器之间通信时要发送的数据,需要遵守的规则; HTTP 协议中的数据又叫报文。

  • 请求 Request:客户端给服务器发送数据。
    • GET请求
    • POST请求
  • 响应 Response:服务器给客户端回传数据。

GET请求的组成:

  • 请求行: 请求方式 请求的资源路径 请求的协议版本号

    如: GET /servlet_1/a.html HTTP/1.1

  • 请求头:以键值对的形式组成

    • Accept: 告诉服务器,客户端可以接收的数据类型;
    • Accept-Language:告诉服务器,客户端可以接收的语言类型,如:zh_CN指中文中国,en_US指英文美国;
    • User-Agent:就是浏览器的信息;
    • Accept-Encoding:告诉服务器,客户端可以接收的数据编码(压缩)格式
    • Host:表示请求的股务器ip和端口号
    • Connection:告诉服务器诗求连接如何处理
      • Keep-Alive :告诉服务器回传数据不要马上关闭,保持一小段时间的连接;
      • Closed:马上关闭

POST请求的组成:

  • 请求行: 请求方式 请求的资源路径 请求的协议版本号

  • 请求头:

    • Accept:表示客户端可以接收的数据类型;

    • Accept-Language:表示客户端可以接收的语言类型;

    • Referer:表示请求发起时,浏览器地址栏中的地址(从哪来)

    • User-Agent:表示浏览器的信息

    • Content-Type:表示发送的数据的类型

      如:application/x-www-form-ur lencoded : 表示提交的数据格式是 name=value&name=value,然后对其进行urI编码,使非英文内容转换为:%xx%xx

      multipart/form-data :表示以多段的形式提交数据给服务器 (以流的形式提交,用于上传)

    • Content-Lnegth:表示发送的数据的长度

    • Cache-Control:表示如何控制缓存, no-cache 指不缓存

  • 空行 (请求头和请求体之间隔一空行)

  • 请求体:发给服务器的数据

区分GET请求和POST请求:

POST请求有:

  • form 标签中 method=post

GET请求有:

  • form 标签 method=get
  • a标签
  • link标签引入css
  • Script标签引入js文件
  • img标签引入图片
  • iframe 引入html页面
  • 在浏览器地址栏中输入地址后敲回车

响应 的组成:

  • 响应行:响应的协议和版本号 状态码 状态描述符
  • 响应头:以键值对形式组成
    • Server:表示服务器的信息;
    • Content-Type:表示响应体的数据类型;
    • Content-Length:响应体的长度;
    • Date:请求响应的时间(格林时间);
  • 空行
  • 响应体:(就是回传给客户端的数据)

常用响应码:

  • 200 —— 请求成功
  • 302 —— 请求重定向
  • 404 —— 表示请求服务器已收到,但所要的数据不存在/请求地址错误
  • 500 —— 表示服务器已经收到请求,但服务器内部错误(错误代码)

MIME类型

MIME类型 指的是HTTP协议中的数据类型 —— Multipurpose Internet Mail Extensions 多功能Internet邮件扩充服务。

格式:大类型/小类型

常见的MIME类型:

文件后缀MIME类型
超文本标记语言文本.html .htmtext/html
普通文本.txttext/plain
RTF文本.rtfapplication/rtf
GIF图形.gifimage/gif
JPEG图形.jpeg .jpgimage/jpeg
au声音文件.auaudio/basic
MIDI音乐文件.mid .midiaudio/midi, audio/x-midi
RealAudio音乐文件.ra .ramaudio/x-pn-realaudio
AVI文件.avividio/mpeg
GZIP文件.gzvideo/x-msvideo
TAR文件.tarapplication/x-gzip
MPEG文件vapplication/x-tar

HttpServletRequest类

每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。 然后传递到 service 方法(doGet 和 doPost)中给我们使用。

而通过 HttpServletRequest 对象,可以获取到所有 请求 的信息。

方法:

  • getRequestURI() 获取请求的资源路径
  • getRequestURL() 获取请求的统一资源定位符(绝对路径)
  • getRemoteHost() 获取客户端的ip地址
  • getHeader() 获取请求头
  • getParameter() 获取请求的参数
  • getParameterValues() 获取请求的参数(多个值的时候使用)
  • getMethod() 获取请求的方式GET或POST
  • setAttribute(key,value) 设置域数据
  • getAttribute(key) 获取域数据
  • getRequestDispatcher() 获取请求转发对象

如果doPost中获取数据出现中文乱码,可以设置请求体的字符集为UTF-8:

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	req.setCharacterEncoding("UTF-8");	//设置字符集要写在获取请求参数之前,否则不生效
}

HttpServletResponse类

HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传递给 Servlet 程序去使用。

HttpServletRequest表示请求过来的信息,HttpServletResponse 表示所有响应的信息,;我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse对象来进行设置。

两个输出流:

  • 字节流 getOutputStream() —— 常用于下载(传递二进制数据)
  • 字符流 getWriter() —— 常用于回传字符串(常用)

两个流同时只能使用一个。

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //resp.setContentType("text/html; charset=UTF-8");  用于解决响应中文乱码:它会同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头;注:要在获取流对象之前使用才有效;    
    // 要求: 往客户端回传 字符串 数据。
    PrintWriter writer = resp.getWriter();
    writer.write("response's content!!!");
    }
}

请求重定向

是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问,叫请求 重定向。(因为之前的地址可能已经被废弃)

response.sendRedirect("新地址");

请求转发/内部转发:

意思是:服务器收到请求后,从一个资源跳转到另一个资源。即服务器内部转发

request.getRequestDispatcher("demo07").forward(request,response);

image-20220329114857941

//办事处1 —— Servlet1程序
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
	// 获取请求的参数(办事的材料)查看
	String username = req.getParameter("username");
	System.out.println("在 Servlet1(柜台 1)中查看参数(材料):" + username);
    
	// 给材料 盖一个章,并传递到 Servlet2(柜台 2)去查看
	req.setAttribute("key1","柜台 1 的章");
    
    // 问路:Servlet2(柜台 2)怎么走
    // 请求转发必须要以斜杠打头,/ 斜杠表示地址为:http://ip:port/工程名/ , 映射到 IDEA 代码的 web 目录
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
    // RequestDispatcher requestDispatcher = req.getRequestDispatcher("http://www.baidu.com");
    
    // 走向 Sevlet2(柜台 2)
    requestDispatcher.forward(req,resp);
}

//办事处2 —— Servlet2程序
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
    // 获取请求的参数(办事的材料)查看
    String username = req.getParameter("username");
    System.out.println("在 Servlet2(柜台 2)中查看参数(材料):" + username);
    
    // 查看 柜台 1 是否有盖章
    Object key1 = req.getAttribute("key1");
    System.out.println("柜台 1 是否有章:" + key1);
    
    // 处理自己的业务
    System.out.println("Servlet2 处理自己的业务 ");
}

保存作用域

作用域一般有四个:

  • page(页面级别,现在几乎不用)

  • request(一次请求响应范围)

    重定向中,客户端实际发起了两次请求;所以在第一次请求中在request的作用域中保存数据,数据不会保存到第二次请求。

    //在 /Servlet_1 中
    req.setAttribute("key","value");
    req.sendRedirect("/Servlet_2");
    //在 /Servlet_2 中
    System.out.println(req.getAttribute("key"));	//打印null,不能得到结果
    
  • session(一次会话范围)

    //在 /Servlet_1 中
    req.getSession().setAttribute("key","value");
    req.sendRedirect("/Servlet_2");
    //在 /Servlet_2 中
    System.out.println(req.getAttribute("key"));	//能得到结果
    
  • application(整个应用程序范围)

    //这里假设/Servlet_1和/Servlet_2是两个不同的用户
    //在 /Servlet_1 中
    ServletContext application = req.getServletContext();
    application.setAttribute("key","value");
    req.sendRedirect("/Servlet_2");
    //在 /Servlet_2 中
    ServletContext application = req.getServletContext();
    System.out.println(application.getAttribute("key"));	//能得到结果
    

文件传输

文件上传:

<form action="url地址" enctype="multipart/form-data" method="提交方式" name="名称">
    
<!-- 如果要设置上传文件,需要加上 enctype="multipart/form-data" ,然后在 input的属性type值为"file" -->

multipart/form-data表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
查看http协议内容时,context-type部分有属性boundary:表示每段数据的分隔符,分隔符是由浏览器每次都随机生成,它就是每段上传数据的分界符。

文件接收:

<!-- 上传文件的表单 -->
<form action="http://192.168.31.74:8080/09_EL_JSTL/uploadServlet" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username" /> <br>
    头像:<input type="file" name="photo" > <br>
    <input type="submit" value="上传">
</form>
//fileupload类库的适用:
//需要导入两个jar包:commons-fileupload.jar 和 commons-io.jar
//解析上传的数据
public class Servlet_1 extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
        //1 先判断上传的数据是否多段数据(只有是多段的数据,才是文件上传的)
        if (ServletFileUpload.isMultipartContent(req)) {
        // 创建 FileItemFactory 工厂实现类
        FileItemFactory fileItemFactory = new DiskFileItemFactory();
        // 创建用于解析上传数据的工具类 ServletFileUpload 类
        ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
        try {
            // 解析上传的数据,得到每一个表单项 FileItem
            List<FileItem> list = servletFileUpload.parseRequest(req);
            // 循环判断,每一个表单项,是普通类型,还是上传的文件
            for (FileItem fileItem : list) {
                if (fileItem.isFormField()) {
                    // 普通表单项
                    System.out.println("表单项的 name 属性值:" + fileItem.getFieldName());
                    // 参数 UTF-8.解决乱码问题
                    System.out.println("表单项的 value 属性值:" + fileItem.getString("UTF-8"));
                } else {
                    // 上传的文件
                    System.out.println("表单项的 name 属性值:" + fileItem.getFieldName());
                    System.out.println("上传的文件名:" + fileItem.getName());
                    fileItem.write(new File("e:\\" + fileItem.getName()));
                }
            }
        } catch (Exception e) {
        	e.printStackTrace();
        }
    }
}

文件下载:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 获取要下载的文件名
        String downloadFileName = "2.jpg";
        //2. 获取要下载的文件内容(通过ServletContext对象可以获取)
        ServletContext servletContext = getServletContext();
        //获取要下载的文件类型
        String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
        //4.在回传前,通过响应头告诉客户端返回的数据类型
        response.setContentType(mimeType);
        //5.告诉客户端收到的数据是用于下载的,还是适用响应头的
        response.setHeader("Content-Disposition","attachment;filename=文件名");
        //输入流获取文件内容
        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
        //获取响应的输出流
        OutputStream outputStream = response.getOutputStream();
        //读取输入流中全部数据,复制给输出流,输出给客户端
        IOUtils.copy(resourceAsStream, outputStream);
}

Filter

Filter表示过滤器,可以把对资源的请求拦截下来;

通常用过滤器完成一些通用的操作,比如:权限控制、统一编码处理、敏感字符处理等等…

JavaWeb三大组件:Servlet、.Filter、Listener;

使用:实现Filter接口 ,并重写三个方法;注意是javax.servlet. 下的Filter接口。

@WebFilter("/*")       //设置拦截路径, “/*” 指拦截全部
public class Filter_1 implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
         // 放行前逻辑(已被拦截)
        filterChain.doFilter(servletRequest, servletResponse);     //放行
        // 放行后逻辑
    }
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化
    }

    @Override
    public void destroy() {
        // 销毁
    }
}

Filter执行流程:

执行放行前逻辑——放行——访问资源——执行放行后逻辑


Filter拦截路径配置

@WebFilter("...")   //括号中设置拦截路径
  • 拦截具体的资源: /index.jsp 只有访问index.jsp时才会被拦截;
  • 目录拦截:/user/* 访问/user下的所有资源都会被拦截;
  • 后缀名拦截: *.jsp 访问后缀名为jsp的资源都会被拦截;
  • 拦截所有: /*

如果要拦截多个页面或分散文件,要在括号例写urlPatterns属性,然后在里面写属性的值,逗号分割;

@WebFilter(urlPatterns = {"...","...","..."})  

过滤器链

一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤器链。

例如:对同一应用,如果执行了2个过滤器,执行顺序为:Filter1的放行前逻辑,Filter1放行,Filter2放行前逻辑,Filter2放行,Filter2放行后逻辑,Filter1放行后逻辑。(类似递归)

过滤器的执行顺序按 过滤器的类名的字典序排序;

FilterConfig类

Filter过滤器的配置文件类

filterConfig.getFilterName()  //获取过滤器的名称
filterConfig.getInitParameter("")   //获取过滤器中配置的初始化参数 

Listener

监听器,是在application,session,request三个对象创建、销毁或者往其中添加修改删属性时自动执行代码的功能组件。

Listener分类:JavaWeb中提供了8个监听器

监听器分类监听器名称作用
ServletContext监听ServletContextListener用于对ServletContext对象进行监听(仓创建、销毁)
ServletContextAttributeListener对ServletContext对象中属性的监听(增别改属性)
Session监听HttpSessionListener对Session对象的整体状态的监听(创建、销毁)
HttpSessionAttributeListener对Session?对象中的属性监听(增删改属性)
HttpSessionBindingListener监听对象于Sessionl的绑定和解除
HttpSessionActivationListener对Session数据的钝化和活化的监听
Request监听ServletRequestListener对Requestx对象进行监听(创建、销毁)
ServletRequestAttributeListener对Reque5t对象中属性的监听(增别改属性)

使用

实现ServletContextListener接口,并重写两个方法;

@WebListener
class a implements ServletContextListener{
    @Override
    public void contextInitialized(ServletContextEvent sce) {
      //加载资源
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //释放资源
    }
}

会话

会话:用户打开浏览器,访问wb服务器的资源,会话建立,直到有一方断开连接, 会话结束(浏览器关闭)。在一次会话中可以包含多次请求和响应

会话跟踪:服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据

由于HTTP协议是无状态的,每次浏览器发出请求,服务器都会将请求视为新的请求,所以需要会话跟踪技术。

  • 客户端会话跟踪技术:Cookie
  • 服务端会话跟踪技术:Session

cookie

客户端会话技术,将数据保存到客户端,以后客户端每次请求都携带Cookie数据进行访问。

客户端第一次向服务端发送请求,服务器会生成一个cookie对象,和响应一起发给客户端;客户端之后向服务端发送请求时,会携带cookie一起发送,服务端识别cookie就会知道客户端的身份。

使用:

//发送:
//创建Cookie对象,设置数据
Cookie cookie = new Cookie("key","value");

//发送Cookie到客户端,使用response对象
response.addCookie(cookie);

//获取:
//获取客户端所有Cookie,使用request对象
Cookie[] cookies = request.getCookies();
//遍历数组,获取每一个Cookie对象
//使用Cookie对象方法获取数据
for (Cookie cookie : cookies){
	String name = cookie.getName();
	if("key".equals(name)){
		String value = cookie.getValue();
		break;
    }
}

//修改Cookie的值
//方法一:创建一个同名的Cookie对象,直接覆盖
Cookie cookie = new Cookie("key","newValue");
resp.addCookie(cookie);
//方法二:找到对应的Cookie对象,用setValue()修改
Cookie cookie = CookieUtils.findCookie("key2", req.getCookies());
if (cookie != null) {
    cookie.setValue("newValue2");
    resp.addCookie(cookie);	//修改后还要通知客户端保存修改
}

原理:

Cookie的实现是基于HTTP协议的;
响应头:set-cookie
请求头:cookie

注:

Cookie存活时间:

  • 默认情况下,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁。

  • setMaxAge(int seconds) :设置Cookie存活时间

    • 正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储;到时间自动删除。

    • 负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁;

    • 零:删除对应Cookie;

Cookie存储中文:

  • 默认情况不能存储中文;如果要存中文,则需要进行转码:可用URL编码

session

服务端会话跟踪技术:将数据保存到服务端;

JavaEE提供HttpSession接口,来实现一次会话的多次请求之间的 数据共享功能。

使用:

//获取Session对象
HttpSession session = request.getSession();
//Session对象功能:
void setAttribute(String name,Object o) //存储数据到session域中
Object getAttribute(String name) //根据key,获取值
void removeAttribute(String name) //根据key,删除该键值对
boolean isNew() //判断是不是刚创建的

原理:

Session技术,底层是基于Cookie技术实现的。

如果客户端发送的请求没有携带cookie,则服务端会新创建一个session和cookie,cookie的key值session的id值相同,然后session保存在服务端,cookie返回给客户端。

如果客户端发送的请求携带了cookie,则服务端会通过cookie的key值找到对应保存的session,然后返回相应的cookie。

注意事项

Session 钝化、活化:

  • 钝化:在服务器正常关闭后,Tomcats会自动将Session数据写入硬盘的文件中;
  • 活化:再次启动服务器后,从文件中加载数据到Session中;

Session销毁:

  • 默认30分钟无操作,销毁;

    <!-- 在web.xml中配置所有session的超时时长 -->
    <session-config>
    	<session-timeout>30</session-timeout>
    </session-config>
    
    //也可以使用session的方法设置单个
    void setMaxInactiveInterval(int interval) //设置session的超时时间,单位为秒,设置负数表示永不超时
    int getMaxInactiveInterval()  //获取超时间
    void invalidate()	//立即超时,销毁
    

Cookie和Session异同点:

Cookie和Session都是来完成一次会话内多次请求间数据共享的;
区别:

  • 存储位置:Cookie是将数据存储在客户端,Session将数据存储在服务端;
  • 安全性:Cookie不安全,Session安全;
  • 数据大小:Cookie最大KB,Session无大小限制;
  • 存储时间:Cookie可以长期存储,Session默认30分钟;
  • 服务器性能:Cookie不占服务器资源,Session占用服务器资源;

JSP

  • 概念:Java Server Pages —— Java服务端页面

  • 一种动态的网页技术,其中既可以定义HTML、JS、CSS等静态内容,还可以定义Java代码的动态内容;

    主要用于代替Servlet程序回传html页面的数据,因为Servlet程序回传html页面非常繁琐,开发维护成本都较高。

    JSP本质上就是一个Servlet程序,JSP在被访问时,由JSP容器(Tomcat)将其转换为Java文件(Servlet),再编译,最终对外提供服务的其实就是字节码文件

  • JSP = HTML + Java

JSP有很多缺点:

书写麻烦:特别是复杂的页面;
阅读麻烦;
复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE;
占内存和磁盘:JSP会自动生成java和 .class文件占磁盘,运行的是 .class文件占内存;
调试困难:出错后,需要找到自动生成的,java文件进行调试;
不利于团队协作:前端人员不会java,后端人员不精HTML;

后续逐渐被ajax+html替代


步骤:

导入JSP坐标——创建jsp文件——编写html标签和java代码

<!-- jsp坐标 -->
<dependencies>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>		<!-- tomcat有,注意要写成provided -->
    </dependency>
</dependencies>

语法

page指令:

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>

属性:

  • language —— 表示 jsp 翻译后是什么语言文件。只支持 java。
  • contentType —— 表示 jsp 返回的数据类型是什么。也是源码中 response.setContentType()参数值
  • pageEncoding —— 表示当前 jsp 页面文件本身的字符集。
  • import —— 跟 java 源代码中一样。用于导包,导类。
  • 给out输出流使用的两个属性(不建议改):
    • autoFlush —— 设置当 out 输出流缓冲区满了之后,是否自动刷新冲级区。默认值是 true。
    • buffer —— 设置 out 缓冲区的大小。默认是 8kb。
  • errorPage —— 设置当 jsp 页面运行时出错,自动跳转去的错误页面路径。路径一般以斜杠开头,表示请求地址为 “http 😕/ip:port/工程路径/ ” 映射到代码的Web目录
  • isErrorPage —— 设置当前 jsp 页面是否是错误信息页面。默认是 false。如果是 true 可以 获取异常信息。
  • session —— 设置访问当前 jsp 页面,是否会创建 HttpSession 对象。默认是 true。
  • extends —— 设置 jsp 翻译出来的 java类继承谁

脚本:

JSP脚本:用于在JSP页面内定义Java代码

分为:

  • 代码脚本 <% … %>

    用于编写需要的功能。内容会直接放到 jspService()方法之中。

    <%--2.代码脚本----for 循环语句--%>
    <table border="1" cellspacing="0">
        <%
        	for (int j = 0; j < 10; j++) {
        %>
            <tr>
                <td>第 <%=j + 1%>行</td>
            </tr>
        <%
        	}
        %>
    </table>
    
  • 表达脚本 <%= … %>

    用于在jsp页面上输出数据。内容会放到out.print()中,作为out.print0的参数

    注:表达脚本中的表达式不能以分号结束。

  • 声明脚本 <%! … %>

    可以给 jsp 翻译出来的 java 类定义属性和方法甚至是静态代码块,内部类等。

    内容会放到 _jspService()方法之外,被类直接包含。

    注:声明脚本很少使用

    <%!
    	private Integer id;
    	private String name;
    	private static Map<String,Object> map;
    %>
    <%!
        static {
            map = new HashMap<String,Object>();
            map.put("key1", "value1");
            map.put("key2", "value2");
            map.put("key3", "value3");
    }
    %>
    

输出

response.getWriter输出 和 out输出 都用于设置返回给客户端的内容。由于jsp翻译后,底层源码都是用out来输出的,所以一般统一用out来进行输出。

注释:

html注释: < !-- – >

java注释:<% // 单行 java 注释 /* 多行 java 注释 */ %>

jsp注释: <%-- --%>

其中html注释和java注释会被翻译到java源代码中,jsp注释不会。


对象

jsp的内置对象:是指 Tomcat 在翻译 jsp 页面成为 Servlet 源代码后,内部提供的九大对象,叫内置对象。

request —— 请求对象
response —— 响应对象
pageContext —— jsp的上下文对象
session —— 会话对象
application —— ServletContext.对象
config —— ServletConfig对象
out —— jsp输出流对象
page —— 指向当前jsp的对象
exception —— 异常对象


jsp四大域对象:

pageContext —— request —— session —— application

域对象可以像Map一样存取数据,其范围和Servlet的四个作用域相同。


常用标签

静态包含(常用)

<%@ include file="" %>

<!-- 例如  --> 
<%@ include file="/include/footer.jsp"%>

file属性指定要包含的jsp页面的路径,地址的第一个斜杠为 “ http 😕/ip:port/工程路径/ ” 映射到web目录。

注:静态包含不会翻译被包含的jsp页面,而是直接把页面拷贝到包含的位置执行输出。

动态包含(少用)

<jsp:include page=""> </jsp:include>

<!-- 例如  --> 
<jsp:include page="/include/footer.jsp">
    <jsp:param name="username" value="bbj"/>
    <jsp:param name="password" value="root"/>
</jsp:include>

page属性是指定要包含的 jsp页面的路径。

注:动态包含会 直接翻译被包含的jsp页面,同时还可以传递参数。

转发标签(常用)

<jsp:forward page=""> </jsp:forward>

page属性设置请求转发的路径

相当于:request.getRequestDispatcher(“/xxxx.jsp”).forward(request,reponse);

EL表达式

Expression Language ,即表达式语言,用于简化 JSP页面内的java代码。

主要功能:获取数据;

语法:

${表达式}

JavaWeb中的四大域对象:

  • page:当前页面有效;
  • request:当前请求有效;
  • session:当前会话有效;
  • application:当前应用有效;

——EL表达式获取数据,会依次从4个域中寻找,直到找到为止。(四个域的范围逐渐增大,即page范围最小,application最大)

  • empty运算

    判断一个数据是否为空,如果为空则输出true。

    值为null,空串时,Object类型数组长度为0时,list集合中元素个数为0,map集合元素个数为0,这些情况均视为空。

    <% 
    	request.setAttribute("obj", null); 
    %>
    ${empty obj}
    
  • 关系运算: == != < > <= >=

  • 逻辑运算:&& || !

  • 算数运算: + - * / %

  • 三元运算

  • 点运算 中括号运算:

    点运算 输出Bean对象中某个属性的值;

    中括号运算 输出有序集合中某个元素的值;

    <body>
        <%
            Map<String,Object> map = new HashMap<String, Object>();
            map.put("a.a.a", "aaaValue");
            map.put("b+b+b", "bbbValue");
            map.put("c-c-c", "cccValue");
            request.setAttribute("map", map);
        %>
        ${ map['a.a.a'] } <br>
        ${ map["b+b+b"] } <br>
        ${ map['c-c-c'] } <br>
    </body>
    

11个隐含对象:

变量类型作用
pageContextPageContextImpl获取jsp九大内置对象
pageScopeMap<String,Object>获取pageContext域中的数据
requestScopeMap<String,Object>获取Request域的数据
sessionScopeMap<String,Object>获取Session域的数据
applicationScopeMap<String,Object>获取ServletContext域的数据
paramMap<String,String>获取请求参数的值
paramValuesMap<String,String[]>获取多个请求参数的值
headerMap<String,String>获取请求头的信息
headerValuesMap<String,String[]>获取多个请求头的信息
cookieMap<String,Cookie>获取当前请求的Cookie信息

获取4个特定域的属性:

pageScopepageContext域
requestScopeRequest域
sessionScopeSession域
applicationScopeServletContext域
<body>
    <%
        application.setAttribute("key2", "application");
    %>
	${ applicationScope.key2 }
</body>

pageContext的使用

<body>
    <!--
    request.getScheme() 它可以获取请求的协议
    request.getServerName() 获取请求的服务器 ip 或域名
    request.getServerPort() 获取请求的服务器端口号
    getContextPath() 获取当前工程路径
    request.getMethod() 获取请求的方式(GET 或 POST)
    request.getRemoteHost() 获取客户端的 ip 地址
    session.getId() 获取会话的唯一标识
    -->
	<%
        pageContext.setAttribute("req", request);
    %>
    <%= request.getScheme() %> <br>
    1.协议: ${ req.scheme }<br>
    2.服务器 ip:${ pageContext.request.serverName }<br>
    3.服务器端口:${ pageContext.request.serverPort }<br>
    4.获取工程路径:${ pageContext.request.contextPath }<br>
    5.获取请求方法:${ pageContext.request.method }<br>
    6.获取客户端 ip 地址:${ pageContext.request.remoteHost }<br>
    7.获取会话的 id 编号:${ pageContext.session.id }<br
</body>

JSTL标签

JSTL标准标签库(Jsp Standarded Tag Library),使用标签取代JSP页面上的Java代码。

步骤:

1.导入坐标:

<dependency>
	<groupId>jstl</groupId>
	<artifactId>jstl</artifactId>
	<version>1.2</version>
</dependency>
<dependency>
	<groupId>taglibs</groupId>
	<artifactId>standard</artifactId>
	<version>1.1.2</version>
</dependency>

2.在JSP页面上引入JSTL标签库:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

JSTL有五个功能不同的标签库:

功能范围URI前缀
核心标签库(常用)http 😕/java.sun.com /jsp/jstl/corec
格式化http 😕/java.sun.com/jsp/jstl/fmtfmt
函数http 😕/java.sun.com/jsp/jstl/functionsfn
数据库(不适用)http 😕/java.sun.com/jsp/jstl/sqlsql
XML(不适用)http 😕/java.sun.com/jsp/jstl/xmlx

标签:

if

<c:if test="true或false">
    ....
</c:if>

<c:if test="${status==0}">
    hello world!
</c:if>

forEach

<!-- items是被遍历的容器 var是遍历生产的临时变量 -->
<c:forEach items="${brands}" var="brand" varStatus="xx">
    <tr align="center">
        <td>$(xx.index)</td>  <!-- varStatus表示下标序号,xx.index表示从0开始,xx.count表示从1开始 -->
        <td>$(brand.brandName)</td>
        <td>S(brand.companyName)</td>
        <td>$(brand.description)</td>
    </tr>
</c:forEach>

<!-- 相当于.. -->
for(Brand brand : brands){
	Integer id = brand.getld();
	String imgUrl = brand.getlmgUrl();
	String brandName = brand.getBrandName();
	String companyName = brand.getCompanyName();
}

<!-- begin是开始数,end是结束数,step是步长 -->
<c:forEach begin="0" end="10" step="1" var='i'>
    ${i}
</c:forEach>

<!-- 相当于.. -->
for(int i = 0; i <= 10; i++){
	System.out.println(i);    
}

MVC

MVC是一种分层开发的模式,其中:

  • M:Model,业务模型,处理业务
  • V:View,视图,界面展示
  • C:Controller,控制器,处理请求,调用模型和视图

image-20220228114916749

MVC只能实现模型到视图的单向展示

三层架构

表现层:接收请求,封装数据,调用业务逻辑层,响应数据

业务逻辑层:对业务逻辑进行封装,组合数据访问层的基本功能,形成复杂的业务逻辑功能

数据访问层(持久层):对数据库的CRUD基本操作

image-20220228115248548

AJAX

概念:AJAX(Asynchronous JavaScript And XML):异步的 javaScript 和 XML

AJAX作用

  1. 与服务器进行数据交换: 通过AJAX可以给服务器发送请求,并获取服务器响应的数据。

    使用了AJAX和服务器进行通信,就可以使用 HTML+AJAX 来替换 JSP 页面了。

  2. 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用校验,等等…

    Ajax 请求的局部更新,浏览器地址栏不会发生变化, 局部更新不会舍弃原来页面的内容。

同步:浏览器请求服务器 ,需要等待服务器处理并响应后,才能继续操作。

异步:浏览器请求服务器,服务器在处理时,浏览器可以做其他操作。


使用步骤

服务端:Servlet程序

客户端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script>
    //1. 创建核心对象
    var xhttp;
    if (window.XMLHttpRequest) {
        xhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //2. 发送请求
    xhttp.open("GET", "http://localhost:8080/ajax-demo/ajaxServlet");
    xhttp.send();

    //3. 获取响应
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            alert(this.responseText);
        }
    };
</script>
</body>
</html>

XMLHttpRequest对象

方法:

方法说明
abort()取消当前请求
getAllResponseHeaders()返回头部信息
getResponseHeader()返回特定的头部信息
open(method, url, async, user, psw)发送请求 —— method:请求类型 GET 或 POST; url:文件位置; async:true(异步)或 false(同步); user:可选的用户名称; psw:可选的密码
send()将请求发送到服务器,用于GET请求
send(string)将请求发送到服务器,用于POST请求
setRequestHeader()向要发送的报头添加标签/值对

XMLHttpRequest属性:

属性说明
onreadystatechange定义当 readyState 属性发生变化时被调用的函数
readyState保存XMLHttpRequest的状态
responseXML以字符串返回响应数据
status返回请求的状态号
statusText返回状态文本(如 “OK” 或 “Not Found”)

readyState中的XMLHttpRequest的状态 :

  • 0:请求未初始化
  • 1:服务器连接已建立
  • 2:请求已收到
  • 3:正在处理请求
  • 4:请求已完成且响应已就绪

status中常见的 返回请求的状态:

  • 200: “OK”
  • 403: “Forbidden”
  • 404: “Not Found”

示例

需求:在完成用户注册时,当用户名输入框失去焦点时,校验用户名是否在数据库已存在

  • 前端完成的逻辑
    1. 给用户名输入框绑定光标失去焦点事件 onblur
    2. 发送 ajax请求,携带username参数
    3. 处理响应:是否显示提示信息
  • 后端完成的逻辑
    1. 接收用户名
    2. 调用service 查询User。此案例是为了演示前后端异步交互,所以此处我们不做业务逻辑处理
    3. 返回标记

后端:

@WebServlet("/selectUserServlet")
public class SelectUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收用户名
        String username = request.getParameter("username");
        //2. 调用service查询User对象,此处不进行业务逻辑处理,直接给 flag 赋值为 true,表明用户名占用
        boolean flag = true;
        //3. 响应标记
        response.getWriter().write("" + flag);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

前端:

//1. 给用户名输入框绑定 失去焦点事件
document.getElementById("username").onblur = function () {
    //2. 发送ajax请求
    // 获取用户名的值 
    var username = this.value;

    //2.1. 创建核心对象
    var xhttp;
    if (window.XMLHttpRequest) {
        xhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //2.2. 发送请求
    xhttp.open("GET", "http://localhost:8080/ajax-demo/selectUserServlet?username="+username);
    xhttp.send();

    //2.3. 获取响应
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            //判断
            if(this.responseText == "true"){
                //用户名存在,显示提示信息
                document.getElementById("username_err").style.display = '';
            }else {
                //用户名不存在 ,q提示信息
                document.getElementById("username_err").style.display = 'none';
            }
        }
    };
}

Axios

Axios 是一个基于 promise 的 HTTP 库,简单的讲就是可以发送get、post请求。

Axios对原生的AJAX进行封装,简化书写。

使用

axios 使用是比较简单的,分为以下两步:

  • 引入 axios 的 js 文件

    <script src="js/axios-0.18.0.js"></script>
    
  • 使用axios 发送请求,并获取响应结果

    • 发送 get 请求

      axios({
          method:"get",
          url:"http://localhost:8080/ajax-demo1/aJAXDemo1?username=zhangsan"
      }).then(function (a){
          alert(a.data);
      })
      
    • 发送 post 请求

      axios({
          method:"post",
          url:"http://localhost:8080/ajax-demo1/aJAXDemo1",
          data:"username=zhangsan"
      }).then(function (a){
          alert(a.data);
      });
      

axios() 是用来发送异步请求的,小括号中使用 js 对象传递请求相关的参数:

  • method 属性:用来设置请求方式的。取值为 get 或者 post
  • url 属性:用来书写请求的资源路径。如果是 get 请求,需要将请求参数拼接到路径的后面,格式为: url?参数名=参数值&参数名2=参数值2
  • data 属性:作为请求体被发送的数据。也就是说如果是 post 请求的话,数据需要作为 data 属性的值。

then() 需要传递一个匿名函数。我们将 then() 中传递的匿名函数称为 回调函数,意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数。而该回调函数中的 resp 参数是对响应的数据进行封装的对象,通过 resp.data 可以获取到响应的数据。


示例

1.后端实现

定义一个用于接收请求的servlet,代码如下:

@WebServlet("/axiosServlet")
public class AxiosServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("get...");
        //1. 接收请求参数
        String username = request.getParameter("username");
        System.out.println(username);
        //2. 响应数据
        response.getWriter().write("hello Axios~");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("post...");
        this.doGet(request, response);
    }
}

2.前端实现

  • 引入 js 文件

    <script src="js/axios-0.18.0.js"></script>
    
  • 发送 ajax 请求

    • get 请求

      axios({
          method:"get",
          url:"http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan"
      }).then(function (resp) {
          alert(resp.data);
      })
      
    • post 请求

      axios({
          method:"post",
          url:"http://localhost:8080/ajax-demo/axiosServlet",
          data:"username=zhangsan"
      }).then(function (resp) {
          alert(resp.data);
      })
      

整体页面代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script src="js/axios-0.18.0.js"></script>
<script>
    //1. get
   /* axios({
        method:"get",
        url:"http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan"
    }).then(function (resp) {
        alert(resp.data);
    })*/

    //2. post  在js中{} 表示一个js对象,而这个js对象中有三个属性
    axios({
        method:"post",
        url:"http://localhost:8080/ajax-demo/axiosServlet",
        data:"username=zhangsan"
    }).then(function (resp) {
        alert(resp.data);
    })
</script>
</body>
</html>

方法

为了方便起见, Axios 已经为所有支持的请求方法提供了别名。如下:

  • get 请求 : axios.get(url[,config])

  • delete 请求 : axios.delete(url[,config])

  • head 请求 : axios.head(url[,config])

  • options 请求 : axios.option(url,config])

  • post 请求:axios.post(url[,data,config])

  • put 请求:axios.put(url[,data,config])

  • patch 请求:axios.patch(url[,data,config])

案例中的 get 请求代码可以改为如下:

axios.get("http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan").then(function (resp) {
    alert(resp.data);
});

入门案例中的 post 请求代码可以改为如下:

axios.post("http://localhost:8080/ajax-demo/axiosServlet","username=zhangsan").then(function (resp) {
    alert(resp.data);
})

携带JSON数据

var jsObject = {name:"张三"};

axios({
    method:"post",
    url:"http://localhost:8080/ajax-demo/axiosServlet",
    data:jsObject  	//这里 axios 会将该js对象转换为 json 串的
}).then(function (resp) {
    alert(resp.data);
})

注:

  • 发送异步请求时,如果请求参数是 JSON 格式,那请求方式必须是 POST。因为 JSON 串需要放在请求体中。
  • axios将js对象转为json字符串,用了 js提供的 JSON对象,即 JSON.stringify (jsObject)。(了解即可)

Vue中的axios

  1. 下载axios:

    npm i axios
    
  2. 引入:

    import axios from 'axios'
    
  3. 使用

跨域问题:

在vue.config.js

方式一:

module.experts={
	devServer:{
		proxy: 'http://localhost:80' //获取数据的地址
	}
}
  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

前端请求的地址端口要改成 8080 (与自己页面的端口一致)

方式二:

module.experts={
	proxy: {
      '/api1': {// 匹配所有以 '/api1'开头的请求路径
          target: 'http://localhost:80',// 代理目标的基础路径
          changeOrigin: true,
          pathRewrite: {'^/api1': ''}
      },
      '/api2': {// 匹配所有以 '/api2'开头的请求路径
          target: 'http://localhost:5001',// 代理目标的基础路径
          changeOrigin: true,
          pathRewrite: {'^/api2': ''}
      }
    }
}
  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。

Thymeleaf

Thymeleaf 是(服务器端)视图模板技术,

优势:和springBoot完美契合。不经过服务器运算仍可以直接查看原始值,对前端友好。


物理视图:

在Servlet中,将请求转发到一个HTML页面文件时,使用的完整的转发路径就是 物理视图。如:/pages/user/login_success.html

由于html页面放在统一的目录下,所以转发地址会有相同的前缀 和 后缀,称为视图前缀,视图后缀

逻辑视图:

物理视图 = 视图前缀 + 逻辑视图 + 视图后缀

也就是说,逻辑视图 就是指转发路径中间不一样的部分(html页面名)。


使用步骤:

  • 添加jar包(maven可直接添加依赖);

  • 配置两个 < context-param >: view-prefix,view-suffix

    <!-- 在上下文参数中配置 视图前缀和视图后缀 -->
    <context-param>
        <param-name>view-prefix</param-name>
        <param-value>/WEB-INF/view/</param-value>	
    </context-param>
    <context-param>
        <param-name>view-suffix</param-name>
        <param-value>.html</param-value>
    </context-param>
    
  • 新建viewBaseServlet(有两个方法)

    public class ViewBaseServlet extends HttpServlet {
    
        private TemplateEngine templateEngine;
    
        @Override
        public void init() throws ServletException {
            // 1.获取ServletContext对象
            ServletContext servletContext = this.getServletContext();
            
            // 2.创建Thymeleaf解析器对象
            ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
    
            // 3.给解析器对象设置参数
            // ①HTML是默认模式,明确设置是为了代码更容易理解
            templateResolver.setTemplateMode(TemplateMode.HTML);
    
            // ②设置前缀
            String viewPrefix = servletContext.getInitParameter("view-prefix");
    
            templateResolver.setPrefix(viewPrefix);
    
            // ③设置后缀
            String viewSuffix = servletContext.getInitParameter("view-suffix");
    
            templateResolver.setSuffix(viewSuffix);
    
            // ④设置缓存过期时间(毫秒)
            templateResolver.setCacheTTLMs(60000L);
    
            // ⑤设置是否缓存
            templateResolver.setCacheable(true);
    
            // ⑥设置服务器端编码方式
            templateResolver.setCharacterEncoding("utf-8");
    
            // 4.创建模板引擎对象
            templateEngine = new TemplateEngine();
    
            // 5.给模板引擎对象设置模板解析器
            templateEngine.setTemplateResolver(templateResolver);
        }
    
        
        protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
            // 1.设置响应体内容类型和字符集
            resp.setContentType("text/html;charset=UTF-8");
    
            // 2.创建WebContext对象
            WebContext webContext = new WebContext(req, resp, getServletContext());
    
            // 3.处理模板数据
            templateEngine.process(templateName, webContext, resp.getWriter());
        }
    }
    

) {
//判断
if(this.responseText == “true”){
//用户名存在,显示提示信息
document.getElementById(“username_err”).style.display = ‘’;
}else {
//用户名不存在 ,q提示信息
document.getElementById(“username_err”).style.display = ‘none’;
}
}
};
}












## Axios

Axios 是一个基于 promise 的 HTTP 库,简单的讲就是可以发送get、post请求。

Axios对原生的AJAX进行封装,简化书写。

### 使用

axios 使用是比较简单的,分为以下两步:

* 引入 axios 的 js 文件

  ```html
  <script src="js/axios-0.18.0.js"></script>
  • 使用axios 发送请求,并获取响应结果

    • 发送 get 请求

      axios({
          method:"get",
          url:"http://localhost:8080/ajax-demo1/aJAXDemo1?username=zhangsan"
      }).then(function (a){
          alert(a.data);
      })
      
    • 发送 post 请求

      axios({
          method:"post",
          url:"http://localhost:8080/ajax-demo1/aJAXDemo1",
          data:"username=zhangsan"
      }).then(function (a){
          alert(a.data);
      });
      

axios() 是用来发送异步请求的,小括号中使用 js 对象传递请求相关的参数:

  • method 属性:用来设置请求方式的。取值为 get 或者 post
  • url 属性:用来书写请求的资源路径。如果是 get 请求,需要将请求参数拼接到路径的后面,格式为: url?参数名=参数值&参数名2=参数值2
  • data 属性:作为请求体被发送的数据。也就是说如果是 post 请求的话,数据需要作为 data 属性的值。

then() 需要传递一个匿名函数。我们将 then() 中传递的匿名函数称为 回调函数,意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数。而该回调函数中的 resp 参数是对响应的数据进行封装的对象,通过 resp.data 可以获取到响应的数据。


示例

1.后端实现

定义一个用于接收请求的servlet,代码如下:

@WebServlet("/axiosServlet")
public class AxiosServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("get...");
        //1. 接收请求参数
        String username = request.getParameter("username");
        System.out.println(username);
        //2. 响应数据
        response.getWriter().write("hello Axios~");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("post...");
        this.doGet(request, response);
    }
}

2.前端实现

  • 引入 js 文件

    <script src="js/axios-0.18.0.js"></script>
    
  • 发送 ajax 请求

    • get 请求

      axios({
          method:"get",
          url:"http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan"
      }).then(function (resp) {
          alert(resp.data);
      })
      
    • post 请求

      axios({
          method:"post",
          url:"http://localhost:8080/ajax-demo/axiosServlet",
          data:"username=zhangsan"
      }).then(function (resp) {
          alert(resp.data);
      })
      

整体页面代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script src="js/axios-0.18.0.js"></script>
<script>
    //1. get
   /* axios({
        method:"get",
        url:"http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan"
    }).then(function (resp) {
        alert(resp.data);
    })*/

    //2. post  在js中{} 表示一个js对象,而这个js对象中有三个属性
    axios({
        method:"post",
        url:"http://localhost:8080/ajax-demo/axiosServlet",
        data:"username=zhangsan"
    }).then(function (resp) {
        alert(resp.data);
    })
</script>
</body>
</html>

方法

为了方便起见, Axios 已经为所有支持的请求方法提供了别名。如下:

  • get 请求 : axios.get(url[,config])

  • delete 请求 : axios.delete(url[,config])

  • head 请求 : axios.head(url[,config])

  • options 请求 : axios.option(url,config])

  • post 请求:axios.post(url[,data,config])

  • put 请求:axios.put(url[,data,config])

  • patch 请求:axios.patch(url[,data,config])

案例中的 get 请求代码可以改为如下:

axios.get("http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan").then(function (resp) {
    alert(resp.data);
});

入门案例中的 post 请求代码可以改为如下:

axios.post("http://localhost:8080/ajax-demo/axiosServlet","username=zhangsan").then(function (resp) {
    alert(resp.data);
})

携带JSON数据

var jsObject = {name:"张三"};

axios({
    method:"post",
    url:"http://localhost:8080/ajax-demo/axiosServlet",
    data:jsObject  	//这里 axios 会将该js对象转换为 json 串的
}).then(function (resp) {
    alert(resp.data);
})

注:

  • 发送异步请求时,如果请求参数是 JSON 格式,那请求方式必须是 POST。因为 JSON 串需要放在请求体中。
  • axios将js对象转为json字符串,用了 js提供的 JSON对象,即 JSON.stringify (jsObject)。(了解即可)

Vue中的axios

  1. 下载axios:

    npm i axios
    
  2. 引入:

    import axios from 'axios'
    
  3. 使用

跨域问题:

在vue.config.js

方式一:

module.experts={
	devServer:{
		proxy: 'http://localhost:80' //获取数据的地址
	}
}
  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

前端请求的地址端口要改成 8080 (与自己页面的端口一致)

方式二:

module.experts={
	proxy: {
      '/api1': {// 匹配所有以 '/api1'开头的请求路径
          target: 'http://localhost:80',// 代理目标的基础路径
          changeOrigin: true,
          pathRewrite: {'^/api1': ''}
      },
      '/api2': {// 匹配所有以 '/api2'开头的请求路径
          target: 'http://localhost:5001',// 代理目标的基础路径
          changeOrigin: true,
          pathRewrite: {'^/api2': ''}
      }
    }
}
  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值