JavaWeb笔记 黑马程序员课程

1 篇文章 0 订阅

JavaWeb

摘要

主要用于记录JavaWeb的学习过程,希望对大家有所帮助。
该学习是基于黑马的JavaWeb课程,感兴趣的盆友可以在b站搜索javaweb进行观看学习。

Day 01 内容

04/07/2020

* Junit单元测试
* 反射
* 注解

Junit单元测试:

* 测试分类:
	* 黑盒测试:不需要写代码,给输入值,看程序能否输出期望值。
    		* 白盒测试:需要写代码。关注程序具体的执行流程。

* Junit使用:白盒测试
	* 步骤:
		1. 定义一个测试类(测试用例)
        	* 建议:
                * 测试类名:被测试的类名Test	calculatorTest
                * 包名:xxx.xxx.xxx.test
		2. 定义测试方法:可以独立运行

			* 建议:
				* 方法名:test测试的方法名	testadd
                * 返回值:void
                * 参数列表:空参
		3. 给方法加@Test
		4. 导入Junit依赖环境
 
	* 判定结果:
		* 红色:失败
		* 绿色:成功
		* 一般我们会使用断言操作来处理结果:
			* Assert.assertEquals(期望的结果, 运算的结果);
	* 补充
		* @before:
			* 修饰的方法会在测试方法之前被自动执行
		* @after:
			* 修饰的方法会在测试方法执行之后被自动执行

反射:框架设计的灵魂

* 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
* 反射:将类的各个组成部分封装为其他对象,这就是反射机制
	* 好处:
		1. 可以在程序运行过程中,操作这些对象。
		2. 可以解耦,提高程序的可扩展性

* 获取Class对象的方式:
	1. Class.forName("全类名"); 将字节码文件加载进内存,返回Class对象
		* 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
	2. 类名.class; 通过类名的属性class来获取
		* 多用于参数的传递
	3. 对象.getClass(); getClass()方法在Object类中定义
		* 多用于对象的获取字节码的方式
* 结论:同一个字节码文件(*.class)在一次程序的运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。


* Class对象功能:
	* 获取功能:
		1. 获取成员变量们
			* Field[] getFileds()
			* Filed getFiled(String name)
            * Field[] getDeclaredFileds()
            * Filed getDeclaredFiled(String name)
		2. 获取构造方法们
			* Constructor<?>[] getConstructors()
            * Constructor\<?\> getConstructor(类\<?\>... parameterTypes)
            * Constructor<?>[] getDeclaredConstructors()
            * Constructor\<?\> getDeclaredConstructor(类\<?\>... parameterTypes)
		3. 获取成员方法们
			* Method[] getMethods()
            * Method getMethod(String name)
            * Method[] getDeclaredMethods()
            * Method getDeclaredMethod(String name)
		4. 获取类名
			* String getName()


* Field:成员变量
	* 操作:
		1. 设置值
			* void set(Object obj, Object value)
		2. 获取值
			* get(Object obj)
		3. 忽略访问权限修饰符的安全检查
			* setAccessible(true):暴力反射


* Constructor:构造方法
	* 创建对象:
		* T newInstance(Object... initargs)
		* 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法


* Method:方法对象
	* 执行方法:
		* Object invoke(Object obj, Object... args)
	* 获取方法名称:
		* String getName()获取方法名


* 案例:
	* 需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法。
	* 实现:
		1. 配置文件
		2. 反射
	* 步骤:
		1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
        2. 在程序中去加载读取配置文件
        3. 使用反射技术来加载类文件进内存
        4. 创建对象
        5. 执行方法

注解:

* 概念:说明程序的。给计算机看的。

* 注释:用文字描述程序。给程序员看的。

* 概念描述:
	* jdk1.5之后的新特性
    * 说明程序的
    * 使用注解:@注解名称
  
* 作用分类
	* 编写文档:生成文档【doc文档】
    * 代码分析:通过注解对代码进行分析【使用反射】
    * 编译检查:让编辑器能实现基本的编译检查【@Override】

* JDK中预定义的一些注解
	* @Override:检测被该注解标注的方法是否是继承自父类(接口)的
    * @Deprecated:将该注解标注的内容,表示已过时
    * @SuppressWarnings:压制警告
    	* 一般传递参数all	@SuppressWarnings("all")
  
* 自定义注解
	* 格式:
		* 元注解
        * public @interface 注解名称() {
        	属性列表;
        }
	* 本质:注解本质上就是一个接口,该接口默认继承Annotation

		* public interface 注解名称 extends java.lang.annotation.Annotation {}
	* 属性:接口中的抽象方法
		* 要求:
			1. 属性的返回值类型有下列取值:
				* 基本数据类型
				* String
                * 枚举
                * 注解
                * 以上类型的数组
			2. 定义了属性,在使用时需要给属性赋值
				1. 如果定义属性时,使用default关键字给属性默认初始值,则使用注解时可以不进行属性的赋值
                2. 如果只有一个属性需要赋值,并且属性的名称为value,则value可以省略,直接定义值即可【@SuppressWarnings】
                3. 数组赋值时,值使用{}包裹,如果数组中只有一个值,则{}可以省略

* 元注解:用于描述注解的注解
	* @Target:描述注解能够作用的位置
        * ElementType取值:
        * TYPE:可以作用于类上
        * METHOD:可以作用于方法上
        * FIELD:可以作用于成员变量上
	* @Retention:描述注解被保留的一个阶段
		* @Rentention(RententionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
	* @Documented:描述注解是否被抽取到api文档中
	* @Inherited:描述注解是否被子类继承
  
* 在程序中使用(解析)注解:获取注解中定义的属性值
	1. 获取注解定义的位置的对象	【Class,Method,Field】
	2. 获取指定的注解
		* getAnnotation(Class)
		* public class ProImpl implements Pro{
              public String className(){
                  return "day01.annotation.Demo1";
              }
              public String methodName(){
                  return "show";
              }
          }

	3. 调用注解中的抽象方法,获取配置的属性值

* 小结
	1. 以后大多数时候,我们会使用注解,而不是自定义注解
    2. 注解给谁用?
    	1. 编译器
    	2. 给解析程序用
    3. 注解不是程序的一部分,可以理解为注解就是一个标签

Day 02 内容

05/07/2020

* 数据库的基本概念
* MySQL数据库软件
	* 安装
    * 卸载
    * 配置
* SQL

数据库的基本概念

1. 数据库的英文单词:DataBase 简称 : DB
2. 什么是数据库?
	* 用于存储和管理数据的仓库。

3. 数据库的特点:
	1. 持久化存储数据的。其实数据库就是一个文件系统
	2. 方便存储和管理数据
	3. 使用了统一的方式来操作数据库 -- SQL

4. 常见的数据库软件	
	* 参见《MySQL基础.pdf》

MySQL数据库软件

1. 安装
	* 参见《MySQL基础.pdf》
2. 卸载
	1. 去mysql的安装目录找到my.ini文件
		* 复制 datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data"
	2. 卸载MySQL
	3. 删除C:/ProgramData目录下的MySQL文件夹。

3. 配置
	* MySQL服务启动
		1. 手动
		2. cmd--> services.msc 打开服务的窗口
		3. 使用管理员打开cmd
			* net start mysql :启动mysql的服务
			* net stop mysql :关闭mysql的服务
		
	* MySQL登录
		1. mysql -uroot -p【password】
		2. mysql -h【ip】 -uroot -p【连接目标的password】
		3. mysql --host=【ip】 --user=root --password=【密码】
	* MySQL退出
		1. exit
		2. quit

	* MySQL目录结构
		1. MySQL安装目录
			* 配置文件 my.ini
		2. MySQL数据目录
			* 几个概念
				* 数据库:文件夹
				* 表:文件
				* 数据:数据

SQL

1. 什么是SQL?
	Structured Query Language:结构化编程语言
	其实就是定义了操作所有关系型数据库的规则。每一种数据库操作的方式存在不一样的地方,称为"方言"
	
2. SQL通用语法
	1. SQL语句可以单行或多行书写,以分号结尾。
	2. 可使用空格和缩进来增强语句的可读性。
	3. MySQL数据库的SQL语句不区分大小写,关键字建议使用大写。
	4. 3种注释
		* 单行注释:-- 注释内容 或 # 注释内容(mysql 特有)
		* 多行注释:/* 注释 */

3. SQL分类
	1) DDL(Data Definition Language)数据定义语言用来定义数据库对象:数据库,表,列等。关键字:create, drop,alter 等
	2) DML(Data Manipulation Language)数据操作语言用来对数据库中表的数据进行增删改。关键字:insert, delete, update 等
	3) DQL(Data Query Language)数据查询语言用来查询数据库中表的记录(数据)。关键字:select, where 等
	4) DCL(Data Control Language)数据控制语言(了解)用来定义数据库的访问权限和安全级别,及创建用户。关键字:GRANT, REVOKE 等

DDL:操作数据库、表

1. 操作数据库:CRUD
	1. C(Create):创建
		* 创建数据库:
			* create database 数据库名称;
		* 创建数据库,判断不存在,再创建:
			* create database if not exists 数据库名称;
		* 创建数据库,并指定字符集
			* create database 数据库名称 character set 字符集名;
		* 练习: 创建db4数据库,判断是否存在,并制定字符集为gbk
			* create database if not exists db4 character set gbk;
	2. R(Retrieve):查询
		* 查询所有数据库的名称:
			* show databases;
		* 查询某个数据库的字符集:查询某个数据库的创建语句
			* show create database 数据库名称;
	3. U(Update):修改
		* 修改数据库的字符集
			* alter database 数据库名称 character set 字符集名称;
	4. D(Delete):删除
		* 删除数据库
			* drop database 数据库名称;
		* 判断数据库存在,存在再删除
			* drop database if exists 数据库名称;
	5. 使用数据库
		* 查询当前正在使用的数据库名称
			* select database();
		* 使用数据库
			* use 数据库名称;
2. 操作表
	1. C(Create):创建
		1. 语法:
			create table 表名(
				列名1 数据类型1,
				列名2 数据类型2,
				....
				列名n 数据类型n
			);
			* 注意:最后一列,不需要加逗号(,)
			* 数据库类型:
             	1. int:整数类型
					* age int,
                2. double:小数类型
                    * score double(5,2)
                3. date:日期,只包含年月日,yyyy-MM-dd
                4. datetime:日期,包含年月日时分秒	 yyyy-MM-dd HH:mm:ss
                5. timestamp:时间戳类型	包含年月日时分秒	 yyyy-MM-dd HH:mm:ss	
                	* 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值
                6. varchar:字符串
                    * name varchar(20):姓名最大20个字符
                    * zhangsan 8个字符  张三 2个字符
 		* 创建表:
            create table student(
                id int,
                name varchar(32),
                age int ,
                score double(4,1),
                birthday date,
                insert_time timestamp
            );
		* 复制表:
            * create table 表名 like 被复制的表名;	  	
    2. R(Retrieve):查询
        * 查询某个数据库中所有的表名称
            * show tables;
        * 查询表结构
            * desc 表名;
    3. U(Update):修改
        1. 修改表名
            alter table 表名 rename to 新的表名;
        2. 修改表的字符集
            alter table 表名 character set 字符集名称;
        3. 添加一列
            alter table 表名 add 列名 数据类型;
        4. 修改列名称 类型
            alter table 表名 change 列名 新列别 新数据类型;
            alter table 表名 modify 列名 新数据类型;
        5. 删除列
            alter table 表名 drop 列名;
    4. D(Delete):删除
        * drop table 表名;
        * drop table if exists 表名 ;                    
  • 客户端图形化工具:SQLYog

    1. 添加数据:

      • 语法:
        • insert into 表名(列名1,列名2,…列名n) values(值1,值2,…值n);
      • 注意:
        1. 列名和值要一一对应。
        2. 如果表名后,不定义列名,则默认给所有列添加值
          insert into 表名 values(值1,值2,…值n);
        3. 除了数字类型,其他类型需要使用引号(单双都可以)引起来
    2. 删除数据:

      • 语法:
        • delete from 表名 [where 条件]
      • 注意:
        1. 如果不加条件,则删除表中所有记录。
        2. 如果要删除所有记录
          1. delete from 表名; – 不推荐使用。有多少条记录就会执行多少次删除操作
          2. TRUNCATE TABLE 表名; – 推荐使用,效率更高 先删除表,然后再创建一张一样的表。
    3. 修改数据:

      • 语法:

        • update 表名 set 列名1 = 值1, 列名2 = 值2,… [where 条件];
      • 注意:

        1. 如果不加任何条件,则会将表中所有记录全部修改。

Day 03 内容

06/07/2020

1. DQL:查询语句
	1. 排序查询
	2. 聚合函数
	3. 分组查询
	4. 分页查询

2. 约束
3. 多表之间的关系
4. 范式
5. 数据库的备份和还原

DQL:查询语句

DQL:查询表中的记录

* select * from 表名;

1. 语法:
    select 
        字段列表
    from
        表名列表
    where
        条件列表
    group by
        分组字段
    having
        分组之后的条件
    order by
        排序
    limit
        分页限定

2. 基础查询
    1. 多个字段的查询
        select 字段名1,字段名2... from 表名;
        * 注意:
            * 如果查询所有字段,则可以使用*来替代字段列表。
    2. 去除重复:
        * distinct
    3. 计算列
        * 一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算)
        * ifnull(表达式1,表达式2):null参与的运算,计算结果都为null
            * 表达式1:哪个字段需要判断是否为null
            * 表达式2:如果该字段为null后的替换值。
    4. 起别名:
        * as:as也可以省略


3. 条件查询
    1. where子句后跟条件
    2. 运算符
        * > 、< 、<= 、>= 、= 、<>
        * BETWEEN...AND  
        * IN( 集合) 
        * LIKE:模糊查询
            * 占位符:
                * _:单个任意字符
                * %:多个任意字符
        * IS NULL  
        * and  或 &&
        * or  或 || 
        * not  或 !

            -- 查询年龄大于20岁

            SELECT * FROM student WHERE age > 20;

            SELECT * FROM student WHERE age >= 20;

            -- 查询年龄等于20岁
            SELECT * FROM student WHERE age = 20;

            -- 查询年龄不等于20岁
            SELECT * FROM student WHERE age != 20;
            SELECT * FROM student WHERE age <> 20;

            -- 查询年龄大于等于20 小于等于30

            SELECT * FROM student WHERE age >= 20 &&  age <=30;
            SELECT * FROM student WHERE age >= 20 AND  age <=30;
            SELECT * FROM student WHERE age BETWEEN 20 AND 30;

            -- 查询年龄22岁,18岁,25岁的信息
            SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25
            SELECT * FROM student WHERE age IN (22,18,25);

            -- 查询英语成绩为null
            SELECT * FROM student WHERE english = NULL; -- 不对的。null值不能使用 = (!=) 判断

            SELECT * FROM student WHERE english IS NULL;

            -- 查询英语成绩不为null
            SELECT * FROM student WHERE english  IS NOT NULL;



            -- 查询姓马的有哪些? like
            SELECT * FROM student WHERE NAME LIKE '马%';
            -- 查询姓名第二个字是化的人

            SELECT * FROM student WHERE NAME LIKE "_化%";

            -- 查询姓名是3个字的人
            SELECT * FROM student WHERE NAME LIKE '___';


            -- 查询姓名中包含德的人
            SELECT * FROM student WHERE NAME LIKE '%德%';

中间的部分内容在这里没有给出,因为本人这部分内容已经掌握,所以未给出。

今日内容

1. 多表查询
2. 事务
3. DCL

多表查询

* 查询语法:
    select
        列名列表
    from
        表名列表
    where....
* 准备sql
    # 创建部门表
    CREATE TABLE dept(
        id INT PRIMARY KEY AUTO_INCREMENT,
        NAME VARCHAR(20)
    );
    INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');
    # 创建员工表
    CREATE TABLE emp (
        id INT PRIMARY KEY AUTO_INCREMENT,
        NAME VARCHAR(10),
        gender CHAR(1), -- 性别
        salary DOUBLE, -- 工资
        join_date DATE, -- 入职日期
        dept_id INT,
        FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键,关联部门表(部门表的主键)
    );
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);
* 笛卡尔积:
    * 有两个集合A,B .取这两个集合的所有组成情况。
    * 要完成多表查询,需要消除无用的数据
* 多表查询的分类:
    1. 内连接查询:
        1. 隐式内连接:使用where条件消除无用数据
            * 例子:
            -- 查询所有员工信息和对应的部门信息

            SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`;

            -- 查询员工表的名称,性别。部门表的名称
            SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`;

            SELECT 
                t1.name, -- 员工表的姓名
                t1.gender,-- 员工表的性别
                t2.name -- 部门表的名称
            FROM
                emp t1,
                dept t2
            WHERE 
                t1.`dept_id` = t2.`id`;


        2. 显式内连接:
            * 语法: select 字段列表 from 表名1 [inner] join 表名2 on 条件
            * 例如:
                * SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;	
                * SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;	

        3. 内连接查询:
            1. 从哪些表中查询数据
            2. 条件是什么
            3. 查询哪些字段
    2. 外链接查询:
        1. 左外连接:
            * 语法:select 字段列表 from 表1 left [outer] join 表2 on 条件;
            * 查询的是左表所有数据以及其交集部分。
            * 例子:
                -- 查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示部门名称
                SELECT 	t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
        2. 右外连接:
            * 语法:select 字段列表 from 表1 right [outer] join 表2 on 条件;
            * 查询的是右表所有数据以及其交集部分。
            * 例子:
                SELECT 	* FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;
    3. 子查询:
        * 概念:查询中嵌套查询,称嵌套查询为子查询。
            -- 查询工资最高的员工信息
            -- 1 查询最高的工资是多少 9000
            SELECT MAX(salary) FROM emp;

            -- 2 查询员工信息,并且工资等于9000的
            SELECT * FROM emp WHERE emp.`salary` = 9000;

            -- 一条sql就完成这个操作。子查询
            SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp);

        * 子查询不同情况
            1. 子查询的结果是单行单列的:
                * 子查询可以作为条件,使用运算符去判断。 运算符: > >= < <= =
                * 
                -- 查询员工工资小于平均工资的人
                SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp);
            2. 子查询的结果是多行单列的:
                * 子查询可以作为条件,使用运算符in来判断
                -- 查询'财务部'和'市场部'所有的员工信息
                SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部';
                SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2;
                -- 子查询
                SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');

            3. 子查询的结果是多行多列的:
                * 子查询可以作为一张虚拟表参与查询
                -- 查询员工入职日期是2011-11-11日之后的员工信息和部门信息
                -- 子查询
                SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2
                WHERE t1.id = t2.dept_id;

                -- 普通内连接
                SELECT * FROM emp t1,dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` >  '2011-11-11'

    * 多表查询练习

            -- 部门表
            CREATE TABLE dept (
              id INT PRIMARY KEY PRIMARY KEY, -- 部门id
              dname VARCHAR(50), -- 部门名称
              loc VARCHAR(50) -- 部门所在地
            );

            -- 添加4个部门
            INSERT INTO dept(id,dname,loc) VALUES 
            (10,'教研部','北京'),
            (20,'学工部','上海'),
            (30,'销售部','广州'),
            (40,'财务部','深圳');



            -- 职务表,职务名称,职务描述
            CREATE TABLE job (
              id INT PRIMARY KEY,
              jname VARCHAR(20),
              description VARCHAR(50)
            );

            -- 添加4个职务
            INSERT INTO job (id, jname, description) VALUES
            (1, '董事长', '管理整个公司,接单'),
            (2, '经理', '管理部门员工'),
            (3, '销售员', '向客人推销产品'),
            (4, '文员', '使用办公软件');



            -- 员工表
            CREATE TABLE emp (
              id INT PRIMARY KEY, -- 员工id
              ename VARCHAR(50), -- 员工姓名
              job_id INT, -- 职务id
              mgr INT , -- 上级领导
              joindate DATE, -- 入职日期
              salary DECIMAL(7,2), -- 工资
              bonus DECIMAL(7,2), -- 奖金
              dept_id INT, -- 所在部门编号
              CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
              CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
            );

            -- 添加员工
            INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES 
            (1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),
            (1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),
            (1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),
            (1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),
            (1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),
            (1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),
            (1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),
            (1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20),
            (1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),
            (1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),
            (1011,'沙僧',4,1004,'2007-05-23','11000.00',NULL,20),
            (1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),
            (1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),
            (1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);



            -- 工资等级表
            CREATE TABLE salarygrade (
              grade INT PRIMARY KEY,   -- 级别
              losalary INT,  -- 最低工资
              hisalary INT -- 最高工资
            );

            -- 添加5个工资等级
            INSERT INTO salarygrade(grade,losalary,hisalary) VALUES 
            (1,7000,12000),
            (2,12010,14000),
            (3,14010,20000),
            (4,20010,30000),
            (5,30010,99990);

            -- 需求:

            -- 1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
            /*
                分析:
                    1.员工编号,员工姓名,工资,需要查询emp表  职务名称,职务描述 需要查询job表
                    2.查询条件 emp.job_id = job.id

            */
            SELECT 
                t1.`id`, -- 员工编号
                t1.`ename`, -- 员工姓名
                t1.`salary`,-- 工资
                t2.`jname`, -- 职务名称
                t2.`description` -- 职务描述
            FROM 
                emp t1, job t2
            WHERE 
                t1.`job_id` = t2.`id`;



            -- 2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
            /*
                分析:
                    1. 员工编号,员工姓名,工资 emp  职务名称,职务描述 job  部门名称,部门位置 dept
                    2. 条件: emp.job_id = job.id and emp.dept_id = dept.id
            */

            SELECT 
                t1.`id`, -- 员工编号
                t1.`ename`, -- 员工姓名
                t1.`salary`,-- 工资
                t2.`jname`, -- 职务名称
                t2.`description`, -- 职务描述
                t3.`dname`, -- 部门名称
                t3.`loc` -- 部门位置
            FROM 
                emp t1, job t2,dept t3
            WHERE 
                t1.`job_id` = t2.`id` AND t1.`dept_id` = t3.`id`;

            -- 3.查询员工姓名,工资,工资等级
            /*
                分析:
                    1.员工姓名,工资 emp  工资等级 salarygrade
                    2.条件 emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary
                        emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary
            */
            SELECT 
                t1.ename ,
                t1.`salary`,
                t2.*
            FROM emp t1, salarygrade t2
            WHERE t1.`salary` BETWEEN t2.`losalary` AND t2.`hisalary`;



            -- 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
            /*
                分析:
                    1. 员工姓名,工资 emp , 职务名称,职务描述 job 部门名称,部门位置,dept  工资等级 salarygrade
                    2. 条件: emp.job_id = job.id and emp.dept_id = dept.id and emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary

            */
            SELECT 
                t1.`ename`,
                t1.`salary`,
                t2.`jname`,
                t2.`description`,
                t3.`dname`,
                t3.`loc`,
                t4.`grade`
            FROM 
                emp t1,job t2,dept t3,salarygrade t4
            WHERE 
                t1.`job_id` = t2.`id` 
                AND t1.`dept_id` = t3.`id`
                AND t1.`salary` BETWEEN t4.`losalary` AND t4.`hisalary`;



            -- 5.查询出部门编号、部门名称、部门位置、部门人数

            /*
                分析:
                    1.部门编号、部门名称、部门位置 dept 表。 部门人数 emp表
                    2.使用分组查询。按照emp.dept_id完成分组,查询count(id)
                    3.使用子查询将第2步的查询结果和dept表进行关联查询

            */
            SELECT 
                t1.`id`,t1.`dname`,t1.`loc` , t2.total
            FROM 
                dept t1,
                (SELECT
                    dept_id,COUNT(id) total
                FROM 
                    emp
                GROUP BY dept_id) t2
            WHERE t1.`id` = t2.dept_id;


            -- 6.查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询

            /*
                分析:
                    1.姓名 emp, 直接上级的姓名 emp
                        * emp表的id 和 mgr 是自关联
                    2.条件 emp.id = emp.mgr
                    3.查询左表的所有数据,和 交集数据
                        * 使用左外连接查询

            */
            /*
            select
                t1.ename,
                t1.mgr,
                t2.`id`,
                t2.ename
            from emp t1, emp t2
            where t1.mgr = t2.`id`;

            */

            SELECT 
                t1.ename,
                t1.mgr,
                t2.`id`,
                t2.`ename`
            FROM emp t1
            LEFT JOIN emp t2
            ON t1.`mgr` = t2.`id`;

事务

1. 事务的基本介绍
    1. 概念:
        * 如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败
    2. 操作:
        1. 开启事务:start transection
        2. 回滚:rollback
        3. 提交:commit
    3. MySQL数据库中事务默认提交
        * 事务提交的两种方式:
            * 自动提交:
                * mysql就是自动提交的
                * 一条DML(增删改)语句会自动提交一次事务。
            * 手动提交:
                * Oracle数据库默认是手动提交事务
                * 需要先开启事务,再提交
        * 修改事务的默认提交方式:
            * 查看事务的默认提交方式:SELECT @@autocommit; -- 1 代表自动提交  0 代表手动提交
            * 修改默认提交方式: set @@autocommit = 0;
2. 事务的四大特征
    1. 原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。
    2. 持久性:当事务提交或回滚后,数据库会持久化的保存数据。
    3. 隔离性:多个事务之间。相互独立。
    4. 一致性:事务操作前后,数据总量不变
3. 事务的隔离级别(了解)
    * 概念:多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。
    * 存在问题:
        1. 脏读:一个事务,读取到另一个事务中没有提交的数据
        2. 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。
        3. 幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。
    * 隔离级别:
        1. read uncommitted:读未提交
            * 产生的问题:脏读、不可重复读、幻读
        2. read committed:读已提交 (Oracle)
            * 产生的问题:不可重复读、幻读
        3. repeatable read:可重复读 (MySQL默认)
            * 产生的问题:幻读
        4. serializable:串行化
            * 可以解决所有的问题

        * 注意:隔离级别从小到大安全性越来越高,但是效率越来越低
        * 数据库查询隔离级别:
            * select @@tx_isolation;
        * 数据库设置隔离级别:
            * set global transaction isolation level  级别字符串;

    * 演示:
        set global transaction isolation level read uncommitted;
        start transaction;
        -- 转账操作
        update account set balance = balance - 500 where id = 1;
        update account set balance = balance + 500 where id = 2;

DCL

* SQL分类:
    1. DDL:操作数据库和表
    2. DML:增删改表中数据
    3. DQL:查询表中数据
    4. DCL:管理用户,授权

* DBA:数据库管理员

* DCL:管理用户,授权
    1. 管理用户
        1. 添加用户:
            * 语法:CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
        2. 删除用户:
            * 语法:DROP USER '用户名'@'主机名';
        3. 修改用户密码:

            UPDATE USER SET PASSWORD = PASSWORD('新密码') WHERE USER = '用户名';
            UPDATE USER SET PASSWORD = PASSWORD('abc') WHERE USER = 'lisi';

            SET PASSWORD FOR '用户名'@'主机名' = PASSWORD('新密码');
            SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123');

            * mysql中忘记了root用户的密码?
                1. cmd -- > net stop mysql 停止mysql服务
                    * 需要管理员运行该cmd

                2. 使用无验证方式启动mysql服务: mysqld --skip-grant-tables
                3. 打开新的cmd窗口,直接输入mysql命令,敲回车。就可以登录成功
                4. use mysql;
                5. update user set password = password('你的新密码') where user = 'root';
                6. 关闭两个窗口
                7. 打开任务管理器,手动结束mysqld.exe 的进程
                8. 启动mysql服务
                9. 使用新密码登录。
        4. 查询用户:
            -- 1. 切换到mysql数据库
            USE myql;
            -- 2. 查询user表
            SELECT * FROM USER;

            * 通配符: % 表示可以在任意主机使用用户登录数据库

    2. 权限管理:
        1. 查询权限:
            -- 查询权限
            SHOW GRANTS FOR '用户名'@'主机名';
            SHOW GRANTS FOR 'lisi'@'%';

        2. 授予权限:
            -- 授予权限
            grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
            -- 给张三用户授予所有权限,在任意数据库任意表上

            GRANT ALL ON *.* TO 'zhangsan'@'localhost';
        3. 撤销权限:
            -- 撤销权限:
            revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';
            REVOKE UPDATE ON db3.`account` FROM 'lisi'@'%';

Day 04 内容:

07/07/2020

1. JDBC基本概念
2. 快速入门
3. 对JDBC中各个接口和类详解

JDBC

1. 概念:Java DataBase Connectivity	Java数据库连接,Java语言操作数据库
    * JDBC本质:其实是官网(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商可以去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类

2. 快速入门:
    * 步骤:
        1. 导入驱动jar包 mysql-connnector-java-x.x.x-bin.jar
            1. 复制mysql-connnector-java-x.x.x-bin.jar包到项目libs目录下
            2. 右键-->Add as library
        2. 注册驱动
        3. 获取数据库的连接对象 Connection
        4. 定义sql
        5. 获取执行sql语句的对象 Statement
        6. 执行sql,接收返回结果
        7. 处理结果
        8. 释放资源

    * 代码实现:
        // 1.导入驱动jar包
        // 2.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 3.获取数据库连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1",
                "root", "********");
        // 4.定义sql语句
        String sql = "insert into test values(1, \"test\")";
        // 5.获取执行sql的对象Statement
        Statement statement = connection.createStatement();
        // 6.执行sql
        int count = statement.executeUpdate(sql);
        // 7.处理结果
        System.out.println(count);
        // 8.释放资源
        statement.close();
        connection.close();

3. 详解各个对象
    1. DriverManager: 驱动管理对象
        * 功能:
            1. 注册驱动:告诉程序该使用哪一个数据库驱动jar包
                static void registerDriver(Driver driver): 注册给定的驱动程序 DriverManager
                写代码使用: Class.forName("com.mysql.jdbc.Driver");
                通过查看源码发现: 在com.mysql.jdbc.Driver类中存在静态代码块
                static {
                    try {
                        DriverManager.registerDriver(new Driver());
                    } catch (SQLException var1) {
                        throw new RuntimeException("Can't register driver!");
                    }
                }

                注意:mysql5之后的驱动jar包可以省略注册驱动的步骤
            2. 获取数据库连接:
                * 方法: static Connerction getConnection(String url, String user, String password)
                * 参数:
                    * url:指定连接的路径
                        * 语法: jdbc:mysql://ip地址(域名):端口号/数据库名称
                        * 例子: jdbc:mysql://localhost:3306/db1
                        * 细节: 如果连接的是本机mysql服务器,并且mysql服务默认端口为3306,则url可以简写为jdbc:mysql:///数据库名称
                    * user:用户名
                    * password:密码

    2. Connection: 数据库连接对象
        1. 功能:
            1. 获取执行sql的对象
                * Statement createStatement()
                * PreparedStatement prepareStatement(String sql)
            2。 管理事务:
                * 开启事务: void setAutoCommit(boolean autoCommit)	: 调用该方法设置参数为false,即开启事务
                * 提交事务: void commit()
                * 回滚事务: void rollback()

    3. Statement: 执行sql的对象
        1. 执行sql
            1. booleann execute(String sql) : 可以执行任意的sql 了解
            2. int executeUpdate(String sql) : 执行DML(insert、update、delete)语句、DDL(create、alter、drop)语句
                * 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0执行成功 反之失败
            3. ResultSet executeQuery(String sql) : 执行DQL(select)语句
        2. 练习:
            1. account表 添加一条记录
            2. account表 修改记录
            3. account表 删除一条记录

            代码:
                Connection connection = null;
                Statement statement = null;
                try {
                    // 1.注册驱动
                    Class.forName("com.mysql.cj.jdbc.Driver");
                    // 2.定义sql
                    String sql = "insert into account values(null, '王五', 3000)";
                    // 3.获取Connection对象
                    connection= DriverManager.getConnection("jdbc:mysql:///db1",
                            "root", "******");
                    // 4.获取执行sql的对象
                    statement = connection.createStatement();
                    // 5.执行sql
                    int count = statement.executeUpdate(sql);
                    // 6.处理结果
                    System.out.println(count);
                    if(count > 0){
                        System.out.println("添加成功");
                    }else{
                        System.out.println("添加失败");
                    }
                } catch (ClassNotFoundException | SQLException e) {
                    e.printStackTrace();
                } finally {
                    // 避免空指针异常
                    if(statement != null){
                        try {
                            statement.close();
                        } catch (SQLException throwables) {
                            throwables.printStackTrace();
                        }
                    }
                    if(connection != null){
                        try {
                            connection.close();
                        } catch (SQLException throwables) {
                            throwables.printStackTrace();
                        }
                    }
                }

    4. ResultSet: 结果集对象,封装查询结果
        * next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),返回boolean值
        * getXxx(参数):获取数据
            * Xxx代表数据类型	如: int getInt()
            * 参数:
                1. int: 代表列的编号,从1开始
                2. String: 代表列名称
        * 注意:
            * 使用步骤:
                1. 游标向下移动一行
                2. 判断是否有数据
                3. 获取数据
            while(rs.next()){...}

        * 练习:
            * 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。
                1. 定义Emp类
                2. 定义方法 public List<Emp> findAll(){}
                3. 实现方法 select * from emp;

    5. PreparedStatement: 执行sql的对象
        1. SQL注入问题: 在拼接SQL时,有一些sql的特殊关键字参与字符串的拼接,会造成安全性问题
            1. 输入用户随便,输入密码:a' or 'a' = 'a
            2. sql : select * from USER where username = 'xxx' and password = 'a' or 'a' = 'a';

        2. 解决sql注入问题:使用PreparedStatement来解决
        3. 预编译的SQL:参数使用?作为占位符
        4. 步骤:
            1. 导入驱动jar包 mysql-connnector-java-x.x.x-bin.jar
            2. 注册驱动
            3. 获取数据库的连接对象 Connection
            4. 定义sql
                * 注意:sql的参数使用?作为占位符。如: select * from user where username = ? and password = ?
            5. 获取执行sql语句的对象 PreparedStatement	Connection.preparedStatement(String sql)
            6. 给?赋值:
                * 方法:setXxx(参数1, 参数2)
                    * 参数1: ?的位置编号 从1 开始
                    * 参数2: ?的值
            7. 执行sql,接收返回结果,不需要传递sql语句
            8. 处理结果
            9. 释放资源
        5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作
            1. 可以防止sql注入
            2. 效率更高

抽取JDBC工具类 : JDBCUtils

* 目的:简化书写
* 分析:
    1. 注册驱动也抽取
    2. 抽取一个方法获取连接对象
        * 需求:不想传递参数(麻烦),还得保证工具类的通用性。
        * 解决:配置文件
            jdbc.properties
                url=
                user=
                password=
    3. 抽取一个方法释放资源
* 代码实现:
    public class JDBCUtils {
        private static String url;
        private static String user;
        private static String password;
        private static String driver;
        /**
         * 文件的读取只需要读取一次即可拿到这些值,使用静态代码块完成
         */
        static {
            try {
                // 读取资源文件,获取值。

                // 1.创建Properties集合类
                Properties pro = new Properties();

                // 获取src路径下的文件的方式--->ClassLoader 类加载器
                ClassLoader classLoader = JDBCUtils.class.getClassLoader();
                URL result = classLoader.getResource("jdbc.properties");
                String path = result.getPath();

                // 2.加载文件
                pro.load(new FileReader(path));
                // 3.获取属性赋值
                url = pro.getProperty("url");
                user = pro.getProperty("user");
                password = pro.getProperty("password");
                driver = pro.getProperty("driver");
                // 4.注册驱动
                try {
                    Class.forName(driver);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        /**
         * 获取连接
         * @return 连接对象
         */
        public static Connection getConnection() throws SQLException {
            return DriverManager.getConnection(url, user, password);
        }

        /**
         * 释放资源
         * @param statement
         * @param connection
         */
        public static void close(Statement statement, Connection connection){
            if(statement != null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

            if(connection != null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

        public static void close(ResultSet resultSet, Statement statement, Connection connection){
            if(statement != null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

            if(connection != null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }

            if(resultSet != null){
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }

    * 练习:
        * 需求:
            1. 通过键盘录入用户名和密码
            2. 判断用户是否登录成功
                * select * from USER where username = '' and password = '';
                * 如果这个sql有查询结果,则成功,反之失败

        * 步骤:
            1. 创建数据库表 user
                CREATE TABLE USER(
                    id INT PRIMARY KEY AUTO_INCREMENT,
                    username varchar(32),
                    password varchar(32)
                );

                INSERT INTO USER VALUES(NULL,'zhangsan','123');
                INSERT INTO USER VALUES(NULL,'lisi','234');

            2. 创建一个类
            ......

JDBC控制事务

1. 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则者多个步骤要么同时成功,要么同时失败。
2. 操作:
    1. 开启事务
    2. 提交事务
    3. 回滚事务
3. 使用Connection对象来管理事务
    * 开启事务: void setAutoCommit(boolean autoCommit)	: 调用该方法设置参数为false,即开启事务
        * 在执行sql之前开启事务(在获得连接后开启)
    * 提交事务: void commit()
        * 当所有sql都执行完提交事务
    * 回滚事务: void rollback()
        * 在catch中回滚事务

Day 05 内容:

1. 数据库连接池
2. Spring JDBC : JDBC Template

数据库连接池

1. 概念:其实就是一个容器(集合),存放数据库连接的容器
	当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

2. 好处:
	1. 节约资源
	2. 用户访问高效

3. 实现:
	1. 标准接口:DataSource	javax.sql包下的
		1. 方法:
			* 获取连接:getConnection()
			* 归还连接:Connection.close()
				如果连接对象Connection是从连接池中获取的,那么调用Connection.close(),则不会再关闭连接,而是归还连接。

	2. 一般我们不去实现它,由数据库厂商实现
		1. C3P0:数据库连接池技术
		2. Druid:数据库连接池实现技术,由阿里巴巴提供的

4. C3P0:数据库连接池技术
	* 步骤:
		1. 导入jar包 (两个)c3p0-0.6.5.2.jar mchange-commons-java-0.2.12.jar
			* 不要忘记导入数据库驱动jar包
		2. 定义配置文件:
			* 名称:c3p0.properties 或者 c3p0-config.xml
			* 路径:直接将文件放在src目录下即可
		
		3. 创建核心对象:数据库连接池对象 ComboPooledDataSource
		4. 获取连接:getConnection()

5. Druid:数据库连接池实现技术,由阿里巴巴提供的
	1. 步骤:
		1. 导入jar包 druid-1.0.9.jar
		2. 定义配置文件:
			* 是properties形式的
			* 可以叫任意名称,可以放在任意目录下
		3. 加载配置文件 	Properties
		4. 获取数据库连接池对象:通过工厂类来获取	DruidDataSourceFactory
		5. 获取连接:getConnection()

	2. 定义工具类
		1. 定义一个类 JDBCUtils
		2. 提供静态代码块加载配置文件,初始化连接池对象
		3. 提供方法
			1. 获取连接方法:通过数据库连接池获取连接
			2. 释放资源
			3. 获取连接池的方法
			代码:
				/**
                 * Druid连接池的工具类
                 */
                public class JDBCUtils {

                    // 1.定义成员变量 DataSource
                    private static DataSource ds;

                    static {
                        try {
                            // 1.加载配置文件
                            Properties pro = new Properties();
                            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
                            // 2.获取DataSource
                            ds = DruidDataSourceFactory.createDataSource(pro);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                    /**
                     * 获取连接
                     */
                    public static Connection getConnection() throws SQLException {
                        return ds.getConnection();
                    }

                    /**
                     * 释放资源
                     * @param statement
                     * @param connection
                     */
                    public static void close(Statement statement, Connection connection){
                        if(statement != null){
                            try {
                                statement.close();
                            } catch (SQLException throwables) {
                                throwables.printStackTrace();
                            }
                        }

                        if(connection != null){
                            try {
                                connection.close();
                            } catch (SQLException throwables) {
                                throwables.printStackTrace();
                            }
                        }
                    }

                    public static void close(ResultSet resultSet, Statement statement, Connection connection){
                        if(statement != null){
                            try {
                                statement.close();
                            } catch (SQLException throwables) {
                                throwables.printStackTrace();
                            }
                        }

                        if(connection != null){
                            try {
                                connection.close();
                            } catch (SQLException throwables) {
                                throwables.printStackTrace();
                            }
                        }

                        if(resultSet != null){
                            try {
                                resultSet.close();
                            } catch (SQLException throwables) {
                                throwables.printStackTrace();
                            }
                        }
                    }

                    /**
                     * 获取连接池方法
                     */
                    public static DataSource getDataSource(){
                        return ds;
                    }
                }

Spring JDBC

* Spring框架对JDBC的简单封装。提供了JDBC Template对象简化JDBC的开发
* 步骤:
	1. 导入jar包
	2. 创建JdbcTemplate对象。依赖于数据源DataSource
		* JdbcTemplate template = new JdbcTemplate(ds);

	3. 调用JdbcTemplate的方法来完成CRUD的操作
		* update(): 执行DML语句。增、删、改语句
		* queryForMap(): 查询结果,将结果集封装为Map集合,将列名作为key,将值作为value,将这条记录封装为value
			* 注意:这个方法查询的结果集长度只能是1
		* queryForList(): 查询结果,将结果集封装为list集合
			* 注意:将每一条记录封装为Map集合,再将Map集合装载在List集合中
		* query(): 查询结果,将结果封装为JavaBean对象
			* query方法的参数:RowMapper
				* 一般使用BeanPropertiyRowMapper实现类。可以完成数据到JavaBean的自动封装。
				* new BeanPropertyRowMapper<类型>(类型.class)
		* queryForObject(): 查询结果,将结果封装为对象
			* 一般用于聚合函数的查询 

	4. 练习:
		* 需求:
			1. 修改1号数据的 salary 为 10000
			2. 添加一条记录
			3. 删除刚才添加的记录
			4. 查询id为1的记录,将其封装为Map集合
			5. 查询所有的记录,将其封装为List集合
			6. 查询所有记录,将其封装为Emp对象的List集合
			7. 查询总的记录数

Day 06 内容:

1. web概念概述
2. HTML

web概念概述

* JavaWeb:
	* 使用Java语言开发基于互联网的项目

* 软件的架构:
	1. C/S:Client/Server 客户端/服务器端
		* 在用户本地有一个客户端程序,在远程有一个服务器端程序
		* 如:QQ,迅雷...
		* 优点:
			1. 用户体验好
		* 缺点:
			1. 开发、安装、部署、维护麻烦
	2. B/S:Browser/Server 浏览器/服务器端
		* 只需要一个浏览器,用户通过不同的网址(URL),可以访问远程不同的服务器端程序
		* 优点:
			1. 开发、安装、部署、维护简单
		* 缺点:
			1. 如果应用过大,用户的体验可能会受到影响
			2. 对硬件要求过高

* B/S架构详解
	* 资源分类:
		1. 静态资源:
			* 使用静态网页开发技术发布的资源
			* 特点:
				* 所有用户访问,得到的结果是一样的
				* 如:文本、图片、音频、视频,HTML,CSS,JavaScript
				* 如果用户请求的是静态资源,那么服务器会直接将静态资源发送给浏览器,浏览器中内置了静态资源的解析引擎
		2. 动态资源:
			* 使用动态网页技术发布的资源
			* 特点:
				* 所有用户访问,得到的结果可能不一样
				* 如:jsp/servlet,php,asp...
				* 如果用户请求的是动态资源,那么服务器将会执行动态资源,转换为静态资源,再发送给浏览器

	* 我们要学习动态资源,必须先学习静态资源!
	
	* 静态资源:
		* HTML:用于搭建基础网页,展示页面的内容
		* CSS:用于美化页面,布局页面
		* JavaScript:控制页面的元素,让页面有一些动态的效果

HTML

1. 概念:是最基础的网页开发语言
	* Hyper Text Markup Language 超文本标记语言
		* 超文本:
			* 超文本是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本。
		* 标记语言:
			* 由标签构成的语言。<标签名称> 如html, xml
			* 标记语言不是编程语言

2. 快速入门:
	* 语法:
		1. html文档后缀名 .html 或者 .htm
		2. 标签分为
			1. 围堵标签:有开始标签和结束标签。如 <html> </html>
			2. 自闭和标签:开始标签和结束标签在一起。 如 <br />

		3. 标签可以嵌套:
			需要正确嵌套,不能你中有我,我中有你
			错误: <a><b></a></b>
			正确: <a><b></b></a>
			
		4. 在开始标签中可以定义属性。属性是由键值对组成,值需要用引号(单双都可)引起来
		5. html的标签不区分大小写,建议使用小写。

3. 标签学习:
	1. 文件标签:构成html最基本的标签
		* html:html文档的根标签
		* head:头标签。用于指定html文档的一些属性。引入外部的资源
		* title:标题标签
		* body:体标签
		* <!DOCTYPE html>:html5中定义改文档是html文档
	2. 文本标签:和文本有关的标签
		* 注释:<!-- -->
		* <h1> to <h6>:标题标签
			* h1~h6字体大小主键递减
		* <p>:段落标签
		* <br>:换行标签
		* <hr>:展示一条水平线
			* 属性:
				* color:颜色
				* width:宽度
				* size:高度
				* align:对齐方式
					* center:居中
					* left:左对齐
					* right:右对齐
		* <b>:字体加粗
		* <i>:字体斜体
		* <font>:字体标签
			* 属性:
				* color:颜色
				* size:大小
				* face:字体
		* <center>:文本居中
		* 属性定义:
			* color:
				1. 英文单词:red,green,blue
				2. rgb(值1, 值2, 值3):值的范围:0~255	如 rgb(0,0,2555)
				3. #值1值2值3:值的范围:00~FF。 如: #FF00FF
			* width:
				1. 数值:width='20',数值的单位,默认是 px(像素)
				2. 数值% :占比相对于父元素的比例

		* 案例
			...
	3. 图片标签
		* img:展示图片
			* 属性:
				* src:指定图片位置
			* 相对路径:
				* 以.开头的路径
					* ./: 代表当前目录	./image/1.jpg
					* ../: 代表上一级目录
	4. 列表标签:
		* 有序列表:
			* ol
			* li
		* 无序标签:
			* ul
			* li
	5. 链接标签
		* a:定义一个超链接
			* 属性:
				* href:指定访问资源的URL(统一资源定位符)
				* target:指定打开资源的方式
					* _self:默认值,在当前页面打开
					* _blank:在空白页面打开
	6. div和span:
		* div:每个div占满一整行。块级标签
		* span:文本信息在一行展示,行内标签,内联标签。

	7. 语义化标签:html5中为了提高程序的可读性,提供了一些标签
		1. <header>: 页眉
		2. <footer>: 页脚
	8. 表格标签
		* table:定义表格
			* width:宽度
			* border:边框
			* cellpadding:定义内容和单元格的距离
			* cellspacing:定义单元格之间的距离。如果指定为0,则单元格的线会合为一条。
			* bgcolor:背景色
			* align:对齐方式
		* tr:定义行
			* bgcolor:背景色
			* align:对齐方式
		* td:定义单元格
			* colspan:合并行
			* rowspan:合并列
		* th:定义表头单元格
		* <caption>:表格标题
		* <thead>:表示表格的头部分
		* <tbody>:表示表格的体部分
		* <tfoot>:表示表格的脚部分

案例:旅游网站首页

1. 确定使用table来完成布局
2. 如果某一行只有一个单元格,则使用<tr><td></td></tr>
3. 如果某一行有多个单元格,则使用
	<tr>
		<td>
			<table></table>
		</td>
	</tr>

Day 07 内容:

1. HTML标签:表单标签
2. CSS:

HTML标签:表单标签

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

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

* 表单项标签:
	* input:可以通过type属性值,改变元素展示的样式
		* type属性:
			* text:文本输入框,默认值
				* placeholder:指定输入框的提示信息,当输入框的内容发生变化,会自动清楚提示信息
			* password:密码输入框
			* radio:单选框
				* 注意:
					1. 要想让多个单选框实现单选的效果,则多个单选框的name属性值必须一样
					2. 一般会给每一个单选框提供value属性,指定其被选中后提交的值
					3. checked属性,可以指定默认值
			* checkbox:复选框
				* 注意:
					1. 一般会给每一个单选框提供value属性,指定其被选中后提交的值
					2. checked属性,可以指定默认值
			* file:文件选择框
			* hidden:隐藏域,用于提交一些信息
			* 按钮:
				* submit: 提交按钮,用于提交表单
				* button:普通按钮
				* image:图片提交按钮

		* label:指定输入项的文字描述信息
			* 注意
				* label的for属性一般会和input的id属性值对应。如果对应了,则点击label区域,会让input输入框获取焦点
	* select:下拉列表
		* 子元素option,指定列表项
	* textarea:文本域
		* cols:指定列数
		* rows:指定行数

CSS: 页面美化和布局控制

1. 概念:Cascading Style Sheets 层叠样式表
	* 层叠:多个样式可以作用在同一个html的元素上,同时生效

2. 好处:
	1. 功能强大
	2. 将内容展示和样式控制分类
		* 降低耦合度,解耦
		* 让分工合作更容易
		* 提高开发效率

3. CSS的使用:CSS和HTML结合方式
	1. 内联样式
		* 在标签内使用style属性指定css代码
		* 如	<div style="color:red;"></div>
	2. 内部样式
		* 在head标签内部定义style标签,style的标签内容就是css代码
		* 如	
			<style>
				div{
					color:blue;
				}
			</style>
			<div></div>
	3. 外部样式
		1. 定义css资源文件
		2. 在head标签内定义link标签,引入外部资源文件
	* 注意:
		* 1、2、3种方式,作用范围越来越大
		* 1方式不常用,后期常用2、3
		* 第3种格式可以写为:
			<style>
				@import "css/a.css";
			</style>
			
4. css语法:
	* 格式:
		选择器 {
			属性名1:属性值1;
			属性名2:属性值2;
			...
		}
	* 选择器:筛选具有相似特征的元素
	* 注意:
		* 每一对属性需要用分号隔开,最后一对属性可以不加

5. 选择器:
	* 分类:
		1. 基础选择器
			1. id选择器:选择具体的id属性值的元素,建议在一个html界面中id值唯一
				* 语法:#id属性值{}
			2. 元素选择器:选择具有相同标签的元素
				* 语法:标签名称{}
				* 注意:id选择器优先级高于元素选择器
			3. 类选择器:选择具有相同的class属性的元素
				* 语法:.class属性值{}
				* 注意:类选择器优先级高于元素选择器
		2. 扩展选择器:
			1. 选择所有元素
				* 语法:* {}
			2. 并集选择器
				* 语法:选择器1,选择器2 {}
			3. 子选择器:筛选选择器1元素下的选择器2
				* 语法:选择器1 选择器2 {}
			4. 父选择器:筛选选择器2父元素选择器1
				* 语法:选择器1 > 选择器2 {}
			5. 属性选择器:选择元素名称,属性名=属性值的元素
				* 语法:元素名称[属性名="属性值"] {}
			6. 伪类选择器:选择一些元素具有的状态
				* 语法:元素:状态 {}
				* 如:<a>
					* 状态:
						* link:初始化的状态
						* visited:被访问过的状态
						* active:正在访问状态
						* hover:鼠标悬浮状态
			
6. 属性
	1. 字体、文本
		* font-size:字体大小
		* color:文本颜色
		* text-alion:对齐方式
		* line-height:行高
	2. 背景
		* background:复合属性
	3. 边框
		* border:设置边框,复合属性
	4. 尺寸
		* width:宽度
		* height:高度
	5. 盒子模型:控制布局
		* margin:外边距
		* padding:内边距
			* 默认情况下内边距会影响整个盒子的大小
			* box-sizing: border-box
		* float:浮动
			* left
			* right

Day 08 内容:

1. JavaScript基础

JavaScript:

* 概念:一门客户端脚本语言
	* 运行在客户端浏览器中。每一个浏览器都有JavaScript的解析引擎
	* 脚本语言:不需要编译,直接就可以被浏览器解析执行了

* 功能:
	* 可以来增强用户和HTML页面的交互过程,可以来控制HTML元素,让页面有一些动态的效果,增强用户的体验。

* JavaScript发展史:
	1. 1992年,Nombase公司,开发出第一门客户端脚本语言,专门用于表单的校验。命名为:C--,后来更名为:ScriptEase
	2. 1995年,Netscape(网景)公司,开发了一门客户端脚本语言:LiveScript。请来SUN公司的专家,修改LiveScript,命名为JavaScript
	3. 1996年,微软抄袭JavaScript开发出JScript语言
	4. 1997年,ECMA(欧洲计算机制造商协会),ECMAScript,就是所有客户端脚本语言的标准。

	* JavaScript = ECMAScript + JavaScript自己特有的东西(BOM + DOM)

* ECMAScript:客户端脚本语言的标准
	1. 基本语法:
		1. 与HTML结合方式
			1. 内部JS:
				* 定义<script>,标签体内容就是js代码
			2. 外部JS:
				* 定义<script>,通过src属性引入外部的js文件

			* 注意:
				1. <script>可以定义在html页面的任何地方,但是定义的位置会影响执行的顺序。
				2. <script>可以定义多个。
		2. 注释
			1. 单行注释:// 注释内容
			2. 多行注释:/* 注释内容 */
		3. 数据类型:
			1. 原始数据类型(基本数据类型):
				1. number:数字。 整数/小数/NaN(not a number 一个不是数字的数字类型)
				2. string:字符串。 字符串 'abc' "a"
				3. boolean:true和false
				4. null:一个对象为空的占位符
				5. undefined:未定义。如果一个变量没有给初始化值,则会被默认为undefined
			2. 引用数据类型:对象
		4. 变量
			* 变量:一小块存储数据的内存空间
			* Java语言是强类型语言,而JavaScript是弱类型语言
				* 强类型:在开辟变量存储空间时,定义了空间将来存储的数据的数据类型。只能存储固定类型的数据。
				* 弱类型:在开辟变量存储空间时,不定义空间将来存储的数据的数据类型。可以存储任意类型的数据。
			* 语法:
				* var 变量名 = 初始化值;

			* typeof运算符:获取变量的类型
				* 注:null运算符后得到的时object
		5. 运算符
			1. 一元运算符:只有一个运算数的运算符
				++ -- +(正号)
			2. 算数运算符
				+ - * / %
			3. 赋值运算符
				= += -= ...
			4. 比较运算符
				> < >= <= == ===(全等于)
				* 比较方式
					1. 类型相同,直接比较
						* 字符串,按照字典顺序比较,按位逐一比较,直到得出大小为止。
					2. 类型不同,先进行类型转换,再比较
						* ===,全等于,在比较前先判断类型,如果类型不一样,则直接返回false
			5. 逻辑运算符
				&& || !
				* 其他类型转boolean
					1. number:0或NaN为假,其他为真
					2. string:除了空字符串(""),其他都是true
					3. null&undefined:false
					4. 对象:所有对象都为true
				* 可用if(obj)判断
					1. obj为空字符串
					2. obj为null或者undefined
			6. 三元运算符
				? :
		6. 流程控制语句:
			1. if...else...
			2. swtich
				* 在java种,switch语句可以接受的数据类型: byte int short char enum(1.5) String(1.7)
				* 在JS种,swtich语句可以接受任意的原始数据类型
			3. while
			4. do...while
			5. for
		7. JS特殊语法:
			1. 语句以;结尾,如果一行只有一条语句,则可以省略
			2. 变量的定义使用var关键字,也可以不使用
				* 用,定义的变量是局部变量
				* 不用,定义的变量是全局变量
		
	2. 基本对象:
		* Function:函数对象
			1. 创建
				1. var 方法名 = new Function(形式参数列表, 方法体);
				2. function 方法名(形式参数列表) {方法体}
				3. var 方法名 = function(形式参数列表) {方法体}
			2. 方法
			3. 属性
				length:代表形参的个数
			4. 特点
				1. 方法定义是,形参的类型不用写,返回值类型也不写
				2. 方法是一个对象,如果定义名称相同的方法,会覆盖
				3. 在JS中,方法的调用只与方法的名称有关,和参数列表无关
				4. 在方法声明中有一个隐藏的内置对象(数组),arguments,封装所有的实际参数
			5. 调用
				方法名称(实际参数列表);
				
		* Array:数组对象
			1. 创建:
				1. var arr = new Array(元素列表);
				2. var arr = new Array(默认长度);
				3. var arr = [元素列表];
			2. 方法
				join(参数):将数组中的元素按照指定的分隔符拼接为字符串
				push(参数):往数组最后添加一个元素
			3. 属性
				length:数组长度
			4. 特点
				1. JS中,数组元素的类型可变的。
				2. JS中,数组的长度是可变的。

		* Boolean
		* Date:日期对象
			1. 创建
				var date  = new Date();
			2. 方法
				toLocaleString():返回当前Date对象对应的实际本地字符串格式
				getTime():获取毫秒值,返回当前日期对象描述的时间和1970年1月1日零点的毫秒值差
		* Math:数学对象
			1. 创建:
				* 特点:Math对象不用创建直接使用。	Math.方法名();
			2. 方法:
				random():返回0~1之间的随机数。含0不含1
				cell(x):向上取整
				floor(x):向下取整
				round(x):四舍五入
			3. 属性
				PI
		* NUmber
		* String
		* RegExp:正则表达式对象
			1. 正则表达式:定义字符串的组成规则。
				1. 单个字符:[]
					如:[a] [ab] [a-zA-Z0-9]
					* 特殊符合代表特殊含义的单个字符
						\d:单个数字字符[0-9]
						\w:单个单词字符[a-zA-Z0-9_]
				2. 量词符号:
					?:表示出现0次或1次
					*:表示出现0次或多次
					+:出现一次或多次
					{m,n}:表示数量 m<=数量<=n
						* m如果缺省:{,n}:最多n次
						* n如果缺省:{m,}:最少m次
				3. 开始结束符号
					* ^:开始
					* $:结束
			2. 正则对象:
				1. 创建:
					1. var reg = new RegExp("正则表达式"); 注意反斜线的转义\\
					2. var reg = /正则表达式/;
				2. 方法
					1. test(参数):验证指定的字符串是否符合正则表达式
		* Global
			1. 特点:全局对象,这个Global中封装的方法不需要对象就可以直接调用。	方法名();
			2. 方法:
				encodeURI():url编码
				decodeURI():url解码
				
				encodeURIComponent():url编码,编码的字符更多
				decodeURIComponent():url解码
				
				parseInt():将字符串转为数字
					* 注意判断每一个字符是否是数字,直到不是数字为止,将前面数字的部分转为number
					* 没有数字转为NaN
				isNaN():判断一个值是否为NaN
					* 参与的==比较都为false 包括其自身参与的比较
				eval():将JS字符串转换为脚本运行
			3. URL编码
				* GBK编码:一个汉字两个字节
				* UTF-8编码:一个汉字三个字节
			
* BOM
* DOM

Day 09 内容:

1. JavaScript:
	1. ECMAScript
	2. BOM
	3. DOM:
		1. 事件

DOM简单学习:为了满足案例要求

* 功能:控制HTML文档的内容
* 代码:获取页面标签(元素)对象	Element
	* document.getElementById("id值");	通过元素id获取元素对象

* 操作Element对象:
	1. 修改属性值:
		1. 明确获取的对象是哪一个
		2. 查看API文档,找其中有哪些属性可以设置
	2. 修改标签体内容:
		* 属性:innerHTML

事件简单学习

* 功能:某些组件被执行了某些操作后,触发某些代码的执行。
* 如何绑定事件
	1. 直接在HTML标签上,指定事件的属性,属性值就是JS代码
		1. 事件:onclick--- 单击事件

	2. 通过JS获取元素对象,指定事件属性,设置一个函数

案例

* 分析
	1. 获取图片对象
	2. 绑定单击事件
	3. 每次点击切换图片
		* 规则,如果on换为off,反之亦然
		* 使用标记flag完成

BOM

1. 概念:Browser Object Model 浏览器对象模型
	* 将浏览器的各个部分封装成对象。
2. 组成
	* Window:窗口对象
	* Navigator:浏览器对象
	* Screen:显示器屏幕对象
	* History:历史记录对象
	* Location:地址栏对象

3. Window:窗口对象
	1. 创建
	2. 方法
		1. 与弹出框有关的方法
			alert()	弹出警告框
			confirm()	弹出对话框(确认或者取消)
				* 如果点击确定 返回true
				* 点击取消 返回false
			prompt()	弹出可输入的对话框
				* 返回值,获取用画输入的内容
		2. 与打开关闭有关的方法
			close() 关闭浏览器窗口
				* 谁调用关谁
			open() 打开一个浏览器窗口
				* 返回新的Window对象
		3. 与定时器有关的方法
			setTimeout()	在指定的毫秒数后调用函数或计算表达式。
				* 参数:
					1. js代码或者方法对象
					2. 毫秒值
				* 返回值:唯一标识,用于取消定时器
			clearTimeout()	取消由setTimeout()方法设置的timeout。
			
			setInterval()	按照指定的周期(以毫秒计)来调用函数或计算表达式。
			clearInterval()	取消由setInterval()设置的timeout。
	3. 属性
		1. 获取其他BOM对象
			history
			location
			Navigator
			Screen
		2. 获取DOM对象
			document
	4. 特点
		* Window对象不需要创建可以直接使用 window来使用 window.方法名();
		* window引用可以省略。	方法名();

4. Location:地址栏对象
	1. 创建(获取):
		1. window.location
		2. location
	2. 方法
		* reload() 重新加载当前文档 刷新
	3. 属性
		* href 设置或返回完整的URL

5. History:历史记录对象
	1. 创建(获取):
		1. window.history
		2. history

	2. 方法:
		* back()	加载history列表中的前一个 URL。
		* forward()	加载history列表中的下一个 URL。
		* go(参数)	加载history列表中的某个具体页面。
			* 参数
				* 正数:前进几个历史记录
				* 负数:后退几个历史记录

	3. 属性
		* length	返回浏览器历史列表中的 URL 数量。

DOM

* 概念:Document Object Model 文档对象模型
	* 将标记语言文档的各个部分,封装为对象。可以使用这些对象,对标记语言文档进行CRUD的动态操作
* W3C DOM 标准被分为3个不同的部分:
	* 核心DOM - 针对任何结构化文档的标准模型
		* Document:文档对象
		* Element:元素对象
		* Attribute:属性对象
		* Text:文本对象
		* Comment:注释对象
		
		* Node:节点对象,其他5个的父对象
	* XML DOM - 针对XML文档的标准模型
	* HTML DOM - 针对HTML文档的标准模型 

* 核心DOM模型:
	* Document:文档对象
		1. 创建(获取),在html dom模型中可以使用window对象来获取
			1. window.document
			2. document
		2. 方法
			1. 获取Element对象:
				1. getElementById():根据id属性值获取元素对象,id属性值一般唯一
				2. getElementByTagName():根据元素名称获取元素对象们,返回值是一个数组
				3. getElementByClassName():根据Class属性值获取元素对象们,返回值是一个数组
				4. getElementByName():根据name属性值获取元素对象们,返回值是一个数组
			2. 创建其他DOM对象
				createAttribute(name)
				createComment()
				createElement()
				createTextNode()
	* Element:元素对象
		1. 创建(获取),通过document来获取和创建
		2. 方法:
			1. removeAttribute():删除属性
			2. setAttribute():设置属性
	* Node:节点对象,其他5个的父对象
		* 特点:所有dom对象都可以被认为是一个节点
		* 方法:
			* CRUD dom树
				* appendChild():向节点的子节点列表的结尾添加新的子节点。
				* removeChild():删除(并返回)当前节点的指定子节点。
				* replaceChild():用新节点替换一个子节点。
		* 属性
			* parentNode:返回节点的父节点。
			
* HTML DOM
	1. 标签体的设置和获取:innerHTML
	2. 使用html元素对象和属性
	3. 控制样式
		1. 使用元素的style属性来设置
			如: div.style.fontSize = "20px";
		2. 提前定义好类选择器的样式,通过元素的className属性来设置其class属性值

事件监听机制

* 概念:某些组件被执行了某些操作后,触发某些代码的执行。
	* 事件:某些操作	如:单击、双击、键盘
	* 事件源:组件	如:按钮、文本输入框
	* 监听器:代码	
	* 注册监听:将事件源、事件、监听器绑定在一起。当事件源上发生了某个事件,则触发执行某个监听器代码

* 常见的事件:
	1. 点击事件:
		1. onclick:单击事件。
		2. ondblclick:双击事件。
	2. 焦点事件:
		1. onblur:失去焦点。
			* 一般用于表单验证
		2. onfocus:元素获得焦点。
	
	3. 加载事件
		1. onload:一张页面或一张图像加载完成。
		
	4. 鼠标事件
		1. onmousedown	鼠标按钮被按下。
			* 定义方法时,定义一个形参,接收event对象。
			* event对象的button属性可以获取鼠标哪个键被点击了
		2. onmousemove	鼠标被移动。
		3. onmouseout	鼠标从某元素移开。
		4. onmouseover	鼠标移到某元素之上。
		5. onmouseup	鼠标按键被松开。
		
	5. 键盘事件
		1. onkeydown	某个键盘按键被按下。
		2. onkeyup	某个键盘按键被松开。
		3. onkeypress	某个键盘按键被按下并松开。
		
	6. 选择和改变
		1. onchange	域的内容被改变。
		2. onselect	文本被选中。
		
	7. 表单事件
		1. onsubmit 确认按钮被点击。
			* 可以阻止表单的提交
				* 方法返回false,则表单被阻止提交
				* 注意:
					如果在标签中使用onsubmit 如<form onsubmit='false'></from>
					这样是无法实现的,原因是在系统进行创建html页面时会调用onsubmit = function(){"onsubmit=内的内容"}也就是onsubmit = function(){false},这个就相当于是没有返回值的,所以无法完成,要想完成,可以通过<form onsubmit='return false'></from>这样来完成,或者在script标签中通过DOM获取form对象设置onsubmit来完成,即document.getElementById('form').onsubmit=function (){return false};即可
		2. onreset	重置按钮被点击。
		
* 案例
	...
	见相应教程 这里就不赘述了
	https://www.bilibili.com/video/BV1J4411877m?p=189
	https://www.bilibili.com/video/BV1J4411877m?p=190

Day 10 内容:

1. Bootstrap

Boostrap

1. 概念:一个前端开发的框架。Bootstrap是美国Twitter公司的设计师Mark Otto和Jacob Thornton合作基于HTML、CSS、JavaScript 开发的简洁、直观、强悍的前端开发框架,使得 Web 开发更加快捷。
	* 框架:一个半成品软件,开发人员可以在框架基础上,再进行开发,简化编码
	* 好处
		1. 定义了很多css样式和js插件。我们开发人员可以直接使用这些样式和插件得到丰富的页面效果。
		2. 响应式布局。
			* 同一套页面可以兼容不同分辨率的设备。

2. 快速入门
	1. 下载Bootstrap
	2. 在项目中将这三个文件夹复制
	3. 创建html页面,引入必要的资源文件

响应式布局

* 同一套页面可以兼容不同分辨率的设备。
* 实现:依赖于栅格系统——将一行平均分成12个格子,可以去指定元素占几个格子
* 步骤:
	1. 定义容器,相当于之前的table
		* 容器分类:
			1. container:两边留白
			2. container-fluid:每一种设备都是100%宽度
	2. 定义行,相当于之前的tr		样式:row
	3. 定义元素。指定该元素在不同的设备上所占的格子数目。	样式:col-设备代号-格子数目
		* 设备代号:
			1. xs:超小屏幕 手机 (<768px):col-xs-12
			2. sm:小屏幕 平板 (≥768px)
			3. md:中等屏幕 桌面显示器 (≥992px)
			4. lg:大屏幕 大桌面显示器 (≥1200px)

	* 注意:
		1. 一行中如果格子数目超过12,则超出部分自动换行
		2. 栅格类属性可以向上兼容,栅格类适用于与屏幕宽度大于或等于分界点大小的设备 
		3. 如果真实设备宽度小于了设置的栅格类属性的设备代码的最小值,元素会占满一整行

CSS样式和JS插件

1. 全局CSS样式:
	* 按钮:class="btn btn-default"
	* 图片
		* class="img-responsive": 图片任意尺寸占100%
		* 形状:class="img-rounded" ...见文档
	* 表格
		* class="table"
		* class="table-hover"
	* 表单
		* 给表单项添加:class="form-control"
2. 组件:
	* 导航条
	* 分页条
3. 插件:
	* 轮播图

Day 11 内容:

1. XML
	1. 概念
	2. 语法
	3. 解析

XML

1. 概念:Extensible Markup Language 可扩展标记语言
	* 可扩展:标签都是自定义的。	<user> <student>

	* 功能:
		* 存储数据
			1. 配置文件
			2. 在网络中传输
	* xml和html的区别:
		1. xml标签都是自定义的,html的标签是预定义。
		2. xml的语法严格,html语法松散。
		3. xml是存储数据,html是展示数据的。

	* w3c:万维网联盟
	
2. 语法
	* 基本语法:
		1. xml后缀名 .xml
		2. xml第一行必须定义为文档声明
		3. xml文档中有且仅有一个根标签
		4. 属性值必须使用引号引起来(单双都可)
		5. 标签必须正确关闭
		6. xml标签名称区分大小写
	* 快速入门
		<?xml versionm='1.0' ?>
		<users>
			<user id='1'>
				<name>zhangsan</name>
			</user>
			<user id='2'>
				<name>lisi</name>
			</user>
		</users>
		
	* 组成部分:
		1. 文档声明
			1. 格式:<?xml 属性列表 ?>
			2. 属性列表
				* version:版本号,必须的属性
				* encoding:编码方式,告知解析引擎当前文档使用的字符集,默认值:ISO-8859-1
				* standalone:是否独立
					* 取值:
						* yes:不依赖其他文件
						* no:依赖其他文件
		2. 指令(了解):结合css
			* <?xml-stylesheet type="text/css" href="a.css" ?>
		3. 标签:标签名称是自定义的
			* 规则:
				* 名称可以包含字母、数字以及其他的字符
				* 名称不能以数字或者标点符号开始
				* 名称不能以字母xml或者(XML、Xml等等)开始
				* 名称不能包含空格
				
		4. 属性:
			id属性值唯一
		5. 文本
			* CDATA区:在该区域中的数据会被原样展示
				* 格式:<![CDATA[数据]]>

	* 约束:规定xml文档的书写规则
		* 作为框架的使用者(程序员):
			1. 能够在xml中引入约束文档
			2. 能够简单读懂约束文档

		* 分类:
			1. DTD:一种简单的约束技术
			2. Schema:一种复杂的约束技术

		* DTD:
			* 引入dtd文档到xml文档中
				* 内部dtd,将约束规则定义在xml文档中
				* 外部dtd,将约束规则定义在外部dtd文件中
					* 本地:<!DOCTYPE 根标签名 SYSTEM "dyd文件的位置">
					* 网络:<!DOCTYPE 根标签名 PUBLIC "dtd文件的名字" "dyd文件的位置url">

		* Schema:
			* 引入:
				1. 填写xml文档的根元素
				2. 引入xsi前缀 xmlns:xsi="..."
				3. 引入xsd文件命名空间 xsi:schemaLocation="... ..."(键值对的形式 前面代表名称 后面代表路径)
				4. 为每一个xsd约束声明一个前缀作为标识 xmlns:(自定义前缀)="..."
			
3. 解析:操作xml文档,将文档中的数据读取到内存中
	* 操作xml文档
		1. 解析(读取):将文档中的数据读取到内存中
		2. 写入:将内存中的数据保存到xml文档中,持久化的存储
		
	* 解析xml的方式:
		1. DOM:将标记语言文档一次性加载进内存,在内存中形成DOM树
			* 优点:操作方便,可以对文档进行CRUD的所有操作
			* 缺点:占内存
		2. SAX:逐行读取,基于事件驱动的。
			* 优点:不占内存。
			* 缺点:只能读取,不能增删改

	* xml常见的解析器:
		1. JAXP:sun公司提供的解析器,支持dom和sax两种思想
		2. DOM4J:一款非常优秀的解析器
		3. Jsoup:jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
		4. PULL:Android操作系统内置的解析器,sax方式的。

	* Jsoup:jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
		* 快速入门:
			* 步骤:
				1. 导入jar包
				2. 获取Document对象
				3. 获取对应的标签Element对象
				4. 获取数据

		* 代码
			// 2.获取Document对象 根据xml文档获取
            // 2.1获取studetns.xml路径
            String res = JsoupDemo1.class.getClassLoader()
                    .getResource("student.xml").getPath();
            String path = java.net.URLDecoder.decode(res, "utf-8");
            // 2.2解析xml文档 加载文档进内存 获取dom树
            Document document = Jsoup.parse(new File(path), "utf-8");
            // 3.获取元素对象 Element
            Elements ele = document.getElementsByTag("name");
            System.out.println(ele.size());
            // 3.1获取第一个name的element对象
            System.out.println(ele.get(0).text());
            
	* 对象的使用:
		1. Jsoup:工具类,可以解析html或xml文档,返回Document
			* parse:解析html或xml文档,返回Document
				* parse(File in, String charsetName):解析html或xml文件的
				* parse(String html):解析xml或xml字符串
				* parse(URL url, int timeoutMillis):通过网络路径获取指定的html或xml的文档对象
		2. Document:文档对象,代表内存中的dom树
			* 获取Element对象
				* getElementsByTag(String tagName):根据标签名称获取元素对象集合
				* getElementByAttribute(String key):根据书写名称获取元素对象集合
				* getElementByArributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合
				* getElementById(String id):根据id属性值获取唯一的Element对象
		3. Elements:元素Element对象的集合。可以当作ArrayList<Element>来使用
		4. Element:元素对象
			1. 获取子元素对象
				* getElementsByTag(String tagName):根据标签名称获取元素对象集合
				* getElementByAttribute(String key):根据书写名称获取元素对象集合
				* getElementByArributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合
				* getElementById(String id):根据id属性值获取唯一的Element对象
			2. 获取属性值
				* String attr(String key):根据属性名称获取属性值
				
			3. 获取文本内容
				* String text():获取所有子标签的纯文本内容
				* String html():获取标签体的所有内容,包括子标签的标签和文本内容
		5. Node:节点对象
			* 是Document和Element的父类
		
	* 快捷查询方式:
		1. selector:选择器
			* 使用的方法:Elements select(String cssQuery)
				* 语法:参考Selector类中定义的语法
		2. Xpath:XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。
			* 使用Jsoup的Xpath需要额外导入jar包
			* 查询w3cschool的参考手册,使用xpath语法完成查询

Day 12 内容:

1. web相关概念回顾
2. web服务器软件:Tomcat
3. Servlet入门学习

web相关概念回顾

1. 软件架构
	1. C/S:客户端/服务器端
	2. B/S:浏览器/服务器端

2. 资源分类
	1. 静态资源
	2. 动态资源

3. 网络通信三要素
	1. IP
	2. 端口
	3. 传输协议

web服务器软件

* 服务器:安装了服务器软件的计算机
* 服务器软件:接收用户的请求,处理请求,做出响应
* web服务器软件:接收用户的请求,处理请求,做出响应
	* 在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目
	* web容器

* 常见的java相关的web服务器软件:
	* webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
	* webSphere:IBM公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
	* JBOSS:JBOSS公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
	* Tomcat:Apache基金组织,中小型JavaEE服务器,仅支持少量的JavaEE规范servlet/jsp。开源的免费的。

* JavaEE:Java语言在企业级开发中使用的技术规范的综合,一共规范了13项大的规范

* Tomcat:web服务器软件
	1. 下载:官网下载
	2. 安装:解压压缩包即可
		* 注意:安装目录建议不要有中文空格
	3. 卸载:删除该目录
	4. 启动
		* bin/startup.bat,双击运行该文件即可
		* 访问:http://localhost:8080 访问自己 http://其他ip:8080 访问别人
		* 可能遇到的问题
			1. 黑窗口一闪而过
				* 原因:没有正确配置JAVA_HOME环境变量
				* 解决方案:正确配置JAVA_HOME环境变量
			2. 启动报错:
				1. 暴力:找到占用端口的进程并杀死
					* netstat -ano
				2. 温柔:修改自身的端口号
					* config/server.xml
					* 一般会将tomcat的默认端口号修改为80,为http协议的默认端口号
						* 好处:访问时不用输入端口号
	5. 关闭
		1. 正常关闭
			* bin/shutdown.bat
			* ctrl+c
		2. 强制关闭
			* 点击启动窗口的X按钮
	6. 配置:
		* 部署项目的方式:
			1. 直接将项目放到webapps目录下即可。
				* /hello:项目的访问路径-->虚拟目录
				* 简化部署:将项目打成war包,再将war包放置到webapps目录下。
					* war包会自动解压缩
			2. 配置conf/server.xml文件
				在<Host>标签体中配置
				<Context docBase="文件路径" path="虚拟目录"/>
			3. 在conf/Catalina/localhost创建任意名称的xml文件,在文件中编写
				<Context docBase="文件路径" /> 虚拟目录即文件名称
				
		* 静态项目和动态项目:
			* 目录结构
				* java动态项目的目录结构:
					-- 项目的根目录
						-- WEB-INF目录:
							-- web.xml:web项目的核心配置文件
							-- class目录:防止字节码文件的目录
							-- lib目录:放置依赖的jar包
							
		* 将Tomcat集成到IDEA中,并且创建JavaEE的项目,部署项目

Servlet: server applet

* 概念:运行在服务器端的小程序
	* Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则
	* 将来我们自定义一个类,实现Servlet接口,复写方法

* 快速入门:
	1. 创建JavaEE的项目
	2. 定义一个类,实现Servlet接口
	3. 实现接口中的抽象方法
	4. 配置Servlet
		在web.xml中配置
		<servlet>
        	<servlet-name>demo1</servlet-name>
        	<servlet-class>web.servlet.day11.ServletDemo1</servlet-class>
    	</servlet>

        <servlet-mapping>
        	<servlet-name>demo1</servlet-name>
        	<url-pattern>/demo1</url-pattern>
    	</servlet-mapping>
   
* 执行原理
	1. 当服务器接收到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
	2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容
	3. 如果有,则找到对应的<servlet-class>全类名
	4. tomcat会将字节码文件加载进内容,并且创建其对象
	5. 调用其方法
* Servlet的生命周期
	1. 被创建:执行init方法,只执行一次
		* Servlet什么时候被创建?
			* 默认情况下,第一次被访问时,Servlet被创建
			* 可以配置指定Servlet的创建时机
				* 在<servlet>标签下配置
                    1. 第一次被访问时创建
                        * <load-on-startup> 值为负数
                    2. 在服务器启动时创建
                        * <load-on-startup> 值为0或正整数
                        
        * Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
        	* 多个用户同时访问时,可能存在线程安全问题
        	* 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对其修改值
	2. 提供服务:执行service方法,执行多次
		* 每次访问Servlet时,Service方法都会被调用一次
	3. 被销毁:执行destroy方法,只执行一次
		* Servlet被销毁时执行。服务器关闭时,Servlet被销毁。
		* 只有服务器正常关闭时,才会执行destroy方法。
		* destroy方法在Servlet被销毁之前之前,一般用于释放资源。
		
* Servlet3.0:
	* 好处:
		* 支持注解配置。可以不需要web.xml了。
	
	* 步骤:
		1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
		2. 定义一个类,实现Servlet接口
		3. 复写方法
		4. 在类上使用@WebServlet注解,进行配置
			* @WebServlet("资源路径")
			
### IDEA与tomcat相关配置
	1. IDEA会为每一个tomcat部署的项目建立一份配置文件
		* 查看控制台的log:C:\Users\xxx\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\_idea_JavaWeb
	2. 工作空间项目    和     tomcat部署的web项目
		* tomcat真正访问的是"tomcat部署的web项目","tomcat部署的web项目"对应着"工作空间项目"中web目录的资源
		* WEB-INF目录下的资源无法被浏览器直接访问
	3. 断点调试:使用"小虫子"启动debug启动

Day 13 内容:

1. Servlet
2. HTTP协议
3. Request

Servlet:

1. 概念
2. 步骤
3. 执行原理
4. 生命周期
5. Servlet3.0注解配置
6. Servlet的体系结构
	Servlet -- 接口
		|
	GenericServlet -- 抽象类
		|
	HttpServlet -- 抽象类
	
	* GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象
		* 将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可
	* HttpServlet:对HTTP协议的一种封装,简化操作
		1. 定义类继承HttpServlet
		2. 复写doGet/doPost()方法

7. Servlet相关配置
	1. urlpartten:Servlet访问路径
		* 一个Servlet可以定义多个访问路径 @WebServlet({"/x","/xx"})
		* 路径定义规则
			1. /xxx
			2. /xxx/xxx 多层路径
			3. *.do 必须在后面加.do才能访问

HTTP:

* 概念:Hyper Text Transfer Protocol 超文本传输协议
	* 传输协议:定义了,客户端和服务器端通信时,发送数据的格式
	* 特点:
		1. 基于TCP/IP的高级协议
		2. 默认端口号:80
		3. 基于请求/响应模型的:一次请求对应一次响应
		4. 无状态的:每次请求之间相互独立,不能交互数据
	* 历史版本:
		* 1.0:每次请求响应都会建立新的连接
		* 1.1:复用连接
		
* 请求消息数据格式
	1. 请求行
		请求方式 请求url 请求协议/版本
		GET /login.html HTTP/1.1
		
		* 请求方式:
			* HTTP协议有7种请求方式,常用的有两种
				* GET
					1. 请求参数在请求行中,在url后。
					2. 请求的url长度有限制的
					3. 不太安全
				* POST
					1. 请求参数在请求体中
					2. 请求的url长度是没有限制的
					3. 相对安全
	2. 请求头:客户端浏览器告诉服务器一些信息
		请求头名称: 请求头值
		* 常见的请求头
			1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
				* 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
			2. Refer:
				* 告诉服务器,我(当前请求)从哪里来?
				* 作用:
					1. 防盗链
					2. 统计工作
	3. 请求空行
		空行,就是用于分割POST请求的请求头和请求体的
	4. 请求体(正文)
		* 封装POST请求消息的请求参数的
	* 字符串格式
		GET /login.html HTTP/1.1
		Host: localhost
		...: ...
		
		username=zhangsan

* 响应消息数据格式

Request:

1. request对象和response对象的原理
	1. request和response两个对象是由服务器创建的,我们来使用它们
	2. request对象是来获取请求消息,response对象是来设置响应消息
	
2. request对象继承体系结构
	ServletRequest	-- 接口
		| 继承
	HttpServletRequest	-- 接口
		| 实现
	org.apache.catalina.connector.RequestFacade 类(tomcat)
	
3. request功能:获取请求消息
	1. 获取请求消息数据
		1. 获取请求行数据
			* GET /day14/demo1?name=zhangsan HTTP/1.1
			* 方法:
				1. 获取请求方式:GET
					* String getMethod()
				2. (*)获取虚拟目录: /day14
					* String getContextPath()
				3. 获取Servlet路径:/demo1
					* String getServletPath()
				4. 获取get方式请求参数:name=zhangsan
					* String getQueryString()
				5. (*)获取请求URI:/day14/demo1
					* String getRequestURI() :/day14/demo1
					* StringBuffer getRequestURL() :http://localhost/day14/demo1
					* URL:统一资源定位符
					* URI:统一资源标识符
				6. 获取协议及版本:HTTP/1.1
					* String getProtocol()
				7. 获取客户机ip地址
					* String getRemoteAddr()
		2. 获取请求头数据
			* 方法:
				* (*)String getHeader(String name):通过请求头名称获取请求头的值
				* Enumeration<String> getHeaderName():获取所有的请求头名称
		3. 获取请求体数据
			* 请求体:只有POST请求方式,菜有请求体,在请求体中封装了POST请求的请求参数
			* 步骤:
				1. 获取流对象
					* BufferReader getReader() :获取字符输入流,只能操作字符数据
					* ServletInputStream getInputStream() :获取字节输入流,可以操作所有数据
						* 在文件上传知识点后讲解
				2. 再从流对象中拿数据
	2. 其他功能:
		1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法获取请求参数
			1. String getParameter(String name): 根据参数名称获取参数值
			2. String[] getParameterValues(String name): 根据参数名称获取参数值的数组
			3. Enumeration<String> getParameterValueNames(): 获取所有的参数名称
			4. Map<String, String[]> getParameterMap(): 获取所有参数的键值对集合
		
            * 中文乱码问题:
                * get方式:tomcat 8 已经将get方式乱码问题解决了
                * post方式:会乱码
                    * 解决:在设置参数前,设置request的编码request.setCharacterEncoding("utf-8");

        2. 请求转发:一种在服务器内部的资源跳转方式
            1. 步骤:
                1. 通过request对象来获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
                2. 使用RequestDispatcher对象进行转发:forward(ServletRequest request, ServletResponse response)
            2. 特点:
                1. 浏览器地址栏路径不发生变化
                2. 只能转发到当前的服务器内部资源中
                3. 转发是一次请求

        3. 共享数据:
            * 域对象:一个有作用范围的对象,可以在范围内共享数据
            * request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
            * 方法:
                1. void setAttribute(String name, Object obj): 存储数据
                2. Object getAttribute(String name): 通过键获取值
                3. void removeAttribute(): 通过键移除键值对

        4. 获取ServletContext:
            * ServletContext getServletContext()

案例:用户登录

* 用户登录案例需求
	1. 编写login.html登录界面
		username & password 两个输入框
	2. 使用Druid数据库连接池技术,操作mysql,day14数据库中user表
	3. 使用JdbcTemplate技术封装JDBC
	4. 登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您
	5. 登录失败跳转到FailServlet展示:登录失败!用户名或密码错误

* 分析

* 开发
    1. 创建项目,导入jar包,配置文件,创建html页面
    2. 创建数据库环境
    3. 创建包domain,创建类User
    4. 创建包dao,创建类UserDao,提供login方法
    5. 创建包util,创建类JDBCUtils,使用Druid连接池
    6. 创建包web.servlet,创建类LoginServlet,完成登录具体逻辑
    7. login.html中form表单的action路径写法
    	* 虚拟目录+Servlet的路径
    8. BeanUtils工具类,简化数据封装
    	* 用于封装JavaBean
    	1. JavaBean:标准的Java类
    		1. 要求:
                1. 类必须被public修饰
                2. 必须提供空参的构造器
                3. 成员变量必须使用private修饰
                4. 提供公共的getter/setter方法
            2. 功能:封装数据
            
    	2. 概念:
    		成员变量:
    		属性:setter/getter方法截取后的产物
    			例如:getUsername() --> Username --> username
    			
    	3. 方法:
    		1. setProperty()
    		2. getProperty()
    		3. populate(Object obj, Map map):将map集合的键值对信息,封装到对应的JavaBean对象中

Day 14 内容:

1. HTTP协议:响应消息
2. Response对象
3. ServletContext对象

HTTP协议:

1. 请求消息:客户端发送给服务器端的数据
	* 数据格式:
		1. 请求行
		2. 请求头
		3. 请求空行
		4. 请求体
2. 响应消息:服务器端发送给客户端的数据
	* 数据格式
		1. 响应行
			1. 组成:协议/版本 响应状态码 状态码描述
			2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
				1. 状态码都是3位数字
				2. 分类:
					1. 1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx状态码
					2. 2xx:成功。代表:200
					3. 3xx:重定向。代表:302(重定向),304(访问缓存)
					4. 4xx:客户端错误。
						* 代表:
							* 404(路径没有对应的资源),
							* 405(请求方式没有对应的doXxx方法)
					5. 5xx:服务器端错误。代表:500(服务器内部出现异常)
		2. 响应头
			1. 格式:头名称: 值
			2. 常见的响应头:
				1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
				2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据
					* 值:
						* in-line:默认值在当前页面内打开
						* attachment;filename=xxx:以附件形式打开响应体。文件下载
		3. 响应空行
		4. 响应体:传输的数据

	* 响应字符串格式
		xxx

Response对象

* 功能:设置响应消息
    1. 设置响应行
        1. 格式:HTTP/1.1 200 ok
        2. 设置状态码:setStatus(int sc)
    2. 设置响应头:setHeader(String name, String value)
    3. 设置响应体:
        * 使用步骤:
            1. 获取输出流
                * 字符输出流:PrintWriter getWriter()
                * 字节输出流:ServletOutputStream getOutputStream()
            2. 使用输出流,将数据输出到客户端浏览器中

* 案例
    1. 完成重定向
        * 重定向:资源跳转的方式
        * 代码实现:
            response.sendRedirect("重定向的地址");
        * 重定向的特点
            1. 地址栏发生变化
            2. 重定向可以访问其他站点(服务器)的资源
            3. 重定向是两次请求,不能使用request对象来共享数据
        * 转发的特点:
            1. 转发地址栏路径不变
            2. 转发只能访问当前服务器下的资源
            3. 转发是一次请求,可以使用requset对象来共享数据
        * forward 和 redirect 区别
        * 路径写法
            1. 路径分类
                1. 相对路径:通过相对路径不能确定唯一资源
                	* 如 ./index.html
                    * 不以/开头,以.开头

                    * 规则:找到当前资源和目标资源之间的相对位置关系
                        * ./:当前目录
                        * ../:后退一级目录
                2. 绝对路径:通过绝对路径可以确定唯一资源
                    * 如 http://localhost/...
                    * 以/开头的路径

                    * 规则:判断定义的路径是给谁用的?判断请求将来从哪发出
                        * 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
                            * 建议虚拟目录动态获取:request.getContextPath()
                            * <a>,重定向
                        * 给服务器使用:不需要加虚拟目录
                            * 转发路径

    2. 服务器输出字符数据到浏览器
        * 步骤:
            1. 获取字符输出流
            2. 输出数据

        * 注意
            * 乱码问题
                1. 获取的流的默认编码为ISO-8859-1
                2. 设置该流的默认编码
                3. 告诉浏览器响应体使用的编码
                // 在获取流之前设置
                response.setContentType("text/html;charset=utf-8");
    3. 服务器输出字节数据到浏览器
        * 步骤:
            1. 获取字节输出流
            2. 输出数据
    4. 验证码
    	1. 本质:图片
    	2. 目的:防止恶意表单注册

ServletContext对象

1. 概念:代表整个web应用,可以和程序的容器(服务器)通信
2. 获取:
	1. 通过request的对象获取
		request.getServletContext();
	2. 通过HttpServlet获取
		this.getServletContext();
3. 功能:
	1. 获取MIME类型:
		* MINE类型:在互联网通信过程中定义的一种文件数据类型
			* 格式:大类型/小类型	image/jpeg

		* 获取:String 
		* getMimeType(String file)
	2. 域对象:共享数据
		1. setAttribute()
		2. getAttribute()
		3. removeAttribute()
		
		* ServletContext对象范围:所有用户所有请求的数据
	3. 获取文件的真实(服务器)路径 
		1. 方法:String getRealPath(String path)
			* web目录 -- /xxx.xxx
			* WEB-INF目录 -- /WEB-INF/xxx.xxx
			* src目录 -- /WEB-INF/classes/xxx.xxx

案例

* 文件下载雪球
	1. 页面显示超链接
	2. 点击超链接弹出下载提示框
	3. 完成图片文件下载

* 分析:
	1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载
	2. 任何资源都必须弹出下载提示框
	3. 使用响应头设置资源的打开方式:
		* content-disposition:attachment;filename=xxx

* 步骤
	1. 定义页面,编写href属性,指向Servlet,传递资源名称filename
	2. 定义Servlet
		1. 获取文件名称
		2. 使用字节输入流加载文件进内存
		3. 指定response的响应头 content-disposition:attachment;filename=xxx
		4. 将数据写出到response输出流

* 问题:
	* 中文文件名
		* 解决思路:
			1. 获取客户端使用的浏览器版本信息
			2. 根据不同的版本信息,设置filename编码方式不同

Day 15 内容:

1. 会话技术
	1. Cookie
	2. Session
2. JSP:入门学习

会话技术

1. 会话:一次会话中包含多次请求和响应。
    * 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
2. 功能:在一次会话的范围内的多次请求间,共享数据
3. 方式:
    1. 客户端会话技术:Cookie
    2. 服务器端会话技术:Session

Cookie

1. 概念:客户端会话技术,将数据保存在客户端
2. 快速入门:
    * 使用步骤
        1. 创建Cookie对象,绑定数据
            * new Cookie(String name, String name)
        2. 发送Cookie对象
            * response.addCookie(Cookie cookie)
        3. 获取Cookie,拿到数据
            * Cookie[] request.getCookies()

3. 实现原理
    * 基于响应头set-cookie和请求头cookie实现
4. cookie的细节
    1. 一次可不可以发送多个cookie
        * 可以
        * 可以创建多个cookie对象,使用response调用多次addCookie方法发送cookie即可
    2. cookie在浏览器中保存多长时间
        1. 默认情况,当浏览器关闭后,Cookie数据被销毁
        2. 持久化存储:
            * setMaxAge(int second)
                1. 正数:将Cookie数据写到硬盘的文件中。持久化存储。cookie存活时间
                2. 负数:默认值
                3. 零:删除cookie信息
    3. cookie能不能存中文
        * 在tomcat8之前,cookie中不能直接存储中文数据。
            * 需要将中文数据转码 -- 一般采用url编码
        * 在tomcat8之后,cookie中支持存储中文数据。但还是不支持特殊字符,建议使用url编码。
    4. cookie共享问题
        1. 假设在一个tomcat服务器中部署了多个web项目,那么在这些项目中,cookie能不能共享
            * 默认情况cookie不能共享

            * setPath(String path) : 设置cookie的共享范围,默认情况下设置当前的虚拟目录
                * 如果要共享,则可以将path设置为"/"

        2. 不同的tomcat服务器cookie共享问题
            * setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
                * setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享

5. cookie的特点和作用
    1. cookie存储数据在客户端浏览器
    2. 浏览器对于单个cookie的大小有限制(4kb),以及对同一个域名下的总cookie的数量也有限制(20)

    * 作用:
        1. cookie一般用于存储少量的不太敏感的数据
        2. 在不登录的情况下,完成服务器对客户端的身份识别

6. 案例:记住上一次访问时间
    1. 需求:
        1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎你首次访问。
        2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串。
    2. 分析:
        1. 可以采用cookie来完成
        2. 在服务器中的Servlet判断是否有一个名为lastTime的cookie
            1. 有,不是第一次访问
                1. 响应数据:欢迎回来,您上次访问时间为...
                2. 写回cookie:lastTime=...
            2. 没有,是第一次访问
                1. 响应数据:您好,欢迎您首次访问
                2. 写回cookie:lastTime=...
	3. 代码
		/**
         * cookie实现访问时间显示
         */
        @WebServlet("/CookieServlet")
        public class CookieServlet extends HttpServlet {
            protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                response.setContentType("text/html;charset=utf-8");
                Cookie[] cookies = request.getCookies();
                boolean flag = false;
                for (Cookie cookie : cookies) {
                    if("lastTime".equals(cookie.getName())){
                        flag = true;
                        String decode = cookie.getValue();
                        String time = URLDecoder.decode(decode, "utf-8");
                        response.getWriter().write("您好,您上次访问时间为" + time);

                        Date date = new Date();
                        SimpleDateFormat s = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
                        time = s.format(date);
                        String encode = URLEncoder.encode(time, "utf-8");
                        System.out.println(time);
                        System.out.println(encode);
                        cookie.setValue(encode);
                        response.addCookie(cookie);
                        break;
                    }
                }
                if(cookies.length == 0 || cookies == null || !flag){
                    Date date = new Date();
                    SimpleDateFormat s = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
                    String time = s.format(date);
                    String encode = URLEncoder.encode(time, "utf-8");
                    System.out.println(time);
                    Cookie c = new Cookie("lastTime", encode);
                    response.addCookie(c);
                    response.getWriter().write("您好,欢迎您首次访问!");
                }
            }

            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                doPost(request, response);
            }
        }

JSP:入门学习

1. 概念:
	* Java Server Pages:java服务器端页面
		* 可以理解为:一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码
		* 用于简化书写!!!

2. 原理:
	* JSP本质上就是一个Servlet

3. JSP的脚本:JSP定义Java代码的方式
	1. <% 代码 %>:定义的Java代码,在service方法中。service可以定义什么,该脚本中就可以定义什么。
	2. <%! 代码 %>:定义的Java代码,在jsp转换后的java类的成员位置。
	3. <%= 代码 %>:定义的Java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
4. JSP的内置对象
	* 在jsp页面中不需要获取和创建就可以使用的对象
	* jsp一共有9个内置对象
	* 今天学习3个:
		* request
		* response
		* out:字符输出流对象。可以将数据输出到页面上。和response.getWriter().write()类似
			* response.getWriter().write()和out.write()的区别:
				* 在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。
				* response.getWriter().write()数据输出永远在out.write()之前

Session

1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession
2. 快速入门:
	1. 获取HttpSession对象
		* request.getSession()
	2. 使用HttpSession对象
		getAttribute()
		setAttribute()
		removeAttribute()
3. 原理
    * Session的实现是依赖于Cookie的。JSESSIONID
4. 细节
    1. 当客户端关闭后,服务器不关闭,两次获取的session是否是同一个
        * 默认情况下不是。
        * 如果需要相同,则可以创建cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。
    2. 客户端不关闭,服务器关闭后,两次获取的session是同一个吗
        * 不是同一个,但是要确保数据不丢失
            * session的钝化:
                * 服务器正常关闭之前,将session对象序列化到硬盘上
            * session的活化:
                * 在服务器正常启动后,将session文件转化为内存中的session对象即可。
    3. session什么时候被销毁
        1. 服务器关闭
        2. session对象调用invalidate()
        3. session默认失效时间 30分钟
            选择性配置修改
            web.xml -- <session-config>

5. session的特点
    1. session用于存储一次会话的多次请求的数据,存在服务器端
    2. session可以存储任意类型,任意大小的数据
        * session和cookie的区别
            1. session存储数据在服务器端,而cookie在客户端
            2. session没有数据大小限制,cookie有
            3. session数据安全,cookie相对于不安全

案例:验证码

1. 案例需求
	1. 访问带有验证码的登陆页面index.jsp
	2. 用户输入用户名,密码以及验证码。
		* 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
		* 如果验证码输入有误,则跳转登录页面,提示:验证码错误
		* 如果全部输入正确,则跳转到success.jsp,显示:用户名,欢迎您

2. 分析

Day 16 内容:

1. JSP:
	1. 指令
	2. 注释
	3. 内置对象

2. MVC开发模式
3. EL表达式
4. JSTL标签
5. 三层架构

JSP:

1. 指令
	* 作用:用于配置JSP页面,导入资源文件
	* 格式:
		<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
	* 分类
		1. page		:配置JSP页面的
			* contentType:等同于response.setContentType()
				1. 设置响应体的mime类型以及字符集
				2. 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要配置pageEncoding设置当前页面的字符集)
			* import:导包
			* erroePage:当前页面发生异常后,会自动跳转到指定的错误页面
			* isErrorPage:标识当前页面是否是错误页面。
				* true:是,可以使用内置对象exception。
				* false:否。默认值,不能使用exception对象。
		2. include  :页面包含的。导入页面的资源文件
			* <%@inlcude file="top.jsp" %>
		3. taglib	:导入资源
			* <%@ tablib prefix="c" uri="..." %>
				* prefix:前缀
2. 注释
	1. html注释:
		<!-- -->:只能注释html代码片段
	2. jsp注释:推荐使用
		<%-- --%>:可以注释所有
3. 内置对象
	* 在jsp页面中不需要创建,直接使用的对象
	* 一共有9个:
			变量名					真实类型					作用
		* pageContext			PageContext					当前页面共享数据,可以获取其他8个对象
		* request				HttpRequest					一次请求访问的多个资源(转发)
		* session				HttpSession					一次会话的多个请求间
		* application			ServletContext				所有用户间共享数据
		* response				HttpResponse				响应对象
		* page					Object						当前页面(Servlet)的对象
		* out					JspWriter					输出对象,数据输出到页面上
		* config				ServletConfig				异常对象	Servlet的配置对象
		* exception				Throwable

MVC:开发模式

1. jsp演变历史
	1. 早期只有Servlet,只能使用response输出标签数据,非常麻烦
	2. 后来有了jsp,简化了Servlet的开发,如果过度使用jsp,在jsp中既写大量java代码,又写html,造成难以维护,难以分工协作。
	3. 再后来,java的web开发借鉴mvc开发模式,使得程序的设计更加合理

2. MVC:
	1. M:model,模型。JavaBean
		* 完成具体的业务操作,如:查询数据库,封装对象
	2. V:view,视图。JSP
		* 展示数据
	3. C:Controller,控制器。Servlet
		* 获取用户的输入
		* 调用模型
		* 将数据交给视图进行展示
	* 优缺点
    1. 优点:
        1. 耦合性低,方便维护,可以利于分工协作
        2. 重用性高
    2. 缺点:
        1. 使得项目架构变得复杂,对开发人员要求高

EL表达式

1. 概念:Expression Language 表达式语言
2. 作用:替换和简化jsp页面中java代码的编写
3. 语法:${表达式}
4. 注意:
    * jsp默认是支持EL表达式的。如果要忽略EL表达式
        1. 设置jsp中page指令中:isELIgnored=“true” 忽略所有的el表达式
        2. \${表达式}:忽略当前这个el表达式
5. 使用
	1. 运算
		* 运算符:
			1. 算数运算符: + - * /(div) %(mod)
			2. 比较运算符: > < >= <= == !=
			3. 逻辑运算符:&&(and) ||(or) !(not)
			4. 空运算符:empty
				* 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0
				* ${empty list}:判断字符串、集合、数组对象是否为null或者长度是否为0
				* ${not empty list}:判断字符串、集合、数组对象是否不为null,且长度大于0
	2. 获取值
		1. el表达式只能从域对象中获取值
		2. 语法:
			1. ${域名称.键名}:从指定域中获取指定键的值
				* 域名称:
					1. pageScope		-->	pageContext
					2. requestScope		-->	request
					3. sessionScope		-->	session
					4. applicationScope	-->	application (ServletContext)
				* 举例:在requset域中存储了name=张三
				* 获取:${requestScope.name}
			2. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
			
			3. 获取对象、list集合、Map集合的值
				1. 对象:${域名称.键名.属性名}
					* 本质上会去调用对象的getter方法
				2. List集合:${域名称.键名[索引]}
				3. Map集合:
					* ${域名称.键名.key名称}
					* ${域名称.键名["key名称"]}
		3. 隐式对象:
			* el表达式中有11个隐式对象
			* pageContext:
				* 获取jsp其他8个内置对象
					* ${pageContext.request.contextPath}:动态获取虚拟目录

JSTL

1. 概念:JavaServer Pages Tag Library JSP标准标签库
	* 是由Apache组织提供的开源的免费的jsp标签

2. 作用:用于简化和替换jsp页面上的java代码

3. 使用步骤:
	1. 导入JSTL相关jar包
	2. 引入标签库:taglib指令	<%@ taglib %>
	3. 使用标签

4. 常用的JSTL标签
	1. if			相当于Java代码的if语句
		1. 属性:
			* test 必须属性,接收boolean表达式
				* 如果表达式为true,则显示if标签体内内容
				* 如果为false则不展示
				* 一般情况下,test属性会结合el表达式一起使用
		2. 注意:c:if标签没有else情况,若需要,可以再定义一个c:if标签
	2. choose		相当于Java代码的switch语句
		1. 使用choose标签声明						相当于switch声明
		2. 使用when标签做判断						相当于case
		3. 使用otherwise标签做其他情况的声明		相当于default
	3. foreach		相当于Java代码的for语句
		1. for(int i=0; i<5; i++)
			* 属性:
				* begin、end、step、var
				* varStatus
					* index:索引
					* count:循环次数
		2. for(User user : list)
			* 属性:
				* items --> list
				* var --> user
				* varStatus
					* 同上

5. 练习:
	* 需求:再request域中有一个存User对象的List集合。需要使用jstl和el将list集合数据展示到jsp页面的表格table中。

三层架构:软件设计架构

1. 界面层(表示层):用户看到的界面。用户可以通过界面上的组件和服务器进行交互
2. 业务逻辑层:处理业务逻辑的。
3. 数据访问层:操作数据存储文件的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ToA7r8pu-1601224866545)(https://i.loli.net/2020/07/26/OnQ9LogXNdtaIjB.png)]

案例:用户信息列表展示

1. 需求:用户信息的增删改查操作
2. 设计:
	1. 技术选型:Servlet + JSP + Mysql + JDBCTemplate + Druid + BeanUtils + Tomcat
	2. 数据库设计:
		create database day17;	-- 创建数据库
		use day17;	-- 使用数据库
		create table user(	-- 创建表
			id int primary key auto_increment,
			name varchar(32) not null,
			gender varchar(5),
			age int,
			address varchar(32),
			qq varchar(20),
			email varchar(50),
		);
		
3. 开发:
	1. 环境搭建
		1. 创建数据库环境
		2. 创建项目,导入需要的jar包
		
	2. 编码

4. 测试
5. 部署运维

Day 17 内容:

1. 综合练习
	1. 简单功能
		1. 列表查询
		2. 登录
		3. 添加
		4. 删除
		5. 修改
	2. 复杂功能
		1. 删除选中
		2. 分页查询
			* 好处:
				1. 减轻服务器内存的开销
				2. 提升用户体验
		3. 复杂条件查询

2. 登录

1. 调整页面,加入验证码功能
2. 代码实现

Day 18 内容:

1. Filter:过滤器
2. Listener:监听器

Filter:过滤器

1. 概念:
    * 生活中的过滤器:净水器、空气净化器、土匪
    * web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊功能。
    * 过滤器的作用:
        * 一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤...
2. 快速入门:
	1. 步骤:
		1. 定义一个类,实现接口Filter
		2. 复写方法
		3. 配置拦截路径
			1. web.xml
			2. 注解
3. 过滤器细节:
	1. web.xml配置
		* 和Servlet配置相似
	2. 过滤器执行流程
		1. 执行过滤器
		2. 执行放行后的资源
		3. 执行过滤器放行代码下方的代码
	3. 过滤器生命周期方法
		1. init:在服务器启动后,创建filter对象,调用该方法,只调用一次
		2. doFilter:每一次请求被拦截都会执行,执行很多次
		3. 在服务器关闭后,Filter对象被销毁,正常关闭的前提下,会执行一次
	4. 过滤器配置详解
		* 拦截路径配置:
			1. 具体资源路径:/index.jsp
			2. 目录拦截:/user/*	访问/user下的所有资源时,过滤器都会被执行
			3. 后缀名拦截:*.jsp	访问所有后缀名为jsp资源时,过滤器都会被执行
			4. 拦截所有资源:/*
		* 拦截方式配置:资源被访问的方式
			* 注解配置:
				* 设置dispatcherTypes属性
					1. REQUEST:默认值。浏览器直接请求资源
					2. FORWARD:转发访问资源
					3. INCLUDE:包含访问资源
					4. ERROR:错误跳转资源
					5. ASYNC:异步访问资源
			* web.xml配置
				* 设置dispatcher标签即可
	5. 过滤器链(配置多个过滤器)
		* 执行顺序:如果有两个过滤器——过滤器1和过滤器2
			1. 过滤器1
			2. 过滤器2
			3. 资源
			4. 过滤器2
			5. 过滤器1
		* 过滤器先后顺序:
			1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
				如:AFilter 和 BFilter,AFilter先执行
			2. web.xml配置:谁定义在上谁先执行

4. 案例
	1. 案例1_登录验证
		* 需求
			1. 访问day17_case案例的资源,验证其是否登录
			2. 如果登录,则放行
			3. 否则,跳转到登录界面,提示“您尚未登录,请先登录”

	2. 案例2_过滤敏感词汇
		* 需求:
			1. 对day17_case案例录入的数据进行敏感词汇过滤
			2. 敏感词汇参考《敏感词汇.txt》
			3. 如果时敏感词汇,替换为 ***

		* 分析:
			1. 对request对象进行增强。增强获取参数相关方法即可
			2. 放行。传递代理对象
			
		* 增强对象的功能:
			* 设计模式:一些通用的解决固定问题的方式
			1. 装饰模式
			2. 代理模式
				* 概念:
					1. 真实对象:被代理的对象
					2. 代理对象
					3. 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
				* 实现方式:
					1. 静态代理:有一个类文件描述代理模式
					2. 动态代理:在内存中形成代理类
						* 实现步骤:
							1. 代理对象和真实对象实现相同的接口
							2. 代理对象 = Proxy.newProxyInstance();
							3. 使用代理对象调用方法
							4. 增强方法
						* 增强方式:
							1. 增强参数列表
							2. 增强返回值类型
							3. 增强方法体执行逻辑

Listener:监听器:

* 概念:web的三大组件之一。
	* 事件监听机制
		* 事件:一件事
		* 事件源:事件发生的地方
		* 监听器:一个对象
		* 注册监听:将事件、事件源、监听器绑定在一起。当事件源上发生一个事件后,执行监听器代码

* ServletContextListener:监听ServletContext对象的创建和销毁
	* 方法
        * void contextDestroyed(ServletContextEvent sce) :对象被销毁前调用
        * void contextInitialized(ServletContextEvent sce) :对象被创建后调用
	* 步骤:
		1. 定义一个类,实现ServletContextListener接口
		2. 复写方法
		3. 配置
			1. web.xml:<listener>标签
				* 指定初始化参数	<context-param>标签
			2. 注解:@WebListener

Day 19 内容:

1. JQuery 基础:
	1. 基本概念:一个JavaScript框架。简化JS开发
		* jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
		* JavaScript框架:本质上就是一些js文件,封装了js的原生代码而已。
		
	2. 快速入门
		1. 步骤:
			1. 下载JQuery
				* 目前三大版本:
					* 1.xx——使用广泛,功能不再新增
					* 2.xx——很少人使用
					* 3.xx——支持最新浏览器
				* jquery-xxx.js 和 jquery-xxx.min.js区别:
					1. jquery-xxx.js:开发版本。有良好的缩进和注释
					2. jquery-xxx.min.js:生产版本。没有缩进,体积小。
			2. 导入JQuery的js文件:导入min.js文件
			3. 使用
				var div1 = $("#div1")
				
	3. JQuery对象和JS对象的区别和转换
		1. JQuery对象在操作时更加方便
		2. JQuery对象和js对象方法不通用
		3. 两者相互转换
			* js --> jq : jq对象[索引] 或者 jq对象.get(索引)
			* jq --> js : $(js对象)
			
	4. 选择器:筛选具有相似特征的元素(标签)
		1. 基本语法学习:
			1. 事件绑定
			2. 入口函数
				* window.onload() = func 和 $(func) 的区别
					* 前者只能定义一次,如果定义多次,后边的会将前边定义的覆盖
					* 后者则可以定义多次
			3. 样式控制
		2. 分类
			1. 基本选择器
				1. 标签选择器(元素选择器)
					* $("html便签名")
				2. id选择器
					* $("#id值")
				3. 类选择器
					* $(".class值")
				4. 并集选择器
					* $("选择器1,选择器2...")
			2. 层级选择器
				1. 后代选择器
					* $("A B") 选择A元素内部的所有B元素
				2. 子选择器
					* $("A > B") 选择A元素下内部的所有B子元素
			3. 属性选择器
				1. 属性名称选择器
					* $("A[属性名]") 包含指定属性的选择器
				2. 属性选择器
					* $("A[属性名='值']") 包含指定属性等于指定值的选择器
					* $("A[属性名^='值']") 属性值为指定值开头的选择器
					* $("A[属性名$='值']") 属性值为指定值结尾的选择器
					* $("A[属性名!='值']") 属性值不为指定值或者不存在该属性的选择器
					* $("A[属性名*='值']") 属性值包含指定值选择器
				3. 复合属性选择器
					* $("A[属性名='值'][]...")
			4. 过滤选择器
				1. 首元素选择器
					* :first
				2. 尾元素选择器
					* :last
				3. 非元素选择器
					* :not(selector)
				4. 偶数选择器
					* :even
				5. 奇数选择器
					* :odd
				6. 等于索引选择器
					* :eq(index)
				7. 大于索引选择器
					* :gt(index)
				8. 小于索引选择器
					* :lt(index)
				9. 标题选择器
					* :header 获取标题元素(h1~h6)
			5. 表单过滤选择器
             	1. 可用元素选择器
             		* :enabled
             	2. 不可用元素选择器
             		* :disabled
             	3. 选中选择器
             		* :checked	单选/多选框
             	4. 选中选择器
             		* :selected 下拉列表
            	
	5. DOM操作
		1. 内容操作
			1. html():获取/设置元素的标签体内容	<a><font>xxx</font></a>	-->	<font>xxx</font>
			2. text():获取/设置元素的标签体纯文本内容	<a><font>xxx</font></a>	-->	xxx
			3. val():获取/设置元素的value属性值
		2. 属性操作
			1. 通用属性操作
				1. attr():获取/设置元素的属性
				2. removeAttr():删除属性
				3. prop():获取/设置元素的属性
				4. removeProp():删除属性
				
				* attr和prop区别:
					1. 如果操作的是元素的固有属性,则建议使用prop
					2. 如果操作的是元素自定义的属性,则建议使用attr
			2. 对class属性的操作
				1. addClass():添加class属性值
				2. removeClass():删除class属性值
				3. toggleClass():切换class属性值
					* toggleClass("one"): 如果存在class="one"则将属性值one删除,如果不存在,则添加。
				4. css()
		3. CRUD操作:
			1. append():父元素将子元素追加到末尾
				* 对象1.append(对象2):将对象2添加到对象1元素内部,并且在末尾
			2. prepend():父元素将子元素追加到开头
				* 对象1.prepend(对象2):将对象2添加到对象1元素内部,并且在开头
			3. appendTo():
				* 对象1.append(对象2):将对象1添加到对象2元素内部,并且在末尾
			4. prependTo():
				* 对象1.prepend(对象2):将对象1添加到对象2元素内部,并且在开头
				
			5. after():添加元素到对应元素后边
				* 对象1.after(对象2):将对象2添加到对象1后边。对象1和对象2是兄弟关系
			6. before():添加元素到对应元素前边
				* 对象1.after(对象2):将对象2添加到对象1前边。对象1和对象2是兄弟关系
			7. insertAfter():
				* 对象1.after(对象2):将对象1添加到对象2后边。对象1和对象2是兄弟关系
			8. insertBefore():
				* 对象1.after(对象2):将对象1添加到对象2前边。对象1和对象2是兄弟关系
			9. remove():移除元素
				* 对象.remove():将对象删除掉
			10. empty():清空元素的所有后代元素
				* 对象.empty():将对象的后代元素全部清空,但是保留当前对象以及其属性节点
	6. 案例
		重要案例 需要时进行查看p383-386

Day 20 内容

1. Jquery 高级
	1. 动画
		1. 默认显示和隐藏方式
			1. show([speed, [easing], [fn]])
				1. 参数
					1. speed:动画速度。三个预定义的值("slow","normal","fast")或表示动画时长的毫秒值
					2. easing:用来指定切换效果,默认是"swing",可用参数"linear"
						* swing:动画执行时效果是先慢,中间快,最后又慢
						* linear:动画执行时速度匀速
					3. fn:在动画完成时执行的函数,每个元素执行一次
			2. hide([speed, [easing], [fn]])
			3. toggle([speed, [easing], [fn]])
		
		2. 滑动显示和隐藏方式
			1. slidDown([speed, [easing], [fn]])
			2. slideUp([speed, [easing], [fn]])
			3. slideToggle([speed, [easing], [fn]])
			
		3. 淡入淡出显示和隐藏方式
			1. fadeIn([speed, [easing], [fn]])
			2. fadeOut([speed, [easing], [fn]])
			3. fadeToggle([speed, [easing], [fn]])
	2. 遍历
		1. js的遍历方式
			* for(初始化值;循环结束条件;步长)
		2. jq的遍历方式
			1. jq对象.each(callback)
				1. 语法:
					jquery对象.each(function(index, element){});
						* index:索引
						* element:元素对象
						* this:每一个元素对象
				2. 回调函数返回值:
					* true:结束循环-break
					* false:结束本次循环,继续下次循环-continue
			2. $.each(object, [callback])
				* object可以为jq对象也可为js对象
			3. for..of
	3. 事件绑定
		1. jquery标准的绑定方式
			jq对象.事件方法(回调函数);
			* 注:如果调用事件方法,不传递回调函数,则会触发浏览器默认行为
				* 表单对象.submit();//表单提交
		2. on绑定事件/off解除绑定
			jq对象.on("事件名称", 回调函数);
			jq对象.off("事件名称");
				* 如果off方法不传递任何参数,则将组件上所有事件解绑
		3. 事件切换:toggle
			* jq对象.toggle(fn1, fn2, ...)
				* 当单击jq对象对应的组件后,会执行fn1,第二次点击执行fn2....
			* 注意该方法在1.9及以上的高版本被移除,需要使用jquery-migrate插件才能生效
	4. 案例
		抽奖小案例
	5. 插件:增强jquery的功能
		1. 实现方式:
			1. $.fn.extend(object)
				* 增强通过JQuery获取的对象的功能	$("#id")
			2. $.extend(object)
				* 增强JQuery对象自身的功能 $/JQuery

Day 21 内容:

1. AJAX
2. JSON

AJAX:

1. 概念:Asynchronous JavaScript And XML	异步的JavaScript和XML
	1. 异步和同步:客户端和服务器端相互通信的基础上
		* 同步:客户端必须等待服务器端的响应,不能进行其他操作
		* 异步:客户端不必须等待服务器端的响应,可以进行其他操作
		
		提升用户的体验,不需要重新加载整个页面实现部分页面的更新
2. 实现方式:
	1. 原生的JS实现方式(了解)
		* 参考w3school手册
	2. JQuery实现方式
		1. $.ajax()
			* 语法:$.ajax({键值对});
				$.ajax({
					url: "",
					data: {
						xx: "",
						yy: ""
					},
					success: function(){},
					error: function(){},
					dataType: ""
				});
		2. $.get():发送GET请求
			* 语法:$.get(url, [data], [callback], [type])
		3. $.post():发送POST请求
			* 同上

JSON:

1. 概念:JavaScript Object Notation	JavaScript对象表示法
	* json现在多用于存储和交换文本信息的语法
	* 进行数据的传输
	* 比XML更小更快更方便
2. 语法:
	1. 基本规则
		* 数据在名称/值对中:json由键值对构成
			* 键用引号引起来,也可以不使用引号
			* 键的取值类型:
				1. 数字(整数或浮点数)
				2. 字符串(双引号)
				3. 布尔值
				4. 数组(方括号)
				5. null
				6. 对象(花括号)
		* 数据由逗号分隔:多个键值对由逗号分隔
		* 花括号保存对象:使用{}定义json格式
		* 方括号保存数组:[]
	2. 获取数据:
		1. json对象.键名
		2. json对象["键名"]
		3. 数组对象[索引]
	3. JSON数据和Java对象的相互转换
		* JSON解析器:
			* 常见的解析器:Jsonlib、Gson、fastjson、jackson
		1. JSON转为Java对象
			1. 导入jackson相关jar包
			2. 创建Jackson核心对象 ObjectMapper
			3. 调用ObjectMapper的相关方法进行转换
				1. readValue(json数据, Class)
		2. Java对象转为JSON
			1. 使用步骤:
				1. 导入jackson相关jar包
				2. 创建Jackson核心对象 ObjectMapper
				3. 调用ObjectMapper的相关方法进行转换
					1. 转换方法:
                        * writeValue(参数1, obj)
                            参数1:
                                File:将obj对象转为json字符串,并保存到对应的文件中
                                Writer:将obj对象转为json字符串,并将json数据填充到字符输出流中
                                OutputStream:将obj对象转为json字符串,并将json数据填充到字节输出流中
                        * writeValueAsString(obj): 将对象转为json字符串
                    2. 注解
                    	1. @JsonIgnore:排除属性
                    	2. @JsonFormat:属性值的格式化
                    		* @JsonFormat(pattern = "yyyy-MM-dd")
                    	3. 复杂Java对象
                    		1. List:数组
                    		2. Map:和对象格式一致

案例

* 校验用户名是否存在
	1. 服务器响应的数据,在客户端使用时,需要转为json的格式来使用
		1. $get(type):将最后一个参数指定为json
		2. 在服务器端设置MIME类型,response.setContentType("application/json;charset=utf-8")

Day 22 内容:

1. redis
	1. 概念
	2. 下载安装
	3. 命令操作
		1. 数据结构
	4. 持久化操作
	5. 使用Java客户端操作redis

Redis

  • 45
    点赞
  • 301
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值