02-janycode.github.io
2021-07-26 09:52:27 3 举报
AI智能生成
JavaSE、JavaWeb、Java分布式开发学习
作者其他创作
大纲/内容
JDK1.8-API中文版
Notepad++
* 创建项目:File > new > project > Java Project* src下创建包:[右键]new > Package* package下创建类:[右键]new > Class (.java文件)* 修改编辑字体:Windows > Preferences > Gerenal > Appearance > Colors and Fonts > Basic > Text Font > Edit > \"Microsoft YaHei Mono\"-11* 修改输出字体:Windows > Preferences > Gerenal > Appearance > Colors and Fonts > Debug > Text Font > Edit > \"Microsoft YaHei Mono\"-11* 重置窗体排布:Windows > Perspective > Reset Perspective
常规使用
* 导入项目:File > Import > General > Existing Projects into Workspace > Browse > [项目根文件夹] > finish
导入项目
* 默认正确,无需改动,如需改动,参考步骤:Windows > Preferences > Java > Installed JRES > 选中JRE > Edit > 选中..\t.jar > Source Attachment > External location > 找到src.zip
附加源码
* Ctrl+1 快捷修复* Ctrl+D 快捷删除行* Shift+Enter 无视光标直接跳入下一行* Ctrl+F11 一键运行* Alt+↑/↓ 快速移动单/多行* Ctrl+Alt+↑/↓ 快速复制单/多行* Ctrl+M 将当前代码编辑框放大/恢复* Alt+/ 快速补全代码 >> sout:System.out.println();* Ctrl+/ 快速注释单/多行和恢复(单行注释符 // )* Ctrl+Shift+/ 快速注释单/多行和恢复,需选中 (多行注释符 /* */)* /** 快速创建函数的javadoc文档注释* Ctrl+Shift+F 格式化代码(注意印象笔记&搜狗输入法的快捷键冲突)* Ctrl+E 弹出快速文件选择窗然后上下选择* Alt+Shift+W 选择第一个Package Explorer即可快速定位* Alt+Shift+R 然后修改即可修改所有相同变量* Ctrl+Q 返回上一个Ctrl+鼠标单击跳转的原始位置* F3 在关键字上按,可以跳转进入源码* Alt+←/→ 浏览F3跳转源码的轨迹* Ctrl+Shift+O 快速导包:导入需要的包同时去掉无用的包* Alt+Shift+Z 选中代码行后,快速创建try-catch块* Ctrl+O 快速显示OutLine悬浮窗,搜索和浏览成员方法* font color=\"#c41230\
快捷键
+o 完成构造方法
+r 添加geter和seter
+s 添加覆盖Object父类toString()方法
+v 继承覆盖方法
+c 继承构造方法
+m 成员的方法
+h 添加 hashcode() 和equals()
Alt+Shift+S 弹出源码选项
快速生成代码
Eclipse
如果已打开项目 File >> Close Project初识启动界面中 + Create New Project
Java Enterprise >> ☑Web Application >> Next
IDEA创建Web项目
配置:Project Structure图标 >> Artifacts >> +新增Web Application: Arichive选择当前项目xxx:war >> OK
生成:Build >> Build Artifacts >> 选择xxx:war点击Build >> out/artifacts/xxx_war/xxx_war.war
部署:将xxx_war.war包放在 Tomcat 的 webapps 目录下,启动服务器会自动解压该web项目,便于直接访问
IDEA生成war包
Web项目
Ctrl+Shift+S 打开全局设置 >> Tools 工具 >> Diagrams 图表 >>Java Class Diagrams >> ☑Fields属性 ☑Constructors构造方法 ☑Methods成员方法Ctrl+Alt+Shift+U 显示类图到新标签栏(Ctrl+/按1:1比例显示,Ctrl按住可拖动,Alt按住为放大镜)
UML类图
Settsings(Ctrl+Alt+S) -->Editor --> Code Style --> SQL --> MySQL 将keywords设置为大写(To upper)
MySQL Console 关键字大写
基本使用
Ctrl+Alt+S 全局设置菜单窗口Ctrl+P 方法的参数提示Ctrl+Q 方法的注释+声明提示Ctrl+F12 显示当前文件的结构(快速跳转)Ctrl+[ / ] 跳转{ }作用域开始 / 结束位置Ctrl+E 显示最近打开过的文件Ctrl+Tab 切换编辑文件或项目树,Ctrl需按住font color=\"#00a650\
窗口菜单
Alt+Insert 插入一切双击Shift+Tab 搜索一切
无敌通用
-----------------------------------------------------------main+Tab 生成main方法,类名下 m 即可sout+Tab 生成输出语句,so 即可new Xxxx( ).var 快速生成引用赋值fori 快速生成for循环 - i 整数遍历iter 快速生成增强for循环 - foreachitar 快速生成array for循环 - 字符串遍历itit 快速生成iterator迭代-while( ) next( )itco 快速生成Collection迭代 - for.foreach 快速foreach循环Ctrl+X 删除+剪切当前行Ctrl+C 高亮+复制当前行Ctrl+D 立即复制当前行到下一行Ctrl+Shift+↑/↓ 快速移动代码行Ctrl+/ 或 Ctrl+Shift+/ 单行 或 多行注释Ctrl+O 重写方法(继承)Ctrl+i 实现方法(实现接口) Alt+Enter代替Ctrl+Shift+U 大小写转换Ctrl+Shift+J 合并选中的行变1行Ctrl+Alt+L 自动缩进及格式化代码Ctrl+\"+/-\" 当前方法展开、折叠Ctrl+Shift+\"+/-\" 全部展开、折叠Alt+/ 代码提示(默认自动提示)b style=\
快速编辑
-----------------------------------------------------------双击Shift+Tab 查找一切Ctrl+N+N 全局搜索ClassCtrl+F 当前文件执行查找Ctrl+Shift+F 整个项目查找文本Ctrl+R 当前文件执行替换Ctrl+W 自动按语法选中代码(递增范围)Shift+F6 批量重命名同1个变量名Ctrl+G 定位行Ctrl+Alt+←/→ 前后跳转编辑过的位置Alt+F7 查看函数/变量/类的所有引用到的地方F4 当前类中查找变量的定义位置Ctrl+Shift+F7 高亮显示选中的相同文本,ESC取消高亮
查找替换
-----------------------------------------------------------Ctrl+Shift+F10 编译运行当前文件目标Shift+ESC 关闭运行结果显示窗口【通用】
编译运行
谷歌翻译插件Ctrl+Shift+Y 可快捷翻译Ctrl+Shift+X 可将中文翻译英文后替换(变量取名)
Translation
大/小/驼峰/下划线切换Alt+Shift+U 来回切换字符串样式,直到满意
CamelCase
生成方法调用序列图方法名上右键选择 Sequence Diagram
SequenceDiagram
生成局部变量的所有set方法调用变量上 Alt+Enter
GenerateAllSetter
右侧折叠小窗记录常用操作,显示快捷键提示
Key Promoter X
查看字节码文件View >> Show ByteCode With Jclasslib
Jclasslib Bytecode Viewer
直接类内 Alt+Insert 选最后一个或者类内 Alt+S 贴入json字符串,自动生成属性+get/set方法
Gson Format
右侧小窗 Database 数据库中连接后右键 表名 选择 Easy Code >> Generate Code 自动生成数据映射关系的包和类
Easy Code
代码编辑区右侧缩略图,同Sublime Text
Code Glance
对单词组合命名的变量/方法/类名使用:Alt + Shift + U 可以调整不同方式命名,不停按6种直到满意。
GamelCase
阿里巴巴 Java 编程规范,自动提示/警告/报错Alt + Enter 修复
Alibaba Java Coding Guidelines
插件
IntelliJ IDEA
装好MySQL后,该客户端工具只需要输入密码即可使用。
工具 >> 首选项 >> 字体编辑器设置
SQLyog
Navicat
Java实现,集成插件。
Hbuilder
C++实现,没有集成插件,更快更轻量。
插件安装:工具 >> 插件安装
快捷键方案:工具 >> 预设快捷键方案切换 >> Intellij IDEA/Webstorm
HbuilderX
Ctrl+/ 快速注释Ctrl+N 快速新建
Hbuilder[X]
Tools
模拟现实世界,解决现实问题。
面向对象
Java有虚拟机,内置了垃圾收集器(GC),自动完成内存空间的管理。
简单
跨操作系统(Windows<C#>,Unix-Linux,MacOS,Solaris)、服务器、数据库。
跨平台
特点
1995年推出 1996年发布JDK1.0 2009年被Oracle收购 2014年由Oracle发布Java 8.0<JDK1.8>
由来
Java Platform Standard Edition (Java平台标准版) CoreJava
JavaSE
Java Platform Enterprise Edition (Java平台企业版) 企业级开发
JavaEE
Java Platform Micro Edition (Java平台微小版) Java最初的定位(机顶盒)
JavaME
分类
先编译,再解释。
*.java(源文件) -> 编译 -> *.class(字节码文件) -> 执行 -> Win/Unic/MacOS/Others-(JVM)
Java设计理念:Write Once Run Anywhere.
运行机制
(Java Virtual Machine)虚拟机:使用软件在不同操作系统中模拟相同的环境。
JVM
(Java Runtime Environment)运行环境:包含JVM和解释器,完整的Java运行环境。
JRE
(Java Development Kit)开大环境:包含JRE[JVM+解释器] + 类库 + 开发工具包(编译器+调试工具)。
JDK
名词解释
概述
oracle官网获取,JDK1.8使用最为广泛。
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
JDK获取
非C盘
路径不带中文或空格
JDK包含JRE可跳过不装JRE
建议:D:\\Java
JDK安装
win+E >> 右键(空白处) >> 属性 >> 环境变量
* 新建系统变量: 变量名:JAVA_HOME 变量值:D:\\Java\\jdk1.8.0_231 (找到实际安装路径)
* 新建系统变量:变量名:CLASS_PATH变量值:.;%JAVA_HOME%\\lib;%JAVA_HOME%\\lib\\tools.jar
* 编辑Path变量:变量名:Path 变量值:;%JAVA_HOME%\\bin;%JAVA_HOME%\\jre\\bin; (末尾添加)
验证:cmd命令窗口中输入\"javac -version\"
JDK环境变量配置
更换盘符:d: 查看当前目录下的文件和文件夹:dir创建文件夹:mkdir 文件夹名字进入文件夹:cd 文件夹名字返回上一级目录:cd ..清空屏幕:cls删除文件:del 文件名删除文件夹:rd 文件夹名称退出:exit
常用DOS命令
环境搭建
class HelloWorld { public static void main(String[] args) { System.out.println(\
源码
javac HelloWorld.java
编译
java HelloWorld
运行
第1个Java程序
* 同一个源文件中可以定义多个类* 相同源文件中的多个类编译后会生成各自的.class文件* 一个类中只能有一个主函数main,每个类都可以有各自的主函数main* public修饰的类成为公开类,要求类名与文件名必须相同,包括大小写* 一个源文件中只能有一个public公开类
类的阐述
作用:类似文件夹,用于管理归纳字节码(.class)文件。
语法:package 包名;
多级:package 包名.包名;
位置:必须写在源文件的第一行。
带包编译:javac -d 目录名 源文件.java (会自动创建package包目录)
带包运行:java 包名.类名 (包名+类名又称全限定名)
Package(包)
生成外部文档:javadoc -d 目录名 源文件.java
文档注意事项:1.源文件编码问题,中文使用utf-8;2.主要查看index.html文件
doc文档生成
终极参考:《阿里巴巴JAVA开发手册.pdf》
编码规范
计算机内存中一块存储空间,是存储数据的基本单位
数据类型
变量名
值
组成部分
数据类型 变量名;变量名 = 值;
先声明,再赋值
声明并赋值
多个同类型变量的声明与赋值
声明方式
变量
1个字节 -128 ~ 127
byte
2个字节 -32768 ~ 32767
short
4个字节 -2^31 ~ 2^31-1
Java中任何一个整数,默认的类型为int,如果整数超过int取值范围,则均报错为过大的整数
int
8个字节 -2^63 ~ 2^63-1
long类型的赋值整数如果超过了int类型取值范围,则需要在数字后加 \"L\" 以标记为long类型
long
整数
4个字节 Float.MIN_VALUE ~ Float.MAX_VALUE
如果使用单精度float类型,则需要在数字后面加\"F\"表示单精度值
float
8个字节 Double.MIN_VALUE ~ Double.MAX_VALUE
Java中任意一个小数默认类型为双精度类型double
double
小数
1个字节(根据具体环境) true / false
Java中的boolean类型变量不能参与算术运算!
boolean
布尔
2个字节
\\' \\\" \\\\ \ \\t
转义字符 \\
通过字符直接赋值【常用】
赋值
char
字符
基本数据类型
任何\"\"之间的内容都是字符串,包括空格
String
字符串
数组
对象
引用数据类型
两种类型兼容,目标类型大于源类型
自动类型转换
两种类型兼容,目标类型小于源类型
整数长度足够,数据完整
整数长度不够,数据截断
小数强转整数,数据截断
保证正整数转换成字符,可以正常显示
字符整数互转,数据完整
boolean不可与其他类型转换
转换规则
强制类型转换
提升优先级规律:double << float << long < int << short/byte
两个操作数中有一个为优先级中的类型,计算结果提升为优先级中对应类型
任何类型与String相加(+)时,实为拼接,结果自动提升为String
【坑】num1+num2+string1:两个操作数为数值时,相加;两个操作数中有一个为String时,拼接。
自动类型提升
类型转换
+ - * / %
算术运算符
= += -= *= /= %=
赋值运算符
> < >= <= == !=
关系运算符
&& || !
逻辑运算符
布尔表达式 ? 结果1 : 结果2
三元运算符
运算符
功能: 将外部class文件功能引入到自身文件中
位置: jdk1.8.0_121\\jre\\lib\t.jar 压缩包中
导包语法:import 包名.类名;
import java.util.Scanner
1.导包
Scanner 类型的变量
Scanner input = new Scanner(System.in);
2.声明
.nextInt(); // 获得整数 .nextDouble(); // 获得小数.next(); // 获得字符串.next().charAt(0); // 获得字符串的第一个字符
输入类型
如果输入了不匹配的数据,则会产生 java.util.InputMismatchException 异常
3.接收
TestScanner.java
控制台输入
概念:根据已知条件进行逻辑判断,满足条件执行操作
基本if选择结构
if-else选择结构
适用于区间判断
多重if选择结构
语法正确、任意嵌套
嵌套if选择结构
选择结构
可判断:font color=\"#c41230\
switch中多个case的取值不可以相同
switch自动向下贯穿的特性,如需中止使用break关键字
switch-case
分支结构
概念:声明在函数内部的变量,必须先赋值再使用
作用范围:从定义行开始到所在的代码块结束
注意:多个变量在一个重合的作用范围内,不可出现重名
局部变量
选择与分支结构
概念:通过某个条件,重复执行一段逻辑代码
首次即有入口条件,适用于循环次数明确的情况
先判断,再执行。
次数:0-n
while循环
首次没有入口条件,适用于循环次数不明确的情况
先执行,再判断。
次数:1-n
do-while循环
初始部分只执行一次,且可以省略
for循环
基本结构
终止循环,跳出当前层级循环(1层)
跳出switch结构、跳出循环结构
break
结束本次,跳过当前层级循环(1层),进入下一次
continue
流程控制关键字
循环结构
概念:实现特定功能的一段代码,可以反复使用。
设计:遵循单一职能原则,一个函数只做一件事
规则:一个类中可以定义多个函数,函数之间是并列关系,不可嵌套
public static void 函数名称 () { // 函数主体}
格式:
调用:函数名();
调用函数时,所传入的数据被称为\"参数\"
public static void 函数名称 (函数形参) { // 形参 等价于 局部变量的声明 // 函数主体}
定义
调用:函数名(实际参数); // 实参 等价于 局部变量的赋值操作
参数:
== 默认比较的地址值,不是字符串内容
str1.equals(str2font color=\"#f15a23\
Tips:【字符串比较】
定义返回值类型:基本数据类型、引用数据类型、void
return value; // 函数可以返回一个结果,类型必须与函数定义的返回值一致
一个函数只能有一个返回值,如果函数中包含分支条件,需要保证所有的分支都有返回值
return value; // 表示结束当前函数,并伴有返回值,返回到函数的调用处
return; // 表示结束当前函数,直接会返回到函数调用处
return 的两种用法
返回值和返回值类型
递归需要设置有效的出口条件,避免无穷递归
出口条件可能为多个
TestFibonacci.java
递归经典:斐波那契数列
多级调用
函数
概念:一组连续的存储空间,存储多个相同数据类型的值
特点:类型相同,长度固定。
数组中每个格子称为数组的元素
数组的下标从 0 开始,有效范围:0 ~ 数组长度-1
数组font color=\"#c41230\
组成
①声明并分配空间数据类型[] 变量名 = new 数据类型[数组大小值];eg:int[] arr = new int[5];
②先声明,再分配空间数据类型[] 变量名;变量名 = new 数据类型[数组大小值];eg:int[] arr;arr = new int[5];
③声明并赋值(繁)font color=\"#f15a23\
④声明并赋值(简)font color=\"#f15a23\
创建
数组名[下标]; eg:int[2];
访问
数组名.lengtheg:arr.length
数组创建之后,长度不可变。
长度
for (int i = 0; i < arr.length; i++) { // arr[i] 使用数组元素}
遍历
思路:创建一个新的更大的数组,将原数组内容复制到新数组中。
循环将原数组内容逐一复制到新数组
font color=\"#f15a23\
数组变量中存储的是数组的首地址
返回值为数组类型,可直接赋值给原数组
3种方式
TestArrayAction.java
【增删改查】
扩容
基本数据类型变量中存储的是 值
引用数据类型变量中存储的是 地址
基本数据类型与引用数据类型
相邻两个值比较大小(arr[j] > arr[j+1]),互换位置
记忆:外层font color=\"#c41230\
冒泡排序
固定值与其他值比较大小(arr[i] > arr[j]),互换位置
选择排序
java.util.Arrays.sort(数组名);
JDK排序
排序
概念:一维数组中的一维数组,数组中的元素还是数组
访问:数组名[高维下标][低维下标]
高维数组中的每一个元素,存储了低维数组的地址。
* 先声明、再分配 数据类型[][] 数组名; 数组名 = new 数据类型[高维长度][低维长度];
* 声明并分配空间 数据类型[][] 数组名 = new 数据类型[高维长度][低维长度];
* 声明并赋值(繁) 数据类型[][] 数组名 = new 数据类型[高维长度][]; //不规则数组数组名[i] = new 数据类型[j]; //自行new低维属组
* 声明并赋值(简)font color=\"#f15a23\
定义方式
Demo
经典案例:杨辉三角
二维数组
语言基础
万物皆对象。对象一定拥有自己的特征和行为。
特征:称之为属性,一般为名词,代表对象有什么。
行为:称之为方法,一般为动词,代表对象能做什么。
程序中的对象:来自于模板(类)创造出来程序中的实体(对象)
类:定义了对象应具有的特征和行为,类是对象的模板
类的抽取:在一组相同或者类似的对象中,抽取共性的特征和行为。
对象:拥有多个特征和行为的实体,对象是类的实例
类与对象
局部变量:方法或方法内的结构中
实例变量:类的内部,方法的外部
定义位置
局部变量:无默认值
实例变量:字面值(与数组相同0/null)
默认值
局部变量:从定义行到其结构结束行
实例变量:本类有效
使用范围
局部变量:不允许重名
实例变量:可与局部变量重名,局部变量优先
命名冲突
实例变量&局部变量
概念:一个类中定义多个相同名称的方法
到底采用哪种形式,需要取决于调用者给定的方法的参数。
方法名称相同
参数列表不同(类型、个数、顺序)
与访问修饰符、返回值类型、形参的名称均无关
要求
方法重载(Overload)
概念:类中的特殊方法,主要用于创建对象
名称与类名完全相同(包括大小写)
没有返回值类型修饰符(void也没有)
创建对象时触发构造方法的调用,不可通过.访问符访问
内存堆区中开辟对象空间
为各个属性赋予初始值(默认0 / 0.0 / null)
执行构造方法中的代码
[将对象的地址赋值给变量]
对象创建过程
构造方法也可以重载,遵循重载规则
如果没有显示定义构造方法,编译器会默认提供一个无参构造方法
如果显示定义了有参构造方法,则无参构造方法必须也要显示定义
注意
构造方法(Constructor)
概念:this是类中的默认引用,代表当前实例(当前对象)
this.属性名 / this.函数名( )
this([参数列表])
语法
调用实例属性、实例方法,eg:this.name、this.sayHi()
this([实参])必须在构造方法的首行,仅可在构造方法中使用
调用本类中的其他构造方法,eg:this( )、this(实参)
表示当前方法(暂未用到)
三种用法
this关键字
概念:尽可能隐藏对象的内部实现细节,控制对象的修改和访问权限
访问修饰符: private font color=\"#f15a23\
get/set方法是外界访问对象私有属性的唯一通道,方法内部对属性检测和过滤
提供public公共访问方法,以保证数据可以正常录入和访问
封装
程序中的继承,是类与类之间特征和行为的一种赠予或获得。
类与类之间必须满足 is a 的关系。
父类的选择:功能越精细,重合点越多的,就越接近直接父类。
父类的抽象:根据程序需要使用到的多个具体类,进行共性提取,进而定义父类。在一组相同或类似的类中,抽取特征和行为,定义在父类中,实现重用。
继承语法:class 子类名 extends 父类名{ } //定义子类时,显式定义父类
完整的子类:完整子类 = 父类共性 + 子类独有
Java为单继承,一个类只能有一个直接父类,但可以多级继承,属性和方法逐级叠加。
构造方法:类中的构造方法,只负责创建本类对象,不可继承
private修饰的属性/方法:仅本类可见,不可继承
父子类不在同一个package中,且default修饰的属性和方法,不可继承
不可继承
public 任何
protected 父子
default 同包
private 本类
访问权限修饰符:private/default/protected/public
写全限定名(包名.类名),eg: java.util.Arrays.copyOf(...);
导包(import),eg: import java.util.Arrays;
跨包访问
同名:方法覆盖
当父类提供的方法无法满足子类的需求时,可在子类中定义和父类相同的方法进行覆盖(Override)
方法名称、参数列表、返回值类型必须与父类相同;
访问修饰符应与父类相同或更宽泛;
方法覆盖原则
执行机制:子类覆盖父类方法后,调用时优先执行子类覆盖后的方法
方法重写(Override)
用法1:子类去访问父类重名的属性/方法时(属性遮蔽、方法覆盖),使用super.专项访问父类的属性/方法
super( ) 默认调用父类无参构造方法,隐式存在于构造方法的首行
super(参数) 指定调用父类有参构造方法,显式调用且编译器不在提供super( )执行
用法2:子类构造方法在调用父类构造方法时
同一个子类构造方法中,super( )和this( )不可同时存在
当子类构造中使用了this()或this(实参),即不可再同时书写super()或super(实参),会由this()指向的构造方法完成super()的调用
this与super
super关键字
继承关系下构建子类对象时,会先构建父类对象
由\"父类共性\" + \"子类独有\" 组合成一个完整的子类对象
① 构建父类对象
② 初始化自身属性
③ 执行自身构造方法中的逻辑代码
流程
继承关系下对象的创建
继承
概念:父类引用指向子类对象,从而产生多种形态。eg: Animal a = new Dog();
二者具有直接或者间接的继承关系时,父类引用可指向子类对象,形成多态。
父类引用仅可调用父类所声明的属性和方法,父类不可调用子类独有的属性和方法。
多态场景下,如果子类覆盖过父类的方法,优先执行子类覆盖后的方法;否则执行父类的方法
父类引用作为方法的【形参】,实现多态,使方法参数的类型更为宽泛 (该父类任一子类均可作为实参传入)
父类引用作为方法【返回值】,实现多态,使方法可以可以返回不同的子类对象
多态的两种使用场景
概念:父类引用中保存真实子类对象。(多态核心概念)
eg: Animal a = new Dog(); // 对象层面的自动类型转换
调用:仅可调用父类中所声明的属性和方法(遵循属性遮蔽/方法覆盖原则)
向上转型(装箱)
概念:将父类引用中的真实子类对象,强转回子类本身类型。
eg: Animal a = new Dog(); Dog dog = (Dog)a; // 对象层面的强制类型转换 Cat cat = (Cat)a; // Error: 不是真实子类对象new Dog(),编译OK,运行则会抛出类型转换异常:java.lang.ClassCastException
调用:只有转回子类真实类型,才可调用子类独有的属性和方法。
向下转型前应该判断引用中的对象真实类型,保证类型转换的正确性。
语法: 父类引用 instanceof 子类类型 // 返回boolean类型结果,意为:父类包含子类对象真实类型,true包含,false不包含
向下转型(拆箱)
多态
三大特性
概念:不够完整,不够具体,不能独立存在 的对象模型
语法:abstract class 类名 {}
抽象类,不能直接独立new对象;
可被子类继承,提供共性属性和方法;
可声明为引用,强制使用多态(更纯粹的多态);
抽象类的构造方法作用:构建子类对象时,先构建父类对象(父类共性 + 子类独有 = 完整子类对象)
作用
经验:abstract修饰后的抽象父类,依附于子类对象存在
修饰 类
概念:抽象方法,不够完整、不够具体 的方法
语法:访问权限修饰符 abstract 返回值类型 函数名([参数列表]);
只有方法声明,没有方法实现;
必须包含在抽象类中(abstract class XX{});
强制子类必须实现该方法,提供完整的、具体的调用版本;
子类继承抽象类,子类必须覆盖父类中所有的抽象方法,否则子类还是抽象类;
抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类。
总结
修饰 方法
abstract
实例属性,是每个对象各自持有的独立内存空间(多份),对象单方面修改,不会影响其他对象。
静态属性,是整个类共同持有的共享空间(一份),任何对象修改,都会影响其他对象。
Java中规定:不能将方法体内的局部变量声明为 static!
静态属性 - 类属性
静态方法 - 类方法
static 修饰的成员
不必创建对象,可直接通过类名访问【推荐】:类名.静态成员
静态方法允许直接访问静态成员(不需要this.);
静态方法不允许直接访问非静态成员;
静态方法中不允许使用this或super关键字(构造方法可以);
静态方法可以继承,不能重写(覆盖)、没有多态;
静态方法规则
在执行类时,希望先执行的初始化动作,可以使用static定义一个静态代码区域,在类加载时即会被执行仅有的一次。
代码示例
静态代码块
JVM首次使用某个类时,需通过CLASSPATH查找该类的.class文件
将.class文件中对类的描述信息加载到内存中,进行保存
单独调用类加载语法:Class.forName(\"全限定名\");
触发:静态属性和静态代码块的执行 - (仅1次)
顺序:静态属性初始化之后执行静态代码块
作用:可谓静态属性赋值,或必要的初始化行为
类加载时
类加载
static
概念:最后的,不可更改的。—— 保护类/方法/变量的功能和值
此类font color=\"#c41230\
类(最终类)
此方法不能被覆盖。
方法(最终方法)
此变量值不能被改变(常量 - 通常变量名全大写),eg: Math.PI
变量(最终变量)
修饰内容
显式初始化、动态代码块、构造方法
①DeadLine:在构造方法完成之前,为实例常量赋值即可;
②如果在构造方法中为实例常量赋值,必须保证所有的构造方法都能对其正确赋值。
实例常量赋值
显式初始化、静态代码块
①Deadline:在类加载完成之前,为静态常量赋值即可。
静态常量赋值
final修饰基本类型:值不可变
final修饰引用类型:地址不可变
对象常量赋值
拷贝引用,为了避免引用值(地址)发生改变。例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。
final作为形参使用
final
三修饰符
Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口用以扩容子类能力。即:Java中使用抽象类/父类表示通用属性时,每个类只能继承一个类,假如子类已经从一个父类继承了,就不能再继续继承另外的父类。但每个类可以实现多个接口,这样子类就拥有了更多的能力。
接口的定义:代表了某种能力
方法的定义:能力的具体要求
微观概念:接口是一种能力和约定。
耦合度:模块与模块之间的关联程度。关联的越密切,耦合越高;关联的越松散,耦合越低。√
宏观概念:接口是一种标准。
接口相当于特殊的抽象类,定义方式、组成部分与抽象类类似。
什么是接口
定义语法:interface 接口名 { }
public interface MyInterface { public static final String FIELD = \"value\"; String S = \"str\"; // public static final 默认隐式存在、修饰 public abstract void method( ); void m( ); // public abstract 默认隐式存在、修饰}//public 关键字仅限用于接口在于其同名文件中被定义
没有构造方法,不能创建对象
只能定义:公开静态常量、公开抽象方法、公开静态方法font color=\"#662c90\
定义要求:
使用语法:font color=\"#f15a23\
// 增加/赋予1种/多种能力(逗号分隔) [约定] calss Sub extends Super implements font color=\"#f15a23\
任何类在实现接口时,必须实现接口中所有抽象方法,否则此类为抽象类
实现接口中的抽象方法,访问修饰符必须是public
使用规范:
使用
接口的语法
1.可编译为字节码文件(.class)2.不能创建对象(接口不是类,也没有构造方法)3.可以作为引用类型4.具备Object类中所定义的方法
相同
1.所有属性都只能且默认是公开静态常量,隐式使用public static final修饰2.所有方法都只能且默认是公开抽象方法,隐式使用public abstract修饰3.没有构造方法、没有动态/静态代码块
不同
对比抽象类
同父类一样,接口也可声明为引用,并指向真实类对象。
使用接口引用作为方法形参,实现更自然的多态(只关注能力-具备能力的类对象均可传入)
仅可调用接口中所声明的方法,不可调用实现类中独有的方法
可强转回真实类本身类型,进行独有方法调用(注意判断真实类对象 instanceof)
【注意】
接口引用【重要】
类与类:单继承,extends 父类名称
接口与接口:多继承,font color=\"#f15a23\
常见关系
将多个常用于表示状态或者固定值的变量,以静态常量的形式定义在接口中同一管理,提高代码可读性。
常量接口使用语法:接口名.常量名
常量接口示例代码
常量接口
重在理解、应用。
思路顺序:(1)接口/标准(2)接口使用者(3)接口实现者
先有接口的使用者,后有接口的实现者。
intreface Comparable { ... }
对象数组排序使用Java已知的接口/标准
java.util.Arrays.sort(对象数组);
接口使用者,在工具类中成员方法传参形式调用(接口回调)
class 类名 implements Comparable<类名> { @Override public int compareTo(类名 o) { /* 参考JDK文档 */ }}
接口实现者,在实现类中编写对应覆盖方法逻辑(方法覆盖)
测试类 main( ) 中调用测试验证
对象数组排序
接口回调【重要】
接口【重要】
面向对象(OOP)
概念:在一个类的内部再定义一个完整的类。
class Outer { class Inner { } }
语法:
编译:Outer$Inner.class 和 Outer.class
* 编译之后可生成独立的字节码文件* 内部类可直接访问外部类的私有成员,而不破坏封装* 可为外部类提供必要的内部功能组件
特点:
内部类
概念:在类的内部定义,与实例变量、实例方法同级别的类。属于外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象
// 定义语法同 内部类// 创建内部类对象Outer out = new Outer();Inner in = out.new Inner(); // 特殊:不具普适性// 成员内部类访问外部类的重名属性Outer.this.属性名
* 当外部类、内部类存在重名属性时,会优先访问内部类属性。* 成员内部类不能定义静态成员
成员内部类
概念:不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员
static 内部类 { }
* 只能直接访问外部类的静态成员(势力成员需实例化外部类对象)
静态内部类
概念:定义在外部类的成员方法中,作用范围和创建对象范围仅限于当前方法
class Outer { public void m( ) { class Inner { } }}
* 不能有静态成员(属性/方法)* 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final* 隐藏类的信息,限制类的使用范围
局部内部类
概念:没有类名的局部内部类(一切特征都与局部内部类相同)
class Outer { public OutInterface m ( ) { return new OutInterfaceb style=\
* 必须继承一个父类或者实现一个接口* 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象* 使用场景:① 显式继承父类时 ② 实现接口时* 优点:可以减少代码量,书写的思路流畅* 缺点:可读性较差
匿名内部类
* 基本数据类型所对应的引用数据类型(8种)。* Object可统一所有数据,包装类的默认值是null。* 包装类中实际上就是持有了一个基本类型的数据,作为数据的存储空间(Byte中有一个byte的value属性),还提供了常用的转型方法,以及常量。既可以存储值,又具备了一系列功能。* 包装类型中提供了若干转型的方法,可以让自身类型与其他包装类型、基本类型、字符串相互之间进行转换。
8种包装类:Byte / Short / Integer / Long / Float / Double / Boolean / Character
① xxxValue( )成员转型方法,java.lang.Number 父类为所有子类分别提供了6种对应类型互相转型的方法,将自身类型转换成其他数字型;
② parseXxxx(String s)静态转型方法,服务7种包装类型(除了Character包装类型都可以通过String构建);
③ valueOf(基本类型)、valueOf(字符串类型)静态转型方法,服务8种包装类型;
④ JDK5之后,赋值时提供自动装箱、拆箱: Byte b4 = 40; // 【自动装箱】将基本类型直接赋值给包装类型,调用valueOf(short s) byte b5 = b4; // 【自动拆箱】将包装类型引用赋值给基本类型(赋的是值),调用byteValue()返回基本类型
⑤ Java预先创建了256个常用的整数包装类型对象(-128~127的常数),在实际应用当中,对已创建的对象进行复用,节约内存效果明显。
【注意】使用字符串构建包装类型对象时,要保证类型的兼容,否则产生 NumberFormatException 异常。
转型方法
包装类
简介:超类、基类,所有类的直接或间接父类,位于继承树的最高层
* 任何类,如果没有书写extends显式继承某个类,都默认继承Object类* Object类中所定义的方法,是所有对象都具备的方法* Object类可以存储任何对象:作为参数,可接收任何对象;作为返回值,可返回任何对象。
返回引用中存储的实际对象类型。应用:通常用于判断两个引用中实际存储对象类型是否一致。
getClass().getName()
返回该对象的字符串表示(表现形式)。可以根据程序需求覆盖该方法,如展示对象各个属性值。特点:* 对象中属性的表现形式,常用于展示对象的各个属性。
toString()
返回该对象的十六进制的哈希码值(对象在内存中的数字型名字)。哈希算法根据对象的地址或者字符串或者数字计算出来的int类型的数值。哈希码并不唯一,可保证相同对象返回相同的哈希码,尽量保证不同对象返回不同的哈希码值。
hashCode()
判断引用地址是否相同
判断引用地址是否为空
确认对象类型是否一致
转型 - 向下转型拆箱
基本数据类型:==
字符串类型:str1.equals(str2)
比较对象中的实际内容
重写覆盖父类Object.equals()方法五步走
equals()
protected void finalize() throws Throwable { }
当对象被判定为辣鸡对象时,由JVM自动调用此方法,用以标记辣鸡对象,进入回收队列。辣鸡对象:没有有效引用只想此对象时,为辣鸡对象。垃圾回收:由GC销毁辣鸡对象,释放数据存储空间。自动回收机制:JVM的内存耗尽,一次性回收所有辣鸡对象。手动回收机制:使用System.gc( );通知JVM触发垃圾回收。
面试题:final finalize finally* final 修饰词,类不可继承/方法不可覆盖/基本类型值不能修改/引用类型地址不可修改* finalize 方法,JVM自动调用,标记辣鸡对象进入回收队列;手动调用,使用System.gc()方法触发* finally 关键字,作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。
finalize()
方法:
Object类
* 字符串是常量,创建后不可改变;* 字符串字面值存储在字符串池中,可以共享;
String s = \"Hello\"; // 产生1个对象,字符串池中存储(方法区常量池中字符串池)String s = new String(\"Hello\"); // 产生2个对象,堆、方法区常量池中各存储一个
s.charAt(0);
1.根据下标获取字符
s.contains(\"llo\");
2.判断是否包含子字符串
s.toCharArray();
3.将字符串转换为数组
s.indexOf(\"o\");
4. 查找子字符串在字符串中第一次出现的位置,不存在返回-1
s.lastIndexOf(\"ld\");
5. 查找子字符串在字符串中最后一次出现的索引,不存在返回-1
str.isEmpty()
6. 判断字符串是否为空
s.length()
7. 返回字符串长度
s2.trim()
8. 去掉字符串前后空格
hi.toUpperCase();
hi.toLowerCase();
9. 大小写转换 - 返回字符串副本,不会修改原字符串
upper.equalsIgnoreCase(lower)
10. 忽略大小写比较
filename.endsWith(\".java\");
11. 判断是否以某个字符串结尾
s.replace(\"Hello\
12. 替换字符串中的字符 - 返回字符串副本,不会修改源字符串
text.split(\",\");
13. 字符串分割,返回字符串数组
text.substring(8);
14. 从指定下标位置到结尾,获取子字符串,通常嵌套使用
方法
可变长字符串,JDK5.0提供,运行效率快、线程不安全。
StringBuilder
可变长字符串,JDK1.0提供,运行效率慢、线程安全。
StringBuffer
可变长字符串
String类
位置:java.math包中作用:精确计算浮点数创建:BigDecimal bd = new BigDecimal(\"1.0\");
BigDecimal add(BigDecimal db) //加BigDecimal subtract(BigDecimal bd)//减BigDecimal multiply(BigDecimal bd)//乘BigDecimal divide(BigDecimal db) //除
BigDecimal类
常类方法
概念:对象的容器,存储对象的对象,绝大多数情况下可替代数组。
特点:容器的工具类,定义了多个对象进行操作的常用方法。
位置:java.util.*
集合
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致。
1. 编译时即可检查,而非运行时抛出异常;2. 访问时,不必类型转换(拆箱);3. 不同泛型之间引用不能相互赋值,泛型不存在多态。
* font color=\"#f15a23\
<T>
* <?> 代表任意通配泛型* <? extends FatherClass> 泛型类型?必须是FatherClass的子类* <? extends MyInterface> 泛型类型?必须是MyInterface的实现类* <? super SubClass> 泛型类型?必须是SubClass类或SubClass的父类* <? extends MyInterface<? extends T>> 泛型类型?必须是MyInterface的实现类,且接口又指定了泛型(必须T类型的子类)* <T extends MyInterface<? super T>> 要求T所代表的类型必须实现MyInterface接口,同时,接口泛型必须是T类型或T的父类
<?>
* 类:创建对象时,为类所定义的泛型,进行参数化赋值\t* 接口:实现接口时,为接口所定义的泛型,进行参数化赋值
普通泛型
* 定义在方法的返回值类型前:<T>/<T extends Object>/<T extends Comparable<T>>/<T extends Comparable<? super T>>,可使用&多接口 * 定义在方法的形参列表当中:<?>/<? extends Object>/<? super SubClass>,不可使用&
静态泛型
高级
泛型集合及用法
概念:集合工具类,定义了除了存储以外的集合常用方法。
public static void sort(List<?> list) // 排序,要求:必须实现Comparable接口,必须可与自身类型比,以及父类类型比public static void reverse(List<?> list) // 反转,倒置元素public static void shuffle(List<?> list) // 随机重置顺序(洗牌)
Collections工具类
泛型集合与工具类
概念:代表该体系结构的根接口,代表一组对象,称为“集合”;每个对象都是该集合的“元素”
特点:代表一组任意类型的对象,无序、无下标。(Collection为父接口)
boolean add(Object obj) // 添加一个对象boolean addAll(Collection c) // 将一个集合中的所有对象添加到此集合中void clear() // 清空此集合中的所有对象boolean contains(Object o) // 检查次集合中是否包含o对象boolean equals(Object o) // 比较此集合是否指定对象相等boolean isEmpty() // 判断此集合是否为空boolean remove(Object o) // 在此集合中移除o对象int size() // 返回此集合中的元素个数Object[] toArray() // 将此集合转换成数组
方法:参考jdk1.8-API文档
Collection体系集合
继承:父接口Collection
特点:有序、有下标、元素可重复
方法:继承了父接口Collection提供的共性方法,同时定义了一些独有的与下标相关的操作方法
特点:\t1. 数组结构实现,查询快、增删慢;\t2. JDK1.2版本,运行效率快、线程不安全;
场景:注册(1次) -> 查询(n次)
注意:* JDK7之前,无参构造方法实际创建长度为 10 的Object数组,用还是不用,数组就在那里,爱用不用(占了内存)* JDK8之后,无参构造方法实际创建长度为 0 的Object数组,首次add元素时,才执行数组扩容操作,然后真正向数组中插入数据(Lazy懒),用的时候创建或加载,有效降低无用内存的占用。
ArrayList类(数组)【重点】
特点:1. 数组结构实现,查询快、增删慢;\t2. JDK1.0版本,运行效率慢、线程安全。
Vector类(数组、线程同步)
特点:\t1. 链表结构实现,增删快,查询慢;
LinkedList类(链表)
ArrayList:必须开辟连续空间,查询快,增删慢。运行快,线程不安全。Vector:必须开辟连续空间,查询快,增删慢。运行慢,线程安全。LinkedList:无需开辟连续空间,查询慢,增删快。
对比
实现类
List接口与实现类
1)无序、无下标、元素不可重复(当插入新元素时,如果新元素与已有元素进行equals比较,结果为true时,则拒绝新元素插入)2)set接口并没有提供自己独有的方法,均是继承Collection的方法
不同:对象一定不同(add成功)
true:对象一定相同(add失败)
true:内容相同(add失败)
false:内容不同(add成功)
false:equals( )内容比较
this==o地址比较
相同:对象不一定不同
hashCode( )比较
去重逻辑
特点:* 基于HashCode实现元素不重复 - 无序* 当存入元素的哈希码相同时,会调用equals确认,结果为true,则拒绝后者加入* 无参构建初始容量为16(负载因子0.75,即+75%容量扩容)* 底层使用的HashMap类,即将所有需要存储的值,通过HashMap去重存入* 先判断hashCode是否相同,再==比较地址是否相同,再equals内容是否相同
HashSet类(HashCode-无序不重复)【重点】
特点:* 继承自HashSet,又基于LinkedHashMap来实现的* 底层使用LinkedHashMap(链表结构)存储,节点形式独立存储数据, 并可以指向下一个节点,通过顺序访问节点,可保留元素的插入顺序 - 插入顺序* 所有方法与HashSet相同,用法也一模一样
LinkedHashSet类(记录插入顺序)
特点:* 基于排列顺序实现元素不重复 - 自动排序* 实现了SortedSet接口,对所有插入集合的元素自动排序* 元素对象的类型必须实现Comparable接口,指定排序规则(Integer/String类默认实现), 通过重写CompareTo方法才能使用,以确定是否为重复元素
TreeSet类(二叉树-自动排序)
方式一:遍历加入到List中使用Collections.sort(list)排序;
方式二:使用TreeSet的构造创建一个TreeSet对象实现自动排序;
Set接口与实现类
* 用于存储任意键值对(Key:Value)* 键:无序、无下标、不允许重复(唯一)* 值:无序、无下标、允许重复
接口方法
SortedMap接口
子接口
特点:* JDK1.2版本,线程不安全,运行效率快;允许用null作为key或是value* 无参构建初始容量为16(负载因子0.75,即+75%容量扩容)* HashMap算法:拿到任何一个对象后,通过hash(key)做运算,key>>>16(除16),只可能得到0-15之间的一个数组,作为插入数组的下标。
HashMap类(效率快+允许null)重点
特点:HashMap的一个子类,保存了记录的插入顺序,也可在构造时带参数,按照访问次序排序。
LinkedHashMap类(记录插入顺序)
特点:JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value
Hashtable类(线程安全)
特点:Hashtable的子类,要求key和value都是String,通常用于配置文件的读取。
Properties类(配置文件读取)
特点:实现了SortedMap接口(Map的子接口),可以对key自动排序。
TreeMap类(自动排序)
Map接口与实现类
for (数据类型 变量名 : 容器名称) { //可遍历集合或数组(常用在无序集合上)}
foreach循环
集合框架
概念:程序在运行过程中出现的特殊情况必要性:任何程序都可能存在大量的位置问题、错误;如果不对这些问题进行正确处理,则可能导致程序的中断,造成不必要的损失。
异常的概念
位置:java.lang.Throwable;
Error类(不可处理)
RuntimeException类
CheckedException类
Exception类
Throwable类
除了RuntimeException类与其子类,以及错误Error类,其他的都是检查异常。
异常的分类
当程序运行时遇到不符合规范的代码或结果时,会产生异常;
自动
1.创建异常对象
2.结合throw关键字,抛出异常
用在【方法内】
throw new 异常类型(\"实际参数\");
手动
异常的产生
概念:按照方法的调用链反向传递,如始终没有处理异常,最终会由JVM进行默认异常处理(打印堆栈跟踪信息)
* 受查异常:throws 声明对应的方法可能存在异常,声明修饰在方法参数列表后端【方法上】,可以用\
异常的传递
try-catchtry-catch-catchtry-catch-finallytry-catch-catch-...-finallytry-finally(不常见)
try { // 可能出现异常的代码} font color=\"#f15a23\
异常的处理
必须继承自Exception或Exception的子类,常用RuntimeException
必须提供无参构造方法;
必须提供String message的1参构造方法,super(message);
声明:①需要声明该异常,传递出去; ②声明的异常类型与抛出的异常类型一致
抛出:throw new 自定义异常类名(异常提示字符串);
Exception受查异常
声明:可声明/可不声明
RuntimeException运行时异常
抛出
System.err.println(e.getMessage());
打印突出显示的错误信息(serr)
自定义异常
* 0. 方法名、参数列表、返回值类型必须和父类相同(覆盖的基本要求)* 1. 父类中方法没有声明异常,则子类中也不可以声明异常* 2. 父类中方法声明了异常,子类重写后可声明也可不声明,如果声明则必须是与其相同或其异常子类* 3. 子类可以声明比父类更多的异常,但必须小于父类的异常类(即异常子类) - 即子类不能抛出比父类更多、更宽的异常
异常方法覆盖
异常处理
进程:程序静止的,真正运行时的程序,才被称为进程。(宏观并行,微观串行)线程:轻量级进程(Light Weight Process),程序中的一个顺序控制流程,同时也是CPU的基本调度单位,进程由1个或多个线程组成,彼此间完成不同的工作,交替执行,称为多线程。
迅雷,是一个进程,当中的多个不同的下载任务即多个线程。JVM,Java虚拟机是一个进程(单进程),当中默认包含主线程(main),可通过代码创建多个独立线程,与main并发执行。
eg
获取win电脑当前CPU核心数命令:① win+R ② wmic ③ cpu get NumberOfCores
扩展
线程概念
操作系统会为每个线程分配执行时间
① CPU时间片
* 堆空间:存储线程需使用的对象,多个线程可以共享堆中的对象;* 栈空间:存储线程需使用的局部变量,每个线程都拥有独立的栈;
② 运行数据
③ 线程逻辑代码
线程组成
① 继承Thread类② 覆盖run()方法③ 创建子类对象④ 调用start()方法 - 启动线程
步骤
MyThread t1 = new MyThread();t1.start();
示例
继承父类
① 实现Runnable接口② 覆盖run()方法③ 创建实现类对象④ 创建线程对象(Thread父类有参构造)⑤ 调用start()方法 - 启动线程
Thread t2 = new Thread(new MyRunnable());t1.start();
* 只是将当前类变成线程任务类,本身不是个线程* run任务是可以多线程对象共享(任务复用)* 更灵活(还可以继承其他的类 + 实现其他的接口能力)
实现接口【推荐】
public interface Callable<V> { public V call() throws Exception;}
* JDK5加入,与Runnable接口类似,实现之后代表一个线程任务;* Callable具有泛型返回值,可以声明异常。
Callable接口
public interface Future<V>
* 异步接收ExecutorService.submit()所返回的状态结果,当中包含了call()的返回值;* 成员方法: V get()以阻塞形式等待Future中的异步处理结果(font color=\"#c41230\
Future接口
并发计算
线程创建
初始New → 运行RUNNABLE → 等待WAITING(限期/无限期) → 阻塞BLOCKED → 终止TERMINATED
* JDK5之后,READY+RUNNING = RUNNABLE(运行态)
所有线程状态图示
线程状态(6)
Thread.currentThread().getId() // 返回当前线程标识符(线程ID)
Thread.currentThread().getName() // 返回当前线程对象名(线程名)
基本
public static void sleep(long millis)// 当前线程主动休眠millis毫秒
* 静态方法,直接类名调用Thread.sleep(1000);* 使当前线程进入阻塞状态,在指定时间内不会执行,不推荐使用;* sleep()被调用时该线程不会释放它所拥有的锁;* 该方法会抛出InterruptedException中断异常;
休眠
public static void yield( )// 当前线程主动放弃时间片,回到就绪状态,竞争下一次时间片
* 静态方法,直接类名调用Thread.yield();* yield只是使当前线程重新回到就绪状态,所以执行yield的线程有可能在进入到就绪状态后马上又被执行。 yield只能使同优先级或更高优先级的线程有执行的机会。* 可能对调试或测试有用,可能有助于根据竞态条件重现错误。 在设计并发控制结构(例如java.util.concurrent.locks包中的并行控制结构)时也可能有用。
放弃
public final void join( )// 允许其他的线程加入到当前线程中来(插队),等待join的线程终止
* 成员方法/最终方法,不能被覆盖;* 如果某个线程在另一个线程t上调用t.join(),此线程将被挂起,直到目标线程t结束才恢复;* 能够释放当前线程锁,其他线程可以调用次线程中的同步方法;* 该方法会抛出InterruptedException中断异常;
结合
线程方法
当多线程并发访问临界资源时,如果破坏原子操作,可能会造成数据不一致;* 临界资源:共享资源(同一对象),一次仅允许一个线程使用,才可以保证正确性;* 原子操作:不可分割的多步操作,被视作一个整体,其顺序和步骤不可打乱或缺省;
线程为什么不安全?
synchronized (临界资源对象) { // 对临界资源加锁 //代码(原子操作)}
* 每个对象都有一个互斥锁标记,用来分配给线程的;* 只有拥有对象互斥锁标记的线程,才能进入对该对象加锁的同步代码块;* 线程退出同步代码块时,会释放相应的互斥锁标记;
方式:同步代码块
synchronized 返回值类型 方法名称(形参列表) { // 对当前对象(this)加锁 // 代码(原子操作)}
* 只有拥有对象互斥锁标记(eg:Object lock;)的线程,才能进入该对象加锁的同步方法中;* 线程退出同步方法时,会释放相应的互斥锁标记。
方式:同步方法
只有在调用包含同步代码块的方法,或者同步方法时,才需要对象的锁标记
如果在调用不包含同步代码块的方法,或普通方法时,则不需要锁标记,可直接调用
同步规则
① StringBuilder② Vector③ Hashtable
公开成员方法均为synchronized修饰的同步方法。
已知线程安全的类
同步方式
Object类的成员方法:public final void wait()public final void wait(long timeout)
说明:必须在对共享临界资源(obj)加锁的同步代码块/同步方法中。在一个线程中调用obj.wait()时,此线程会释放其拥有的所有锁标记,同时此线程阻塞在obj的等待队列中。即当前线程释放锁,进入等待队列(无限期等待 - 除非收到通知)。
阻塞/等待
Object类的成员方法:public final void notify()public final void notifyAll()
说明:必须在对共享临界资源(obj)加锁的同步代码块/同步方法中。从obj的waiting中释放一个或全部线程,对自身没有任何影响。
通知/唤醒
线程通信
* 当第一个线程拥有A对象锁标记,并等待B对象锁标记,同时第二个线程拥有B对象锁标记,并等待A对象锁标记,产生死锁。* 一个线程可以同时拥有多个对象的锁标记,当线程阻塞时,不会释放已经拥有的锁标记,由此可能造成死锁。
死锁
若干个生产者在生产产品,这些产品将提供给若干个消费者去消费。为了使生产者和消费者能并发执行,在两者之间设置一个能存储多个产品的缓冲区:生产者将生产的产品放入缓冲区,消费者从缓冲区中取走产品进行消费。显然生产者和消费者之间必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个满的缓冲区中放入产品。
生产者与消费者
经典问题
线程同步
多线程
问题:* 线程是宝贵的内存资源、单个线程约占1MB的空间,过多分配易造成内存溢出;* 频繁的创建及销毁会增加虚拟机回收频率、资源开销,造成程序性能下降。
线程池:* 线程容器,可设定线程分配的数量上限;* 将预先创建的线程对象存入池中,并重用线程池中的线程对象;* 避免频繁的创建和销毁。
概念
将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程。
原理
位置:java.util.concurrent;
接口,线程池的顶级接口
Executor接口
Executor的子接口,线程池接口
public interface ExecutorService extends Executor
Future<?> submit(Runnable task)// 该成员方法用于提交任务代码进而自动由线程池创建线程并运行
ExecutorService接口
工厂/工具类,通过此类可以获得一个线程池
① 通过 Executors.newFixedThreadPool(int nThreads) 获取固定数量的线程池 @return ExecutorService 接口类型引用
② 通过 Executors.newCachedThreadPool()获得动态数量的线程池,如不够则创建新的,没有上限 @return ExecutorService 接口类型引用
Executors类
线程池(接口/类)
位置:java.util.concurrent.locks;
public interface Lock {}
特点:* 提供更多实用性方法,功能更强大、性能更优越。
方法:① void lock() // 获取锁,如锁被占用,则等待② boolean trylock() // 尝试获取锁(成功true,失败false,不阻塞)③ void unlock() // 释放锁
Lock接口
public class font color=\"#f15a23\
特点:* Lock接口的实现类,与synchronized一样具有互斥锁功能。注意:1)使用Lock,需要显式的获取锁和释放锁;2)为了避免拿到锁的线程在运行期间出现异常,导致程序终止没有释放锁!应用try-finally来保证无论是否出现异常,最终必须释放锁;3)ReentrantLock为重入锁,避免递归,如果必须递归,必须正确控制退出条件。(此锁支持同一线程的2147483647个递归锁的最大值。试图在Error超过这个限制的结果将从锁定的方法。)
使用:①创建重入锁对象;②显式开启锁;③显式释放锁;④释放锁必须放在finally代码块中
ReentrantLock类(重入锁/递归锁)
public class ReentrantReadWriteLock extends Object implements font color=\"#c41230\
特点:* 一种支持一写多读的同步锁,读写分离,可分别分配读锁、写锁;* 支持多次分配读锁,使多个读操作可以并发执行(写锁同步,读锁异步)。
互斥规则:① 写-写:互斥,阻塞;-- 独占② 读-写:互斥,读阻塞写、写阻塞读;③ 读-读:不互斥、不阻塞;* 在读操作远远高于写操作的环境下,可在保证线程安全的情况下,极大提高运行效率。
ReentrantReadWriteLock类(读写锁)
互斥锁(接口/类)
位置:java.util.Collections;
public static <T> Collection<T> synchronizedCollection(Collection<T> c)public static <T> List<T> synchronizedList(List<T> list)public static <T> Set<T> font color=\"#f15a23\
特点:* 都是返回对应泛型集合类型的方法;* 都是静态方法,通过Collections直接调用;* 都是在静态方法中new了一个synchronized同步的静态内部类;* 实际使用时的成员方法与原集合没有区别;* JDK1.2提供,接口统一、维护性高,但性能没有提升,均以synchonized实现。
特点:* 符合List特点:有序、有下标、元素可重复* 线程安全的ArrayList,加强版读写分离;* 写有锁,读无锁,读写之间不阻塞,优于读写锁;* 写入时,先copy一个容器副本、再添加新元素,最后替换引用;* 使用方式与ArrayList无异。
List<String> alist = new CopyOnWriteArrayList<String>();
CopyOnWriteArrayList类(线程安全的List)
public class CopyOnWriteArraySet<E>extends AbstractSet<E>implements Serializable
说明:* 符合Set特点:无序、无下标、元素不重复* 线程安全的Set,底层使用CopyOnWriteArrayList实现;* 唯一不同在于:使用addIfAbsent()添加元素(查重),会遍历数组;* 如存在元素,则不添加(扔掉副本)。
Set<String> aset = new CopyOnWriteArraySet<String>();
CopyOnWriteArraySet类(线程安全的Set)
特点:* 初识容量默认为16段(Segment),使用分段锁设计;* 不对整个Map加锁,而是为每个Segment加锁(16把锁);* 当多个对象存入同一个Segment时,才需要互斥;* 最理想状态位16个对象分别存入16个Segment,并行线程数量16个;* 使用方式与HashMap无异。// JDK1.7: 分段锁设计 Segment// JDK1.8: CAS交换算法(CAS比较和交换) + 同步锁(锁的是表头)
ConcurrentHashMap类(线程安全的Map)
类
线程安全(方法/类)
位置:java.util.Queue;
public interface Queue<E> extends Collection<E>
* Collection的子接口,表示队列FIFO(First In First Out)
常用方法:(1)抛出异常boolean add(E e) // 顺序添加1个元素(到达上限后,再添加则会抛出异常)E remove() // 获得第1个元素并移除(如果队列没有元素时,则抛异常)E element() // 获得第1个元素但不移除(如果队列没有元素时,则抛异常)(2)返回特殊值【推荐使用】boolean offer(E e) // 顺序添加1个元素(到达上限后,再添加则会返回false)E poll() // 获得第1个元素并移除(如果队列没有元素时,则返回null)E keep() // 获得第一个元素但不移除(如果队列没有元素时,则返回null)
Queue接口
说明:* 线程安全、可高效读写的队列,高并发下性能最好的队列;* 无锁、font color=\"#c41230\
ConcurrentLinkedQueue(线程安全的队列Queue)
public interface BlockingQueue<E> extends Queue<E>
常用方法:void put(E e) // 将指定元素插入此队列中,如果没有可用空间,则死等E take() // 获取并移除此队列头部元素,如果没有可用元素,则死等说明:* Queue的子接口,阻塞的队列,增加了两个线程状态为无限期等待的方法* 可用于解决生产者、消费者问题
BlockingQueue接口(阻塞队列)
* 数组结构实现,有界队列。手工固定上限
BlockingQueue<String> abq = new ArrayBlockingQueue<String>(3);
ArrayBlockingQueue类(有界阻塞队列)
* 链表结构实现,无界队列。默认上限Integer.MAX_VALUE
BlockingQueue<String> lbq = new LinkedBlockingQueue<String>();
LinkedBlockingQueue类(无界阻塞队列)
队列(FIFO)
比较与交换(compare and swap),是一种无锁算法,即不使用锁的情况下实现多线程之间的变量同步。也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三个操作数:需要读写的内存变量V、进行比较的值(预期值)E、拟写入的新值N。当且仅当V的值等于E时,CAS通过原子方式用新值N来更新V值,否则不会执行任何操作(比较和替换是一个原子操作)。一般情况下是一个自旋转操作,即不断的重试。
CAS比较交换算法
线程池
字节流&字符流汇总图
内存与存储设备之间传输数据的通道。
流的概念
按方向:【重点】相对于程序操作的内存,进入内存为输入,从内存出去为输出。① 输入流:将[存储设备]中的内容输入到[内存]中;② 输出流:将[内存]中的内容输出到[存储设备]中。
按单位:① 字节流:以字节为单位,可以读写所有数据;② 字符流:以字符为单位,只能读写文本数据。
按功能:① 节点流:具有实际传输数据的读写功能;② 过滤流:在节点流的基础之上增强功能。
流的分类
InputStream 字节输入流
OutputStream 字节输出流
抽象父类
FileInputStream 类
FileOutputStream 类
子类:字节节点流
BufferedInputStream 类
BufferedOutputStream 类
子类:字节过滤流(缓冲流)
ObjectInputStream 类
ObjectOutputStream 类
* 增强了缓冲区功能* 增强了读写8种基本数据类型和字符串功能* 增强了读写对象的功能: 1) Object readObject() // 从流中读取一个对象 2) void writeObject(Object obj) // 向流中写入一个对象
对象序列化:使用流传输对象的过程称为序列化、反序列化。1)必须实现 Serializable 接口;2)对象自身和类中属性都必须序列化 (即实现Serializable这个空接口即可,基本数据类型数组可不序列化,引用数据类型必须序列化);3)transient 关键字修饰为临时属性,不参与序列化;4)对象的默认序列化机制写入对象的类、类签名和所有非瞬态和非静态字段的值, 因此属性不能使用static修饰,否则取的都是最后一次的值(static属于类本身,会影响序列化)。5)序列化对象流读取到文件尾,会抛出 EOFException 异常 - 捕获后停止读取文件。
子类:字节过滤流(对象流)
字节流
Demo_copyPic
Reader 字符输入类
Writer 字符输出类
BufferedReader 字符输入过滤流
BufferedWriter 字符输出过滤流
PrintWriter 字符输出过滤流(写入后换行)【常用】
子类:字符过滤流
InputStreamReader 桥转换输入流
OutputStreamWriter 桥转换输出流
* 可将字节流转换为字符流;(为的就是可以设置字符编码方式)* 可指定字符的编码方式;
字节流转换字符流步骤:①创建字节流 Output/InputStream②创建过滤流,设置字符编码集(按需) OutputStreamWriter/InputStreamReader③封装过滤流 PrintWriter/BufferedReader④读写数据 write/read⑤关闭流 close
一行套娃:PrintWriter pw1 = new PrintWriter(new OutputStreamWriter(new FileOutputStream(\"files\\\\convert.txt\
子类:桥转换流
FileReader 字符节点输入流
FileWriter 字符节点输出流
子类:字符节点输入输出流
字符流
* 文件和目录路径名的抽象表示形式。* 没有无参构造。* 具体方法都很常用,查询jdk1.8 API文档。
File 类
* 当调用File类中的listFiles()方法时,支持传入FileFilter接口的实现类对象, 对获取文件进行过滤,只有满足条件的文件才可出现在listFiles()的返回值中。——接口回调
FileFilter 接口
文件操作
Server Demo
Client Demo
简单FTP下载功能核心IO逻辑
IO框架
应用层
表示层
会话层
传输层
网络层
数据链路层
物理层
网络接口层
TCP/IP四层模型
回环地址 127.0.0.1,指本机,一般用于测试。
查看IP命令:ipconfig
测试IP命令:ping D.D.D.D
IP协议
程序的唯一标识。
公认端口 0-1023
注册端口 1024-49151
动态或私有端口 49152-65535
端口分类
MySql:3306
Oracle:1521
Tomcat:8080
SMTP:25
Web服务器:80
FTP服务器:21
常用端口
Port
标识花联网协议(IP)地址对象,封装了与该IP地址对象相关的所有信息,并提供常用方法
无法直接创建对象,构造方法私有化,需要通过getxxx方法获得
Inet4Address
Inet6Address
InetAddress
创建客户端的类
Socket
创建服务器的类
ServerSocket
① 建立通信连接(会话)* 创建ServerSocket,指定端口号;* 调用accept等待客户端接入;② 客户端请求服务器* 创建Socket,指定服务器IP + 端口号;* 使用字节输出流,发送请求数据给服务器;* 使用字节输入流,接收响应数据到客户端(等待);③ 服务器响应客户端* 使用字节输入流,接收请求数据到服务器(等待);* 使用字节输出流,发送响应数据到客户端。
开发步骤
网络编程
常用方法见JDK1.8-API文档
OSI七层模型
概念:程序运行时动态获取信息以及动态调用对象方法的功能为Java语言的反射机制。
String getName() 返回由 类对象表示的实体(类,接口,数组类,原始类型或空白)的名称,作为 String 。static Class<?> forName(String className) 获取类对象名Package getPackage() 获取类对象的包名Class<? super T> getSuperclass() 获取父类的类对象名Class<?>[] getInterfaces() 获取接口的类对象名Constructor<?>[] getConstructors() 获取构造方法Class<?>[] getParameterTypes() 获取方法(构造/成员)的参数类型列表Field[] getFields() 获取属性(自身+父类的所有public公开属性)Field[] getDeclaredFields() 获取属性(自身所有的属性)Method[] getMethods() 获取方法(自身+父类单继承叠加的所有public公开方法)Method[] getDeclaredMethods() 获取方法(自身所有的方法)T newInstance() 创建由此类对象表示的类的新实例(此类对象必须有无参构造)
Class类
Field类
public Method font color=\"#f15a23\
Method类
Constructor类
类全名:Class.forName(\"全限定名\");
编译期:类名.class;
运行时:对象名.getClass( );
创建类的实例对象:T newInstance( );
获取 Class 对象并创建实例对象
Class<?> clazz = Class.forName(\"com.demo.reflect.User\");// 获取无参构造,创建对象Constructor<?> c1 = clazz.getConstructor();User u1 = (User) c1.newInstance();// 获取有参构造,创建对象 Constructor<?> c2 = clazz.font color=\"#f15a23\
操作 构造方法 对象
Class<?> clazz = Class.forName(\"com.demo.reflect.User\");User user = (User) clazz.newInstance();// 获取私有属性,设置属性的值 Field idField = clazz.getDeclaredField(\"id\");idField.setAccessible(true); // 忽略访问修饰检查(突破封装)idField.font color=\"#f15a23\
操作 成员变量 对象
Class<?> clazz = Class.forName(\"com.demo.reflect.User\");User user = (User) clazz.newInstance();// 获取私有方法,调用执行该方法Method setName = clazz.getMethod(\"setName\
操作 成员方法 对象
反射执行任意实体类对象的 set 方法:Demo
反射执行任意实体类对象的 get 方法:Demo
反射执行任意实体类对象的任意方法:Demo
读取配置文件反射创建任意实体对象:Demo
通用编程
// @param className 类的全限定名public static Object createInstance(String className) throws Exception { return Class.forName(className).newInstance( );}
结合多态:扩展性更强工厂模式:降低耦合度反射机制:去代码冗余
工厂模式
单例(singleton):只允许创建一个该类的对象。
天生线程安全(无锁)、类加载时创建(不用也创建,占用资源)
饿汉式
天生线程不安全(需同步锁、效率低)、使用时创建
懒汉式
天生线程安全(无锁)、使用时创建(静态内部类)
懒汉式(线程安全版)
单例模式
提供代理对象,增强方法功能。
步骤:① 自定义一个代理类(增强类)实现和被代理类(被增强类)相同的接口② 在代理类中声明被代理类的对象③ 在代理类的方法中使用被代理类调用方法
优点:增强被代理类的功能,可以控制被代理类的对象缺点:必须要重写被代理类接口的所有的方法(破坏单一职能原则,耦合性高)
静态代理设计模式
步骤:① 自定义一个装饰类(增强类)实现和被装饰类(被增强类)相同的接口② 在装饰类中声明被装饰类的引用③ 在装饰类的方法中使用被装饰类调用方法
优点:增强被代理类的功能,无法控制被代理类的对象缺点:必须要重写被装饰类接口的所有的方法(破坏单一职能原则,耦合性高)
装饰者设计模式
动态代理本质就是通过反射来生成的一个代理。在Java中 java.lang.reflect 包下提供了一个 Proxy 类和 InvocationHandler 接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理,有更强大的代理cglib,Proxy类中的方法创建动态代理对象。
步骤:——基于接口的方法增强① 编写一个代理类的接口② 实现一个真正的代理类,实现该接口③ 创建一个动态的代理类,实现 InvocationHandler 接口,并重写该 invoke() 方法④ 在测试类中调用 Proxy.newProxyInstance() 方法生成动态代理对象优化:③④可合并为匿名内部类实现。
优点:不需要重写接口中的所有方法,耦合度更低。
// ClassLoader loader: 被代理类对应的类加载器// Class<?>[] interfaces: 被代理类所实现的所有接口// InvocationHandler h: 一个用以增强代理类的处理器接口名 p = (接口强转) Proxy.font color=\"#f15a23\
// 匿名内部类对象 - 指定需要增强的方法UserDao np = (UserDao) Proxy.newProxyInstance( userDao.getClass().font color=\"#f15a23\
核心代码片段
④ Demo
③ Demo
② Demo
① Demo
动态代理设计模式
代理模式
// 1.实现和被装饰类相同的接口public class UserDaoWrapper implements UserDao { // 2.在装饰类中声明被装饰类的引用 private UserDao userDao; public UserDaoWrapper() { } public UserDaoWrapper(UserDao userDao) { this.userDao = userDao; } // 3.在装饰类的方法中使用被装饰类调用方法 @Override public void add() { System.out.println(\"权限校验\"); userDao.add(); System.out.println(\"日志记录\"); }}
// 1.实现和被代理类相同的接口public class UserDaoProxy implements UserDao { // 2.在代理类中声明被装饰类的引用 private UserDao userDao; public UserDaoProxy() { userDao = new UserDaoImpl(); } // 3.在代理类的方法中使用被代理类调用方法 @Override public void add() { System.out.println(\"权限校验\"); userDao.add(); System.out.println(\"日志记录\"); }}
设计模式
配置文件 + 工厂模式 + 反射 + 注解 + xml解析
反射-设计模式
① 使用 default 关键字就可以给接口增加一个非抽象的方法实现;
② 接口还可以存在 static 静态方法实现,使用 接口名.静态方法名 的形式直接调用;
* 包括声明 @FunctionalInterface 限制接口只有1个抽象方法时,也可以增加①或②。
* 一般不建议写实现。
接口中的实现方法
概念:允许把函数作为一个方法的参数,代码简洁紧凑(函数作为参数传递到方法中)
函数式接口 变量名 = font color=\"#f15a23\
* 形参列表的数据类型会自动推断* 如果形参列表为空,只需保留()* 如果形参列表只有1个参数,可以省略(),只要参数名字即可* 如果执行语句只有1句,且无返回值,{}可以省略* 若有返回值,仍想省略{},return也省略,必须保证执行语句为1句* Lambda表达式不会生成单独的内部类文件* Lambda表达式访问局部变量时,变量要修饰为final,如果没加会隐式自动添加* Lambda表达式只能用在函数式接口的使用场景中
概念:如果一个接口只有 1 个公开抽象方法,则该接口为函数式接口。
* 为了确保接口达到只有1个方法的要求,接口名上添加注解 @FunctionalInterface
位置:java.util.function
① Predicate<T>接口(断言、返回真假)
② Consumer<T>接口(消费、有去无回)
③ Supplier<T>接口(创造、无中生有)
④ font color=\"#f15a23\
https://simple.blog.csdn.net/article/details/105000639
4 个核心函数式接口
函数式接口
Lambda 表达式
Lambda表达式的一种简写形式。
如果Lambda表达式方法体中只是调用一个特定的已存在的方法,则可以使用方法引用。
① 对象::实例方法② 类::静态方法③ 类::实例方法④ 类::new
4 种使用形式
注意:调用的方法的参数列表与返回值类型,都与函数式接口中的方法参数列表与返回值类型一致。
方法引用 ::
支持顺序和并行聚合操作的一系列元素,是Java8中处理数组、集合的抽象概念。可以执行非常复杂的查找、过滤、映射等操作。
流(与I/O不同)
位置:java.util.stream
创建.中间操作....最终操作
* 中间操作可.多个
Stream<T> stream = 集合或数组.stream();
Stream<T> filter(Predicate<? super T> predicate)返回由与此给定谓词匹配的此流的元素组成的流。Stream<T> limit(long maxSize)返回由此流的元素组成的流,截短长度不能超过 maxSize 。Stream<T> distinct()返回由该流的不同元素(根据 Object.equals(Object) )组成的流。<R> Stream<R> font color=\"#f15a23\
中间操作
long count()返回流中的元素个数。void forEach(Consumer<? super T> action)对此流的每个元素执行遍历操作。boolean anyMatch(Predicate<? super T> predicate)或,流中是否有包含指定规则的元素boolean allMatch(Predicate<? super T> predicate)且,流中是否全部包含指定规则的元素boolean noneMatch(Predicate<? super T> predicate)非,流中是否都不包含指定规则的元素Optional<T> findFirst()返回流的第一个元素的Optional,如果流为空,则返回一个空的Optional 。Optional<T> findAny()返回流的任意一个随机元素的Optional,如果流为空,则返回一个空的Optional 。Optional<T> max(Comparator<? super T> comparator)根据提供的 Comparator 返回此流的最大元素。Optional<T> min(Comparator<? super T> comparator)根据提供的 Comparator 返回此流的最小元素。
最终操作
主要的API方法
.stream()
串行流
.parallelStream()
比串行流的效率更高
并行流
Stream 接口
Java8新特性
ArrayList
Vector
LinkedList
CopyOnWriteArrayList
List
HashSet
LinkedHashSet
TreeSet
SortedSet
CopyOnWriteArraySet
AbstractSet
Set
ConcurrentLinkedQueue
ArrayBlockingQueue
LinkedBlockingQueue
AbstractQueue抽象类b style=\
Queue
Colleciton
HashMap
LinkedHashMap
Properties
Hashtable
TreeMap
ConcurrentHashMap
AbstractMap
Map
public static <T extends Comparable<? super T>> void sort(List<T> list)public static void reverse(List<?> list)public static void shuffle(List<?> list)
同步
其他诸如检查、判空、最大小值、交换等... API文档。
Collections
集合体系
FileOutputStream (fn)
BufferedOutputStream (fos)
FilterOutputStream
ObjectOutputStream (fos)
OutputStream
write时对象类、属性(引用数据类型)必须:实现Serializable接口以序列化
FileInputStream (fn)
BufferedInputStream (fis)
FilterInputStream
ObjectInputStream (fis)
InputStream
字节流体系
FileWriter (fn)
OutputStreamWriter (fos)
BufferedWriter
PrintWriter (osw)
Writer
FileReader (fn)
InputStreamReader (fis)
BufferedReader (isr)
Reader
字符流体系
关系结构数据库:Oracle、DB2、MySQL、SQL Server。以表格(Table)存储,多表间建立关联关系,通过分类、合并、连接、选取等运算实现访问。
DBMS,数据库管理系统。MySQL:免费、适合中小型企业(被Oracle收购)。在 WEB 应用方面,MySQL是最好的 RDBMS(关系数据库管理系统)应用软件之一。
官方网站:https://www.mysql.com/下载地址:https://dev.mysql.com/downloads/mysql/安装包名:mysql-installer-community-5.7.28.0.msi* MySQL57,即5.7版本应用较为广泛。
获取
https://simple.blog.csdn.net/article/details/105099985
详细安装步骤
安装
1. 创建MYSQL_HOME : C:\\Program Files\\MySQL\\MySQL Server 5.72. 追加Path:%MYSQL_HOME%\\bin;
Win
* 终端中输入cd ~ 进入目录,并检查.bash_profile是否存在,有则追加,无则创建* 创建文件 touch .bash_profile* 打开文件 open .bash_profile* 输入export PATH=${PATH}:/usr/local/mysql/bin 保存并退出终端
Mac
环境变量
C:\\ProgramData\\MySQL\\MySQL Server 5.7\\my.ini
客户端默认字符集,默认被注释,即遵循环境的字符集
default-character-set
服务器端默认字符集,默认被注释,即遵循环境的字符集
character-set-server
客户端和服务器端的端口号,默认 port=3306
port
MySQL默认存储引擎 INNODB
default-storage-engine
[mysql] # 第一处 line67default-character-set=utf8
[mysqld] # 第二处 line102character-set-server=utf8collation-server=utf8_general_ci
重启MySQL服务:win> net stop mysql57 && net start mysql57Linux$ service mysql restart
解决插入中文数据乱码或问号的问题
配置参数
win> net start mysql57
启动
旧版(mysql57可用):root可替换为其他用户名SET PASSWROD FOR root@localhost = PASSWORD('123456');新版:ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';
修改root密码
配置
快速、可靠并价格相宜的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设。* 使用 Navicate 需要会pj
Navicate
广泛的预定义工具和查询、友好的视觉界面、类似 Excel 的查询结果编辑界面。
SQLyog
IDEA开发工具集成。DataGrip是捷克公司的产品,需要付费。如果买了IDEA,DataGrip通用。
DataGrip
客户端工具
1.\t数据`查询`语言 `DQL`(Data Query Language):select、where、order by、group by、having2.\t数据`定义`语言 `DDL`(Data Definition Language):create、alter、drop3.\t数据`操作`语言 `DML`(Data Manipulation Language):insert、update、delete4.\t事务`处理`语言 `TPL`(Transaction Process Language):commit、rollback5.\t数据`控制`语言 `DCL`(Data Control Language):grant、revoke
SQL语言分类
SELECT 列名 FROM 表名;
运算 + - * / 没有 %(它现在是占位符)
列 AS '列别名'
DISTINCT 列名
基本查询
去重
SELECT 列名 FROM 表名 font color=\"#f15a23\
ASC 升序
DESC 降序
排序规则
排序查询
单列/多列排序
SELECT 列名 FROM 表名 WHERE 条件
等值判断 =
不等值判断 >、<、>=、<=、!=、<>(也是不等)
逻辑判断 font color=\"#f15a23\
包含两端边界两个值
小到大顺序不能颠倒
区间判断 BETWEEN ... AND ...
NULL值判断 font color=\"#f15a23\
枚举查询 font color=\"#f15a23\
_ 单个任意字符,模糊内容、精确长度
列名 LIKE 'S_'
% 0或多个任意字符0-n个
列名 LIKE 'S%'
模糊查询
CASE WHEN 条件1 THEN 结果1 WHEN 条件2 THEN 结果2 WHEN 条件3 THEN 结果3 ELSE 结果xEND AS '列别名'
对紧跟列名的操作,注意列名后的 逗号
分支结构查询
条件查询
SELECT 时间函数([参数列表]);
时间查询
SELECT 聚合函数(列名) FROM 表名;
COUNT(列) 总行数,忽略null值SUM(列) 所有行中单列结果的综合AVG(列) 平均值MAX(列) 最大值MIN(列) 最小值
聚合函数
SELECT 列名 FROM 表名 WHERE 条件 GROUP BY 分组依据列;
WHERE 条件 也可省略。
分组查询
SELECT 列名 FROM 表名 WHERE 条件 GROUP BY 分组列 HAVING 过滤规则;
过滤规则:定义对分组后的数据进行过滤,相当于一个新的条件。
分组过滤查询
SELECT 字符串函数([参数列表]);
* 注意:MySQL 中字符串下标是从 1 开始。
字符串查询
* 注意:LIMIT 的起始行是从 0 开始为第1 行。
【公式】第 i 页: font color=\"#f15a23\
限定查询
SELECT 列名 font color=\"#c41230\
执行顺序:⑤ SELECT 列名① FROM 表名② WHERE 条件 ③ GROUP BY 分组font color=\"#f15a23\
【查询总结】
SELECT 列名 FROM 表名 WHERE 条件 > (子查询结果值);
子查询结果:一行一列(1个值)
子查询结果作为条件判断
SELECT 列名 FROM 表名 WHERE 列名 IN(子查询结果列);
子查询结果:多行单列(1列值) - IN可替换为 ANY 或 ALL 关键字
子查询结果作为枚举查询条件
SELECT 列名 FROM (子查询结果表) AS 表别名;
子查询结果:多行多列(1张表)
子查询结果作为一张表
子查询
SELECT * FROM 表名 1 UNION SELECT * FROM 表名 2
去重合并
SELECT * FROM 表名1 UNION ALL SELECT * FROM 表名2
全部合并
列数必须相同,行内容向下追加。
合并查询
SELECT 列名 FROM 表1 连接方式 表2 ON 连接条件;
内连接方式: INNER JOIN ... ON ...
内连接多表: INNER JOIN ... INNER JOIN ... ON ...
外连接左表: LEFT JOIN ... ON ...
外连接右表: RIGHT JOIN ... ON ...
四种连接方式
表连接查询
查询
数值类型:INT / DOUBLE / font color=\"#f15a23\
日期类型:DATE / TIME / YEAR / DATETIME / TIMESTAMP
字符串类型:CHAR / VARCHAR / BOLB / TEXT
库中的数据类型
SHOW DATABASES; #显示当前MySQL中包含的所有数据库
查看所有数据库
CREATE DATABASE mydb1; #创建mydb数据库CREATE DATABASE mydb2 CHARACTER SET gbk; #创建数据库并设置编码格式gbk【常用】CREATE DATABASE mydb3 CHARACTER SET gbk COLLATE gbk_chinese_ci; #支持简体中文和繁体中文CREATE DATABASE IF NOT EXISTS mydb4; #如果mydb4数据库不存在,则创建;如果存在,则不创建。
创建自定数据库
SHOW CREATE DATABASE mydb2; #查看创建数据库时的基本信息
查看库创建信息
ALTER DATABASE mydb2 CHARACTER SET utf8; # 修改mydb1 的字符集为 utf-8
修改数据库信息
DROP DATABASE mydb1; #删除数据库mydb1
删除指定数据库
SELECT DATABASE( ); #查看当前使用的数据库
查看使用数据库
USE mydb1; #使用mydb1数据库
切换使用数据库
库操作
CREATE TABLE 表名font color=\"#f15a23\
创建自定数据表
DML:增、删、改
INSERT INTO 表名(列 1,列 2,列 3....) VALUES(值 1,值 2,值 3......);
* 表名后的列名和 VALUES 里的`值要一一对应`(个数、顺序、类型)
SHOW CREATE TABLE student; #查看创建数据表时的信息:列名和类型
查看表创建信息
UPDATE 表名 font color=\"#f15a23\
* 注意:SET 后多个列名=值,绝大多数情况下都要`加 WHERE 条件`,指定修改,`否则为整表更新`。
# 【增】最右侧添加:如果想在一个已经建好的表中添加一列,可以用ALTER TABLE mydb1 ADD COLUMN NEW_COLUMN_NAME VARCHAR(45) NOT NULL;# 【增】指定位置添加:这条语句向已有的表中加入新的一列,这一列在表的最后一列位置,希望添加在指定的一列ALTER TABLE mydb1 ADD COLUMN NEW_COLUMN_NAME VARCHAR(45) NOT NULL AFTER COLUMN_NAME;# 【增】添加到第一列:上面这个命令的意思是说添加新列到某一列后面。如果想添加到第一列ALTER TABLE mydb1 ADD COLUMN NEW_COLUMN_NAME VARCHAR(45) NOT NULL FIRST;# 【改】将表 mydb1 中,列名 def 改为unitALTER TABLE mydb1 CHANGE def unit CHAR;# 【删】将表 mydb1 中,列名 unit 的列删除ALTER TABLE mydb1 DROP COLUMN unit;
列的增删改
修改
DELETE FROM 表名 WHERE 条件;
* 注意:删除时,`必须加 WHERE 条件`,如若不加 WHERE条件,删除的是整张表的数据* 注意:仅仅删除数据,不会影响数据表的结构
删除
TRUNCATE TABLE 表名;
* 注意:TRUNCATE 是`把表销毁`,再按照原表的格式`创建一张新表`
清空
【DML】
表操作
库表
* 标识每一列数据不重复、实体唯一。
PRIMARY KEY
列值:不可重复,不能为 NULL
主键约束
UNIQUE
列值:不可重复,可以为 NULL
唯一约束
AUTO_INCREMENT
列值:从 1 开始,每次加 1;不能单独使用,和主键配合
自动增长列
实体完整性约束
* 限制列的单元格的数据正确性。
NOT NULL
列值:必须有值,不能为 NULL
非空约束
DEFAULT
列值:为列赋予默认值;书写DEFAULT,以指定的默认值进行填充
默认值约束
CONSTRAINT 引用名 FOREIGN KEY(列名) REFERENCES 被引用表名(列名)
列值:FOREIGN KEY 引用外部表的某个列的值,新增数据时,约束此列的值必须是引用表中存在的值
引用完整性约束
域完整性约束
约束
事务,是一个原子操作,是一个最小执行单元,可以由一个或多个SQL语句组成。在同一个事务当中,所有的SQL语句都成功执行时,整个事务成功,有一个SQL语句执行失败,整个事务都执行失败。
开始:上一个事务结束后的第一条增删改的语句,即事务的开始。# 1.开启事务 方式一: START TRANSACTION; # 1.开启事务 方式二:SET autoCommit = 0; # autoCommit = 0 关闭自动提交,1 开启自动提交
结束:\t1).\t提交:\t\t\ta.\t显示提交:COMMIT;\t\t\tb.\t隐式提交:一条创建/删除的语句,正常退出(客户端退出连接);\t2).\t回滚:\t\t\ta.\t显示回滚:ROLLBACK;\t\t\tb.\t隐式回滚:非正常退出(断电/宕机)执行了创建/删除语句,但是失败了,会为这个无效的语句执行回滚。
边界
数据库会为每一个客户端都维护一个`空间独立的缓存区`(回滚段)。一个事务中所有的增删改语句的`执行结果都会缓存在回滚段`中,只有当事务中所有 SQL 语句均`正常结束`(commit),才会将回滚段中的数据同步到数据库。否则无论因为哪种原因失败,整个事务将回滚(rollback)。
Atomicity(原子性)表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败。
Consistency(一致性)表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前状态。
Isolation(隔离性)事务查看数据操作时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。
Durability(持久性)持久性事务完成之后,它对于系统的影响是永久性的。
特性(ACID)
应用环境:基于增删改语句的操作结果(均返回操作后受影响的行数),可通过程序逻辑手动控制事务提交或回滚。
模拟转账 Demo
应用&实例
事务
CREATE USER 用户名 IDENTIFIED BY 密码;
创建用户
GRANT ALL ON 数据库.表 TO 用户名;
授权用户
REVOKE ALL ON 数据库.表名 FROM 用户名;
撤销授权
DROP USER 用户名;
删除用户
权限
视图,`虚拟表`,从一个表或多个表中查询出来的表,作用和真实表一样,`包含一系列带有行和列的数据`。视图中,用户可以使用 SELECT 语句查询数据,也可以使用 INSERT、UPDATE、DELETE 修改记录(影响原表),视图可以使用户操作方便,并保障数据库系统安全。
- 简单化,数据所见即所得。- 安全性,用户只能查询或修改他们所能见到得到的数据。- 逻辑独立性,可以屏蔽真实表结构变化带来的影响。
优点
- 性能相对较差,简单的查询也会变得稍显复杂。- 修改不方便,特变是复杂的聚合视图基本无法修改。
缺点
CREATE VIEW 视图名 AS 查询数据源表语句;
SELECT * 与正常的 TABLE 使用方式相同
方式① CREATE OR REPLACE VIEW 视图名 AS 查询语句;方式② ALTER VIEW 视图名 AS 查询语句;
DROP VIEW 视图名;
视图
命令
MySQL
JDBC(Java DataBase Connectivity) Java连接数据库,可以使用Java语言连接数据库完成 CRUD 操作。CRUD:增加(Create)、读取(Retrieve)、更新(Update)和删除(Delete)
Java中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver数据库驱动)
Driver: mysql-connector-java-5.1.X 适用于5.X版本Driver: mysql-connector-java-8.0.X 适用于8.X版本
API
核心思想
5.x 链接:https://pan.baidu.com/s/1pB0xoNHDt2NxCX0fgA4ezg 提取码:48t68.x 链接:https://pan.baidu.com/s/1FWzpLm1XUqCFKkVt9KDINA 提取码:d5b3
1. 在项目下新建 lib 文件夹,用于存放 jar 文件2. 复制MySQL驱动文件 mysql-connector-java-5.1.25-bin.jar 到项目的 lib 文件夹中3. 选中 lib 文件夹,右键选择 add as library,点击OK
// 反射:触发类加载,Driver 执行了 static 代码块b style=\
1. 加载驱动
// 数据库连接地址,兼容中文正确显示的参数:?useUnicode=true&characterEncoding=utf8String url = \"jdbc:mysql://localhost:3306/companydb?useUnicode=true&characterEncoding=utf8\"; String user = \"root\"; // 用户名 String password = \"admin123\"; // 密码 Connection connection = DriverManager.font color=\"#00a650\
2. 连接数据库
// 普通对象Statement statement = connection.createStatement();
//【使用】预编译SQL语句;安全地避免SQL注入;动态填充数据执行多个同构的SQL语句PreparedStatement preparedStatement = connection.prepareStatement(sql);font color=\"#f15a23\
3. 获取发送 SQL 语句的对象
// DML(增删改)操作int result = preparedStatement.executeUpdate();
// DQL(查询)操作ResultSet resultSet = preparedStatement.executeQuery();
4. 编写并执行 SQL 语句
if (result > 0) { /* 执行成功 */ } else { /* 执行失败 */ }
if (resultSet.next()) { 类型 变量 = resultSet.get类型(int columnIndex); // 列的编号从1开始 类型 变量 = resultSet.get类型(String columnLable); // 列名} else { /* 查询失败 */ }
5. 处理结果
// 原则:先开后闭非空 resultSet.close();非空 preparedStatement.close();非空 connection.close();
6. 关闭资源
封装了获取连接、释放资源两个方法:public static Connection getConnection( )public static void font color=\"#f68b1f\
DBUtils.java - Demo
重用性方案
定义 private static final Properties properties = new Properties(); // 配置文件集合定义 static{ // 首次使用工具类,触发类加载 InputStream is = DBUtils.class.getResourceAsStream(\"文件路径\"); // 复用本类自带流,读取配置文件 properties.load(is); // 将is流中的配置文件信息,加载到集合中 Class.forName(properties.getProperty(\"driver\"));}在 getConnection 方法中应用 properties.getProperty(\"url\"); // 以及 username 和 password
src/db.properties - Demo
跨平台方案
优化封装事务
封装连接
概念:Object Relational Mapping,对象关系映射。将数据库查询到的结果集遍历映射为对象集合。entity规则:表名=类名;列名=属性名;提供各个属性的get/set方法;提供无参构造和[若需有参构造]
ORM 思想:零散数据的载体
概念:Data Access Object,font color=\"#f15a23\
DAO 层:数据访问对象
封装数据
String 类型,用户输入类型
java.util.Date 类型,java应用层的日期类型
java.sql.Date 类型,java的MySQL中特殊日期类型
日期格式化类: SimpleDateFormat
//按照指定格式转换成util.Date类型String dateStr = \"1999-09-09\";SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd\");java.util.Date date = sdf.parse(dateStr);
String → java.util.Date
// java.sql.Date(long mesc) 参数为毫秒值的有参构造public static java.sql.Date utilToSql(java.util.Date date) { return new java.sql.Date(date.getTime());}
java.util.Date → java.sql.Date
// 无需转换:父类引用指向子类对象java.util.Date utilDate = new java.sql.Date(long msec); // mesc: 毫秒值// eg:java.util.Date user_borndate = resultSet.getDate(\"user_borndate\");
java.sql.Date → java.util.Date
日期转换
步骤:1.连接池初始化时,创建一些连接,并存储到 LinkedList中2.获取连接,LinkedList.remove(0)3.归还连接,addBack(connection)
自定义连接池普通版
步骤:1.连接池初始化时,创建一些连接,并存储到 LinkedList中2.加入装饰者设计模式,将普通连接对象Connection中的close方法改变成归还连接 > 破坏单一职责原则,使用了中间类3.获取连接,使用装饰者设计模式,返回增强的连接对象4.归还连接,就无序addBack(connection)方法
自定义连接池优化版
步骤:1.连接池初始化时,创建一些连接,并存储到 LinkedList中2.加入动态代理,将普通连接对象Connection中的close方法改变成归还连接3.获取连接,使用动态dialing,返回增强的连接对象
自定义连接池终极版
Druid 是目前比较流行高性能的,分布式列存储一、亚秒级查询二、实时数据注入三、可扩展的PB级存储四、多环境部署五、丰富的社区
链接:https://pan.baidu.com/s/1f0pl7CnEJ5vNkWGFS3kdrg提取码:05wc
导入jar包:druid-1.1.5.jar
配置文件:database.properties
DBPoolUtils.java
Druid 德鲁伊环境配置
数据库连接池
概念:用户要完成的一个业务功能,是由一个或多个的DAO调用组成。软件、程序提供的一个功能都叫业务
UserInfoServiceImpl.java Demo
Service业务(Biz/Business)
ThreadLocal 可以绑定当前线程与1个泛型对象的键值对的对象。常用方法:1. public void set(T value); // 设置当前线程绑定的对象2. public T get(); // 返回当前线程绑定的对象3. public void remove(); // 移除当前线程的绑定对象
简介
1. 验证 fromAccount 是否存在2. 验证 fromAccount 是否密码正确3. 验证当前账户余额是否充足4. 验证 toAccount 是否存在5. 减少 fromAccount 的余额6. 增加 toAccount 的余额
转账基本流程
// 创建对象:当前线程绑定1个 Connection 类型对象 private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal<>();
// 当前线程从 ThreadLocal 里取,DBUtils.getConnection()Connection connection = THREAD_LOCAL.get(); // 默认 get 到的是 nullif (connection == null) { // 如果为空 connection = DriverManager.getConnection(...); // properties获取三参 THREAD_LOCAL.set(connection);}
线程绑定连接
Connection connection = null;
// ① 建立了一个数据库连接(线程已绑定)connection = DBUtils.getConnection();
// ② 开启事务:关闭自动提交connection.setAutoCommit(false);
/* ... 业务中的原子操作,如转账中的余额扣除、余额增加 ... */
// ③ 提交事务:执行到这里无异常connection.commit();
} catch (...) { // ④ 回滚事务:如果出现了异常 if (connection != null) { connection.rollback(); }} finally { DBUtils.closeAll(font color=\"#c41230\
转账事务核心
ThreadLocal 类解决转账事务
转账事务逻辑 Demo
DBUtils.java
普适性泛型工具类
命名:xxxVIew职责:收集用户的数据和需求、展示数据
c: TestXxxxView
view/
i: XxxxService
命名:XXXServiceImpl职责:数据的加工处理、调用Dao组合完成业务实现、控制事务
c: XxxxServiceImpl
impl/
service/
业务层
i: XxxxDao
命名:xxxDaoImpl职责:向业务层提供数据,将业务层加工处理后的数据同步到数据库
c: XxxxDaoImpl
dao/
DAO层
c: Xxxx
entity/
ORM 思想封装访问数据
实体类
c: DBUtils
c: DateUtils
utils/
工具类
三层架构设计
Commons DbUtils 是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能勾简化JDBC应用程序的开发!同时,不会影响程序的性能。
DbUtils是Java编程中数据库操作实用小工具,小巧、简单、实用。对于数据表的查询操作,可以吧结果转换为List、Array、Set等集合。便于操作对于数据表的DML操作,也变得很简单(只需要写SQL语句)。
介绍
ResultSetHandler 接口:转换类型接口 BeanHandler 类:实现类,把一条记录转换成对象 BeanListHandler 类:实现类,把多条记录转换成List集合。 ScalarHandler 类:实现类,适合获取一行一列的数据。
QueryRunner:执行sql语句的类 增、删、改:update(); 查询:query();
接口/类
① jar包:mysql-connector-java-5.1.25-bin.jar② jar包:druid-1.1.5.jar③ jar包:commons-dbutils-1.6.jar④ database.properties配置文件
// DBUtils中静态属性:nullprivate static DruidDataSource dataSource = null;
// DBUtils中静态代码块:创建Druid德鲁伊 dataSource 连接池对象static { // ... database.properties dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);}
// DBUtils中静态方法:返回一个数据源 public static DataSource getDataSource() { return dataSource;}
// DAO实现类中调用方式// 1.创建 QueryRunner 对象,并传递一个数据源对象private QueryRunner queryRunner = new QueryRunner(DBUtils.getDataSource());// 2.使用 queryRunner 对象,DML-增删改使用 .update(); DQL-查询使用 .query();Object[] params = {xxx.getXx()...}; // 对应占位符获取值return queryRunner.update(\
使用步骤
ThreadLocal 线程绑定当前使用的线程池中 connection 对象,即可正确对事务进行开启、提交、回滚时操作的是同一个数据库连接!
XxxxDaoImpl
# 数据库配置driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/account?useUnicode=true&characterEncoding=utf8username=rootpassword=font color=\"#c41230\
database.properties
Apache的DBUtils
# 数据库配置driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8username=rootpassword=font color=\"#c41230\
druid配置文件
# 数据库配置c3p0.driverClass=com.mysql.jdbc.Driverc3p0.jdbcUrl=jdbc:mysql://localhost:3306/dbc3p0.user=rootc3p0.password=123456
c3p0.properties
c3p0配置文件
JDBC
DateUtils.java Demo
概述:HTML,Hyper Text Markup Language(超文本标记语言)浏览器解析HTML标记的内容
特点:简易性、可扩展性、平台无关性、通用性
发展:HTML2.0 >> 3.2 >> 4.0 >> 4.01 >> 5
<!DOCTYPE html> <!-- 文档声明,告诉浏览器使用html解析 --><html> <!-- 页面标记 --> <head> <!-- 网页头部 --> <meta charset=\"utf-8\" /> <!-- 字符集编码 --> <title>我的页面</title> <!-- 页面标签标题 --> </head> <body> <!-- 网页主体,显示的部分 --> 第一个页面! </body></html>
1. HTML页面包含头部 head 和主体 body2. HTML标签通常成对出现,有开始标签、结束标签称为 对标签;没有结束标签的为 空标签3. HTML标签都有属性,格式:属性名=\"属性值\" (多个属性名用空格间隔)4. HTML不区分大小写,建议小写5. HTML文件后缀名为 .html / .htm
<html> </html>
根
<head> </head>
头
<title> </title> 在头标签中
标题
b style=\
元信息
<body> </body>
主体
color=\"颜色\"bgcolor=\"背景色\"background=\"背景图路径\"颜色表示方式:① 颜色名称 red green ② RGB模式 #000000 #FFFFFF
属性
结构标签
<!-- 注释文本 -->
注释
<br />
换行
<p> </p> 自带换行,有行间距
align=\"文本对齐方式 left 默认、center、right\"
段落
<hr />
width=\"宽度\" 像素px / 百分比%size=\"高度\" 水平线的粗细,避免过粗,一般个位数,eg:6pxcolor=\"水平线颜色\"align=\"对齐方式 left、center默认、right\"
水平线
排版标签
<h1>一级标题</h1> 数字越小<h2>二级标题</h2> 字号越大<h3>三级标题</h3> 默认加粗<h4>四级标题</h4> 默认字号<h5>五级标题</h5> 默认占据一行<h6>六级标题</h6> 默认有行间距
标题标签
<div> </div> 独占一行,自带换行默认宽度为浏览器部分宽度,高度会跟随元素内的文本内容而改变应用:结合css做页面分块,布局
块标签
<span> </span> 所有内容都在同一行默认宽度和高度都会随着内容改变应用:友好提示信息的显示
行级标签
容器标签
type=\"?\"实心圆:disc (默认)空心圆:circle黑色方块:square
<ul> <li> </li> <li> </li> <li> </li></ul>
无序列表
type=\"?\"数字:1大小写字母:A / a罗马数字:I / i
<ol> <li> </li> <li> </li> <li> </li></ol>
有序列表
定义列表
可以相互任意嵌套
列表嵌套
列表标签
<img />
src=\"图片地址\"height=\"高度\"width=\"宽度\"border=\"边框\"alt=\"图片未被加载时的提示文字\"title=\"图片被鼠标悬停时的提示文字\"
图片标签
href=\"跳转的地址\" // 跳转外网需要添加协议http/httpstarget=\"_self\"(当前页) \"_blank\"(一直新页面) \"_search\"(仅1个新页面复用)
充当锚点(跳转顶部/跳转底部)提供率 name 属性,为其赋值点击跳转的标签 href 属性给 #name<a name=\"tops\"></a><a href=\"#tops\">跳到顶部</a>
链接标签
width=\"表格宽度\"height=\"表格高度\"border=\"边框宽度\"bordercolor=\"边框颜色\"cellspacing=\"单元格之间的间距\"cellpadding=\"单元格与内容的间距\"align=\"对齐方式 left center right\" 表格相对于页面
table
表头,默认加粗、居中
th
align=\"对齐方式 left center right\" 内容相对于单元格valign=\"对齐方式 top middle bottom\" 内容相对于单元格
td
colspan=\"横跨的列数\"
列合并
rowspan=\"纵跨的行数\"
行合并
表格标签
普通的文字是这样b style=\
文本标签
基本标签
<form> </form>
HTML表单用于搜集不同类型的用户输入信息。
定义标签
<input />
表单元素:type 不同的输入方式name 用于拼接到链接地址提交到服务器,格式:name1=value1&name2=value2value 默认值checked 单选选中selected 多选选中
账户:<input type=\"text\" name=\"username\" placeholder=\"请输入账户\" />密码:<input type=\"password\" name=\"password\" placeholder=\"请输入密码\" />性别: <input type=\"radio\" name=\"sex\" value=\"male\" checked=\"checked\" />男 <input type=\"radio\" name=\"sex\" value=\"female\" />女照片:type=\"file\"地址:<select name=\"city\"> <option value=\"zz\">郑州</option> <option value=\"zz\" selected=\"selected\">南阳</option> </select>爱好: <input type=\"checkbox\" name=\"hobbys\" value=\"basketball\" checked=\"checked\" />篮球 <input type=\"checkbox\" name=\"hobbys\" value=\"football\" checked=\"checked\" />足球 <input type=\"checkbox\" name=\"hobbys\" value=\"volleyball\" checked=\"checked\" />排球介绍:<textarea name=\"introduce\"></textarea>提交:<input type=\"submit\" name=\"submit\" value=\"注册\" /><button type=\"submit\">注册</button>清空:<input type=\"reset\" name=\"reset\" id=\"\" value=\"清空\" /><button type=\"reset\">清空</button>
登陆界面
输入标签
表单标签
<frameset> </frameset> // 代替body标签font color=\"#f15a23\
frameset属性:row=\
frame属性:src=\"填充的内容\" noresize=\"noresize\" 不能改变大小 scrolling=\"no\" 不显示滚动条定位到具体位置使用 name 属性
框架标签
<!-- 网页的编码 --><meta charset=\"utf-8\"><!-- 网页的编码:html 4.01 --><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/><!-- 网页的关键字 seo --><meta name=\"keywords\" content=\"关键词1,关键词2,关键词3\"/><!-- 网页的描述 seo --><meta name=\"description\" content=\"this is my page\"/><!-- 页面自动跳转,2秒后跳转百度 --><meta http-equiv=\"refresh\" content=\"2;url=https://www.baidu.com\"/><!-- href: 引入css文件地址 --><link rel=\"stylesheet\" type=\"text/css\" href=\"css/01CSS.css\"/><!-- src: js文件地址 --><script src=\"js文件地址\" type=\"text/javascript\"></script>
标签
< 小于号 <> 大于号 >& 与字符 &" 引号 \"® 已注册 ®© 版权©™ 商标™ 空格¥ 人民币 ¥
符号
其他标签
HTML
<style> 选择器{ 属性名:属性值; }</style>
<xxx style=\"aaa:AAA; bbb:BBB;\">
标签/属性
<font style=\"color: red;\">这是一行字</font>
标签内,单独对特定标签元素生效,简单,但不能复用。
内联方式
<style type=\"text/css\"> font{ font-size: 50px; color: darkblue; } a{ text-decoration:none }</style></head>
在 head 标签中,使用 style 标签使用选择器选中元素编写 css 代码
内部方式
<link rel=\"stylesheet\" type=\"text/css\" href=\"./css/01CSS.css\"/>
新建一个 css 样式文件编写 css 代码在 html 文件中引入 css 外部文件,使用 link 标签引入
外部方式
CSS使用方式
标签名{ 属性名:属性值;}
body全局样式:标签名使用body
标签选择器
id=\"aaa\"
#id选择器{ 属性名:属性值;}
id选择器
class=\"aaa\"
.类选择器{ 属性名:属性值;}
类选择器
标签名[属性名=\"值\"]{ 属性名:属性值;}
标签名[属性名]{ 属性名:属性值;}
eg:a[href^=\"http\"] { 样式 } 以http开头的a[href$=\"cn\"] { 样式 } 以cn结尾的a[href*=\"u\"] { 样式 } 包含了字符u的
属性选择器
A选择器~B选择器{ 属性名:属性值;}// 【通用兄弟】自身之后的所有兄弟标签
A选择器+B选择器{ 属性名:属性值;}// 【相邻兄弟】自身之后的1个兄弟标签
父选择器>子选择器{ 属性名:属性值;}// 【子代】亲儿子不跨标签层级
父选择器 子选择器{ 属性名:属性值;}//【后代】会跨子标签层级
在结构中有标签包裹父子/相邻层级关系时使用。
层级选择器
逗号分隔不同的选择器,将这些划分为一组,使用共同的样式
分组选择器
不同的选择器不同的样式做修改,样式会叠加。不同的选择器相同的样式做修改,遵循优先级:优先级(范围越小优先级越高):内联样式 > id > class > 标签
用于向某些选择器添加特殊的效果。
* 主要用于 a 标签上a:link {color: #FF0000} /* 未访问的链接样式 */a:visited {color: #00FF00} /* 已访问的链接样式 */a:hover {color: #FF00FF} /* 鼠标移动到标签内容上 */a:active {color: #0000FF} /* 选定时标签内容样式 */
注意:在 CSS 定义中,a:hover 必须被置于 a:link 和 a:visited 之后,才是有效的。注意:在 CSS 定义中,a:active 必须被置于 a:hover 之后,才是有效的。注意:伪类名称对大小写不敏感。
锚伪类
CSS伪类
CSS选择器
定义文本的字体系列、大小、加粗、风格(如斜体)和变形(如小型大写字母)
font\t简写属性。作用是把所有针对字体的属性设置在一个声明中。eg:font:oblique 700 30px \"黑体\"; /* 样式 加粗 大小 风格 */font-family\t设置字体系列。font-size\t设置字体的尺寸。font-style\t设置字体风格。(斜体)font-weight\t设置字体的粗细。
字体
改变文本的颜色、字符间距,对齐文本,装饰文本,对文本进行缩进,等等
color\t设置文本颜色direction\t设置文本方向。line-height\t设置行高。text-align\t对齐元素中的文本。(左对齐、居中、右对齐)text-decoration\t向文本添加修饰。(上划线、下划线、删除线、无线条)text-indent\t缩进元素中文本的首行(2em : 2个字符;20% : 20%的宽度)text-transform\t控制元素中的字母。(全大写、全小写、所有单词首字母大写)unicode-bidi\t设置文本方向。white-space\t设置元素中空白的处理方式。(=\"nowrap\" 禁止文本分行,即都在1行内)letter-spacing\t设置字符间距。word-spacing\t设置单词间距。
文本
background-color:设置背景颜色,默认透明background-image:url(\"图片路径\");设置背景图片background-size: 设置背景图片的尺寸属性background-repeat: repeat-y:只在垂直方向都平铺 repeat-x:只在水平方向都平铺 repeat:在水平垂直方向都平铺 no-repeat:任何方向都不平铺background-position: 改变图像在背景中的位置。top、bottom、left、right 和 center(1个位置值或多个组合位置值)/*简写 没有顺序*/background: red center no-repeat url(img/003.jpg);
背景
list-style-type:decimal;改变列表的标志类型list-style-image: url(\"images/dog.gif\");用图像表示标志list-style-position: inside;确定标志出现在列表项内容之外还是内容内部 简写list-style: decimal url(img/001.png) inside;去掉样式:list-style:none;list-style-type:none;
列表
display: none 不显示 block 块级元素 inline 行内元素 inline-block 行内块级元素display:flex 伸缩布局: flex-direction:row/column 主轴方向 align-items: center; 垂直居中 justify-content: center; 水平居中
显示
轮廓(outline)绘制于元素周围的一条线,位于边框边缘的外围,可起到突出元素的作用。常用属性:outline-style: solid(实线) dotted(虚线) dashed(虚线的每段较长) double(框为空心); 设置轮廓的样式outline-color:red; 设置轮廓的颜色outline-width:10px 设置轮廓的宽度
轮廓
float=\"?\"left 左浮动 right 右浮动 none 不浮动 inherit 继承父元素* 浮动起来的元素会遮盖没有浮动属性的元素
clear=\"?\"left 左侧不允许浮动元素right 右侧不允许浮动元素both 左右两侧均不允许浮动元素none 默认,允许浮动元素出现在两侧inherit 继承父元素
浮动
position: static(默认) relative(相对定位) 相对自身原来的位置偏移某个距离,原本所占的空间仍然保留。 absolute(绝对定位) 相对于已定位的父元素进行偏移某个距离,不保留原空间。(如无已定位的父元素则相对于浏览器) fixed(固定定位) 固定加载位置,不会因为滚动而变化位置left - 相对浏览器左边right - 相对浏览器右边top - 相对浏览器顶端bottom - 相对浏览器底端
注意:body有默认的margin(8px)
定位
CSS属性
width:设置元素的宽度height:设置元素的高度line-height:设置元素的行高
尺寸
borderul style=\
边框
外边距
内边距
盒子模型的实际的宽度:width+2*(padding+border+margin)盒子模型的实际的高度:height+2*(padding+border+margin)
实际
CSS盒子
border-radius:50%; //圆角半径可以将正方形图片切为圆形。
圆角
阴影
<body style=\"text-align: center; background:url(img/1.png); background-size: 200px 300px; background-repeat: no-repeat;\"></body> //背景图片尺寸,不平铺
背景图片尺寸
多个背景图片
CSS3扩展属性
CSS
C/S模式:Client/Server模式(客户端/服务器)【优】客户端分担了负载【劣】新功能必须需要重新下载B/S模式:Browser/Server模式(浏览器/服务器) 【优】使用简单只需要浏览器【劣】负载都交给了服务器
Tomcat,是Apache-Jarkarta开源项目中的一个子项目,小型、轻量级的支持JSP和Servlet技术的web服务器。最新的Servlet和JSP规范因为有 Sun 公司的参与和支持总能得到体现,技术先进、性能稳定、免费!
web动态项目比web静态项目区别:动态资源中可以有静态资源,可以有动态资源,必须有 WEB_INF 目录 和 WEB_INF/web.xml 文件。
基本概念
1.官网下载 tomcat.apache.org Tomcat8.0|8.5版本2.解压到一个没有特殊符号的路径3.进入到解压的目录下,bin\\startup.bat启动* 不要放入层次多的文件夹中、不建议放中文路径、依赖JAVA_HOME环境变量。
bin 二进制可执行文件和启动脚本文件conf 配置目录: server.xml 配置整个服务器的信息 tomcatusers.xml 存储tomcat用户信息 font color=\"#f15a23\
目录
bin/startup.bat 启动服务器bin/shutdown.bat 关闭服务器
* 中文乱码解决:logging.properties >> 注释掉line47 #java.util.logging.ConsoleHandler.encoding = UTF-8
http://ip:port/project/资源 (静态[html/css/javascript]、动态[servlet/jsp])
浏览器访问 http://localhost:8080 或 http://127.0.0.1:8080
原因:Tomcat目录 conf 目录下 web.xml 规定了默认欢迎页面
<welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file></welcome-file-list>
自定义的 web 项目也部署到 tomcat 中,也会遵守该规定。
默认访问 index.xml 或 index.jsp
404:无法找到文件500:内部服务器错误
常见错误
直接修改 tomcat 的 web.xml 中的 <welcome-file-list> 会影响到所有项目的欢迎页面。
在项目目录中 WEB_INF/web.xml 中修改 <welcome-file-list> 仅针对当前项目有效。
配置默认访问页
<Connector port=\"8080\" protocol=\"HTTP/1.1\" connectionTimeout=\"20000\" redirectPort=\"8443\" /> //默认8080
<Connector port=\"80\" protocol=\"HTTP/1.1\" connectionTimeout=\"20000\" redirectPort=\"8443\" /> //遵循浏览器默认端口可以直接用 http://localhost 访问
配置端口号:conf/server.xml
重命名 ROOT 项目或删除该目录
</Host>前 新增如下内容:<Context docBase=\"磁盘绝对路径\" path=\"\" debug=\"0\" reloadable=\"true\"/>
配置项目为默认启动项目:conf/server.xml
B/S数据流程图
Tomcat服务器搭建
直接拷贝
直接将项目放到webapps目录
<Host> ... <Context docBase=\"磁盘路径\" path=\"/访问名称\" /></Host>
访问 http://localhost:8080/访问名称/资源文件
conf/server.xml
配置虚拟项目目录
新建 projname.xml
编辑<?xml version=\"1.0\" encoding=\"UTF-8\"?><Context docBase=\"磁盘路径\" />
访问 http://localhost:8080/projname/资源文件
conf/Catalina/localhost
配置虚拟项目目录优化版
Tomcat项目部署
Window >> Preferences >> Server
点击add >> 选择对应的版本 >> Finish
Eclipse中集成Tomcat
File >> Settings >> build-execution-deployment >> 选择Application Servers >> 添加Tomcat >> 选择Tomcat安装根目录如:D:\\tomcat\\apache-tomcat-8.5.53
* 解决源码编译运行后打印中文乱码问题:Tomcat-8.5.53 >> Edit Configuration >> VM option:-Dfile.encoding=utf-8
Intellij IDEA中集成Tomcat
Tomcat在开发工具支持
Tomcat配置
自定义Tomcat服务器
Tomcat
注解Annotation用于描述元数据的修饰符,包括类、成员变量、构造方法、成员方法、方法参数和声明。JDK5.0之后引入的特性。
标记注解:注解中没有属性可以设置,如 @Override、@Deprecated单值注解:注解中只有一个属性(\"value=\"可省略),如 @SuppressWarings{ String[] value; }完整注解:注解中有多个属性
类型
判断子类中的方法是否是一个父类方法的重写方法
@Override方法覆盖注解
标记一个类/方法/变量是否是过时的,调用时会有删除线
@Deprecated过时标记注解
可以消除编译器/开发工具对警告的提示
@SupressWarning(\"all\")压制所有警告注解
标记只能有1个公开抽象方法,用于Lambda简写
@FunctionaInterface函数式接口注解
帮助检查可变参数与泛型结合时的使用情况
@SafeVarargs安全的可变参数注解
Java内置注解
import org.junit.Test;* 该注解的方法被强制public且无参* 可以直接运行@Test注解的方法,底层还是 main 方法运行,通过(反射+@Test注解)生效。
其他待补充
Junit
Servlet3.0+版本支持,可以替代web.xml配置。
@WebServletweb资源配置注解
Servlet
(框架注解)待补充
第三方注解
@Retention(RetentionPolicy.RUNTIME)public font color=\"#f15a23\
自定义注解
来源
注解分类
定义在自定义注解上,规定自定义的作用区域、存活策略。
public @interface Target { ElementType[] value();}
当前定义的注解可以应用的范围:span style=\"font-size: inherit;\
@Target规定自定义注解的作用区域
public @interface Retention { RetentionPolicy value();}
@Retention规定自定义注解的存活策略
将注解中的内容包含到Javadoc中。
@Documented文档标记注解(无参数)
例如B继承了A,A添加了注解,那么B也会继承同样的注解。
@Inherited可随修饰类被继承的标记注解(无参数)
元注解
反射机制① 注解在类/方法上,获取对应的 Class 对象 / Method 对象② 判断类/方法上的注解是否存在 .isAnnotationPresent(注解名.class)③ 获取注解信息 .getAnnotation(注解名.class)
核心步骤
步骤:1.自定义注解2.在测试类上使用该自定义注解3.让自定义注解生效 ● 获取测试类的Class对象 ● 获取测试类的成员方法 ● 判断方法上是否有自定义注解 ● 执行添加了注解的方法
自定义注解@MyTest
步骤:1.自定义注解@JDBCInfo2.在DBUtils工具类上使用@JDBCInfo3.在DBUtils工具类的静态代码中获取注解中的属性(反射读取注解信息)
Class<DBUtils> dbClass = DBUtils.class;boolean present = dbClass.isAnnotationPresent(JDBCInfo.class);if (present) { JDBCInfo jdbcInfo = dbClass.getAnnotation(JDBCInfo.class); DRIVERCLASS = jdbcInfo.driverClass(); ...}
TestJDBCInfo
DBUtils
@JDBCInfo
自定义注解@JDBCInfo
获取注解信息
装饰类中调用所有方法,并定义printLog()方法增加日志信息: 1.获取UserDao实现子类的 Class 对象 2.获取UserDao接口的 Class 对象 3.获取到接口中对应的方法 4.判断方法上是否有注解信息 5.有注解,则获取注解信息 6.拼接日志需要的时间和必要信息
装饰者模式
动态代理的匿名内部类参数中定义增强日志信息的逻辑: 1.检查方法上是否有对应注解 2.有注解:执行原有功能,打印日志 3.拼接日志需要的时间和必要信息 4.没注解:执行原有功能
动态代理模式
测试类验证
装饰者设计模式:UserDaoWrapper装饰类
动态代理设计模式:测试类 Proxy.newProxyInstance(...) 验证
UserDaoImpl实现类
UserDao接口
@SysLog
注解+反射+设计模式【日志记录】
优点:1、降低耦合,使容易扩展2、对象之间的关系一目了然3、xml配置文件比注解功能齐全缺点:1、配置文件配置工作量相对注解要大
xml
优点:1、在class文件中,可以降低维护成本2、提高开发效率缺点:1、如果对注解文件(Annotation)进行修改,需要重新编译整个工程2、业务类之间的关系不如xml配置那样一目了然3、程序中过多的注解,对于代码的简洁度有一定影响4、注解功能没有xml配置文件齐全
注解
* 大多数情况下使用配置文件,Spring Boot流行起来,就流行注解配置(注解开发)。
xml与注解-对比
@注解
Servlet 一个可以执行在服务器中的Java程序。
1. 接收客户端浏览器请求,完成操作任务2. 动态生成网页(页面数据可变)3. 将包含操作结果的动态网页响应给客户端浏览器
核心作用
|--webapps(存放所有网站) |--MyServlet(网站) |--WEB_INF(核心内容) |--classes/*.class(.class文件) |--lib/*.jar(网站需要的jar包) |--web.xml(配置文件) |--css/*.css(样式文件) |--img/*.jpg/png/bmg/gif(图片资源) |--js/*.js(脚本文件) |--*.html(静态页面)|--XXXServlet
目录结构
External Library中没有Tomcat包( jsp-api.jar & servlet-api.jar)时:Alt+1 切到项目窗口 >> F4 打开Module Setting >> 选择Dependencies >> 增加Tomcat的库
配置库包
创建目录结构
方式一:实现 javax.servlet.Servlet 接口,重写 5 个主要方法,处理请求的方法是 service( )——缺点:5个方法中只有1个方法有用方式二:继承 javax.servlet.GenericServlet 抽象类,重写需要的方法,处理请求的方法是 service( )——缺点:与协议无关,无法满足http协议的web项目方式三:继承 javax.servlet.http.HttpServlet 抽象类,默认重写了 service( ) 方法,且针对http协议优化,需自行重写 doGet( ) 和 doPost( ) 方法处理请求
<servlet> <servlet-name>Demo01</servlet-name> <servlet-class>com.demo.t1.servlet.Demo01</servlet-class> <load-on-startup>0</load-on-startup></servlet><servlet-mapping> <servlet-name>Demo01</servlet-name> <url-pattern>/demo</url-pattern></servlet-mapping>
web项目中会有 /demo 的访问资源,访问方式: http://localhost:8080/projname/demo
在文件 WEB_INF/web.xml 中新增如下内容
web.xml注释
Servlet基础
为当前项目配置多个Servlet映射:配置方式:b style=\
精确匹配 /具体的名称 只有url路径是具体的名称的时候才会触发Servlet后缀匹配 *.xxx 只要是xxx结尾的就匹配触发Servlet目录匹配 /a/b/c* 匹配对应目录资源下所有请求,包含服务器的所有资源通配匹配 / 匹配所有请求,包含服务器的所有资源,不包含.jsp——为缺省Servlet(Tomcat自带缺省)
<url-pattern>匹配规则
<load-on-startup>0</load-on-startup></servlet>
1) 标记容器是否在启动的时候就加载对应的 Servlet (实例化并调用其init()方法)2) 它的值必须是一个整数,表示servlet应该被载入的顺序3) 当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个 Servlet4) 当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载5) 正数的值越小,该servlet的优先级越高,应用启动时就越先加载6) 当值相同时,容器就会自己选择顺序来加载
<load-on-startup>加载Servlet
分类:① 带协议的绝对路径:http://localhost:8080/projname/img/pic.jpg② 不带协议的绝对路径:/projname/img/pic.jpg③ 相对路径: 当前目录 ./ 可省略 上级目录 ../ 不可省略
服务器路径问题
web.xml配置(Servlet所有版本支持)
@WebServlet( name = \"TestWebServlet\
name:任意起的当前Servlet的名字value:配置url路径,该路径在当前项目中必须唯一urlPatterns:配置url路径,和value作用一样,不能同时使用loadOnStartup:配置Servlet的创建时机
【快捷创建】包下 Alt+Insert >> font color=\"#f15a23\
@WebServlet注解式配置(Servlet3.0+支持)
① 默认只有 index.jsp 时会只显示其为首页
② 如果写了 index.html 页面则会以其优先为首页
<welcome-file-list> <welcome-file>page.html</welcome-file> <welcome-file>page.htm</welcome-file> <welcome-file>page.jsp</welcome-file></welcome-file-list>
<error-page> <!--当页面未找到报404时显示 location 标签指定的页面--> <error-code>404</error-code> <location>/error/404.html</location></error-page>
③ 默认页面找不到时显示的页面
页面显示控制
Servlet配置
是一个配置对象,通过 web.xml 或 注解方式配置 Servlet 参数后,可以通过 ServletConfig 对象获取初始化参数。
1. ServletConfig 对象是由服务器创建的,通过 Servlet 的 init 方法传递到 Servlet 中;2. 作用: 获取 Servlet 名称使用 getServletName(); 获取 Servlet 初始化参数 getInitParameter(); getInitParameterNames(); 获取 ServletContext 对象3. 获取 ServletContext 对象:继承 HttpServlet 后直接调用 Servlet 接口的 getServletContext() 方法。
ServletConfig 接口
是一个域对象(上下文对象),用来存储数据。全局的储存信息的空间,服务器开始就存在,服务器关闭才释放。
1. 当服务器启动时,会为服务器中的每一个web应用创建一个 ServletContext 对象;2. 作用: ① 实现多个 Servlet 数据共享 ② 获取全局初始化参数 ③ 获取资源在服务器上的真实磁盘路径 ④ 用 ServletContext 实现请求转发
public Object getAttribute(String name) 获取域中指定参数名称的值public void removeAttribute(String name) 将指定的参数和值移除public void font color=\"#f15a23\
① 数据共享
<!--全局初始化参数:整个web应用,随着服务器的启动而初始化--><context-param> <param-name>username</param-name> <param-value>root</param-value></context-param><context-param> <param-name>password</param-name> <param-value>1234</param-value></context-param><!--或注解方式配置初始化参数-->
public String getInitParameter(String name) 获取初始化参数public java.util.Enumeration<E> getInitParameterNames() 获取初始化参数集合
② 获取全局初始化参数
public String getRealPath(String path) 获取资源的真实路径根据项目的当前路径 / 拼接,注意参数给的时候也是相对于 / 当前路径。
③ 获取资源在服务器上的真实磁盘路径
案例:统计站点访问次数
ServletContext 接口
ServletConfig与ServletContext
注意事项:1. 路径配置,注解中的value路径、html中的路径;2. QueryRunner注意传参时的实体类参数;3. 确保数据库配置文件正确,能够正确被DruidUtils加载到;
Servlet集成JDBC三层架构
// 监听 Servlet 的初始化——通过浏览器页面请求调用Servlet时仅初始化 1 次【font color=\"#c41230\
生命周期
尽可能使用局部变量。
线程安全
xml或注解。
初始化参数
Servlet生命周期
1. Servlet 在服务器中只会创建一个实例2. 当多个请求同时请求一个 Servlet 时,就会根据 tomcat 中的 server.xml 文件中的 <Connector> 标签配置线程池,然后当项目启动时,根据项目中 web.xml 初始化线程池3. 当请求到达时,Servlet 容器通过调度线程池中等待状态的线程给请求4. 线程执行 Servlet 的 service 方法5. 请求结束,放回线程池,等待被调用
优点:* Servlet 单实例,减少了产生 Servlet 的开销* 通过线程池来响应多个请求,提高了请求的响应时间缺点:* 在 Servlet 中尽量避免使用成员变量,因为成员变量属于对象实例,而 Servlet 是单实例,所以相当于这个成员变量是多线程共享,存在线程不安全的问题。
Servlet单示例多线程
协议:两个设备进行数据交换的约定。HTTP协议:超文本(字符/音频/视频/图片)传输协议,基于TCP协议。
请求行: Request URL: 请求网址 Request Method:请求方式(GET/POST) Protocol:http协议版本请求头: Cookie: cookie Content-Type:请求正文的数据类型 User-Agent:请求的浏览器类型请求数据: 请求正文(POST+请求参数)的具体数据
HTTP请求报文(图)
响应行: Status Code:响应状态码(200/404...)响应头:Location:与302状态码组合完成重定向功能 Content-Type:响应正文的数据类型(Content-Type:text/html;charset=utf-8) Refesh:定时跳转 Content-disposition:文件下载响应数据: 响应正文的具体数据
HTTP响应报文(图)
发起请求域名解析 本地域名解析(C:\\Windows\\System32\\drivers\\etc\\hosts) 互联网域名解析(DNS)执行请求响应请求
HTTP请求执行流程
● get只能传递1kb以下的数据;post可以传递大数据● get请求参数会直接拼接到Request URL上(&);post请求参数是在请求正文中,更安全● get主要用于获取/查询数据;post主要用于更新数据/上传文件
GET/POST请求区别
200:服务器响应成功302:页面重定向304:页面无变化,无需重新请求服务器404:没有对应的服务器资源500:服务器内部错误
常用响应状态码
HTTP协议
response.font color=\"#f15a23\
操作响应行
response.setHeader() 覆盖原有响应头的值response.addHeader() 在原有的响应头的基础上添加新值(Cookie)
操作响应头
response.getWriter().println(\"响应正文内容\") 返回可将字符文本发送到客户端的 java.io.PrintWriter 对象
操作响应正文
浏览器的解码方式不固定
// ● 终极方案:同时设置服务器的编码,设置浏览器解码方式response.setContentType(\"text/html;charset=utf-8\");// 其他方案:分别设置服务器编码、浏览器解码response.setCharacterEncoding(\"utf-8\") 设置服务器的编码方式response.setHeader(\"Content-Type\
操作响应中文乱码
/*定时跳转*/response.setHeader(\"refresh\
定时跳转
// 方式一:设置 Status Code=302 和 Location=urlresponse.setStatus(302);response.setHeader(\"location\
原理:浏览器发送http请求 >> web服务器回复响应状态码302+响应头location给浏览器 >> 浏览器收到302则自动再发送1个http请求(url+location) >> 服务器根据新请求的url寻找资源响应给浏览器
特点:1. 重定向是客户端行为2. 重定向是浏览器做了至少 2 次的访问请求3. 重定向浏览器地址改变4. 重定向两次跳转之间传输的信息会丢失(request生命周期为单次请求)5. 重定向可以定向到任何web资源(当前站点/外部站点)
重定向
response 对象
request.getMethod() 获取请求方式request.getRequestURI() 获取请求路径request.getQueryString() 获取请求路径上的参数,仅限于GET
操作请求行
request.getHeader(String name) 根据请求头名称获取值,如 User-Agent
操作请求头
request.getParameter() 获取指定参数名称的值request.getParameterValues() 获取指定参数名称的一组值request.getParameterMap() 返回此请求的参数的 java.util.Maprequest.getParameterNames() 获取所有的参数名称
操作请求参数
@WebServlet(name = \"任意名字\
<!--默认提交方式为 GET,同时可省略,POST不可省略--><form method=\"post\" action=\"/projname/资源路径\">...</form>
操作请求数据
浏览器的编码方式固定为 utf-8
/* POST请求正文乱码,两种方式都可以;GET是QueryString乱码,只能用方式二 */// ● 终极方案:设置请求正文编码,用于POST在Tomcat8.5环境。 request.setCharacterEncoding(\"utf-8\");// 其他方案:将请求中拿到的乱码字符串编码成iso8859-1字节,再将字节解码为utf-8字符串,通用Tomcat7.0&8.5环境。String serverEncoding = request.getCharacterEncoding();String tmp = request.getParameter(\"username\
操作请求中文乱码
// 转发,如提交成功自动进行一次配置路径的Servlet请求调用执行,此处为配置路径(无projname)request.getRequestDispatcher(\"/资源路径\").font color=\"#f15a23\
原理:客户浏览器发送http请求 >> web服务器接收此请求 >> 服务器内部完成请求处理和转发动作 >> 将目标资源响应给客户
特点:1. 转发是服务器行为2. 转发是浏览器只做了 1 次访问请求3. 转发浏览器地址不变4. 转发两次跳转之间的信息不会丢失(request生命周期内可传递数据)5. 转发只能将请求转发给同一个web项目内的资源
请求转发
request 对象
request域对象生命周期:在一次请求中,请求结束服务器响应时即销毁。
request.font color=\"#f15a23\
request域对象共享数据方法
● 重定向中不能使用 request域对象,因为1次请求响应后该对象便销毁;● 转发中可以使用 request域对象,因为转发只有1次请求,在域对象生命周期内。
request域对象
1. 使用相对路径时,没有区别;2. 使用绝对路径时,重定向使用/project/资源,转发使用/资源
重定向和转发的路径问题
请求&响应
客户端状态管理技术,将状态信息保存在客户端。网景公司发明,浏览器会话技术。一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称name和设置值value。浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个大小限制为4kb。
执行流程:1.浏览器向服务器发送请求,服务器需要创建cookie,服务器会通过响应携带cookie, 在产生响应时会产生Set-Cookie响应头,从而将cookie信息传递给了浏览器;2.当浏览器再次向服务器发送请求时,会产生cookie请求头,将之前服务器的cookie信息再次发送给了服务器, 然后服务器根据cookie信息跟踪客户端状态。
图示
工作原理
// 用响应创建Cookie,等价于 response.addHeader(\"set-cookie\
创建添加
// 用请求获取CookieCookie[] cookies = request.getCookies(); // 获取Cookies返回数组// 需遍历cookie.getName();cookie.getValue();// 修改Cookiecookie.setValue(String);
获取修改
// 设置Cookie的共享范围cookie.setPath(\"/\");
/ 当前项目下所有资源均可共享访问该Cookie对象内容/project/demo 当前项目下只有资源demo均可共享访问该Cookie对象内容
共享范围
// 设置Cookie生命周期,单位scookie.setMaxAge(int); // 7天:7*24*60*60
<0:浏览器会话结束/浏览器关闭,内存存储(默认)=0:失效>0:生效时间,单位s* 在生命周期内Cookie会跟随任何请求,可通过设置路径限制携带Cookie的请求资源范围。
中文:Unicode,4个字节 英文:ASCII,2个字节
Cookie的中文乱码需要进行编码和解码处理:编码:java.net.URLEncoder 的 URLEncoder.font color=\"#f15a23\
编码与解码
chrome://settings/content/cookies
chrome://settings/siteData
chrome浏览器查看cookie信息
优点:● 可配置三种到期规则:1次请求就失效,1次浏览器会话(关闭)失效,配置永久生效● 简单性:基于文本的轻量结构,简单键值对● 数据持久性:虽然Cookie可被客户端浏览器的过期处理和干预,但Cookie通常也是客户端上持续时间最长的数据保留形式
缺点:● 大小受到限制:大多数浏览器的Cookie只有4kb大小的限制● 用户配置禁用:客户浏览器设置了禁用接收Cookie的能力,限制了该功能● 潜在安全风险:用户可能会操纵篡改浏览器上的Cookie,会造成Cookie应用程序执行失败的问题
优劣
LastVisitTimeServlet
案例:记录用户上一次访问时间
ShowHistoryServlet
HistoryServlet
案例:记录商品的浏览历史信息
Cookie
request 1个用户可有多个;session 1个用户1个;servletContext 所有用户共用1个。为了节省空间,提高效率,ServletContext 中要放必须的、重要的、所有用户需要共享的线程安全的一些信息。
三大域对象
服务器状态管理技术,将状态信息保存在服务器端。是sun公司定义的一个接口。
执行流程:1. 第一次请求,请求头中没有jsessionid的cookie,当访问到对应的servlet资源时,执行到getSession()会创建HttpSession对象;进而响应时就将session的id作为cookie的value,响应到浏览器 Set-cookie:jsessionid=xxxx;2. 再一次请求时,http请求中就有一个cookie:jsessionid=xxxx信息,那么该servlet就可以通过getSession()获取到jsessionid在服务器内查找对应的session对象,有就使用,无就创建。
// 获取session对象HttpSession session = request.getSession();// 获取session对象的唯一标识:sessionID (JSESSIONID=E925DE1EF00F7944537C01A3BC0E2688)String jsessionid = session.getId();// 销毁session对象中的jsessionidsession.invalidate();
// 往 session 中存储 msgHttpSession session = request.getSession();session.setAttribute(\"msg\
数据共享
<session-config> <session-timeout>30</session-timeout></session-config>
web.xml
一般都是默认值 30 分钟,无需更改。
浏览器关闭:销毁Cookie中的jsessionid=xxx,原session对象会保留默认30min后才销毁,30分钟后为新的session;session销毁:调用 session.invalidate() 方法后,立即将session对象销毁,再次访问时会创建新的session。
DAOImpl
c3p0-0.9.5.4.jarcommons-dbutils-1.7.jarmchange-commons-java-0.2.16.jarmysql-connector-java-5.1.48.jar
c3p0连接池
ShowServlet
LoginServlet
CreateCodeServlet
login.html
页面和Servlet
案例:使用验证码登陆和共享用户信息
Session
生命周期为服务器开启和关闭,而且所有用户都会共享,范围过大,保密性不高。
ServletContext
生命周期太短,一次请求就丢失,无法再重定向后再次获取内容
request
存储在客户端浏览器,不安全!客户端浏览器可对cookie进行查看或修改,而且cookie无法定义特殊符号
cookie
存储在服务器,默认30分钟才销毁更新,或者服务器中主动销毁,适合用户登陆信息的共享
session
http请求中4大共享数据方式
CookieUtils
Cookie工具类
会话技术
对客户端向服务器发送的请求进行过滤,用于在请求之前处理资源的组件。Filter和Listener都属于Servlet中的高级部分,Filter是最为实用的技术。
基本信息
请求时,从客户端到服务端顺序处理;响应时,从服务端到客户端顺序处理。> 遵从原则:先过滤,后放行。
过滤器链
执行流程:1. 浏览器发起请求2. 服务器会根据这个请求,创建 request 对象及 response 对象3. 过滤器会持有 request 对象及 response 对象4. 只有当过滤器放行之后,request 对象及 response 对象才会传给 Servlet
* 随着服务器的初始化而初始化* 随着服务器的关闭而销毁
开发步骤:1. 自定义类实现 Filter 接口(包:javax.servlet.Filter)2. 重写 init() doFilter() destroy() 三个方法3. 在 web.xml 中配置过滤器:①声明过滤器 ②配置过滤器的过滤路径
public class Filter01 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println(\"Filter01 过滤器的初始化\"); } @Override public void font color=\"#f15a23\
FilterDemo
<!--声明Filter01过滤器--><filter> <filter-name>Filter01</filter-name> <filter-class>com.demo.filter.Filter01</filter-class></filter><!--配置Filter01的过滤路径--><filter-mapping> <filter-name>Filter01</filter-name> <!--/ 代表所有资源都过滤--> <url-pattern>/*</url-pattern></filter-mapping>
<!--无限接近SpringMVC中文乱码解决方案--> <filter> <filter-name>EncodingFilter</filter-name> <filter-class>com.demo.filter.EncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param></filter><filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
步骤:声明过滤器,配置过滤路径。
<url-pattern>标签中的匹配规则:\t* / 完全匹配\t* /开头,*结尾 目录匹配\t* *开头,后缀名结尾 后缀名匹配
匹配规则
@WebFilter注解WebInitParam[] initParams() default {}; //配置初始化参数String filterName() default \"\"; //配置过滤器名称String[] servletNames() default {}; //配置过滤的ServletString[] urlPatterns() default {}; //配置过滤路径
使用注解
注解配置
配置方式
页面乱码处理 login.jsp 不会乱码
html 请求和响应乱码
方式一:过滤器处理
方式二:继承(通用Servlet)
中文乱码
1. 登陆账户后,根据是否勾选了自动登录选项框2. 判断是否访问和登陆相关资源 * 如果是,直接放行 * 如果不是,判断是否已经在登陆状态 * 如果已登陆,直接放行 * 如果不是,需要从cookie中取出存储的用户信息,进行登陆操作 * 如果登陆成功,直接放行 * 如果登陆失败,就跳转到登陆页面
逻辑流程
流程图示
ShowIndexServlet
AutoLoginFilter
AutoLoginServlet
login.jsp
代码逻辑
案例:实现自动登陆
使用动态代理模式在过滤器中增强 request.getParameter() 方法使其在浏览器发起请求时拥有过滤敏感词功能。
核心逻辑
SensitiveWordsFilter
案例:请求中的敏感词过滤
过滤器
概念:监听器就是一个实现了特定接口的Java类
一类监听器:监听域对象的创建、销毁
二类监听器:监听域对象中的属性变更(属性设置、属性替换、属性移除)
三类监听器:监听域对象中的java对象的绑定
事件源:request、session、servletContext三大域对象
监听器:Servlet对象(三种监听器)
绑定:web.xml配置 或 @WebListener注解
事件:域对象发生改变
Servlet监听器
1. 实现了特定接口的类为监听器,用来监听另一个Java类的方法调用或者属性改变;2. 当被监听的对象发生了方法调用或者属性改变后,监听器的对应方法就会立即执行。
监听ServletContext域对象的创建、销毁
// 服务器启动,ServletContext域对象创建,该监听器方法则执行public void contextInitialized(ServletContextEvent servletContextEvent)// 服务器关闭,ServletContext域对象销毁,该监听器方法则执行public void contextDestroyed(ServletContextEvent servletContextEvent)
ServletContextListener
监听HttpSession域对象的创建、销毁
// 服务器第一次调用getSession方法时,该监听器方法被执行public void sessionCreated(HttpSessionEvent httpSessionEvent)// session过期/调用了invalidate方法销毁session时,该监听器方法被执行public void sessionDestroyed(HttpSessionEvent httpSessionEvent)
问题:* 访问一个Servlet会不会创建session对象?会!* 访问一个JSP页面会不会创建session对象?会!* 访问一个HTML页面会不会创建session对象?不会!
HttpSessionListener
监听ServletRequest域对象的创建、销毁
// 客户端向服务器发送了一个请求,服务器就会为该请求创建一个request对象,该监听器方法就被执行public void requestInitialized(ServletRequestEvent servletRequestEvent)// 当服务器为这次请求做出了响应后,将request对象销毁,该监听器方法就被执行public void requestDestroyed(ServletRequestEvent servletRequestEvent)
问题:* 访问一个Servlet会不会创建request对象?会!* 访问一个JSP页面会不会创建request对象?会!* 访问一个HTML页面会不会创建request对象?不会!
ServletRequestListener
一类
ServletContextAttributeListener
HttpSessionAttributeListener
ServletRequestAttributeListener
二类
监听session域对象中的java对象的状态(绑定和解绑)绑定:将java对象存储到session域对象解绑:将java对象从session域对象移除* 该监听器不需要在web.xml中配置
开发步骤:Java对象实现该接口,重写方法。
HttpSessionBindingListener
三类
// 监听ServletContext域对象中属性的【添加】void attributeAdded(ServletContextAttributeEvent var1);// 监听ServletContext域对象中属性的【替换】void attributeReplaced(ServletContextAttributeEvent var1);// 监听ServletContext域对象中属性的【移除】void attributeRemoved(ServletContextAttributeEvent var1);
定义类实现监听器接口
重写方法
<listener> <listener-class>Listener的全限定名</listener-class></listener>
配置 web.xml
@WebListener
逻辑图示
LogoutServlet
User
代码实现
案例:统计在线人数
监听器
登陆成功,修改登陆状态,跳转首页登陆失败,跳转到登陆页面
登陆
不再登陆状态,提示用户登陆在登陆状态,显示用户名显示注销登陆按钮显示用户列表
首页
session.removeAttribute / session.invalidate注销成功,跳转到登陆页面注销失败,跳转到首页,重新手动注销登陆
注销
不在登陆状态,不显示用户列表在登陆状态: · 操作数据库,获取所有用户 · 通过table标签将用户列表显示出来
用户列表
在table的每一行中都添加一个删除按钮在添加删除按钮时,会给出所在行的记录的id在点击删除按钮时,请求删除用户的DeleteUserServlet删除成功与否都跳转首页
在table的每一行中都添加一个复选框在每个删除标签中,需要给给每个复选框,设定name属性、value属性 · name=\"ids\" · value就是每一行记录的id当点击批量删除按钮时,请求批量删除的ServletDeleteUsersServlet删除成功与否都跳转到首页
批量删除
首页新加一个添加用户按钮点击添加用户按钮之后,跳转到添加用户页面当点击提交按钮,开始添加用户AddUserServlet 添加成功跳转首页,添加失败,跳转到添加用户页面
添加用户
在table的每一行中都添加一个修改按钮点击修改用户按钮之后,跳转到修改用户页面ShowUpdateUserServlet: · 获取要修改的用户信息 · 生成要修改用户的页面点击提交按钮,开始修改用户UpdateUserServlet · 修改成功跳转到首页 · 修改失败,跳转到修改用户页面
修改用户
BaseServlet充当了父类的通用Servlet,所有自定义的Servlet都继承于BaseServlet实现请求的分发,不同的请求交给不同的方法进行处理
UserServlet
BaseServlet
高级版
通用Servlet
综合案例:用户管理
作用在当前页面
pageContext
作用在一次请求中
默认随浏览器关闭而销毁(存储在浏览器,可设置更长生命周期)
作用在一次会话中,随浏览器关闭而销毁
随服务器初始化而初始化,服务器关闭而关闭
filter
listener
作用在服务器开启和关闭
ServletContext / application
生命周期划分
HTTP
JSP,java server page,和Servlet一样,是sun公司定义的一种动态网页技术。本质就是一个servlet,可以使用jsp代替servlet来处理请求,显示数据。即 jsp可以理解为在html页面中写java代码,或 一个可以获取java数据的html文件。
JSP为什么本质是一个Servlet?testjsp.jsp 继承自 testjsp.java/testjsp.class 继承自 HttpJspPage 继承自 JspPage 继承自 Servlet。Tomcat镜像中将jsp文件转义为了java文件和编译后的class字节码文件:C:\\Users\\Administrator\\.IntelliJIdea2019.3\\system\\tomcat\\Tomcat_8_5_53_demo61\\work\\Catalina\\localhost\\demo\\org\\apache\\jsp\\demo.java
/ * * 由Apache Tomcat的Jasper组件生成 * 版本:Apache Tomcat/8.5.53 * 生成时间:2020-xx-xx xx:xx:xx * 注意:此文件的最后修改时间设置为生成后源文件的最后修改时间,以帮助跟踪修改。 * /
/** Generated by the Jasper component of Apache Tomcat* Version: Apache Tomcat/8.5.53* Generated at: 2020-04-26 07:19:38 UTC* Note: The last modified time of this file was set to* the last modified time of the source file after* generation to assist with modification tracking.*/
查看生成java文件
① 当在浏览器上输入 http://localhost:8080/demo/index.jsp② 服务器tomcat得到请示,会通过JspServlet将后缀名是.jsp的请求处理③ 会将index.jsp翻译成index_jsp.java文件④ 再将index_jsp.java文件编译成index_jsp.class文件⑤ jvm将.class加载运行⑥ 服务器生成响应,响应信息中就包含了jsp页面上的html代码
JSP原理
可以在页面上写java代码
分类:● 声明脚本:<%! Java代码 %>在jsp对应的java类中生成一个成员变量● 片段脚本:<% Java代码 %>在jsp对应的java类的_jspService方法中,生成一个局部变量● 输出脚本:<%= Java代码 %>向浏览器输出内容,相当于 response.getWriter().write(Java代码)在jsp对应的java类的 out.prinln() 中
脚本
jsp文件中可以有 jsp + html + java 代码即 可以使用上述三种语言的注释标签。
● jsp:<%-- 注释 --%>jsp注释不会生成到jsp对应的java文件中● html:<!-- 注释 -->● java:/* 注释1 */ // 注释2html、java注释均会生成到jsp对应的java文件中
JSP脚本
用于指示jsp执行某些操作或特性行为/效果
<%@ 指令名称 属性1=\"值1\" 属性2=\"值2\" %>
设置jsp页面的基本属性
<%@ page contentType=\"text/html;charset=UTF‐8\" language=\"java\" import=\"java.util.List\" isELIgnored=\"false\" session=\"false\"%>
contentType=\"...\" 相当于 response.setContentType(\"...\") 设置编解码方式language=\"java\" jsp脚本上可以使用的语言,一般不用,默认javaimport=\"java.util.List\" 页面上导入java包,多个包使用逗号分隔(IDEA可以导入包,默认导入jsp页面顶部-为单独的page指令导包)isELgnored=\"false\" 是否忽略el表达式,默认false是不忽略errorPage=\"error.jsp\" 用于指定错误页面,当前页面发生错误后,会跳转到指定的错误页面isErrorPage=\"true\" 为true时可以在当前页面直接使用jsp内置对象exception,即 <%= exception.toString() %> 或 ${exception} 页面输出错误信息extends=\"org.apache.jasper.runtime.HttpJspBase\" 默认继承自HttpJspBase类,不动!
page 指令
在当前jsp页面导入 jstl 标签库(JSP标准标签库是由JCP所制定的标准规范)
uri属性确定标签库的位置,prefix属性指定标签库的前缀<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>
taglib 指令
嵌套其他jsp文件的jsp代码(其他jsp代码可以只是所需部分)
第一种 include指令:`通过file属性来指定被包含的页面`,当JSP转换成Servlet时引入指定文件,`一般不需要写头`<%@ pagecontentType=\"text/html;charset=GB2312\" language=\"java\"errorPage=\"\"%><%@ include file=\"head.jsp\"%><%@ include file=\"body.jsp\"%><%@ include file=\"tail.jsp\"%>
第二种 <jsp:include>动作元素:`通过page属性来指定被包含的页面`,当JSP页面被请求时引入指定文件,`需要写头`可以用<jsp:param>来向所包含页传递参数。<%@ page contentType=\"text/html; charset=GB2312\"language=\"java\" errorPage=\"\"%><jsp:include page=\"head.jsp\"/> <jsp:param name=\"uid\"value=\"username\"/> <jsp:param name=\"pwd\"value=\"password\"/></jsp:include><jsp:include page=\"body.jsp\"/><jsp:include page=\"tail.jsp\"/>
include 指令
JSP指令
能够在jsp页面上直接使用这些对象,一共有9个。9大对象就是jsp页面翻译成java文件中创建的对象,所以可以可以在jsp页面中直接使用。
page:页面对象,java.lang.Object类型的page对象request:HttpServletRequest,javax.servlet.http.HttpServletRequest类型的request对象response:HttpServletResponse,javax.servlet.http.HttpServletResponse类型的response对象session:HttpSession,javax.servlet.http.HttpSession类型的session对象application:ServletContext,javax.servlet.ServletContext类型的application对象out:JspWriter,javax.servlet.jsp.JspWriter类型的out对象config:ServletConfig,javax.servlet.ServletConfig类型的config对象exception:Throwable,java.lang.Throwable类型的exception对象pageContext:pageContext,javax.servlet.jsp.PageContext类型的pageContext对象
9大内置对象
代表 page 域,但是 jsp 中 page 它的类型是 Object,所以操作 page 域我们使用的是 pageContext 对象,page 域就是指当前页面
对应 Servlet 域对象:HttpServletRequest
作用在一次请求
对应 Servlet 域对象:HttpSession
作用在一次会话
对应 Servlet 域对象:ServletContext
作用在整个项目
application
4大域对象
① 获取其他内置对象
② 操作 page 域及其他域
pageContext 域对象
案例:JSP实现用户登陆
内置对象
${表达式}
代替 <%=变量值%> jsp脚本。
格式
算术、关系、逻辑、三目运算 Demo
${str == 'hello'}${str != 'hello'}
${not empty str}${empty str}
字符串判断/判空
el 运算操作
page域: ${pageScope.name1}
request域: ${requestScope.name2}
session域: ${sessionScope.name3}
application域: ${applicationScope.name4}
简写:${name}
获取方式
注意事项:* 如果 el 表达式没有获取到结果,返回的不是 null 而是 \"\" 空字符串;* ${name} 不指定域的写法,jsp 页面就会从小到大的域数据进行查找:pageScope -> requestScope -> sessionScope -> applicationScope* 域中的共享数据一定要区别 name 的名字,以区别不同的域;
数组 Demo
list Demo
map Demo
对象 Demo
获取内容
域对象操作 × 4
包含 4 个域对象:pageScope / requestScope / sessionScope / applicationScope包含 7 个 web 对象:param / paramValues / initParam / header / headerValues / cookie / pageContext常用:4个域对象 + cookie + pageContext
param <==> request.getParameter()paramValues <==> request.getParameters()initParam <==> 获取初始化参数header <==> 获取单个请求头headerValues <==> 获取一组请求头cookie <==> 获取 Map 类型的 cookie 对象pageContext <==> 获取 jsp 内置的 9 大对象
web 对象操作 × 11
操作
<% Integer count = (Integer) application.getAttribute(\"count\"); count = (count == null || count == 0) ? 1 : count+1; application.setAttribute(\"count\
案例:3行实现访问量统计
EL表达式
jstl.jar
standard.jar
WEB_INF/lib/ 导入jar包
<%@taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\" %>
当前 jsp 页面导入标签库
环境配置
<%-- set标签:往域中设置数据 --%><c:set var=\"msg\" scope=\"request\" value=\
向域中设置数据,等价于 域对象.setAttribute()
set
<%-- remove标签:从域中移除数据 --%><c:remove var=\"msg\" scope=\"request\"/><%-- 获取为空 --%>${msg}
将数据从域中移除,等价于 域对象.removeAttribute()
remove
<%-- catch标签:捕获异常 --%><c:catch var=\"e\"> <% int num = 1/0; %></c:catch><%-- 获取异常信息 --%>${e} <br>${e.message}
捕获异常,等价于 try-catch
catch
<%-- if标签:条件判断 --%><c:set var=\"msg\" scope=\"request\" value=\"100\"/><c:if test=\"${msg == 100}\"> msg 等于 100</c:if><c:if test=\"${msg != 100}\"> msg 不等于 100</c:if>
条件判断
if
<% List<String> strs = new ArrayList<>(); strs.add(\"hello\"); strs.add(\"world\"); strs.add(\"OMG\"); request.setAttribute(\"strs\
遍历数组或集合
foreach
<%-- forTokens标签:分割字符串 --%><% String s = \"hello:word:OMG\"; request.setAttribute(\"s\
分割字符串
fotTokens
核心标签
随用随查
格式化标签
SQL 标签
XML 标签
JSTL 函数
productList.jsp
bean.Product
dao.ProductDaoImpl
servlet.ProductServlet
综合案例:显示商品列表信息
jstl标签库
jsp:请求处理、业务处理、数据库操作、数据显示javaBean:数据封装
优点:开发简单缺点:维护难,代码几乎都在 jsp 中
① jsp+javaBean
jsp: 数据显示Servlet: 请求处理、业务处理、数据库操作javaBean: 数据封装
优点:维护方便,开发各司其职利于模块分工,适合开发复杂项目,组件可以重用缺点:开发难度大,对开发要求高
commons-beanutils-1.9.4.jarcommons-collections-3.2.2.jarcommons-logging-1.2.jar
jar 包下载:http://commons.apache.org/proper/commons-beanutils/download_beanutils.cgi
导入3个 jar 包
要求:页面上的参数 name 名需要与Bean实体类的属性名完全一致。
BeanUtils 框架
public class User { private Integer id; private String username; private String password; private Integer age; ...}
RegServlet.doPost()
<form action=\"/demo/reg\" method=\"post\"> 账号:<input type=\"text\" name=\"username\"> <br> 密码:<input type=\"text\" name=\"password\"> <br> 年龄:<input type=\"text\" name=\"age\"> <br> <button type=\"submit\">注册</button></form>
regist.jsp
精简版的 BeanUtils 源码实现逻辑
自定义 MyBeanUtils.populate()
② jsp+javaBean+Servlet
JSP 模式
Model View Controller,经典设计模式,用一种业务逻辑,数据,界面分离的方式来组织代码,将业务聚集到一个部件中,方便程序的重复使用,提高开发效率。
模型层,数据封装
Model
视图层,数据显示
View
控制层,请求处理
Controller
业务层,业务逻辑
Service
持久层,数据库操作
Dao
三层架构
MVC 组成
Tomcat 8.5Intellij IDEA 2020.3JDK 1.8
环境
BeanUtilsDbUtilsC3p0MySQLJSTL
依赖
配置文件
https://simple.blog.csdn.net/article/details/105849671
综合案例:JSP优化用户管理
MVC 设计模式
开发模式
主要解决页面数据加载过多,导致页面访问速度变慢的问题
一次性全部查询出来,存放到List中,在List中截取subList作为页数据
优:减少操作数据库的次数缺:数据量非常大,查询时间比较长
逻辑分页
页面查询一页,就从数据库里查询一页数量的数据
优:减少单次查询数据库的时间缺:增加了操作数据库的次数
物理分页
第1/10页 总记录数:100 每页10条 [首页] [上一页] [下一页] [尾页]
效果
当前页数 currentPage
请求
总页数 totalPage
总记录数 totalSize
每页记录数 pageSize
当前页数据 pageList
响应
请求和响应
PageBean 封装总页数 = (总记录数 % 每页记录数 == 0) ? (总记录数 / 每页记录数) : (总记录数 / 每页记录数 + 1);当前页数据 list = query( select * from limit font color=\"#c41230\
恶补
new ScalarHandler<>( )
https://simple.blog.csdn.net/article/details/105868086
源码案例
分页查询
本质就是将一台电脑中的文件根据网络协议通过 io 流传递到另一台电脑(服务器)上。
表单数据提交方式 POST
表单中设置文件上传项 <input type=\"file\">
enctype=multipart/form-data
三要素
commons-fileupload-1.4.jar
commons-io-2.6.jar
导入 jar 包
<form action=\"${pageContext.request.contextPath}/upload\" method=\"post\" enctype=\"multipart/form-data\"> 描述:<input type=\"text\" name=\"desc\"> <br> 上传附件:<input type=\"file\" name=\"file\"> <br> <button type=\"submit\">提交</button></form>
前台:文件上传项(JSP)
1. 创建磁盘文件项工厂对象 DiskFileItemFactory2. 创建核心解析类 ServletFileUpload3. 解析请求,获取到所有的文件项
后台:编写 Servlet
实现步骤
parseRequest(HttpServletRequest request) 解析请求,并获取相关文件项
setHeaderEncoding(String encoding) 解决中文文件名乱码
ServletFileUpload 核心解析类
boolean isFormField() 返回为true,普通字段。返回为false,就是文件
String getFieldName() 获取表单 name 字段
String getString(String encoding) 根据指定编码格式获取字段值,解决描述文本中文乱码
String getName() 获取上传文件名称
InputStream getInputStream() 获取上传文件对应的输入流
FileItem 文件项
文件上传API
// 1. 创建磁盘文件项工厂对象// 2. 创建核心解析对象ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());// 解决文件名中文乱码问题servletFileUpload.setHeaderEncoding(\"utf-8\");
文件名中文乱码
// 判断 fileItem 是否是上传的文件if (fileItem.isFormField()) { // true:其他的 form 项 // 描述 text 的中文内容乱码问题 System.out.println(fileItem.getString(\"utf-8\"));} else { ... }
描述内中文乱码
// 文件名 = 当前时间毫秒值 + 用户名(不重复) + 文件名String path = serverPath + File.separator + System.currentTimeMillis() + \"-\" + username + \"-\" + fileItem.getName();
文件名重复问题
乱码和重复问题
UploadServlet
FileListServlet
controller
service
dao
bean
文件上传+数据库
上传 Upload
本质就是将一台电脑(服务器)中的文件根据网络协议通过 io 流传递到另外一台电脑上。
浏览器支持的文件格式,可在浏览器打开;浏览器不支持才会提示下载
超链接
手动编写代码的方式下载
两种形式
<a href=\"${pageContext.request.contextPath}/download?fileName=${file.fileName}\">下载</a>
下载入口
// 1. 设置媒体类型 <- 获取下载文件的媒体类型String fileName = request.getParameter(\"fileName\");String mimeType = request.getServletContext().getMimeType(fileName);response.setContentType(mimeType);
设置媒体类型
String userAgent = request.getHeader(\"User-Agent\");String newFileName = userAgent.contains(\"Chrome\
设置下载窗口
// 3. IO读写文件: 读出服务器文件,响应写入到浏览器String path = request.getServletContext().getRealPath(\"upload\") + File.separator + fileName;BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));BufferedOutputStream bos = new BufferedOutputStream(response.font color=\"#f15a23\
IO读写(写-响应给浏览器)
不同浏览器编码方式不同:对文件名进行编码时以谷歌为代表的是 utf-8,其他浏览器是 base64
根据浏览器在下载窗口前设置编码方式
public String base64EncodeFileName(String fileName) { BASE64Encoder base64Encoder = new BASE64Encoder(); try { return \"=?UTF‐8?B?\" + new String(base64Encoder.encode(fileName.getBytes(\"UTF-8\"))) + \"?=\"; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); }}
base64编码
下载文件名中文乱码问题
下载 Download
上传下载
JSP
用来描述或者匹配一系列符合某个语法规则的字符串的单个字符串。即一种规则,有自己特殊的应用。
1. 匹配 测试字符串内的模式。例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。2. 替换 可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。3. 提取 基于模式匹配从字符串中提取子字符串,可以查找文档内或输入域内特定的文本。
String 成员方法:boolean matches(String regex); // 正则匹配String[] split(String regex); // 正则分割String font color=\"#f15a23\
Pattern 类:public static Pattern compile(String regex); // 编译正则public Matcher matcher(CharSequence input); // 匹配正则对象Matcher 类:boolean find() // 查找匹配子串String group() // 返回匹配子串String replaceAll(String replacement) // 替换所有String replaceFirst(String replacement) // 替换第一个
String reg = \"[a]{3}\";Pattern pattern = Pattern.compile(reg);Matcher matcher = pattern.matcher(\"aaa\");boolean b = matcher.matches();System.out.println(b); // true
匹配用法
String s = \"18937162148...safsdfa.f.ds.afsdf18566206696a651sdfas18937111765\";String reg = \"[1]{1}[356789]{1}\\\\d{9}\";Pattern pattern = Pattern.compile(reg);Matcher matcher = pattern.matcher(s);List<String> phones = new ArrayList<>();// find() 查找匹配的子字符串while (matcher.find()) { // group() 返回匹配的子字符串 phones.add(matcher.group());}System.out.println(phones);
提取用法
Pattern 类Matcher 类
方法和类
● `[abc]` a/b/c任意1个● `[^abc]` 除了a/b/c的任何字符● `[a-zA-Z]` a到z或A到Z含边界字符● `[0-9]` 0-9之间的字符都包括
单字符类
● `.` 任意1个字符● `\\d` 单个数字 [0-9]● `\\D` 非数字 [^0-9]● `\\w` 单词字符 [a-zA-Z_0-9]● `\\W` 非单词字符 [^\\w]● `\\s` 空白字符 [\\t\\\x0B\\f\]● `\\S` 非空白字符 [^\\s]
预定义字符类/元字符
数量词
正则规则
正则表达式
一门客户端脚本语言。
可以用来增强用户和 html 页面的交过过程,可以控制 html 元素,让页面有一些动态的效果,增强用户体验。
1992,Nombase开发,用于表单校验,ScriptEase1995,Netscape(网景)开发LiveScript,SUN公司更名JavaScript1997,ECMA协会制定标准ECMAScript,统一了所有客户端脚本语言的编码方式总结:JavaScript = ECMAScript + JavaScript(BOM+DOM)
发展
使用 console.log() 方法在浏览器中显示 JavaScript 值。F12 启用调试模式, 在调试窗口中点击 \"Console\" 菜单。font color=\"#c41230\
使用 window.alert() 弹出警告框。使用 document.write() 方法将内容写到 HTML 文档中。使用 innerHTML 写入到 HTML 元素。使用 console.log() 写入到浏览器的控制台。
输出
<head> <title>ECMAScript和页面结合之内部结合</title> <%--JS脚本内部结合--%> <script> console.log(\"js脚本111\") </script></head>
定义<script>标签,标签内就是js代码
内部JS
<head> <title>ECMAScript与页面结合之外部结合</title> <script src=\"${pageContext.request.contextPath}/xxx.js\"> /*外部结合方式后,script 标签内js代码无效*/ </script></head>
定义<script>,通过src属性引入外部的js文件
外部JS
a. <script>可以定义在页面的任何地方,位置会决定执行顺序b. <script>可以定义多个
单行 //多行 /* */
number:数字,整数/小数/NaN(一个不是数字的number类型)string:字符串,\"hello\" 'abc'boolean:true 和 falsenull:一个对象为空的占位符undefined:未定义,变量没有初始化时的初始值
基本对象:Array / Boolean / Date / Number / String / RegExp / Functions(全局函数对象) / Math / Events
创建方法
var 方法名 = new Function(\"形式参数列表\
Function对象
Java是强类型语言,JavaScript是弱类型语言。
var 变量名 = 初始化值;
获取变量的类型。
<script> console.log(typeof 123); // number console.log(typeof \"abc\
typeof
比较方式:1. 类型相同:直接比较,字符串按照字典顺序比较;2. 类型不同:先进行类型转换,再比较;(=== 全等于,类型和值都比较,先判断类型,类型不同,直接返回false)switch分支:1. Java中 switch 可接收的数据类型:byte int short char 枚举(jdk1.5) String(jdk1.7);2. JS中 switch 可接收的数据类型:任意JS中的基本数据类型
一元:++ --算术:+ - * / %赋值:= += -=比较:> < >= <= == ===(全等于)逻辑:&& || !三元:表达式 ? 值1 : 值2流程:if-else switch-case while do-while for try-catch
number:0或者NaN为 false,其他为 truestring:除了空字符串\"\"为 false,其他为 truenull 和 undefined:都是 false对象:所有对象都是 true
注意事项
demo
<a href=\"#\">跳转</a>// 死链接,点击跳转时页面和链接不会发生变化<a href=\"javascript:void(0)\">跳转</a>// 死链接,void中内容会执行但不会有任何返回<a href=\"javascript:void(alert('Warning'))\">跳转</a>
a标签
JS Array 对象方法
Array 对象
JS Date 对象方法
Date 对象
/^正则表达式$/
JS RegExp 对象方法
RegExp 对象
<script> // eval() 更多的用于 json 字符串返回 js 对象 var jsonStr = '{\"username\":\"root\
parseInt() // 数字字符串转换为数字isNaN() // 判断变量是否是NaNeval() // 多用于转换json字符串为js对象,以调用属性
JS 全局函数方法
全局函数对象
引用
// 第一种方式font color=\"#f15a23\
// 第二种方式var method02 = font color=\"#f15a23\
// 第三种方式 - 基本不用var method03 = new Function(\
三种方式
JavaScript 支持 内嵌函数(类似于成员内部类)
JavaScript 闭包
JavaScript Object Notation 一种轻量级的数据交换格式。易于阅读和编写,同时易于机器解析和生成(网络传输速率)。
同步请求中,数据从后台到前端,需要将数据对象存储在 域对象 中;异步请求中,数据从后台到前端,需要将数据对象转换为 JSON 字符串。根据 JavaBean 对象生成对应的 JSON 字符串。
JavaBean 有单一对象,容器对象,JSON对单一对象和容器对象有不同的写法。
{\"键1\
一个数据
[{\"键1\
一组数据
数据格式
FastJSON、Gson和Jackson性能对比 - CSDN
性能对比分析
FastJSON、Jackson、Gson
fastjson-1.2.62.jar
// 可转对象/list/map >> jsonUser user = new User(\"root\
对象 >>> json字符串
// 可转json字符串 >> 为java对象/list/map String jsonStr = \
json字符串 >> 对象
FastJson
ObjectMapper objectMapper = new ObjectMapper();
jackson-annotations-2.9.9.jarjackson-core-2.9.9.jarjackson-databind-2.9.9.jar
对象 >> json字符串
// 可转json字符串 >> 为java对象/list/mapString jsonStr = \
Jackson
Gson gson = new Gson();
gson.jar
Gson
Java中转换
<script> // 方式一:JSON.stringify() JSON.parse() var user = {\"username\": \"root\
<script> // 方式二:eval() 更多的用于 json 字符串返回 js 对象 var jsonStr = '{\"username\":\"root\
JavaScript中转换
JSON字符串
JavaScript 事件参考手册
事件参考手册
<%--事件源 + 绑定方式①--%>// 监听器function fn1() { console.log(\"按钮1点击了...\");}...<button onclick=\"fn1()\">事件按钮1</button>
<%--事件源 + 绑定方式②--%>// 获取 id 为 btn 的标签对象var ele = document.getElementById(\"btn\");// fn2 使用方式 ② - 不推荐function fn2() { console.log(\"按钮2点击了...\");}ele.onclick = fn2;...<button id=\"btn\">事件按钮2</button>
<%--事件源 + 绑定方式②--%>// 获取 id 为 btn 的标签对象var ele = document.getElementById(\"btn\");// fn2 使用方式 ① -- 最佳ele.onclick = function () { console.log(\"按钮2点击了...\");}...<button id=\"btn\">事件按钮2</button>
事件源:html标签监听器:js方法绑定/注册:标签中的属性赋值事件:具体的操作
触发条件
function fn1() { console.log(\"这是个图片。。\");}...<img src=\"img/girl.jpg\" onload=\"fn1()\">
图像
// 如果使用 dom 分配事件,推荐该方式(获取标签id的js代码可写在页面上方)// 监听页面加载完成后的操作window.onload = function () { console.log(\"页面加载完成\"); var ele = document.getElementById(\"girl\"); ele.onclick = function () { console.log(\"我正在疯狂的点击图片...\"); }}...<img id=\"girl\" src=\"img/girl.jpg\">
页面
页面或图像加载完成
onload
用户退出页面
onunload
图像加载被中断
onabort
当加载文档或图像时发生某个错误
onerror
加载
<script>function fn1() { console.log(\"1 获取焦点\"); }function fn2() { console.log(\"2 失去焦点\"); }function fn3() { console.log(\"3 获取焦点\"); }function fn4() { console.log(\"4 失去焦点\"); }</script><input type=\"text\" onfocus=\"fn1()\" onblur=\"fn2()\"> <br><input type=\"text\" onfocus=\"fn3()\" onblur=\"fn4()\">
元素获得焦点
onfocus
元素失去焦点
onblur
焦点
鼠标单击某个对象
onclick
鼠标双击某个对象
ondblclick
<script>function fn1() { console.log(\"鼠标按下\"); }function fn2() { console.log(\"鼠标移动\"); }function fn3() { console.log(\"鼠标松开\"); }</script><body onmousedown=\"fn1()\" onmousemove=\"fn2()\" onmouseup=\"fn3()\">
鼠标的按键被按下
onmousedown
鼠标的按键被松开
onmouseup
鼠标移动
onmousemove
鼠标移到某个元素上
onmouseover
鼠标从某个元素移开
onmouseout
鼠标
<script>function fn1() { console.log(event.keyCode + \" 键盘按下 \"); }function fn2() { console.log(event.keyCode + \" 键盘松开 \"); }</script><input type=\"text\" onkeydown=\"fn1()\" onkeyup=\"fn2()\">
键盘的键被按下
onkeydown
键盘的键被按下或按住
onkeypress
键盘的键被松开
onkeyup
键盘
重置按钮被点击
onreset
<script>function fn1() { console.log(\"表单提交了...\"); var num = 1; // 数据校验 if (num === 1) { return true; // 不拦截表单 } else { return false; // 拦截表单提交 }}</script><%-- return fn1() --%><form action=\"index.jsp\" onsubmit=\"return fn1()\">消息:<input type=\"text\" name=\"message\"> <br><button type=\"submit\">发送</button></form>
提交按钮被点击
onsubmit
按钮
<script>function fn1() { console.log(\"内容发生改变\"); }function fn2() { console.log(\"选项发生改变...\"); }</script><input type=\"text\" onchange=\"fn1()\"><select onchange=\"fn2()\"><option>选项1</option><option>选项2</option><option>选项3</option></select>
用户改变了内容
onchange
文本被选定
onselect
窗口或框架被调整尺寸
onresize
其他
监听事件
事件
Browser Object Model,浏览器对象模型
可以通过 window 对象获取其他4个BOM对象document\t对 Document 对象的只读引用。history\t对 History 对象的只读引用。location\t用于窗口或框架的 Location 对象。可以设置页面跳转路径Navigator\t对 Navigator 对象的只读引用。Screen\t对 Screen 对象的只读引用。
alert(message)\t显示带有一段消息和一个确认按钮的警告框。confirm(message)\t显示带有一段消息以及确认/取消对话框。promptspan style=\"font-size: inherit;\
window 对象
navigator 对象
screen 对象
length\t返回浏览器历史列表中的 URL 数量。
back()\t加载 history 列表中的前一个 URL。forward()\t加载 history 列表中的下一个 URL。go()\t加载 history 列表中的某个具体页面。
history 对象
hash\t设置或返回从井号 (#) 开始的 URL(锚)。host\t设置或返回主机名和当前 URL 的端口号。hostname\t设置或返回当前 URL 的主机名。href\t设置或返回完整的 URL。pathname\t设置或返回当前 URL 的路径部分。port\t设置或返回当前 URL 的端口号。protocol\t设置或返回当前 URL 的协议。search\t设置或返回从问号 (?) 开始的 URL(查询部分)。
assign()\t加载新的文档。reload()\t重新加载当前文档。replace()\t用新的文档替换当前文档。
location 对象
BOM 对象
核心 DOM 模型:document + element + node
document 文档对象
element 元素对象
node 节点对象
XML DOM
HTML DOM 定义了访问和操作 HTML 文档的标准方法。HTML DOM 把 HTML 文档呈现为带有元素、属性和文本的树结构(节点树)。
innerHTML / innerText
使用 HTML 元素对象的属性
控制元素样式
HTML DOM
获取 select 下所有的 option 中的文本信息
获取 select 下选中的 option 中的文本信息和 value 属性的值
在 select 下增加一个选项
全选 & 全不选 & 反选
正则校验的注册表单
JS:综合案例
JavaScript
Asynchronous Javascript And XML,异步 JavaScript 和 XML,一种创建交互式网页应用的网页开发技术。
通过在后台与服务器进行少量数据交换,AJAX可以是网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的部分内容进行更新。(普通不适用AJAX的网页如果需要更新则必须刷新整个页面内容)
1. 可以刷新局部页面内容2. 可以发起异步请求
同步请求:当页面内容发生改变时,必须全部刷新,且刷新的时候不能发出其他请求。异步请求:可以局部改变网页的内容,当正在发生改变时,其他的模块内容也可以发出请求。
异步&同步请求
ajax异步请求对象。
典型的xhr建立ajax的过程:1、new一个xhr对象;2、调用xhr对象的open方法;3、send一些数据;4、对服务器的响应过程进行监听,来知道服务器是否正确得做出了响应,接着就可以做一些事情。比如获取服务器响应的内容,在页面上进行呈现。
status / statusText:以数字/文本形式返回http状态码
* 当 b style=\
responseText / responsXML:获得字符串/XML形式的相应数据
getAllResponseHeader():获取所有的响应报头
getResponseHeader():查询响应中的某个字段的值
setRequestHeader(\"Content-Type\
模拟form表单,专用于POST请求
send(数据);
GET请求,send 方法不需要携带参数,直接将参数拼接在 open 方法的路径后面POST 请求,需要 send 方法带参来发送
XMLHttpRequest 对象
GET 请求
POST 请求
在以下情况中,请使用 POST 请求:无法使用缓存文件(更新服务器上的文件或数据库)向服务器发送大量数据(POST 没有数据量限制)发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
异步 GET/POST请求
Ajax
ServletDemo
JavaWeb
枚举
四舍五入
Stream流
Java
Thread
CodePart
janycode.github.io - Jerry
0 条评论
回复 删除
下一页