JavaWeb学习

一、数据库

MySQL数据库管理系统

关系型数据库:多张能互相连接的二维表(正常的行列表格)组成的数据库

SQL通用语法

1.SQL可以单行或多行书写,以分号结尾

2.MySQL数据库的SQL语句不区分大小写,但关键字建议使用大写

3.注释  单行注释:1.-- 注释内容 2. #注释内容                      多行注释:/* 注释 */

SQL分类

 DDL操作数据库

 DDL操作表

查询(Retrieve)

查询当前数据库下所有表名称 
show tables;
查询表结构
desc 表名称;

创建(Create)

create table 表名(
字段名1 数据类型1,
字段名2 数据类型2,
...
字段名n 数据类型n

);

注意:最后一行末尾,不能加逗号

数据类型

1.age int

2.score double(总长度,小数点后保留的位数)

3.birthday date

4.name char(最大存储数)     如果最大储存数为10,我输入张三,后面会自动补8个空格,占满10个字符空间   存储性能高,浪费空间(空间换时间)

5.name varchar(最大存储数)    只会占需要用到的存储空间(每次都会计算具体要用多少字符空间)  存储性能低,节约空间(时间换空间)

删除(Delete)

删除表
drop table 表名;
删除表时判断表是否存在
drop table if exists 表名;

修改(Update)

DML

添加(insert)

修改(update)

1.修改表数据
update 表名 set 列名1=值1,列名2=值2,...[where 条件];

注意:修改语句中如果不加where条件,则将所有数据都修改

删除(delete)

删除数据
delete from 表名[where 条件];

注意:修改语句中如果不加where条件,则将所有数据都删除

-- 查询所有数据
SELECT
	* 
FROM
	tb_user;-- 给指定列添加数据INSERT INTO 表名(列名1,列名2,...) VALUES(值1,值2,...);
INSERT INTO tb_user ( id, username )
VALUES
	( 1, '张三' );
INSERT INTO tb_user ( id, username, `password` )
VALUES
	( 2, '李四', 113448 );-- 给所有列添加数据,列名的列表可以省略的,但尽量不要去省略
INSERT INTO tb_user
VALUES
	( 3, '李四', 113448 );
	
	SELECT *from tb_user;
	-- 修改数据 update 表名 set 列名1=值1,列名2=值2,...[where 条件];
	update tb_user set `password`=10086 where username='李四';
	-- 删除 delete from 表名[where 条件];
	DELETE from tb_user where username='张三';

DQL查询数据

基础查询

条件查询

select 字段列表 from 表名 where 条件列表;

-- 删除stu表
DROP table if exists stu;
-- 创建stu表
CREATE TABLE stu(
id int,-- 编号
name varchar(20), -- 姓名
age int,--年龄
sex varchar(5),-- 性别
address varchar(100),-- 地址
math double(5,2),--数学成绩
english double(5,2),--英语成绩
hire_date date --入学时间
);

-- 添加数据
insert into stu(id,name,age,sex,address,math,english,hire_date)
VALUES
(1,'马云',55,'男','杭州',66,78,'1995-09-01'),
(2,'马化腾',45,'女','深圳',98,87,'1988-09-01'),
(3,'马克思',55,'男','香港',56,77,'1999-09-02'),
(4,'留白',20,'女','湖南',76,65,'1997-09-05'),
(5,'留情',20,'男','湖南',86,NULL,'1998-09-01'),
(6,'刘德华',57,'男','香港',99,99,'1998-09-01'),
(7,'张学友',22,'女','香港',99,99,'1988-09-01'),
(8,'德玛西亚',18,'男','南京',56,65,'1994-09-02');

select * from stu;

-- 条件查询===================
-- 1.查询年龄大于20岁的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where age>20;

-- 2.查询年龄大于等于20岁的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where age>=20;


-- 3.查询年龄大于等于20岁并且年龄小于等于30岁的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where age>=20 and age<=30;select id,name,age,sex,address,math,english,hire_date from stu where age>=20 && age<=30;select id,name,age,sex,address,math,english,hire_date from stu where  age between 20 and 30;

-- 4.查询入学日期在'1998-09-01'到'1999-09-01'之间的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where hire_date between '1998-09-01' and '1999-09-01';

-- 5.查询年龄等于18岁的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where age=18;

-- 6.查询年龄不等于18岁的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where age!=18;
select id,name,age,sex,address,math,english,hire_date from stu where age <> 18;

-- 7.查询年龄等于18岁或者年龄等于20岁或者年龄等于22岁的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where age=18 or age=20 or age=22;
select id,name,age,sex,address,math,english,hire_date from stu where age in(18,20,22);

-- 8.查询英语成绩为null的学员信息
-- 注意:null值的比较不饿使用 = != ,需要使用 is  is not
select id,name,age,sex,address,math,english,hire_date from stu where english is null;
select id,name,age,sex,address,math,english,hire_date from stu where english is not null;



-- 模糊查询 like =============
/*
通配符:
1. _ :代表单个任意字符
2. % :代表任意个数字符
*/
-- 1.查询性'马'的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where name like '马%';
-- 2.查询第二个字是'化'的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where name like '_化%';
-- 3.查询名字中包含'德'的学员信息
select id,name,age,sex,address,math,english,hire_date from stu where name like'%德%';

排序查询

select 字段列表 from 表名 order by 排序字段名1[排序方式1],排序字段名2[排序方式2]...;

排序方式:

ASC:升序排序(默认值)

DESC:降序排列 

注意:如果有多个排序条件,当前边的条件值一样时,才会根据第二个条件进行排序

-- 1.查询学生信息,按照年龄升序排序
select id,name,age,sex,address,math,english,hire_date from stu order by age asc;

-- 2.查询学生信息,按照数学成绩降序排列
select id,name,age,sex,address,math,english,hire_date from stu order by math DESC;

-- 3.查询学生信息,按照数学成绩降序排列,如果数学成绩一样,再按照英语成绩升序排列
select id,name,age,sex,address,math,english,hire_date from stu order by math DESC,english ASC;

分组查询

聚合函数:将一列数据作为一个整体,进行纵向计算

count(列名)    统计数量

max(列名)  最大值

min(列名)    最小值

sum(列名)   求和

age(列名)     平均值

select 聚合函数名(列名) from 表;

注意:null值不参与所有聚合函数运算


-- 1.统计班级一共有多少个学生
select count(id) from stu;
-- 2.查询数学成绩的最高分
select max(math) from stu;
-- 3.查询数学成绩的最低分
select min(math) from stu;
-- 4.查询数学成绩的总分
select sum(math) from stu;
-- 5.查询数学成绩的平均分
select avg(math) from stu;

分组查询

select 字段列表 from 表名 [where 分组前条件限定] group by 分组字段名 [having 分组后条件过滤];

注意:分组之后,查询的字段为聚合函数和分组字段,查询其他字段无任何意义

-- 1.查询男同学和女同学各自的数学平均分
select sex,avg(math)  from stu group by sex;
-- 2.查询男同学和女同学各自的数学平均分,以及各自人数
select sex,avg(math),count(id)  from stu group by sex;

-- 3.查询男同学和女同学各自的数学平均分,以及各自人数,要求:分数低于70分的不参与分组
select sex,avg(math),count(id)  from stu where math>70 group by sex;

-- 4.查询男同学和女同学各自的数学平均分,以及各自人数,要求:分数低于70分的不参与分组,分组后人数大于2
select sex,avg(math),count(id)  from stu where math>70 group by sex having count(id)>2;

where和having区别:

执行时机不一样:where是分组之前进行限定,不满足where条件,则不参与分组,而having是分组后对结果进行过滤

可判断的条件不一样:where不能对聚合函数进行判断,having可以

执行顺序:where>聚合函数>having

分页查询

select 字段列表 from 表名 limit 起始索引,查询条目数;

起始索引:从哪开始查    从0开始

select * from stu;
-- 1.从0开始查询,查询3条数据
select * from stu limit 0,3;
-- 2.每页显示3条数据,查询第1页数据
select * from stu limit 0,3;
-- 3.每页显示3条数据,查询第2页数据
select * from stu limit 3,3;
-- 4.每页显示3条数据,查询3页数据
select * from stu limit 6,3;

计算公式:起始索引=(当前页码-1)*每页显示的条数

约束

约束是作用于表中列上的规则,用于限制加入表中的数据

 注意:MySQL里面没有检查约束

drop table if exists emp;

-- 员工表
create table emp(
id int primary key auto_increment,-- 员工id,主键且自增长
ename varchar(50) not null unique,-- 员工姓名,非空且唯一
joindate date not null,-- 入职日期,非空
salary double(7,2) not null,-- 工资,非空
bonus double(7,2) default 0 -- 奖金,如果没有奖金默认为0 

);

insert into emp(id,ename,joindate,salary,bonus) values(1,'张三','1999-11-11',8000,5000);
-- 主键约束: 非空且唯一
-- 自动增长:auto_increment:当列是数组类型并且是唯一约束
insert into emp(ename,joindate,salary,bonus) values('张三2','1999-11-11',8000,5000);
insert into emp(id,ename,joindate,salary,bonus) values(null,'张三3','1999-11-11',8000,5000);


select * from emp;

外键约束

添加外键

[constraint][外键名称] foreign key(外键列名) references 主表(主表列名)

drop table if exists dept;
drop table if exists emp;
-- 部门表
CREATE TABLE dept(
id int PRIMARY KEY auto_increment,
dep_name varchar(20),
addr varchar(20)
);
-- 员工表
CREATE TABLE emp(
id int PRIMARY KEY auto_increment,
name VARCHAR(20),
age int,
dep_id int,

-- 添加外键 dep_id,关联dept表的id 主键
CONSTRAINT fk_emp_dept FOREIGN KEY(dep_id) REFERENCES dept(id)
);
-- 添加两个部门
INSERT INTO dept(dep_name,addr) VALUES('研发部','广州'),('销售部','深圳');

-- 添加员工,dep_id 表示员工所在的部门
INSERT INTO emp(name,age,dep_id) VALUES
('张三',20,1),
('李四',20,1),
('王五',20,1),
('赵六',20,2),
('孙七',20,2),
('周八',18,2);
select * from emp;

-- 删除外键
ALTER table emp drop foreign key fk_emp_dept;

-- 建完表后,添加外键
alter table emp add CONSTRAINT fk_emp_dept foreign key(dep_id) REFERENCES dept(id);

数据库设计

软件研发步骤

多表关系

一对多:部门表和员工表 

             在多的一方建议外键,指向一的一方主键

多对多:商品和订单

            建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

/*
多对多:
*如:订单和商品
*一个商品对应多个订单,一个订单包含多个商品

实现方式:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

*/
-- 删除表
drop table if exists tb_order_goods;
drop table if exists tb_order;
drop table if exists tb_goods;

-- 订单表
create table tb_order(
id int primary key auto_increment,
payment double(10,2),
payment_type tinyint,
status tinyint
);

-- 商品表
create table tb_goods(
id int primary key auto_increment,
title varchar(100),
price double(10,2)
);

-- 订单商品中间表
create table tb_order_goods(
id int primary key auto_increment,
order_id int,
goods_id int,
count int
);

-- 建完表后,添加外键
alter table tb_order_goods add constraint fk_order_id foreign key (order_id) references tb_order(id);
alter table tb_order_goods add constraint fk_order_id foreign key(order_id) references tb_goods(id);

一对一:用户  用户详情

一对一关系多用于表拆分,将一个实体中经常使用的字段放一张表,不经常使用的字段放另一张表,用于提升查询性能

实现方式:在任意一方加入外键,关联另一方外键,并且设置外键为唯一(unique)

多表查询

-- 多表查询

select * from emp,dept;

-- 笛卡尔积:有A,B两个集合,取A,B所有的组合情况   A有4个,B有8个,总共就有32种组合

-- 消除无效数据

-- 查询emp和dept的数据,emp.dep_id=dept.did

select * from emp,dept where emp.dep_id=dept.did;

 内连接:

-- 隐式内连接
selevt * from emp,dept where emp.dep_id=dept.did;

-- 查询emp的name,gender,dept表的dname
select emp.name,emp.gender,dept.dname from emp,dept where emp.dep_id=dept.did;

-- 给表起别名    as可以省略
select t1.name,t1.gender,t2.dname from emp as t1,dept as  t2 where t1.dep_id=t2.did;

-- 显示内连接    inner可省略

select * from emp inner join dept on emp.dep_id=dept.did;

外连接:

-- 左外连接
select * fron emp left [outer] join dept on empldep_id=dept.did;

-- 右外连接
select * fron emp right [outer] join dept on empldep_id=dept.did;

子查询:查询中嵌套查询,称嵌套查询为子查询

 单行单列

-- 1.查询猪八戒的工资
select salary from emp where name="猪八戒";

-- 2.查询工资高于猪八戒的员工信息
select * from emp where salary>3600;

select * from emp where salary>(select salary from emp where name="猪八戒");

多行单列

-- 查询“财务部”和“市场部”所有员工的信息
select did from dept where dname="财务部" or dname="市场部";
select * from emp where dep_id in (select did from dept where dname="财务部" of dname="市场部");

多行多列

查询入职日期是2011-11-11之后的员工信息和部门信息
查询入职日期是2011-11-11之后的员工信息
select * from emp where join_date>'2011-11-11';
select * from (select * from emp where join_date>'2011-11-11') as t1 ,dept where t1.dep_id=dept.did;

count(*)统计数量

事务

事务包含了一组数据库操作命令,这一组命令要么同时成功,要么同时失败

-- 开启事务
start transaction; 或者 begin;
-- 提交事务
 commit;
-- 回滚事务
rollback;

事务四大特征

drop table if exists account1;

-- 创建账户表
create table account1(
id int primary key auto_increment,
name varchar (10),
money double(10,2)
);

-- 添加数据
insert into account1(name,money) values('张三',1000),('李四',1000);

select * from account1;

-- 转账操作
-- 开启事务
begin;
-- 本窗口打开还会是1000 500,但用别的窗口打开仍然是1000 1000,临时的

-- 1.查询李四的余额

-- 2.李四金额-500
-- update 表名 set 字段=新值… where 条件
update account1 set money =money-500 where name='李四';
出错了...

-- 3.张三金额+500
update account1 set money =money+500 where name='张三';

-- 提交事务 将事务实体化,别的窗口打开也可以看到变化
commit;   
-- 回滚事务  回滚到开启事务之前的状态
rollback;

-- 1.查询事务的默认提交方式
select @@autocommit;
-- 结果为1为默认提交,0则需要commit手动提交,MySQ为自动提交

 二、JDBC

简介

JDBC就是使用Java语言操作关系型数据库的一套API

package com.itheima.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

/*
*JDBC快速入门
 */
public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接
        String url="jdbc:mysql://127.0.0.1:3306/db1";
        String username="root";
        String password="1234";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3.定义sql
        String sql="update account set money=2000 where id=1";
        //4.获得执行sql对象 statement
        Statement stmt = conn.createStatement();
        //5.执行sql
        int count = stmt.executeUpdate(sql);//返回受影响的行数
        //6.处理结果
        System.out.println(count);
        //7.释放资源
        stmt.close();
        conn.close();
    }
}

API详解

DriverManager(驱动管理类)

作用:1.注册驱动(DriverManagerr类里有registerDriver)   可省略

2.获取数据库连接getConnection(url,user,password)

url:连接路径     jdbc:mysql://ip地址(或域名):端口号/数据库名称?参数键值对1&参数键值对2

user:用户名

password:密码

public class JDBCDemo02_DriverManager {
    /*
    * JDBC API 详解:DriverManager
     */
    public static void main(String[] args) throws Exception{
        //2.获得连接:如果连接的是本机mysql并且端口是默认的3306 可以简化书写
        String url="jdbc:mysql:///db1?useSSl=false" ;//useSSl=false禁用安全连接,让系统不会爆红色提醒,减少程序占用内存空间
       String username="root";
       String password="1234";
        Connection conn = DriverManager.getConnection(url, username, password);
    }
}

Connection(数据库连接对象)

作用:

1.获取执行SQL对象

Statement createStatement()

2.管理事务

开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务;false为手动提交事务,极为开启事务

提交事务:commit()

回滚事务:rollback()

package com.itheima.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/*
*JDBC API详解:Connection
 */
public class JDBCDemo3_Connection {
    public static void main(String[] args) throws Exception {
       // 2.获取连接
        String url="jdbc:mysql:///db1?useSSL=false";
        String username="root";
        String password="1234";
        Connection conn = DriverManager.getConnection(url,username,password);
    //3.定义SQL
        String sql1="update account set money =3000 where id=1";
        String sql2="update account set money =3000 where id=2";
        //4.获取执行sql的对象 statement
        Statement stmt = conn.createStatement();
        //开启事务

        try {
            //开启事务
            conn.setAutoCommit(false);
            //5.执行sql
            int count1 = stmt.executeUpdate(sql1);//受影响的行数
            //6.处理结果
            System.out.println(count1);
            int count2 = stmt.executeUpdate(sql2);
            System.out.println(count2);

            //提交事务
           conn.commit();
        } catch (Exception e) {
            //回滚事务
            conn.rollback();

            e.printStackTrace();
        }

        //7.释放资源
        stmt.close();
        conn.close();

    }
}

Statement(执行类)

作用:1.执行SQL语句

int executeUpdate(sql):执行DML、DDL语句

返回值:(1)DML语句影响行数(2)DDL执行成功后也可能返回0

2.Result executeQuery(sql):执行DQL语句

返回值:ResultSet结果焦对象

package com.itheima.jdbc;

import org.testng.annotations.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

/*
*JDBC API 详解:Statement
 */
public class JDBCDemo4_Statement {
    @Test //测试类,要给这个类单独导入一个包alt+回车
    public void testDML() throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接
        String url="jdbc:mysql://127.0.0.1:3306/db1?useSSL=false";
        String username="root";
        String password="1234";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3.定义sql
        String sql="update account set money=2000 where id=5";
        //4.获得执行sql对象 statement
        Statement stmt = conn.createStatement();
        //5.执行sql
        int count = stmt.executeUpdate(sql);//返回受影响的行数
        //6.处理结果
        //System.out.println(count);
        if (count>0) {
            System.out.println("修改成功");
        }else
        {
            System.out.println("修改失败");
        }
        //7.释放资源
        stmt.close();
        conn.close();
    }

}

ResultSet(结果集对象)

作用:1.封装DQL查询语句的结果

ResultSet stmt.executeQuery(sql) 执行DQL语句,返回ResultSet对象

获取查询结果

boolean next():(1)将光标从当前位置向前移动一行(2)判断当前行是否为有效行(是否有数据)

getxxx(参数):获取数据

xxx:数据类型  如:int getint(参数)   ; String getString(参数)

package com.itheima.jdbc;

import org.testng.annotations.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/*
*JDBC API 详解:Result
 */
public class JDBCDemo05_ResultSet {
    /*
    *执行DQL查询语句
     */
    @Test
    public void testResultSet() throws Exception{
         //2.获得连接
        String url="jdbc:mysql:///db1?useSSL=false";
        String username="root";
        String password="1234";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3.定义sql
        String sql="select * from account";
        
        //4.获取statement对象
        Statement stmt = conn.createStatement();
        
        //5.执行sql
        ResultSet rs = stmt.executeQuery(sql);

        //6.处理结果,遍历rs中所有的数据
        //6.1 光标向下移动一行,并且判断当前行是否有数据
        while (rs.next()){
            //6.2 获取数据
            int id=rs.getInt(1);//也可以getInt("id)
            String name=rs.getString(2);
            double money=rs.getDouble(3);

            System.out.println(id);
            System.out.println(name);
            System.out.println(money);

            System.out.println("-----------------");

        }

        //7.释放资源
        rs.close();
        stmt.close();
        conn.close();

    }
}

PreparedStatement

作用:1.预编译SQL语句并执行,预防SQL注入问题

2:对敏感字符进行转义  在单引号 前面放\

SQL注入:通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法

用户登录密码连接数据库

package com.itheima.jdbc;

import org.testng.annotations.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/*
*用户登录
 */
public class JDBCDemo06_UserLogin {
    @Test
    public void testResultSet() throws Exception{
        //2.获取连接
        String url="jdbc:mysql:///db1?useSSL=false";
        String username="root";
        String password ="1234";
        Connection conn = DriverManager.getConnection(url,username,password);

        //接收用户输入的用户名和密码
        String name="zhangsan";
        String pwd="1fsfsaf";

        String sql="select * from tb_user where username = '"+name+"' and password ='"+pwd+"'";

        //获取stmt对象
        Statement stmt = conn.createStatement();
        
        //执行sql
        ResultSet rs = stmt.executeQuery(sql);

        //判断是否成功
        if (rs.next()){
            System.out.println("登录成功");
        }else {
            System.out.println("登录失败");
        }
        //释放资源
        rs.close();
        stmt.close();
        conn.close();


    }
}

sql注入

String pwd="'or'1'='1 ";

利用字符串拼成恒等式

 解决sql注入问题  利用占位符替代字符

package com.itheima.jdbc;

import org.testng.annotations.Test;

import java.sql.*;

/*
*API详解:PrepareStatement
 */
public class JDBCDemo7_PrepareStatement {
@Test
    public void testPreparedStatement() throws Exception{
    //获取连接
    String url="jdbc:mysql:///db1?useSSL=false";
    String username="root";
    String password ="1234";
    Connection conn = DriverManager.getConnection(url, username, password);

    //接收用户输入用户名和密码
    String name="zhagnsan";
    String pwd="sadfsaf";

    //定义sql
    String sql="select * from tb_user where username =? and password =?";

    //获取pstmt对象
    PreparedStatement pstmt = conn.prepareStatement(sql);

    //设置?的值
    pstmt.setString(1,name);
    pstmt.setString(2,pwd);
    
    //执行sql
    ResultSet rs = pstmt.executeQuery();

    //判断登录是否成功
    if (rs.next())
    {
        System.out.println("登录成功");
    }else {
        System.out.println("登录失败");
    }
    //释放资源
    rs.close();
    pstmt.close();
    conn.close();
}
}

数据库连接池

一个容器,里面有提前开好的连接conn,有用户来就从容器里拿一个连接conn用,用完也不关闭,而是再次放入容器中

Druid(德鲁伊)连接池

标准接口:DataSource    

获得连接

Connection getConnection()

package druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;

/*
*Druid数据库连接池演示
 */
public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //1.导入jar包

        //2.定义配置文件

        //3.加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream(""));
        //4.获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //5.获得数据库连接Connection
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }
}

JDBC练习

环境准备和查询

package example;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.testng.annotations.Test;
import pojo.Brand;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Properties;

/*
*品牌数据的增删改查操作
 */
public class BrandTest {
    /*
    *查询所有
    * 1.SQL:select * from tb_brand;
    * 2.参数:不需要
    * 3.结果List<Brand>
     */
    @Test
    public void testSelectAll() throws Exception{
        //1.获取连接Connection
        //3.加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream(""));
        //4.获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //5.获取数据库连接Connection
        Connection conn = dataSource.getConnection();
        //2.定义SQL
        String sql="select * from tb_brand";
        //3.获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
        //4.设置参数
        //5.执行SQL
        ResultSet rs = pstmt.executeQuery();
        //6.处理结果 List<Brand> 封装Brand对象,装载List集合
        Brand brand=null;
        ArrayList<Brand> brands = new ArrayList<>();
        while (rs.next()){
            //获取数据
            int id = rs.getInt("id");
            String brandName = rs.getString("brand_name");
            String companyName = rs.getString("company_name");
            int ordered = rs.getInt("ordered");
            String description = rs.getString("description");
            int status = rs.getInt("status");

            //封装Brand对象
            brand = new Brand();
            brand.setId(id);
            brand.setBrandName(brandName);
            brand.setCompanyName(companyName);
            brand.setOrdered(ordered);
            brand.setDescription(description);
            brand.setStatus(status);

            //装载集合
            brands.add(brand);
        }
        System.out.println(brands);
        //7.释放资源
        rs.close();
        pstmt.close();
        conn.close();

    }
}

添加

insert into tb_brand(  ,  ,  ,  )values(?,?,?,?)
public class BrandTest {
    /*
    *添加
    * 1.SQL:insert into tb_brand(brand_name,company_name,ordered,description,status)values(?,?,?,?,?);
    * 2.参数:需要  除了id之外的所有参数信息
    * 3.结果:boolean
     */
    @Test
    public void testAdd() throws Exception{
        //接收页面提交的参数
        String brandName="香飘飘";
        String companyName="香飘飘";
        int ordered=1;
        String description="绕地球一圈";
        int status=1;


        //1.获取连接Connection
        //3.加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream(""));
        //4.获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //5.获取数据库连接Connection
        Connection conn = dataSource.getConnection();
        //2.定义SQL
        String sql="insert into tb_brand(brand_name,company_name,ordered,description,status)values(?,?,?,?,?);";
        //3.获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
        //4.设置参数
        pstmt.setString(1,brandName);
        pstmt.setString(2,companyName);
        pstmt.setInt(3,ordered);
        pstmt.setString(4,description);
        pstmt.setInt(5,status);
        //5.执行SQL
        int count = pstmt.executeUpdate();//影响的行数
        //6.处理结果
        System.out.println(count>0);

        //7.释放资源
        pstmt.close();
        conn.close();

    }
}

修改

update tb_brand
set brand_name=?,
     company_name=?,
ordered=?,
description=?,
status=?
where id=?
   
 public void testUpdate() throws Exception{
        //接收页面提交的参数
        String brandName="香飘飘";
        String companyName="香飘飘";
        int ordered=1000;     //排序越大排的越靠前,可以正常打广告用
        String description="绕地球三圈";
        int status=1;
        int id=4;


        //1.获取连接Connection
        //3.加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream(""));
        //4.获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //5.获取数据库连接Connection
        Connection conn = dataSource.getConnection();
        //2.定义SQL
        String sql="update tb_brand\n" +
                "      set brand_name=?,\n" +
                "     company_name=?,\n" +
                "     ordered=?,\n" +
                "     description=?,\n" +
                "     status=?\n" +
                "     where id=?";
        //3.获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
        //4.设置参数
        pstmt.setString(1,brandName);
        pstmt.setString(2,companyName);
        pstmt.setInt(3,ordered);
        pstmt.setString(4,description);
        pstmt.setInt(5,status);
        pstmt.setInt(6,id) ;
        //5.执行SQL
        int count = pstmt.executeUpdate();//影响的行数
        //6.处理结果
        System.out.println(count>0);

        //7.释放资源
        pstmt.close();
        conn.close();

    }
}

删除

delete from tb_brand where id=?

三、Maven

Maven基本使用

compile:编译

clean:清理

test:测试

package:打包

install:安装

Maven生命周期:一次构建过程经历了多少个事件

同一生命周期内,执行后边的命令,前边的所有命令会自动执行

Maven坐标

Maven中的坐标是资源的唯一标识

组成:

groupld:定义当前Maven项目隶属组织名称(通常是域名反写,com.itheima)

artifactld:定义当前Maven项目名称(通常是模块名称,例如order-service、goods-service)

version:定义当前项目版本号

使用坐标导入jar包

1.在pom.xml中编写<dependencies>标签

2.在<dependencies>标签中使用<dependency>引入坐标

3.定义坐标的groupld,artifactld,version

4.点击刷新按钮,使坐标生效(可在设置里选择自动刷新)

依赖管理

<scope><scope>   默认值:compile

 四、MyBatis

JavaEE三层架构:表现层、业务层、持久层

MyBatis使一款优秀的持久层框架,用于简化JDBC开发

查询user表中所有数据

执行sql

 List<User> users = sqlSession.selectList("test.selectAll");
        System.out.println(users);

Mapper代理开发

UseMapper useMapper = sqlSession.getMapper(UseMapper.class);
        List<User> users = useMapper.selectAll();

 五、html

1.基础标签

2.图片音频视频标签

3.超链接标签

<a>  定义超链接,用于链接到另一个资源

href:指定访问资源的URL

target:指定打开资源的方式(   _self:默认值,在当前页面打开     _blank:在空白页面打开)

4.列表标签

<ol>   有序列表   用1 2 3标识
<ul>   无序列表   用黑点标识
<li>   列表项

type:设置项目符号

5.表格标签

<table>  表格
<tr>     行
<td>     单元格
<th>     表头单元格(第一行  一般比较特殊)

table:定义表格(   border: 表格边框的宽度     width:表格的宽度   cellspacing:单元格之间的空白)

tr:定义行  (  align:表格行的内容对齐方式)

td:定义单元格   (rowspan:单元格可以横跨的行数     colspanl:单元格可以横跨的列数)

6.布局标签

<div>   定义html文档中一个区域部分,经常与CSS一起使用,用来布局网页
<sapn>  用于组合元素

7.表单标签

表单:在网页中主要负责数据采集功能,使用<form>标签

表单项(元素):不同类型的input元素,下拉列表、文本域等

<form>   表单
<input>  表单项,通过type属性控制输入形式
<label>  表单项定义标注
<select> 下拉列表
<option> 下拉列表的列表项
<textarea> 文本域
 
form:
      action:指定表单数据提交的URL
      * 表单项数据想要被提交,就必须指定其name属性
      method:指定表单提交的方式
      1.get:默认值
      *请求参数会拼接在URL后边
      *url的长度有限制 4kb
      2.post:
      *请求参数会在http请求协议的请求体中
      *请求参数无限制

六、css

 选择器

 七、JavaScript

基础语法

1.引入方式

1.内部脚本:将JS代码定义在HTML页面中(js代码必须位于<script></script>标签之间)

<script>
alert("hello,js");
</script>

在html文档中可以在任意地方放置任意数量<script>

一般将脚本置于<body>元素底部,可改善显示速度,因为脚本的执行会拖慢显示

2.书写语法

1.区分大小写  2.结尾分号可有可无

<script>
    window.alert("hello js");//写入警告框

    document.write("hell js2");//写入html页面

    console.log("hello js3");//写入浏览器的控制台


</script>

3.变量&数据类型

var关键字(相当于全局变量)

var test=20;
test="张三"

let关键字(只在let关键字所在代码块内有效,且不允许重复声明)

const关键字声明只读常量

使用typeof运算符可以获取数据类型

alert(typeof age)

4.运算符

==     1.判断类型是否一样,如果不一样,则进行强制类型转换   2.再去比较其值

===    1.判断类型是否一样,如果不一样,直接返回false   2.再去比较其值

类型转化

其他类型转为number:

1.string:按照字符串的字面值,转为数字,如果字面值不是数字,则转为NaN,一般使用parseInt

2.boolean:true转为1   false转为0

其他类型转为boolean:

1.numbei:0和NaN转为false,其他的数组转为true

2.string:空白字符串转为false,其他的字符串转为true

3.null:false

4.underfined:false

5.函数

function关键字

function add(a,b){
return a+b;
}
var add=fuction(a,b){
return a+b;
}

js中,函数调用可以传递任意个数参数

对象

Array

var 变量名=new Array(元素列表);
var 变量名=[元素列表]
var arr=new Array(1,2,3);
var arr=[1,2,3];

js中的数组相当于java中集合,变长变类型

String

var 变量名=s;

方法

charAt()   返回在指定位置的字符
indexOf()   字母第一次出现的位置
trim()  去除字符串前后两端的空白字符

自定义对象

var 对象名称={
属性名称1:属性值1,
属性名称2:属性值2,
函数名称:function(形参列表){}
};

BOM

浏览器对象模型

组成:Window:浏览器窗口对象

Navigator:浏览器对象

Screen:屏幕对象

History:历史记录对象

Loaction:地址栏对象 

Window

浏览器窗口对象

获取:直接使用window,其中window.可以省略

window.alert("abc");

属性:获取其它BOM对象

方法:

alert()    显示带有一段消息和一个确认按钮的警告框

confirm()   显示带有一段消息以及确认按钮和取消按钮的对话框(点击确定按钮会返回true,在取消返回false)

setInterval()   按照指定的周期(以毫秒计)来调用函数或者计算表达式  (循环执行)

setTimeout() 在指定的毫秒数后调用函数或计算表达式(只执行一次)

History

历史记录

获取:使用window.history获取,window.可以省略

window.history.方法();
history.方法();

方法:

back()    加载history列表中的前一个URL

forward()   加载history列表中的下一个URL

Location

地址栏对象

获取:使用window.location获取,其中window.可以省略

window.location.方法();
location.方法();

属性:

href     设置或返回完整的URL

DOM

文档对象模型

讲标记语言的各个组成部分封装为对象

Document:整个文档对象

Element:元素对象

Attribute:属性对象

Text:文本对象

Comment:注释对象

获取Element对象

元素对象

获取:使用Document对象的方法来获取

1.getElementById:根据id属性值获取,返回一个Element对象

2.getElementsByTagName:根据标签名称获取,返回Element对象数组

3.getElementsByName:根据name属性值获取,返回Element对象数组

4.getElementByClassName:根据class属性值获取,返回Element对象数组

常见HTML Element对象的使用

查文档

事件监听

事件:HTML事件是发生在HTML元素上的“事情”

eg:1.按钮被点击  2.鼠标移动到元素之上  3.按下键盘按键

事件监听:JavaScript可以在事件被侦测到时执行代码

事件绑定

一、通过HTML标签中的事件属性进行绑定

<input type="button" onclick='on()'>
function on(){
alert("我被点了");
}

二、通过DOM元素属性绑定

<input type="button" id="btn">
document.getElementById("btn").onclick=function(){
alert("我被点了");
}

常见事件

查文档

表单验证

 正则表达式

正则表达式定义了字符串组成的规则

定义:

注意:不要加引号,因为不是字符串

var reg=/^\w{6,12}$/;
var reg=new RegExp("^\\w{6,12}$");

方法:

test(str):判断指定字符串是否符合规则,返回true或false

 八、Web核心

B/S架构:Browser/Server,浏览器/服务器架构模式,特点:客户端只需要浏览器,应用程序的逻辑和数据都存储再服务器端。浏览器只需要请求服务器,获取Web资源,服务器把Web资源发送给浏览器即可

浏览器请求服务器:  HTTP协议:定义通信规则

Web服务器;负责解析HTTP协议,解析请求数据,并发送响应数据

HTTP

请求数据格式

 请求行:请求数据的第一行。其中GET表示请求方式,/表示请求资源路径,HTTP/1.1表示协议版本

请求头:第二行开始,格式为key:value形式

常见的HTTP请求头:

Host:表示请求的主机名

User-Agent:浏览器版本

Accept:表示浏览器能接受的资源类型,如text/*,image/*或者*/*(表示所有)

Accept-Language:表示浏览器偏好的语言,服务器可以据此返回不同语言的网页(中,英...)

Accept-Encoding:表示浏览器可以支的压缩类型

请求体:POST请求的最后一部分,存放请求参数(与请求体有一行空行隔开)

 GET请求和POST请求区别:

1.GET请求请求参数在请求行中,没有请求体,POST请求请求参数在请求体中

2.GET请求请求参数大小有限制(URL长度有限制),POST没有

相应数据格式

相应行:相应数据的第一行。其中HTTP/1.1表示协议版本,200表示相应状态码,OK表示状态码描述

200   OK     客户端请求成功,即处理成功

404   Not Found    请求资源不存在,一般是URL输入有误,或者网站资源被删除了(改路径)

500   Internal Server Error  服务器发生不可预期的错误,服务器出异常(修改Java代码)

响应头:第二行开始,格式为key:value形式

Content-Type:表示该响应内容的类型,例如text/html,image/jpeg

Content-Length:表示响应内容的长度(字节数)

Content-Encoding:表示该响应压缩算法,例如gzip

Cache-Control:指示客户端应如何缓存(缓存到本地下次就可以直接从本地打开减少响应时间),例如max-age=300(表示可以最多缓存300s)

响应体:最后一部分,存放响应数据(与响应头有一行空行隔开)

Tomcat

基本使用

启动:双击:bin\startup.bat

关闭:Crtl+C:正常关闭

配置:修改端口号:conf/server.xml(HTTP协议默认端口号为80,如果将Tomcat端口号改为80,则将来访问Tomcat不用输入端口号)

启动:端口号冲突找到对应程序,将其关闭

部署项目:将项目放到webapps目录下(一般JavaWeb项目会被打成war包,然后将war包放到webapps目录下,Tomcat会自动解压缩war文件)

项目结构:

创建MavenWeb项目:

 IDEA中使用Tomcat

Servlet

Servlet是Java提供的一门动态(不同用户访问看到的效果就不一样,个性化)web资源开发技术

 

Servlet其实就是一个接口,由web服务器运行Servlet 

快速入门

 demo

@WebServlet("/demo1")
public class ServletDemo1 implements Servlet {
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet hello world");
    }

.xml

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
<!-- Tomcat插件     -->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
      </plugin>
    </plugins>
  </build>
  <packaging>war</packaging>

执行流程

 生命周期

@WebServlet(urlPatterns = "/demo2")
public class ServletDemo3 implements Servlet {
    private ServletConfig config;

    public void init(ServletConfig servletConfig) throws ServletException {

        this.config=config;
        //初始化方法
        //1.调用时机:默认情况下Servlet被第一次访问时调用
        //2.调用次数:1次
        System.out.println("init...");
    }
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //提供服务
        //调用时机:每一次Servlet被访问时,调用
        //调用次数:多次
        System.out.println("servlet hello world");
    }

    public String getServletInfo() {
        return null;
    }
    //返回一些关于Servlet的信息,作者版权版本

    public void destroy() {

        //销毁方法
        //1.调用时机:内存释放或者服务器关闭的时候,Servlet对象会被销毁,调用
        //2.调用次数:1次
        System.out.println("destroy");
    }


    public ServletConfig getServletConfig() {
        return config;
    }

}

 体系结构

@WebServlet("/demo5")
public class ServletDemo5 extends MyHttpServlet {
    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {
        System.out.println("get...");
    }

    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
        System.out.println("post...");
    }
}
public class MyHttpServlet implements Servlet {
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    public ServletConfig getServletConfig() {
        return null;
    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

        //根据请求方式的不同,进行分别的处理(get/post)
        HttpServletRequest request=(HttpServletRequest) req;

        //1.获取请求方式
        String method = request.getMethod();

        //2.判断
        if("GET".equals(method)){
            //get方式的处理逻辑
            doGet(req,res);
        }else if("POST".equals(method))
        {
            //post方式的处理逻辑
            doPost(req,res);
        }
    }

    protected void doPost(ServletRequest req, ServletResponse res) {
    }//protected子类可见

    protected void doGet(ServletRequest req, ServletResponse res) {
    }

    public String getServletInfo() {
        return null;
    }

    public void destroy() {

    }
}

Servlet urlPattern配置

Servlet要想被访问,必须配置其访问路径(urlPattern)

1.一个Servlet可以配置多个urlPattern

@WebServlet(urlPatterns={"/demo1","demo2"})

 2.配置规则

 优先级:精确路径>目录路径>扩展名路径>/*>/

Request(请求)&Response(响应)

Request:获取请求数据

Response:设置响应数据

Request继承体系

 Request获取请求数据

请求行

@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //GET/request-demo1/req1?username=zhangsan HTTP/1.1
        //String getMethod():   获取请求方式:GET
        String method = req.getMethod();
        System.out.println(method);//GET
        //String getContextPath():获取虚拟目录:request-demo1
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        //StringBuffer getRequrstURL():获取URL(统一资源定义符):http://localhost:8080/request-demo1/req1
        StringBuffer url = req.getRequestURL();
        System.out.println(url);
        //StringBuffer getRequestURI();获取URI(统一资源标识符):request-demo1/req1
        String uri = req.getRequestURI();
        System.out.println(uri);
        //String getQueryString(): 获取请求参数(GET方式):username=zhangsan
        String queryString = req.getQueryString();
        System.out.println(queryString);

    }

请求头

 //---------------
        //获取请求头:user-agent:浏览器的版本信息
        String agent = req.getHeader("user-agent");
        System.out.println(agent);

请求体 

 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取post 请求体:请求参数

        //1.获取字符输入流
        BufferedReader br = req.getReader();
        //2.读取数据
        String line = br.readLine();
        System.out.println(line);
    }

Request对象获得请求参数

Map <String,String[]> getParameterMap():获取所有参数集合
String[] getParameterValues(String name):根据名称获取参数值(数组)
String getParameter(String name):根据名称获取参数值(单个值)
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //GET请求逻辑

        System.out.println("get....");
        
        //1.获取所有参数的map集合
        Map<String, String[]> map = req.getParameterMap();
        for (String key : map.keySet()) {
            //username:zhangsan lisi
            System.out.print(key+":");

            //获取值
            String[] values = map.get(key);
            for (String value : values) {
                value= new String(value.getBytes("ISO-8859-1"), "utf-8");
                System.out.print(value+" ");
            }
            System.out.println();
        }
        System.out.println("---------");

        //2.根据key获取参数值,数组
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }

        //3.根据key.获取单个参数值
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        System.out.println(password);


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //POST请求逻辑
        this.doGet(req,resp);
    }
}

请求参数中文乱码

POST解决方案:

   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   //1.解决乱码:POST.getReader()
        request.setCharacterEncoding("UTF-8");//设置字符输入流的编码

        //2.获取username
        String username = request.getParameter("username");
        System.out.println("解决乱码前:"+username);
}

GET解决方案:


{ //2.获取username
        String username = request.getParameter("username");
        System.out.println("解决乱码前:"+username);

        //3.GET,获取参数的方式:getQueryString
        //乱码原因;tomcat进行URL解码,默认的字符集ISO-8859-1
       /* //3.1 先对乱码数据进行编码:转为字节数组
        byte[] bytes = username.getBytes("ISO-8859-1");
        //3.2 字节数组解码
       username = new String(bytes,"utf-8");*/
        username=new String(username.getBytes("ISO-8859-1"),"utf-8");
        System.out.println("解决乱码后:"+username);
    }

请求转发

forward:一种在服务器内部的资源跳转方式(类似流水线)

 实现方式:

req.getRequestDispatcher("资源B路径").forward(req,resp);

请求转发资源间共享数据:使用Request对象

1.void setAttribute(String name,Object o):存储数据到request域中

2.Object getAttribute(String name): 根据key,获取值

3.void removeAttribute(String name):根据key,删除键值对

请求转发特点

1.浏览器地址栏路径不发生变化

2.只能转发到当前服务器的内部资源

3.一次请求,可以在转发的资源间使用request共享数据

Response设置响应数据功能介绍&完成重定向

 重定向(Redirect):一种资源跳转方式

 实现方式:

resp.setStatus(302);
resp.setHeader("location","资源B的路径")

简化方式:

resp.sendRedirect("资源B的路径");

重定向特点(与请求转发相反):

1.浏览器地址栏路径发生变化

2.可以重定向到任意位置的资源(服务器内部,外部均可)

3.两次请求,不能在多个资源使用request共享数据

资源路径问题

浏览器使用:需要加虚拟路径(项目访问路径)

服务端使用:不需要加虚拟目录

 //动态获取虚拟目录
        String contextPath = request.getContextPath();
        response.sendRedirect(contextPath+"/resp2");

Response响应字符&字节数据

字符:

使用:

1.通过Response对象获取字符输出流

PrintWriter writer=resp.getWriter();

2.写数据

writer.write("aaa");

字节:

使用:

1.通过Response对象获取字符输出流

ServletOutStream outputStream=resq.getOutputStream();

2.写数据

outputStream.write(字节数据);

IOUtils工具类使用

1.导入坐标

<dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>1.4</version>
    </dependency>

2.使用

IOUtills.copy(输入流,输出流);

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

        //1.读取文件
        FileInputStream fis = new FileInputStream("e://a.jpg");

        //2.获取response字节输出流
        ServletOutputStream os = response.getOutputStream();

        //3.完成流的copy
       /* byte[] buff = new byte[1024];
        int len=0;
        while ((len=fis.read(buff))!=-1){
            os.write(buff,0,len);
        }
        */
        IOUtils.copy(fis,os);
        fis.close();

    }

案例

用户登录:

用户注册:

避免重复开资源,创一个工具类,里面放static块(只能被执行一次)

JSP

Java服务端页面

JSP=HTML+Java

快速入门

JSP脚本

JSP脚本用于在JSP页面内定义Java代码

1.<%...%>:内容会直接放到_jspService()方法之中

2.<%=...%>:内容会放到out.print()中,作为out.print()的参数

3.<%!...%>:内容会放到_jspService()方法之外,被类直接包含

<%@ page import="pojo.Brand" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %><%--
  Created by IntelliJ IDEA.
  User: LYQ
  Date: 2022/11/26
  Time: 20:48
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%
  List<Brand> brands = new ArrayList<Brand>();
  brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
  brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
  brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
%>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<input type="button" value="新增"><br>
<hr>
<table border="1" cellspacing="0" width="800">
  <tr>
    <th>序号</th>
    <th>品牌名称</th>
    <th>企业名称</th>
    <th>排序</th>
    <th>品牌介绍</th>
    <th>状态</th>
    <th>操作</th>

  <tr align="center">
    <td>1</td>
    <td>三只松鼠</td>
    <td>三只松鼠</td>
    <td>100</td>
    <td>三只松鼠,好吃不上火</td>
    <td>启用</td>
    <td><a href="#">修改</a> <a href="#">删除</a></td>
  </tr>

<%
  for (int i = 0; i < brands.size(); i++) {
    Brand brand = brands.get(i);
 %>
  <tr align="center">
    <td><%=brand.getId()%></td>
    <td><%=brand.getBrandName()%></td>
    <td><%=brand.getCompanyName()%></td>
    <td><%=brand.getOrdered()%></td>
    <td><%=brand.getDescripition()%></td>
    <td><%=brand.getStatus()%></td>
    <td><a href="#">修改</a> <a href="#">删除</a></td>
  </tr>

  <%
  }
%>

</table>

</body>
</html>

EL表达式

用于简化JSP页面内的Java代码

语法:${expression}

${brands}:获取域中存储的key为brands的数据

JavaWeb中的四大域对象:1.page 当前页面有效     2.request   当前请求有效       3.session  当前会话有效   4.application   当前应用有效

JSTL标签

使用标签取代JSP页面上的Java代码

1.导入坐标

<!--   jstl -->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>
  </dependencies>

2.在JSP页面上引入JSTL标签库

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

3.使用

<c:if></c:if>       if判断

<body>

<%--
  c标签
--%>

<c:if test="${status==1}">
   <h1>启用</h1>
</c:if>

<c:if test="${status==0}">
    <h1>禁用</h1>
</c:if>
</body>

<c:forEach>:相当于for循环

items:被遍历的容器

var:遍历产生的临时变量

在page directive中的isELIgnored属性用来指定是否忽略。格式为: <%@ page isELIgnored="true|false"%> 如果设定为真,那么JSP中的表达式被当成字符串处理。比如下面这个表达式${1000 % 10}, 在isELIgnored="true"时输出为${1000 % 10},而isELIgnored="false"时输出为100。Web容器默认isELIgnored="false"

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="button" value="新增"><br>
<hr>
<table border="1" cellspacing="0" width="800">
    <tr>
        <th>序号</th>
        <th>品牌名称</th>
        <th>企业名称</th>
        <th>排序</th>
        <th>品牌介绍</th>
        <th>状态</th>
        <th>操作</th>

    </tr>

    <c:forEach items="${brands}" var="brand" varStatus="status">
        <tr align="center">
<%--            <td>${brand.id}</td>--%>
            <td>${status.count}</td>
<%--       status.index代表从0开始  status.count代表从1开始--%>
            <td>${brand.brandName}</td>
            <td>${brand.companyName}</td>
            <td>${brand.oedered}</td>
            <td>${brand.description}</td>
           <c:if test="${brand.status==1}">
               <td>启用</td>
           </c:if>
            <c:if test="${brand.status!=1}">
                <td>禁用</td>
            </c:if>

            <td>${brand.status}</td>
            <td><a href="#">修改</a> <a href="#">删除</a></td>
        </tr>

    </c:forEach>

</table>

<hr>

<c:forEach begin="0" end="10" step="1" var="i">
    <a href="#"> ${i}<br> </a>
</c:forEach>

</body>
</html>

MVC模式和三层架构

MVC是一种分层开发的模式:

M:Model,业务模型,处理业务

V:View,视图,界面展示

C:Controller,控制器,处理请求,调用模型和视图

三层架构:

数据访问层:dao/mapper

业务逻辑层:service

表现层:web/controller

案例

1.创建新的模块brand_demo,引入坐标

2.创建三层架构的包结构

3.数据库表tb_brand

4.实体类Brand

5.MyBatis基础环境:Mybatis-config.xml(mybatis核心配置文件,1.类起别名2.环境准备3.扫描mapper(mapper接口))        BrandMapper.xml       BrandMapper接口

service层作用:真正大型的项目并非只是根据页面的条件进行增删改查的。 查询的时候页面传递给service层的只是简单的一些查询条件,但是页面需要显示的查询结果的数据并不在同一个对象(或者说表)中,这就需要service层进行一些逻辑处理了,比如将这些查询条件进行拆分、组合用以查询不同的数据,然后再将这些不同的数据进行整合反馈给前台页面显示。

提高代码复用性

查询所有

解决实体类属性名称和字段名称不一致

配置映射文件

BrandMapper.xml

  <resultMap id="brandResultMap" type="brand">
        <result column="brand_name" property="brandName"></result>
       <result column="company_name" property="companyName"></result>
    </resultMap>

添加

修改

 回显数据:讲原来的数据展示给用户

修改数据

会话跟踪技术

Cookie:将数据放在客户端           Session:将数据放在服务端

Cookie基本使用

客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问

发送Cookie

1.创建Cookie对象,设置数据

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

2.发送Cookie到客户端:使用response对象

response.addCookie(cookie);

获取Cookie

3.获取客户端携带的所有Cookie,使用request对象

Cookie[] cookies=request.getCookies();

4.遍历数组,获取每一个Cookie对象:for

5.使用Cookie对象方法获取数组

cookie.getName();
cookie.getValue();

Cookie原理

响应头:set-cookie

请求头:cookie

Cookie存活时间

默认情况下,Cookie存在浏览器内存中,当浏览器关闭,内存释放,则cookie被销毁

setMaxAge(int seconds):设置Cookie存活时间

1.正数:讲Cookie写入浏览器所在的电脑的硬盘,持久化存储。到时间自动删除

2.负数:默认值

3.零:删除对应Cookie

Cookie存储中文

如需要存储,需要进行转码:URL编码

package com.itheima.web.cookie;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.net.URLEncoder;

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//发送cookie
        
        //1.创建cookie
        //Cookie cookie = new Cookie("username","zs");

        String value="张三";
        //URL编码
        value = URLEncoder.encode(value, "UTF-8");
        System.out.println("存储数据"+value);

        Cookie cookie = new Cookie("username", value);

        //设置存活时间  1周7天  直接放进去可自动算出来
        cookie.setMaxAge(60*60*24*7);


        //2.发送Cookie。response
        response.addCookie(cookie);
    }

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

package com.itheima.web.cookie;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;

@WebServlet("/bServlet")
public class BServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取cookie

        //1.获取Cookie数组
        Cookie[] cookies = request.getCookies();
        //2.遍历数组
        for (Cookie cookie : cookies) {
            //3.获取cookie数据
            String name = cookie.getName();
           if ("username".equals(name))
           {
               String value = cookie.getValue();
               //URL编码
               value = URLDecoder.decode(value, "UTF-8");
               System.out.println(name+":"+value);
               break;
           }
        }

    }

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

Session基本使用

总是和客户端交互可能会不安全

将数据保存到服务端

JavaEE提供HttpSession接口,来实现一次会话的多次请求间数据共享功能

使用:

1.获取Session对象

HttpSession session=request.getSession();

2.Session对象功能

void setAttribute(String name,Object o) //存储数据到session域中
Object getAtrribute(String name)//根据key,获取值
void removeAttribute(String name) //根据key,删除该键值对

Session原理

Session是基于Cookie实现的

Session钝化、活化:

不能因服务器的重启导致数据丢失

钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中

活化:再次去启动服务器后,从文件中加载数据到Session中

Session销毁:

浏览器关闭,Session获得的就不是同一个了,而cookie可以写到电脑硬盘中,长时间储存数据

默认情况下,无操作,30min自动销毁

可通过web.xml配置

  <session-config>
    <session-timeout>100</session-timeout>
  </session-config>

主动销毁数据(登录退出)

session.invalidate();

package com.itheima.web.session;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet("/demo1")
public class SessionDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   //存储到Session中
        //1.获取Session中
        HttpSession session = request.getSession();
        //2.存储数据
        session.setAttribute("username","zs");

    }

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

package com.itheima.web.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/demo2")
public class SessionDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取数据:从session中
        //1.获取Session对象
        HttpSession session = request.getSession();

        //销毁
      session.invalidate();

        //2.获取数据
        Object username = session.getAttribute("username");
        System.out.println(username);


    }

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

小结:

区别:

存储位置:Cookie是将数据存储在客户端,Session将数据存储在服务端

安全性:Cookie不安全(传来传去),Session安全

数据大小:Cookie最大3KB,Session无大小限制

存储时间:Cookie可以长期存储,Session默认30分钟

服务器性能:Cookie不占服务器资源,Session占用服务器资源

Cookie用来保证用户在未登录状态下的,Session保护用户登录后的数据

Filter

过滤器

可以把对资源的请求拦截下来,从而实现一些特殊的功能

一般完成一些通用的操作(进入到后面资源都需要用到的操作,写一遍代码就行,比如说登录)

eg:权限控制、统一编码处理、敏感字符处理

Fileter快速入门

1.定义类,实现Filter接口(先接),并重写其所有方法

2.配置Filter拦截资源的路径:在类上定义@WebFilter注解

3.在doFilter方法输出一句话,并放行

package com.itheima.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

//设置需要拦截哪些东西,什么都想拦/*
@WebFilter("/*")
public class FilterDemo implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       //1.放行前,对request数据进行处理
        System.out.println("FilterDemo...");
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
        //2.放行后,对Response数据进行处理
        System.out.println("3.FilterDemo");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    @Override
    public void destroy() {

    }
}

Filter执行流程

资源访问完成后,还会回到Filter中

执行放行前逻辑->放行->访问资源->执行放行后逻辑

Filter使用细节

Filter拦截路径配置

@WebFilter("/*")

public class FilterDemo

拦截具体的资源:/index.jsp:只有访问index.jsp时才会被拦截

目录拦截:/user/* :访问/user下的所有资源,都会被拦截

后缀名拦截:*.jsp:访问后缀名为jsp的资源,都会被拦截

拦截所有:/*:访问所有资源,都会被拦截

过滤器链

一个Web应用中,可以配置多个过滤器,这多个过滤器称为过滤器链

 优先级按照过滤器类名(字符串)的自然排序     字典序

Listener

监听器:可以监听就是在application,session,request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件

 1.定义类,实现ServletContextListener接口

2.在类上添加@WebListener注解

package com.itheima.web.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class ContextLoaderListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

        //加载资源
        System.out.println("ContextLoaderListener...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

AJAX

作用:1.与服务器进行数据交换:通过AJAX可以给服务器发送请求,并获取服务器响应的数据

使用AJAX和服务器进行通信,就可以使用HTML+AJAX来替换JSP页面

 2.异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想,用户名是否可用校验

 同步和异步

 AJAX快速入门

看文档w3school 在线教程

1.编写AjaxServlet,并使用response输出字符串

2.创建XMLHttpRequest对象:用于和服务器交换数据

3.向服务器发送请求

4.获取服务器响应数据

Axios异步框架

对原生AJAX进行封装,简化书写

<script src="js/axios-0.18.0.js"></script>
<script>
    // //1.get
    // axios({
    //     method:"get",
    //     url:"http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan"
    // }).then(function (resp)
    // {
    //     alert(resp.data);
    //

    //2.post
    //1.get
    axios({
        method:"post",
        url:"http://localhost:8080/ajax-demo/axiosServlet",
        data:"username=zhangsan"
    }).then(function (resp)
    {
        alert(resp.data);
    })

</script>
package com.itheima.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/axiosServlet")
public class AxiosServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("get....");

        //1.接收请求参数
        String username = request.getParameter("username");
        System.out.println(username);


        //2.响应数据
        response.getWriter().write("hello axios~");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("post...");
        this.doGet(request, response);
    }
}

Axios请求方式别名

JSON

JavaScript对象表示法         作为数据载体

 JSON基础语法

定义

var 变量名={

"key1":value1,
"key2":value2,


};

value的数据类型为:数字,字符串,逻辑值(false或true),数组(在方括号中),对象(在花括号中),null

获取数据:变量名.key

JSON数据和Java对象转换

浏览器

请求数据:JSON字符串转为Java对象

响应数据:Java对象转为JSON字符串

Fastjson库

1.导入坐标

<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>2.0.18</version>
    </dependency>

2.Java对象转JSON

String jsonStr=JSON.toJSONString(obj);

3.JSON字符串转Java对象

User user=JSON.parseObjecet(jsonStr,User.class)

Vue

Vue是一套前端框架,免除原生JavaScript中的DOM操作,简化书写

基于MVVN思想,实现数据的双向绑定

 

Vue快速入门

 ../代表上一层目录

../../代表上上层目录

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">

    <input v-model="username">
     <!--  插值表达式      上面的模型一变,取出来的数值就跟着变化-->
    {{username}}
</div>


<script src="../js/vue.js"></script>
<script>
   //1.创建vue的核心对象
   new Vue({
       el:"#app",
       data() {
       return{
           username:""
       }
     }
   })

</script>
</body>
</html>

Vue常用指令

html标签上带有v-前缀的特殊属性

v-bind:为HTML标签绑定属性值,如设置href,css样式等(直接写href会把程序写死,这样写可以随意改变)

v-model:为表单元素上创建双向数据绑定

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="app">
    <a v-bind:href="url">点击一下</a>
    <br>
    <a :href="url">点击一下</a>

    <input v-model="url">
</div>

<script src="../js/vue.js"></script>
<script>

    //1.创建Vue核心对象
    new Vue({
        el:"#app",
        data() {
            return{
                username:"",
                url:"https://www.baidu.com"
            }

        }
    })

</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <input type="button" value="一个按钮" v-on:click="show()">
    <input type="button" value="一个按钮" @click="show()">
</div>

<script src="../js/vue.js"></script>
<script>

    new Vue({
       el:"#app",
        methods:{
            show(){
                alert("我被点了...")
            }
        }
    })
</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <input type="button" value="一个按钮" v-on:click="show()">
    <input type="button" value="一个按钮" @click="show()">

    <div v-if="count==3">div1</div>
    <div v-else-if="count==4">div2</div>
    <div v-else>div3</div>
    <hr>
    <div v-show="count==3">v-show</div>

    <input v-model="count">
</div>

<script src="../js/vue.js"></script>
<script>

    new Vue({
       el:"#app",
        data(){
           return{
               count:3
           }
        },
        methods:{
            show(){
                alert("我被点了...")
            }
        }
    })
</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">

    <div v-for="(addr,i) in addrs">
      {{i+1}}--{{addr}}  <br>
    </div>
</div>

<script src="../js/vue.js"></script>
<script>

    new Vue({
       el:"#app",
        data(){
           return{
               username:"",
               url:"https://www.baidu.com",
               count:3,
               addrs:["北京","上海","徐州"]
           }
        },
        methods:{
            show(){
                alert("我被点了...")
            }
        }
    })
</script>
</body>
</html>

Vue生命周期

Vue案例

查询所有

新增品牌

v-model输入的值产生变化,模型自动产生变化(获取值再赋值的代码就不用写了)

Element

基于Vue的网站组件库,用于快速构建网页

Element官网

快速入门

1.引入Element的文件

先引入vue在引入element-ui

<script src="../js/vue.js"></script>
<script src="../element-ui/lib/index.js"></script>
<link rel="stylesheet" href="../element-ui/lib/theme-chalk/index.css">

2.创建Vue核心对象

3.官网复制Element组件代码

 

布局

 

组件

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值