JavaWeb

Java 同时被 2 个专栏收录
9 篇文章 0 订阅
1 篇文章 0 订阅

JavaWeb 知识点总结

文章目录

HTML/CSS/JS

HTML

HTML简介

HTML:HyperText Markup Language,超文本标记语言

超文本:超级文本,能做到普通文本做不到的事情,比如:图片,视频,音频,点击跳转……

标记:标签。将你需要的功能封装成各种各样的标签,你需要使用什么功能,就使用对应的标签即可。

常规标签

标签名称语法
标题标签<h1></h1><h6></h6>
分割线标签<hr/>
文字标签<font></font>
加粗标签<strong>
斜体标签<em>/<i>
下划线标签<u>
删除线标签<del>
换行标签<br/>
段落标签<p>
实体字符空格:&nbsp;,&:&amp;
注释<!-- -->

超文本标签

标签名称语法
图片标签<img src="图片路径" width="宽度" height="高度" title="标题" alt="加载失败时显示的内容"/>
超链接标签<a href="要跳转的路径" target="页面打开的位置(常用值:_self(默认)/_blank)">点击的内容</a>
列表标签无序:<ul></ul>,有序:<ol></ol> (常用属性type);列表项:<li></li>
表格标签<table><tr><td></td></tr></table>
表单标签<form action="提交位置" method="post/get"></form>
表单域标签<input type="" name="" value="" />
下拉框标签<select><option></option></select>
文本域标签<textarea cols="可见列数" rows="可见行数"></textarea>
框架标签<frameset> <frame>

表格标签

  • <table>的属性:

    • border:边框
    • cellpadding:内容与边框之间的距离
    • cellspacing:框与框之间的距离
    • width:表格的宽度
    • height:表格的高度
    • align:设置表格水平位置,常用值:left,center,right
    • bgcolor:表格背景颜色
  • <tr>的属性:

    • height:行的高度
    • align:设置行内容的水平位置,常用值:left,center,right
    • bgcolor:设置行的背景颜色
  • <td>的属性:

    • width:设置单元格的宽度,设置宽度以后,当前单元格所在的列都会跟着变化

    • align:设置单元格内容的水平位置,常用值:left,center,right

    • bgcolor:设置单元格的背景颜色

    • 合并单元格属性:

      • rowspan:上下合并

      • colspan:左右合并

        注意:被合并的单元格需要删除掉

  • <thead>:表头

  • <tbody>:表内容

  • <th>:内容自动居中且加粗的单元格

表单标签

  • <form>的常用属性:
    • action:数据提交的位置
    • method:数据提交的方式
  • <input>的常用属性:
    • type属性:
      • text: 文本框
      • password: 密码框
      • radio: 单选按钮,一组单选按钮的name属性值必须一致才能实现单选
      • file: 文件框
      • checkbox: 多选框,通常一组多选框的name属性值是一致的
      • submit: 提交按钮,将表单中的数据提交到action指定的位置
      • reset: 重置按钮
      • button: 普通按钮
    • maxlength:设置输入数据的最大长度
    • value:设置初始值
    • size:设置输入框大小
    • readonly:只读
    • disabled:不可用
    • name:给表单域取名字
    • checked:设置单选按钮和多选框默认选中项目

框架标签

  • <frameset>作用:将页面划分为几个模块

    常用属性:

    • rows:上下划分

    • cols:左右划分

    • border:边框

    • noresize:不能改变模块大小

      注意:<frameset><body>不能同时使用

  • <frame>作用:将指定的HTML文件放到指定的模块中显示出来


CSS

DIV&CSS简介

  • DIV: DIVison, 层叠样式表单元的位置和层次
    • 其实,就是一个标签,主要用于布局。宽度是父标签的100%,高度默认是0,有内容,高度就是内容的高度。
  • CSS: Cascading Style Sheets, 层叠样式表
    • CSS 指层叠样式表 (Cascading Style Sheets)
    • 样式定义如何显示 HTML 元素
    • 样式通常存储在样式表
    • 把样式添加到 HTML 4.0 中,是为了解决内容与表现分离的问题
    • 外部样式表可以极大提高工作效率
    • 外部样式表通常存储在 CSS 文件
    • 多个样式定义可层叠为一

CSS的三种使用方式

  1. 行内样式

    在标签中使用style属性设置CSS样式

  2. 内部样式

    <head>标签中使用<style>标签进行CSS样式设置

  3. 外部样式

    将CSS样式独立到一个.css的文件中,在需要使用该样式的HTML文件中使用<link>引入该css文件

CSS样式语法
行内样式<div style="..."></div>
内部样式<style type="text/css">div{...}</style>
外部样式<link href="css/style.css" type="text/css" rel="stylesheet"/>

CSS选择器

在内部样式或者外部样式中使用

语法:

选择器{
样式名1:样式值1;
样式名2:样式值1;
……
}
选择器类型HTML中选择器语法
标签选择器<标签名></标签名>标签名{...}
ID选择器<标签名 id="ID名"></标签名>#ID名{...}
类选择器<标签名 class="类名"></标签名>.类名{...}

三种基本选择器的优先级:

  • ID选择器>类选择器>标签选择器

CSS基本样式

样式类型属性1属性2属性3属性4属性N…
字体样式font-familyfont-sizefont-style (字体倾斜)font-weight (字体加粗)font-…
文本样式width/heightbackground-color/colortext-decoration (装饰加线)text-indent (首行缩进)text-…
超链接伪样式a:link (点击之前)a:visited (点击后)a:hover: (鼠标放到上面)a:active: (鼠标点击未释放)a:…
边框样式width/heightborderborder-left/right/top/buttomborder-radiusborder-…
背景样式width/heightbackground-colorbackground-imagebackground-positionbackground-…

盒子模型

  • 盒子模型: content(标签设置的宽和高)–>padding(内边距)–>border–>margin(外边距)

  • 内边距: 内容与边框之间的空白区域

    相关样式: padding,padding-top,padding-right,padding-bottom,padding-left

  • 外边距:边框与父标签之间的空白区域

    样式: margin,margin-top,margin-right,margin-bottom,margin-left

  • 使用margin让盒子水平居中

    margin: auto;

浮动

  • 样式:float
    • 常用值:left,right
    • 浮动的框可以向左或者向右移动,知道它的外边框碰到父标签的边缘或者另一个浮动框的边缘为止。
  • 样式:clean
    • 常用值:left,right,both
    • 清除前面的浮动对后面的标签造成的影响。

定位

  • 样式:position
    • 常用值:relative,absolute,fixed
    • 偏移量样式:left,right,top,bottom
定位样式常用值特征
相对定位relative相对于原来的位置进行偏移,原本的位置会保留
绝对定位absolute相对于页面的顶点来偏移,原本的位置不保留
固定定位fixed相对于页面顶点进行偏移,原本的位置不保留,不受滚动条的影响

实现导航效果

标签的分类:

  • 行标签:不会自动换行,不能设置宽高
    • <font>,<strong>,<b>,<em>,<i>,<u>,<del>,<a>,<span>……
  • 块标签:能自动换行,能设置宽高
    • <div>,<table>,<ul>,<li>,<ol>,<h*>……
  • 行块标签:不会自动换行,能设置宽高
    • <img>

标签类型的转换

  • 样式:display
    • 常用值:
      • inline:转换成行标签,
      • block:转换成块标签,
      • inline-block:转换成行块标签,
      • none:隐藏

浮动与行块转换的区别:

  1. 浮动会对后面的标签产生影响,行块转换不会
  2. 浮动后,标签是紧挨在一起的,行块转换后,标签之间有默认的空隙

JavaScript

JS简介

  • JavaScript (简称JS) 是一种具有函数优先的轻量级,解释型的高级编程语言。

  • JS是一门客户端脚本语言

    • 运行在客户端JS浏览器中的。每一个浏览器都有JavaScript的解析引擎
    • 脚本语言:不需要编译,直接就可以被浏览器解析执行了
  • JS可以通过DOM操作HTML的标签,读写标签的内容,验证提交的数据,验证浏览器的信息,也可以给页面添加动画效果。

JS组成

  • ECMAScript:核心,包含了基本的语法,语句,事件,对象等等
  • DOM:Document Object Model,文档对象模型,操作元素
  • BOM:Broswer Object Model,浏览器对象模型,操作浏览器

JS的三种使用方式

  1. 行内式

    在标签中的事件里使用javascript:加JS语法。

  2. 内嵌式

    将JS代码写在<script>标签中。<script>可以写在页面的任意位置。

  3. 外链式

    将JS代码写到一个后缀名为.js的文件中,再在HTML中使用<script>引入该js文件。

JS样式语法
行内式<input type="button" value="click me" onclick="javascript:alert('Hello JS')"/>
内嵌式<script type="text/javascript">alert('Hello JS')</script>
外链式<script type="text/javascript" src="js/script.js"></script>

JS基础语法

  1. 变量
  • JS本身是一门弱类型语言,不需要指定数据类型,直接使用var关键字即可。

  • 语法:(三种写法)

    • var 变量名;
    • var 变量名 = 变量值;
    • var 变量名1,变量名;
  1. 数据类型
数据类型分类数据类型介绍
基础数据类型Undefined值只有undefined,定义的变量未初始化
基础数据类型Null值只有null,Undefined是Null派生出来的。ECMAScript将Undefined与Null认定为等值
引用数据类型Number任意数字
引用数据类型String字符串,可以使用双引号也可以使用单引号
引用数据类型Boolean布尔,值只有true和false

引用数据类型:通常叫做类(Class),JS会将之转换成对象来使用。

  1. 运算符
运算符分类运算符
算数运算符+ - * / % ++ --
赋值运算符= += -= *= /= %=
比较运算符> >= < <= == !=
逻辑运算符&& || !
条件运算符(三元运算符)?:
  1. 分支结构
分支结构语法
单分支if(条件){...}
双分支if(条件){...}else{...}
多分支if(条件1){...}else if(条件2){...}else{...}
等值多分支:switch(值){case 分支1: ...; break; ... 分支N: ...; break; default: ...;}
  1. 数组
创建数组方法语法
创建空数组var arr1 = new Array();
创建有长度的数组var arr2 = new Array(5);
创建有初始值的数组var arr3 = ["d","a","n","n","y"];
  1. 循环结构

JS中的循环与Java中循环基本一致。

循环语句语法
whilewhile(条件){...}
do whiledo(...)while(条件){...}
forfor(var i=0; i<5; i++){...}
forEachfor(var str in 数组名){...}

JS函数

函数类型语法
无参函数function 函数名(){函数体;}
有参函数function 函数名(形参1,形参2,...){函数体;}
有返回值的函数function 函数名(形参1,形参2,...){函数体;return...;}

JS事件句柄(Event Handlers)

HTML 4.0 的新特性之一是能够使 HTML 事件触发浏览器中的行为,比如当用户点击某个 HTML 元素时启动一段 JavaScript。下面是一个属性列表,可将之插入 HTML 标签以定义事件的行为。

属性此事件发生在何时…
onabort图像的加载被中断。
onblur元素失去焦点
onchange域的内容被改变。
onclick当用户点击某个对象时调用的事件句柄。
ondblclick当用户双击某个对象时调用的事件句柄。
onerror在加载文档或图像时发生错误。
onfocus元素获得焦点
onkeydown某个键盘按键被按下。
onkeypress某个键盘按键被按下并松开。
onkeyup某个键盘按键被松开。
onload一张页面或一幅图像完成加载。
onmousedown鼠标按钮被按下。
onmousemove鼠标被移动。
onmouseout鼠标从某元素移开。
onmouseover鼠标移到某元素之上。
onmouseup鼠标按键被松开。
onreset重置按钮被点击。
onresize窗口或框架被重新调整大小。
onselect文本被选中。
onsubmit确认按钮被点击。
onunload用户退出页面。

JS事件绑定

  1. 方式一: 直接在标签上使用对应的事件属性即可

    <script>
    function changeText(id) { 
        id.innerHTML = "Hello:)";
    }
    </script>
    <h1 onclick="changeText(this)">点击此文本!</h1>
    
  2. 方式二: 在JS中找到要绑定事件的标签,再给它绑定对应的事件

    <p>请点击“试一试”按钮,以执行 displayDate() 函数。</p>
    <button id="myBtn">试一试</button>
    <p id="demo"></p>
    <script>
    document.getElementById("myBtn").onclick = displayDate;
    function displayDate() {
      document.getElementById("demo").innerHTML = Date();
    }
    </script>
    </body>
    </html> 
    

DOM

DOM简介

HTML DOM 是 HTML 的标准对象模型和编程接口。它定义了:

  • 作为对象的 HTML 元素
  • 所有 HTML 元素的属性
  • 访问所有 HTML 元素的方法
  • 所有 HTML 元素的事件

换言之:HTML DOM 是关于如何获取、更改、添加或删除 HTML 元素的标准

HTML DOM(文档对象模型)

当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model)。

HTML DOM 模型被结构化为对象树

对象的 HTML DOM 树

DOM HTML 树

通过这个对象模型,JavaScript 获得创建动态 HTML 的所有力量:

  • JavaScript 能改变页面中的所有 HTML 元素
  • JavaScript 能改变页面中的所有 HTML 属性
  • JavaScript 能改变页面中的所有 CSS 样式
  • JavaScript 能删除已有的 HTML 元素和属性
  • JavaScript 能添加新的 HTML 元素和属性
  • JavaScript 能对页面中所有已有的 HTML 事件作出反应
  • JavaScript 能在页面中创建新的 HTML 事件

使用DOM查找元素

四种方法查询元素语法
通过id属性的值来找到元素。只能找到一个元素document.getElementById(“id属性值”);
通过name属性值来找到元素。因为name属性的值可以重复,所以能找到多个元素,所以返回的是元素数组。document.getElementsByName(“name属性值”);
通过class属性值来找到元素。因为class属性的值可以重复,所以能找到多个元素,所以返回的是元素数组。document.getElementsByClassName(“class属性值”);
通过标签名来找到元素。因为标签名可以重复,所以能找到多个元素,所以返回的是元素数组。document.getElementsByTagName(“标签名”);

使用DOM修改元素

修改元素语法
修改属性document.getElementById(id).attribute = new value
修改内容document.getElementById(id).innerHTML = new text
修改样式document.getElementById(id).style.property = new style

关于innerText和innerHTML的区别

  1. 获取内容时:
    • innerText只能获取文本内容,不能获取标签;
    • innerHTML能获取所有内容。
  2. 设置内容时:
    • innerText会将标签当成普通文本放进去;
    • innerHTML放进去的标签能被浏览器直接翻译。

BOM

BOM简介

  • 浏览器对象模型(Browser Object Model (BOM))

  • 不存在浏览器对象模型(BOM)的官方标准。

  • 现代的浏览器已经(几乎)实现了 JavaScript 交互相同的方法和属性,因此它经常作为 BOM 的方法和属性被提到。

Window 对象

Window 对象表示浏览器中打开的窗口。

如果文档包含框架(frame 或 iframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框架创建一个额外的 window 对象。

**注释:**没有应用于 window 对象的公开标准,不过所有浏览器都支持该对象。

  • Window 对象集合
集合描述
frames[]返回窗口中所有命名的框架。该集合是 Window 对象的数组,每个 Window 对象在窗口中含有一个框架或 <iframe>。属性 frames.length 存放数组 frames[] 中含有的元素个数。注意,frames[] 数组中引用的框架可能还包括框架,它们自己也具有 frames[] 数组。
  • Window 对象属性
属性描述
closed返回窗口是否已被关闭。
defaultStatus设置或返回窗口状态栏中的默认文本。
document对 Document 对象的只读引用。请参阅 Document 对象
history对 History 对象的只读引用。请参数 History 对象
innerheight返回窗口的文档显示区的高度。
innerwidth返回窗口的文档显示区的宽度。
length设置或返回窗口中的框架数量。
location用于窗口或框架的 Location 对象。请参阅 Location 对象
name设置或返回窗口的名称。
Navigator对 Navigator 对象的只读引用。请参数 Navigator 对象
opener返回对创建此窗口的窗口的引用。
outerheight返回窗口的外部高度。
outerwidth返回窗口的外部宽度。
pageXOffset设置或返回当前页面相对于窗口显示区左上角的 X 位置。
pageYOffset设置或返回当前页面相对于窗口显示区左上角的 Y 位置。
parent返回父窗口。
Screen对 Screen 对象的只读引用。请参数 Screen 对象
self返回对当前窗口的引用。等价于 Window 属性。
status设置窗口状态栏的文本。
top返回最顶层的先辈窗口。
windowwindow 属性等价于 self 属性,它包含了对窗口自身的引用。
screenLeft screenTop screenX screenY只读整数。声明了窗口的左上角在屏幕上的的 x 坐标和 y 坐标。IE、Safari 和 Opera 支持 screenLeft 和 screenTop,而 Firefox 和 Safari 支持 screenX 和 screenY。

Window定时器

  1. 周期定时器:
  • var id=window.setInterval(function,time);//每隔多少时间就执行某函数。
    //function是要执行的函数。time是间隔时间,单位是毫秒。
    //清除定时器:
    window.clearInterval(id);
    
  1. 超时定时器:
  • var id = window.setTimeout(function,time);//隔多少时间调用某函数。
    //function是被调用的函数。time是时间,单位是毫秒。
    //清除定时器:
    window.clearTimeout(id);
    

Windows弹框

类型语法(window 前缀可省略)
警告框window.alert("sometext");如果要确保信息传递给用户,通常会使用警告框。当警告框弹出时,用户将需要单击“确定”来继续
确认框window.confirm("sometext");如果您希望用户验证或接受某个东西,则通常使用“确认”框。当确认框弹出时,用户将不得不单击“确定”或“取消”来继续进行。如果用户单击“确定”,该框返回 true。如果用户单击“取消”,该框返回 false
提示框window.prompt("sometext","defaultText");如果您希望用户在进入页面前输入值,通常会使用提示框。当提示框弹出时,用户将不得不输入值后单击“确定”或点击“取消”来继续进行。如果用户单击“确定”,该框返回输入值。如果用户单击“取消”,该框返回 NULL

Window其他对象

window 前缀可省略

  • window.location 对象可用于获取当前页面地址(URL)并把浏览器重定向到新页面。

    • window.location.href 返回当前页面的 href (URL)
    • window.location.hostname 返回 web 主机的域名
    • window.location.pathname 返回当前页面的路径或文件名
    • window.location.protocol 返回使用的 web 协议(http: 或 https:)
    • window.location.assign 加载新文档
  • window.history 对象包含浏览器历史。

    • history.back() - 等同于在浏览器点击后退按钮
    • history.forward() - 等同于在浏览器中点击前进按钮

jQuery

jQuery简介

  • jQuery 库可以通过一行简单的标记被添加到网页中。

  • jQuery 是一个 JavaScript 函数库。

  • jQuery 库包含以下特性:

    • HTML 元素选取

      HTML 元素操作

      CSS 操作

      HTML 事件函数

      JavaScript 特效和动画

      HTML DOM 遍历和修改

      AJAX

      Utilities

jQurey的使用

  1. 下载jQuery库文件
  • https://jquery.com/
  1. 添加 jQuery 库

    • jQuery 库位于一个 JavaScript 文件中,其中包含了所有的 jQuery 函数。

    • 可以通过下面的标记把 jQuery 添加到网页中:

    • <head>
      <script type="text/javascript" src="js/jquery-3.5.1.js" ></script>
      </head>
      

      请注意,<script>标签应该位于页面的 <head>部分。

  2. jQuery的使用

    • <script type="text/javascript">
      	//就绪函数:当前页面加载完成后自动执行的函数
      	jQuery(document).ready(function(){
      		alert("这是最原始的就绪函数");
      	});
      	//第二个版本的就绪函数
      	$(document).ready(function(){
      		alert("这是第二个版本的就绪函数");
      	});
      	//最简单的就绪函数
      	$(function(){
              alert("这是最简单的就绪函数");
      	});
      </script>
      

DOM对象与jQuery对象的转换

<script type="text/javascript">
	$(function(){
		//使用DOM获取id为test的元素,获取到的元素对象我们称为DOM对象(js对象)
		var testDOM = document.getElementById("test");
		//alert(testDOM.innerText);
		
		//使用jQuery获取id为test的元素,获取到的元素对象我们称为jQuery对象
		var testjQuery = $("#test");
		//alert(testjQuery.text());
		//结论:DOM对象的属性与jQuery对象函数不能混用
				
		//将DOM对象转换为jQuery对象
		//alert($(testDOM).text());
				
		//将jQuery对象转换为DOM对象
		//alert(testjQuery[0].innerText);
		//alert(testjQuery.get(0).innerText);
	});
</script>

jQuery选择器

  1. 基本选择器
选择器实例选取
*$("*")所有元素
#id$("#lastname")id=“lastname” 的元素
.class$(".intro")所有 class=“intro” 的元素
element$(“p”)所有 <p> 元素
.class.class$(".intro.demo")所有 class=“intro” 且 class=“demo” 的元素
  1. 层次选择器
选择器实例选取
(空格)$(“out span”)id=out元素中所有的span元素
>$(“out>span”)id=out元素中的span子元素
~$(“out~span”)id=out元素后面同辈的span元素
+$(“out+span”)id=out元素后面同辈相邻的span元素
  1. 过滤选择器
选择器实例选取
:first$(“p:first”)第一个<p> 元素
:last$(“p:last”)最后一个 <p> 元素
:even$(“tr:even”)所有偶数 <tr>元素
:odd$(“tr:odd”)所有奇数 <tr> 元素
:eq(index)$(“ul li:eq(3)”)列表中的第四个元素(index 从 0 开始)
:gt(no)$(“ul li:gt(3)”)列出 index 大于 3 的元素
:lt(no)$(“ul li:lt(3)”)列出 index 小于 3 的元素
:not(selector)$(“input:not(:empty)”)所有不为空的 input 元素
  1. 属性选择器
选择器实例选取
[attribute]$("[href]")所有带有 href 属性的元素
[attribute=value]$("[href=’#’]")所有 href 属性的值等于 “#” 的元素
[attribute!=value]$("[href!=’#’]")所有 href 属性的值不等于 “#” 的元素
[attribute^=value]$("[href^=’#’]")所有 href 属性的值包含以 “#” 开头的元素
[attribute$=value] ( " [ h r e f ("[href ("[href=’.jpg’]")所有 href 属性的值包含以 “.jpg” 结尾的元素
[attribute**=value]$("[href*=’#’]")所有 href 属性含有"#" 的元素
  1. 表单选择器
选择器实例选取
:input$(":input")所有 <input> 元素
:text$(":text")所有 type=“text” 的 <input>元素
:password$(":password")所有 type=“password” 的 <input>元素
:radio$(":radio")所有 type=“radio” 的 <input>元素
:checkbox$(":checkbox")所有 type=“checkbox” 的 <input>元素
:submit$(":submit")所有 type=“submit” 的 <input> 元素
:reset$(":reset")所有 type=“reset” 的 <input> 元素
:button$(":button")所有 type=“button” 的 <input> 元素
:image$(":image")所有 type=“image” 的 <input> 元素
:file$(":file")所有 type=“file” 的 <input> 元素
:enabled$(":enabled")所有激活的 input 元素
:disabled$(":disabled")所有禁用的 input 元素
:selected$(":selected")所有被选取的 input 元素
:checked$(":checked")所有被选中的 input 元素

jQuery绑定事件

<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
  $("button").click(function(){
    $("p").hide();
  });
});
</script>
</head>

<body>
<h2>This is a heading</h2>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<button>Click me</button>
</body>

</html>

jQuery特效

  • jQuery hide() 和 show()

    通过 jQuery,您可以使用 hide() 和 show() 方法来隐藏和显示 HTML 元素:

$("#hide").click(function(){
  $("p").hide();
});

$("#show").click(function(){
  $("p").show();
});
  • 语法:
$(selector).hide(speed,callback);

$(selector).show(speed,callback);
  • 可选的 speed 参数规定隐藏/显示的速度,可以取以下值:“slow”、“fast” 或毫秒。

  • 可选的 callback 参数是隐藏或显示完成后所执行的函数名称。

jQuery 效果函数

方法(speed,callback)描述
animate()对被选元素应用“自定义”的动画
clearQueue()对被选元素移除所有排队的函数(仍未运行的)
delay()对被选元素的所有排队函数(仍未运行)设置延迟
dequeue()运行被选元素的下一个排队函数
fadeIn()逐渐改变被选元素的不透明度,从隐藏到可见(淡入)
fadeOut()逐渐改变被选元素的不透明度,从可见到隐藏(淡出)
fadeToggle()淡入与淡出之间切换
fadeTo()把被选元素逐渐改变至给定的不透明度
hide()隐藏被选的元素
queue()显示被选元素的排队函数
show()显示被选的元素
slideDown()通过调整高度来滑动显示被选元素(向下显示)
slideToggle()对被选元素进行滑动隐藏和滑动显示的切换
slideUp()通过调整高度来滑动隐藏被选元素(向上隐藏)
stop()停止在被选元素上运行动画
toggle()对被选元素进行隐藏和显示的切换

jQuery操作CSS

jQuery 拥有若干进行 CSS 操作的方法。

  • addClass() - 向被选元素添加一个或多个类
  • removeClass() - 从被选元素删除一个或多个类
  • toggleClass() - 对被选元素进行添加/删除类的切换操作
  • css() - 设置或返回样式属性

jQuery操作属性

  • attr()

    • attr(“属性名”)
      • 获取某属性的值
    • attr(“属性名”,”属性值”)
      • 设置某属性的值
  • prop()

    • prop(“属性名”)
      • 获取某属性的值
    • prop(“属性名”,”属性值”)
      • 设置某属性的值
  • attr()与prop()的区别:

    • attr()在jQuery1.5以后就不进行维护了,推荐使用prop()。

jQuery操作DOM

  • $();创建标签
  • append();在指定的标签中后置添加
  • prepend();在指定的标签中前置添加
  • after();在指定的标签后面添加
  • before();在指定的标签前面添加
  • remove();移除某标签

jQuery 遍历函数

jQuery 遍历函数包括了用于筛选、查找和串联元素的方法。

函数描述
.add()将元素添加到匹配元素的集合中。
.andSelf()把堆栈中之前的元素集添加到当前集合中。
.children()获得匹配元素集合中每个元素的所有子元素。
.closest()从元素本身开始,逐级向上级元素匹配,并返回最先匹配的祖先元素。
.contents()获得匹配元素集合中每个元素的子元素,包括文本和注释节点。
.each()对 jQuery 对象进行迭代,为每个匹配元素执行函数。
.end()结束当前链中最近的一次筛选操作,并将匹配元素集合返回到前一次的状态。
.eq()将匹配元素集合缩减为位于指定索引的新元素。
.filter()将匹配元素集合缩减为匹配选择器或匹配函数返回值的新元素。
.find()获得当前匹配元素集合中每个元素的后代,由选择器进行筛选。
.first()将匹配元素集合缩减为集合中的第一个元素。
.has()将匹配元素集合缩减为包含特定元素的后代的集合。
.is()根据选择器检查当前匹配元素集合,如果存在至少一个匹配元素,则返回 true。
.last()将匹配元素集合缩减为集合中的最后一个元素。
.map()把当前匹配集合中的每个元素传递给函数,产生包含返回值的新 jQuery 对象。
.next()获得匹配元素集合中每个元素紧邻的同辈元素。
.nextAll()获得匹配元素集合中每个元素之后的所有同辈元素,由选择器进行筛选(可选)。
.nextUntil()获得每个元素之后所有的同辈元素,直到遇到匹配选择器的元素为止。
.not()从匹配元素集合中删除元素。
.offsetParent()获得用于定位的第一个父元素。
.parent()获得当前匹配元素集合中每个元素的父元素,由选择器筛选(可选)。
.parents()获得当前匹配元素集合中每个元素的祖先元素,由选择器筛选(可选)。
.parentsUntil()获得当前匹配元素集合中每个元素的祖先元素,直到遇到匹配选择器的元素为止。
.prev()获得匹配元素集合中每个元素紧邻的前一个同辈元素,由选择器筛选(可选)。
.prevAll()获得匹配元素集合中每个元素之前的所有同辈元素,由选择器进行筛选(可选)。
.prevUntil()获得每个元素之前所有的同辈元素,直到遇到匹配选择器的元素为止。
.siblings()获得匹配元素集合中所有元素的同辈元素,由选择器筛选(可选)。
.slice()将匹配元素集合缩减为指定范围的子集。

实例

输出每个 li 元素的文本:

$("button").click(function(){
  $("li").each(function(){
    alert($(this).text())
  });
});

定义和用法

each() 方法规定为每个匹配元素规定运行的函数。

**提示:**返回 false 可用于及早停止循环。

语法

$(selector).each(function(index,element))

Database

数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。

数据库相关概念:

  • 数据库系统(DBS):包括数据库管理系统,数据库管理员,数据库
  • 数据库管理系统(DBMS):操作和管理数据库的大型软件
  • 数据库管理员(DBA):操作和维护受苦管理系统的工作人员
  • 数据库(DB):按照数据结构来组织,存储和管理数据的仓库

数据库的分类:

  • 关系型数据库管理系统:以表格的形式存储数据,表格与表格之间会有关系。比如:MySQL,SQL Server,Oracle……
  • 非关系型数据库管理系统:结构简单,数据之间没有关系。比如:Redis,MongeDB……

每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据。

我们也可以将数据存储在文件中,但是在文件中读写数据速度相对较慢。

所以,现在我们使用关系型数据库管理系统(RDBMS)来存储和管理大数据量。所谓的关系型数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。

RDBMS 即关系数据库管理系统(Relational Database Management System)的特点:

  • 1.数据以表格的形式出现
  • 2.每行为各种记录名称
  • 3.每列为记录名称所对应的数据域
  • 4.许多的行和列组成一张表单
  • 5.若干的表单组成database

MySQL简介

MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。

  • MySQL 是开源的,目前隶属于 Oracle 旗下产品。
  • MySQL 支持大型的数据库。可以处理拥有上千万条记录的大型数据库。
  • MySQL 使用标准的 SQL 数据语言形式。
  • MySQL 可以运行于多个系统上,并且支持多种语言。这些编程语言包括 C、C++、Python、Java、Perl、PHP、Eiffel、Ruby 和 Tcl 等。
  • MySQL 对PHP有很好的支持,PHP 是目前最流行的 Web 开发语言。
  • MySQL 支持大型数据库,支持 5000 万条记录的数据仓库,32 位系统表文件最大可支持 4GB,64 位系统支持最大的表文件为8TB。
  • MySQL 是可以定制的,采用了 GPL 协议,你可以修改源码来开发自己的 MySQL 系统。

MySQL基本操作

  1. 登录数据库管理系统

    • 使用MySQL 5.5 Command Line Client 或者

    • 使用控制台(CMD)

      • 输入命令

        mysql -h地址(如果登录本地可省略) -u账号 -p密码

  2. DOS命令

    • 关闭服务: net stop mysql
    • 启动服务: net start mysql
    • 退出: exit;

SQL语言

  • SQL 是用于访问和处理数据库的标准的计算机语言。

  • 什么是 SQL?

    • SQL 指结构化查询语言

    • SQL 使我们有能力访问数据库

    • SQL 是一种 ANSI 的标准计算机语言

      **编者注:**ANSI,美国国家标准化组织

  • SQL 能做什么?

    • SQL 面向数据库执行查询
    • SQL 可从数据库取回数据
    • SQL 可在数据库中插入新的记录
    • SQL 可更新数据库中的数据
    • SQL 可从数据库删除记录
    • SQL 可创建新数据库
    • SQL 可在数据库中创建新表
    • SQL 可在数据库中创建存储过程
    • SQL 可在数据库中创建视图
    • SQL 可以设置表、存储过程和视图的权限
  • 结构化查询语言,是一门带有特殊目的的编程语言,用于操作数据库。

  • SQL的分类:

    • DDL:数据库定义语言,针对库,表进行创建,修改以及删除等操作。
  • DML:数据库操作语言,针对表数据进行新增,修改以及删除等操作。

    • DQL:数据库查询语言,针对表数据进行查询操作。
  • DCL:数据库权限控制语言,对数据库管理系统进行权限控制。

    • DTL(TCL):数据库事务语言,确保DML对数据的影响得以更新。
  • CCL:指针控制语言,对一个表或者多个表进行单独操作。

MySQL数据类型

在 MySQL 中,有三种主要的类型:文本、数字和日期/时间类型。

Text 类型:

数据类型描述
CHAR(size)保存固定长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的长度。最多 255 个字符。
VARCHAR(size)保存可变长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的最大长度。最多 255 个字符。注释:如果值的长度大于 255,则被转换为 TEXT 类型。
TINYTEXT存放最大长度为 255 个字符的字符串。
TEXT存放最大长度为 65,535 个字符的字符串。
BLOB用于 BLOBs (Binary Large OBjects)。存放最多 65,535 字节的数据。
MEDIUMTEXT存放最大长度为 16,777,215 个字符的字符串。
MEDIUMBLOB用于 BLOBs (Binary Large OBjects)。存放最多 16,777,215 字节的数据。
LONGTEXT存放最大长度为 4,294,967,295 个字符的字符串。
LONGBLOB用于 BLOBs (Binary Large OBjects)。存放最多 4,294,967,295 字节的数据。
ENUM(x,y,z,etc.)允许你输入可能值的列表。可以在 ENUM 列表中列出最大 65535 个值。如果列表中不存在插入的值,则插入空值。注释:这些值是按照你输入的顺序存储的。可以按照此格式输入可能的值:ENUM(‘X’,‘Y’,‘Z’)
SET与 ENUM 类似,SET 最多只能包含 64 个列表项,不过 SET 可存储一个以上的值。

Number 类型:

数据类型描述
TINYINT(size)-128 到 127 常规。0 到 255 无符号*。在括号中规定最大位数。
SMALLINT(size)-32768 到 32767 常规。0 到 65535 无符号*。在括号中规定最大位数。
MEDIUMINT(size)-8388608 到 8388607 普通。0 to 16777215 无符号*。在括号中规定最大位数。
INT(size)-2147483648 到 2147483647 常规。0 到 4294967295 无符号*。在括号中规定最大位数。
BIGINT(size)-9223372036854775808 到 9223372036854775807 常规。0 到 18446744073709551615 无符号*。在括号中规定最大位数。
FLOAT(size,d)带有浮动小数点的小数字。在括号中规定最大位数。在 d 参数中规定小数点右侧的最大位数。
DOUBLE(size,d)带有浮动小数点的大数字。在括号中规定最大位数。在 d 参数中规定小数点右侧的最大位数。
DECIMAL(size,d)作为字符串存储的 DOUBLE 类型,允许固定的小数点。

* 这些整数类型拥有额外的选项 UNSIGNED。通常,整数可以是负数或正数。如果添加 UNSIGNED 属性,那么范围将从 0 开始,而不是某个负数。

Date 类型:

数据类型描述
DATE()日期。格式:YYYY-MM-DD注释:支持的范围是从 ‘1000-01-01’ 到 ‘9999-12-31’
DATETIME()*日期和时间的组合。格式:YYYY-MM-DD HH:MM:SS注释:支持的范围是从 ‘1000-01-01 00:00:00’ 到 ‘9999-12-31 23:59:59’
TIMESTAMP()*时间戳。TIMESTAMP 值使用 Unix 纪元(‘1970-01-01 00:00:00’ UTC) 至今的描述来存储。格式:YYYY-MM-DD HH:MM:SS注释:支持的范围是从 ‘1970-01-01 00:00:01’ UTC 到 ‘2038-01-09 03:14:07’ UTC
TIME()时间。格式:HH:MM:SS 注释:支持的范围是从 ‘-838:59:59’ 到 ‘838:59:59’
YEAR()2 位或 4 位格式的年。注释:4 位格式所允许的值:1901 到 2155。2 位格式所允许的值:70 到 69,表示从 1970 到 2069。

* 即便 DATETIME 和 TIMESTAMP 返回相同的格式,它们的工作方式很不同。在 INSERT 或 UPDATE 查询中,TIMESTAMP 自动把自身设置为当前的日期和时间。TIMESTAMP 也接受不同的格式,比如 YYYYMMDDHHMMSS、YYMMDDHHMMSS、YYYYMMDD 或 YYMMDD。

DDL数据定义语言

DDL库操作

关键字含义语法
database数据库
create创建create database 数据库名 character set 编码集
show展示show databases / show create database 数据库名
alter修改alter database 数据库名 character set 编码集
drop删除drop database 数据库名
use使用use database 数据库名

DLL表操作

关键字含义语法
table
create创建create table 表名 (列名1 数据类型1, 列名2 数据类型2, ...)
show展示当前库中的所有表show tables
desc展示表的信息desc 表名
alter修改表alter ...
rename修改表名alter table 旧表名 rename 新表名
change修改列alter table 表名 change 旧表名 新表名 数据类型
add添加列alter table 表名 add 列名
drop删除列alter table 表名 drop 列名
drop删除表drop table 表名

DML数据操作

关键字含义语法
insert新增insert into 表名(列1,列2,……) values(值1,值2,……)
update修改update 表名 set 列1=值1,列2=值2,…… where 列=值
delete删除delete from 表名 where 列=值
truncate清空truncate 表名
  • 两种清空方式的区别:

    1. delete清空,将表数据一条一条删除。

    2. truncate清空,先将表删除掉,再创建一张跟之前一样的表。

    3. truncate效率较高

DQL数据查询

关键字含义语法
select查询select * from 表名 where 条件1 and 条件2...
like模糊查询select * from 表名 where 列 like 通配符+值
limit分页查询select * from 表名 limit 数值1(索引),数值2(每页显示多少数据);
order by (默认asc)排序select * from 表名 order by 列 (asc/desc)
distinct去重select distinct 列 from 表名
  • 通配符:
    • %:代表任意个字符
    • _:代表一个字符
  • 排序关键字:order by
    • 升序:默认/asc
    • 降序:desc

MySQL进阶

事务

事务简介
  • 完成一个功能,需要执行多条SQL语句,可以使用事务将这些SQL语句绑定成一个逻辑单元;要么全部执行成功;如果其中任意一条出现错误,则全部失败,已执行的要全部撤销,及回滚。
  • 事务的语句:
    • 开启一个事务:start transaction
    • 提交事务:commit
    • 回滚事务:rollback
  • 实现步骤:
  • start transaction;
  • 写SQL语句
  • 成功commit;
  • 失败rollback;
事务特征
  • MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!

    • 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
    • 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
    • 事务用来管理 insert,update,delete 语句
  • 一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

    • **原子性:**一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
    • **一致性:**在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
    • **隔离性:**数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
    • **持久性:**事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

    MYSQL 事务处理主要有两种方法:

    1. 用 BEGIN, ROLLBACK, COMMIT来实现

      • BEGIN 开始一个事务
      • ROLLBACK 事务回滚
      • COMMIT 事务确认
    2. 直接用 SET 来改变 MySQL 的自动提交模式:

      • SET AUTOCOMMIT=0 禁止自动提交
      • SET AUTOCOMMIT=1 开启自动提交
事务的作用

事务管理对于企业级应用而言至关重要,它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。就像银行的自动提款机ATM,通常ATM都可以正常为客户服务,但是也难免遇到操作过程中及其突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过ATM机一样,以保证用户和银行的利益都不受损失。

并发下事务会产生的问题

举个例子,事务A和事务B操纵的是同一个资源,事务A有若干个子事务,事务B也有若干个子事务,事务A和事务B在高并发的情况下,会出现各种各样的问题。“各种各样的问题”,总结一下主要就是五种:第一类丢失更新、第二类丢失更新、脏读、不可重复读、幻读。五种之中,第一类丢失更新、第二类丢失更新不重要,不讲了,讲一下脏读、不可重复读和幻读。

  1. 脏读

    所谓脏读,就是指事务A读到了事务B还没有提交的数据,比如银行取钱,事务A开启事务,此时切换到事务B,事务B开启事务–>取走100元,此时切换回事务A,事务A读取的肯定是数据库里面的原始数据,因为事务B取走了100块钱,并没有提交,数据库里面的账务余额肯定还是原始余额,这就是脏读。

  2. 不可重复读

    所谓不可重复读,就是指在一个事务里面读取了两次某个数据,读出来的数据不一致。还是以银行取钱为例,事务A开启事务–>查出银行卡余额为1000元,此时切换到事务B事务B开启事务–>事务B取走100元–>提交,数据库里面余额变为900元,此时切换回事务A,事务A再查一次查出账户余额为900元,这样对事务A而言,在同一个事务内两次读取账户余额数据不一致,这就是不可重复读。

  3. 幻读

    所谓幻读,就是指在一个事务里面的操作中发现了未被操作的数据。比如学生信息,事务A开启事务–>修改所有学生当天签到状况为false,此时切换到事务B,事务B开启事务–>事务B插入了一条学生数据,此时切换回事务A,事务A提交的时候发现了一条自己没有修改过的数据,这就是幻读,就好像发生了幻觉一样。幻读出现的前提是并发的事务中有事务发生了插入、删除操作。

事务隔离级别:
事务隔离级别脏读不可重复读幻读数据库的默认级别
未提交读(read-uncommitted)
已提交读(read-committed)Oracle/SQL Server
可重复读(repeatable-read)MySQL
可串行化/序列化(serializable)

以上四种隔离级别按照从低到高的顺序排列为:Read uncommitted < Read committed < Repeatable read < Serializable

  1. Read uncommitted:未提交读,就是一个事务可以读取另一个未提交事务的数据。
  2. Read committed:已提交读,就是一个事务要等另一个事务提交后才能读取数据。
  3. Repeatable read:可重复读,就是在开始读取数据(事务开启)时,不再允许修改操作。
  4. Serializable: 序列化
    • Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

约束

关键字约束语法
primary key主键id int primary key,
auto_increment自增id int primary key auto_increment,
not null非空name varchar(20) not null
unique唯一phone varchar(20) unique
default默认sex char(10) default 'male'
foreign key外键forign key 列 reference 另外一个表名(主键列)
  • 自增特征:

    1. 只有整型数据列才能自增长

    2. 只给主键设置自增长

    3. 自增长列不用手动给值

    4. 初始值为1,增量也为1

    5. 默认的存储引擎下,自增长的数据一旦使用就不会再出现

  • 外键约束: 用来建立表与表之间的关系

  • unsigned: 代表值不能为负

表关系

  • 三种关系:
    • 一对一:one-to-one
      • 例如:丈夫-妻子
      • (外键可以建立在两张表中任意一张表上)
    • 一对多/多对一:one-to-many
      • 例如:班级-学生,用户-订单
      • (会在多的那张表上添加一个列,该列通常是另一张表的主键,外键建立在多的那张表上)
    • 多对多:many-to-many
      • 例如:老师-学生,学生-课程,商品-订单
      • (将两个表的主键一起放到中间表中,在中间表创建外键)

连接查询

连接方式语法
隐式内连接select 要查询的列 from 表名1,表名2 where 连接条件 [and 筛选条件]
显式内连接select 要查询的列 from 表名1 inner join 表名2 on 连接条件 [where 筛选条件]
  • 四种JOIN的差异
    • JOIN: 如果表中有至少一个匹配,则返回行
    • LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
    • RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
    • FULL JOIN: 只要其中一个表中存在匹配,就返回行

聚合函数

  • 集合函数:
    • 最大值:max()
    • 最小值:min()
    • 求和:sum()
    • 统计条数:count()
    • 平均数:avg()
  • 语法
    • select 聚合函数 from 表名

分组查询

  • 将数据按照条件进行分组,再对分组后的数据进行汇总。分组查询通常都会使用聚合函数,对分组后的信息进行统计计算。

    • 关键字:group by [having]

    • 语法:select 查询内容 from 表名 group by 分组列 [having 筛选条件]

  • having和where的区别:

    1. having是对分组后的数据进行筛选,where对分组前的数据进行筛选

    2. SQL语句中一旦出现having,那么前面一定有group by,有group by不一定有having

    3. having后面能使用聚合函数,where后面不能使用聚合函数

    4. 如果一个语句中,既有where又有group by还有having,where先执行,然后是group by,最后是having

子查询(嵌套查询)

  • 以一个表的查询结果作为一个表名/数据进行二次查询
  • 语法
    • select * from 表名2 where 列1 = (select 列1 from 表名1 where 条件)
    • select t1.* from 表名1 t1, (select 列1 from 表名2) t2 where t1.列1 = t2.列1

数据库的备份与恢复

  1. DOS指令
    • 备份
      • mysqldump -u账号 -p密码 要备份的数据库名>d:/文件名.sql
    • 恢复
      • 先创建数据库
      • mysql -u账号 -p密码 要恢复的数据库名<d:/文件名.sql
  2. 使用SQLyog进行备份与恢复

Java DataBase

JDBC

JDBC简介

  • JDBC定义
    • 全称:Java DataBase Connectivity即Java数据库连接技术。
    • 由SUN提供的一套连接数据库的规范(接口)。各个数据库厂商就会遵守这套规范,提供了一套访问自己公司数据库的程序,这套程序称为数据库驱动。
  • 常用的接口和类
    • DriverManager类:驱动管理类,主要作用:注册JDBC驱动
    • Connection接口:连接对象,主要作用:与数据库连接
    • Statement接口:SQL编译器,主要作用:向数据库发送SQL语句,返回执行结果
    • ResultSet接口:结果集对象,主要作用:执行查询操作,接收结果

JDBC入门

  1. 下载驱动 https://dev.mysql.com/downloads/connector/j/

  2. 创建Java项目,将jar文件复制到lib目录中

  3. Java代码实现功能

    import java.sql.*;
    /**
     * 
     * @author Administrator
     *JDBC详解
     */
    public class JdbcDetailDemo {
    	public static void main(String[] args) {
    		Connection conn = null;
    		Statement stmt = null;
    		ResultSet rs = null;
    		try {
    			//1、加载驱动
    			Class.forName("com.mysql.cj.jdbc.Driver");
    			//2、创建连接
    			String url = "jdbc:mysql://localhost:3306/offcnoa?"
    					+ "serverTimezone=GMT%2B8&characterEncoding=utf-8";
    			String user = "root";
    			String pwd = "111";
    			conn = DriverManager.getConnection(url, user, pwd);
    			//创建SQL编译器
    			stmt = conn.createStatement();
    			//创建SQL语句
    			String sql = "select * from emp";
    			//执行SQL语句并返回结果
    			rs = stmt.executeQuery(sql);
    			//解析结果集
    			while(rs.next()) {
    				//方式一:根据列名及列的数据类型来获取,使用getXxx(),Xxx代表数据类型
    				int empno1 = rs.getInt("empno");
    				String ename1 = rs.getString("ename");
    				double sal1 = rs.getDouble("sal");
    				System.out.println(empno1+":"+ename1+":"+sal1);
    				//方式二:根据列的序号及其数据类型来获取,使用getXxx(),Xxx代表数据类型
    				int empno2 = rs.getInt(1);
    				String ename2 = rs.getString(2);
    				double sal2 = rs.getDouble(6);
    				System.out.println(empno2+":"+ename2+":"+sal2);
    			}
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		} finally {
    			//释放资源 (记得释放资源,如果不释放,会导致项目运行越来越慢,最后崩溃。)
    			try {
    				if(rs != null) {
    					rs.close();
    				}
    				if(stmt != null) {
    					stmt.close();
    				}
    				if(conn != null) {
    					conn.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    url值的含义:

    • jdbc:mysql::使用jdbc连接MySQL数据库
      localhost::连接的数据库的IP地址,本地可以直接写localhost或者127.0.0.1;远程就要写对方的IP地址
      3306:数据库的端口号
      如果,连接的是本地数据库且端口号为3306,那么这部分内容可以省略:jdbc:mysql:///offcnoa?serverTimezone=GMT%2B8&characterEncoding=utf-8
      offcnoa:要连接的数据库名
      ?后面是设置的参数,如果有多个,就用&隔开
      	serverTimezone=GMT%2B8:设置时区;注意8.*的版本必须设置,以前的不需要。
      characterEncoding=utf-8:设置编码集
      user:数据库账号
      pwd:数据库密码(写自己的)
      DriverManager.getConnection(url, user, pwd);连接数据库
      

JDBC CRUD

Java 使用JDBC对数据库进行增删改查

/**
 * 
 * @author Administrator
 *JDBC的CRUD
 */

import java.sql.*;

import org.junit.jupiter.api.Test;

public class JdbcCrudDemo {
	@Test
	public void insert() {
		Connection conn = null;
		Statement stmt = null;
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/db_1113?" 
			+ "serverTimezone=GMT%2B8&characterEncoding=utf-8";
			String user = "root";
			String pwd = "111";
			conn = DriverManager.getConnection(url, user, pwd);
			stmt = conn.createStatement();
			String sql = "insert into class(cname) values('物理班')";
			int rows = stmt.executeUpdate(sql);
			System.out.println(rows);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (stmt != null) {
					stmt.close();
				}
				if (conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	@Test
	public void delete() {
		Connection conn = null;
		Statement stmt = null;
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/db_1113?" 
			+ "serverTimezone=GMT%2B8&characterEncoding=utf-8";
			String user = "root";
			String pwd = "111";
			conn = DriverManager.getConnection(url, user, pwd);
			stmt = conn.createStatement();
			String sql = "delete from class where cid=5";
			int rows = stmt.executeUpdate(sql);
			System.out.println(rows);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (stmt != null) {
					stmt.close();
				}
				if (conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	@Test
	public void update() {
		Connection conn = null;
		Statement stmt = null;
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/db_1113?" 
			+ "serverTimezone=GMT%2B8&characterEncoding=utf-8";
			String user = "root";
			String pwd = "111";
			conn = DriverManager.getConnection(url, user, pwd);
			stmt = conn.createStatement();
			String sql = "update class set cname='化学班'  where cid=4";
			int rows = stmt.executeUpdate(sql);
			System.out.println(rows);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (stmt != null) {
					stmt.close();
				}
				if (conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	@Test
	public void select() {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			String url = "jdbc:mysql://localhost:3306/db_1113?" 
			+ "serverTimezone=GMT%2B8&characterEncoding=utf-8";
			String user = "root";
			String pwd = "111";
			conn = DriverManager.getConnection(url, user, pwd);
			stmt = conn.createStatement();
			String sql = "select * from class where cid=3";
			rs = stmt.executeQuery(sql);
			while(rs.next()) {
				System.out.println(rs.getInt("cid")+","+rs.getString("cname"));
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null) {
					rs.close();
				}
				if (stmt != null) {
					stmt.close();
				}
				if (conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

SQL注入问题

  • SQL注入攻击:传入的参数是直接拼接到SQL语句中的。

  • 拼入 条件1 or true 能通过数据库

  • 使用PreparedStatement来替换Statement。

PreparedStatement CRUD

  • PreparedStatement 增删改查

    /**
     * 
     * @author Administrator
     *PreparedStatement的CRUD
     */
    import java.sql.*;
    import org.junit.jupiter.api.Test;
    public class PstmtCrudDemo {
    	public void insert(String sname,int cid,int age) {
    		Connection conn = null;
    		PreparedStatement pstmt = null;
    		try {
    			Class.forName("com.mysql.cj.jdbc.Driver");
    			String url = "jdbc:mysql://localhost:3306/db_1113?serverTimezone=GMT%2B8&characterEncoding=utf-8";
    			String user = "root";
    			String pwd = "111";
    			conn = DriverManager.getConnection(url, user, pwd);
    			String sql = "insert into student(sname,cid,age) values(?,?,?)";
    			pstmt = conn.prepareStatement(sql);
    			pstmt.setString(1, sname);
    			pstmt.setInt(2, cid);
    			pstmt.setInt(3, age);
    			int rows = pstmt.executeUpdate();
    			System.out.println(rows);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if(pstmt != null) {
    					pstmt.close();
    				}
    				if(conn != null) {
    					conn.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    	public void delete(int sid) {
    		Connection conn = null;
    		PreparedStatement pstmt = null;
    		try {
    			Class.forName("com.mysql.cj.jdbc.Driver");
    			String url = "jdbc:mysql://localhost:3306/db_1113?serverTimezone=GMT%2B8&characterEncoding=utf-8";
    			String user = "root";
    			String pwd = "111";
    			conn = DriverManager.getConnection(url, user, pwd);
    			String sql = "delete from student where sid=?";
    			pstmt = conn.prepareStatement(sql);
    			pstmt.setInt(1, sid);
    			int rows = pstmt.executeUpdate();
    			System.out.println(rows);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if(pstmt != null) {
    					pstmt.close();
    				}
    				if(conn != null) {
    					conn.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    	public void update(int sid,String sname,int cid,int age) {
    		Connection conn = null;
    		PreparedStatement pstmt = null;
    		try {
    			Class.forName("com.mysql.cj.jdbc.Driver");
    			String url = "jdbc:mysql://localhost:3306/db_1113?serverTimezone=GMT%2B8&characterEncoding=utf-8";
    			String user = "root";
    			String pwd = "111";
    			conn = DriverManager.getConnection(url, user, pwd);
    			String sql = "update student set sname=?,cid=?,age=? where sid=?";
    			pstmt = conn.prepareStatement(sql);
    			pstmt.setString(1, sname);
    			pstmt.setInt(2, cid);
    			pstmt.setInt(3, age);
    			pstmt.setInt(4, sid);
    			int rows = pstmt.executeUpdate();
    			System.out.println(rows);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if(pstmt != null) {
    					pstmt.close();
    				}
    				if(conn != null) {
    					conn.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    	public void select(int cid) {
    		Connection conn = null;
    		PreparedStatement pstmt = null;
    		ResultSet rs = null;
    		try {
    			Class.forName("com.mysql.cj.jdbc.Driver");
    			String url = "jdbc:mysql://localhost:3306/db_1113?serverTimezone=GMT%2B8&characterEncoding=utf-8";
    			String user = "root";
    			String pwd = "111";
    			conn = DriverManager.getConnection(url, user, pwd);
    			String sql = "select * from student where cid=?";
    			pstmt = conn.prepareStatement(sql);
    			pstmt.setInt(1, cid);
    			rs = pstmt.executeQuery();
    			while(rs.next()) {
    				System.out.println(rs.getString("sname"));
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if(rs != null) {
    					rs.close();
    				}
    				if(pstmt != null) {
    					pstmt.close();
    				}
    				if(conn != null) {
    					conn.close();
    				}
    			} catch (SQLException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	@Test
    	public void t01() {
    		/*
    		 * String sname = "李现"; int cid = 1; int age = 20; insert(sname, cid, age);
    		 */
    		/*
    		 * int sid = 7; delete(sid);
    		 */
    		/*
    		 * String sname = "李现"; int cid = 1; int age = 20; int sid = 3; update(sid,
    		 * sname, cid, age);
    		 */
    		int cid = 1;
    		select(cid);
    	}
    }
    

JDBC的事务操作

  • 事务的操作:

    1. 开启事务(设置事务为手动模式):

      • conn.setAutoCommit(false);
    2. 如果成功则提交:

      • conn.commit();
    3. 如果失败则回滚:

      • conn.rollback();
  • 代码实现:

    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import org.junit.jupiter.api.Test;
    public class TransactionDemo {
    	@Test
    	public void giveMoney() {
    		Connection conn = JdbcUtil.getConn();
    		PreparedStatement pstmt = null;
    		String sql1 = "UPDATE account SET money=money+3000 WHERE aid=2";
    		String sql2 = "UPDATE account SET money=money-3000 WHERE aid=1";
    		try {
    			//在所有SQL语句运行之前,开启事务
    			conn.setAutoCommit(false);
    			pstmt = conn.prepareStatement(sql1);
    			int rows1 = pstmt.executeUpdate();
    			System.out.println("李四收钱:"+rows1);
    
    			pstmt = conn.prepareStatement(sql2);
    			int rows2 = pstmt.executeUpdate();
    			System.out.println("张三转钱:"+rows2);
    			
    			//能够正常运行到这一行,代表成功,提交
    			System.out.println("转账成功");
    			conn.commit();
    		} catch (SQLException e) {
    			//运行到这里,代表失败,回滚
    			System.out.println("失败了,开始回滚");
    			try {
    				conn.rollback();
    			} catch (SQLException e1) {
    				e1.printStackTrace();
    			}
    			System.out.println("回滚结束");
    			e.printStackTrace();
    		} finally {
    			JdbcUtil.closeResources(null, pstmt, conn);
    		}
    	}
    }
    

连接池

  • 实现连接的循环利用

  • 连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。

  • 连接池的优势:

    1. 程序启动时,就在池子里面放入一定数量的连接,不需要用户发出请求的时候创建,减少了服务器的压力。

    2. 用户要操作数据库的时候,直接从池子里面拿一个空闲链接使用即可,用完以后再还回来供下一个用户使用,实现了连接的循环利用。

    3. 用户获取连接的时候,池子里面的连接都被其他用户拿走了。如果池子容量未达上限,那么就创建一批新的连接放进去。如果池子容量到达上限,用户就必须等待其他用户还回来再使用。

    4. 如果池子中有长期处于空闲状态的连接,关闭一批空闲连接,优化系统性能。

  • 实现步骤:

    1. 创建一个连接池类,在类中创建池子(集合)
    2. 在池子中放入一定数量的连接
    3. 创建获取连接的方法,用户调用时,就可以从池子中拿一个连接
    4. 创建归还连接的方法,用户调用时,就可以将连接还回池子
  • 代码展示

    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    public class JdbcPoolDemo {
    	//	1、创建一个连接池类,在类中创建池子(集合)
    	private static List<Connection> pool = new ArrayList<Connection>();
    	
    	//	2、在池子中放入一定数量的连接
    	static {
    		for(int i=0;i<5;i++) {
    			Connection conn = JdbcUtil.getConn();
    			pool.add(conn);
    			System.out.println(conn+"连接被放入池子中了,当前池子中有"+pool.size()+"个连接");
    		}
    	}
    	
    	//	3、创建获取连接的方法,用户调用时,就可以从池子中拿一个连接
    	public static Connection getConnByJdbcPool() {
    		Connection conn = pool.remove(0);
    		System.out.println(conn+"被拿去用了,当前池子中有"+pool.size()+"个连接");
    		return conn;
    	}
    	
    	//	4、创建归还连接的方法,用户调用时,就可以将连接还回池子
    	public static void returnConn(ResultSet rs,PreparedStatement pstmt,Connection conn) {
    		try {
    			if(rs != null) {
    				rs.close();
    			}
    			if(pstmt != null) {
    				pstmt.close();
    			}
    			if(conn != null) {
    				//还回来
    				pool.add(conn);
    				System.out.println(conn+"被还回来了,当前池子中有"+pool.size()+"个连接");
    			}
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

DBCP连接池

  • 步骤:

    1. 将jar包导入到项目中

      1. commons-dbcp-1.4.jar
      2. commons-pool-1.5.6.jar
    2. 创建配置文件(配置文件必须放在src下,等号前面的key不能改)

      • dbcp.properties

      • driverClassName=com.mysql.cj.jdbc.Driver
        url=jdbc:mysql://localhost:3306/db_1026?serverTimezone=GMT%2B8&characterEncoding=UTF-8
        username=root
        password=111
        initialSize=10
        maxActive=30
        
    3. 代码实现

      import java.io.FileInputStream;
      import java.io.InputStream;
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.util.Properties;
      import javax.sql.DataSource;
      import org.apache.commons.dbcp.BasicDataSourceFactory;
      
      public class DbcpPoolDemo {
      	//1、初始化连接池(数据源)
      	private static DataSource ds = null;
      	static {
      		try {
      			InputStream in = new FileInputStream("src/dbcp.properties");
      			Properties prop = new Properties();
      			prop.load(in);
      			ds = BasicDataSourceFactory.createDataSource(prop);
      		} catch (Exception e) {
      			e.printStackTrace();
      		}
      	}
      	
      	//2、创建获取连接的方法,用户调用时,就可以从池子中拿一个连接
      	public static Connection getConnByDbcpPool() {
      		Connection conn = null;
      		try {
      			conn = ds.getConnection();
      		} catch (SQLException e) {
      			e.printStackTrace();
      		}
      		return conn;
      	}
      	
      	//3、创建归还连接的方法,用户调用时,就可以将连接还回池子
      	public static void returnConn(ResultSet rs,PreparedStatement pstmt,Connection conn) {
      		try {
      			if(rs != null) {
      				rs.close();
      			}
      			if(pstmt != null) {
      				pstmt.close();
      			}
      			if(conn != null) {
      				//close()的不同实现,这里是归还而非释放
      				conn.close();
      			}
      		} catch (SQLException e) {
      			e.printStackTrace();
      		}
      	}
      }
      

C3P0连接池

  • 步骤:

    1. 导入jar包

      1. c3p0-0.9.2.1.jar
      2. mchange-commons-java-0.2.3.4.jar
    2. 创建配置文件(放在src目录下,等号前面的key不能变,文件名也不能变)

      • c3p0配置参数:https://blog.csdn.net/zhanghanlun/article/details/80918422

      • c3p0.properties

      • c3p0.driverClass=com.mysql.cj.jdbc.Driver
        c3p0.jdbcUrl=jdbc:mysql://localhost:3306/db1?serverTimezone=GMT%2B8&characterEncoding=UTF-8
        c3p0.user=root
        c3p0.password=root
        c3p0.acquireIncrement=3
        c3p0.initialPoolSize=10
        c3p0.maxIdleTime=60
        c3p0.maxPoolSize=150
        c3p0.minPoolSize=5
        
    3. 代码实现

      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import com.mchange.v2.c3p0.ComboPooledDataSource;
      public class C3p0PoolDemo {
      	// 初始化连接池,调用ComboPooledDataSource的构造方法,内部自动读取指定路径下的配置文件,并根据读取到的内容,生成数据源
      	private static ComboPooledDataSource ds = new ComboPooledDataSource();
      
      	// 创建获取连接的方法,用户调用时,就可以从池子中拿一个连接
      	public static Connection getConnByC3p0Pool() {
      		Connection conn = null;
      		try {
      			conn = ds.getConnection();
      		} catch (SQLException e) {
      			e.printStackTrace();
      		}
      		return conn;
      	}
      
      	// 创建归还连接的方法,用户调用时,就可以将连接还回池子
      	public static void returnConn(ResultSet rs, PreparedStatement pstmt, Connection conn) {
      		try {
      			if (rs != null) {
      				rs.close();
      			}
      			if (pstmt != null) {
      				pstmt.close();
      			}
      			if (conn != null) {
      				// close()的不同实现,这里是归还而非释放
      				conn.close();
      			}
      		} catch (SQLException e) {
      			e.printStackTrace();
      		}
      	}
      }
      

JavaBean

  • 为了将查询到的数据持久化

    • 通常放到entity包中
  • JavaBean 是特殊的 Java 类,使用 Java 语言书写,并且遵守 JavaBean API 规范。

    接下来给出的是 JavaBean 与其它 Java 类相比而言独一无二的特征:

    • 提供一个默认的无参构造函数。
    • 需要被序列化并且实现了 Serializable 接口。
    • 可能有一系列可读写属性。
    • 可能有一系列的 getter 或 setter 方法。

DBUtils

DBUtils工具简介

  • Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。尤其结合连接池使用效果更为理想。

  • Commons DbUtils的核心是两个类一个接口:

    1. DBUtils类:主要为关闭连接,装载JDBC驱动程序之类的常规工作提供方法,都是静态的方法。
    2. QueryRunner类:为我们提供两个重要方法,调用方法之前需要先创建一个QueryRunner的对象。
      • QueryRunner qRunner=new QueryRunner(new ComboPooledDataSource());
      • 创建对象时需要传入一个连接池的数据源,这里结合c3p0连接池来完成。
      • qRunner.update():支持DML操作
      • qRunner.query():支持DQL操作
      • 两个方法都有多个重载,可以根据需求选择不同的重载方法。
    3. ResultSetHandler接口:用于处理ResultSet结果集,将结果集的的数据转换成不同形式。该接口的实现类有很多:
    实现类名简介
    ArrayHandler将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值。
    ArrayListHandler将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。
    BeanHandler将结果集中第一条记录封装到一个指定的javaBean中。
    BeanListHandler将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中。
    ColumnListHandler将结果集中指定的列的字段值,封装到一个List集合中。
    ScalarHandler它是用于单列数据查询。例如:select count(*) from users 操作。
    MapHandler将结果集中第一条记录封装到Map集合中,Key代表列名, Value代表该列数据。
    MapListHandler将结果集中每一条记录封装到Map集合中,Key代表列名, Value代表该列数据,Map集合再存储到List集合

DBUtils的使用

  • 步骤:

    1. 导入jar包

      1. commons-dbutils-1.4.jar
    2. 代码实现

      1. 增删改操作

        //新增
        	public int insert(String aname,double money) {
        		int rows = 0;
        		//获取数据源
        		ComboPooledDataSource ds = new ComboPooledDataSource();
        		//初始化QueryRunner
        		QueryRunner qr = new QueryRunner(ds);
        		String sql = "insert into account(aname,money) values(?,?)";
        		//执行SQL语句并返回结果
        		try {
        			rows = qr.update(sql, aname, money);
        		} catch (SQLException e) {
        			e.printStackTrace();
        		}
        		return rows;
        	}
        	
        	//删除
        	public int delete(int aid) {
        		int rows = 0;
        		ComboPooledDataSource ds = new ComboPooledDataSource();
        		QueryRunner qr = new QueryRunner(ds);
        		String sql = "delete from account where aid=?";
        		try {
        			rows = qr.update(sql, aid);
        		} catch (SQLException e) {
        			e.printStackTrace();
        		}
        		return rows;
        	}
        	
        	//修改
        	public int update(int aid,String aname,double money) {
        		int rows = 0;
        		ComboPooledDataSource ds = new ComboPooledDataSource();
        		QueryRunner qr = new QueryRunner(ds);
        		String sql = "update account set aname=?,money=? where aid=?";
        		try {
        			rows = qr.update(sql, aname, money, aid);
        		} catch (SQLException e) {
        			e.printStackTrace();
        		}
        		return rows;
        	}
        
      2. 查询操作

        //查询所有
        	public List<Account> getAllAccount(){
        		List<Account> list = new ArrayList<Account>();
        		ComboPooledDataSource ds = new ComboPooledDataSource();
        		QueryRunner qr = new QueryRunner(ds);
        		String sql = "select * from account";
        		try {
        			//Account.class含义:将查询到的每一条数据都封装成对应的Account实例,然后再将这些实例放到集合中
        			//Account的属性必须和表当中的列的名字一模一样
        			list = qr.query(sql, new BeanListHandler<>(Account.class));
        		} catch (SQLException e) {
        			e.printStackTrace();
        		}
        		return list;
        	}
        	
        	//根据主键查询
        	public Account getAccountByAid(int aid){
        		Account account = null;
        		ComboPooledDataSource ds = new ComboPooledDataSource();
        		QueryRunner qr = new QueryRunner(ds);
        		String sql = "select * from account where aid=?";
        		try {
        			account = qr.query(sql, new BeanHandler<>(Account.class), aid);
        		} catch (SQLException e) {
        			e.printStackTrace();
        		}
        		return account;
        	}
        	
        	//查询表的数据行数
        	public int getCountRows() {
        		int countRows = 0;
        		ComboPooledDataSource ds = new ComboPooledDataSource();
        		QueryRunner qr = new QueryRunner(ds);
        		String sql = "select count(*) from account";
        		try {
        			countRows = (int)(long)qr.query(sql, new ScalarHandler());
        		} catch (SQLException e) {
        			e.printStackTrace();
        		}
        		return countRows;
        	}
        

Web Server

软件架构(C/S,B/S)

  1. C/S架构

    • C/S架构即Client/Server(客户机/服务器)结构。
    • C/S结构在技术上很成熟,它的主要特点是交互性强、具有安全的存取模式、网络通信量低、响应速度快、利于处理大量数据。但是该结构的程序是针对性开发,变更不够灵活,维护和管理的难度较大。通常只局限于小型局域网,不利于扩展。并且,由于该结构的每台客户机都需要安装相应的客户端程序,分布功能弱且兼容性差,不能实现快速部署安装和配置,因此缺少通用性,具有较大的局限性。
  2. B/S架构

    • B/S即Browser/Server(浏览器/服务器)结构。
    • B/S结构应用程序相对于传统的C/S结构应用程序是一个非常大的进步。 B/S结构的主要特点是分布性强、维护方便、开发简单且共享性强、总体拥有成本低。但数据安全性问题、对服务器要求过高、数据传输速度慢、软件的个性化特点明显降低,这些缺点是有目共睹的,难以实现传统模式下的特殊功能需求。
  3. C/S与B/S对比

    对象硬件环境客户端要求软件安装升级维护安全性
    C/S用户群体固定,一般用于小型局域网范围,要求拥有相同的操作系统。客户端计算机配置要求较高。每一个客户端都必须安装和配置软件。每一个客户机都要升级程序。可以采用自动升级。安全性好
    B/S要有操作系统和浏览器,与操作系统平台无关。客户端计算机配置要求较低。可以随时随地进行操作而不用安装任何专门的软件,只要有浏览器即可。客户机不必安装及维护,要需要对服务器进行统一升级维护。相比C/S架构安全性弱
    • 一般面向相对固定的用户群,程序更加注重流程,可以对权限进行多层次校验,提供更安全的存取模式,对信息安全的控制能力很强,高度机密的信息系统采用C/S结构适宜。
    • 一般对用户群体没有特殊要求,客户端基本做到零维护,只需要通过浏览器就可以随时随地进行业务处理,并且方便功能扩展,开发简单,共享性强,对安全性没有更好的要求时采用B/S结构更合适。

Web简介

  • web(World Wide Web)即全球广域网,也称为万维网,它是一种基于超文本和HTTP的、全球性的、动态交互的、跨平台的分布式图形信息系统。是建立在Internet上的一种网络服务,为浏览者在Internet上查找和浏览信息提供了图形化的、易于访问的直观界面,其中的文档及超级链接将Internet上的信息节点组织成一个互为关联的网状结构。
  • Web服务器:Tomcat,JBoss……

Tomcat

Tomcat服务器简介

  • Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
  • Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
  • 诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。目前Tomcat最新版本为9.0.41。

Tomcat的使用步骤

  1. 下载 Tomcat
    • http://tomcat.apache.org/
    • apache-tomcat-9.0.38-windows-x64.zip
    • 解压 Tomcat 文件
  2. Tomcat 的启动与关闭
    • 启动:
      • 双击打开bin文件夹下的startup.bat
      • 打开浏览器访问默认地址 http://localhost:8080 或者 http://127.0.0.1:8080
      • 默认端口号为8080,可以用记事本打开conf文件夹下的server.xml中找到8080并修改端口号
      • 如果端口号修改为80,浏览器访问时端口号可以省略,即http://localhost或者 http://127.0.0.1
    • 关闭:
      • 方法一:直接关闭控制台
      • 方法二:在控制台内按ctrl+c
  3. Tomcat 在Eclipse 与 IDEA中的集成配置
    • https://blog.csdn.net/shihao1998/article/details/104427629/

Servlet

Servlet简介

  • Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

  • 使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

  • Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

    • 性能明显更好。
    • Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
    • Servlet 是独立于平台的,因为它们是用 Java 编写的。
    • 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
    • Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。
Servlet 架构

下图显示了 Servlet 在 Web 应用程序中的位置。

Servlet 架构

Servlet 任务
  • Servlet 执行以下主要任务:
    • 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
    • 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
    • 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
    • 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
    • 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。
Servlet 包
  • Java Servlet 是运行在带有支持 Java Servlet 规范的解释器的 web 服务器上的 Java 类。

  • Servlet 可以使用 javax.servletjavax.servlet.http 包创建,它是 Java 企业版的标准组成部分,Java 企业版是支持大型开发项目的 Java 类库的扩展版本。

  • 这些类实现 Java Servlet 和 JSP 规范。在写本教程的时候,二者相应的版本分别是 Java Servlet 2.5 和 JSP 2.1。

  • Java Servlet 就像任何其他的 Java 类一样已经被创建和编译。在您安装 Servlet 包并把它们添加到您的计算机上的 Classpath 类路径中之后,您就可以通过 JDK 的 Java 编译器或任何其他编译器来编译 Servlet。

Servlet 生命周期

  • Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:(初始化,服务,销毁)
    • Servlet 初始化后调用 init () 方法。
    • Servlet 调用 service() 方法来处理客户端的请求。
    • Servlet 销毁前调用 destroy() 方法。
    • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

生命周期的方法:

init() 方法
  • init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。

  • Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。

  • 当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。

  • init 方法的定义如下:

    • public void init() throws ServletException {
        // 初始化代码...
      }
      
service() 方法
  • service() 方法在生命周期中会提供n次服务

  • service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。

  • 每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

  • 下面是该方法的特征:

    • public void service(ServletRequest request, 
                          ServletResponse response) 
            throws ServletException, IOException{
      }
      
  • service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重写 doGet() 或 doPost() 即可。

doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征。

doGet() 方法
  • GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。

    • public void doGet(HttpServletRequest request,
                        HttpServletResponse response)
          throws ServletException, IOException {
          // Servlet 代码
      }
      
doPost() 方法
  • POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。

    • public void doPost(HttpServletRequest request,
                         HttpServletResponse response)
          throws ServletException, IOException {
          // Servlet 代码
      }
      
destroy() 方法
  • destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。

  • 在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。destroy 方法定义如下所示:

    • public void destroy() {
      // 终止化代码...
      }
      

Servlet的生命周期,并说出Servlet和CGI的区别?

  • servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。

  • 这个生存期由javax.servlet.servlet接口中的init、service、destroy方法表达。

  • web容器加载servlet,生命周期开始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法实现根据请求的不同调用不同的do**()方法。结束服务,web容器调用servlet的destroy()方法。

    img

  • 区别:

    • Servlet处于服务器进程中,它通过多线程运行service()方法,一个实例可以服务于多个请求,并且实例一般不会被销毁;而CGI对每个请求都产生一个新的进程,服务完成后就销毁,所有效率低于Servlet

Servlet快速入门

  • 表单数据示例代码:
    • https://www.runoob.com/servlet/servlet-form-data.html

Servlet的体系结构与Tomcat的关系

  1. Servlet与Tomcat之间的关系

    • Tomcat在启动的时候,会自动读取web.xml配置文件,根据这个文件当中的相关信息,初始化Servlet,生成ServletConfig和ServletContext。同时会创建ServletRequest和ServletResponse交给Servlet,这样一来,service方法就拥有了这两个参数。
  2. Servlet的体系结构

    技术分享图片

    • 总结:基于HTTP协议的web项目,Servlet直接继承HttpServlet就可以了。

        1. 当form表单的method属性值为get,调用doGet()
        1. 当form表单的method属性值为post,调用doPost()
      • 总结:请求达到的时候,自动调用的是继承的Service方法,在这个方法中,获取了当前的请求方式,然后根据这个方式调用对应的doXxx方法,而这些doXxx方法自己又重写了,所以最终运行的是自己写的doXxx方法。
    • 什么时候调用doGet:

      1. form表单的method未给值

      2. form表单的method值为get

      3. <a>标签请求Servlet

      4. 直接通过路径访问Servlet

    • 什么时候调用doPost:

      • form表单的method值为post
    • get和post的区别

      1. get方式会将提交的数据直接显示到地址栏,post不会

      2. get方式提交的数量较小,post没有限制

      3. get方式提交的数据会被浏览器缓存下来,post不会

      • 总而言之,数据量较小且不敏感就可以用get,反之用post

url-pattern

  • <servlet-mapping>的字标签,用于给Servlet配置访问路径

    • 注意点:

      1. 最前面必须有/,代表当前项目的根目录

      2. 路径中可以出现文件夹,比如/user/text/url……

    • 项目的文件路径问题:

    • 访问HTML文件,只需要关注自己创建的内容,不用管自动生成的内容。

    • 访问Servlet时,照着url-pattern设置的内容即可

    • HTML文件中,要访问Servlet,name就需要注意HTML的路径与Servlet路径之间的相对关系。

HttpServletResponse接口

  • 服务器响应对象,父接口:ServletResponse

响应行

  • 包含内容:协议及其版本,状态码
    • 示例http/1.1 200
HTTP协议
  • 超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使开发和部署非常地直截了当。

  • 工作原理

    HTTP是基于客户/服务器模式,且面向连接的。典型的HTTP事务处理有如下的过程:

    (1)客户与服务器建立连接;

    (2)客户向服务器提出请求;

    (3)服务器接受请求,并根据请求返回相应的文件作为应答;

    (4)客户与服务器关闭连接。

  • 客户端与服务器之间的通信是非常短暂的,一次通信只能解决一个请求。

  • HTTP协议是一种无状态协议:不具备记忆效果。

  • 创建连接需要三次握手:

    1. 客户端问服务器,我们可以连接吗
    2. 服务器回应,可以
    3. 客户端连接服务器
HTTP1.0/1.1版本的区别
  • 1.0:客户端请求服务器上的一个文件,发现文件上有图片,先将文件拿走,再发送请求拿图片。
  • 1.1:客户端请求服务器上的一个文件,发现文件上有图片,将文件和图片打包拿走。
状态码
  • HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:

    分类分类描述
    1**信息,服务器收到请求,需要请求者继续执行操作
    2**成功,操作被成功接收并处理
    3**重定向,需要进一步的操作以完成请求
    4**客户端错误,请求包含语法错误或无法完成请求
    5**服务器错误,服务器在处理请求的过程中发生了错误
  • 常见状态码:

    200 OK                        //客户端请求成功
    400 Bad Request               //客户端请求有语法错误,不能被服务器所理解
    401 Unauthorized              //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 
    403 Forbidden                 //服务器收到请求,但是拒绝提供服务
    404 Not Found                 //请求资源不存在,eg:输入了错误的URL
    500 Internal Server Error     //服务器发生不可预期的错误(代码有问题,95%都是空指针异常)
    503 Server Unavailable        //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
    
  • 更多状态码http://www.runoob.com/http/http-status-codes.html

  • 可以手动设置状态码:response.setStatus(404);

  • 设置状态码的同时,还可以设置提示信息: response.setError(404,'提示内容')

响应头

下表总结了从 Web 服务器端返回到浏览器的最有用的 HTTP 1.1 响应报头,您会在 Web 编程中频繁地使用它们:

头信息描述
Allow这个头信息指定服务器支持的请求方法(GET、POST 等)。
Cache-Control这个头信息指定响应文档在何种情况下可以安全地缓存。可能的值有:public、privateno-cache 等。Public 意味着文档是可缓存,Private 意味着文档是单个用户私用文档,且只能存储在私有(非共享)缓存中,no-cache 意味着文档不应被缓存。
Connection这个头信息指示浏览器是否使用持久 HTTP 连接。值 close 指示浏览器不使用持久 HTTP 连接,值 keep-alive 意味着使用持久连接。
Content-Disposition这个头信息可以让您请求浏览器要求用户以给定名称的文件把响应保存到磁盘。
Content-Encoding在传输过程中,这个头信息指定页面的编码方式。
Content-Language这个头信息表示文档编写所使用的语言。例如,en、en-us、ru 等。
Content-Length这个头信息指示响应中的字节数。只有当浏览器使用持久(keep-alive)HTTP 连接时才需要这些信息。
Content-Type这个头信息提供了响应文档的 MIME(Multipurpose Internet Mail Extension)类型。
Expires这个头信息指定内容过期的时间,在这之后内容不再被缓存。
Last-Modified这个头信息指示文档的最后修改时间。然后,客户端可以缓存文件,并在以后的请求中通过 If-Modified-Since 请求头信息提供一个日期。
Location这个头信息应被包含在所有的带有状态码的响应中。在 300s 内,这会通知浏览器文档的地址。浏览器会自动重新连接到这个位置,并获取新的文档。
Refresh这个头信息指定浏览器应该如何尽快请求更新的页面。您可以指定页面刷新的秒数。
Retry-After这个头信息可以与 503(Service Unavailable 服务不可用)响应配合使用,这会告诉客户端多久就可以重复它的请求。
Set-Cookie这个头信息指定一个与页面关联的 cookie。
设置 HTTP 响应报头的方法

下面的方法可用于在 Servlet 程序中设置 HTTP 响应报头。这些方法通过 HttpServletResponse 对象可用。

序号方法描述
1String encodeRedirectURL(String url)为 sendRedirect 方法中使用的指定的 URL 进行编码,或者如果编码不是必需的,则返回 URL 未改变。
2String encodeURL(String url)对包含 session 会话 ID 的指定 URL 进行编码,或者如果编码不是必需的,则返回 URL 未改变。
3boolean containsHeader(String name)返回一个布尔值,指示是否已经设置已命名的响应报头。
4boolean isCommitted()返回一个布尔值,指示响应是否已经提交。
5void addCookie(Cookie cookie)把指定的 cookie 添加到响应。
6void addDateHeader(String name, long date)添加一个带有给定的名称和日期值的响应报头。
7void addHeader(String name, String value)添加一个带有给定的名称和值的响应报头。
8void addIntHeader(String name, int value)添加一个带有给定的名称和整数值的响应报头。
9void flushBuffer()强制任何在缓冲区中的内容被写入到客户端。
10void reset()清除缓冲区中存在的任何数据,包括状态码和头。
11void resetBuffer()清除响应中基础缓冲区的内容,不清除状态码和头。
12void sendError(int sc)使用指定的状态码发送错误响应到客户端,并清除缓冲区。
13void sendError(int sc, String msg)使用指定的状态发送错误响应到客户端。
14void sendRedirect(String location)使用指定的重定向位置 URL 发送临时重定向响应到客户端。
15void setBufferSize(int size)为响应主体设置首选的缓冲区大小。
16void setCharacterEncoding(String charset)设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。
17void setContentLength(int len)设置在 HTTP Servlet 响应中的内容主体的长度,该方法设置 HTTP Content-Length 头。
18void setContentType(String type)如果响应还未被提交,设置被发送到客户端的响应的内容类型。
19void setDateHeader(String name, long date)设置一个带有给定的名称和日期值的响应报头。
20void setHeader(String name, String value)设置一个带有给定的名称和值的响应报头。
21void setIntHeader(String name, int value)设置一个带有给定的名称和整数值的响应报头。
22void setLocale(Locale loc)如果响应还未被提交,设置响应的区域。
23void setStatus(int sc)为该响应设置状态码。

响应体

  • 响应给客户端的数据。

    • 响应数据需要通过输出流进行传递,response自带两个输出流:

      • ServletOutputStream out = response.getOutputStream();字节流

      • PrintWriter out = response.getWriter();字符流

    • 注意:这两个流不能同时使用。

HttpServletRequest接口

  • 请求对象,父接口:ServletRequest

请求行

  • 包含:请求方式,请求的资源,协议及其版本

请求头

当浏览器请求网页时,它会向 Web 服务器发送特定信息,这些信息不能被直接读取,因为这些信息是作为 HTTP 请求的头的一部分进行传输的。您可以查看 HTTP 协议 了解更多相关信息。

以下是来自于浏览器端的重要头信息,您可以在 Web 编程中频繁使用:

头信息描述
Accept这个头信息指定浏览器或其他客户端可以处理的 MIME 类型。值 image/pngimage/jpeg 是最常见的两种可能值。
Accept-Charset这个头信息指定浏览器可以用来显示信息的字符集。例如 ISO-8859-1。
Accept-Encoding这个头信息指定浏览器知道如何处理的编码类型。值 gzipcompress 是最常见的两种可能值。
Accept-Language这个头信息指定客户端的首选语言,在这种情况下,Servlet 会产生多种语言的结果。例如,en、en-us、ru 等。
Authorization这个头信息用于客户端在访问受密码保护的网页时识别自己的身份。
Connection这个头信息指示客户端是否可以处理持久 HTTP 连接。持久连接允许客户端或其他浏览器通过单个请求来检索多个文件。值 Keep-Alive 意味着使用了持续连接。
Content-Length这个头信息只适用于 POST 请求,并给出 POST 数据的大小(以字节为单位)。
Cookie这个头信息把之前发送到浏览器的 cookies 返回到服务器。
Host这个头信息指定原始的 URL 中的主机和端口。
If-Modified-Since这个头信息表示只有当页面在指定的日期后已更改时,客户端想要的页面。如果没有新的结果可以使用,服务器会发送一个 304 代码,表示 Not Modified 头信息。
If-Unmodified-Since这个头信息是 If-Modified-Since 的对立面,它指定只有当文档早于指定日期时,操作才会成功。
Referer这个头信息指示所指向的 Web 页的 URL。例如,如果您在网页 1,点击一个链接到网页 2,当浏览器请求网页 2 时,网页 1 的 URL 就会包含在 Referer 头信息中。
User-Agent这个头信息识别发出请求的浏览器或其他客户端,并可以向不同类型的浏览器返回不同的内容。
读取 HTTP 头的方法

下面的方法可用在 Servlet 程序中读取 HTTP 头。这些方法通过 HttpServletRequest 对象可用。

序号方法描述
1Cookie[] getCookies() e 对象。返回一个数组,包含客户端发送该请求的所有的 Cooki
2Enumeration getAttributeNames()返回一个枚举,包含提供给该请求可用的属性名称。
3Enumeration getHeaderNames()返回一个枚举,包含在该请求中包含的所有的头名。
4Enumeration getParameterNames()返回一个 String 对象的枚举,包含在该请求中包含的参数的名称。
5HttpSession getSession()返回与该请求关联的当前 session 会话,或者如果请求没有 session 会话,则创建一个。
6HttpSession getSession(boolean create)返回与该请求关联的当前 HttpSession,或者如果没有当前会话,且创建是真的,则返回一个新的 session 会话。
7Locale getLocale()基于 Accept-Language 头,返回客户端接受内容的首选的区域设置。
8Object getAttribute(String name)以对象形式返回已命名属性的值,如果没有给定名称的属性存在,则返回 null。
9ServletInputStream getInputStream()使用 ServletInputStream,以二进制数据形式检索请求的主体。
10String getAuthType()返回用于保护 Servlet 的身份验证方案的名称,例如,“BASIC” 或 “SSL”,如果JSP没有受到保护则返回 null。
11String getCharacterEncoding()返回请求主体中使用的字符编码的名称。
12String getContentType()返回请求主体的 MIME 类型,如果不知道类型则返回 null。
13String getContextPath()返回指示请求上下文的请求 URI 部分。
14String getHeader(String name)以字符串形式返回指定的请求头的值。
15String getMethod()返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。
16String getParameter(String name)以字符串形式返回请求参数的值,或者如果参数不存在则返回 null。
17String getPathInfo()当请求发出时,返回与客户端发送的 URL 相关的任何额外的路径信息。
18String getProtocol()返回请求协议的名称和版本。
19String getQueryString()返回包含在路径后的请求 URL 中的查询字符串。
20String getRemoteAddr()返回发送请求的客户端的互联网协议(IP)地址。
21String getRemoteHost()返回发送请求的客户端的完全限定名称。
22String getRemoteUser()如果用户已通过身份验证,则返回发出请求的登录用户,或者如果用户未通过身份验证,则返回 null。
23String getRequestURI()从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分。
24String getRequestedSessionId()返回由客户端指定的 session 会话 ID。
25String getServletPath()返回调用 JSP 的请求的 URL 的一部分。
26String[] getParameterValues(String name)返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null。
27boolean isSecure()返回一个布尔值,指示请求是否使用安全通道,如 HTTPS。
28int getContentLength()以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1。
29int getIntHeader(String name)返回指定的请求头的值为一个 int 值。
30int getServerPort()返回接收到这个请求的端口号。
31int getParameterMap()将参数封装成 Map 类型。

请求体

  • Servlet中获取请求携带的数据,常用方法:

    • request.getParameter(“name属性的值”);返回值类型是String

    • request.getParameterValues(“name属性的值”);返回值类型是String[]

  • 解决乱码问题

    • request.setCharacterEncoding("utf-8");
      response.setContentType("text/html;charset=utf-8");
      
  • 文件上传案例

    • 就是在指定的位置复制出一个跟源文件一模一样的文件。
      1. 表单的method的属性值必须是post,在表单上加入enctype="multipart/form-data"
      2. 在Servlet中加上@MultipartConfig
    • https://www.runoob.com/servlet/servlet-file-uploading.html

MVC 模式

三层架构

  1. 生活中的三层架构

mvc1

  • 优点:

    • 各司其职,互不干扰

    • 任意环节出现问题,找对应的负责人,与其他人无关

  • 缺点:

    • 人员变多,成本变高

2、软件中的三层架构

mvc2

mvc3

  • 优点:

    • 结构清晰,降低耦合度(解耦)
    • 可维护性高,可扩展性高
    • 有利于团队开发
    • 适应需求变化
  • 缺点:

    • 增加代码量
    • 降低系统性能
  • 什么是三层?

    • UI(表现层):主要是指用户交互的界面。用于接收用户输入的数据和显示处理后用户需要的数据。

    • BLL:(业务逻辑层):UI层和DAL层之间的桥梁。实现业务逻辑。业务逻辑具体包含:验证、计算、业务规则等等。

    • DAL:(数据访问层):与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交给业务层,同时将业务层处理的数据保存到数据库。(当然这些操作都是基于UI层的。用户的需求反映给界面(UI),UI反映给BLL,BLL反映给DAL,DAL进行数据的操作,操作后再一一返回,直到将用户所需数据反馈给用户)

MVC

MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。

  • Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
  • View(视图) - 视图代表模型包含的数据的可视化。
  • Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

img

实现

我们将创建一个作为模型的 Student 对象。StudentView 是一个把学生详细信息输出到控制台的视图类,StudentController 是负责存储数据到 Student 对象中的控制器类,并相应地更新视图 StudentView

MVCPatternDemo,我们的演示类使用 StudentController 来演示 MVC 模式的用法。

mvc-url

  • 使用MVC搭建项目结构
    • 页面(表示层):HTML或者JSP放在webcontent目录中,com.danny.servlet
    • 控制器(业务逻辑层):com.danny.service
    • 模型(数据访问层,持久层):com.danny.dao
    • 实体类:com.danny.entity
    • 工具类:com.danny.util

两者差异

  • https://www.cnblogs.com/yellowwenhao/p/11542367.html

servlet进阶

ServletConfig和ServletContext对象

  • 简介

    • ServletConfig对象就是Servlet的初始配置信息。初始信息在web.xml文件中配置。注意:ServletConfig独属于当前被配置的Servlet
    • 上下文对象,该对象属于当前项目,对当前项目中所有的Servlet公开。在web.xml文件中进行配置
  • 它们的作用和区别

    • 作用
      • 可以从web.xml中读取数据,给Servlet使用
      • 它们都能够给Servlet预置参数
    • 区别
      • config和Servlet是1对1的关系
      • context和Servlet是1对多的关系
      • Tomcat会保障它们和Servlet的关系

img

  • 具体代码及区别参考:
    • https://blog.csdn.net/wangqing84411433/article/details/71131608

作用域对象

  • 作用域对象可以用来存值并且在不同的组件中进行传递。但是,受它本身作用范围的约束,一旦超过这个范围,失效。
  • 两个作用域对象:
    • HttpServletRequest对象:作用域是一次请求范围内有效
    • ServletContext对象:作用域是当前整个项目, 这个项目中所有的Servlet都能在里面放数据取数据移除数据
  • 作用域常用方法:
    • setAttribute(“key”,”value”);向作用域中放值
    • getAttribute(“key”);根据key获取value
    • removeAttribute(“key”);根据key移除数据

请求转发与重定向

  • 路径跳转的方式

    • 请求转发:

      • request.getRequestDispatcher("URL").forward(request,response);
    • 重定向:

      • response.sendRedirect("URL");
  • 请求转发是服务器行为,客户端不知道整个操作过程中到底经过了多少次处理。所以地址栏中路径不会发生改变,整个过程中只有一次请求,所以request作用域对过程中所有的Servlet公开。

  • 重定向是客户端行为,客户端向ThirdServlet发送请求,ThirdServlet给了客户端响应告诉客户端去找FourthServlet,客户端再次对FourthServlet发送请求。所以地址栏会发生改变,request作用域不共享。

  • 请求转发与重定向的区别

    1. 发出的位置不同,请求转发是服务器行为,重定向是客户端行为

    2. 地址栏内容不同,请求转发地址栏不变,重定向地址栏要变

    3. 请求转发是一个请求,重定向不是一个请求

    4. 请求转发request作用域共享,重定向request作用域不共享

    5. 请求转发速度高于重定向

    6. 请求转发只能在当前项目中进行跳转,重定向不是

Servlet3.0注解

  • 注意:Servlet3.0及JDK1.5之后的版本。

  • 最简单的注解:@WebServlet("/Servlet名")

  • 同一个Servlet,要么使用注解配置,要么使用web.xml文件配置,但是不能同时用两种方式配置。

  • 属性列表:

    属性名类型描述
    nameStringservlet-name,如果没有显示指定,该Servlet的取值为全限定名
    valueString[]等价于 urlPatterns 属性,与该属性不能同时使用
    urlPatternsString[]指定Servlet url的匹配模式,等价于<url-parttern>
    loadOnStartupint指定Servlet的加载顺序
    initParamswebInitParam[]指定初始化参数
    asyncSupportedboolean是否支持异步操作
    descriptionString描述
    displayNameStringservlet显示名

XML

  • 什么是 XML?

    • XML 指可扩展标记语言(EXtensible Markup Language)。
    • XML 是一种很像HTML的标记语言。
    • XML 的设计宗旨是传输数据,而不是显示数据。
    • XML 标签没有被预定义。您需要自行定义标签。
    • XML 被设计为具有自我描述性。
    • XML 是 W3C 的推荐标准。
  • XML 和 HTML 之间的差异

    • XML 不是 HTML 的替代。

    • XML 和 HTML 为不同的目的而设计:

      • XML 被设计用来传输和存储数据,其焦点是数据的内容。
      • HTML 被设计用来显示数据,其焦点是数据的外观。
    • HTML 旨在显示信息,而 XML 旨在传输信息。

  • XML 不会做任何事情

    • 也许这有点难以理解,但是 XML 不会做任何事情。XML 被设计用来结构化、存储以及传输信息。
  • XML文件的格式要求

    1. 第一行必须是版本声明等信息
    2. 必须要有唯一的根标签
    3. 不区分大小写,推介使用小写
    4. 自定义标签名不能是关键字
    5. 标签之间必须正确的嵌套
    6. 标签名开头不能是数字
    7. 标签可以有属性,格式为属性名=”属性值”
  • XML文件的作用

    1. 配置文件
    2. 结构化的存储数据
    3. 数据交换(典型应用:AJAX)

dom4j解析XML文件

  • 步骤:

    1. 导入jar包

      • dom4j-1.6.1.jar
    2. 代码实现

      import java.util.List;
      
      import org.dom4j.Document;
      import org.dom4j.DocumentException;
      import org.dom4j.Element;
      import org.dom4j.io.SAXReader;
      import org.junit.jupiter.api.Test;
      
      public class Dom4jDemo {
      	@Test
      	public void readXml() {
      		//使用SAXReader读取文件,返回一个Document对象
      		SAXReader read = new SAXReader();
      		try {
      			Document document = read.read("src/first.xml");
      			//获取根标签
      			Element root = document.getRootElement();
      			//获取根标签的address属性的值
      			String address = root.attributeValue("address");
      			System.out.println(address);
      			//获取根标签的子标签
      			List<Element> list = root.elements();
      			for(Element e:list) {
      				//获取当前循环到的student标签的sname子标签的内容
      				String sname = e.element("sname").getText();
      				//获取当前循环到的student标签的ssex子标签的内容
      				String ssex = e.element("ssex").getText();
      				System.out.println(sname+","+ssex);
      			}
      		} catch (DocumentException e) {
      			e.printStackTrace();
      		}
      	}
      }
      

使用XPath读取XML文件

  • XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。

  • XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。

  • 因此,对 XPath 的理解是很多高级 XML 应用的基础。

  • 步骤

    1. 导入jar包

      1. dom4j-1.6.1.jar
      2. jaxen-1.1-beta-6.jar
    2. 代码实现

      import java.util.List;
      
      import org.dom4j.Document;
      import org.dom4j.DocumentException;
      import org.dom4j.Element;
      import org.dom4j.io.SAXReader;
      import org.junit.jupiter.api.Test;
      
      public class XpathDemo {
      	@Test
      	public void readXml() {
      		//使用SAXReader读取文件,返回Document对象
      		SAXReader read = new SAXReader();
      		try {
      			Document document = read.read("src/first.xml");
      			//获取所有的sname标签,并打印这些标签的内容  //sname
      			List<Element> list1 = document.selectNodes("//sname");
      			for(Element e:list1) {
      				System.out.println(e.getText());
      			}
      			System.out.println("---------------------------------");
      			//获取所有age属性值为18的student标签,并打印这些标签的sname子标签的内容  //student[@age=18]/sname
      			List<Element> list2 = document.selectNodes("//student[@age='18']/sname");
      			for(Element e:list2) {
      				System.out.println(e.getText());
      			}
      		} catch (DocumentException e) {
      			e.printStackTrace();
      		}
      	}
      }
      

JSP

JSP简介

  • JSP全称Java Server Pages,是一种动态网页开发技术。它使用JSP标签在HTML网页中插入Java代码。标签通常以<%开头以%>结束。
  • JSP是一种Java servlet,主要用于实现Java web应用程序的用户界面部分。网页开发者们通过结合HTML代码、XHTML代码、XML元素以及嵌入JSP操作和命令来编写JSP。
  • JSP通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页。
  • JSP标签有多种功能,比如访问数据库、记录用户选择信息、访问JavaBeans组件等,还可以在不同的网页中传递控制信息和共享信息。

为什么使用JSP?

  • JSP程序与CGI程序有着相似的功能,但和CGI程序相比,JSP程序有如下优势:

    • 性能更加优越,因为JSP可以直接在HTML网页中动态嵌入元素而不需要单独引用CGI文件。
    • 服务器调用的是已经编译好的JSP文件,而不像CGI/Perl那样必须先载入解释器和目标脚本。
    • JSP 基于Java Servlet API,因此,JSP拥有各种强大的企业级Java API,包括JDBC,JNDI,EJB,JAXP等等。
    • JSP页面可以与处理业务逻辑的 Servlet 一起使用,这种模式被Java servlet 模板引擎所支持。
  • 最后,JSP是Java EE不可或缺的一部分,是一个完整的企业级应用平台。这意味着JSP可以用最简单的方式来实现最复杂的应用。

JSP的优势

  • 以下列出了使用JSP带来的其他好处:

    • 与ASP相比:JSP有两大优势。首先,动态部分用Java编写,而不是VB或其他MS专用语言,所以更加强大与易用。第二点就是JSP易于移植到非MS平台上。

    • 与纯 Servlet 相比:JSP可以很方便的编写或者修改HTML网页而不用去面对大量的println语句。

    • 与SSI相比:SSI无法使用表单数据、无法进行数据库链接。

    • 与JavaScript相比:虽然JavaScript可以在客户端动态生成HTML,但是很难与服务器交互,因此不能提供复杂的服务,比如访问数据库和图像处理等等。

    • 与静态HTML相比:静态HTML不包含动态信息。

JSP 生命周期

  • 理解JSP底层功能的关键就是去理解它们所遵守的生命周期。

  • JSP生命周期就是从创建到销毁的整个过程,类似于servlet生命周期,区别在于JSP生命周期还包括将JSP文件编译成servlet。

  • 以下是JSP生命周期中所走过的几个阶段:

    • 编译阶段:
      • servlet容器编译servlet源文件,生成servlet类
    • 初始化阶段:
      • 加载与JSP对应的servlet类,创建其实例,并调用它的初始化方法
    • 执行阶段:
      • 调用与JSP对应的servlet实例的服务方法
    • 销毁阶段:
      • 调用与JSP对应的servlet实例的销毁方法,然后销毁servlet实例
  • 很明显,JSP生命周期的四个主要阶段和servlet生命周期非常相似,下面给出图示:

img

JSP文件的执行流程

  1. 翻译阶段: 将jsp页面翻译成一个.java源文件 (即Servlet)
  2. 编译阶段: 将.java源文件编译成一个.class字节码文件
  3. 执行阶段: 执行.class文件

JSP与Servlet的区别

  1. JSP主要给用户看的页面,Servlet是控制器
  2. JSP在被Tomcat翻译成Java文件的时候,自动给了九大内置对象。Servlet没有。
  3. JSP是简化版的Servlet,Servlet的功能更加全面
  4. JSP不是一个纯粹的java类,Servlet是一个纯粹的Java类

JSP页面组成

  1. HTML标签及其内容

  2. Java代码

    语法作用&注意事项
    脚本<% java代码 %>Java语句、变量、方法或表达式,不能定义方法
    表达式<%= 要输出的数据 %>先被转化成String将数据显示到页面上
    声明<%! Java代码 %>可以定义方法
  3. JSP指令

    指令描述
    <%@ page ... %>定义页面的依赖属性,比如脚本语言、error页面、缓存需求等等
    <%@ include ... %>包含其他文件
    <%@ taglib ... %>引入标签库的定义,可以是自定义标签
  4. 注释

    • JSP注释主要有两个作用:为代码作注释以及将某段代码注释掉。
    语法描述
    <%-- 注释 --%>JSP注释,注释内容不会被发送至浏览器甚至不会被编译
    <!-- 注释 -->HTML注释,通过浏览器查看网页源代码时可以看见注释内容
    <\%代表静态 <%常量
    %\>代表静态 %> 常量
    '在属性中使用的单引号
    "在属性中使用的双引号

JSP指令

Page指令

  • Page指令为容器提供当前页面的使用说明。一个JSP页面可以包含多个page指令。

  • Page指令的语法格式:

    • <%@ page attribute="value" %>
      
  • 等价的XML格式:

    • <jsp:directive.page attribute="value" />
      
  • 属性

    • 下表列出与Page指令相关的属性:

      属性描述
      buffer指定out对象使用缓冲区的大小
      autoFlush控制out对象的 缓存区
      contentType指定当前JSP页面的MIME类型和字符编码
      errorPage指定当JSP页面发生异常时需要转向的错误处理页面
      isErrorPage指定当前页面是否可以作为另一个JSP页面的错误处理页面
      extends指定servlet从哪一个类继承
      import导入要使用的Java类
      info定义JSP页面的描述信息
      isThreadSafe指定对JSP页面的访问是否为线程安全
      language定义JSP页面所用的脚本语言,默认是Java
      session指定JSP页面是否使用session
      isELIgnored指定是否执行EL表达式
      isScriptingEnabled确定脚本元素能否被使用

Include指令

  • JSP可以通过include指令来包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是该JSP文件的一部分,会被同时编译执行。

  • Include指令的语法格式如下:

    • <%@ include file="文件相对 url 地址" %>
      
  • include 指令中的文件名实际上是一个相对的 URL 地址。

  • 如果您没有给文件关联一个路径,JSP编译器默认在当前路径下寻找。

  • 等价的XML语法:

    • <jsp:directive.include file="文件相对 url 地址" />
      

Taglib指令

  • JSP API允许用户自定义标签,一个自定义标签库就是自定义标签的集合。

  • Taglib指令引入一个自定义标签集合的定义,包括库路径、自定义标签。

  • Taglib指令的语法:

    • <%@ taglib uri="uri" prefix="prefixOfTag" %>
      
  • uri属性确定标签库的位置,prefix属性指定标签库的前缀。

  • 等价的XML语法:

    • <jsp:directive.taglib uri="uri" prefix="prefixOfTag" />
      

EL表达式

  • JSP表达式语言(EL)使得访问存储在JavaBean中的数据变得非常简单。JSP EL既可以用来创建算术表达式也可以用来创建逻辑表达式。在JSP EL表达式内可以使用整型数,浮点数,字符串,常量true、false,还有null

  • 语法${...}

  • EL中的基础操作符

    • EL表达式支持大部分Java所提供的算术和逻辑操作符:
    操作符描述
    .访问一个Bean属性或者一个映射条目
    []访问一个数组或者链表的元素
    ( )组织一个子表达式以改变优先级
    +
    -减或负
    *
    / or div
    % or mod取模
    == or eq测试是否相等
    != or ne测试是否不等
    < or lt测试是否小于
    > or gt测试是否大于
    <= or le测试是否小于等于
    >= or ge测试是否大于等于
    && or and测试逻辑与
    || or or测试逻辑或
    ! or not测试取反
    empty测试是否空值
  • JSP EL中的函数

    • JSP EL允许您在表达式中使用函数。这些函数必须被定义在自定义标签库中。函数的使用语法如下:

      • ${ns:func(param1, param2, ...)}
        
    • ns指的是命名空间(namespace),func指的是函数的名称,param1指的是第一个参数,param2指的是第二个参数,以此类推。比如,有函数fn:length,在JSTL库中定义,可以像下面这样来获取一个字符串的长度:

      • ${fn:length("Get my length")}
        
    • 要使用任何标签库中的函数,您需要将这些库安装在服务器中,然后使用<taglib>标签在JSP文件中包含这些库。

  • JSP EL隐含对象

    • JSP EL支持下表列出的隐含对象:
    隐含对象描述
    pageScopepage 作用域
    requestScoperequest 作用域
    sessionScopesession 作用域
    applicationScopeapplication 作用域
    paramRequest 对象的参数,字符串
    paramValuesRequest对象的参数,字符串集合
    headerHTTP 信息头,字符串
    headerValuesHTTP 信息头,字符串集合
    initParam上下文初始化参数
    cookieCookie值
    pageContext当前页面的pageContext

反射

  1. 获取类的字节码对象

    • Class类:存储当前运行的类的相关信息

      • import java.lang.reflect.Method;
        import com.danny.entity.Student;
        //注意:类的字节码对象只有1个,所以,三种方式获取的对象是同一个对象。
        Student stu = new Student();
        //方式一:使用已经实例化的对象来获取
        Class c1 = stu.getClass();
        //方式二:使用类名来获取
        Class c2 = Student.class;
        //方式三:使用Class的静态方法forName()来获取
        Class c3 = Class.forName("com.danny.entity.Student");
        
  2. Class类的常用方法获取你想要的的内容

    • Method类:提供类的方法的信息
      • import java.lang.reflect.Method;	
        	//获取Student类的公共的方法的信息(包括继承来的)
            Method[] ms1 = c3.getMethods();
            for(Method m:ms1) {
                System.out.println(m);
            }
        
            System.out.println("------------------------------");
            //获取Student类的所有的方法的信息(不包括继承来的)
            Method[] ms2 = c3.getDeclaredMethods();
            for(Method m:ms2) {
                System.out.println(m);
            }
        
            System.out.println("------------------------------");
            //找到名为setSemail方法,并运行它(注意:这个方法是私有的)
            Method m = c3.getDeclaredMethod("setSemail", String.class);
            //打破方法的私有化限制
            m.setAccessible(true);
            //运行方法
            m.invoke(stu, "zs@qq.com");
            System.out.println(stu.getSemail());
        } catch (Exception e) {
            e.printStackTrace();
        }
        

使用反射实现多方法请求

  • 使用if方式的优缺点:

    • 优点:实现了一个Servlet完成多个功能的效果
    • 缺点:扩展性差,每多一个功能,就要多写一个else if与之对应
  • 反射实现多方法请求

    1. 创建BaseServlet.java

      • import javax.servlet.ServletException;
        import javax.servlet.http.HttpServlet;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import java.io.IOException;
        import java.lang.reflect.Method;
        
        public class BaseServlet extends HttpServlet{
            UserService us = new UserService();
            DoctorService ds = new DoctorService();
            MedicineService ms = new MedicineService();
            RegisterService rs = new RegisterService();
            @Override
            protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                req.setCharacterEncoding("utf-8");
                resp.setContentType("text/html;charset=utf-8");
                try {
                    String flag = req.getParameter("flag");
                    Class currentClass = this.getClass();
                    Method method = currentClass.getDeclaredMethod(flag, HttpServletRequest.class,HttpServletResponse.class);
                    method.setAccessible(true);
                    method.invoke(this, req,resp);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        
    2. StudentServlet,继承BaseServlet,其中不同功能的代码需要独立成不同的方法,方法名必须是前端传递的flag的值,方法的参数必须是request,response

      • @WebServlet("/student")
        public class studentServlet extends BaseServlet{
        	protected void ShowStudent(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        	...
        	}
        }
        
      • <a href="student?flag=ShowStudent">查看学生信息</a>
        

JSP九大隐含对象

  • Tomcat在将JSP翻译成Java文件时,自动给的
  • JSP支持九个自动定义的变量,江湖人称隐含对象。这九个隐含对象的简介见下表:
对象类型描述
request请求HttpServletRequest类的实例
response响应HttpServletResponse类的实例
out输出PrintWriter类的实例,用于把结果输出至网页上
session会话HttpSession类的实例
application服务器ServletContext类的实例,与应用上下文有关
config初始化数据ServletConfig类的实例
pageContext页面内容PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问
page当前页面类似于Java类中的this关键字
exception异常exception 类的对象,代表发生错误的 JSP 页面中对应的异常对象

equest对象

  • request对象是javax.servlet.http.HttpServletRequest 类的实例。每当客户端请求一个JSP页面时,JSP引擎就会制造一个新的request对象来代表这个请求。
  • request对象提供了一系列方法来获取HTTP头信息,cookies,HTTP方法等等。

response对象

  • response对象是javax.servlet.http.HttpServletResponse类的实例。当服务器创建request对象时会同时创建用于响应这个客户端的response对象。
  • response对象也定义了处理HTTP头模块的接口。通过这个对象,开发者们可以添加新的cookies,时间戳,HTTP状态码等等。

out对象

  • out对象是 javax.servlet.jsp.JspWriter 类的实例,用来在response对象中写入内容。
  • 最初的JspWriter类对象根据页面是否有缓存来进行不同的实例化操作。可以在page指令中使用buffered='false’属性来轻松关闭缓存。
  • JspWriter类包含了大部分java.io.PrintWriter类中的方法。不过,JspWriter新增了一些专为处理缓存而设计的方法。还有就是,JspWriter类会抛出IOExceptions异常,而PrintWriter不会。
  • 下表列出了我们将会用来输出boolean,char,int,double,String,object等类型数据的重要方法:
方法描述
out.print(dataType dt)输出Type类型的值
out.println(dataType dt)输出Type类型的值然后换行
out.flush()刷新输出流
  • Servlet中PrintWriter对象与JSP中out对象的区别
    • PrintWriter对象,不带缓冲区,直接放到页面上
    • JSP中out对象,带缓冲区,先放到缓冲区,再放到页面上

session对象

  • session对象是 javax.servlet.http.HttpSession 类的实例。和Java Servlets中的session对象有一样的行为。
  • session对象用来跟踪在各个客户端请求间的会话。

application对象

  • application对象直接包装了servlet的ServletContext类的对象,是javax.servlet.ServletContext 类的实例。
  • 这个对象在JSP页面的整个生命周期中都代表着这个JSP页面。这个对象在JSP页面初始化时被创建,随着jspDestroy()方法的调用而被移除。
  • 通过向application中添加属性,则所有组成您web应用的JSP文件都能访问到这些属性。

config对象

  • config对象是 javax.servlet.ServletConfig 类的实例,直接包装了servlet的ServletConfig类的对象。

  • 这个对象允许开发者访问Servlet或者JSP引擎的初始化参数,比如文件路径等。

  • 以下是config对象的使用方法,不是很重要,所以不常用:

    • config.getServletName();
      
  • 它返回包含在<servlet-name>元素中的servlet名字,注意,<servlet-name>元素在 WEB-INF\web.xml 文件中定义。

pageContext 对象

  • pageContext对象是javax.servlet.jsp.PageContext 类的实例,用来代表整个JSP页面。

  • 这个对象主要用来访问页面信息,同时过滤掉大部分实现细节。

  • 这个对象存储了request对象和response对象的引用。application对象,config对象,session对象,out对象可以通过访问这个对象的属性来导出。

  • pageContext对象也包含了传给JSP页面的指令信息,包括缓存信息,ErrorPage URL,页面scope等。

  • PageContext类定义了一些字段,包括PAGE_SCOPE,REQUEST_SCOPE,SESSION_SCOPE, APPLICATION_SCOPE。它也提供了40余种方法,有一半继承自javax.servlet.jsp.JspContext 类。

  • 其中一个重要的方法就是 removeAttribute(),它可接受一个或两个参数。比如,pageContext.removeAttribute(“attrName”) 移除四个scope中相关属性,但是下面这种方法只移除特定 scope 中的相关属性:

    • pageContext.removeAttribute("attrName", PAGE_SCOPE);
      

page 对象

  • 这个对象就是页面实例的引用。它可以被看做是整个JSP页面的代表。
  • page 对象就是this对象的同义词。

exception 对象

  • exception 对象包装了从先前页面中抛出的异常信息。它通常被用来产生对出错条件的适当响应。

JSP作用域

JSP四大作用域

JSP对象作用域范围Servlet对象
pageContext针对当前页面,页面切换失效javax.servlet.jsp.PageContext(抽象类)
request针对请求,一次请求内有效javax.servlet.httpServletRequest
Session针对浏览器,浏览器关闭失效javax.servlet.http.HttpSession
Application针对项目,当前项目中有效javax.servlet.ServletContext
  • 在一个页面上,四大作用域都有效
    • 页面一旦切换,pageContext作用域就失效
    • 使用重定向,不止一个请求,request作用域失效
    • 浏览器关闭,session作用域失效
    • 服务器关闭,application作用域失效

EL进阶

  • 使用EL表达式分别获取四大作用域的数据

    • <body>
      	<%
      		pageContext.setAttribute("name", "pageContext");
      		request.setAttribute("name", "request");
      		session.setAttribute("name", "session");
      		application.setAttribute("name", "application");
      	%>
      	pc:${pageScope.name }<br/>
      	req:${requestScope.name }<br/>
      	sess:${sessionScope.name }<br/>
      	app:${applicationScope.name }
      </body>
      
  • 从作用域最小的对象开始读取,顺序:pageContext–>request–>session–>application

  • 如果四大作用域中存入了相同key的数据,该怎样获取指定作用域的数据?

    • 方案:在el表达式前面加上对应的限制即可
      • pageContext–>pageScope
      • request–>requestScope
      • session–>sessionScope
      • application–>applicationScope

JSP动作标签

  • 与JSP指令元素不同的是,JSP动作元素在请求处理阶段起作用。JSP动作元素是用XML语法写成的。
  • 利用JSP动作可以动态地插入文件、重用JavaBean组件、把用户重定向到另外的页面、为Java插件生成HTML代码。
  • 动作元素只有一种语法,它符合XML标准:
    • <jsp:action_name attribute="value" />
  • 动作元素基本上都是预定义的函数,JSP规范定义了一系列的标准动作,它用JSP作为前缀,可用的标准动作元素如下:
语法描述
jsp:include在页面被请求的时候引入一个文件。
jsp:useBean寻找或者实例化一个JavaBean。
jsp:setProperty设置JavaBean的属性。
jsp:getProperty输出某个JavaBean的属性。
jsp:forward把请求转到一个新的页面。
jsp:plugin根据浏览器类型为Java插件生成OBJECT或EMBED标记。
jsp:element定义动态XML元素
jsp:attribute设置动态定义的XML元素属性。
jsp:body设置动态定义的XML元素内容。
jsp:text在JSP页面和文档中使用写入文本的模板

常见的属性

  • 所有的动作要素都有两个属性:id属性和scope属性。

    • id属性:

      • id属性是动作元素的唯一标识,可以在JSP页面中引用。动作元素创建的id值可以通过PageContext来调用。
    • scope属性:

      • 该属性用于识别动作元素的生命周期。 id属性和scope属性有直接关系,scope属性定义了相关联id对象的寿命。 scope属性有四个可能的值: (a) page, (b)request, ©session, 和 (d) application。
  • <jsp:include>动作元素

    • <jsp:include>动作元素用来包含静态和动态的文件。该动作把指定文件插入正在生成的页面。语法格式如下:

      • <jsp:include page="相对 URL 地址" flush="true" />
        
    • 前面已经介绍过include指令,它是在JSP文件被转换成Servlet的时候引入文件,而这里的jsp:include动作不同,插入文件的时间是在页面被请求的时候。

      • 以下是include动作相关的属性列表。

      • 属性描述
        page包含在页面中的相对URL地址。
        flush布尔属性,定义在包含资源前是否刷新缓存区。

静态与动态include

  • include指令(静态include)和include标签(动态include)的区别:
    1. 语法不一样
    2. 翻译方式不一样,指令只翻译一个文件,标签翻译所有文件
    3. 指令效率相对较高,标签低一些
    4. 指令不能携带数据,标签可以

JSTL标签库

  • 步骤

    1. 导入jar包

      • 官方地址: http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/
      1. jstl.jar
      2. standard.jar
    2. 在JSP页面中使用taglib指令引入需要的标签库

      • 常用库

        • http://java.sun.com/jsp/jstl/fmt
        • http://java.sun.com/jsp/jstl/core
        • http://java.sun.com/jsp/jstl/functions
      • 使用任何库,你必须在每个 JSP 文件中的头部包含 <taglib> 标签。

核心标签

  • 核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:

    • <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      
  • 标签描述
    <c:out>用于在JSP中显示数据,就像<%= ... >
    <c:set>用于保存数据
    <c:remove>用于删除数据
    <c:catch>用来处理产生错误的异常状况,并且将错误信息储存起来
    <c:if>与我们在一般程序中用的if一样
    <c:choose>本身只当做<c:when>和<c:otherwise>的父标签
    <c:when><c:choose>的子标签,用来判断条件是否成立
    <c:otherwise><c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行
    <c:import>检索一个绝对或相对 URL,然后将其内容暴露给页面
    <c:forEach>基础迭代标签,接受多种集合类型
    <c:forTokens>根据指定的分隔符来分隔内容并迭代输出
    <c:param>用来给包含或重定向的页面传递参数
    <c:redirect>重定向至一个新的URL
    <c:url>使用可选的查询参数来创造一个URL

格式化标签

  • JSTL格式化标签用来格式化并输出文本、日期、时间、数字。引用格式化标签库的语法如下:

    • <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
      
  • 标签描述
    <fmt:formatNumber>使用指定的格式或精度格式化数字
    <fmt:parseNumber>解析一个代表着数字,货币或百分比的字符串
    <fmt:formatDate>使用指定的风格或模式格式化日期和时间
    <fmt:parseDate>解析一个代表着日期或时间的字符串
    <fmt:bundle>绑定资源
    <fmt:setLocale>指定地区
    <fmt:setBundle>绑定资源
    <fmt:timeZone>指定时区
    <fmt:setTimeZone>指定时区
    <fmt:message>显示资源配置文件信息
    <fmt:requestEncoding>设置request的字符编码

JSTL函数

  • JSTL包含一系列标准函数,大部分是通用的字符串处理函数。引用JSTL函数库的语法如下:

    • <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
      
  • 函数描述
    fn:contains()测试输入的字符串是否包含指定的子串
    fn:containsIgnoreCase()测试输入的字符串是否包含指定的子串,大小写不敏感
    fn:endsWith()测试输入的字符串是否以指定的后缀结尾
    fn:escapeXml()跳过可以作为XML标记的字符
    fn:indexOf()返回指定字符串在输入字符串中出现的位置
    fn:join()将数组中的元素合成一个字符串然后输出
    fn:length()返回字符串长度
    fn:replace()将输入字符串中指定的位置替换为指定的字符串然后返回
    fn:split()将字符串用指定的分隔符分隔然后组成一个子字符串数组并返回
    fn:startsWith()测试输入字符串是否以指定的前缀开始
    fn:substring()返回字符串的子集
    fn:substringAfter()返回字符串在指定子串之后的子集
    fn:substringBefore()返回字符串在指定子串之前的子集
    fn:toLowerCase()将字符串中的字符转为小写
    fn:toUpperCase()将字符串中的字符转为大写
    fn:trim()移除首尾的空白符

Cookie&Session

会话技术

Cookie

  • Cookie 是存储在客户机的文本文件,它们保存了大量轨迹信息。在 Servlet 技术基础上,JSP 显然能够提供对 HTTP cookie 的支持。

  • 通常有三个步骤来识别回头客:

    • 服务器脚本发送一系列 cookie 至浏览器。比如名字,年龄,ID 号码等等。
    • 浏览器在本地机中存储这些信息,以备不时之需。
    • 当下一次浏览器发送任何请求至服务器时,它会同时将这些 cookie 信息发送给服务器,然后服务器使用这些信息来识别用户或者干些其它事情。
  • Cookie的注意事项:

    1. Cookie是以字符串的形式存储数据的,key不能写中文

    2. Cookie是小型文本文件,极限是4kb

    3. Cookie存储在客户端,不安全的

    4. Cookie默认浏览器关闭时自动失效,但是可以手动设置失效时间

  • 使用 JSP 设置 cookie

    • 使用 JSP 设置 cookie 包含三个步骤:

      1. 创建一个 cookie 对象: 调用 cookie 的构造函数,使用一个 cookie 名称和值做参数,它们都是字符串。

        • Cookie cookie = new Cookie("key","value");

        请务必牢记,名称和值中都不能包含空格或者如下的字符:

        • [ ] ( ) = , " / ? @ : ;
      2. **设置有效期:**调用 setMaxAge() 函数表明 cookie 在多长时间(以秒为单位)内有效。下面的操作将有效期设为了 24 小时。

        • cookie.setMaxAge(60*60*24);
      3. **将 cookie 发送至 HTTP 响应头中:**调用 response.addCookie() 函数来向 HTTP 响应头中添加 cookie。

        • response.addCookie(cookie);
  • 更多内容及代码: https://www.runoob.com/jsp/jsp-cookies.html

Session

  1. 由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。
  2. 思考一下服务端如何识别特定的客户?这个时候Cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
  3. Cookie其实还可以用在一些方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以写到Cookie里面,访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了,能够方便一下用户。这也是Cookie名称的由来,给用户的一点甜头。
  • 总结:
    • Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
    • Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
    • session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)
    • session 可以放在 文件、数据库、或内存中都可以。
    • 用户验证这种场合一般会用 session
  • 更多内容及代码: https://www.runoob.com/jsp/jsp-session.html

Java日期类型回顾

Date类型

  • MySQL中的时间日期类型:

    • date: yyyy-MM-dd

    • time: HH:mm:ss

    • datetime: yyyy-MM-dd HH:mm:ss

  • Java中的时间日期类型:

    • java.util.Date:年月日时分秒

    • java.sql.Date:年月日

  • 将字符串转换成时间日期对象以及获取当前时间的工具类

    • import java.text.ParseException;
      import java.text.SimpleDateFormat;
      import java.util.Date;
      
      public class DateUtil {
          public static Date stringToDate(String str) {
              Date date = null;
              if (str != null && !"".equals(str)) {
                  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                  try {
                      date = sdf.parse(str);
                  } catch (ParseException e) {
                      e.printStackTrace();
                  }
              }
              return date;
          }
          public static Date getCurrentDate(){
              Date date = null;
              SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
              String dateStr = sdf.format(new Date());
              try {
                  date = sdf.parse(dateStr);
              } catch (ParseException e) {
                  e.printStackTrace();
              }
              return date;
          }
      }
      

    JSTL时间格式化

    • <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
      <fmt:formatDate value="..." pattern="yyyy-MM-dd"/>
      

JSP点击量实例

  • https://www.runoob.com/jsp/jsp-hits-counter.html

AJAX

AJAX简介

  • AJAX = 异步 JavaScript 和 XML。
  • AJAX 是一种用于创建快速动态网页的技术。
  • 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
  • 传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
  • 有很多使用 AJAX 的应用程序案例:新浪微博、Google 地图、开心网等等。
  • 实际项目中的应用:
    • 直播或者视频播放时的弹幕,评论,点赞;网页上某部分内容根据操作产生变化。
  • 总结:局部刷新异步交互

AJAX 工作原理

AJAX


AJAX是基于现有的Internet标准

  • AJAX是基于现有的Internet标准,并且联合使用它们:
    • XMLHttpRequest 对象 (异步的与服务器交换数据)
    • JavaScript/DOM (信息显示/交互)
    • CSS (给数据定义样式)
    • XML (作为转换数据的格式)

lamp AJAX应用程序与浏览器和平台无关的!

原生JS实现Ajax请求

  1. 创建核心对象
    • var xhr = new XMLHttpRequest();
  2. 指定发送请求的相关信息(方式,路径,同异步)
    • xhr.open(“get/post”,”路径”,true);
  3. 发送请求
    • xhr.send();
  4. 定义onreadystatechange事件
    • xhr.onreadystatechange = function(){}
  5. 获取状态码
    • var statu = xhr.readyState
  6. 当状态码为4的时候,获取服务器返回的数据
    • var msg = xhr.responseText
  7. 处理数据

jQuery版本的Ajax

  • jQuery封装的Ajax的三个常用方法。
  1. $.ajax();

    • 语法:

      • $.ajax({
        url:”路径”,
        type:get/post”,
        data:{“key1”:”value1”,”key2”:”value2”},
        dataType:”响应数据的类型”,
        success:function(){},
        error:funciton(){}
        });
        
      • 注意点:

        1. 单词不要写错,data不是date
        2. 所有符号全是英文符号
        3. 每组值之间用逗号隔开,最后一组不需要
        4. dataType的T是大写
        5. 参数顺序可变
  2. $.get();

    • 语法

      • $.get(“路径”,{“key1”:”value1”,”key2”:”value2”},function(){    
        },”返回数据类型”);
        
      • 注意点:

        1. 该方法只有4个参数,顺序不能变
        2. 如果请求不携带数据,那么第二个参数写null
        3. 第三个参数是请求成功以后调用的函数
  3. $.post();

    • 语法

      • $.post(“路径”,{“key1”:”value1”,”key2”:”value2”},function(){},”返回数据类型”);
        
      • 注意点:

        1. 该方法只有4个参数,顺序不能变

        2. 如果请求不携带数据,那么第二个参数写null

        3. 第三个参数是请求成功以后调用的函数

  • $.ajax()$.get()$.post()的异同:
    • 相同点:都是jQuery封装的Ajax方法
    • 不同点:
      • $.ajax()是jQuery的第一次封装,使用是稍微麻烦一些,但是功能要强大些;
      • $.get()$.post()是在$.ajax()的基础上进行的二次封装,功能一样,参数顺序不能变。
  • 返回数据类型:
    1. text:字符串
    2. xml:XML标签
    3. HTML:HTML标签
    4. Script:脚本类型
    5. JSON:JSON类型
    6. JSONP:JSON类型,支持跨域访问

JSON简介

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
  • JSON 具有自我描述性,更易理解

JSON 语法

  • JSON 语法是 JavaScript 语法的子集。

  • JSON 语法规则

    • JSON 语法是 JavaScript 对象表示语法的子集。
      • 数据在名称/值对中
      • 数据由逗号分隔
      • 大括号 {} 保存对象
      • 中括号 [] 保存数组,数组可以包含多个对象
  • JSON 名称/值对

    • JSON 数据的书写格式是:key : value
    • 名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:
      • "name" : "Danny"
    • 这很容易理解,等价于这条 JavaScript 语句:
      • name = "Danny"

JSON 值

JSON 值可以是:

  • 数字(整数或浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true 或 false)
  • 数组(在中括号中)e.g."[1,2,3,4]"
  • 对象(在大括号中)e.g."{\"sid\":1,\"sname\":\"danny\",...}"
  • null

JSON 应用

  • 数组加对象的使用

    • servlet中

      • String str = "[{\"sid\":1,\"sname\":\"danny\",\"sage\":21},{\"sid\":2,\"sname\":\"jackson\",\"sage\":21}]";
        PrintWriter out = response.getWriter();
        out.print(res);
        out.close();
        
    • jQuery中

      • $("#btn").click(function(){
            $.get("JsonServlet",null,function(msg){
                $(msg).each(function(index,content){
                    console.log(content.sid+","+content.sname+","+content.sage);
                });
            },"json");
        });
        
  • 布尔值的使用

    • servlet中

      • boolean res = true;
        PrintWriter out = response.getWriter();
        out.print(res);
        out.close();
        
    • jQuery中

      • $("#btn").click(function(){
            $.get("JsonServlet",null,function(msg){
                if(msg){
                    alert("这是真的");
                }else{
                    alert("这是假的");
                }
            },"json");
        });
        

Jackson工具

  • 步骤:

    1. 导入jar包

      1. jackson-annotations-2.7.9.jar
      2. jackson-core-2.7.9.jar
      3. jackson-databind-2.7.9.jar
    2. 代码实现

      • 数组加对象的使用

        • servlet中

          • Student stu1 = new Student(1, "mary", 18, "female", "mary@qq.com");
            Student stu2 = new Student(2, "tom", 18, "male", "tom@qq.com");
            Student stu3 = new Student(3, "jack", 18, "male", "jack@qq.com");
            List<Student> list = new ArrayList<Student>();
            list.add(stu1);
            list.add(stu2);
            list.add(stu3);
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(list);
            System.out.println(json);
            PrintWriter out = response.getWriter();
            out.print(json);
            out.close();
            
        • jQuery中

          • $.post("JacksonServlet",null,function(msg){
                $(msg).each(function(index,content){
                    console.log(content.sname+","+content.semail);
                });
            },"json");
            

AJAX同步与异步

  • 异步:

    • 一个操作,涉及到发送多个请求时,运行是按照书写顺序进行,但结果的返回并不一定按照书写顺序来返回。哪个请求先完成,哪个请求就先返回。
  • 同步:

    • 一个操作,涉及到发送多个请求时,运行是按照书写顺序进行,结果返回也是按照顺写顺序来进行。
  • 特殊请求:

    • 第二个请求的条件是第一个请求的结果,这时候就不需要使用同步。

表单序列化

  • 实例

    • 输出序列化表单值的结果:

      • $("button").click(function(){
          $("div").text($("form").serialize());
        });
        

    定义和用法

    • serialize() 方法通过序列化表单值,创建 URL 编码文本字符串。
    • 您可以选择一个或多个表单元素(比如 input 及/或 文本框),或者 form 元素本身。
    • 序列化的值可在生成 AJAX 请求时用于 URL 查询字符串中。
  • 语法

    • $(selector).serialize()
      
  • 详细说明

    • .serialize() 方法创建以标准 URL 编码表示的文本字符串。它的操作对象是代表表单元素集合的 jQuery 对象。

JavaWeb面试题

Get与Post的区别

不同点GetPost
参数传递方式通过URL传递参数用&隔开也是表单的默认传递方式,不安全对所有用户不可见,相对Get而言更安全
传送数据量较小,受URL长度限制较大,一般默认为不受限制
提交数据是缓存请求保留在浏览器的历史记录中请求不会保留在历史记录中
编码类型仅支持一种编码方式(Tomcat8后默认UTF-8)支持多种编码方式

转发与重定向的区别

不同点转发重定向
发生位置服务器客户端
浏览器地址栏不变改变
请求与响应一次请求一次响应至少两次请求两次响应
request作用域的数据可共享不能共享
跳转语句request.getRequestDispatcher("URL").forward(request,response)response.sendRedirect("URL")
执行速度较高因为是服务器行为较低
执行范围URL是当前项目内URL可以是外部项目,没有限制

静态包含与动态包含的区别

不同点静态包含动态包含
写法<%@include fire="***" %><jsp:include page="***"></jsp:include>
编译方式将被包含的页面先整合到包含页面再编译,所以只有一个文件包含与被包含的页面都会编译,运行后再通过servlet整合
参数传递不能先被包含的页面传递参数可以使用jsp:param标签向被包含的页面传递参数
运行效率相对而言比较快,包含一个页面相对而言比较慢,包含多个页面

Session与Cookie的区别

不同点SessionCookies
存储位置服务器客户端(浏览器)
存储数据的大小没有上限不超过4kb
存储数据的类型任意类型字符串类型
默认有效期默认有效期30分钟浏览器关闭
  • 2
    点赞
  • 0
    评论
  • 7
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 1024 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值