JavaWeb

JavaWeb

html

1.html基本规则

1.文件标签:构成html最基本的标签
		* html:html文档的根标签
		* head:头标签。用于指定html文档的一些属性。引入外部的资源
		* title:标题标签。
		* body:体标签
		* :html5中定义该文档是html文档


2.文本标签:和文本有关的标签

		

        Html注释
        

2.html特殊字符


原代码	 	显示结果	  	描述
&lt;		<		  	小于号或显示标记
&gt;		>		  	大于号或显示标记
&amp;		&	      	可用于显示其它特殊字符
&quot;		“	   		引号
&reg;		®	   		已注册
&copy;		©			版权
&trade;		™			商标
&ensp;				半个空白位
&emsp;				一个空白位
&nbsp;				不断行的空白

3.常用标签


标题标签 显示方式 属性
h1~h6 块元素 h1~h6:字体大小逐渐递减
p 上下间距 自成一行
div 单纯块 每一个div占满一整行
span 行内标签 内联标签 文本信息在一行展示
u 行内 下划线
strong 行内 加粗
em 行内 斜体
dl 自定义列表
dt 列表标题
dd 列表内容
例子:	
		<dl>
			<dt>列表标题dt>
			<dd>列表内容dd>
			<dt>列表标题dt>
			<dd>列表内容dd>
			<dd>列表内容dd>
			
		dl>
列表标签:
		* 有序列表:--type属性    序号类型
			* ol:
			* li:
		* 无序列表: --type属性    序号类型
			* ul:
			* li:

		<ol type="I">
			<li>列表项1li>
			<li>列表项2li>
			<li>列表项3li>
			<li>列表项3li>
		ol>
---------------------------------------------------		
		<ul type="circle">
			<li>列表项1li>
			<li>列表项2li>
			<li>列表项3li>
			<li>列表项3li>			
		ul>
---------------------------------------------------		
		<li>列表项3li>

		 

链接标签:(a  超链接  行内)
	 a:定义一个超链接
		 属性:
			href:指定访问资源的URL(统一资源定位符)
			target:指定打开资源的方式
				* _self:默认值,在当前页面打开
				* _blank:在空白页面打开
<a href="http://www.itcast.cn" target="_self">点我a>
<a href="http://www.itcast.cn" target="_blank">点我a>
---------------------------------------------------------------
锚点
我的超链接锚点: <a href="#myaim">链接a>     ---->"myaim"跳到id为myaim的位置   /"#"代表跳到顶部   "###"哪也不跳

 href属性  链接的地址
         http协议
		 相对路径   从当前所在路径出发 寻找目标资源路径  ./当前目录  通常可以省略    ../  上级目录
		 相对根路径  从根出发 寻找目标资源路径          /根  root
		 绝对路径   跳转到外部链接使用                 http://www.jd.com
---------------------------------------------------------------

图片标签:
	img:展示图片
		属性:   src:指定图片的位置
	代码:
		 
		<img src="image/jingxuan_2.jpg" align="right" alt="古镇" width="500" height="500"/>
        //Src  图片路径    Width  图片宽度    Height  图片高度     Alt  图片说明

	src
			相对路径   从当前所在路径出发 寻找目标资源路径  ./当前目录  通常可以省略    ../  上级目录
			相对根路径  从根出发 寻找目标资源路径          /根  root
			绝对路径   跳转到外部链接使用                 http://www.jd.com

4.表格标签

	
<table border="10" cellpadding="10" cellspacing="10">
			<caption>学生表caption>
			<thead>
				<tr><th>姓名th><th>年龄th><th>性别th><th>电话th>tr>
			thead>
			<tbody>
				<tr><td colspan="2">小明td><td>15td><td align="center">td>tr>
				<tr><td rowspan="2">小黑td><td>17td><td>td><td>1434234td>tr>
				<tr><td>17td><td>td><td>1434234td>tr>
			tbody>		
table>

5.表单标签

* 表单:
	* 概念:用于采集用户输入的数据的。用于和服务器进行交互。
	* form:用于定义表单的。可以定义一个范围,范围代表采集用户数据的范围
        * 属性:
            * action:指定提交数据的URL
            * method:指定提交方式
                * 分类:一共7种,2种比较常用
                   * get:
                        1. 请求参数会在地址栏中显示。会封装到请求行中(HTTP协议后讲解)。
                        2. 请求参数大小是有限制的。
                        3. 不太安全。
                   * post:
                        2. 请求参数不会再地址栏中显示。会封装在请求体中(HTTP协议后讲解)
                        2. 请求参数的大小没有限制。
                        3. 较为安全。

        * 表单项中的数据要想被提交:必须指定其name属性



* 表单项标签:
		* input:可以通过type属性值,改变元素展示的样式
			* type属性:
				* text:文本输入框,默认值
					* placeholder:指定输入框的提示信息,当输入框的内容发生变化,会自动清空提示信息
                    * maxlength  最大长度
                    * value      默认值
				* password:密码输入框     (同上)
				* radio:单选框

                    * value    选项框对应的值    (一般会给每一个单选框提供value属性,指定其被选中后提交的值)
                    * name     单选框分组       (要想让多个单选框实现单选的效果,则多个单选框的name属性值必须一样。)
                    * checked  认选中           (checked属性,可以指定默认值)

				* checkbox:复选框   (同上)
					* 注意:
						1. 一般会给每一个单选框提供value属性,指定其被选中后提交的值
						2. checked属性,可以指定默认值

				* file:文件选择框
				* hidden:隐藏域,用于提交一些信息。
                    * value   隐藏框的值
				* 按钮:
					* button:普通按钮
                       --value 按钮显示的文本
					* submit:提交按钮。可以提交表单
					* reset: 提交按钮。重置当前表单
					* image:图片提交按钮
						* src属性指定图片的路径	

		   * label:指定输入项的文字描述信息
			   * 注意:
				   * label的for属性一般会和 input 的 id属性值 对应。如果对应了,则点击label区域,会让input输入框获取焦点。
				   * action  填写请求的地址
		* select: 下拉列表
			* 子元素:option,指定列表项
			* multiple="multiple" 变成多选
			
		* textarea:文本域
			* cols:指定列数,每一行有多少个字符
			* rows:默认多少行。
		<form action="1html基本规则.html" method="get">     //action 内容提交的位置 method 提交的方法     
			<label for="uname">用户名label><input id="uname" name="uname" value="默认值" type="text" maxlength="5" placeholder="请输入用户名"/><br />       //for的内容 与 id的内容相同的话 就可以点lable的文字就激活后边文本框 让你输入内容
                                       //input的name是你提交的信息的名字
			<label for="upwd">密码label><input id="upwd" name="upwd"  type="password" maxlength="5" placeholder="请输入密码"/><br />
			<input id="radmale" name="gender" checked="checked" value="male" type="radio" /><label for="radmale">label>
			<input id="radfmale" name="gender" value="fmale" type="radio" /><label for="radfmale">label><br />
			兴趣爱好:<input id="cb1" name="hobby" value="1" type="checkbox" /><label for="cb1">篮球label>
					 <input id="cb2" name="hobby"  checked="checked" value="2" type="checkbox" /><label for="cb2">label>
					 <input id="cb3" name="hobby" value="3" type="checkbox" /><label for="cb3">label>
					 <input id="cb4" name="hobby"  checked="checked" value="4" type="checkbox" /><label for="cb4">Raplabel>
            

            
			<input type="hidden" name="mykey" value="myval" />
			<br />
			<select name="myarea" multiple="multiple">
				<option>---请选择---option>
				<option value="010">北京option>
				<option value="021">上海option>
				<option value="035">深圳option>
			select>
			<br />
			<textarea name="mydesc" rows="10" cols="50">textarea>
			<br />
			<input type="button" value="我的按钮" />	
			<input type="submit" value="我的提交按钮"/>
			<input type="reset" value="我的重置按钮"/>
	
		form>
GET POST
后退按钮/刷新 无害 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。
书签 可收藏为书签 不可收藏为书签
缓存 能被缓存 不能缓存
编码类型 application/x-www-form-urlencoded application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。
历史 参数保留在浏览器历史中。 参数不会保存在浏览器历史中。
对数据长度的限制 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 无限制。
对数据类型的限制 只允许 ASCII 字符。 没有限制。也允许二进制数据。
安全性 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET ! POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。
可见性 数据在 URL 中对所有人都是可见的。 数据不会显示在 URL 中。

css

1.css引入方式

/* 
			 选择器{属性:属性值}
			 */
			
			/* 
			 引入方式1   style标签中写css代码             调试代码时使用
					2   link标签 href 引入文件的地址      调试完成 放在css文件中 通过link标签引入
					3   style属性直接编辑css样式          不建议使用
			 
			 style属性 优先级最高 style标签与link标签 优先级相同 后加载的把先加载的覆盖掉
			 */

2.css选择器

/* 
			 选择器:
			 基本选择器
				 元素选择器      标签名
				 class选择器     .class属性值  元素的class属性允许多值
				 id选择器        #id属性值   一般不用
			 
			 通过元素特征查找
			 id选择器>>class选择器>>元素选择器
			 辅助选择器
				并集选择器       选择器,选择器
				交集选择器       选择器选择器  先用元素筛选 再用其他选择器
				后代选择器       选择器 选择器
				子代选择器       选择器>选择器 比后代选择器跟严格
				属性选择器       [属性] [属性="属性值"]  通常和元素选择器 交集选择器 配合使用input[type="text"]
				全局选择器       * 选择所有元素
			 */




/* 			h1{                                -->元素选择器 
				color: red;                          
			}
	
			.mycls{                            -->class选择器
				color: lightsalmon
			}
			
			#myrow{                            --> id选择器
				color: blue;
			} */
/* 			h1,.mycls{                         -->并集选择器
				color: red;
			} */
/* 			p.mycls{                           -->交集选择器     p标签里有mycls属性值
				color: red;
			}	 */		
/* 			div p{                             -->后代选择器     p标签外边包了一层div(满足层级结构)
				color: red;
			} */
/* 			div>div>p{                         -->子代选择器 
				color: red;
			} */

/* 			input[type="text"]{                -->属性选择器
				color: red;
			}

/* 			*{                                -->全局选择器
				color: red;
			} */
/* 
			 伪类选择器
			 :hover    鼠标悬停
			 :active   鼠标点击
			 
			 cursor: pointer  出现小手
			 
			 */


例子:

	
		
		
		
	
	
		"xxx">我的链接
		
"mydiv">mydiv

3.常用样式属性

常用样式属性
颜色 color: #22FF44;
透明度 opacity: 1;/*透明度*/
字体大小 font-size: xx-large;
字体类型 font-family: "楷体";
字体粗细 font-weight: 800;
文字对齐方式 text-align: center;
文字描述 text-decoration:line-through;width: 1000px;/* px 像素 720p  1080p 2k 4k */height: 1000px;
边框 border: 1px dashed lightseagreen;
边框圆角 border-radius: 50%;
背景图片 background: url(img/e0cd1d847573b096.jpg);
背景重复方式 background-repeat: repeat-x;
背景颜色 background-color: #20B2AA;
行高 line-height: 1000px; 通常用来做块中的文字水平居中


显示方式  display    block  块
					inline  行内
					inline-block 行内块(就是可以设置宽高)
					none    不可见

position 定位 
			static   默认文档流规则
			relative 相对定位 以本身位置进行偏移 不脱离文档流
			absolute 绝对定位 以窗体位置进行偏移 脱离文档流
			fixed    固定定位 以窗体位置进行便宜并固定在窗体上  脱离文档流

            top    上偏移
            left   左偏移
            z-index 有层叠时 设置层叠的先后顺序

:
	/* 		.d1{
				background-color: #ADD8E6;
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			} */
盒子模型
padding  内部填充
margin   外边距
overflow  超过边界处理方式
        * hidden
// padding:40px 30px 20px 10px;   //四个方向  上 右 下 左    //两个值就是 上下 左右    //三个值就是上 左右 下
   padding-left: 10px;            //左边加了10px
   margin:10px auto;             //上下距离10px  左右自动调节          



float    漂浮元素
		* left
		* right

JavaWeb_第1张图片

​ 注意:盒子模型相关属性 可以使用复合属性 也可以单独设置

javascript

1. Javascript基本语法

1.1 js引入方式

js引入方式
1.页面中加script标签 <script></script>     调试时使用
2.通过script标签加src 引入js文件 <script type="text/javascript" src="js/myjs.js"></script> 调试完 放入js文件 引入到html中
3.在事件上直接编辑javascript代码             尽量不用

    
<script>
	console.log(123);
</script>    

    
//JavaScript的注释方法,与Java一致			
// 单行注释
/* 多行注释*/

1.2 基本语法

  • 变量声明规则与java基本一致
  1. 由于 JavaScript 对大小写敏感,变量名也对大小写敏感 (y 和 Y 是两个不同的变量)
  2. 变量必须以字母或下划线或美元符$开始 ,不能使用关键字作为变量名 //JS的变量声明 ,是通过 var 语句来声明 //弱类型,声明时无需指定数据类型,赋值时根据值决定类型 var num = 10 ;

弱类型 定义时不指定类型 赋值时根据值的类型

  • Js中变量类型
  1. Number 数字类型

  2. String 字符串类型 /* 引号中的引号 使用单引号套双引号 或者双引号套单引号 */

  3. Boolean 布尔类型

  4. Undefined 未定义或未初始化类型

  5. Null 表示空对象 一般作为对象类型的初始值

  6. Object 复合类型 包含js中的各种对象

    var mystr2 = "a15";//NAN not a number 数字类型的特殊值 表示不是数字
    
  • Typeof关键字 可以返回当前变量的类型,typeof运算符返回值如下:
  1. undefined:变量被声明后,但未被赋值

  2. string:用单引号或双引号来声明的字符串

  3. boolean:true或false

  4. number:整数或浮点数

  5. function:函数方法

  6. object:对象 或 数组 或 Null 类型

  • 类型转换函数
  1. parseInt():字符串转换为整数
  2. parseFloat():字符串转换为浮点数 丢失精度时,可以使用.toFixed 保留指定位数的小数
  3. toString():返回字符串
  4. 注意parseInt parseFloat对字符串的转换
  • 运算符
类型 运算符
算术运算符 +,-,*,/,%,++,-
赋值运算符 =,+=,-=,*=,/=,%=
比较运算符 >,<,>=,<=,,!=,=
逻辑运算符 &&,||,!

Js中运算符与java中基本一致

+可以做数字加 也可以做字符串拼接

注意:小数相加时会丢失精度 如0.1+0.2 需要取位数 使用toFixed(位数)

=的区别

console.log("----------");
var temp3 = false;
var temp4 = 0;
console.log(temp3===temp4);   //false      == 就是 true
/* 
0  false
1  true

if(!0){

	  }

==比较值   ===比较值和类型

1.3 条件与循环

  • 条件语句语法与java基本一致

    If…else

    Switch…case

  • 循环语句语法与java基本一致

    For

    for…in 可循环数组成员

    While

    Do…while

1.4 函数

系统函数(parseInt()

parseInt

parseFloat

IsNaN 是否不是数字

eval 把字符串转为运行的结果

			var mystr = "123a";
			console.log(isNaN(mystr))     //true
			//isNaN 是否不是数字
			var mystr = "123+211";
			console.log(eval(mystr));     //334
			//eval 把字符串转为运行的结果
自定义函数(mytest()
function 函数名(参数1,参数2,参数3){
     
   //代码
}

等同于

var 函数名 = function(参数1,参数2,参数3){
     
   //代码
}

Js中的函数不需要定义返回值类型 如果需要返回值 在函数中加上return关键字即可

function 函数名(参数1,参数2,参数3){
     
   //代码
return xxx;
}
注意1:特殊写法 立即执行函数

(function(){
     

})(); 

注意2:js中作用域,有函数作用域与全局 
function myTest(){
     
				var myval1 = 10;             //不加var就是全局   在函数外随机生成了myval1
				console.log("函数内输出"+myval1);
			}

1.5 Js事件

Js会自动对行为进行监听,当触发某些行为时,可以调用自定义函数来完成用户交互。

事件通常与函数配合使用,当事件发生时去调用函数

  1. 鼠标点击 onclick
  2. 鼠标悬浮于页面的某个热点之上 onmouseover 鼠标离开页面的某个热点后状态 onmouseout
  3. 在表单中选取输入框 onfocus 在表单中离开输入框后状态 onblur
  4. 内容改变 onchange(不与onfocus 同时使用 产生冲突)
  5. 页面或图像载入 onload(加载结束)
  6. 键盘按键 onkeyup
  7. 表单提交 onsubmit
/* 
			 1.由谁触发
			 2.触发什么事件
			 3.触发的代码
			   --哪个元素 发生什么改变
			   .style.xxx   改变元素的样式
			   .value       表单元素的值
			   .innerHTML   双标签中的内容
			   .src        图片路径
			   .className  改class
			 */

onclick        鼠标点击    button  块元素
onmouseover    鼠标经过    块元素
onmouseout     鼠标移出    。。。
onfocus        获取焦点    输入框
onblur         失去焦点    。。。
onchange       内容改变    select 输入框
onkeyup        键盘弹起    输入框
onload         加载结束    body
onsubmit       表单提交    form
			/*                                    //第一种方式   推荐
			 1.在元素上选择事件
			 2.定义出来函数
			 3.用函数给事件赋值			 
			 */




	



            //第二种方式        //绑定事件   
    


	//onmouseover 鼠标悬浮于页面的某个热点之上   用法

		<head>
		<meta charset="utf-8">
		<title></title>
		<script>						
			function clickBtn(){
     
				console.log("按钮被点了");
			}
			
			function changeColor(mycolor){
     				
				//元素.属性.属性 = "xxx"   给属性赋值     写    将读完的属性值修改成xxx
				//var xxx = 元素.属性.属性 读取属性的值   读    将读完的属性值赋给定义的xxx
                
                /* console.log(document.getElementById("mydiv"));
				var mydivColor = document.getElementById("mydiv").style.backgroundColor;
				console.log(mydivColor); */
				
                
                //js调用函数传参 οnmοuseοver="changeColor('lightblue')"   参数和数字不用加 字符串加上''
                
                //this用法
				//this表示触发当前onmouseover的元素    这个事件在哪个模块 哪个模块就触发
                //οnmοuseοver="changeFontColor('red',this)"
                //在函数里传入"myobj",用它来表示document.getElementById("mydiv")
                
				document.getElementById("mydiv").style.backgroundColor=mycolor;
				
			}
			
			/* 
			document.getElementById("xxx")获取元素
			.style.xxx         样式相关属性
			.value             值			 
			 */			
		</script>
		<style>
			.mydiv{
     
				width: 100px;
				height: 100px;
				border: 1px solid black;
			}
			
		</style>
	</head>
	<body>
		<div id="mydiv" class="mydiv" onclick="clickBtn()" onmouseover="changeColor('lightblue')">mydiv</div>
	</body>
//内容改变    onchange

function myCopy(){
     
				//console.log(document.getElementById("text1").value);    //可直接获取获取	text1 输入的值			
				
				//document.getElementById("text2").value=document.getElementById("text1").value;
                //获取	通过text1 输入的值改变text2的值
			}



<input id="text1" type="text" onchange="myCopy()"/>
<input id="text2" type="text" />
 键盘按键              onkeyup
 表单提交              onsubmit


	
		
		
		
		
	
	
	
//onsubmit

1.6 正则表达式

在js中 经常用正则表达式配合进行前端校验,给用户相应提示

语法:/ reg /

两个特殊的符号’^‘和’$’。他们的作用是分别指出一个字符串的开始和结束。

例:/^xxxxxx$/

  • 字符匹配符
1[]:匹配方括号中包含的字符集中的任意一个字符。例如,正则表达式“[abc]”,字符“a”、“b”、“c”都可以与之匹配。
(2[^]:匹配方括号中未包含的任何字符。例如,正则表达式“[^ab]”,除了字符“a”、“b”之外,其他的任何字符都可以与之匹配。
(3[a-z][1-9]:匹配指定范围内的任何字符。
(4[^a-z][^1-9]:匹配不在指定的范围内的任何字符。
(5)\d:匹配任意一个数字字符,等效于[0-9]。
(6)\D:匹配任意一个非数字字符,等效于[^0-9]。
(7)\s:匹配任何空白字符,包括空格、制表符等。
(8)\S:匹配任何非空白字符。
(9)\w:匹配任何英文字母、数字和下划线,等效于[A-Za-z0-9_]。
(10)\W:匹配任何非英文字母和数字类字符,但不包括下划线,等效于[^A-Za-z0-9_]。
(11.:匹配除换行符\n之外的任何单字符。
  • 次数限定符
1{
     n}:出现n次
(2{
     n,}:规定前面的元素或组合项至少出现n次。例如“o{
     2,}”,字符串“bod”不能与之匹配,但“foood”可以与之匹配。
(3{
     n,m}:规定前面的元素或组合项至少连续出现n次,至多连续出现m次,其中n≤m,逗号和数字之间不能有空格。例如“o{
     1,3}”,字符串“food”和字符串“foood”都能与之匹配。
(4+:规定前面的元素或组合项必须出现一次或连续出现多次,等效于{
     1,}。
(5*:规定前面的元素或组合项可以出现零次或连续多次,等效于{
     0,}。例如“zo*”,字符串“z”和“zoo”都能与之匹配。
(6?:规定前面的元素或组合项出现零次或一次,等效于{
     0,1}。例如“zo?,字符串“z”和“zo”都能与之匹配。

  • 常见正则表达式
1.匹配身份证号码:^\d{
     15}$|^\d{
     18}$
2.邮箱:^\w+@\w+.[a-zA-Z]{
     2,3}(.[a-zA-Z]{
     2,3})?$;
3.中国的邮政编码:^\d{
     6}$
4.匹配字符串中的中文字符:
5.验证512位的qq号:^\d{
     5,12}$	
6.验证手机号 ^1(3|4|5|7|8)\d{
     9}$

2.Javascript操作对象

Bom浏览器对象模型

Window对象
<script>			
			//停止页面加载运行   难看
			//alert("abc");
			//prompt("请输入");
			//confirm("确认么");
			//文档对象 文档对象模型 属于window对象
			//document	
		</script>

//Window 对象是全局对象,可直接调用其方法和属性
//Window对象的一些方法和属性可省略不写
//如 window.document 等同于 document 
//window.alert() 等同于 alert()
History对象

常用方法

History对象 浏览器历史记录

back():加载上一个浏览的文档
forward():加载下一个浏览过的文档
go(n):n为整数,跳转第n个浏览过的文档
  n==0 则刷新当前页面
  n>0 则向前跳转到第n个文档
  n<0 则向后跳转到第n个文档

  
//例子:
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script>
			function myBack(){
     
				history.back();
			}
			function myFword(){
     
				history.forward();
			}
			function myGo(){
     
				history.go(0);
			}
			
		</script>
	</head>
	<body>
		<input type="button" value="鍚庨��" onclick="myBack()" />
		<input type="button" value="鍓嶈繘" onclick="myFword()" />
		<input type="button" value="go" onclick="myGo()" />
	</body>
</html>
Location对象

常用属性和方法

location对象   浏览器地址栏

.Href属性          与浏览器地址栏直接输入地址效果相同
.Reload()方法    与浏览器刷新按钮效果相同

//例子
		<script>
			function myJump(){
     
				location.href="1window对象.html?aaa=xxx&bbb=xxx";
			}
			
			function myReload(){
     
				location.reload();
			}			
		</script>
Document对象

常用属性和方法

Title                         可以设置文档的title
getElementById()              返回对拥有指定id的第一个对象的引用   通过id查找  找到一个
getElement ByTagName()        返回带有指定名称的对象集合          通过标签名查找
getElementsByName()                                           通过name属性查找
getElementsByClassName()      返回带有指定名称的对象集合           通过class属性查找

//js中可以获取多个元素
//拿到的元素集合是数组  用下标(index)取值
//通常和遍历一起使用

//Elements 查到的放在数组中 通过下标取值
			 
//为了避免找到不想关的元素
//在元素上加嵌套关系 
//先查父元素 再查子元素
//document.getElementById("mydiv").getElementsByTagName("input")   //可以在元素内部查找元素
//如果还筛选不出来 可以再加上元素的属性来筛选
//if(myeles[i].type=="text"){}


			window.onload=function(){
     
				var myeles = document.getElementById("mydiv").getElementsByTagName("input");
				
				for(var i = 0;i<myeles.length;i++){
     
					if(myeles[i].type=="text"){
     
						myeles[i].value="默认值";
					}

				}
			}
Window对象常用方法

newWin= window.open(“弹出窗口的url”, “窗口名称”, “窗口特征”)

属性名称 说明
height、width 窗口文档显示区的高度
left、top 窗口的x坐标、y坐标。以像素记
toolbar=yes|no|1|0 是否显示浏览器的工具栏。默认是yes
scrollbars=yes|no|1|0 是否显示滚动条。默认是yes
localtion=yes|no|1|0 是否显示地址字段。默认是yes
status=yes|no|1|0 是否显示状态栏。默认是yes
menubar=yes|no|1|0 是否显示菜单栏。默认是yes
resizable=yes|no|1|0 窗口是否可调节尺寸。默认是yes
titlebar=yes|no|1|0 是否显示标题栏。默认是yes
fullscreen=yes|no|1|0 是否使用全屏模式显示浏览器。默认是no

newWin.close() 关闭打开的窗口

		<script>
			var newWin;
			
			function myOpen(){
     
				newWin = window.open("1window对象.html","","")
			}
			
			function myClose(){
     
				newWin.close();
			}
/* 			window.οnlοad=function(){
				//window.open("1window对象.html","","")
			} */
			
		</script>
定时函数
  • setInterval(fun,time)开启定时循环函数 反复执行
  • clearInterval 停止
方式1var task = setInterval(“myfun(),1000//("需要执行的函数",毫秒数)
方式2var task = setInterval(myfun,1000)        不常用
方式3var task = setInterval(function(){
     xxxxxx},1000)

clearInterval(task) 停止定时函数
  • setTimeout(fun,time)开启定时函数 执行一次
  • clearTimeout 停止
		<script>
			var mytask			
			function myalert(){
     
				alert(1);
			}
			
			function myTimeOut(){
     
				mytask = setTimeout("myalert()",3000);				
			}	

			function myStop(){
     
				clearTimeout(mytask);
			}
		</script>

用法同上

文档对象模型(dom树结构)

DOM(文档对象模型)提供了添加、移动、改变或移除结构文档的方法和属性

HTML 文档中的每个成分都是一个节点(Node)
DOM 是这样规定的:
整个文档是一个文档节点
每个 HTML 标签是一个元素节点
包含在 HTML 元素中的文本是文本节点
每一个 HTML 属性是一个属性节点
注释属于注释节点
每个节点都拥有包含节点某些信息的属性
nodeName(节点名称)
元素节点的 nodeName 是标签名称
属性节点的 nodeName 是属性名称
文本节点的 nodeName 永远是 #text
文档节点的 nodeName 永远是 #document
nodeValue(节点值)
对于文本节点,nodeValue 属性包含文本
对于属性节点,nodeValue 属性包含属性值
nodeType(节点类型)
元素 1 、属性 2、 文本 3、 注释 8、 文档 9
不同数字代表不同节点类型

常用方法和属性

1. 获取元素节点
getElementById():返回对拥有指定id的第一个对象的引用
getElementsByTagName():返回带有指定名称的对象集合
getElementsByClassName():返回带有指定名称的对象集合
2. 根据节点层次关系获取节点(属性 不是方法)
parentNode:返回节点的父节点
childNodes:返回子节点集合,childNodes[i]
firstElementChild:返回节点的第一个子节点,最普遍的用法是访问该元素的文本节点
lastElementChild: 返回节点的最后一个子节点
nextElementSibling:下一个节点
previousElementSibling:上一个节点
3. 获取操作属性节点
getAttribute() 获取某个节点的属性值
节点对象.getAttribute( "属性名" );
setAttribute()  设置某个节点的属性值
节点对象.setAttribute( "属性名", "属性值" );
Dom动态操作相关方法
createElement("元素类型")    创建元素
appendChild(新元素)       追加元素
insertBefore(新元素,某元素)      在某元素前追加元素
cloneNode(bol)      复制元素:bol 默认为false 不复制子元素 /   true  复制子元素
removeChild()       删除元素
Dom操作表格相关方法

Js中把table描述成二维数组 有rows数组和cells数组 可以根据行列下标 找到对应的单元格内容

table被描述为二维数组
.rows     所有行
.cells    该行的所有单元格

insertRow(idx)    添加行
insertCell(idx)   新增单元格(列)
deleteRow(idx)    删除行



//例子
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script type="text/javascript">
			function getTableVal(){
     
				//table描述成二维数组   rows  所有的行   cells 该行所有的单元格
				console.log(document.getElementById("mytable").rows[3].cells[0].innerHTML);
			}
			
			function addOneRow(){
     
				var newRow = document.getElementById("mytable").insertRow(document.getElementById("mytable").rows.length);
				var td1 = newRow.insertCell(0);
				var td2 = newRow.insertCell(1);
				var td3 = newRow.insertCell(2);
				
				td1.innerHTML="奥利给";
				td2.innerHTML="奥利给";
				td3.innerHTML="奥利给";
				
			}
			
			function delOneRow(){
     
				document.getElementById("mytable").deleteRow(document.getElementById("mytable").rows.length-1);
			}
			
			
		</script>
	</head>
	<body>
		<input type="button" value="获取table中的数据" onclick="getTableVal()" />
		<input type="button" value="动态添加一行数据" onclick="addOneRow()" />
		<input type="button" value="动态删除一行数据" onclick="delOneRow()" />
		<table id="mytable" border="1">
			<tr><th>姓名</th><th>年龄</th><th>班级</th></tr>
			<tr><td>葫芦大娃</td><td>1</td><td>704A</td></tr>
			<tr><td>葫芦二娃</td><td>1</td><td>704A</td></tr>			
			
		</table>
	</body>
</html>



//从页面拿值增加表格
			function getTableVal(){
     
				//table描述成二维数组   rows  所有的行   cells 该行所有的单元格
				console.log(document.getElementById("mytable").rows[3].cells[0].innerHTML);
			}
			
			function addOneRow(){
     
				var rowName = document.getElementById("nameText").value;
				document.getElementById("mytable").innerHTML+=''+rowName+
                    '2704A';
			}
			
			function delOneRow(){
     
				document.getElementById("mytable").deleteRow(document.getElementById("mytable").rows.length-1);
			}
			
			
		</script>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script>
            //元素.innerHTML 以文本方式 添加 替换
            //删除时 使用dom操作
			/* 
			 追加 替换  
			 innerHTML
			 
			 删除 
			 dom操作
			 
			 */
			
			
			function addEle(){
     
				//innerHTML 浏览器可以解析html标签内容  innerText 不解析html标签内容
				document.getElementById("myul").innerHTML+='
  • '
    ; //document.getElementById("myul").innerText console.log(document.getElementById("myul").innerHTML); } function delEle(){ document.getElementById("myul").removeChild(document.getElementById("myul").lastElementChild); } </script> </head> <body> <input type="button" value="添加元素" onclick="addEle()" /> <input type="button" value="删除元素" onclick="delEle()" /> <hr /> <ul id="myul"> <li id="aimli"><input type="password" /></li> </ul> </body> </html>

    Js常用对象

    String

    字符串对象中包含很多字符串处理方法,跟java类似

    IndexOf                 查找指定字符
    subString                截取字符串
    Substr                   截取字符串
    Split                     分割
    toUppercase              转大写
    
    
    //例子
    		
    
    Math
    Ceil                     向上取整
    Floor                    向下取整 
    Round                   四舍五入
    Random                 伪随机数 [0-1)
    
    
    //例子
    		<script>
    			var mynum = 12.1
    			var res = Math.round(mynum);
    			var res = Math.floor(mynum);
    			var res = Math.ceil(mynum);
    			console.log(res);
    			
    			var myrand = parseInt(Math.random()*3)+1;
    			//获取指定随机数时  1.扩倍数   2.通过加减移动区间
    			console.log(myrand);//[0-1)		
    		</script>
    
    Date

    日期相关对象

    通过new Date()获取日期对象 参数允许多种格式如”2011-11-11 11:11:11” “2011/11/11”都可以 不加参数获取当前客户端的时间

    方法 说明
    getDate() 返回Date对象的一个月中的每一天,其值介于1~31之间
    getDay() 返回Date对象的星期中的某一天,其值介于0~6之间
    getHours() 返回Date对象的小时数,其值介于0~23之间
    getMinutes() 返回Date对象的分钟数,其值介于0~59之间
    getSeconds() 返回Date对象的秒数,其值介于0~59之间
    getMonth() 返回Date对象的月份,其值介于0~11之间
    getFullYear() 返回Date对象的年份,其值为4位数
    getTime() 返回某一时刻(1970年1月1日)以来的毫秒数
    		<script>
    			/* 
    			 new Date()               获取执行时的时间
    			 new Date("2011-11-11 11:11:11") 指定时间
    			 
    			 获取年
    			 月 
    			 日
    			 时分秒
    			 
    			 1970年1月1日到现在的毫秒数 没带市区 跟东八区有误差
    			 getTime()
    			 
    			 */
    			
    			var nowDate = new Date();
    			console.log(nowDate.getTime());
    			var myDate = new Date("2011-11-11 11:11:11");
    			var myDate = new Date("2011/12/12 11:11:11");
    			console.log(myDate);
    
    		</script>
    
    Array对象

    创建数组可直接赋值 var myarr=[1,3,5,”g”];

    也可以通过var myarr = new Array();

    js中数组不定长 可以扩容 也可以放任意类型数据

    属性
    Lenght             数组长度
    方法
    Join()             通过特定字符拼成字符串
    Sort()             排序
    Push()            尾部添加元素
    Pop()             尾部删除元素
    Shift()            头部删除元素
    Unshift()          头部添加元素
    
    <script>
    			var myarr = ["a",15,true,new Date()];			
    			console.log(myarr.join());                     //Join()             通过特定字符拼成字符串
    			
    			
    			var myarr2 = [1,15,8,6];                       //Sort()             排序			
    			myarr2.sort(function(a,b){
         
    				return b-a;                                //a-b 升序排列   b-a 降序排列
    			})
    			console.log(myarr2);
    			
    			myarr2.push("a");                              //Push()            尾部添加元素
    			console.log(myarr2);
    			
    			myarr2.unshift("b");                           //Unshift()          头部添加元素
    			console.log(myarr2);
    			
    			myarr2.pop();                                  //Pop()             尾部删除元素	
    			console.log(myarr2);
    			
    			myarr2.shift()                                 //Shift()            头部删除元素			
    			console.log(myarr2);
    			
    			/* 
    			 push(xxx)  队尾添加
    			 pop()      队尾清除
    			 unshift(xxx)  队头添加
    			 shift()       队头清除
    			 
    			 
    			 */
    			
    			/* 
    			js中 获取元素集合  数组中放节点对象 			 
    			 */
    			
    			
    			var myarr3 = [[1,2],["a","b"],[true,false]];
    			
    			console.log(myarr3);
    			
    		</script>
    

    Js中常用属性总结

    Xxx.value 表单标签的value值

    Xxx.innerHTML 双标签中的内容

    Xxx.className 标签的class属性

    Xxx.style.xxx 标签的样式属性(某些属性与css的属性值不相同)

    jquery

    Jquery下载使用

    jQuery官网:http://jquery.com

    jQuery库分开发版和发布版

    Jquery-x.x.js 开发版

    Jquery-x.x.min.js 发布版 代码经过压缩 容量更小

    在页面引入jQuery
    <script src="jquery-x.x.min.js" >script>
    

    Jquery基本语法

    基本语法结构与常用方法

    Jquery基本语法结构 :$(选择器).jquery方法();

    Jquery常用方法:

    ( d o c u m e n t ) . r e a d y ( f u n c t i o n ( ) ) 等 同 于 (document).ready(function(){}) 等同于 (document).ready(function())(function(){}) 页面加载结束后执行

    window.onload $(document).ready()
    执行时机 必须等待网页中所有的内容加载完毕后(包括图片,flash,视频等)才能执行 网页中所有DOM文档结构绘制完毕后即刻执行,可能与DOM元素关联的内容(图片,flash,视频等)并没有加载完
    编写个数 同一页面不能同时编写多个 同一页面能同时编写多个
    简化写法 $(function(){ //执行代码 });
    常用方法
    --隐式循环特性  一组元素统一赋值时 自动遍历赋值
    
    $(选择器).css("属性","属性值")  元素的样式                                                         .style.xxx
    $(选择器).html()  双标签中的内容,括号里传参就是替换掉原来的,不传就是获得原来的内容          .innerHTML
    $(选择器).val()   表单元素的value                                                   .value
    以上几个方法较常用,且用法类似
    
    
    			$(function(){
         
    				$("h1").css("background-color","red");
                 
    				console.log($("h1").html());
    				console.log($("h1").css("background-color"));
    				
    				$("h1").html("新标题");
    				$("#mytext").val("默认值");                                      //id选择器 "#"			
    				$(".mycls").css("color","lightblue");                           //class选择器 "."
    			})
    
    
    
    如果有参数是设置属性,如果没参数是读取属性。
    //写操作  带参数
    //读操作  不带参数
    

    Jquery对象与原生js对象

    • Jquery对象与原生js对象不可通用

    ​ Jquery对象只能调用jquery的方法 不能调用原生对象的属性

    原生对象只能调用原生的方法和属性 不能调用jquery的方法

    • 原生对象与jquery对象可以转换

      原生对象---->jquery对象 ( 原 生 对 象 ) 通 过 工 厂 函 数 (原生对象) 通过工厂函数 ()()进行转换

      jquery对象---->原生对象 jquery对象[0] 或者 jquery对象.get(0)

    注意:this是原生对象 在jquery中使用this时 需要$(this)

    		<script src="js/jquery-3.4.1.js" type="text/javascript" charset="utf-8"></script>
    		<script>
    			$(function(){
         
    								
    				//隐式循环
    				//事件绑定  
    				//$("选择器").事件(function(){ dosomething... })
    				$(".mybtn").click(function(){
         	
                        //如果有多个按钮可能区分不出来  可以使用this表示当前被点击对象 
    					$(this).css("background-color","red");
    					
    					$("h1").css("background-color","#FFCC99");
    					$("h1").html("李白--静夜思");
    					
    					$(".rowstyle1").css("background-color","#99CC99");
    					$(".rowstyle2").css("background-color","#6666FF"); 
    				
                        
    					/* 
    					jquery对象  调jquery方法
    					原生js对象
    					
    					this原生对象   
    					$(this) 转成jquery对象
    					 */
    					
    					//$(document.getElementById("mytext")).val("abc123");         //this原生对象转成jquery对象
    					//$("#mytext")[0].value="abc123";                            //jquery对象转成原生js对象
    					
    					
    				})				
    			})			
    		</script>
    

    Jquery选择器

    常见选择器

    名称 语法
    id选择器 #id名
    Class选择器 .class名
    元素选择器 元素名(标签名)
    全局选择器 *
    交集选择器 选择器选择器 //标签选择器其他选择器
    并集选择器 选择器,选择器
    后代选择器 选择器 选择器
    子代选择器 选择器>选择器
    相邻兄弟选择器 选择器+选择器 //两个元素紧邻
    同辈元素选择器 选择器~选择器 //满足此结构的所有元素
    属性选择器 [属性] 或[属性=”属性值”] //常和元素选择器一起使用
    名称 语法
    首元素 :first
    末元素 :last
    奇数 :even
    偶数 :odd
    指定索引 :eq(idx)
    小于指定索引 :lt(idx)
    大于指定索引 :gt(idx)
    名称 语法
    表单元素选择 :input
    文本框 :text
    密码框 :password
    单选框 :radio
    复选框 :checkbox
    普通按钮 :button
    提交按钮 :submit
    图片 :image
    选中的复选框 :checked
    选中的下拉列表 :selected
    显示的元素 :visible
    隐藏的元素 :hidden (使用.show()方法显示出来)
    //注意
    //$("#myform :text").val("默认值");    id是myform下的文本框          //空格
    //$("#myform:text").val("默认值");     id是myform并且type是文本框    //没空格
    

    辅助筛选元素的方法

    名称 语法
    查找子元素 jquery元素.find(选择器)
    按索引查找 jquery元素.eq(idx)
    排除 jquery元素.not(选择器)
    向后查找同级 jquery元素.next()
    向前查找同级 jquery元素.prev()
    $("#myul :checked").each(function(i){
           //元素集合.each(匿名函数)
    			console.log(i);             //i表示遍历的索引
    			console.log($(this).val());	//遍历中可以使用this
    			allstr+=$(this).val();
    })
    

    元素绑定事件

    $("#showBtn").on("click",function(){
         
         //执行的代码
    })
    

    设置元素的属性

    $("#cbs :checkbox").prop("checked",true);   //给checkbox的checked属性赋值选中
    

    注意:jquery中给元素赋值时 有隐式循环特性 可以直接给选到的元素全部赋值

    取值时没有此特性 需要循环取值

    Jquery常用方法

    Jquery常用方法补充回顾

    html() 可以解析html标签 对双标签内容进行取值和赋值
    val() 对表单元素的value属性进行取值和赋值
    text() 不解析html标签 对双标签内容进行取值和赋值
    css() 操作样式属性 样式属性使用跟css相同的属性和值
    addClass() 追加样式
    removeClass() 移除样式
    find(选择器) 在当前元素中查找子元素
    eq(idx) 在当前元素中按索引查找元素
    not(选择器) 排除指定元素
    next() 同级向后查找
    prev() 同级向前查找
    prop() .prop(“属性”) 取属性的值
    .prop(“属性”,“属性值”) 修改属性的值
    例子1:	
    	 	<script src="js/jquery-3.4.1.js" type="text/javascript" charset="utf-8"></script>
    		<script>
    			$(function(){
         
    				var myele = $("#mydiv");
    				myele.css("background-color","lightgreen");
    				myele.find("p").not(":first").eq(1).next().next().prev().css("background-color","lightyellow");				
    			})
    			
    			
    		</script>
    
    
    例子2:
    <script>
    	$("#mydiv").addClass("cls4"); 								
    	$("#mydiv").removeClass("cls1");			
    </script>
    
    <div id="mydiv" class="mycls cls1 cls2" >mydiv</div>
    

    Jquery节点操作

    元素节点操作

    1. 子节点
    A.append(B)   A里添加节点B
    B.appendTo(A) 把B添加到A的内部
    A.prepend(B)   A里添加节点B    头部插入
    B.prependTo(A) 把B添加到A的内部 头部插入
    2. 同辈节点
    A.after(B)  A后边添加同辈节点B
    B.insertAfter(A) 把同辈节点B添加到A后边
    A.before(B)  A前边添加同辈节点B
    B.insertBefore(A) 把同辈节点B添加到A前边
    3. 替换节点
    A.replaceWith(B) B替换A
    B.replaceAll(A)  B替换A
    4. 复制节点
    A.	clone(true)    复制A节点  
                 参数决定是否复制元素上绑定的事件
    5. 删除节点
    A.remove()       删除A节点及其子孙
    A.empty()        删除A的子孙节点
    根据层次获取
    1. 获取子节点
    A.children()      获取A的子节点
    2. 获取同辈节点
    A.next()          获取A的紧邻下个节点
    A.prev()          获取A的紧邻上个节点
    A.siblings()      获取A的所有同辈节点
    3. 获取父节点
    A.parent()        获取父节点
    A.parents()       获取所有父节点
    

    属性节点操作

    attr()     可以获取自定义属性   对disabled checked等属性返回undefined或者字符串值(解决事件绑定不好传值的问题)
    prop()    不可以获取自定义属性 对disabled checked等属性直接返回bol值
    removeAttr()   删除属性
    removeProd()   删除属性
    
    		<script>
    			$(function(){
         
    				console.log($("#mycb").prop("checked"));
    				console.log($("#mycb").attr("checked"));
    				console.log($("#mycb").prop("type"));
    				console.log($("#mycb").attr("type"));
    				console.log($("#mycb").prop("id"));
    				console.log($("#mycb").attr("id"));
    				console.log($("#mycb").prop("abc123"));
    				console.log($("#mycb").attr("abc123"));
    			})		
    		</script>
    	</head>
    	<body>
    		<input id="mycb" abc123="test"  type="checkbox" />		
    	</body>
    

    注意:属性节点操作在普通属性上 选择两个方法都可以

    在有bol值的属性上 适合使用prop

    Jquery事件绑定

    Jquery中对事件和事件绑定语法做了优化 可以使用同一格式对事件进行绑定

    $(.mybtn”).on("事件",function(){
           //绑定事件
       //执行的代码
    //匿名函数中可以使用$(this)
    })
    $(.mybtn”).off(“事件”)          //解绑事件
    
    表单的onsubmit 通过return 控制表单是否可以提交
    $("#myform").on("submit",function(){
         
    		return bol;
     })
    
    注意1:如果绑定事件时通过隐式循环,给多个元素绑定事件,$(this)代表的是当前发生事件的元素。
    注意2:事件绑定时,必须保证元素在页面中存在,如果元素不存在绑定无效。
    注意3:如果动态添加绑定事件时 页面中已存在与将要绑定的元素特征相同 ,会造成已存在元素事件重复绑定,一般需要先解绑,再重新绑定
    
    
    	
    	
    		
    		

    Jquery常用事件

    <script src="js/jquery-3.4.1.js" type="text/javascript" charset="utf-8"></script>
    		<script>
    			/* 
    			 .dblclick                          双击
    			 .click                            鼠标单击
    			 .mouseover                        鼠标移入
    			 .mouseout                         鼠标移出
    			 .focus                            获得焦点
    			 .blur                             失去焦点
    			 .change                           内容改变
    			 .keyup                            键盘弹起
    			 .submit(function(){return bol})   做验证 通过bol值决定是否提交表单
    			 .submit()                         让表单提交
    			 */
    			
    			$(function(){
         
    				$("#mysel").change(function(){
         
    					console.log($(this).val());
    				})
    			
    				$("#mytext").keyup(function(event){
         
    					//event.keyCode 获取键盘码
    					console.log(event.keyCode);
    				})
    				
    				$("#myform").submit(function(){
         
    					//通过return 布尔值  决定表单是否能提交
    					return true;
    				})
    				
    				$("#mysubmitBtn").click(function(){
         
    					$("#myform").submit();
    				})			
    			})		
    		</script>
    	</head>
    	<body>
    		<select id="mysel">
    			<option value="0" selected="selected" disabled>------请选择-------</option>
    			<option value="021" >上海</option>
    			<option value="010">北京</option>
    			
    		</select>
    		<form id="myform">
    			<input id="mytext" name="mytext" type="text" placeholder="请输入" /><br />
    			<input type="submit"/>
    			<input id="mysubmitBtn" type="button" value="我的提交"/>
    		</form>	
    	</body>
    

    Jquery显示效果相关方法

    Jquery中直接封装了一些针对显示效果的方法,可以用来制作一些常见特效

    方法 功能
    .show() 显示
    .hide() 隐藏
    .toggle() 切换显示和隐藏
    .fadeIn() 淡入
    .fadeOut() 淡出

    可以传参 控制显示效果快慢

    <script>
    			$(function(){
         
    				$("#hideImgBtn").click(function(){
         
    					$("#imgdiv").hide("slow");
    				})
    				
    				$("#showImgBtn").click(function(){
         
    					$("#imgdiv").show("fast");
    				})
    				
    				$("#toggleImgBtn").click(function(){
         
    					$("#imgdiv").toggle(1000);             //传入毫秒数
    				})
    				
    				$("#fadeinBtn").click(function(){
         
    					$("#imgdiv").fadeIn(2000);
    				})
    				
    				$("#fadeoutBtn").click(function(){
         
    					$("#imgdiv").fadeOut(2000);
    				})				
    			})			
    		</script>
    

    JSON

    Json格式

    Json是js中的对象 可以通过对象.属性的方法获取值

    • Json格式 json使用键值对存储{key:value,key:value} 类似java中的Map结构
    前端使用的json格式
    {
         uname:"jack",uage:15};
    标准json格式
    {
         "uname":"jack","uage":15};
    

    注意:如果纯前端使用json key部分不需要加引号 值部分可以使用string、boolean、number

    两种方式在前端读取时没有区别,如果是后台传递到前台的json格式字符串,

    必须使用标准格式才能解析

    • 把json格式字符串转成json对象的方法

    var jsonobj = JSON.parse(myJsonstr)

    • Json使用时,经常和数组搭配使用
    //在数组中套json对象    类似java中的List
    [{
         uname:"jack",uage:15},{
         uname:"rose",uage:16}];
    
    //value部分可以使用数组   类似java中Map>
    {
         utotal:3,students:[{
         uname:"jack",uage:15},
    {
         uname:"rose",uage:16},
    {
         uname:"jase",uage:1}]
    };
    //取值时注意当前取到的是json还是数组对象 数组对象用索引 json对象用.属性
    
    <script>
    			
    			/* 
    			 js 中的一种对象格式
    			 键值对形式保存  key:value
    			 对象.key   得到值
    			 扩展键值对
    			 对象.key = 值
    			 
    			 JSON.parse(json格式字符串)
    			 key带引号    标准格式               可以从字符串解析为json对象
    			 key不带引号  简化格式(纯前端使用)  不能从字符串解析为json对象
    			 
    			 
    			 json使用时  通常 json套数组 数组套json
    			 取值时 如果当前取到json对象 使用key取值
    			        如果当前取到数组     使用下标(索引)取值			 
    			 */
        
    			var myJsonObj = {
         "name":"jack","age":15,"addr":"科学大道"};		
    		    console.log(myJsonObj.addr);   
    			myJsonObj.classroom = "704A";                                     //增加了 classroom:"704A"  键值对
    			console.log(myJsonObj);    
    			
    			var myJsonObj2 = {
         name:"jack2",age:152,addr:"科学大道2"};
    			console.log(myJsonObj2.addr);                                    //科学大道2
    
    			var myJsonObj = '{"name":"jack","age":15,"addr":"科学大道"}';     //后端传来字符串
    			var myobj = JSON.parse(myJsonObj);                              //将myJsonObj字符串解析为json格式
    			console.log(myobj);
    
    
    			
    			
    			var students ={
         "totalnum":3,"dataList":[{
         "name":"jack","age":15,"addr":"科学大道"},
    													{
         "name":"rose","age":16,"addr":"科学大道2"},
    													{
         "name":"小明","age":17,"addr":"科学大道3"}]}
    											
    			
    			console.log(students.dataList[2].age);
    			
    			
    			//jquery 遍历指定数组
    			// $.each(需要遍历的集合,function(i,d){//index  索引    data 数据				
    			//})
    	
    			$.each(students.dataList,function(i,d){
         //index-索引    data-数据
    				console.log(d.name);
    			})
    		
    		</script>
    
    级联菜单
    
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title></title>
    		<script src="js/addr.js" type="text/javascript" charset="utf-8"></script>
    		<script src="js/jquery-3.4.1.js" type="text/javascript" charset="utf-8"></script>
    		<script>
    			/* 
    			 1.了解联动菜单的做法
    			 2.熟悉json结构 和json的遍历			 
    			 */
    			
    			$(function(){
         
    				$.each(addrs,function(i,d){
         
    					console.log(d.code+"-----"+d.label);
    					var myoption = 'd.code+'">'+d.label+'';
    					$("#prov").append(myoption);
    				})
    				
    				$("#prov").change(function(){
         
    					console.log($(this).val());
    					var provcode = $(this).val();
    					$("#city").html('');
    					$("#xianqu").html('');
    					//遍历所有省数据
    					$.each(addrs,function(i,d){
         
    						//通过选取的省代码 找到省数据
    						if(d.code==provcode){
         
    							//遍历省的children(市数据)
    							$.each(d.children,function(i,d){
         
    								//把遍历到的市数据 做成option 放入市下拉列表中
    								var myoption = 'd.code+'">'+d.label+'';
    								$("#city").append(myoption);
    							})
    						}
    					})
    				})
    								
    				$("#city").change(function(){
         
    					
    					var provcode = $("#prov").val();
    					var citycode =  $(this).val();
    					
    					console.log(provcode+"----"+citycode)
    					
    					$("#xianqu").html('');
    					
    					//遍历省
    					$.each(addrs,function(i,d){
         
    						//匹配选择的省
    						if(d.code==provcode){
         
    							//遍历市
    							$.each(d.children,function(i,d){
         
    								//匹配选择的市
    								if(d.code==citycode){
         
    									//遍历县区
    									$.each(d.children,function(i,d){
         
    										//拼成option 放到县区下拉列表里
    										var myoption = 'd.code+'">'+d.label+'';
    										$("#xianqu").append(myoption);
    									})
    								}
    							})
    						}
    					})
    
    				})		
    			})
    			
    		</script>
    	</head>
    	<body>
    		<select id="prov">
    			<option value="0" selected="selected" disabled>------请选择-------</option>
    			
    		</select><select id="city">
    			<option value="0" selected="selected" disabled>------请选择-------</option>
    			
    		</select><select id="xianqu">
    			<option value="0" selected="selected" disabled>------请选择-------</option>
    			
    		</select></body>
    </html>
    
    

    Bootstrap

    1. Bootstrap下载使用

    网址:https://www.bootcss.com/

    注意:Bootstrap下载后包含样式 js 模板 字体等文件 根据不同需要选择使用

    2. Bootstrap详解

    2.1 Bootstrap栅格系统

    2.1.1 栅格介绍
    • Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列。它包含了易于使用的预定义类,还有强大的mixin 用于生成更具语义的布局。
    • 栅格是Bootstrap的核心所在
    • 栅格系统用于通过一系列的行(row)与列(column)的组合来创建页面布局,你的内容就可以放入这些创建好的布局中。行与列的布局很像table的使用方式,bootstrap吸取了table的优点,使用div+css进行布局
    <div class="container">
        <div class="row">
            <div class="col-md-6">leftdiv>
            <div class="col-md-6">rightdiv>
        div>
    div>
    
    2.1.2 栅格原理
    • Bootstrap会检测窗口宽度,根据具有特征的几种宽度可以动态改变显示效果
    /* 超小屏幕(手机,小于 768px) */
    /* 没有任何媒体查询相关的代码,因为这在 Bootstrap 中是默认的(还记得 Bootstrap 是移动设备优先的吗?) */
    /* 小屏幕(平板,大于等于 768px) */
    @media (min-width: @screen-sm-min) { ... }
    /* 中等屏幕(桌面显示器,大于等于 992px) */
    @media (min-width: @screen-md-min) { ... }
    /* 大屏幕(大桌面显示器,大于等于 1200px) */
    @media (min-width: @screen-lg-min) { ... }
    
    2.1.3 栅格布局细节
    • 将最外面的布局元素 .container 修改为 .container-fluid,就可以将固定宽度的栅格布局转换为 100% 宽度的布局。
    • 布局时每行不要超过12列,超过会变形。
    • 布局时可以不满12列,布局左对齐。如果想让左边产生空白 可以在class中加

    ​ .col-分辨率-offset-列数 相当于在左侧加了margin

    <div class="col-sm-offset-2  col-sm-10">
    div>
    
    • 如果需要让整体位置不动,某一列自己位移,可以使用

    ​ .col-分辨率-push-列数 向右移动

    ​ .col-分辨率-pull-列数 向左移动

    <div class="col-sm-push-2  col-sm-10">
    div>
    

    2.2 Bootstrap样式

    Bootstrap提供了很多样式

    1. 表格
    2. 表单
    3. 按钮
    4. 图片
    5. 辅助类

    这些样式只需要导入bootstrap的css文件即可

    2.3 Bootstrap组件

    Bootstrap提供了一系列组件

    1. 字体图标
    2. 下拉菜单
    3. 按钮式下拉菜单
    4. 输入框组
    5. 导航
    6. 导航条 等等

    Bootstrap组件需要配合bootstrap提供的js bootstrap的js依赖于jquery

    2.4 Bootstrap内置插件

    1. 模态框
    2. 标签页
    3. 工具提示
    4. 弹出框
    5. 警告框
    6. 轮播图 等等

    Bootstrap插件包含了开发过程中有可能使用的一些组件

    注意:Bootstrap官方文档中例子非常完善,可以直接从官方文档中查找需要使用的样式、组件和插件

    3.Bootstrap合作插件

    Bootstrap有很多基于bootstrap开发的插件 需要单独下载js文件

    如日期选择、开关按钮、下拉菜单、富文本编辑器等

    Bootstrap工具

    下载地址:http://www.ibootstrap.cn/ 可视化工具

    注意:使用此工具时注意是否跟使用的bootstrap版本匹配

    4. 图表插件

    1. 图表插件在国内主要使用由百度提供的Echarts
    2. Echarts通过原生js绘制图表,文件小,不需要依赖其他文件,开发人员设置json格式的参数完成个性化图表绘制
    3. Echarts可以在官网下载所需要的图表组件js文件,参考官方文档demo

    下载地址:https://echarts.apache.org/zh/index.html

    其它UI库

    layui
    nowui
    

    Servlet入门

    1. Web服务器介绍

    • Web服务器是基于B/S结构,通过http协议进行数据交互(收发)

    报文实例

    请求:
    GET  /mytest  HTTP/1.1  
    Host: www.cnblogs.com 
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0  
    .......
    
    响应:
    HTTP/1.1 200 OK
    Content-Type:text/html;charset=utf-8
     
    <html>
        <body>
           Hello http!
    body>
    html>
    
    • 简单selvet实现

    http包下

    public class MyRequest {
         
        private String method;
        private String url;
        
        public MyRequest(InputStream is){
         
            try {
         
                BufferedReader br = new BufferedReader(new InputStreamReader(is));// 01 获取请求报文
                String readHeader = br.readLine();                                // 02 获取请求报文的第一句
                String[] methodAndUrl = readHeader.split(" ");  
                // GET  /mytest  HTTP/1.1   03 以空格为条件将方法 地址放入数组
                this.method = methodAndUrl[0];  //04 取得请求报文方法
                this.url = methodAndUrl[1];     //05 取得请求报文地址
            } catch (IOException e) {
         
                e.printStackTrace();
            }
        }
    
        public String getMethod() {
                          //为了外部取该方法中定义的私有属性method
            return method;
        }
        
        public String getUrl() {
                              //为了外部取该方法中定义的私有属性url
            return url;
        }
    }
    
    public class MyResponse {
        private OutputStream writer;
    
        public static String respHeader =   "HTTP/1.1 200 OK\n" +
                                            "Content-Type:text/html;charset=utf-8\n" +
                                            "\n";   //06 响应报文头部内容
        public MyResponse(OutputStream os){
            this.writer = os;            //07
        }
        
        public OutputStream getWriter() {
            return writer;                         //07 获取到的输出流对象提供给其它类
        }
    }
    

    servlet包下

    public abstract class MyServlet {                             //08 定义  规则抽象类   为类对应的方法定义规则
    
        public void doService(MyRequest req, MyResponse resp){
            if("GET".equals(req.getMethod())){                   //09  直接抽象类判断完后  不用每个方法在重复写进行判断
                doGet(req,resp);
            }else{
                doPost(req,resp);
            }
        };
    
        public abstract void doGet(MyRequest req, MyResponse resp);   //10  定义的请求 报文的"请求方法" 的抽象方法
        public abstract void doPost(MyRequest req, MyResponse resp);  //10  定义的请求 报文的"请求方法" 的抽象方法
    
    }
    
    //实现登录功能
    public class LoginServlet extends MyServlet {
        @Override
        public void doGet(MyRequest req, MyResponse resp) {
            OutputStream out = resp.getWriter();             //11 获得到响应的输出流对象
            try {
                out.write(resp.respHeader.getBytes());       //12 写入响应报文 头部
                out.write("login ok!!!!".getBytes());        //13 接着写响应的页面代码内容
                out.flush();                                 //刷新 关闭
                out.close();                                 //接下来建立对应的properties文件
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void doPost(MyRequest req, MyResponse resp) {
        }
    }
    
    
    //实现 吟首诗
    public class QueryServlet extends MyServlet{
        @Override
        public void doGet(MyRequest req, MyResponse resp) {
            OutputStream out = resp.getWriter();
            try {
                out.write(resp.respHeader.getBytes());
                out.write("

    我的标题


    床前明月光

    ".getBytes()); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } @Override public void doPost(MyRequest req, MyResponse resp) { } }

    properties文件

    servlet.one.url=/login
    servlet.one.class=com.javasm.servlet.LoginServlet
    
    
    servlet.three.url=/query
    servlet.three.class=com.javasm.servlet.QueryServlet
    

    server包下

    public class MyServer {
    
        public static Map myMapping = new HashMap();
        //14 定义Servlet容器  通过请求 找到指定的servlet
        private static Properties prop = new Properties();
        //15 初始化properties对象
    
    
        public static void myInit(){
            try {
                prop.load(MyServer.class.getResourceAsStream("/MyMapping.properties"));   //16 获取properties位置 并加载
                Set keys = prop.keySet();                                            //17 获取properties所有Key
                for (Object key: keys){
                    if(key.toString().endsWith(".url")){
                        //18 将properties里的地址  对应方法  通过键值对放入myMapping里
                        String url = prop.getProperty(key.toString());
                        String classNameKey = key.toString().replace("url","class");
                        String className = prop.getProperty(classNameKey);
                        MyServlet ms = (MyServlet)Class.forName(className).newInstance();
                        myMapping.put(url,ms);
                    }
                }
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    
        public static void serverStart(){
            try {
                ServerSocket s = new ServerSocket(8011);      //18 开一个指定的监听的端口8011
                System.out.println("服务器开启 监听8011端口 等待访问");
                while (true){                                       // 就是让他一直开着
                    Socket soc = s.accept();                        
                    //19 拿到Socket对象  多线程开就是一个端口等待请求 多线程开启
                    MyProcess newThread = new MyProcess(soc);       //20 请求线程
                    newThread.start();                              //25 开启线程
    
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            MyServer.myInit();
            MyServer.serverStart();
        }
    
    }
    
    public class MyProcess extends Thread{
        Socket soc;                           //定义 Socket对象
        public MyProcess(Socket soc){
            this.soc = soc;
        }
    
        @Override
        public void run() {
            try{
                MyRequest req = new MyRequest(soc.getInputStream());       //21 拿到请求报文
                MyResponse resp = new MyResponse(soc.getOutputStream());   //22 拿到响应报文
                MyServlet ms = MyServer.myMapping.get(req.getUrl());       //23 通过拿到的对象的网址拿到myMapping对应的方法
                if(ms!=null){                                              //24 判断下如果是空的告诉用户没有该方法
                    ms.doService(req,resp);
                }else{
                    OutputStream out = resp.getWriter();
                    out.write(resp.respHeader.getBytes());
                    out.write("404 not  Found!!!".getBytes());
                    out.flush();
                    out.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    

    2. Tomcat下载和使用

    2.1 Tomcat介绍

    下载地址:http://tomcat.apache.org/;

    安装:下载到的是一个压缩包,解压缩即可(路径中不要有中文);

    2.2 Tomcat目录结构

    名称 作用
    /bin 存放Windows或Linux平台上用于启动和停止Tomcat的脚本文件
    /conf 存放Tomcat服务器的各种配置文件,其中最重要的是server.xml
    /lib 存放Tomcat服务器所需的各种JAR文件 //自己创建
    /logs 存放Tomcat运行中产生的日志文件
    /webapps 存放Tomcat发布的Web应用
    /work Tomcat把由JSP生成的Servlet放于此目录下
    • 启动和停止Tomcat服务器

    可通过apache解压目录中的startup.bat/shutdown.bat来启动或停止tomcat

    在浏览器地址栏中输入:http://127.0.0.1:端口号或者http://localhost:端口号,页面进入到Tomcat启动成功界面

    Tomcat默认端口号为-8080

    • 可以在conf中的server.xml中修改tomcat端口号
    <Connector port="8080" protocol="HTTP/1.1 " 
    connectionTimeout="20000" redirectPort="8443 " 	
    />
    

    2.3 Tomcat在idea中配置

    1.创建空项目
    2.配置tomcat
      右上角 edit configurations defaults 配置模板 选择tomcat真实目录
      点加号 用此模板添加一份
    3.新建模块 选javaEE  勾选 web application
    
    4.如果默认没创建好项目与tomcat的关联 手动添加artifacts   web application war exploded
    5.tomcat中加载项目 artifact 改项目名
    
    //
    

    2.4 其他web服务器

    • Jetty 更轻量级,更灵活,被一些框架集成,免费
    • JBoss JBoss支持JavaEE标准,能够作为JavaEE应用服务器使用,Servlet容器只是其

    中一部分,免费

    • Weblogic 市场上最好的J2EE工具之一,功能大而全,收费

    3. Servlet

    3.1 servlet介绍

    • Servlet是JavaEE规范中的Web开发组件;

    • Servlet运行在服务器端,需要Servlet容器的支持,例如Tomcat(运行在tomcat中);

    • 可以通过浏览器访问Servlet,Servlet可以生成动态页面返回给浏览器

    JavaWeb_第2张图片

    3.2 编写servlet

    public class TestServlet extends HttpServlet {
         //继承httpservlet 重写doGet doPost方法
    	  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         
    		  //处理代码
    	}
    	  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         
    		  doGet(request, response);
    	}
    }
    
    
    Web.xml中配置
        <servlet>
            <servlet-name> TestServlet </servlet-name>                               //name---TestServlet
            <servlet-class>com.javasm.servlet. TestServlet </servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name> TestServlet </servlet-name>                               //name---TestServlet
            <url-pattern>/TestServlet </url-pattern>
    	</servlet-mapping>
    配置中servlet-name相同作为同一组配置 
    servlet-class配置完整包名类名
    url-pattern配置开放的访问路径 该路径为虚拟的路径
    

    3.3 Servlet实现方式

    • 实现Servlet的三种方式:一个实现,两个继承
    1. 实现Servlet接口
    2. 继承GenericServlet抽象类 重写service()方法
    3. 继承HttpServlet抽象类 HttpServlet继承于GenericServlet 重写doGet(),doPost()方法 //最常用

    3.4 Servlet生命周期

    JavaWeb_第3张图片

    3.5 Servlet其他配置参数

    • servlet中配置初始化参数,可在servlet中直接读取
    配置中:
    <servlet>
            <servlet-name>HelloServlet</servlet-name>
            <servlet-class>com.javasm.servlet.HelloServlet</servlet-class>
            <init-param>
                <param-name>testParam</param-name>
                <param-value>Hello Servlet</param-value>
            </init-param>
    </servlet>
    
    代码中:
    String initParam = getInitParameter("testParam");      
    //在代码中直接将上面存储的"testParam"的值读取了
    //不过只能在 "HelloServlet" Servlet里读取得到
    
    • 配置servlet全局参数,与servlet标签同级,所有servlet都可以读取
    配置中:    //配置服务器全局参数用
     <context-param>
            <param-name>contextParam</param-name>
            <param-value>Hello Servlet</param-value>
     </context-param>
    
    代码中:
    String contextParam = getServletContext().getInitParameter("contextParam");
    //这个全局都可以得到
    
    • 配置servlet启动顺序load-on-startup
    <servlet>
            <servlet-name>HelloServlet</servlet-name>
            <servlet-class>com.javasm.servlet.HelloServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
    </servlet>
    

    注意:如果配置了load-on-startup,servlet实例会在项目启动时就加载,并且按照load-on-startup中配置的顺序加载,如果不加load-on-startup,实例会在有请求访问到该servlet时实例化

    3.6 Servlet中处理乱码

    Servlet运行在web容器(tomcat)中,tomcat默认对传递的数据使用iso-8859-1进行编码,传递中文无法正常显示。

    请求乱码:
    如果数据在传递时是正常中文,但是在servlet中取出是乱码,需要在请求对象中设置编码格式,对请求数据进行重新编码。
    request.setCharacterEncoding("UTF-8");
    响应乱码:
    如果数据在servlet中是正常中文,到页面中显示乱码,则需要在响应对象中设置响应头,让页面指定以何种编码格式解析响应数据。
    response.setContentType("text/html;charset=UTF-8");
    
    public class LoginServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("运行了");
            //获取请求的参数 getParameter
            //设置请求参数编码格式setCharacterEncoding 需要在获取之前设置
            //设置响应编码格式resp.setContentType("text/html;charset=utf-8");
            // 实际上设置在响应头中 先设置响应头 再获取输出流
    
            req.setCharacterEncoding("utf-8");              //将请求格式调整为utf-8格式
            String uname = req.getParameter("uname");
            String upwd = req.getParameter("upwd");
    
            System.out.println(uname+" ___ "+upwd);
            resp.setContentType("text/html;charset=utf-8");   //将响应后的格式调整为utf-8格式
            PrintWriter out = resp.getWriter();
            out.print("

    hello !!! "+uname+"

    "); out.flush(); out.close(); } }

    注意:如果浏览器中样式没有起效果 将web文件夹 右键

    在这里插入图片描述

    @WebServlet("/login")    //注解: 直接写请求地址   //javax包下   不用大量在web.xml写大量的配置方法;了
    public class LoginServlet extends HttpServlet {
    
    }
    

    Servlet详解

    1. Servlet线程特性

    • 肯定会有多个客户端同时请求访问一个Servlet,Web服务器怎么处理多个请求呢?

    ​ 多用户访问时,servlet会针对每个请求开启新线程来处理数据收发,因为对每个请求的处理是固定的,一次收发请求就结束。

    • 第一次访问Servlet时,服务器将创建一个该Servlet类的对象,并调用doXXX方法生成响应;多个客户端访问同一个Servlet时,不再创建新的对象,而是共用同一个Servlet对象。可以说,Servlet是多线程单实例的

    注意:多线程访问单实例的情况下,会不会产生线程安全问题?

    每个线程间,栈是独立的,运行方法时,会压入栈帧,所以运行方法时线程间不会互相影响。

    因为单实例,所以如果servlet中有成员变量,那么所有线程都会访问到同一个实例的成员变量,会造成线程安全问题

    所以使用servlet时,尽量不要建立成员变量

    2. Servlet域对象

    1. 域对象,是指服务器交互过程中可以用来存储数据的空间,相对独立,生效的时机不同,都可以用来存储信息
    2. Servlet三大域对象的应用
    • Request

      一个用户可有多个

      每次请求都会产生一个

      请求结束对象消失

      建议用于页面间值的传递

    • Session

      一个用户一个

      每一个浏览器都会产生一个

      会话过期或者关闭浏览器对象消失

      建议存放一些用户信息,不要把过多的信息存放在session里

      invalidate 设置session失效

    • ServletContext(application)

      全局只有一个

      是一个全局的储存信息的空间,服务器开始就存在,服务器关闭才释放。

      为了节省空间,提高效率,只存放少量的重要信息

    域对象统一方法

    void setAttribute(String key,Object value) 以key/value的形式保存对象值
    Object getAttribute(String key) 通过key获取对象值

    3. Servlet中常用类和方法

    3.1. ServeltContext接口
    方法 说明
    public void setAttribute (String name,Object object) 绑定一个java对象和一个属性名,并存放到ServletContext中,参数name指定属性名,参数Object表示共享数据
    pulbic Object getAttribute (String name) 根据参数给定的属性名,返回一个Object类型的对象
    public String getContextpath() 返回当前web应用的URL入口
    public String getInitParameter (String name) 返回web应用范围内匹配的初始化参数值。在web.xml中,元素中的元素表示应用范围内的初始化参数
    3.2. ServletConfig接口
    方法 说明
    public String getInitParameter(String path) 获取web.xml中指定Servlet的初始化参数值
    public ServletContext getServletContext() 获取ServletContext实例
    public String getServletName() 获取当前Servlet的名称
    3.3. HttpRequest(很常用)
    方法 说明
    public String getParameter (String name) 获取页面提交指定名称的参数值
    public String[] getParameterValues(String name) 获取页面提交相同名称参数的数组值
    public void setCharacterEncoding(“UTF-8”) 设置字符编码格式
    public Map getParameterMap() 返回一个保存了请求的所有参数和值的Map对象
    public void setAttribute (String name,Object obj) 向request范围内设置属性,参数name为属性名,obj为属性值
    public Object getAttribute (String name) 返回一个请求中属性名为name的属性值
    public String getContextPath() 返回当前Web项目的根路径
    • Request对象中封装了很多获取跟http相关的路径的方法
    request.getContextPath();     项目名/WebDemo
    request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";  
    结果如下:http://localhost:8080/WebDemo/  
    request.getRemoteAddr()      客户端ip地址
    request.getServletPath()       请求的servlet的地址/student
    request.getRealPath("/")       在tomcat中的路径
    request.getRequestURI();       获得请求路径 /web_demo/student
    
    3.4. HttpResponse
    方法 说明
    Public PrintWriter getWriter() 获取响应的打印输出流对象
    Public void setContentType (“text/html;charset=UTF-8”) 设置响应内容的类型和字符编码格式

    Response对象中主要封装跟输出信息相关的方法

    3.5. HttpSession
    方法 说明
    setAttribute (String key,Object value) 以key/value的形式保存对象值
    getAttribute(String key) 通过key获取对象值
    getMaxInactiveInterval() 获取session的有效非活动时间,以秒为单位
    getId() 获取session对象的编号
    invalidate() 设置session对象失效
    • Session使用

    HttpSession session = request.getSession();

    从request对象中获取会话(session)对象每个浏览器都会产生单独的session对象

    session作为会话对象,经常用来保存用户的相关登录信息,方便服务器调用(用户本身信息,权限信息等)

    * session  做域对象 存跟用户相关数据
    * session  控制访问流程 根据有没有指定的key 判断用户是否执行过某个流程(servlet)
    *          登陆访问控制
    
    • 例:用户登录,通过session做是否已登录的访问控制

    jsp

    1. JSP介绍

    1.1 什么是JSP

    • JSP(Java Server Page)是JavaEE规范中的Web组件,用来编写动态页面;
    • JSP文件以.jsp为后缀,在工程目录中存在WebContent目录下,跟静态资源使用方式非常相似;
    • JSP文件中的内容就是 HTML+Java代码,静态部分使用HTML和文本即可,动态部分使用Java代码;

    1.2 Jsp本质

    • 结合由tomcat自动生成的jsp相关java文件,

    理解Web容器处理JSP文件请求需要经过3个阶段

    1. 翻译阶段
    2. 编译阶段
    3. 执行阶段

    1、翻译:Web服务器找到test.jsp,对其进行翻译,生成test_jsp.java文件;查看路径: 工作空间 work\Catalina\localhost

    2、编译:服务器将test_jsp.java编译成类文件,翻译和编译的过程遵守Servlet规范,

    3、实例化并提供服务:服务器实例化类,调用类中的_jspService方法提供服务

    • 总结:
    1. Servlet生成动态页面比较繁琐,使用JSP生成动态页面比较便捷,因为其中的静态内容可以使用HTML生成;
    2. JSP的执行过程是:翻译-编译-实例化-提供服务;
    3. JSP的本质就是Servlet,不过是服务器将JSP进行了翻译和编译;可以说,JSP也是一个Java类;

    2. Jsp语法格式

    Jsp中嵌入java代码的格式

    	Page指令(配置页面基本信息)
    <%@ page 属性1="属性值" 属性2="属性值1,属性值2"… 属性n="属性值n"%>
    
    	Include指令(file="路径" 使用项目相对根路径 不需要手动拼项目名
                      作用:  1.引入公用的html部分
                            2.引入公用的java部分)
         <%@ include file="left.jsp" %>        //引入了文件名为left的
    
    	小脚本
    <%	%>     小脚本中可以直接声明变量
    
    	输出信息到页面
    <%=	%>   直接输出信息到页面,不能带分号
    
    	声明
    <%! %>      声明中定义方法
    
    	注释   
    <%-- --%>  与区别 <%-- --%>不出现在页面中
    

    3. Jsp九种内置对象及4种作用域

    3.1 什么是的内置对象

    • Jsp文件翻译成java文件时,有一些对象被自动写在了java文件中,这些被自动写进去的对象叫内置对象。

    3.2 九种内置对象

    1、request对象
    request 对象是 javax.servlet.httpServletRequest类型的对象。 该对象代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据。(包括头信息、系统信息、请求方式以及请求参数等)。request对象的作用域为一次请求。
    
    2、response对象
    response 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。response对象也具有作用域,它只在JSP页面内有效。
    
    3、session对象
    session 对象是由服务器自动创建的与用户请求相关的对象。服务器为每个用户都生成一个session对象,用于保存该用户的信息,跟踪用户的操作状态。session对象内部使用Map类来保存数据,因此保存数据的格式为 “Key/value”。 session对象的value可以使复杂的对象类型,而不仅仅局限于字符串类型。
    
    4、application对象
    application 对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效。与session对象相比,application对象生命周期更长,类似于系统的“全局变量”。
    
    5、out 对象
    out 对象用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓冲区。在使用 out 对象输出数据时,可以对数据缓冲区进行操作,及时清除缓冲区中的残余数据,为其他的输出让出缓冲空间。待数据输出完毕后,要及时关闭输出流。
    
    6、pageContext 对象
    pageContext 对象的作用是取得任何范围的参数,通过它可以获取 JSP页面的out、request、reponse、session、application 等对象。pageContext对象的创建和初始化都是由容器来完成的,在JSP页面中可以直接使用 pageContext对象。
    
    7、config 对象
    config 对象的主要作用是取得服务器的配置信息。通过 pageConext对象的 getServletConfig() 方法可以获取一个config对象。当一个Servlet 初始化时,容器把某些信息通过 config对象传递给这个 Servlet。 开发者可以在web.xml 文件中为应用程序环境中的Servlet程序和JSP页面提供初始化参数。
    
    8、page 对象
    page 对象代表JSP本身,只有在JSP页面内才是合法的。 page隐含对象本质上包含当前 Servlet接口引用的变量,类似于Java编程中的 this 
    
    9、exception 对象
    exception 对象的作用是显示异常信息,只有在包含 isErrorPage="true" 的页面中才可以被使用,在一般的JSP页面中使用该对象将无法编译JSP文件。excepation对象和Java的所有对象一样,都具有系统提供的继承结构。exception 对象几乎定义了所有异常情况。在Java程序中,可以使用try/catch关键字来处理异常情况; 如果在JSP页面中出现没有捕获到的异常,就会生成 exception 对象,并把 exception 对象传送到在page指令中设定的错误页面中,然后在错误页面中处理相应的 exception 对象。
    

    3.3 四种作用域

    使用的对象          作用域名  
    ServletContext        application域
    HttpServletRequet  	request域
    HttpSession        	session域
    PageContext        	page域
    

    4. Jsp与servlet配合使用

    4.1 Jsp与servlet分工

    servlet与jsp一般配合使用
    servlet 请求接收 数据控制(调用业务方法) 控制由哪个页面展示结果
    jsp     展示数据 静态技术  少量java代码
    

    4.2 跳转方式

    • 响应重定向
    响应重定向 通过response对象调用,让浏览器向重定向的地址重新发送一次请求
    response.sendRedirect("error.jsp");
    

    注意:因为重定向会发送新的请求,会导致第一次请求的相关数据在第二次请求中读取不到,如果我们需要这些数据可以使用转发的跳转方式。

    • 请求转发
    请求转发 通过request对象调用,把请求对象和响应对象与要跳转的地址共享
    request.getRequestDispatcher("showIP.jsp").forward(request, response);
    
    • 两者区别
    转发(较常用效率更高) 重定向
    浏览器URL不变 浏览器URL的地址栏改变
    服务器行为(服务器内部) 客户端行为(告诉客户端重新请求)
    浏览器只做了一次访问请求 浏览器做了至少两次的访问请求的
    2次跳转之间传输的信息不会丢失 2次跳转之间传输的信息会丢失(request范围)
    跳转方式
             1.响应 重定向   浏览器发起多次请求
             servlet jsp 关联不紧密
            
              路径方式
              1.相对路径         通过../   退出目录  /目录名   进入目录
              2.项目相对根路径    /项目名/资源地址
              3.绝对路径         协议://地址/资源地址
            
             2.请求 转发     浏览器发起一次请求  多个处理单元 共享req resp
             servlet jsp 关联紧密 比较复杂的对象 集合的展示
                         使用request域 传值
                         req.setAttribute("testuser",u1);
            
               路径方式(只能在当前服务器跳转)
               1.相对路径
               2.项目相对根路径   /项目名(自动拼接 不需要手动写)   /资源地址
    

    5.El表达式和jstl标签

    1. El表达式

    1.1 El表达式特点
    • 自动转换类型

    EL得到某个数据时可以自动转换类型

    对于类型的限制更加宽松

    • 使用简单

    相比较在JSP中嵌入Java代码,EL应用更简单

    • EL的语法

    以"${“作为开始,以”}"作为结束

    1.2 El表达式操作
    request域中
    request.setAttribute(“testuser”,myuser);
    使用el表达式取域中user对象的username属性,并输出到页面
    ${testuser.username}
    
    操作符“.”
    获取对象的属性,例如:${news.title}
    
    操作符“[]”
    获取集合中的对象,例如:${newsList[0]}
    
    //${empty newsList}   //true 则是里面为空  false 则是不为空                 //一般${not empty newsList}判断
    

    El表达式中允许使用运算符

    JavaWeb_第4张图片

    1.3 El表达式隐式对象

    EL表达式包含一些隐式对象

    • 作用域访问对象 可用来指定从某个域中取值 默认从上到下取值
    • ( $(requestScope.testuser.username) 表示从requestScope里找 testuser这个对象 不加 默认从上到下)

    pageScope

    requestScope

    sessionScope

    applicationScope

    • 参数访问对象 可指定从request的参数部分取值

    param

    paramValues

    • Jsp配置对象

    pageContext

    pageContext.request.contextPath ----> 项目根路径

    2. Jstl标签

    1.1. Jstl标签作用
    • El表达式主要是取值和输出功能,需要配合jstl标签来完成逻辑控制(条件判断、循环)

    • JSTL(JavaServerPages Standard Tag Library) jsp基本标签库,主要用来替换页面中跟逻辑判断相关的java代码,经常和el表达式配合使用

    1.1. Jstl使用

    Jstl需要jar包支持

    http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/

    下载jstl.jarstandard.jar

    在使用jstl的页面中,需要加入taglib指令,导入核心标签库

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

    1.2 Jstl中常用标签

    通用标签

    set:设置指定范围内的变量值

    out:计算表达式并将结果输出显示

    remove:删除指定范围内的变量

    	 //var--key键   value--值   scope---放在哪个域
    <c:out value="${example}"/>                                  //out:输出显示
                       //remove:删除
    

    条件标签

    If:条件判断语句

    <c:if test="${empty loginUser }" var="islogin" scope="session">
    
    		<c:redirect url="testEL.jsp">c:redirect>
    c:if>
    
    
    <c:if test="${not islogin}">
    
    	已登录
    c:if> 
    

    迭代标签

    forEach:遍历集合中的元素时使用

    <c:forEach items="${listEitity }" var="myentity">
    			<tr><td>${myentity.ename }td><td>${myentity.eage }td><td>${myentity.eaddr }td>tr>
    
    c:forEach>
    
    
    例子:
    <table class="table">
        <thead>
        <tr><th>用户idth><th>姓名th><th>密码th><th>备注th><th>电话th>tr>
        thead>
        <tbody>
        <c:forEach items="${listUser}" var="myuser">
            <tr>
                <td>${myuser.userId}td>
                <td>${myuser.userName}td>
                <td>${myuser.userPwd}td>
                <td>${myuser.userPhone}td>
                <td>${myuser.userRemark}td>
            tr>
        c:forEach>
        tbody>
    table>
    

    6.Cookie

    1 会话跟踪

    • 什么叫会话跟踪

    ​ 在无状态(一次请求响应就结束)的HTTP协议下,想要跟踪用户的路径(知道是谁,在干什么,要去哪)需要通过其他技术来辅助实现。

    • 会话跟踪实现方式

    ​ 常用的会话跟踪技术有四种

    1. URL方式:需要保存的信息直接追加到URL后,
    例如:http://127.0.0.1:8080/chapter03/viewList?pageNo=12
    
    2. 隐藏域方式:可以使用表单中的隐藏域保存相关信息, 例如:
    input type="hidden" name="status" value="true">
    
    3. Session方式:将状态信息保存到服务器的会话对象中,通过唯一标记的ID值
    与客户端进行绑定使用;例如访问控制功能就可以使用Session实现
    
    4. Cookie方式:将状态信息保存到客户端,服务器能够获得相关信息进行分析,
    从而生成对客户端的响应;例如简化登录功能就可以使用Cookie实现;
    

    2 Cookie介绍

    • Cookie译为小型文本文件或小甜饼,Web应用程序利用Cookie在客户端缓存服务器端文件。Cookie是以键值对形式存储在客户端主机硬盘中,由服务器端发送给客户端,客户端再下一次访问服务器端时,服务器端可以获取到客户端Cookie缓存文件。
    • Cookie是由服务器端创建的,然后由服务器端发送给客户端,客户端以键值对形式存储Cookie,并标注Cookie的来源。客户端再次访问服务器端时,存储的Cookie会保存在请求协议中,服务器端可以获取上次存储的缓存文件内容。

    Cookie特点

    • Cookie的用途:

      电子商城中购物车功能(每买一样商品,保存一个Cookie)

      用户自动登录功能(第一次登录时,将用户名和密码存储在Cookie)

    • Cookie的缺点:

      多人共用一台计算机(例如导致用户名和密码不安全等问题)。

      Cookie被删除时,利用Cookie统计用户数量出现偏差。

      一人使用多台计算机(网站会将看成多个用户等问题)

      Cookie会被附加在每次Http请求协议中,增加流量。

      Cookie使用明文(未加密)传递的,安全性低。

      Cookie的大小限制在4KB左右,无法存储复杂需求。

    • Cookie规范

      Http协议提供了有关Cookie的规范,现今市场上出现大量浏览器,一些浏览器对该Cookie规范进行了一些“扩展”,但Cookie缓存文件不会占满硬盘空间。

      Cookie存储的大小上限为4KB。

      一个服务器最多在客户端浏览器中可以保存20个Cookie。

      一个浏览器最多可以保存300个Cookie。

    3 Cookie主要属性

    name:cookie的名字,每个cookie都有一个名字;
    content:cookie的值,与名字一起作为键值对形式存在;
    domain:域,该cookie的域名,例如csdn.net,说明当前cookie来自csdn.net;
    path:路径,访问csdn.net下该路径时,当前cookie将被发送;
    created:cookie被创建的时间;
    Expired:cookie失效的时间;
    最大生命时间:失效时间和创建时间的时间差,就是cookie的最大生命时间,超过该时间,cookie将失效,不再被发送到相应的域地址;
    
    //cookie在浏览器中 可以修改 可以禁用
    //只放跟用户相关的数据(不要放关键数据)
    

    4 Cookie操作(java部分)

    	写cookie
    //创建/修改cookie对象,键值对形式
    Cookie cookie = new Cookie("username", "admin");
    
    //设置过期时间 单位秒,删除Cookie只需要修改过期时间为负数
    //正数 有效秒    0  设置cookie失效    负值 -1  设置为浏览器关闭即失效
    cookie.setMaxAge(60*60);
    //cookie还可以设置path等信息
    
    //cookie对象存入response,响应给浏览器,浏览器接受到响应数据时才会把cookie存储在本地
    response.addCookie(cookie);    //写Cookie 最后必须有这一步
    
    	读cookie
    //从request对象中取值
    Cookie[] cookies = request.getCookies();
    //循环输出值
    for(Cookie ck : cookies){
         
    	 String ckkey = ck.getName();   //键:
    	String ckval = ck.getValue();   //值:
    }
    
    
    //JSESSIONID  服务器自动创建的cookie  值是cookie的id
    //服务器是否重新创建cookie 是由jsessionid决定的
    

    5 Cookie操作(js部分 即浏览器那边)

    	Cookie写
    document.cookie="jscook=jsval1;path=/;expires="+new Date("2021-11-11 11:11:11");
    //直接创建--> jscook-键 jsval1-值; path=/ 路径是/; 到期时间2021-11-11 11:11:11   
    
    	Cookie读
    var cookie =  document.cookie //读到键值对格式的字符串 如果需要找到特定key的value需要手动解析    //只有键值对
    var mycks = document.cookie.split(";");
    		$.each(mycks,function(i,d){
         
    			var kvarr = d.split("= ");
    			console.log("key是:"+ kvarr[0]+" value是:"+kvarr[1]);
    		})
    
    	删除cookie
    //document.cookie ="jskey=jsval2;path=/;expires="+new Date("2011-11-11 11:11:11");
    document.cookie="jskey=jsval;path=/;expires="+new Date(now.getTime()-1000).toGMTString(); //上一秒时间直接让他过期
    

    注意:cookie在使用时,相同domain,不同path下可以存储同名cookie,为了让cookie设置统一,和解决cookie读取权限问题,经常会把cookie的path直接设置到根/

    7 Web storage使用

    • HTML5 提供了两种在客户端存储数据的新方法 统称Web storage:

    localStorage - 没有时间限制的数据存储

    sessionStorage - 针对一个 session 的数据存储,数据在浏览器关闭后自动删除

    • Web storage是一种设计由前端存储数据的技术,跟cookie有相似之处,但是因为设计给前端使用,所以操作上比cookie方便很多

    • Web storage操作

    localStorage.username = "admin";//设置值
    console.log(localStorage.username)//取值
    localStorage.setItem("user", "user_name");//设置值
    console.log(localStorage.getItem("user"));//取值
    
    //以上两种方式存值/取值都可以
    localStorage.removeItem("user");//移除指定的key
    localStorage.clear();//清空所有的数据
    

    注意:sessionStorage用法同localStorage

    Web storage是前端的技术,跟服务端的session对象无直接关系

    Web storage没有默认随请求发送到服务器的机制

    Ajax

    1.Ajax原理

    浏览器中的线程状态:

    js是单线程的,那么是否代表参与js执行过程的线程就只有一个?

    不是的,会有四个线程参与该过程,但是永远只有JS执行引擎线程在执行JS脚本程序,其他的三个线程只协助,不参与代码解析与执行。参与js执行过程的线程分别是:

    JS****执行引擎线程: 也称为JS内核,负责解析执行Javascript脚本程序的主线程(例如V8引擎)

    事件触发线程: 归属于浏览器内核进程,不受JS引擎线程控制。主要用于控制事件(例如鼠标,键盘等事件),当该事件被触发时候,事件触发线程就会把该事件的处理函数推进事件队列,等待JS引擎线程执行

    定时器触发线程:主要控制计时器setInterval和延时器setTimeout,用于定时器的计时,计时完毕,满足定时器的触发条件,则将定时器的处理函数推进事件队列中,等待JS引擎线程执行。
    注:W3C在HTML标准中规定setTimeout低于4ms的时间间隔算为4ms。

    HTTP异步请求线程:通过XMLHttpRequest连接后,通过浏览器新开的一个线程,监控readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进事件队列中,等待JS引擎线程执行。
    注:浏览器对通一域名请求的并发连接数是有限制的,Chrome和Firefox限制数为6个,ie8则为10个。

    总结:永远只有JS引擎线程在执行JS脚本程序,其他三个线程只负责将满足触发条件的处理函数推进事件队列,等待JS引擎线程执行。

    ajax由js编写,使用XMLHttpRequest 对象对数据收发进行封装,

    发送ajax请求时,ajax会要求调用方(浏览器)开启新线程向服务器进行请求,并对响应的结果进行反复读取,当读取到特定状态后,停止反复读取。读取过程中会把需要运行的js(回调函数)添加入js的执行队列(js执行引擎为单线程),js执行引擎按队列顺序执行。

    2. 原生ajax代码步骤

    • 创建XMLHttpRequest对象

    • 设置回调函数

    • 初始化XMLHttpRequest组件(设置)

    • 发送请求

    //异步请求 局部刷新(通过回调函数 控制服务器返回的数据)   无刷新(接收到响应数据后 浏览器不跳转)
    //发送异步请求 通过回调函数 处理服务器的响应数据
    //回调函数的处理需要与服务器响应数据搭配
    
    <%--
      Created by IntelliJ IDEA.
      User: JAVASM
      Date: 2020/8/15
      Time: 10:03
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
        <script src="js/jquery-3.4.1.min.js">
        </script>
        <script>
    
    
            $(function(){
         
                $("#myBtn").click(function(){
         
                    myAjaxReq();
                })
            })
            //原生ajax调用过程
            function myAjaxReq(){
         
                //XMLHttpRequest  ajax核心对象
                var xmlhttp;
                if (window.XMLHttpRequest){
         // code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp=new XMLHttpRequest();
                }
                else{
         // code for IE6, IE5
                    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                }
    
                //回调函数 当请求正常返回时 用js操作页面
                xmlhttp.onreadystatechange=function(){
         
                    //readyState ajax请求的状态 4代表请求发送完成
                    //status     http的状态    200代表正确返回
                    if (xmlhttp.readyState==4 && xmlhttp.status==200){
         
                        //处理响应的代码
                        //xmlhttp.responseText  获取服务器响应的数据
                        console.log(xmlhttp.responseText);
                        document.getElementById("showRes").innerHTML=xmlhttp.responseText;
                    }
                }
                //设置请求的地址 方式 是否使用异步
                //初始化异步请求对象
                xmlhttp.open("POST","ajaxDemo",true);
                //设置请求头
                xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
                //设置发送的参数
                //method不同 发送数据的格式不同?
                xmlhttp.send("mytest="+document.getElementById("mytext").value);
            }
    
    
    
        </script>
      </head>
      <body>
        <input id="myBtn" type="button" value="发送异步请求">
        <hr>
        <input id="mytext" type="text">
        <span id="showRes"></span>
      </body>
    </html>
    
    • XMLHttpRequest对象的属性和方法

    JavaWeb_第5张图片
    JavaWeb_第6张图片

    注意:使用ajax时参数需要自己传递,get方式把参数直接拼接在url后,post方式把参数写在send方法的参数中。

    3. JqueryAjax

    原生ajax配置格式不规整,使用使用时经常使用jquery优化后的ajax

    //jquery封装的ajax请求
    //通过json格式设置参数
    			$.ajax({
         
    				url:"ajaxServlet",//地址
    				type:"post",//请求类型
    				data:{
         "uname":$("#username").val()}, //请求的参数 常用json格式
    				dataType:"text",//返回数据的类型
    				success:function(data){
         //响应成功时的回调函数 data表示返回的数据
    					console.log(data);
    				}
    			});
    
    
    //例子:
        <script>
            $(function(){
         
                $("#myBtn").click(function(){
         
                    
                    $.ajax({
         
                        url:"ajaxDemo",//地址
                        type:"post",//请求类型
                        data:{
         "mytest":$("#mytext").val()}, //请求的参数 常用json格式  或者普通键值对   一般用json格式
                         //普通键值对---{"mytest":$("#mytext").val()}              
                        dataType:"json",//返回数据的类型
                        success:function(data){
         //响应成功时的回调函数 data表示返回的数据
                            console.log(data);
                            $("#showRes").html(data);
                        }
                    });                                              
                    
               //简化格式     
                    $.get("ajaxDemo",
                          "mytest":$("#mytext").val()    //"mytest="+$("#mytext").val()+"&test=abc123",
                          function(data){
         
                        	console.log(data);
                    	  },"text")
    
                })
            })
        </script>
    

    Jquery中简化ajax,json格式改为固定参数

    $.post(
    //发送的请求地址
    //要发送的数据key/value,
    //回调函数,
    //返回内容格式,xml,html,script,json,text
    )
    $.get(
    //发送的请求地址
    //要发送的数据key/value,
    //回调函数,
    //返回内容格式,xml,html,script,json,text
    )
    

    进一步简化

    .getJSON(
    “发送地址”,
    发送参数,
    回调函数
    )
    

    注意1:使用ajax时,需要自己拼接参数,可以使用$("#myform").serialize(),把form序列化成键值对字符串格式。

    注意2:后台可以借助fastJSON工具,给前台返回json格式字符串。

    // ajax使用例子
    
    //定义响应码   10000 成功  10001 有点成功  20000失败 20001 有点失败
    //回调返回的数据   传json  拼成标准json格式  key带引号
    //gson  jackson   fastjson(China 阿里 用它)
    //returnCode  returnMSG   returnData
    //为了让返回数据标准化
    
    
    /*
    * ReturnEntity  规范返回数据的key
    * ReturnCode   规范返回数据的 Code MSG 的值
    */
    
    
    //ReturnCode   规范返回数据的 Code MSG 的值
    public enum ReturnCode {
         
        SUCCESS(10000,"操作成功"),
        FAILED(20000,"操作失败"),
        UNAME_OK(10001,"用户名可用"),
        UNAME_DUPLICATE(20001,"用户名重复");
        
        Integer code;
        String msg;
    
        private ReturnCode(Integer code,String msg){
         
            this.code = code;
            this.msg = msg;
        }
    
        public Integer getCode() {
          return code; }
        public String getMsg() {
          return msg; }
    }
    
    
    //ReturnEntity  规范返回数据的key
    public class ReturnEntity {
         
        //returnCode  returnMSG   returnData
        private Integer returnCode;
        private String returnMSG;
        private List returnData;
    
        public Integer getReturnCode() {
         return returnCode;}
        public void setReturnCode(Integer returnCode) {
         this.returnCode = returnCode;}
        public String getReturnMSG() {
         return returnMSG;}
        public void setReturnMSG(String returnMSG) {
         his.returnMSG = returnMSG;}
        public List getReturnData() {
         return returnData;}
        public void setReturnData(List returnData) {
         this.returnData = returnData;}
        public ReturnEntity(Integer returnCode, String returnMSG, List returnData) {
         
            this.returnCode = returnCode;
            this.returnMSG = returnMSG;
            this.returnData = returnData;
        }
        public ReturnEntity() {
         
        }
    }
    
    
    
    //异步调用的页面
    @WebServlet("/checkUname")
    public class CheckServlet extends HttpServlet {
         
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            ReturnEntity reEntity = new ReturnEntity();
            req.setCharacterEncoding("utf-8");
            String uname = req.getParameter("uname");
            resp.setContentType("text/html;charset=utf-8");
            PrintWriter writer = resp.getWriter();
            String resStr = "";
            if("jack".equals(uname)){
         
                reEntity.setReturnCode(ReturnCode.UNAME_DUPLICATE.getCode());
                reEntity.setReturnMSG(ReturnCode.UNAME_DUPLICATE.getMsg());
            }else{
         
                reEntity.setReturnCode(ReturnCode.UNAME_OK.getCode());
                reEntity.setReturnMSG(ReturnCode.UNAME_OK.getMsg());
            }
            resStr = JSON.toJSONString(reEntity);    // fastjson(China 阿里 用它)  将数据转换成了json串
            writer.print(resStr);
            writer.flush();
            writer.close();
        }
    }
    
    
    
    //显示页面
    <%--
      Created by IntelliJ IDEA.
      User: JAVASM
      Date: 2020/8/15
      Time: 10:51
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
        <style>
            .mysuccess{
         
                color: greenyellow;
            }
            .myfailed{
         
                color: lightcoral;
            }
        </style>
        <script src="js/jquery-3.4.1.min.js">
        </script>
        <script>
            $(function(){
         
                $("#uname").change(function()                                       //文本框改变发启用
                    $.post("checkUname",{
         "uname":$(this).val()},function(data){
         
                        if(10001==data.returnCode){
         
                            $("#checkNameSpan").removeClass("myfailed")
                            $("#checkNameSpan").addClass("mysuccess")
                        }else if(20001==data.returnCode){
         
                            $("#checkNameSpan").removeClass("mysuccess")
                            $("#checkNameSpan").addClass("myfailed")
                        }
                        $("#checkNameSpan").html(data.returnMSG);
                    },"json")
                })
            })
    
        </script>
    </head>
    <body>
        <form action="/day5/regist" method="post">
            <input id="uname" type="text" placeholder="请输入用户名"><span id="checkNameSpan"></span><br>
            <input type="text" placeholder="请输入密码"><br>
            <input type="text" placeholder="请输入电话"><br>
            <input type="text" placeholder="请输入邮箱"><br>
            <input type="submit"><br>
        </form>
    </body>
    </html>    
    

    分页

    1.分页实现思路

    • 1.查询列表时默认显示固定数量的数据

    • 2.算出当前符合条件的所有数据的总页码数

    • 3.显示上一页下一页按钮

    • 4.每次点击按钮是判断是否是首尾页

    • 分页功能需要页面显示与数据查询同步进行。

    分页的功能需要由数据库语句体现,mysql数据库中分条显示数据语句:

    select uid,uname,upwd,unick_name,uage,uaddr from my_user limit  0  ,  5
    如果page从1开始,那么这两个值的关系      (page-1)*pageSize  ,  pageSize;
    

    在dao中 可以接收参数 来拼接查询语句。

    public interface UserDao {
         
    	List<MyUser> queryUser(int page,int pageSize);
    }
    

    在给用户显示页面时,需要把将要访问的页数写进页面,当用户点击翻页时,后台可以接收到数据并根据页数查找数据

    <a class="btn" href="${pageContext.request.contextPath }/queryUser?page=${page+1 }">下一页
    a>
    

    判断按钮是否可用时需要知道以当前的每页显示记录数总共有多少页数据,此数据是通过总记录数和每页显示记录数算出的

    int totalpage =
    totalnum%pageSize==0?totalnum/pageSize:(totalnum/pageSize)+1;
    //如果总记录数能被每页显示记录数整除,那总页数直接相除得到,
    //如果不能整除,剩余部分需要多占一页
    

    总结:在后台计算页数,并把上一页、下一页要查询的参数提前在后台生成好,生成在页面中,用户点击生成好的链接,在后台查询新的数据,同时生成新的上一页、下一页的参数。以此完成页数前端与后台的同步

    2. 分页与条件查询

    • 查询功能中经常有通过特定条件对记录进行筛选。

    多条件时,用户如果填写有内容,则数据库语句需要拼接上此条件,如果没有时此条件不拼接。条件查询经常需要和分页功能同时存在

    • 多条件查询拼接
    List<Object> params = new ArrayList<Object>();	//存放参数列表	
    boolean isWhere = true;     //通过开关判断是否要拼接where
    		if(quser.getUname()!=null&&!"".equals(quser.getUname())) {
         //判断条件是否存在
    			if(isWhere) {
                              //判断是否拼接where
    				sql+=" where "+ " uname = ? ";  //拼接where
    				isWhere = false;              //把拼接where的标记改为false
    			}else {
                                   //否则拼接and
    				sql+=" and "+ " uname = ? ";
    			}
    			params.add(quser.getUname());     //把此条参数放入保存参数的list中
    		}
    
    psta = conn.prepareStatement(sql);
    		int paramIndex = 1;
    		for(Object param: params) {
                  //设置查询参数时 把list列表中的参数直接读出
    			psta.setObject(paramIndex, param);//一个个按位设置给prepareStatement对象
    			paramIndex++;
    		}
    	  rs = psta.executeQuery();
    

    注意:查总记录数的语句需要与分条查询语句查询条件相同

    • 页面中翻页时,查询条件需要一起发送到后台,页面中可以利用表单中的隐藏域
    <form id="qform" action="${pageContext.request.contextPath }/queryUser" method="post" >
    
    	  <input id="page"  name="page"  type="hidden">
    <input id="pageSize" name="pageSize" type="hidden" name="pageSize">
    
    	  <input type="submit" class="btn btn-success" value="查询">
    	form>
    
    $("#page").val(gopage); //js操作时 给隐藏域中的属性设置值
    $("#qform").submit();  //通过js触发表单提交
    

    3. Ajax分页

    当条件查询与分页合在一起使用时,为了处理查询条件与页数同时同步,代码处理上较为麻烦,如果改成页面不刷新,只改变部分数据,逻辑结构上会更加清晰

    • 页面不跳转,查询数据都保留在页面中

    • 页面中通过js创建变量,保存当前翻到第几页

    • 每次查询请求,将页面上的查询数据和页数发送到后台,后台返回数据和最新的页数,页面接收到数据,把数据的部分替换到页面中,并更新js中保存页数相关的变量

    服务器部分进行配合ajax响应的改造,改为向页面输出json格式字符串

    Map<String,Object> returnMap = new HashMap<String,Object>();
    		returnMap.put("returnCode", "10000");  //状态码(公司自己定义)
    		returnMap.put("returnData", lu);       //数据库查询出的数据
    		returnMap.put("pageInfo", pif);        //页数相关数据
    		String returnstr = JSON.toJSONString(returnMap);//转成json格式字符串
    		pw.print(returnstr);
    

    前端部分改造成ajax请求

    $.ajax({
         
    			url:"ajaxQueryUser",//地址
    			type:"post",//请求类型
    			data:mydata,   //请求的参数 键值对字符串  json格式
    			dataType:"json",//返回数据的类型
    			success:function(data){
         //响应成功时的回调函数
    				//console.log(data.returnData);
    				$("#mainData").html("");//清空之前的数据
                //遍历返回的数据,填入到页面
    				$.each(data.returnData,function(i,d){
         
    					var newdata = ""+d.uid+""+d.uname+""
    						+""+d.age+""+d.uNickname+""
    						+""+d.uaddr+""
    					$("#mainData").append(newdata);
    				})
    				//更新页数相关变量,更新页面显示页码
    				page = data.pageInfo.page;
    				pagesize = data.pageInfo.pageSize;
    				totalpage = data.pageInfo.totalPage;
    				//$("#myMsg").html(data);
    				$("#showPage").html(page);
    				$("#showSize").html(pagesize);
                    $("#showTotal").html(totalpage);
                    //重置按钮禁用状态
    				initBtn();
    			}
    		});
    

    4.增删改思路

    添加
    添加页面
    后台接收到用户发送的数据 --》做数据合法性验证 --》调用添加方法
    跳转到显示结果页面
    跳转到查询
    
    修改
    把当条记录的标记传递到后台 通过id查询该记录的完整信息
    修改页面  展示该记录的信息
    后台接收到用户发送的数据 --》做数据合法性验证 --》调用修改方法
    跳转到显示结果页面
    跳转到查询
    
    删除
    把当条记录的标记传递到后台 --》做数据合法性验证 --》调用删除方法
    跳转到显示结果页面
    跳转到查询
    

    5.案例

    //param() 方法创建数组或对象的序列化表示。
    //该序列化值可在进行 AJAX 请求时在 URL 查询字符串中使用。
    实例
    序列化一个 key/value 对象:
    var params = {
          width:1900, height:1200 };
    var str = jQuery.param(params);
    $("#results").text(str);
    结果:
    width=1680&height=1050
    
        
    //ajaxShowUser.html  页面
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8"/>
        <title>Title</title>
        <link rel="stylesheet" href="css/bootstrap.css">
        <script src="js/jquery-3.4.1.min.js"></script>
        <script src="js/bootstrap.min.js"></script>
        <script>
            var page;
            var pageSize;
            var totalPage;
            var selectRow=[];                   
    /*
    *
    *       *  page
            *  pageSize
            *  quname
            *  quremark
    *
    * */
            $(function(){
         
                myQuery("");                        //初始化myQuery方法  防止查询页面是空的 
    
                $("#submitBtn").click(function(){
         
                   //取界面上的值放入params
                    var params = {
         "quname":$("#quname").val(),"quremark":$("#quremark").val()};        
                    myQuery(params);
                })
    
                $("#prevBtn").click(function(){
         
                    var params = {
         "quname":$("#quname").val(),"quremark":$("#quremark").val(),
                                  "page":page-1,"pageSize":pageSize};
                    myQuery(params);
                })
                $("#nextBtn").click(function(){
         
                    var params = {
         "quname":$("#quname").val(),"quremark":$("#quremark").val(),
                                  "page":page+1,"pageSize":pageSize};
                    myQuery(params);
                })
                //打开修改面板
                //优化版本
                //已经在点击某个数据的时候 把数据放进了创建的selectRow[]里
                //点击编辑事件的时候  初始化被选中的数据  放入修改面板中
                $("#editBtn").click(function(){
         
                    //如果列表中数据够用
                    //如果修改面板中数据比列表中的多  用id从后台取完整数据
                    $("#euid").val(selectRow[0]);
                    $("#euname").val(selectRow[1]);
                    $("#eupwd").val(selectRow[2]);
                    $("#euphone").val(selectRow[3]);
                    $("#euremark").val(selectRow[4]);
                })
                //提交修改请求
                $("#editSubmit").click(function(){
         
                      //普通版本
    /*                var myparam = {"euid":$("#euid").val(),
                                    "euname":$("#euname").val(),
                                    "eupwd":$("#eupwd").val(),
                                    "euphone":$("#euphone").val(),
                                    "euremark":$("#euremark").val()}*/
                    //把指定form中的有name属性的内容 拼成键值对格式
                    var newparam = $("#editform").serialize();
                    
                    $.post("ajaxUser/mymodify",newparam,function(data){
         
                        //1.给用户展示处理结果
                        var alertcls = "";
                        //判断弹出框属性
                        if(data.returnCode==10000){
         
                            alertcls = "alert-success";
                        }else{
         
                            alertcls = "alert-danger";
                        }
                        //写出弹出框html代码  将alertcls属性加入
                        var content = '
    +alertcls+' alert-dismissible fade in" role="alert">' + ' ' + '

    操作结果

    '
    + '

    '+data.returnMSG+'

    '
    + '
    '
    $("#myalert").append(content); //添加弹出框html代码 //2.重新查询 刷新数据 var params = { "quname":$("#quname").val(),"quremark":$("#quremark").val(), "page":page,"pageSize":pageSize}; myQuery(params); },"json") }) }) //控制上一页 下一页按钮显示 function initBtn(){ $("#nextBtn").prop("disabled",false); $("#prevBtn").prop("disabled",false); if(page<=1){ $("#prevBtn").prop("disabled",true); } if(page>=totalPage){ $("#nextBtn").prop("disabled",true); } } function myQuery(params){ $.post("ajaxUser/myquery",params,function(data){ //清空之前查询的数据 $("#mainData").html(""); if(data.returnCode==10000){ //判断数据 正确 //遍历加入数据库数据 $.each(data.returnData,function(i,d){ var content = ''+d.userId+''+d.userName +''+d.userPwd+''+d.userPhone +''+d.userRemark+'' $("#mainData").append(content); }) //控制选中行的颜色 并将数据填入selectRow[] $("#mainData tr").click(function(){ $("#mainData tr").removeClass("success"); $(this).addClass("success"); selectRow = []; $(this).find("td").each(function(i){ selectRow.push($(this).html()); }) }) page = data.returnPif.page; pageSize = data.returnPif.pageSize; totalPage = data.returnPif.totalPage; $("#totalPageSpan").html(totalPage); $("#pageSpan").html(page); $("#pageSizeSpan").html(pageSize); initBtn(); }else if(data.returnCode==21000){ $("#mainData").html("没有数据"); page = data.returnPif.page; pageSize = data.returnPif.pageSize; totalPage = data.returnPif.totalPage; $("#totalPageSpan").html(totalPage); $("#pageSpan").html(page); $("#pageSizeSpan").html(pageSize); initBtn(); } },"json") } </script> <style> #myalert{ width: 200px; height: 150px; position: absolute; left: 30%; top:100px; } </style> </head> <body> <div class="container"> <div class="row"> <form class="form-inline"> <div class="form-group"> <label for="quname">用户名</label> <input type="text" class="form-control" id="quname" name="quname" value="" placeholder="Jane Doe"> </div> <div class="form-group"> <label for="quremark">备注</label> <input type="text" class="form-control" id="quremark" name="quremark" value="" placeholder="备注信息"> </div> <button id="submitBtn" type="button" class="btn btn-success">查询</button> <button id="resetBtn" type="reset" class="btn btn-success">重置</button> <!-- Button trigger modal --> //data-target 绑定相应的模态框 <button type="button" class="btn btn-info" data-toggle="modal" data-target="#myAddModal"> 添加 </button> <button id="editBtn" type="button" class="btn btn-warning" data-toggle="modal" data-target="#myEditModal"> 修改 </button> </form> <table class="table"> <thead> <tr><th>用户id</th><th>姓名</th><th>密码</th><th>电话</th><th>备注</th></tr> </thead> <tbody id="mainData"> </tbody> </table> <input id="prevBtn" class="btn btn-default" type="button" value="上一页"> <input id="nextBtn" class="btn btn-default" type="button" value="下一页"><br> 总共<span id="totalPageSpan"></span> 页, 当前第<span id="pageSpan"></span>页, 每页显示<span id="pageSizeSpan"></span>条记录 </div> </div> <!-- Modal --> <div class="modal fade" id="myAddModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <h4 class="modal-title" id="myModalLabel">添加</h4> </div> <div class="modal-body"> <form > <div class="form-group"> <label for="auid">用戶id</label> <input type="text" class="form-control" name="auid" id="auid" placeholder="xxx"> </div> <div class="form-group"> <label for="auname">用戶名</label> <input type="text" class="form-control" name="auname" id="auname" placeholder="xxx"> </div> <div class="form-group"> <label for="aupwd">密碼</label> <input type="text" class="form-control" name="aupwd" id="aupwd" placeholder="xx"> </div> <div class="form-group"> <label for="auphone">手機號</label> <input type="text" class="form-control" name="auphone" id="auphone" placeholder="xxx"> </div> <div class="form-group"> <label for="auremark">备注</label> <input type="text" class="form-control" name="auremark" id="auremark" placeholder="xxx"> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> <button type="button" class="btn btn-primary" data-dismiss="modal">保存</button> </div> </div> </div> </div> <!-- Modal --> <div class="modal fade" id="myEditModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <h4 class="modal-title">修改</h4> </div> <div class="modal-body"> <form id="editform"> <div class="form-group"> <label for="euid">用戶id</label> <input type="text" class="form-control" name="euid" id="euid" readonly placeholder="xxx"> </div> <div class="form-group"> <label for="euname">用戶名</label> <input type="text" class="form-control" name="euname" id="euname" placeholder="xxx"> </div> <div class="form-group"> <label for="eupwd">密碼</label> <input type="text" class="form-control" name="eupwd" id="eupwd" placeholder="xx"> </div> <div class="form-group"> <label for="euphone">手機號</label> <input type="text" class="form-control" name="euphone" id="euphone" placeholder="xxx"> </div> <div class="form-group"> <label for="euremark">备注</label> <input type="text" class="form-control" name="euremark" id="euremark" placeholder="xxx"> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> <button id="editSubmit" type="button" class="btn btn-primary" data-dismiss="modal">保存</button> </div> </div> </div> </div> <div id="myalert"> //放弹出框代码 </div> </body> </html>
    <%--
      Created by IntelliJ IDEA.
      User: JAVASM
      Date: 2020/8/18
      Time: 11:14
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Title
        
    
    
    

    fade包

    //将每个方法都需要调用的步骤抽离出来作为父类
    //基础类继承HttpServlet 子类直接继承基础类 就不用继承HttpServlet了
    //子类继承后就不用重复写了
    //这个就是判断前端传过来哪个方法
    public class BaseServlet extends HttpServlet {
         
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            System.out.println(req.getServletPath());//servlet路径
            //用户输入的请求路径    //ajax传过来的
            String requri = req.getRequestURI();
            String methodName = requri.substring(requri.lastIndexOf("/")+1);
            try {
         
                //用路径中的最后一段 决定调用哪个方法
                // 从路径中的最后一段  抽取出方法对象
                //再用被调用的子类实例 调用方法
                Method mymethod = this.getClass().getMethod
                    (methodName,HttpServletRequest.class,HttpServletResponse.class);
                mymethod.invoke(this,req,resp);
            } catch (NoSuchMethodException e) {
         
                e.printStackTrace();
                //异常信息告知给tomcat 让tomcat给用户报错
                resp.sendError(HttpServletResponse.SC_NOT_FOUND);
            } catch (IllegalAccessException e) {
         
                e.printStackTrace();
            } catch (InvocationTargetException e) {
         
                e.printStackTrace();
            }
        }
    }
    
    @WebServlet("/ajaxUser/*")   //  "/ajaxUser/*"   * 代表ajaxUser里的所有方法的通配
    public class AjaxUserServlet extends BaseServlet {
         
    
        public void myquery(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            //查询用户列表
            req.setCharacterEncoding("utf-8");              //调整前端数据传来的格式
            UserService us = new UserServiceImpl();         
            //设置默认值 防止访问时不传参报错
            Integer page = 1;        Integer pageSize = 3;
    
            String pageStr = req.getParameter("page");            //获取前端传来的页数
            String pageSizeStr = req.getParameter("pageSize");    //获取前端传来的一页里有多少个
            //如果请求中带参数 用带的参数覆盖默认值
            if(pageStr!=null&&!"".equals(pageStr)){
                        //判断数据是否正确
                page = Integer.parseInt(pageStr);               
            }
            if(pageSizeStr!=null&&!"".equals(pageSizeStr)){
                //判断数据是否正确
                pageSize = Integer.parseInt(pageSizeStr);
            }
    
            String quname = req.getParameter("quname");            
            String quremark = req.getParameter("quremark");
            User quser = new User(quname,quremark);               //将前端数据实例化为对象
    
            List<User> allUser = us.getAllUser(page,pageSize,quser);   //根据数据从数据库取数据
            Integer totalPage = us.getTotalPage(pageSize,quser);       //获得总页数
    
            PageInfo pif = new PageInfo(page,pageSize,totalPage);       //将页数,页码,总页数实例化对象
            ReturnEntity returnEntity = new ReturnEntity();             //实例化对象返回对象returnEntity
            if(allUser.size()>0){
                                                //将数据放入实例化对象returnEntity中
                returnEntity.setReturnCode(ReturnCode.SUCCESS.getCode());
                returnEntity.setReturnMSG(ReturnCode.SUCCESS.getMsg());
                returnEntity.setReturnData(allUser);
                returnEntity.setReturnPif(pif);
            }else {
                                                            
                returnEntity.setReturnCode(ReturnCode.NO_DATA.getCode());
                returnEntity.setReturnMSG(ReturnCode.NO_DATA.getMsg());
                returnEntity.setReturnPif(pif);
            }
            resp.setContentType("text/html;charset=utf-8");        //规范返回对象
            PrintWriter out = resp.getWriter();
            //返回json格式字符串
            out.print(JSON.toJSONString(returnEntity));           
            out.flush();
            out.close();
        }
    
    
        public void getoneuser(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            System.out.println("准备用户修改数据");
            //获取单个用户
            String uid =  req.getParameter("uid");     //获取id
            UserService us = new UserServiceImpl();
            User user = us.getOneUser(Integer.parseInt(uid));
            //放回数据放入了属性名为"myuser" , 内容是user对象
            req.setAttribute("myuser",user);
            //请求转发 通过request对象调用,把请求对象和响应对象与要跳转的地址共享
            getRequestDispatcher("/editUser.jsp").forward(req,resp);
    
        }
        public void mymodify(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            System.out.println("执行用户的修改");
            //执行修改语句
            //取参数保存
            /*auid: 8
                auname: 宇智波·刘能123
                aupwd: abc23
                auphone: 2222344444
                auremark: 舞王同伙*/
            req.setCharacterEncoding("utf-8");
            String auid = req.getParameter("euid");
            String auname = req.getParameter("euname");
            String aupwd = req.getParameter("eupwd");
            String auphone = req.getParameter("euphone");
            String auremark = req.getParameter("euremark");
    
            User user = new User(Integer.parseInt(auid), auname, aupwd, auphone, auremark);
            UserServiceImpl us = new UserServiceImpl();
            Boolean res = us.editUser(user);
    
            ReturnEntity returnEntity = new ReturnEntity();
            if(res){
         
                returnEntity.setReturnCode(ReturnCode.SUCCESS.getCode());
                returnEntity.setReturnMSG(ReturnCode.SUCCESS.getMsg());
            }else {
         
                returnEntity.setReturnCode(ReturnCode.NO_DATA.getCode());
                returnEntity.setReturnMSG(ReturnCode.NO_DATA.getMsg());
            }
            resp.setContentType("text/html;charset=utf-8");
            PrintWriter out = resp.getWriter();
            //返回json格式字符串
            out.print(JSON.toJSONString(returnEntity));
            out.flush();
            out.close();
        }
    
        public void mycreate(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            System.out.println("执行用户的创建");
            //执行insert语句
    
        }
    
        public void myremove(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            System.out.println("执行用户的删除");
            //执行删除语句
        }
    }
    

    dao 包

    public interface UserDao {
         
        List<User> getUserByPage(Integer page,Integer pageSize,User queryUser);
        List<User> getAllUser(User queryUser);
        User getOneUser(Integer uid);
        Integer editUser(User editUser);
    }
    
    
    
    public class UserDaoImpl implements UserDao {
         
        @Override
        public Integer editUser(User editUser) {
         
            Connection conn = DBHelper.getConn();
            String sql = "update tb_user set user_name = ?,user_pwd = ?,user_phone = ?,user_remark = ?" +
                         "where user_id = ?";
    
            System.out.println(sql);
            User myuser = null;
            PreparedStatement psta = null;
            ResultSet rs = null;
            int resnum = 0;
            try {
         
                psta = conn.prepareStatement(sql);
                psta.setString(1,editUser.getUserName());
                psta.setString(2,editUser.getUserPwd());
                psta.setString(3,editUser.getUserPhone());
                psta.setString(4,editUser.getUserRemark());
                psta.setInt(5,editUser.getUserId());
                resnum = psta.executeUpdate();
            } catch (SQLException e) {
         
                e.printStackTrace();
            }finally {
         
                DBHelper.CloseConn(conn,null,psta,rs);
            }
            return resnum;
        }
    
        @Override
        public User getOneUser(Integer uid) {
         
            Connection conn = DBHelper.getConn();
            String sql = "select tu.user_id,tu.user_name,tu.user_pwd,tu.user_phone,tu.user_remark from tb_user tu where tu.user_id = ?";
            System.out.println(sql);
            User myuser = null;
            PreparedStatement psta = null;
            ResultSet rs = null;
            try {
         
                psta = conn.prepareStatement(sql);
                psta.setInt(1,uid);
                rs = psta.executeQuery();
                while(rs.next()){
         
                    Integer userId = rs.getInt("user_id");
                    String userName = rs.getString("user_name");
                    String userPwd = rs.getString("user_pwd");
                    String userPhone = rs.getString("user_phone");
                    String userRemark = rs.getString("user_remark");
                    myuser = new User(userId, userName, userPwd, userPhone, userRemark);
                }
            } catch (SQLException e) {
         
                e.printStackTrace();
            }finally {
         
                DBHelper.CloseConn(conn,null,psta,rs);
            }
            return myuser;
        }
    
        @Override
        public List<User> getUserByPage(Integer page,Integer pageSize,User queryUser) {
         
            Connection conn = DBHelper.getConn();
            String sql = "select tu.user_id,tu.user_name,tu.user_pwd,tu.user_phone,tu.user_remark from tb_user tu ";
    
          /*  "where" " tu.user_name = ?"
              "and" " tu.user_remark like ?"*/
            boolean isWhere = true;
            List params = new ArrayList();
            if(queryUser.getUserName()!=null&&!"".equals(queryUser.getUserName())){
         
                if(isWhere){
         
                    sql+=" where ";
                    isWhere = false;
                }else{
         
                    sql+=" and ";
                }
    
                sql+=" tu.user_name = ? ";
                params.add(queryUser.getUserName());
            }
            if(queryUser.getUserRemark()!=null&&!"".equals(queryUser.getUserRemark())){
         
                if(isWhere){
         
                    sql+=" where ";
                    isWhere = false;
                }else{
         
                    sql+=" and ";
                }
                sql+=" tu.user_remark like ? ";
                params.add("%"+queryUser.getUserRemark()+"%");
            }
            sql+="limit "+(page-1)*pageSize+","+pageSize;
            System.out.println(sql);
            List<User> lu = new ArrayList<User>();
            PreparedStatement psta = null;
            ResultSet rs = null;
            try {
         
                psta = conn.prepareStatement(sql);
                //循环传参
                //上面有两个条件可能同时使用 可能只使用其中一个 使得参数是一个变量
                //这样PreparedStatement操作不了变量  这时候可以将参数放进params数组里 有几个条件就放进去
                //到时候执行sql语句就从数组里取出来 这时候就间接是静态的
                for(int i = 0;i<params.size();i++){
         
                    psta.setObject(i+1,params.get(i));
                }
                rs = psta.executeQuery();
                while(rs.next()){
         
                    Integer userId = rs.getInt("user_id");
                    String userName = rs.getString("user_name");
                    String userPwd = rs.getString("user_pwd");
                    String userPhone = rs.getString("user_phone");
                    String userRemark = rs.getString("user_remark");
                    User myuser = new User(userId, userName, userPwd, userPhone, userRemark);
                    lu.add(myuser);
                }
            } catch (SQLException e) {
         
                e.printStackTrace();
            }finally {
         
                DBHelper.CloseConn(conn,null,psta,rs);
            }
            return lu;
        }
    
        @Override
        public List<User> getAllUser(User queryUser) {
         
            Connection conn = DBHelper.getConn();
            String sql = "select tu.user_id,tu.user_name,tu.user_pwd,tu.user_phone,tu.user_remark from tb_user tu";
                  /*  "where" " tu.user_name = ?"
              "and" " tu.user_remark like ?"*/
            boolean isWhere = true;
            List params = new ArrayList();
            if(queryUser.getUserName()!=null&&!"".equals(queryUser.getUserName())){
         
                if(isWhere){
         
                    sql+=" where ";
                    isWhere = false;
                }else{
         
                    sql+=" and ";
                }
                sql+=" tu.user_name = ? ";
                params.add(queryUser.getUserName());
            }
            if(queryUser.getUserRemark()!=null&&!"".equals(queryUser.getUserRemark())){
         
                if(isWhere){
         
                    sql+=" where ";
                    isWhere = false;
                }else{
         
                    sql+=" and ";
                }
                sql+=" tu.user_remark like ? ";
                params.add("%"+queryUser.getUserRemark()+"%");
            }
            List<User> lu = new ArrayList<User>();
            PreparedStatement psta = null;
            ResultSet rs = null;
            try {
         
                psta = conn.prepareStatement(sql);
                //循环传参
                for(int i = 0;i<params.size();i++){
         
                    psta.setObject(i+1,params.get(i));
                }
                rs = psta.executeQuery();
                while(rs.next()){
         
                    Integer userId = rs.getInt("user_id");
                    String userName = rs.getString("user_name");
                    String userPwd = rs.getString("user_pwd");
                    String userPhone = rs.getString("user_phone");
                    String userRemark = rs.getString("user_remark");
                    User myuser = new User(userId, userName, userPwd, userPhone, userRemark);
                    lu.add(myuser);
                }
            } catch (SQLException e) {
         
                e.printStackTrace();
            }finally {
         
                DBHelper.CloseConn(conn,null,psta,rs);
            }
            return lu;
        }
    }
    

    service包

    //service是业务层   操作dao数据访问层传来的数据
    public interface UserService {
         
        List<User> getAllUser(Integer page,Integer pageSize,User queryUser);
        Integer getTotalPage(Integer pageSize,User queryUser);
        User getOneUser(Integer uid);
        Boolean editUser(User editUser);
    }
    
    
    public class UserServiceImpl implements UserService {
         
    
        @Override
        public Boolean editUser(User editUser) {
         
            UserDao ud = new UserDaoImpl();
            Integer resnum = ud.editUser(editUser);    
            Boolean flag = false;
            if(resnum>=1){
         
                flag = true;
            }
            return flag;
        }
    
        @Override
        public List<User> getAllUser(Integer page,Integer pageSize,User queryUser) {
         
            UserDao ud = new UserDaoImpl();
            return ud.getUserByPage(page,pageSize,queryUser);
        }
    
        @Override
        public Integer getTotalPage(Integer pageSize,User queryUser) {
         
            UserDao ud = new UserDaoImpl();
             List<User> lu = ud.getAllUser(queryUser);
            Integer totalNum = lu.size();
            Integer totalPage = 0;
            if(lu.size()!=0){
         
                totalPage = totalNum%pageSize>0?totalNum/pageSize+1:totalNum/pageSize;
            }
    
            //用总记录数 和每页显示记录数 算总页数
            // 总记录数与每页记录取余数 看是否有余数   有余数 totalNum/pageSize+1  没余数 totalNum/pageSize
    
            return totalPage;
        }
    
    
        @Override
        public User getOneUser(Integer uid) {
         
            UserDao ud = new UserDaoImpl();
            return ud.getOneUser(uid);
        }
    }
    

    entity包

    public class PageInfo {
         
    
        private Integer page;
        private Integer pageSize;
        private Integer totalPage;
    
        public Integer getPage() {
         
            return page;
        }
    
        public void setPage(Integer page) {
         
            this.page = page;
        }
    
        public Integer getPageSize() {
         
            return pageSize;
        }
    
        public void setPageSize(Integer pageSize) {
         
            this.pageSize = pageSize;
        }
    
        public Integer getTotalPage() {
         
            return totalPage;
        }
    
        public void setTotalPage(Integer totalPage) {
         
            this.totalPage = totalPage;
        }
    
    
        public PageInfo(Integer page, Integer pageSize, Integer totalPage) {
         
            this.page = page;
            this.pageSize = pageSize;
            this.totalPage = totalPage;
        }
    
        public PageInfo() {
         
        }
    }
    
    public enum ReturnCode {
         
    
        SUCCESS(10000,"操作成功"),
        UNAME_OK(10001,"用户名可用"),
        UNAME_DUPLICATE(20001,"用户名重复"),
        FAILED(20000,"操作失败"),
        NO_DATA(21000,"没有数据");
    
        Integer code;
        String msg;
    
        private ReturnCode(Integer code,String msg){
         
            this.code = code;
            this.msg = msg;
        }
    
        public Integer getCode() {
         
            return code;
        }
    
        public String getMsg() {
         
            return msg;
        }
    }
    
    public class ReturnEntity {
         
        //returnCode  returnMSG   returnData
        private Integer returnCode;
        private String returnMSG;
        private List returnData;
        private PageInfo returnPif;
    
        public PageInfo getReturnPif() {
         
            return returnPif;
        }
    
        public void setReturnPif(PageInfo returnPif) {
         
            this.returnPif = returnPif;
        }
    
        public Integer getReturnCode() {
         
            return returnCode;
        }
    
        public void setReturnCode(Integer returnCode) {
         
            this.returnCode = returnCode;
        }
    
        public String getReturnMSG() {
         
            return returnMSG;
        }
    
        public void setReturnMSG(String returnMSG) {
         
            this.returnMSG = returnMSG;
        }
    
        public List getReturnData() {
         
            return returnData;
        }
    
        public void setReturnData(List returnData) {
         
            this.returnData = returnData;
        }
    
        public ReturnEntity(Integer returnCode, String returnMSG, List returnData) {
         
            this.returnCode = returnCode;
            this.returnMSG = returnMSG;
            this.returnData = returnData;
        }
    
        public ReturnEntity() {
         
    
        }
    
        @Override
        public String toString() {
         
            return "ReturnEntity{" +
                    "returnCode=" + returnCode +
                    ", returnMSG='" + returnMSG + '\'' +
                    ", returnData=" + returnData +
                    ", returnPif=" + returnPif +
                    '}';
        }
    }
    
    public class User {
         
        private Integer userId;
        private String userName;
        private String userPwd;
        private String userPhone;
        private String userRemark;
    
        public Integer getUserId() {
         
            return userId;
        }
    
        public void setUserId(Integer userId) {
         
            this.userId = userId;
        }
    
        public String getUserName() {
         
            return userName;
        }
    
        public void setUserName(String userName) {
         
            this.userName = userName;
        }
    
        public String getUserPwd() {
         
            return userPwd;
        }
    
        public void setUserPwd(String userPwd) {
         
            this.userPwd = userPwd;
        }
    
        public String getUserPhone() {
         
            return userPhone;
        }
    
        public void setUserPhone(String userPhone) {
         
            this.userPhone = userPhone;
        }
    
        public String getUserRemark() {
         
            return userRemark;
        }
    
        public void setUserRemark(String userRemark) {
         
            this.userRemark = userRemark;
        }
    
        public User(String userName, String userRemark) {
         
            this.userName = userName;
            this.userRemark = userRemark;
        }
    
    
        public User(Integer userId, String userName, String userPwd, String userPhone, String userRemark) {
         
            this.userId = userId;
            this.userName = userName;
            this.userPwd = userPwd;
            this.userPhone = userPhone;
            this.userRemark = userRemark;
        }
    
        public User() {
         
        }
    
        @Override
        public String toString() {
         
            return "User{" +
                    "userId=" + userId +
                    ", userName='" + userName + '\'' +
                    ", userPwd='" + userPwd + '\'' +
                    ", userPhone='" + userPhone + '\'' +
                    ", userRemark='" + userRemark + '\'' +
                    '}';
        }
    }
    

    util包

    public class DBHelper {
         
    	static String username;
    	static String pwd;
    	static String url;
    	static String drivername;
    	
    	
    	static {
         
    		Properties p = new Properties();
    		try {
         
    			//程序运行时 不一定在你的工程目录的编译目录下
    			p.load(DBHelper.class.getResourceAsStream("/jdbc.properties"));
    			username = p.getProperty("jdbc.user");
    			pwd = p.getProperty("jdbc.pass");
    			url = p.getProperty("jdbc.url");
    			drivername = p.getProperty("jdbc.driver");
    			Class.forName(drivername);		
    		} catch (Exception e) {
         
    			e.printStackTrace();
    		}
    	}
    	
    	public static Connection getConn() {
         
    		Connection con = null;
    		
    		try {
         
    			con = DriverManager.getConnection(url, username, pwd);
    		} catch (SQLException e) {
         
    			e.printStackTrace();
    		}
    		return con;
    	}
    	
    	
    	public static void CloseConn(Connection conn,Statement stat,PreparedStatement psta,ResultSet rs){
         		
    			try {
         
    				if(stat!=null)stat.close();
    				if(psta!=null)psta.close();
    				if(rs!=null)rs.close();
    				if(conn!=null)conn.close();			
    			} catch (SQLException e) {
         
    				e.printStackTrace();
    			}
    	}
    }
    

    src下 jdbc,protites

    jdbc.user = root
    jdbc.pass = root
    jdbc.url = jdbc:mysql://127.0.0.1:3306/my_db?characterEncoding=utf8&useSSL=true
    jdbc.driver = com.mysql.jdbc.Driver
    

    文件上传、过滤器、监听器

    文件上传、过滤器、监听器

    1.文件上传

    1.1 使用工具

    文件上传需要对请求中传的的文件流进行解析,一般会选择工具来对文件流进行解析

    • 文件上传相关的jar包

    ​ commons-fileupload-1.3.3.jar

    ​ commons-io-2.5.jar

    1.2 文件上传

    • 文件上传请求由浏览器发起
    <form action="myUpload" method="post" enctype="multipart/form-data">
    	<input type="text" name="uname"><br>
    	<input type="file" name="myfile"><br>
    	<input type="submit">
    form>
    

    需要文件选择框并且设置了name属性,form的method为post,加设置enctype=“multipart/form-data”,此时form提交时,会把选择到的文件以二进制数据形式发送到服务器,否则不会发送文件

    • 服务器需要对请求中的文件数据进行解析,还原成文件,这个由jar包中提供的类完成
    //如果页面中加了  enctype="multipart/form-data" 提交数据的方式发生改变 不会封装成键值对
            //getParameter 取不到值
            //req.getParameter("xxx");
    
            //enctype="multipart/form-data"
            //默认使用iso-8859-1 解析  需要把中文的内容 根据iso-8859-1拆解 再用utf-8 重组
    
            /*
            * 上传文件
            * 1. form中设置 method="post"  enctype="multipart/form-data"
            * 2. 服务器使用 commons-fileupload-1.2.jar 对数据流解析
            * 3.在指定的服务器位置创建一个与上传的文件同名的空文件
            * 4.把工具解析出的临时文件的内容 复制到新创建的文件中
            *
            * */
    @WebServlet("/myUpload")
    public class MyUploadServlet extends HttpServlet {
         
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            doPost(req, resp);
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         
            //multipart/form-data 处理上传文件的servlet和普通数据的servlet分开 处理数据格式不同
            
            //项目所在实际路径   web文件夹同级
            String basePath =  req.getServletContext().getRealPath("/");
            //创建拼接+文件上传地址的对象
            String myFolder = "upload\\";
            //解析流中数据的核心对象
            boolean ismultipart = ServletFileUpload.isMultipartContent(req);
            if(ismultipart){
         
                //生成FileItem的工厂 创建fileItem对象  上传的数据封装成fileItem(既可以表示为普通数据 也可以文件对象 )
                //普通数据        fileItem
                // 文件对象       fileItem
                //可以设置生成数据的参数
                DiskFileItemFactory dff = new DiskFileItemFactory();
                //通过工厂生成上传文件对象
                ServletFileUpload sfu = new ServletFileUpload(dff);
    
                try {
         
                    //列表里放入所有的fileItem对象
                    List<FileItem> lf = sfu.parseRequest(req);
                    //
                    for(FileItem fi:lf){
         
                        if(!fi.isFormField()){
         
                            //处理文件
                            
                            //存放上传文件的目录
                            String fileFullName = basePath+myFolder+fi.getName();
                            //写入的时候  myFolder文件夹必须存在  可回顾第一阶段知识io流
                            File newFile = new File(fileFullName);
                            //把临时文件 写入到指定的文件中
                            fi.write(newFile);
                        }else{
         
                            //处理普通字段
                            System.out.println(fi.getFieldName()+" --- "+fi.getString());
                        }
                        
                    }
                } catch (Exception e) {
         
                    e.printStackTrace();
                }
            }
        }
    }
            /*
            必须有name属性 不管是名字还是文件
            文件名字最好不是中文 要不然需要转格式    
            
            流中数据 根据格式 都生成临时文件
            普通字段   isFormField = true     name=null        FieldName=uname
            文件       isFormField = false    name=test.png    FieldName=myfile
            */
    

    1.3 Ajax文件上传

    l 文件上传使用form传递,普通数据取值变得非常麻烦,可以把文件上传和普通表单提交的流程分开,通过工具把文件单独上传到服务器(异步上传),并在页面接收存储的地址(相对路径),用户填完数据提交表单时,文件已上传过,只需要提交普通表单即可。

    后台        
            //项目所在实际路径
            String basePath = req.getServletContext().getRealPath("/");        //这个是编译时的路径 在out里
            //存放上传文件的目录
            String fileFolder = "upload/";
            //临时文件工厂
            DiskFileItemFactory dff = new DiskFileItemFactory();
            //临时文件工厂 解析数据时 使用该工厂
            ServletFileUpload sfu = new ServletFileUpload(dff);
            String imgSrc ="";
            try {
         
                List<FileItem> list = sfu.parseRequest(req);
                for(FileItem fi:list){
         
                    if(!fi.isFormField()){
         
                         //文件  把工厂中的临时文件 复制到服务的指定位置的文件里
                        File newFile = new File(basePath+fileFolder+fi.getName());   //上面已经加了"/"了               
                        fi.write(newFile);
                         //复制完毕后的文件地址
                        imgSrc = fileFolder+"/"+fi.getName();
                    }
                }
            } catch (Exception e) {
         
                e.printStackTrace();
            }
     
            resp.setContentType("text/html;charset=utf-8");
            PrintWriter pw = resp.getWriter();
            pw.print("{\"imgsrc\":\""+imgSrc+"\"}");
            pw.flush();
            pw.close();
    
    前端
        
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
        <script src="js/jquery-3.4.1.min.js"></script>
        <script src="js/ajaxfileupload.js"></script>
        <script>
          $(function(){
         
              $("#myfile").change(function(){
         
                  console.log(1);
                  //ajaxFileUpload
                  $.ajaxFileUpload({
         
                      url:"ajaxUpload",//地址
                      type:"post",//请求类型
                      data:{
         },
                      fileElementId:"myfile",
                      secureuri:false,
                      dataType:"text",//返回数据的类型
                      success:function(data){
         //响应成功时的回调函数 data表示返回的数据
                          //console.log(data);
                          var jsonobj = JSON.parse(data)
                          //console.log(jsonobj);
                          $("#fileurl").val(jsonobj.imgSrc);          //选择文件按钮后边   显示选择的文件名字   
                          $("#showImg").html('+jsonobj.imgSrc+'">');
                      }
                  });
              })
          })
        </script>
      </head>
      <body>
        <form action="myRegist" method="post">
          <input type="text" name="uname" placeholder="用户名"><br>
          <input type="text" name="uphone" placeholder="手机号"><br>
          <input type="text" name="uemail" placeholder="邮箱"><br>
          <input type="text" name="uaddr" placeholder="住址"><br>
          <input type="file" id="myfile" name="myfile"><br>
          <input type="hidden" id="fileurl" name="fileurl" value="xxx/xxx.png">
          <input type="submit">
        </form>
      <div id="showImg">
      </div>
      </body>
    </html>
    

    2.Filter过滤器

    2.1 什么是过滤器

    • 过滤器是向 Web 应用程序的请求和响应处理添加功能的Web 服务组件

    • Filter是一个可以加在servlet前执行的组件,可以通过这个机制制作一些通用性的功能,跟生活中用的水的过滤器的机制很相似。

    2.2 过滤器生命周期

    JavaWeb_第7张图片

    2.3 过滤器典型案例

        //如果servlet与filter配置地址相同 访问同一个地址时 filter会先运行
        //同一个地址可以配置多个filter filter执行的先后顺序
        //                             配置文件  配置的先后                //web.xml里配置
        //                             注解      类名排列先后              //filter1比filter2先
        //  fitler一般用来做通用功能
        //  需要和通配符*搭配   如果配置为/*  所有的网络请求都会走过滤器 包括 html css js bootstrap等 各种图片
        //  做通用功能
        //  1.处理请求字符编码
        //  2.访问限制(权限功能)
    
    @WebFilter("/*")
    public class MyFilter1 implements Filter {
         
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
         
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
         
            //从session中取权限列表
            /**
             * 在登录访问控制之后
             * 权限过滤  较细粒度的访问控制
             * servletRequest -->> HttpServletRequest
             * servletResponse -->> HttpServletResponse
             *判断用户是否具有权限  通过用户访问的url
             *myreq.getRequestURI()      获取请求的路径
             *myreq.getServletPath()     获取当次要访问的servlet配置的路径
             *
             *
             *
             *  配置白名单 白名单
             * 忽略静态资源
             * 忽略某些特定模块
             *
             *
             * 跟权限列表匹配
             *
             * 如果是ajax请求 页面跳转无效
             * 响应没有权限相关的数据
             *
             * 页面中请求的响应上 加上对没有权限的处理(location.href 转到一个精美的没有权限页面)
             */
            
            //创建servlet拥有访问权限页面的集合   
            List<String> userAuth =new ArrayList<String>();
            userAuth.add("/ajaxProd");
            userAuth.add("/ajaxOrder");
            userAuth.add("/ajaxXXX");
            //web应用走的都是http协议  像ServletRequest servletRequest这些子类实例都可以强转
            //将ServletRequest转换成HttpServletRequest格式   用来取要访问的页面
            HttpServletRequest myreq = (HttpServletRequest) servletRequest;
            String servletPath = myreq.getServletPath();
            //白名单                黑名单
            //忽略静态资源
            //忽略某些特定模块
            //设置这些静态资源直接通过   为白名单
            if(servletPath.endsWith(".html")||servletPath.endsWith(".js")||
               servletPath.endsWith(".css")||servletPath.endsWith(".png")||
               servletPath.endsWith(".jpeg")||"/text".equals(servletPath)){
         
                filterChain.doFilter(myreq,servletResponse);
            }else{
         
                //询问是否有访问该页面权限
                if(userAuth.contains(servletPath)){
         
                    //有权限     
                    filterChain.doFilter(myreq,servletResponse);     //这句话就是带着参数继续往下走servlet
    
                }else{
         
                    //没有权限
                    ReturnEntity returnEntity = new ReturnEntity();
    
                    returnEntity.setReturnCode(ReturnCode.NO_AUTH.getCode());
                    returnEntity.setReturnMSG(ReturnCode.NO_AUTH.getMsg());
    
                    servletResponse.setContentType("text/html;charset=utf-8");
                    PrintWriter out = servletResponse.getWriter();
                    //返回json格式字符串      通过返回的数据跳转到一个提示没有访问权限精致页面
                    out.print(JSON.toJSONString(returnEntity));
                    out.flush();
                    out.close();
                }
            }
        }
    
        @Override
        public void destroy() {
         
        }
    }
    

    3.监听器

    3.1 什么是监听器

    监听器是javaweb组件中提供的另外一种机制,用来监控域对象的创建、销毁过程(在发生创建、销毁时,可以执行自己的代码)以及域对象中属性的创建、替换、销毁。

    • 监听web对象创建与销毁的监听器

    ​ ServletContextListener

    ​ HttpSessionListener

    ​ ServletRequestListener

    • 监听web对象属性变化

    ServletContextAttributeListener

    HttpSessionAttributeListener

    ServletRequestAttributeListener

    3.2 监听器配置和使用

    HttpSessionListener为例

    public class MyListener implements HttpSessionListener {
         
    	@Override
    	public void sessionCreated(HttpSessionEvent arg0) {
         
        //session创建时执行的代码
    	}
    
    	@Override
    	public void sessionDestroyed(HttpSessionEvent arg0) {
         
        //session销毁时执行的代码
    	}
    }
    

    Web.Xml中配置

    <listener>
    	<listener-class>com.javasm.listener.MyListenerlistener-class>
    listener>
    

    数据库连接池 & servlet3.0

    1.数据库连接池

    1.1 数据库连接池

    • 连接池

    连接池是在内存中预设好一定数量的连接对象,以备用户在进行数据库操作时直接使用

    • 性能

    数据库连接的建立、断开均由管理池统一管理

    • 连接池技术与传统数据库连接的比较

    数据库操作性能得到提升

    通过连接池管理数据库的连接与释放、提高了系统资源的使用效率。

    JavaWeb_第8张图片

    1.2 Druid

    • Druid是阿里巴巴开源平台上一个数据库连接池实现

    • Druid是Java语言中最好的数据库连接池

    • Druid能够提供强大的监控和扩展功能

    • Druid可以由不同类型的节点,组成一个集群

    1.2.1 Druid下载
    • druid-x.x.x.jar 项目中导入Jar包

    Jar包下载地址:

    http://repo1.maven.org/maven2/com/alibaba/druid/1.1.10/druid-1.1.10.jar

    源码下载地址:

    http://repo1.maven.org/maven2/com/alibaba/druid/1.1.10/druid-1.1.10-sources.jar

    1.2.2 Druid对象和设置
    	创建对象配置
    DruidDataSource druidDataSource = new DruidDataSource();
    druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");//驱动名
    druidDataSource.setUrl("jdbc:mysql://192.168.2.2:3306/sqltest");//数据库地址
    druidDataSource.setUsername("root");//用户名
    druidDataSource.setPassword("root");//密码
    //以下为非必填项,不设置也有默认值
    druidDataSource.setMinIdle(1);//最小连接池数量 可设置最大值8
    druidDataSource.setInitialSize(1);//初始化时建立物理连接的个数
    druidDataSource.setMaxActive(10);//最大连接池数量
    druidDataSource.setMaxWait(10000);//获得连接最大等待时间 单位毫秒
    druidDataSource.setMinEvictableIdleTimeMillis(300000);// 配置一个连接在池中最小生存的时间,单位是毫秒
    	获得连接
    Connection conn = druidDataSource.getConnection();
    获得连接之后的步骤,与JDBC一致
    	归还连接
    Conn.close();
    关闭连接并非真的关掉连接,而是把连接返回给数据库连接池,等待下一次调用
        	连接池关闭
    druidDataSource.close();
    该方法是关闭数据库连接池,执行完之后,不可以再从连接池中获得连接
    

    2.Servlet3.0介绍

    • 使用nio(非阻塞型io)处理 效率相对提高

      –8.5及以上版本默认使用nio处理

    • 使用注解进行配置

    2.1 Servlet3.0注解

    • Servlet3.0中可以使用注解(annotation)替代web.xml进行配置;

    • 常用的注解有三种类型:

    @WebServlet:对Servlet进行配置

    @WebServlet:对Servlet进行配置示例,包括的属性如下,这些属性除了vlaue或urlPatterns是必选的,其他的都是可选的:
    1)name:等价于web.xml配置文件中的 。如果没有指定, Servlet 的取值为类的全限定名,比如XXX.XXX.XXX。
    2)urlPatterns:等价于web.xml配置文件中的  标签
    3)value:等价于 urlPatterns 属性。
    4)loadOnStartup:等价于web.xml配置文件中的 标签
    5)initParams :等价于web.xml配置文件中的 标签,他的参数是@WebInitParam注解的集合(此注解之后介绍)
    6)asyncSupported:等价于web.xml配置文件中的 标签
    7)description:等价于web.xml配置文件中的 标签
    8)displayName:等价于web.xml配置文件中的  标签
    
    注解配置:
    @WebServlet(urlPatterns = {
         "/demo"}, 
    asyncSupported = true, 
    loadOnStartup = -1, 
    name = "DemoServlet", 
    displayName = "DemoServlet ", 
    initParams = {
         
    @WebInitParam(name = "username",
     value = "etc") 
    } ) 
    
    配置文件配置:
    <servlet>
        <display-name> DemoServlet display-name>
        <servlet-name>DemoServletservlet-name>
    <servlet-class>com.sm.SimpleServletservlet-class>
        <load-on-startup>-1load-on-startup>
        <async-supported>trueasync-supported>
        <init-param>
            <param-name>usernameparam-name>
            <param-value>etcparam-value>
        init-param>
    servlet>
    <servlet-mapping>
        <servlet-name> DemoServlet servlet-name>
        <url-pattern>/demourl-pattern>
    servlet-mapping>
    

    @WebFilter:配置过滤器

    @WebFilter:配置过滤器此注解为声明一个过滤器,主要属性有以下几个。
    在这些属性当中value、urlPatterns、servletNames 三个属性至少要包含其中的一个,并且 value 和 urlPatterns 属性只能有一个,如果两个同时配置,一般情况下value取值将会被忽略。其他的都是可选属性。
    filterName:等价于web.xml配置文件中的 标签
    value:该属性等价于 urlPatterns 属性
    urlPatterns:等价于web.xml配置文件中的  标签
    servletNames:指定该过滤器将应用的 范围。如果是注解的话取值是 @WebServlet 中的 name 属性的取值,如果servlet这 web.xml 中配置的话,取值是  的取值
    dispatcherTypes:过滤器的转发模式。取值包括:
    ASYNC(异步)、ERROR(错误)、FORWARD(请求转发)、INCLUDE(包含)、REQUEST(请求)。
    initParams:等价于web.xml配置文件中的 标签
    asyncSupported:等价于web.xml配置文件中的 标签
    description:等价于web.xml配置文件中的 标签
    displayName:等价于web.xml配置文件中的 标签
    

    @WebListener :配置监听器

    @WebListener:配置监听器,此注解是用来声明监听器,它主要的属性只有一个:
    value:这个属性表示的是监听器的描述信息,整个配置可以简写成@WebListener("XXX")
    

    VUE

    1.什么是vue

    是一套前端框架,简化前端大量的jquery,原生js的重复DOM操作代码。用来简化开发。

    是一套数据驱动视图的前端框架,基于MVVM架构,M:model数据,V:view视图,vm:viewModel视图数据监听器,当数据改变,修改视图;当视图发生变化,修改model数据。是一种数据双向绑定监听的实现。

    是国人尤雨溪开发。

    JavaWeb_第9张图片

    2.开发环境准备

    1. hbuilderX前端开发工具
    2. chrome浏览器调试程序

    3.使用vue

    1. 引入vue.js依赖

      cdn加速服务引入:文件存储在服务器上 通过外网访问 不需要本地存放。

      本地引入:

      • 开发版本:支持vue调试工具,开发使用

      • 正式版本:不支持vue调试工具,上线使用

    2. 入门测试:

      <!--vue绑定页面数据 需要一个根标签作为渲染的基板-->
      <div id="base">
          <!--插值表达式,获取data对象中的数据-->
          {
             {
             msg}}
      </div>
      
      <script>
          //原data数据对象 也可以在vue对象中直接定义
          let mydata = {
             msg:'尚马教育'}
          //创建Vue实例对象,每个vue应用都是从这里开始
          let vm = new Vue({
             
              //将基板与vue对象绑定 如果没有在基板中的数据 不会被vue渲染
              el:"#base",
              //页面上显示的数据对象   
              data:mydata
       })
      
          //取得vue实例对象中的数据,与原data对象中数据一致
          console.log(vm.msg)
          //设置vue实例对象中数据,原data对象也改变,同时页面显示数据发生改变
          vm.msg='郑州尚马教育'
          console.log(mydata.msg)
      	console.log(vm.msg)
          mydata.msg='武汉尚马教育'
      	console.log(mydata.msg)
          console.log(vm.msg)
      </script>
      
    3. 注意点:

      只有当实例被创建时就已经存在于 data 中的 property 才是响应式的 ,后续向vue实例对象中添加的数据无效。建议页面中数据预先定义在vue实例对象中。

    4.vue基本语法

    1. 插值表达式

      数据绑定基本方式就是使用 { { xxx }}(双大括号)的文本插值 可将modelView中的数据渲染到页面中对应的位置,页面中绑定的位置根据modelView中定义的数据改变而改变

    2. vue对象中的属性

      vue对象中的属性 可以通过创建的vue对象读取到,但是如果读取vue对象的属性时 通常需要通过$指明 跟data中用户自定义属性有所区分

      console.log(vm.$data)
      console.log(vm.$el)
      console.log(vm.$data.msg)
      //为了省略 如果对data中的数据进行取值时 可以省略$data
      //vm.$data.msg 等同于 vm.msg
      console.log(vm.msg)
      
    3. v-html插入html代码

      因为vue中关注数据绑定 而不是页面中元素变化 插值默认不可以插入html代码 如果在一些特殊场景 需要插入html代码时 可以使用v-html指令

      <div id="base">
          <div v-html="msg"></div>
      </div>
          
      <script>
      new Vue({
             
        el: '#base',
        data: {
             
          msg: '

      带格式的标题

      '
      } }) </script>
    4. v-bind指令将html中元素与viewModel中数据绑定 html的属性都可以通过v-bind与数据模板进行绑定

      		<style>
      			.test{
             
      				background-color: lightcoral;
      				width: 100%;
      				height: 100%;
      			}
      		</style>	
      
      		<div id="base">
      			<div v-bind:class="mycls">
      				123
      			</div>
      		</div>
      
              <script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          mycls:"test"
                      }
                  })
              </script>
      

      同时因为class属性是允许多值的 比较特殊 所以在class属性的绑定上 还提供了额外的方式

      		<style>
      			.cls1{
             
      				width: 100px;
      				height: 100px;
      			}
      			.cls2{
             
      				background-color: #F08080;
      			}
      			.cls3{
             
      				color: aliceblue;
      			}
      		</style>	
      
      		<div id="base">
                  <!-- 一定有的class属性 可以单写class属性赋值(cls3) 
                  需要动态控制的class属性 可以通过bol值决定是否生效 并且可以配置多个(cls1 cls2) -->
      			<div class="cls3" v-bind:class="{'cls1':cls1use,'cls2':cls2use}">
      				123
      			</div>
      		</div>
      		
              <script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          cls1use:true,
                          cls2use:true
                      }
                  })
              </script>
      

      ​ 注意:v-bind指令比较常用 所有在使用v-bind指令时 通常可以简写为 :属性

      <div class="cls3" :class="{'cls1':cls1use,'cls2':cls2use}">
      
    5. v-if指令 绑定bol值控制页面元素是否可见

      		<div id="base">
                  <div v-if="showStatus">test</div>
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          showStatus:false
                      }
                  })
              </script>
      <!--  通常配合使用还有 v-else-if v-else  可以在标签属性上直接使用表达式 或绑定data中的数据  -->
          	<div id="base">
                  <div v-if="showStatus==1">test1</div>
      			<div v-else-if="showStatus==2">test2</div>
      			<div v-else>test3</div>
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          showStatus:1
                      }
                  })
              </script>
      
    6. v-on指令 绑定事件

      在开发过程中 页面中的效果通常会通过浏览器对事件的监听来触发自定义的函数 对事件进行处理

      在vue中 在元素中通过v-on绑定事件,再在vue对象的methods中 定义处理的函数

      vue主要关注绑定的数据,所以在vue的methods中定义的函数 主要用来改变viewmodel(data)中的数据,

      获取时 通常可以使用this 此时this表示myvue这个对象

      		<div id="base">
                  <input type="text" :value="test" />
                  <input type="button" value="点击触发修改绑定数据" v-on:click="myMethod" />
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          test:"123"
                      },
                      methods:{
             
      					myMethod:function(){
             
      					this.test='abc';
      				}
                  })
              </script>
      

      绑定事件也很常用 也有省略写法

      		<div id="base">
                  <input type="text" :value="test" />
                      <!--简写  v-on:click ==>  @click   -->
                  <input type="button" value="点击触发修改绑定数据" @click="myMethod" />
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          test:"123"
                      },
                      methods:{
             
                          <!--简写  myMethod:function(){
               ==>  myMethod(){
               -->
      					myMethod(){
             
      					this.test='abc';
      					}
                       }
                  })
              </script>
      
    7. v-model 双向绑定

      表单元素是页面中非常常用的一类元素 通常用来与用户交互 接收用户的输入 点击等动作

      在获取用户输入时 vue提供了v-model 并且可以通过v-model进行双向绑定

      双向绑定(可以通过输入 改变viewmodel中的数据 也可以改变viewmodel中的数据 直接显示在绑定的元素上)

      		<div id="base">
                  <!-- 文本框1为双向绑定 用户的输入可以改变viewmodel中的test的值
                      此时与test值绑定的其他位置的数据可以直接改变
                      点击按钮时 通过事件触发test值的改变 被双向绑定的第一个文本框 也会接受到test值的	   改变而改变 此为双向绑定-->
                  <input type="text" v-model="test"/>    //获取数据                  
                  <input type="text" :value="test"/>     //把获取的数据设置给它
                      {
             {
             test}}
                  <input type="button" value="点击触发修改绑定数据" @click="myMethod" />
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          test:"123"
                      },
                      methods:{
             
      					myMethod(){
             
      						this.test='abc';
      					}
                      }
                  })
              </script>
      

      双向绑定在表单元素中应用较多 除了文本框外 在其他元素上有不同的用法

      **单选框:**v-model可以用来对单选框分组 不需要再加name属性 同时可以通过v-model 获取或改变单选按钮中选中的值

      		<div id="base">
                 <input type="radio" id="male" value="male" v-model="gender"/>
      			<label for="male"></label>
      			<input type="radio" id="fmale" value="fmale" v-model="gender"/>
      			<label for="fmale"></label>
      			{
             {
             gender}}
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          gender:"fmale",
                      }
                  })
              </script>
      

      **复选框:**v-model可以用来对复选框分组 不需要再加name属性 同时可以通过v-model 获取或改变复选按钮中选中的值 复选按钮的数据格式为数组

      	<div id="base">
               	<input id="java" type="checkbox" value="1" v-model="hobby" />
      		<label for="java">java</label>
      		<input id="c#" type="checkbox" value="2" v-model="hobby" />
      		<label for="c#">c#</label>
      		<input id="python" type="checkbox" value="3" v-model="hobby" />
      		<label for="python">python</label>
      		{
             {
             hobby}}
      	</div>
      	<script>
                 var myvue = new Vue({
             
                     el:"#base",
                     data:{
             
                         hobby:[1,2]
                     }
                 })
             </script>
      

      **下拉菜单:**v-model需要定义在select框上 用来获取或者设置选中的option的value

      		<div id="base">
                	<select v-model="area" @change="getVal">
      				<option disabled value="">------请选择------</option>
      				<option value="100">北京</option>
      				<option value="110">上海</option>
      				<option value="120">深圳</option>
      			
      			</select>
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          //设置area的值 可以让对应的option选中
                          area:""
                      },
                      methods:{
             
                          getVal(){
             
                              console.log(this.area);
                          }
                      }
                  })
              </script>
      

      注意:v-model在不同的元素上 使用方法略有差别 用法上实际上还是与viewmodel中的数据绑定

    8. v-for 循环结构 vue中如果需要迭代在页面中生成的元素 可以使用v-for进行遍历 遍历的数据需要在data中定义好

      		<div id="base">
                	<ul>
                  <!-- lis为数组 li是数组中遍历到的数据 
                  	 在遍历过程中 可以通过li读取数组中的json元素的值 -->
      				<li v-for="li in lis">{
             {
             li.content}}</li>
      			</ul>
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          lis:[{
             content:'主页'},{
             content:'相关新闻'},{
             content:'关于我们'}]
                      }
                  })
              </script>
      

      v-for还经常用在table和select上 来动态加载table数据 或者select的下拉列表数据

      		<div id="base">
                	<table border="1">
      				<caption>测试table</caption>
      				<tr><th>姓名</th><th>年龄</th><th>性别</th></tr>
      				<tr v-for="tr in trs">
      					<td>{
             {
             tr.name}}</td>
                          <td>{
             {
             tr.age}}</td>
                          <td>{
             {
             tr.gender}}</td>
      				</tr>
      			</table>
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          trs:[{
             name:"jack",age:16,gender:"男性"},
      						{
             name:"rose",age:17,gender:"女性"},
                              {
             name:"小明",age:20,gender:"女性"}
                              ]
                      }
                  })
              </script>
      
      		<div id="base">
                	<select v-model="area" @change="getVal">
      				<option disabled value="">------请选择------</option>
                  <!--遍历过程中 需要显示在页面中的数据 通常用插值 {
              {
              option.text } }
                  如果是给属性赋值 需要使用绑定数据的语法 给属性做绑定 
                  并通过遍历到的数据给其赋值  : value = "option.val" -->
      			    <option v-for="option in options" :value="option.val">	
                            {
             {
             option.text}}
                      </option> 
      
      			
      			</select>
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          options:[{
             val:"1001",text:"北京"},
      						{
             val:"2001",text:"上海"},
      						{
             val:"3001",text:"深圳"}]
                      }
                  })
              </script>
      
    9. 钩子函数

      vue的数据绑定 渲染是通过vue对象自动实现的,这个过程我们无法主动参与,vue为了让程序员可以在进行这些步骤时,加一些程序员自己的处理,加入了钩子函数 钩子函数实际上就是在vue对象创建过程中,提供了几个执行的时机,在这些时机发生时 可以同时执行程序员自己的代码 类似javaEE中的监听器

      JavaWeb_第10张图片

    ​ vue中提供了一些钩子函数

    • beforeCreate

    • created

    • beforeMount

    • mounted

    • beforeUpdate

    • updated

    • beforeDestroy

    • destroyed

      vue对象创建 create

      vue挂载 mount

      vue属性改变 update

      vue销毁 destory

      如果有一些自己需要执行的代码 可以写在钩子函数中 语法如下

      		<div id="base">
                	<select v-model="area" @change="getVal">
      				<option disabled value="">------请选择------</option>
                  <!--遍历过程中 需要显示在页面中的数据 通常用插值 {
              {
              option.text } }
                  如果是给属性赋值 需要使用绑定数据的语法 给属性做绑定 
                  并通过遍历到的数据给其赋值  : value = "option.val" -->
      			    <option v-for="option in options" :value="option.val">	
                            {
             {
             option.text}}
                      </option> 
      
      			
      			</select>
      		</div>
      		<script>
                  var myvue = new Vue({
             
                      el:"#base",
                      data:{
             
                          options:[{
             val:"1001",text:"北京"},
      						{
             val:"2001",text:"上海"},
      						{
             val:"3001",text:"深圳"}]
                      },
                      methods:{
             
                          mymethod(){
             
                              //xxxxx
                          }
                      },
                      created() {
             
      					//创建出vue对象后执行
      				},
                      mounted(){
             
                          //vue对象挂载到#base后执行
                      }
                  })
              </script>
      

      5.vue常用组件

      1.axios

      Vue推荐使用 axios 来完成 ajax 请求。

      axios 基于promise对象 针对promise对象的成功和失败 封装在.then 和.catch中

      .then中编写服务器正常响应的代码

      .catch中 编写服务器异常响应的代码

      导入axios文件

      <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script>
      

      请求写法:

      //param 为请求时需要传递的参数 可以从vue的data中取值放在参数中
      axios.get('请求路径?'+param)
          .then(response => {
             
          //response为完整的响应的数据
          console.log(response);
          //response.data为服务端响应的json
          console.log(response.data);
      }).catch(function(error) {
             
          //异常时的异常信息对象
          console.log(error);
      });
      
      //post方式 请求路径后不拼参数 请求的参数放在post方法的第二个参数上
      axios.post('请求路径',param)
          .then(response=>{
             
          console.log(response);
          console.log(response.data);
      }).catch(function (error) {
             
          console.log(error);
      });
      
      
      
    注意:使用post方式传递参数时 如果参数为json格式 请求的参数会放入请求头的payload中 不在formdata中
      
    后台直接用getParameter取值会取不到 如果后台想通过getParameter取值 需要让参数进入formdata中,在axios中如果参数格式为url普通键值对参数(xxx=xxx&yyy=yyy)那么参数就会进入formdata
      
    
      
    手动拼接参数不便时 我们会需要使用到一个把json转为url普通键值对参数的工具
      
    引入地址:
      
      ```javascript
      
    

    用法:

    axios.post('请求路径', window.Qs.stringify(this.myform))
        .then(response=>{
         
        console.log(response);
        console.log(response.data);
    }).catch(function (error) {
         
        console.log(error);
    });
    
    //同源策略  域检请求
    		//禁止跨域访问
    		//跨协议  跨ip  跨 端口 都算跨域
    
    
    /*      解决跨域问题
            resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
            resp.setHeader("Access-Control-Allow-Origin", "*");
            // 允许的访问方法
            resp.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
            // Access-Control-Max-Age 用于 CORS 相关配置的缓存
            resp.setHeader("Access-Control-Max-Age", "3600");
            resp.setHeader("Access-Control-Allow-Headers", "token,Origin, X-Requested-With, Content-Type, Accept");
    */
    
       实例:
        /* 允许跨域的主机地址 */
        resp.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8848");
        /* 允许跨域的请求方法GET, POST, HEAD 等 */
        resp.setHeader("Access-Control-Allow-Methods", "*");
        /* 重新预检验跨域的缓存时间 (s) */
        resp.setHeader("Access-Control-Max-Age", "3600");
        /* 允许跨域的请求头 */
        resp.setHeader("Access-Control-Allow-Headers", "*");
        /* 是否携带cookie */
        resp.setHeader("Access-Control-Allow-Credentials", "true");
    

    你可能感兴趣的:(javaweb,前端)