java web
junit单元测试
测试分类:
- 黑盒测试
- 白盒测试:关注程序代码,需要自己写一些代码进行测试
junit使用步骤:白盒测试
-
定义一个测试类
测试类型:被测试的类名Test
包名:xxx.xxx.xx.test
-
定义测试方法:可以去独立运行
方法名:test测试的方法名
返回值:void
参数列表:空参
-
给方法加@Test,便可以独立运行
-
导入junit的依赖
判定结果:看最后结果的颜色,绿色代表成功
一般使用断言来处理结果
1
Assert.assertEquals(3,result);
也可以用@Before用于修饰初始化方法,@After用于修饰结束方法
反射
框架:半成品软件,在框架的基础上进行软件开发,简化编码
概念:将类的各个组成部分封装为其他对象,这是反射机制
- 在程序的运行过程中,操作这些对象
- 可以解耦,提高程序可扩展性
获取class对象的方法:(对应代码的三个阶段)
-
Class.forName(“全类名”):将字节码文件加载进内存,返回class对象
多用于配置文件,奖类名定义在配置文件,读取文件,加载类
-
类名.class:通过类名的属性class来获取
多用于参数传递
-
对象.getclass():getclass()在object中定义的
多用于对象的获取字节码方式
同一字节码文件在一次程序运行过程中,只会被加载一次,不论通过哪种方法获取class对象都同一个地址
Class对象功能:(参照代码reflect部分,见cn.itcast.reflect)
-
获取成员变量
getFields()//获取所有public类型的成员变量
getField(String name)
getDeclaredFields()
getDeclaredField(String name)
-
获取构造方法
用于创建对象
-
获取成员方法
-
获取类名
注解
概念:用于说明程序
使用注解:@注解名称
作用分类:
-
编写文档:通过代码里标识的注解生成文档【doc文档】
然后复制该文件到一个文件夹中,然后打开命令行窗口
输入 javadoc 文件名,便可生成doc文档
-
代码分析:通过代码里标识的注解对代码进行分析【使用反射】
-
编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查
JDK中预定义的一些注解
- @Override:检测被该注解标注的方法是否是继承自父类(接口)
- @Deprecated:将该注解标注的内容,表示已过时
- @SuppressWarnings:压制警告
自定义注解
格式:
public @interface myAnno{}
对该文件进行反编译
本质:注解本质上是一个接口,该接口默认继承Annotation接口
属性:接口中的抽象方法
要求:
1、属性的返回值类型
* 基本数据类型
* String
* 枚举
* 注解
* 以上类型的数组
2、定义了属性,在使用时需要给属性赋值
1、如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值
2、如果只有一个属性需要赋值,就可以直接定义值
3、数组类型赋值的时候,值使用{}包裹,如果数组中只有一个值,则{}可以省略
元注解:用于描述注解的注解
*@Target:描述注解能够作用的位置
*ElementType取值:
*TYPE:可以作用于类上
*METHOD:可以作用于方法上
*FIELD:可以作用于成员变量上
*@Retention:描述注解被保留的阶段
*@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码中,并被JVM读取到
*@Documented:描述注解是否被抽取到api文档中
*@Inherited:描述注解是否被子类继承
在程序中使用注解:获取注解中定义的属性值。在以后大多数文件中注解的作用是用于替换配置文件(见cn.itcast.annocation.reflectTest)
-
获取注解定义位置得对象, class,method对象等
1
Class<reflectTest> reflectTestClass=reflectTest.class;
-
获取指定的注解
1
pro an=reflectTestClass.getAnnotation(pro.class);
-
调用注解中抽象的方法获取配置的属性值
1 2
String classname=an.className(); String methodname=an.methodName();
通过注解写简单的测试框架(见cn.itcast.annocation.demo)
大多数时候,都是使用注解,而不是定义注解。注解不是程序的一部分
注解使用者:
- 编译器
- 给解析程序用
数据库
特点:
- 持久化存储数据的
- 方便存储和管理数据
- 使用统一的方式操作数据库
mysql卸载
-
首先在mysql安装目录下找到my.ini文件
复制 datadir=D:\mysql\mysql-8.0.11-winx64\mysql-8.0.11-winx64\data
-
在控制面板中对mysql进行卸载
-
在文件夹中找到这个目录,卸载mysql的数据
配置
mysql服务启动
-
cmd——> services.msc 打开服务窗口
-
管理员权限cmd
Mysql登录
- mysql -uroot -p
- mysql -hip -uroot -p
- mysql –host=ip –user=root –password=密码
mysql退出
- exit
- quit
SQL:Structured Query Language
- SQL语句可以单行或者多行书写,但要用分号结尾
- 可使用空格和缩进来增强语句的可读性
- mysql语句不区分大小写,关键句用大写
SQL分类
DDL:操作数据库和表
-
操作数据库
-
增
创建数据库:create database bd1;(防止存在的情况可以:create database if not exists db1;)
设置特定的字符集:create database db2 character set gbk;
综合:create database if not exists db3 character set gbk;
-
删
删除数据库:drop database 数据库名称;
先判断数据库是否存在,存在再删除:drop database if exists db1;
-
改
修改数据库字符集:alter db character set utf8;
-
查
查询所有数据库名称:show databases;
查看对应数据库的字符集:show create database 数据库的名称;
-
使用数据库
查询当前正在使用的数据库名称:select database();
进入某个数据库:use db1;
-
-
操作表
-
增
创建表:create table 表名(
列名1 数据类型1,
列名2 数据类型2,
列名n 数据类型n
);
最后一列不加逗号
数据库类型:
整数类型:age int,
小数类型:score double(5,2)
日期类型:date
时间戳类型(timestamp):yy-MM-dd HH:mm:ss 如果不给这个字段赋值则默认当前时间系统
字符串类型(varchar):varchar(20)
-
删
删除表:drop table 表名;
删除表带条件:drop table if exists 表名;
-
改
修改表名:alter table 表名 rename to 新表名;
修改表的字符集:alter table 表名 character set 字符集名称;
添加一列:alter table 表名 add 列名 数据类型;
修改列的名称 类型:alter table 表名 change 列名 新列名 新数据类型;(alter table 表名 modify 列名 新数据类型;)
删除列:alter table 表名 drop 列名;
-
查
查询某个数据库所有表名称:show tables;
查询表结构:desc 表名;
-
客户端图形化工具
DML:操作数据
- 添加数据:insert into 表名(列名1,列名2,…,列名n) values(值1,值2,…,值n);
- 删除数据:delete from 表名 where 条件;
- 修改数据:update 表名 set 列名1=值1,列名2=值2…where 条件
TRUNCATE TABLE 表名;–删除表,然后创建一个一模一样的空表
DQL:查询数据
-
查询数据:select * from 表名;
-
语法
select (distinct)字段列表 from 表名列表
where 条件列表 ——分组前限定,不可以进行聚合函数的判断
group by 分组字段
having 分组之后的条件 —–分组后限定,可以进行聚合函数的判断
order by 排序
limit 分页限定
-
排序查询 ORDER BY MATH ASC(DESC),ENGLISH ASC(DESC);
-
聚合函数(排除了null的值)
- count:计算个数 COUNT(IFNULL(MATH,0)) 这样就可以将为NULL的数据统计个数
- max(min):计算最大值(最小值)
- sum:求和
- avg:求平均
-
聚合函数(查询分组字段或者聚合函数)
SELECT sex,AVG(math) FROM student GROUP BY sex;
SELECT sex,AVG(math) FROM student GROUP BY sex HAVING COUNT(id)>2;
-
分页限定
limit:开始的索引,每页查询的条数
SELECT * FROM TABLE LIMIT 0,3; —-第一页
SELECT * FROM TABLE LIMIT 3,3; —-第二页
任何数据+null会变成null,所以可以使用IFNULL方法,即IFNULL(age,0),表示如果age为null则设置为0
gender as sex,查询时将gender名字换成sex
条件查询运算符:
AND、条件运算符、BETWEEN…AND…、IN
NULL需要用is来进行修饰
LIKE:模糊查询
- SELECT * FROM TABLE WHERE NAME LIKE ‘马%’;(姓马)
- SELECT * FROM TABLE WHERE NAME LIKE ‘_化%’;(第二个字是化)
- SELECT * FROM TABLE WHERE NAME LIKE ‘___’;(名字是三个字)
- SELECT * FROM TABLE WHERE NAME LIKE ‘%马%’;(名字中含有马)
约束
对表中的数据进行限定,保证数据的正确性、有效性、完整性
分类
-
主键约束:primary key 非空且唯一
CREATE TABLE stu( id INT PRIMARY KEY, phone VARCHAR(20) );
ALTER TABLE stu DROP PRIMARY KEY; —-删除主键
ALTER TABLE stu MODIFY phone VACHAR(20) PRIMARY KEY —–创建主键
自动增长:在创建表时,使用 AUTO_INCREMENT完成自动增长
CREATE TABLE stu( id INT PRIMARY KEY AUTO_INCREMENT, phone VARCHAR(20) );
ALTER TABLE stu MODIFY id INT; —-删除自动增长
ALTER TABLE stu MODIFY phone VACHAR(20) PRIMARY KEY AUTO_INCREMENT, —–添加自动增长
-
**非空约束:NOT NULL **
CREATE TABLE stu( id INT, NAME VARCHAR(20) NOT NULL );
ALTER TABLE stu MODIFY NAME VARCHAR(20) (NOT NULL); —-删除(添加)其非空约束
-
唯一约束:unique
CREATE TABLE stu( id INT, phone VARCHAR(20) UNIQUE );
ALTER TABLE stu DROP INDEX phone; —-删除唯一约束
ALTER TABLE stu MODIFY phone VACHAR(20) UNIQUE —–创建唯一约束
-
外键约束:foreign key 通过外键的约束,使得B的某个列元素收到A的主键约束,并且A的数据不能轻易删除
-
在创造多张表的时候,可以添加外键
create table B(
…
外键列
constraint 外键名称 foreign key (外键列名称) references A(主列表名称)
);
-
删除外键
AlTER TABLE B DROP FOREIGN KEY 外键名称;
-
添加外键
AlTER TABLE B ADD constraint 外键名称 foreign key (外键列名称) references A(主列表名称);
级联更新操作:在添加外键的时候设置级联
AlTER TABLE B ADD constraint 外键名称
foreign key (外键列名称) references A(主列表名称) ON UPDATE CASCADE ON DELETE CASCADE;
-
数据库的设计
-
多表之间的关系
-
分类
-
一对一:
人和身份证的关系
-
一对多(多对一)
部分和员工
-
多对多
学生和课程
-
-
实现
-
一对多
实现方式:在多的一方建立外键,在一的一方建立主键
-
多对多
建立一张中间表,两边的主键加入其中
-
一对一
合成一张表
-
-
-
数据库设计的范式
设计数据时,需要的一些规范
分类:
-
第一范式:每一列都是不可分割的原子数据项
-
第二范式:在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码部分函数依赖)
函数依赖:A–》B,如果通过A属性,可以唯一确定B,则称B依赖于A
完全函数依赖:A–》B,如果A是一个属性组,则B属性值的确定需要依赖于A属性组中所有的属性值
部分函数依赖:A–》B,如果A是一个属性组,则B属性值的确定需要依赖于A属性组中部分属性值
传递函数依赖:A–》B,B–》C,则A–》B
码:在一张表中,一个属性或属性组,被其他属性完全依赖,则称这个属性为该表的码
主属性:码属性组中所有的属性
非主属性:除去码属性组的属性
通过拆分表,使得分主属性完全依赖于主属性
-
第三范式:在2NF的基础上,任何非主属性不依赖于其他非主属性(消除传递依赖)
-
数据库的备份和还原
-
命令行的方式
备份方式:mysqldump -u用户名 -p密码 数据库名称> 保存路径
还原方式
- 登录数据库
- 创建数据库
- 使用数据库
- 执行文件 source 文件路径
-
图形化工具
多表查询
笛卡尔积—–消除无用的数据
多表查询分类:
-
内连接查询
- 隐式内连接:使用where条件来消除无用数据
- 显示内连接:SELECT 字段列表 FROM 表名1 [INNER] JOIN 表名2 ON 条件;
使用内连接要知道:
1、从哪些表查询数据,2、条件是什么,3、查询哪些字段
-
外连接查询
-
左外连接:SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 条件
查询的是左表所有数据以及其交集部分(当右表有数据缺失时,如果使用内连接则不能查到缺失组成的行)
-
右外连接:SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 条件
-
-
子查询
查询中嵌套的查询为子查询
子查询的不同情况:
-
子查询结果是单行单列:子查询的结果是一个值,便可以直接用计算符来进行计算
-
子查询结果是多行单列:使用运算符in来进行判断
SELECT * FROM TABLE1 WHERE ID IN (SELECT ID FROM TABLE2 WHERE NAME=’张三’ OR NAME=’李四’);
-
子查询结果是多行多列:将该结果作为一个虚拟表参与查询
多表查询,首先看要查找的元素分别是哪几个表,然后在找表之间关联的属性,对其进行连接
-
事务
概念:如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败
四大特征:
- 原子性:不可分割,同时成功或失败
- 持久性:事务一旦提交或回滚,数据库表会持续跟新
- 隔离性:多个事务之间相互独立
- 一致性:事务操作前后,数据总量不变
操作:
- 开启事务:START TRANSACTION;
- 回滚:返现出问题了,进行回滚事务 ROLLBACK;
- 提交:COMMIT;
事务的提交方式有两种:
-
自动提交
- mysql是自动提交
- 一个dml语句会自动提交一次事务
-
手动提交
oracle数据库是默认提交
需要先开启事务,再提交
修改事务默认提交方式:
- 查看事务默认提交方式:SELECT @@autocommit; –1代表自动提交,0是手动
- 修改默认方式:set @@autocommit =0;
事务的隔离级别:多个事务之间是隔离的,相互独立的,如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别可以解决这些问题
存在的问题:
- 脏读:一个事务,读取到同一个事务中没有提交的数据
- 不可重复读:在同一个事务,两次读取的数据不一样
- 幻读:一个事务操作数据表中所有记录,另一个事务添加了一个数据,则第一个事务查询不到自己的修改
隔离级别:用于解决上面问题 级别越高,效率越低
- read uncommited:读未提交 存在的问题:脏读、不可重复读、幻读 a事务进行操作后,b事务就能收到表的变化
- read commited:读已提交 存在的问题:不可重复读、幻读 a事务进行操作后,并commited,b事务收到表的变化
- repeatable read:可重复读 存在的问题:幻读 a事务进行操作后并commited,b事务需要自己commited,才能收到表的变化
- serializable:串行化 存在的问题:无 加锁,在事务表操作时,其他表不能操作
查询隔离级别:SELECT @@tx_isolation;
设置隔离级别:set global transaction isolation level 级别字符串;
DCL:管理用户,授权
在mysql修改root密码
- cmd—-》net stop mysql;
- 使用无验证方式启动mysql服务:mysqld –skip-grant-tables
- use mysql;
- UPDATE USER SET PASSWORD=PASSWORD(‘新密码’) WHERE USER=’用户名’;
- 关闭两个窗口
- 打开任务管理器,手动结束mysqld.exe的进程
- 启动musql服务
- 使用新密码登录
DCL操作:
-
管理用户
- 增:CREATE USER ‘用户名’@’主机名’ IDENTIFIED BY ‘密码’;
- 删:DROP USER ‘用户名’@’主机名’;
- 改:UPDATE USER SET PASSWORD=PASSWORD(‘新密码’) WHERE USER=’用户名’;
- 查:USE mysql; SELECT * FROM USER;
-
权限管理
-
查询权限:show GRANTS FOR ‘用户名’@’主机名’;
-
授予权限:GRANT 权限列表 ON 数据库名.表名 TO ‘用户名’@’主机名’;
GRANT ALL ON * . * TO ‘用户名’@’主机名’;
-
撤销权限:REVOKE 权限列表 ON 数据库名.表名 FROM ‘用户名’@’主机名’;
-
JDBC
java语言操作数据库,定义了所有操作关系型数据库的规则(接口),各个数据库厂商去实现这套接口,提供数据库驱动的jar包,使用JDBC编程,真正执行的是驱动jar包的实现类
使用JDBC
-
导入驱动jar包
复制jar到项目libs目录下
右键–》add as library
-
注册驱动
-
获取数据库的连接对象Connection
-
定义sql语句
-
获取执行sql语句对象Statement
-
执行sql,接受返回结果
-
处理结果
-
释放资源
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) throws Exception {
//1.导入驱动jar包
//2.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//3.获取数据库连接对象
//***因为jar包用的是8.0以上的版本,数据库与系统之间有时差,在jdbc连接后面的url加上?serverTimezone=UTC即可
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?serverTimezone=UTC","root","dycdyc");
//4.定义一个sql语句
String sql="UPDATE stu SET score=60 WHERE id=1";
//5.获取执行sql的对象
Statement stmt=conn.createStatement();
//6.执行sql
int count=stmt.executeUpdate(sql);
//7.处理结果
System.out.println(count);
//8.释放资源
stmt.close();
conn.close();
}
详解各个对象
-
DriverManager:驱动管理对象
功能:
-
注册驱动:告诉程序该使用哪一个数据库驱动jar包
-
static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManager
-
写代码使用: Class.forName(“com.mysql.cj.jdbc.Driver”);
在源码中com.mysql.cj.jdbc.Driver类调用registerDriver方法
mysql5之后可以省略注册驱动的步骤
-
-
获取数据库连接
static Connection getConnection(String url,String user,String password);
url:指定连接路径 jdbc:mysql://ip地址:端口号/数据库名称
-
-
Connection:数据库连接对象
功能:
-
获取执行sql的对象
-
Statement createStatement()
-
PreparedStatement PreparedStatement(String sql)
-
-
管理事务
- 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务
- 提交事务:commit()
- 回滚事务:rollback()
-
-
Statement:
-
执行sql
-
boolean execute(String sql):可以指向任意sql
-
int executeUpdate(String sql):执行DML,DDL语句
返回值是数据库中影响的行数
-
ResultSet executeQuery(String sql):执行sql语句
-
-
-
ResultSet:
-
next方法:游标向下移动一行,判断当前行是否是最后一行末尾,如果是则返回false
-
getxxx(参数):获取数据
xxx:代表数据类型 如:int getInt(参数)
参数:
- int:代表列的编号,从1开始
- String:代表列的名称
1 2 3 4 5
while(rs.next()){ //循环判断是否遍历完所有数据 int id = rs.getInt(1); String name = rs.getString("name"); System.out.println(id+name); }
定义一个方法,查询stu表的数据将其封装成对象,装载集合返回
- 定义stu类
- 定义方法
- 实现方法 select *from stu
定义JDBC工具类:JDBCUtils
目的:简化书写
抽取部分:
-
注册驱动抽取
-
连接对象抽取
需求:不想传递参数,还得保证工具类的通用性
解决:通过配置文件
-
释放资源抽取
练习:做一个登录界面
需求:
- 通过键盘录入用户名和密码
- 判断用户是否登录成功
步骤:
-
创建数据库表
CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20) NOT NULL, PASSWORD INT ); SELECT * FROM USER;
INSERT INTO USER VALUES(NULL,’zhangsan’,123); INSERT INTO USER VALUES(NULL,’lisi’,123);
-
创建登录类
-
-
PreparedStatement:执行sql对象
-
sql注入问题:在凭借sql时,在一些sql的特殊关键字参与字符串的拼接,
- 输入用户随变,输入密码:a’ or ‘a’ =’a
- sql语句时:SELECT * FROM stu WHERE name=‘ssss’ AND password=a’ or ‘a’ =’a’ //or后面语句为true
-
解决sql注入问题:使用PreparedStatement对象来解决
-
预编译SQL:参数使用?作为占位符
-
步骤:
-
导入驱动jar包
-
注册驱动
-
获取数据库的连接对象Connection
-
定义sql语句
注意:sql的参数使用?作为占位符。如SELECT * FROM stu WHERE name=? AND password=?;
-
获取执行sql语句对象PreparedStatement Connection.preparedStatement(String sql)
-
给?进行赋值
setxxx(参数1,参数2)
- 参数1:?的位置编号,从1开始
- 参数2:?的值
-
执行sql,接收返回结果,不需要sql语句
-
处理结果
-
释放资源
-
后期都会使用PreparedStatement来完成增删改查的所有操作
- 可以方式sql注入
- 效率更高
-
使用JDBC控制事务
操作事务:
- 开启事务
- 提交事务
- 回滚事务
使用Connection对象来管理事务
-
开启事务:setAutoCommit(Boolean autoCommit):调用该方法设置参数为false,即开启事务 在执行sql语句前开启事务
-
提交事务:commit()
在结束时提交事务
-
回滚事务:rollback()
在try catch中回滚事务
数据库连接池
一个集合,存放数据库连接的容器(当系统初始化后,容器被创建,容器会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完后,会将连接对象归还给容器)
实现:
-
标准接口:DataSource java.sql包下
-
方法:
获取连接:getConnection()
归还连接:如果连接对象是从连接池中获取的,那么Connection.close()便不回关闭连接,变成了归还连接
-
-
一般不去实现,有数据库厂商进行实现
-
C3P0:数据库连接池技术
-
导入jar包 c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar
-
定义配置文件
名称:c3p0.properties 或者 c3p0-config.xml
路径:直接放在src目录下面
-
创建核心对象 数据库连接池对象
-
获取连接:getConnection
-
-
Druid:数据库连接池技术
步骤:
-
导入jar包 druid-1.0.9.jar
-
定义配置文件
- 是properties形式
- 可以叫任何名称
-
加载配置文件
-
获取数据库连接池对象:通过工厂类来获取 DruidDataSourceFactory
-
获取连接:getConnection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
public static void main(String[] args) throws Exception { //导入jar包 //定义配置文件 //加载配置文件 Properties pro=new Properties(); InputStream is=DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); //获取连接池对象 DataSource ds=DruidDataSourceFactory.createDataSource(pro); //获取连接 Connection conn=ds.getConnection(); System.out.println(conn); } 配置文件 druid.properties driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/db1?serverTimezone=UTC username=root password=dycdyc initialSize=5 //初始化5个 maxActive=10 //最多10个 maxWait=3000 //等待时间最多3000
定义工具类
- 定义一个类JDBCutils
- 提供静态代码块加载配置文件,初始化连接对象
- 提供方法
- 获取连接方法:通过数据库连接池获取连接
- 释放资源
- 获取连接池的方法
-
-
Spring JDBC:JDBC Template
Spring框架对JDBC的简单封装。提供了一个JDBC Template对象对JDBC的开发
步骤:
-
导入jar包
-
创建JDBC Template对象,依赖于数据源DataSource
1
JdbcTemplate template=new JdbcTemplate(JDBCutils.getDataSource());
-
使用JDBC Template的方法来完成增删改查的操作
update():执行DML操作
1 2 3 4
public void test1(){ String sql="update stu set score =20 where id =?"; template.update(sql,3); }
queryFORMap():查询结果封装为map 查询的结果集长度只能是1
1 2 3 4 5 6
public void test2(){ String sql="SELECT * FROM stu WHERE id=?"; Map<String,Object>map=template.queryForMap(sql,3); System.out.println(map); /*{id=3, name=wangwu, score=20}*/ }
queryFORList():查询结果封装为list 将每一个记录封装为map集合,再将集合封装为list集合中
1 2 3 4 5 6 7 8 9 10 11 12
public void test3(){ String sql="SELECT * FROM stu "; List<Map<String,Object>> list=template.queryForList(sql); for(Map<String,Object> x:list){ System.out.println(x); } /* * {id=1, name=zhangsan, score=200} {id=2, name=lisi, score=100} {id=3, name=wangwu, score=20} * */ }
query():查询结果封装为JavaBean对象 一般使用BeanPropertyRowMapper实现类,可以完成数据到javaBean自动封装
1 2 3 4 5 6 7
public void test5(){ String sql="SELECT * FROM stu "; List<stu>list=template.query(sql,new BeanPropertyRowMapper<stu>(stu.class)); for(stu x:list){ System.out.println(x); } }
queryFoeObject():查询结果,封装为对象
用于聚合函数的运行
1 2 3 4 5
public void test6(){ String sql="SELECT count(id) FROM stu "; int count=template.queryForObject(sql,int.class); System.out.println(count); }
软件架构
-
C/S:client/server 客户端/服务器端
在本地有一个客户端程序,在远程有一个服务器端程序
优点:用户体验好
缺点:开发,安装,部署,维护麻烦
-
B/S:browser/server 浏览器/服务器端
只需要一个浏览器,用户通过不同的网址,客户访问不同的服务器端程序
优点:开发,安装,部署,维护简单
缺点:如果应用过大,用户体验会受影响;对硬件要求过高
资源分类
-
静态资源:
使用静态网页开发技术发布的资源
特点:
- 所有用户访问,得到结果是一样的
- 如文本,图片,音频 HTML,CSS,JavaScript
- 如果用户请求是静态资源,那么服务器会直接将静态资源发送给浏览器,浏览器内置了静态资源的解析引擎,可以展示静态资源
-
动态资源:
使用动态网页及时发布的资源
特点:
- 所有用户访问,得到的结果可能不一样
- 如:jsp/servlet,php,asp
- 如果用户请求的动态资源,服务器会执行动态资源,转化为静态资源,再发送给浏览器
静态资源:
- HTML:用于搭建基础网页,展示页面的内容
- CSS:用于美化页面,布局页面
- JavaScript:控制页面元素,让页面有动态效果
-
HTML
Hyper Text Markup Language 超文本标记语言
-
超文本:
超文本是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本
-
标记语言
由标签构成的语言 如html,xml
标记语言不是编程语言,没有逻辑性
语法:
-
后缀名为:.html
-
标签:
-
围堵标签:有开始标签和结束标签。如<html></html>
标签之间可以嵌套 <html><head></head></html>
-
自闭和标签:开始标签和结束标签在一起。如
-
-
在开始标签中可以定义属性,属性有键值对构成,值需要用引号引起来
-
标签不区分大小写,建议使用小写
标签:
-
文件标签:构成html最基本的标签
-
html:html文档根标签
-
head:头标签,用于指定html文档一些属性
-
title:标题标签
-
body:体标签
-
!DOCTYPE:html5中定义该文档为html标签
-
meta:定义文字类型,在body中
1
<meta charset="UTF-8">
-
-
文本标签:和文本有关的标签
-
h1 to h6:字体逐渐减小
-
p:进行分段
-
br:换行
-
hr:显示一条水平线
-
b:字体加粗
-
i:字体倾斜
-
font:字体标签
1 2 3 4 5 6 7 8 9 10 11 12
<font color="red" size="5" face="楷体"> 白日依山尽,<br/> <i><b>黄河入海流。</b></i> </font> 属性定义: color: 1、英文单词 2、rgb(x,y,z) 3、#xyz width: 1、数值 2、百分比
-
注释:
-
center:文本居中
-
-
图片标签:
img标签:展示图片
相对路径:
- 以.开头的路径
- ./:代表当前目录
- ../:代表上一级目录
1 2
<!--当图片加载失败时,显示alt里的内容--> <img src="image/6e64a01f8dd1313d744d4523f9b68e1.jpg" align="right" alt="风景" width="500" height="300"/>
- 以.开头的路径
-
列表标签:
- 有序列表
- ol:
- li:
- 无序列表
- ul:
- li:
1 2 3 4 5 6 7 8 9 10 11 12 13
<ol type="A" start="5"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ol> <hr/> <ul type="disc"/"square"/"circle"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul>
- 有序列表
-
超连接标签:
用a来定义超链接
1
<a href="https://www.baidu.com">百度</a>
-
target:指定打开资源的方式
1 2 3 4 5
<a href="https://www.baidu.com">百度</a> <br> <a href="https://www.baidu.com" target="_blank">百度</a><!--在新页面打开--> <br> <a href="https://www.baidu.com" target="_self">百度</a><!--在当前页面打开-->
-
访问其他页面标签
1 2
<a href="5_列表标签.html">列表标签</a><br> <a href="mailto:1351355@qq.com"></a>
-
和image标签结合使用(点击图片进入其他页面)
1
<a href="1_helloworld.html"> <img src="image/07c79eaf27d2be6c2c440c78a4b324c.jpg"></a>
-
-
表格标签:
table:定义表格
- width
- border
- cellpadding:定义内容和单元格间距
- cellspacing:定义单元格之间的间距,如果为0则单元格线合为1条
- bgcolor:背景色
tr:定义行
- bgcolor:背景色
- align:文本格式
th:定义表头单元格
td:定义列
- colspan:合并行
- rowspan:合并列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
<table border="1" width="50%" cellpadding="0" cellspacing="0" bgcolor="#faebd7" align="center"> <caption>学生信息表</caption> <!--第一行三列,第二第三行两列--> <tr> <th rowspan="2">编号</th> <th>姓名</th> <th>成绩</th> </tr> <tr> <td>1</td> <td></td> </tr> <tr> <td>2</td> <td colspan="2"></td> </tr> </table>
caption:标题
thead:表示表的头部分
tbody:表示表的体部分
tfoot:表示表的尾部分
1 2 3 4 5 6 7 8 9 10 11 12 13
<table border="1" width="50%" cellpadding="0" cellspacing="0" bgcolor="#faebd7" align="center"> <caption>学生信息表</caption> <tr> <th>编号</th> <th>姓名</th> <th>成绩</th> </tr> <tr> <td>1</td> <td></td> <td></td> </tr> </table>
-
语义化标签:
1 2 3
用于程序可读性 <header></header> <footer></footer>
-
表单标签:
表单:用于采集用户输入数据的,用于和服务器进行交互
使用form标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<!--form:用于定义表单,可以定义一个范围,范围代表采集用户数据得范围 1、action:指定提交数据的url位置 2、method:指定提交方式 分类:一共七种,有两种比较常见 get: 1、请求参数会在地址栏中显示 2、请求参数的长度有限制 3、不安全 post: 1、请求参数不会在地址栏中显示,会封装在请求体中 2、请求参数的长度没有限制 3、较为安全 3、表单项的数据想要被提交:必须指定name属性 --> <form action="#" method="get"> 用户名:<input name="username"><br> 密码:<input name="password"><br> <input type="submit" value="登录"> </form>
input:可以通过type属性值,改变元素展示形式
type属性:
-
text:文本输入框
placeholder:指定输入框的提示信息,当输入框的内容发生变化,会自动清空提示信息
-
password:密码输入框
-
radio:单选框
- 要让多个单选框实现单选效果,则多个单选框name属性必须一样
- 一般会给每一个单选框提供value属性,指定其被选中后提交的值
- checked属性,可以指定属性默认值
-
checkbox:复选框
- 一般会给每一个单选框提供value,指定其选中后提交的值
- checked属性,指定默认值
-
file:文件选择框
-
hidden:隐藏域
-
按钮
sumbit:提交按钮
button:用于js结合使用
image:图片提交按钮
src:指定图片路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<form action="#" method="get"> <label for="username"> 用户名:</label><input type="text" name="username" placeholder="请输入用户名" id="username"><br> 密码:<input type="password" name="password"><br> 性别:男<input type="radio" name="gender" value="male" checked> 女<input type="radio" name="gender" value="female"><br> 爱好:<input type="checkbox" name="hobby" value="1" checked >玩 <input type="checkbox" name="hobby" value="2">玩 <input type="checkbox" name="hobby" value="3">玩<br> 图片:<input type="file" name="file"><br> 隐藏域:<input type="hidden" value="aa" name="id"><br> 取色器:<input type="color" name="color"><br> 生日:<input type="date" name="data"><br> 生日:<input type="datetime-local" name="date"><br> 邮箱:<input type="email" name="email"><br> 年龄:<input type="number" name="age"><br> <input type="submit"> </form>
label:指定输入项文字描述信息
- label的for属性一般会和input的id属性对应,就可点击label区域,会让imput输入框获得焦点
1 2 3
<form action="#" method="get"> <label for="username"> 用户名:</label><input type="text" name="username" placeholder="请输入用户名" id="username"><br> </form>
select属性:下拉列表
1 2 3 4 5 6 7 8
<form action="#" method="get"> 省份:<select name="province"> <option>请选择</option> <option value="1">1</option> <option value="22">2</option> </select> <input type="submit"> </form>
textarea属性:文本域
1 2
<textarea cols="20" rows="50" name="des"> </textarea>
-
-
div和span:
1 2 3 4 5 6
<!--span:文本信息在一行中展示,行内标签,内联标签--> <span>黑马</span> <span>传值</span> <!--div:每一个div占满一行,块级标签--> <div>黑马</div> <div>传值</div>
可以使用table来进行布局,可以使用table嵌套
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<table border="1" width="50%" cellpadding="0" cellspacing="0" align="center">
<tr>
<td>
<a href=""></a>
</td>
</tr>
<tr>
<td>
<table>
<tr>
<td>
<img src="" alt="">
<p>
sidjsidjd
</p>
</td>
<td>
<img src="" alt="">
</td>
<td>
<img src="" alt="">
</td>
</tr>
</table>
</td>
</tr>
</table>
CSS
层叠样式表
好处:
- 功能强大
- 将内容的展示和样式控制分离
- 降低耦合度
- 让分工协作更容易
- 提高开发效率
css与html的结合(三种方式的作用范围越来越大)
- 内联:在标签使用style属实指定css代码
- 内部:在head标签内定义style标签,style标签体的内容就是css代码
- 外部:定义css资源文件,在head标签内,定义link标签,引入外部资源文件
css基本语法:
格式:
选择器{
属性名:属性值1;
属性名:属性值2;
}
选择器:筛选具有相似特征的元素
-
基本选择器
- id选择器
- 元素选择器
- 类选择器
优先级:id>类>元素
-
扩展选择器
属性
-
字体
- font-size
- color
- text-align
- line-height
-
背景
- background
- background:url(“图片链接”) no repeat center
- background:color
- background
-
边框
- boder
-
尺寸
- width
- height
-
盒子模型
-
margin:外边距
-
padding:内边距
默认情况下内边距会影响盒子的大小,可以通过box-sizing: border-box;设置盒子的属性,让width和height就是最终盒子的大小
-
float:浮动
left right
-
案例
首先对页面内容进行布局,用div进行分块,然后对每个分块用css进行修饰
JavaScript
客户端脚本语言,运行在客户端浏览器中,每个浏览器都有其解析引擎
脚本语言:不需要编译,可直接被浏览器解析执行,不需要服务器运行,直接在浏览器上运行,这样可以节省时间,增加用户体验
功能:增强用户和页面交互性过程,控制html元素,让页面有动态效果
JavaScript=ECMAScript+JavaScript特有的东西(DOM+BOM)
ECMAScript
-
基本语法
-
与html结合方式
-
内部js
1 2 3 4
<input type="text"> <script> alert("hello world"); </script>
-
外部js
1
<script src="js/a.js"></script>
可以定义任何位置,但是定义位置会影响执行顺序
-
-
注释
// /**/
-
数据类型
- 原始数据类型
- number:整数/小数/NaN
- string
- boolean
- null
- undefined:未定义,如果一个变量未给初始化值,则定义为undefined
- 引用数据类型:对象
- 原始数据类型
-
变量
java是强类型的,javascript是弱类型
强类型在开辟变量存储空间,定义空间将来存储的数据的数据类型,只能存储固定类型的数据
弱类型在开辟变量存储空间,不定义空间将来存储的数据的数据类型,可以存放任意类型的数据
语法:
1
var 变量名=初始化值;
-
运算符
-
一元运算符
在JS中,如果运算数不是运算符所要求的类型,那么js引擎会自动的将运算数进行类型转化
其他类型转number:
string转number:按照字面值直接进行转化,但如果不是数字,则转为NaN
1 2
var a= +"123" ----转为number类型 var a= +"abc" ----转为NaN
boolean转number:true转1,false转0
-
算数运算符
-
赋值运算符
-
比较运算符
如果类型不同,先进行类型转化,再进行比较
===:全等于,在比较之前先判断类型,如果类型不同,则不会再进行比较
-
逻辑运算符
其他类型转boolean:
1.number:0为假
2.string:空字符串为假
3.null和undefined:false
4.所有对象都是true
-
三元运算符
-
-
流程控制语句
-
if else
-
switch
所有类型都可以
-
for
-
while
-
do while
-
-
-
基本对象
-
Function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
1.创建 1.var fun1=new Function("a","b","alert(a)") 2.通过function 方法名称(参数){方法体} 3.var 方法名=function(形式参数){方法体} 2.方法 3.属性 1.length:代表形参的个数 4.特点 1.方法定义时,形参的类型不用写 2.方法是一个对象,如果定义名称相同的方法,会进行覆盖 3.在js中,方法的调用只与方法的名称有关,与参数列表无关,即可以传与形参数量不等的参数 4.在方法声明中,有一个隐藏的内置对象,arguments封装所有实际参数 例: /*定义任意参数数量的加法*/ function add(){ var sum=0; for(var i=0;i<arguments.length;i++){ sum+=arguments[i]; } return sum; } 5.调用
-
Boolean
-
Array:数组对象
1 2 3 4 5 6 7 8 9 10
1.创建 1.var arr=new Array(元素列表); 2.var arr=new Array(默认长度); 3.var arr=[元素列表]; 2.特点 1.数组元素的属性是可变的 2.数组元素的长度是可变的 3.方法 1.join:将数组中元素按照指定的分隔符拼接为字符串 2.push:在数组末尾添加一个元素
-
Date
1 2 3 4 5 6 7 8 9 10 11
Date:日期对象 1.创建 1. var date=new Date(); 2.方法: toLocalString():返回当前date对象对应的时间本地字符串格式 getTime():获取毫秒值,返回当前如期对象描述的时间到1970年1月1日零点的毫秒值 var date=new Date(); document.write(date+"<br>"); document.write(date.toLocaleString()+"<br>"); document.write(date.getTime()+"<br>");
-
Math
1 2 3 4 5 6 7 8 9 10 11 12
/* 1.创建 math对象不用创建直接使用,即直接使用Math. 2.方法 random():返回0-1之间随机整数,含0不含1 ceil():对数进行向上取整 floor():对数进行向下取整 round():把数四舍五入进行取整 3.属性 */ document.write(Math.random()+"<br>"); document.write(Math.floor(Math.random()*100)+1);
-
Number
-
String
-
RegExp:正则表达式对象
-
正则表达式:定义字符串的组成规则
-
单个字符
如:[a] [ab] [a-zA-Z0-9_]
特殊符号代表特殊含义的单个字符
\d:单个数字字符[0-9]
\w:单个单词字符[a-zA-Z0-9_]
-
量词符号
*:表示出现0次或多次
?:表示出现0次或1次
+:出现1次或多次
{m,n}:表示数量大于等于m,小于等于n
m,n可以缺省
-
开始结束符号
^:开始
$:结束
-
-
正则对象:
- 创建
- var reg=new RegExp(“正则表达式”);
- var reg=/正则表达式
- 方法
- test(参数):验证指定的字符串是否符合正则定义的规范(所以可以通过正则表达式来进行表单检验)
- 创建
-
-
Global
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Global 1.特点:全局对象,这个globa中封装的方法不需要对象就可以直接调用 2.方法: 1.解码编码 encodeURI():url编码 decodeURI():url解码 encodeURIComponent():url编码,编码的字符更多 decodeURIComponent():url解码 2.数字类型转化 parseInt():将字符串转化为数字 *逐一判断每一个字符是否是数字,直到不是数字为止,将前边数字部分转化为number 3.isNaN():判断一个值是否是NaN 用==是不能直接判断的,需要借用这个函数 4.eval():将JavaScript字符串,转换成脚本执行
-
BOM:Browser object Model
将浏览器的各个组成部分封装成对象
组成:
window:窗口对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
window对象
1.创建
2.方法
1.与弹出框有关的方法
alert() 显示带有一段消息和一个确认按钮的警告框
confirm() 显示带有一段消息以及确认按钮和取消按钮的对话框
prompt() 显示可提示用户输入的对话框
2.与打开关闭窗口有关的方法
close() 关闭浏览器窗口,谁调用关谁
open() 打开一个新的浏览器窗口
3.定时器
setTimeout() 在指定的毫秒数后调用函数或计算表达式
参数
1.js代码或者方法对象
2.毫秒值
clearTimeout() 取消由 setTimeout() 方法设置的 timeout
setInterval() 按照指定的周期(以毫秒计)来调用函数或计算表达式
clearTimeout() 取消由 setTimeout() 方法设置的 timeout
3.属性
1.获取其他BOM对象
history
location
Navigator
Screen
2.获取DOM对象
获取Document
4.特点
1.window对象不需要创建可以直接用window使用 window.方法名();
2.window引用可以省略 方法名()
轮播图案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<img src="img/1.jpg" width="100%" id="img">
<script>
/*
1.页面使用img标签展示图片
2.定义一个方法,修改图片对象src属性
3.定义一个定时器,每隔一段时间调用方法一次
*/
var num=0;
function fun(){
var s=document.getElementById("img");
s.src="img/"+(num%2+1)+".jpg";
num++;
}
setInterval(fun,3000);
</script>
Navigator:浏览器对象
Screen:显示屏对象
History:历史记录对象
方法:
back()
forword()
go()
属性:
length:返回当前窗口历史列表的url记录
Location:地址栏对象
方法:
reload();
属性:
href
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<input type="button" id="btn" value="刷新">
<input type="button" id="itcast" value="itcast">
<script>
//定义一个按钮,点击按钮,刷新当前页面
//获取按钮
var btn=document.getElementById("btn");
btn.onclick=function (){
location.reload();
}
//获取href
alert(location.href);
var itcast=document.getElementById("itcast");
itcast.onclick=function (){
location.href="https://www.bilibili.com"
}
</script>
DOM:
功能:用于控制html文档的内容,将标记语言文档的各个组成部分,封装为对象。可以使用这些对象,对标记语言文档进行CRUD的动态操作
代码:获取页面标签对象 Element
document.getElementById(“id值”):通过元素的ID获取元素的对象
DOM被分为三个不同部分
-
核心DOM:针对任何结构化文档的标注模型
Document:文档对象
-
获取Element对象
-
getElementById():根据id属性值获取对象,id属性值一般唯一
-
getElementsByTagName():根据元素名称获取元素对象们,返回值是一个数组
-
getElementsByClassName():根据Class属性值获取元素对象,返回值是一个数组
-
getElementsByName():根据name属性值获取元素对象,返回值是一个数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<div >div1</div> <div >div1</div> <div class="cs1">div1</div> <div class="cs1">div1</div> <input type="text" name="username"> <script> //getElementsByTagName():根据元素名称获取元素对象们,返回值是一个数组 var divs=document.getElementsByTagName("div"); document.write(divs.length); //getElementsByClassName():根据Class属性值获取元素对象,返回值是一个数组 var div2=document.getElementsByClassName("cs1"); document.write(div2.length) //getElementsByName():根据name属性值获取元素对象,返回值是一个数组 var div3=document.getElementsByName("username"); document.write(div3.length); </script>
-
-
创建其他DOM对象
createElement()
Elment:元素对象
-
通过Document对象获取
-
方法:
- removeAttribute():删除属性
- setAttribute():设置属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<a>hhh</a> <input type="button" value="设置属性" id="btn"> <input type="button" value="删除属性" id="btn1"> <script> var btn=document.getElementById("btn"); btn.onclick=function (){ //获取a标签 var a1=document.getElementsByTagName("a")[0]; a1.setAttribute("href","https://www.bilibili.com"); } var btn1=document.getElementById("btn1"); btn1.onclick=function (){ //获取a标签 var a1=document.getElementsByTagName("a")[0]; a1.removeAttribute("href"); } </script>
Atttibute:属性对象
Text:文本对象
Comment:注释对象
Node:节点对象,其他五个的父节点
-
特点:所有dom对象都被认为是一个节点
-
方法
-
crdu dom树
-
appendChild():向节点的子节点列表的结尾添加新的子节点
-
removeChild():删除当前节点的指定子节点
-
replaceChile():用新节点替换一个子节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<div id="div1"> <div id="div2">div2</div> div1 </div> <a href="javascript:void(0);" id="de1">删除节点</a> <!--如果不加这句话,点击链接时就会跳转到当前界面,看不出删除效果--> <script> var aa=document.getElementById("de1"); aa.onclick=function (){ var d1=document.getElementById("div1"); var d2=document.getElementById("div2"); d1.removeChild(d2); } </script>
-
-
-
-
XML DOM
-
HTML DOM
- 标签体的设置和获取:innerHTML
- 使用HTML元素对象的属性
- 控制样式
操作Element对象:
-
设置属性值
- 明确获取的对象是哪个
- 查看API文档,找其中有哪些属性可以设置
-
修改标签体内容
属性:innerHTML
1.获取元素对象
2.使用innerHTML属性修改标签体内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<div>div</div> <div>div2</div> <script> //直接通过编码的方式进行修改 var d=document.getElementsByTagName("div")[0] d.onclick=function (){ d.style.border="1px solid red"; d.style.fontSize="20px"; } //提前定义好类选择器的样式 var d1=document.getElementsByTagName("div")[1] d1.onclick=function (){ d1.className="d1"; } </script>
事件
功能:某些组件被执行某些操作后,触发某些代码的执行
绑定事件
-
直接在html标签上,指定事件的属性,属性值就是js代码
事件:onclick———单击事件,就会触发其他事件
-
通过js获取元素对象,指定事件属性,设置一个函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
<img src="img/1.jpg" onclick="fun()" id="light"> <img src="img/1.jpg" id="light2"> <script> function fun(){ alert('123'); } function fun2(){ light2.src="img/2.jpg"; } var light2=document.getElementById("light2"); light2.onclick=fun2; </script>
Bootstrap
一个前端开发的框架,基于HTML,CSS,JavaScript,简单灵活,是web开发更加快捷
定义了很多css,html插件,响应式布局(同一套页面可以兼容不同分辨率的设备)
使用bootstrap
- 下载bootstrap
- 在项目中将这三个文件夹复制
- 创建html界面,引入资源文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link rel="stylesheet" href="css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="js/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
</head>
<body>
<h1>使用bootstrap的基本模板</h1>
</body>
</html>
响应式布局
同一套页面可以兼容不同分辨率的设备
实现:依赖于栅格系统:将一行平均分为12个格子,可以指定元素占几个格子
步骤:
-
定义容器,相当于table
容器分类:
- container:固定长度 两边留白
- container-fluid:100%
-
定义行,相当于tr
-
定义元素,指定该元素在不同的设备上,所占格子的数目 样式:col-设备代码-格子数目
- xs
- sm
- md
- lg
注意:
- 一行如果格数超标,会自动换行
- 类属性向上兼容 栅格类适用于与屏幕宽度大于等于分界点大小的设备
- 如果真实设备小于设置栅格类属性的设备代码的最小值,会一个元素占满一整行
css样式和js插件
全局css样式:
-
按钮 class=”btn btn-default”
-
图片
图片形状
1 2 3
<img src="..." alt="..." class="img-rounded"> <img src="..." alt="..." class="img-circle"> <img src="..." alt="..." class="img-thumbnail">
-
表格
-
表单
组件
- 导航条
- 分页条
插件
- 轮播图
XML
概念:可扩展标记语言
可扩展:标签都是自定义的
功能
xml和html区别
- xml标签自定义,html预定义
- xml语法严格
- xml是存储数据,html展示数据
语法:
-
基本语法
- 后缀名:xml
- xml第一行必须定义为文档声明
- xml文档中有且仅有一个根标签
- 属性值必须用引号
- 标签必须正确关闭
- xml标签区分大小写
-
组成部分
-
文档说明
- 格式:<?xml 属性列表 ?>
- 属性列表:
- version:版本号
- encoding:编码方式
- standalone:是否独立
- yes:不依赖其他文件
- no:依赖其他文件
-
指令:结合css <?xml-stylesheet type=”text/css” href=”a.css”?>
-
标签:标签名称自定义
- 名称包含字母数字以及其他字符
- 名称不能以数字或者标点符号开始
- 名称不能以字母xml开始
- 名称不能包含空格
-
属性
id属性值唯一
-
文本
CDATA:在该区域中的数据会被原样展示
<![CDATA[]]>
-
-
约束文档
能读懂就行
分类:
- DTD:简单的约束技术
- 引入dtd文档到xml文档中 <!DOCTYPE xx SYSTEM “xx.dtd”>
- 内部dtd:将约束规则约束在xml文档中
- 外部dtd:将约束规则定义在外部的dtd文件中
- 本地: <!DOCTYPE 根标签名 SYSTEM “xx.dtd”>
- 网络: <!DOCTYPE 根标签名 PUBLIC “dtd文件名字” “xx.dtd”>
- 引入dtd文档到xml文档中 <!DOCTYPE xx SYSTEM “xx.dtd”>
- Schema:复杂的约束文档
- 填写xml根元素
- 引入xsi前缀
- 引入xsd文件命名空间
- 为每个xsd约束声明一个前缀
- DTD:简单的约束技术
-
解析:操作xml文档,将文档中的数据读取到内存中
-
解析xml的方式
-
DOM:将标记语言文档一次性加载进内存,在内存中形成dom树
优点:操作方便,可以对文档进行CRUD操作
缺点:占内存
-
SAX:逐行读取,在内存中一直只有一行,基于事件的驱动来逐行获取
优点:基本不占内存
缺点:只能读取
-
-
xml常见的解析器
- JAXP:支持dom和sax思想
- DOM4J:
- Jsoup:HTML解析器,可直接解析某个url,html内容。可通过DOM,CSS以及jquery来取出和操作数据
- PULL:Android操作系统内置解析器,sax方式
Jsoup:
-
快速入门
步骤:
- 导入jar包
- 获取document对象
- 获取对应element对象
- 获取数据
-
对象使用
-
Jsoup:工具类,可以解析html或xml文档,返回Document
- parse:解析html或xml文档,返回document
- parse(File in,String charsetName):解析xml或html文件的
- parse(String html):解析xml或html字符串的
- parse(URL url,int timeoutMillis):通过网络路径获取指定的tml或xml的文档
- parse:解析html或xml文档,返回document
-
Document:文档对象,代表内存dom树
- 获取element对象
- getElementByTag(String tagName):根据标签名获取元素对象集合
- getElementByAttribute(String key):根据属性名称获取元素对象集合
- getElementByAttributeValue(String key,String value):根据对应的属性名和属性值获取元素对象
- getElementById(String id):根据id属性值获取唯一的element对象
- 获取element对象
-
Elements:元素Element对象集合,可以当作ArrayList
来使用 -
Element:元素对象
-
获取子元素对象
- getElementByTag(String tagName):根据标签名获取元素对象集合
- getElementByAttribute(String key):根据属性名称获取元素对象集合
- getElementByAttributeValue(String key,String value):根据对应的属性名和属性值获取元素对象
- getElementById(String id):根据id属性值获取唯一的element对象
-
获取属性值
String attr(String Key):根据属性值名称获取属性值
-
获取文本对象
String text():根据文本内容 只获取文本内容
String html():获取html内容 获取标签体所有内容,包括标签
-
-
Node:节点对象
Document和Element的父类
-
-
快捷查询方式
-
selector:选择器
使用方法:Elements select(String cssQuery)
语法:参考selector类定义方法
-
XPath:xml的路径语言,在xml文档中查找信息
使用jsoup的xpath需要额外导入jar包
-
-
Tomcat
网络通信:ip,端口,传输协议(TCP,UDP)
服务器:安装了服务器软件的计算机
服务器软件:接受用户的请求,处理请求,做出相应
web服务器软件:接受用户请求,处理请求,做出回应
- 在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目
- web容器
常见的java相关的web服务器软件:
- webLogic:大型javaEE服务器,支持所有的JavaEE(java语言在企业级发开使用的技术规范总和)规范
- webSphere:大型javaEE服务器,支持所有的JavaEE
- JBOSS:大型javaEE服务器,支持所有的JavaEE
- Tomcat:中小型的javaEE服务器
Tomcat
-
安装(安装路径不要有中文空格)
-
运行:bin/startup.bat
乱码:在conf文件的logging中将所有的UTF-8改为GBK
本电脑tomcat端口:8083
访问自己:127.0.0.1:8083(localhost:8083)
访问别人:别人的ip:别人tomcat端口号(默认8080)
可能遇到问题
- 闪退,环境变量配置错误
- 启动报错:端口号被占用。1.可以杀死占用该端口的进程2.修改自身端口号(在conf/server.xml 大概七十行位置)
-
配置
-
部署项目的方式
-
直接将项目放到webapps目录下即可
浏览器中搜项目访问路径
-
配置conf/server.xml文件(不安全)
在
标签体中配置 -
在conf\Catalina\localhost创建任意名称的xml文件。
在文件中编写
虚拟目录:xml文件的名称
-
-
目录结构
- 静态项目
-
动态项目
- 项目的根目录–WEB-INF目录–web.xml(web项目核心配置),classes目录(字节码文件),lib目录(jar包)
-
-
tomcat集成到IDEA中,并创建JavaEE项目,部署项目
Servlet
概念:运行在服务器端的小程序,定义java类被浏览器访问的规则
自定义一个类,实现servlet接口,复写方法
快速入门
-
创建javaee项目
-
定义一个类,实现servlet接口
1
public class HelloServlet extends HttpServlet
-
实现接口中的抽象方法
-
配置servlet
在web.xml中配置
1 2 3 4 5 6 7 8 9 10
<!--配置servlet--> <servlet> <servlet-name>demo1</servlet-name> <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class> </servlet> <servlet-mapping> <servlet-name>demo1</servlet-name> <url-pattern>/demo1</url-pattern> </servlet-mapping>
执行原理
- 当服务器接受客户浏览器的请求后,会解析请求URL路径,获取访问的Servelt的资源路径
- 查找web.xml文件,是否有对应的
标签体内容 - 如果有,则找到对应的
全类名 - tomcat会将字节码文件加载进内存,并创建其对象
- 调用类中方法
Servlet方法:
-
被创建:执行init,执行一次 说明对象只有一个,说明servelt是单例的(多线程访问时可能存在访问问题)
默认情况下,第一次被访问的时候创建,可以在web.xml中配置指定servelt创建时间
1 2 3 4
1.第一次访问时创建 <load-on-startup></load-on-startup>值为负 2.在服务器启动时创建 <load-on-startup></load-on-startup>值为非负数
-
提供服务:执行service方法,可执行多次
-
被销毁:执行destory方法,执行一次
在servlet销毁前执行,用于释放资源
可以不需要配置xml文件(常用)
- 创建JavaEE项目,选择Servlet高版本
- 定义一个类,实现Servelt接口
- 复写方法
- 在类上使用@WebServlet注解,进行配置@WebServlet(“资源路径”)
Servlet——–>GenericServlet———->HttpServlet
GenericServlet:将servlet接口中其他方法做了默认空实现,只将service方法作为抽象
将来定义servlet类时,可以继承GenericServlet,实现service方法即可
HttpServlet:对http协议的封装,简化操作
- 定义类继承HttpServlet
- 复写doGet/doPost
Servlet相关配置
- 一个servlet可以定义多个路径
- 路径定义规则:
- /xxx
- /xxx/xxx:多层目录结构
- /*:优先级低,找不到其他的才到这
- xx.do :前面就不用加/
HTTP
Hyper Text Transfer Protocol 超文本传输协议
定义了客户端和服务器端通信时,发送数据的格式
特点:
- 基于TCP/IP的高级协议
- 默认端口号为80
- 基于请求响应模型(请求和相应是一一对应)
- 无状态的:每次请求之间相互独立,不能交互数据
请求消息数据格式
-
请求行
请求方式 请求url 请求协议/版本
GET/POST login.html HTTP/1.1
请求方式:
GET:
- 请求参数在url后面
- url限制长度
- 不安全
POST:
- 请求参数在请求体中
- 不限制长度
- 相对安全
-
请求头(告诉服务器,浏览器的信息)
请求头名称:请求头值
常见请求头:
-
User-Agent:浏览器告诉服务器,该浏览器的版本信息(可以由此解决浏览器兼容问题)
-
Referer:http://localhost/login.html
告诉服务器,从哪里来
作用:
- 防盗链(判断是否是自己同意的网站来进行访问)
- 统计工作
-
-
请求空行
空行
-
请求体
封装post请求消息时的请求参数
Request:
-
Request对象和Response对象原理
- request和response对象由服务器创建
- resquest用于获取请求信息,response用于响应信息
-
request对象继承体系结构
-
request功能:
-
获取请求消息数据
-
获取请求行数据
-
获取请求方式
String getMethod()
-
获取虚拟目录
String getContextPath()
-
获取servlet路径
String getServletPath()
-
获取请求参数
String getQueryString()
-
获取客户机ip地址
String getRemoteAddr()
-
获取URI
String getRequestURI()
URL:统一资源定位符
URI:统一资源表示符
-
-
获取请求头数据
String getHeader(String name):通过请求头获得该信息
1 2 3 4 5 6
Enumeration<String>headerNames=request.getHeaderNames();//获取头对象 while(headerNames.hasMoreElements()){//判断是否有头 String name=headerNames.nextElement();//获取请求头 String value=request.getHeader(name); System.out.println(name+"-----"+value); }
-
获取请求体数据
只有post方式才有请求体,封装了post请求参数
步骤:
-
获取流对象
BufferedReader getReader():获取字符输入流,只操作字符数据
ServletInputStream getInputStream():获取字节输入流,可以操作所有数据
-
再从流对象中获取数据
line=br.readLine()
-
-
-
其他功能
-
获取请求参数 无论get还是post方式都可以利用下列方法获取参数,因此以后只用写一个
-
String getParameter(String name):根据参数名称获取参数值
-
String []getParameter(String name):根据参数名称获取参数值 数组
-
Enumeration
getParameterNames() :获取所有请求参数名称 该对象有有个方法要记住
- hasMoreElements():判断还有无参数
- nextElement():输出参数名称
通过获取名称,再调用方法一获取对应的参数
-
Map<String,String[]>getParameterMap():获取所有参数
中文乱码问题:get方式不会,post会乱码(设置流的字符集)
-
-
请求转发:一种服务器内部资源跳转的方式
-
步骤:
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 通过RequestDispatcher对象进行转发:forward(ServletRequest request,ServletResponse response)
1
request.getRequestDispatcher("/RequestDemo6").forward(request,response);
特点:
- 不能访问服务器外的资源
- 浏览器地址栏路径不发生变化
- 转发就是一次请求
-
-
共享数据
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
- setAttribute
- getAttribute
- removeAttribute
-
获取ServletContext
getServletContext()
-
登录界面(项目login)
步骤
-
在webapp/WEB-INF中创建lib文件夹并导入jar包
-
配置druid.properties文件,文件位置要放在resources文件夹下面
1 2 3 4 5 6 7
driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/login?serverTimezone=UTC username=root password=dycdyc initialSize=5 maxActive=10 maxWait=3000
-
在SQLyog中创建数据库,表
1 2 3 4 5 6 7 8 9 10
CREATE DATABASE login; USE login; CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(20) NOT NULL, PASSWORD INT ); SELECT * FROM USER; INSERT INTO USER VALUES(NULL,'zhangsan',123); INSERT INTO USER VALUES(NULL,'lisi',123);
-
创建文件夹domain,创建用户类user,设置成员变量得setter,getter方法和tostring方法
-
创建util文件夹,编写JDBCutils类用户连接数据库
-
创建dao文件夹,编写UserDao类用于操作数据库,在里面编写sql语句,返回查询结构
-
编写servlet文件夹,编写loginservlet,通过servlet来获取数据,封装成user对象,然后调用userdao中的方法进行判断
-
如果正确就利用request中请求转发的方式到正确的界面,反之转发到错误的界面
-
在webapp文件夹中创建login.html作为登录界面,并通过action设置参数传输到loginservlet中
BeanUtils工具类,简化user对象的封装
1
BeanUtils.populate(封装对象, 要封装的参数);
-
响应消息数据格式
数据格式
-
响应行
- 组成:协议/版本 响应状态码 状态码描述
- 响应状态码:服务器告诉客户端浏览器本次请求和响应的状态
- 状态码都是三位数
- 分类
- 1xx:服务器接受客户端消息,没有接受完成,等待一段时候后,发送看是否还有
- 2xx:成功
- 3xx:重定向
- 4xx:客户端错误 代表请求路径没有对应的资源
- 5xx:服务器端错误
-
响应头
常见响应头
-
Content-Type:服务器告诉客户端响应体数据格式以及编码格式
-
Content-Length:
-
Content-disposition:服务器告诉客户端以什么样的格式打开响应体数据
in-line:默认,在当前页面打开
attachment:以附件形式打开响应服务
-
-
响应空行
-
响应体
Response对象
功能:设置响应消息
-
设置响应行
- 格式:HTTP/1.1 200 ok
- 设置状态码:setStatus(int sc)
-
设置响应头
setHeader(String name,String value)
-
设置响应体
使用步骤:
- 获取输出流
- 字符输出流 getWriter()
- 字节输出流 getOutputStream()
- 使用输出流,将数据输出到客户端浏览器
- 获取输出流
案例
-
完成重定向
- 告诉浏览器重定向:状态码302
- 告诉浏览器B资源的路径:响应头Location:B的路径
1 2
//更简单的方法 response.sendRedirect("/response_war_exploded/ResponseDemo2");
特点(redirect):
- 地址栏路径发生变化
- 可以访问其他站点资源
- 两次请求,不能用request对象共享数据了
转发(forward):
- 地址栏路径发生不会变化
- 不可以访问其他站点资源
- 一次请求,可以用request对象共享数据了
路径:
-
相对路径:不可确定唯一资源,以.开头
-
绝对路径:可以确定唯一资源,以/开头
判断定义得路径给谁用的
- 给客户端浏览器用则需要加虚拟目录(页面链接,重定向)
- 给服务器端用不需要加虚拟目录(转发)
由于路径可能会发生变化,改虚拟目录很麻烦,所以可以动态获取虚拟目录
String contextPath=request.getContextPath();
response.sendRedirect(contextPath+”/ResponseDemo2”);
-
服务器输出字符数据到浏览器
步骤:
- 获取字符输出流
- 输出数据
1 2 3 4 5 6 7 8
//获取流对象之前,设置流的默认编码 //response.setHeader("content-type","text/html;charset=utf-8"); response.setContentType("text/html;charset=utf-8"); //1.获取字符输出流 PrintWriter printStream=response.getWriter(); //2.输出数据 printStream.write("hello");
-
服务器输出字节数据到浏览器
- 获取字节输出流
- 输出数据
1 2 3 4 5
response.setContentType("text/html;charset=utf-8"); //1.获取字节输出流 ServletOutputStream servletOutputStream=response.getOutputStream(); //2.输出数据 servletOutputStream.write("hello".getBytes());
-
验证码
- 本质:图片
- 目的:防止恶意注册
详情见response/checknode
ServletContext对象
-
代表整个web应用,可以和程序容器来通信
-
获取(两种方式是一样的)
-
通过request对象获取
1
ServletContext servletContext=request.getServletContext();
-
通过HttpServlet对象获取
1
ServletContext servletContext1=this.getServletContext();
-
-
功能:
-
获取MIME类型
在互联网通信过程的定义的一种文件数据类型
获取:String getMimeType(String file)
-
域对象,共享数据
setAttribute()
getAttribute()
所有用户都共享了,所有用户都可以使用该数据
-
获取文件真实路径
- getRealPath(String Path)
-
案例:
文件下载需求
- 页面显示超链接
- 点击超链接后弹出下载提示框
- 完成图片下载
分析:
-
任何资源都必须弹出下载提示框
-
使用响应头设置资源打开方式:
content-disposition:attachment;filename=xxx
步骤:
- 定义页面,编辑超链接href属性,指向servlet,传递资源文件名称
- 定义servlet
- 获取文件名称
- 使用字节输入流加载文件进内存
- 指定response响应头:content-disposition:attachment;filename=xxx
- 将数据写到response输出流
会话技术
一次会话中包含多次请求和响应
功能:在一次会话的范围内多次请求间,共享数据
方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
Cookie
客户端会话技术:将数据保存在客户端
使用:
-
创建cookie对象,指定数据
new Cookie(String name,String value)
-
发送cookie对象
response.addCookie(Cookie cookie)
-
获取cookie对象,拿到数据
Cookie[] request.getCookies()
实现原理:
特点
-
一次可以发送多个cookie,创建多个cookie对象,使用response调用多次addCookie方法发送cookie即可
-
默认情况下,当浏览器关闭,cookie结束
持久化存储:setMaxAge(int seconds)
正数:将cookie数据写到硬盘的文件中,持久化存储。cookie存活时间
负数:默认值
零:删除cookie信息
-
在tomcat 8之前 cookie不能直接存储中文数据,在tomcat 8之后,cookie支持中文数据
-
在一个tomcat部署多个项目,多个项目不能共享cookie
setPath(String path):设置cookie获取范围,默认情况下是当前的虚拟目录
如果要共享,则cookie.setPath(“/”)
-
不同的tomcat服务器也可以共享数据
setDomain(String Path):如果设置一级域名相同,多个服务器之间也可以共享
-
本身特点
- 存储数据在客户端浏览器————不安全
- 浏览器对于单个cookie大小(4k)有限制,一般数量限制20个————–少量
- 一般用于存储少量不太重要的数据,在不登陆情况下对客户端身份识别
案例:记住上一次访问时间(ServletCookieExample)
在服务器中servlet判断是否有一个名为lastTime的cookie
1.有:不是第一次访问
2.没有:是第一次访问
Session
服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中
HttpSession对象
-
获取HttpSession对象
1
HttpSession httpSession=request.getSession();
-
使用HttpSession对象
1 2 3 4
//存储数据 httpSession.setAttribute("msg","hello"); //获取数据 Object msg=httpSession.getAttribute("msg");
原理:
服务器通过创建一个cookie将session id传送给浏览器,然后浏览器下次要使用服务器的时候,将该session id放到请求信息中,用于服务器辨认session
细节:
-
当浏览器关闭后,两个session不是同一个
1 2 3 4 5
//也可以让两次session一样 //根据session原理,可以设置一个cookie将sessionid存储在服务器中,设置cookie长期有效,则sessionid长期有效 Cookie cookie=new Cookie("sessionid",httpSession.getId()); cookie.setMaxAge(60*60); response.addCookie(cookie);
-
客户端不关闭,服务器关闭,session不是同一个
session的钝化:
在服务器正常关闭前,将session对象系列化硬盘上
session的活化
在服务器启动后,将session文件转化为内存中的session对象
-
销毁时间
- 服务器关闭
- session对象调用invalidate()
- 默认失效时间 30min(可以在xml中更改)
特点:
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型,任意大小的数据
session vs cookie
- session在服务器端,cookie客户端
- session无大小限制,cookie有
- session安全,cookie相对不安全
案例
- 访问带有验证码的登录界面login.html
- 用户输入用户名,密码以及验证码
- 如果输入错误,跳转页面登录页面,提示错误
- 如果验证码错误,跳转登录页面,提示验证码错误
- 如果全部正确,则跳转success.jsp页面,显示正确
JSP
概念:java sever pages:
- 一个特殊的页面,既可以直接定义html的标签,又可以定义java代码
- 用于简化书写
本质上是一个servelt
JSP指令:
-
作用:用于配置JSP页面,导入资源文件
-
格式:
<%@ 指令名称 属性名 属性名%>
-
分类
-
page 配置jsp页面
1
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
-
taglib 导入资源
-
include 页面包含的,导入页面资源文件,导入其他jsp等
-
注释
-
html注释:
-
jsp注释:
注释脚本内容或者代码片段需要用jsp注释 <%– –%> 注释的内容都不会发送到浏览器中
JSP脚本:JSP定义java代码的方式
- <% 代码 %>:定义的java代码在service中。service中可以定义什么,该脚本就可以定义什么
- <%! 代码 %>:定义的java代码在jsp转换后的java类成员变量的位置
- <%= 代码%>:定义的java代码会直接输出到页面上
JSP内置对象:
在jsp页面中不需要获取和创建,可以直接使用的对象
jsp一共有9个内置对象
request 一次请求访问多个资源
response 响应对象
out:可以将数据输出到页面上
- response.getwriter() vs out.print()
response永远会在out前输出
pageContext 当前页面共享数据 还可以获取其他八个对象
session 一次会话多个请求
application 所有用户间共享数据
page 当前页面对象 this
config servlet配置对象
exception 异常对象
EL表达式
作用:替换和简化jsp页面java代码的编写
MVC
model :完成具体的业务操作,例如:查询数据库,封装对象
view:展示数据
controller:获取用户输入,调用模型,将数据给视图展示
优点:耦合性低,方便维护,利于分工,重用性高
缺点:使得项目架构变得复杂
三层架构
- 界面层:用户看得到的界面,用户可以通过界面上的组件和服务器进行交互
- 业务逻辑层:处理业务逻辑的
- 数据访问层:操作数据存储文件
#