首页 > 编程语言 >2020-5-5-JAVAWEB

2020-5-5-JAVAWEB

时间:2024-03-22 17:00:30浏览次数:41  
标签:java String javax 2020 import servlet public JAVAWEB

测试、反射、注解、Mysql、JDBC、Tomcat、servlet、HTTP、EL表达式、JSTL、Filter过滤器、代理模式、监听器、Redis、Maven

测试

1黑白盒测试

黑盒测试:不需要写代码,给输入值,看程序能否给出期望的输出值

白盒测试:需要写代码,关注程序具体执行流程

2测试步骤

1)定义测试类

包名:cn.itcast.test

类名:CaculatorTest

2)定义测试方法

方法名:test测试方法名

返回值:void

参数:空

3)使用注解@Test

执行后结果为红色,执行失败;绿色,执行成功。

4)断言

Assert.assertEquals(期望值,结果值)

5)初始化方法和释放资源方法

@Before//修饰的方法在测试方法之前执行
public void init(){}
@After//修饰的方法在测试方法之后执行,一般用于释放资源
public void close(){}

反射

将类的各部分封装为其他类对象,多用于框架(半成品软件,简化编码)的开发。优势在于,一是可以在程序运行过程中操作这些对象,二是解耦程序,提高程序可扩展性

1获取class对象的方式

1)class.forName(全类名)

多用于配置文件

2)类名.class

多用于参数传递

3)对象.getClass()

多用于对象

同一字节码文件在异常程序运行过程中,只会被加载一次,不论通过那只方式获取的Class对象都是同一个

2Class对象的功能

1)获取成员变量

//获取public修饰的成员变量
public Field[] getFields() throws SecurityException;
public Field getField(String name);

//获取所有声明的成员变量
public Field[] getDeclaredFields() throws SecurityException;
public Field getDeclaredField(String name);

2)获取构造方法

public Constructor<?>[] getConstructors() throws SecurityException;
public Constructor<T> getConstructor(Class<?>... parameterTypes);
public Constructor<?>[] getDeclaredConstructors() throws SecurityException ;
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);

3)获取成员方法

public Method[] getMethods() throws SecurityException;
public Method getMethod(String name, Class<?>... parameterTypes);
public Method[] getDeclaredMethods() throws SecurityException;
public Method getDeclaredMethod(String name, Class<?>... parameterTypes);

4)获取类名

public String getName();

5)获取、改变成员变量的值

public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException;
public void set(Object obj, Object value);

6)创建对象

(1)构造方法对象创建有参实例对象

public T newInstance(Object ... initargs);

(2)类对象创建实例无参对象

public T newInstance();
public class Person{
    public String name;
    private int age;

    public Person() {
        super();
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public void say(){
        System.out.println("我是"+this.name+",今年"+this.age+"岁了");
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Hello{
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        //获取类对象
        Class ps=Person.class;

        //获取类名
        System.out.println(ps.getName());

        //获取声明的成员变量
        Field[] fields=ps.getDeclaredFields();
        Field name=ps.getDeclaredField("name");
        Field age=ps.getDeclaredField("age");
        System.out.println(Arrays.toString(fields));
        System.out.println(name);
        System.out.println(age);

        //获取声明的构造方法
        Constructor[] c=ps.getDeclaredConstructors();
        System.out.println(Arrays.toString(c));
        Constructor c1=ps.getDeclaredConstructor(String.class,int.class);
        System.out.println(c1);

        //获取声明的成员方法
        Method[] mt=ps.getMethods();
        System.out.println(Arrays.toString(mt));
        Method m1=ps.getMethod("setAge", int.class);
        System.out.println(m1);
        Method m2=ps.getMethod("say");
        System.out.println(m2);

        //创建对象
        Object person=c1.newInstance("zhang",22);//构造方法对象创建有参对象
        System.out.println(person);
        Object person1=ps.newInstance();//类对象创建无参对象
        System.out.println(person1);

        //通过成员变量对象获取成员变量值
        Object name_value=name.get(person);
        System.out.println(name_value);
        age.setAccessible(true);//忽略访问权限修饰符的安全检测,无此语句会抛出错误
        Object age_value=age.get(person);//age是私有属性
        System.out.println(age_value);

        //通过成员变量对象设置成员变量值
        name.set(person,"zh");
        System.out.println(person);

        //通过成员方法对象执行对象的成员方法
        m2.invoke(person);
    }

}

2手写框架案例

要求:不改变类的任何代码的前提下,创建任意类对象,并执行其中的方法

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class Hello{
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //读取配置文件
        Properties pro=new Properties();
        ClassLoader cl=Hello.class.getClassLoader();
        InputStream is=cl.getResourceAsStream("pro.Properties");
        pro.load(is);
        System.out.println(pro);//{ClassName=aaa.Person, MethodName=say}
        
        //创建类及对象,并执行方法
        Class ps = Class.forName(pro.getProperty("ClassName"));
        Constructor c = ps.getConstructor(String.class,int.class);
        Object person=c.newInstance("zhanghuan",22);
        Method m=ps.getMethod(pro.getProperty("MethodName"));
        m.invoke(person);//我是zhanghuan,今年22岁了
    }

}

注解

JDK1.5后的新特性,对元素进行说明注释,用于编译检查、生成doc文档、代码分析

1自带注解

@Override

检测被该注解标注的方法是否是继承自父类(接口)

@Deprecated

该注解标注的内容,表示已过时

@SuppressWarnings

压制警告,可传参数all,如@SuppressWarnings("all")

2自定义注解

1)格式

元注解
Public @interface MyAnno{

}

2)本质

注解的本质是一个接口,将其编译后再进行反编译,发现其是一个继承自java.lang.annotation.Annotation的接口

3)属性

指接口中定义的抽象方法,具有返回值

(1)返回值类型

int,String,枚举,注解及以上数据类型的数组

(2)属性赋值

使用属性前需要给属性赋值,设置default默认值的可不赋值

只有一个属性需要赋值,且属性名是value,可省略value并直接赋值

数组赋值时,需用{}包裹,只有一个值时,{}可省略

4)元注解

对注解进行注释

(1)@Target

描述注解的作用范围,参数分别是ElementType.TYPE类,ElementType.METHOD方法,ElementType.FIELD成员变量

(2)@Retention

注解被保留的阶段,参数常用RetentionPolicy.RUNTIME

(3)@Documented

注解是否被抽取到api文档中

(4)@Inherited

阐述了某个被标注的类型是被继承的

3获取类的注解

获取到类的class对象时,调用该对象的getAnnotation(注释名.class)方法

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
    public String name();
    public int age();
}
@MyAnno(name="zhanghuan",age=22)
public class Hello{
    public static void main(String[] args) {
        Class<Hello> hello=Hello.class;
        MyAnno an= hello.getAnnotation(MyAnno.class);
        //此方法相当于创建一个MyAnno的子类实现对象
        /*类似于以下的类
            class abc implements MyAnno{
                String name;
                int age;
                public abc(String name, int age) {
                    this.name = name;
                    this.age = age;
                }
                @Override
                public String name() {
                    return this.name;
                }
                @Override
                public int age() {
                    return this.age;
                }
            }
         */
        System.out.println(an.name());//zhanghuan
        System.out.println(an.age());//zhanghuan
    }

}

4测试案例

//定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
}
//定义类,并在需要测试的方法上标注注解
public class Calculator {
    @Check
    public static int add(int a,int b){
        return a+b;
    }
    @Check
    public static int subtract(int a,int b){
        return a-b;
    }
    @Check
    public static int multiply(int a,int b){
        return a*b;
    }
    @Check
    public static int divide(int a,int b){
        return a/b;
    }
}
//定义测试类
public class TestCalculator {
    public static void main(String[] args) throws ClassNotFoundException, IOException {
        Class cal=Class.forName("aaa.Calculator");
        Method[] m=cal.getMethods();
        BufferedWriter bw=new BufferedWriter(new FileWriter("bug.txt"));
        int num=0;
        for (Method method:
             m) {
            if(method.isAnnotationPresent(Check.class)){
                try {
                    Object result = method.invoke(cal.getInterfaces(), 10, 0);
                    System.out.println(result);
                }catch (Exception e){
                    num++;
                    bw.write(method.getName()+"()方法出异常了");
                    bw.newLine();
                    bw.write(e.toString());
                    bw.newLine();
                    bw.write("___________________________________");
                    bw.newLine();
                }
            }
        }
        bw.write("一共测出了"+num+"个异常");
        bw.close();
    }
}

Mysql

1数据文件删除

在mysql的安装目录可找到init文件,打开后找到有一行为datadir="c:\ProgrData\MySql\MySqlServer5.5\",找到该路径,删除里面的文件即可

2常用命令

//打开服务窗口
Service.msc

//停止服务
net stop mysql

//开启服务
net start mysql

//登陆服务器
mysql -h127.0.0.1 -uroot -p

//登陆服务器方式二
myql --host=ip --user=root --password=abc

//退出mysql
exit

3SQL结构化查询语言

操作所有关系型数据库的规则

1)语法规则

(1)SQL语言可单行、多行书写,以分号结尾

(2)使用空格和缩进来则鞥去语句的可读性

(3)mysql的SQL语言不区分大小写,建议关键词大写

(4)注释,--或#为单行注释,其中#为mysql独有;/**/为多行注释

2)分类

(1)DDL(Data Defining langrage)定义语言

定义数据库对象:数据库,表,列等,如crete,drop,alter

(2)DML(Data Manipulation langrage)操作语言

对表中数据进行增、删、改,如insert,delete,update

(1)DQL(Data Query langrage)查询语言

查询表中记录,如select where

(1)DCL(Data Control langrage)控制语言

定义访问权限和安全级别,如GRANT,REVOKE

5对数据库的操作

1)创建

//创建一个名为db1的数据库
create database db1;

//创建一个数据库db1(如果db1不存在才创建)并设置字符集为gbk
create database if not exists db1 character set gbk;

2)查询

//查看所有数据库
show databases;

//查看数据库db1的创建语句
show create database db1;

3)修改

//将数据库db1的字符集修改为utf8
alter database db1 character set utf8;

4)删除

//删除数据库db1
drop database db1;

//删除数据库db1(如果存在才删除)
drop database if exists db1;

5)使用数据库

//查看正在使用的数据库
select database();

//使用数据库db1
use db1;

6对表的操作

1)创建

//创建一个名为student的表
create table student(
	name vachar(20),
	age int(2)
);
//复制表student
create table stu like student;

数据类型

数据类型 说明
int 整数,有符号的整数范围在正负21亿之间。声明时需要传入一个参数size,即整数的长度
double 双精度浮点数。声明时需要传入两个参数,分别指小数点左侧数的长度和小数点右侧数的长度
varchar 可变长度字符串,长度不超过255个字符。声明时需要传入字符串的长度
date 包含年月日的日期
datetime 包含年月日时分秒的日期
timestamp 包含年月日时分秒的时间戳,插入数据时会自动截取当前时间存入

2)查询

//查询所有表
show tables;

//查询表结构
dest student;

3)修改

(1)修改表名

alter table 表名 rename to 新表名;

(2)修改字符集

alter table 表名 character set 字符集名称;

(3)添加列

alter table 表名 add 列名 数据类型;

(4)修改列名称及其数据类型

alter table 表名 modify 列名 新列名 新数据类型;

(5)删除列

alter table 表名 drop 列名;

4)删除

//删除表student
drop table student

//删除表student(如果存在才删除)
drop table if exists student

7对数据操作

1)添加数据

insert into 表名(列名1,列名2) values(值1,值2);

注意

1.列名和值必须一一对应

2.表名后不写列名,表示给所有列增加值

3.除数字外吗,其他类型的值都需要用引号包裹

2)删除数据

delet form 表名 [where条件]

注意

1.如果不加条件,表示删除表中所有数据

2.如果要删除表中所有数据,推荐使用TRUNCATE TABLE 表名,效率高,其原理是删除表后再重新创建一张同名表

3)修改数据

update 表名 set 列名1=值1,列名2=值2 [where条件]

注意

如果不加条件,表中所有数据将会被修改

7查询表中数据

1)语法

select
	字段1,字段2……
from 
	表1,表2……
where
	条件列表
goroup by
	分组字段
having
	分组之后条件
order by
	排序
limit
	分页

2)基础查询

(1)去除重复结果

SELECT DISTINCT adress from student;

(2)计算列

SELECT name,math,english,math+IFNULL(english,0) FROM student;

IFNULL(english,0)是指如果english为null,当作0来处理

(3)起别名

//AS来替代字段名进行显示,AS可省略
SELECT name AS 姓名,math AS 数学,english AS 英语,math+IFNULL(english,0) AS 总分 FROM student;

(4)条件查询

除了常规的运算符

<,>,>=,<=,=,!=,<>

还有

//BWTWEEN AND
SELECT name,math,english FROM student where math BETWEEN 70 AND 80;
//AND
SELECT name,math,english FROM student where math>70 AND math<80;
//OR
SELECT name,math,english FROM student where math<70 OR math>80;
//IN
SELECT name,math,english FROM student where math IN (50,52,64);

如果数据内容是null,则不可以用判断

//找出english是null的数据
SELECT name,math,english FROM student where english IS NULL;
//找出english不是null的数据
SELECT name,math,english FROM student where english IS NOT NULL;

模糊查询LIKE

SELECT name,math,english FROM student where name LIKE "%杰_";
/*
%是多个字符的占位符
_是单个字符的占位符
*/

(5)排序查询

//将结果math进行默认排序(升序)
SELECT name,math,english FROM student ORDER BY math;
//将结果math进行升序排列
SELECT name,math,english FROM student ORDER BY math ASC;
//将结果math进行降序排列
SELECT name,math,english FROM student ORDER BY math DESC;

注意

1.默认按升序排列

2.有多个排序条件,则前面条件值一样时,才会使用后面的排序条件

(6)聚合函数

将一列数据作为一个整体,纵向计算。包含COUNT,MAX,MIN,SUM,AVG

//计数
SELECT COUNT(name) FROM student;
//求最大值
SELECT MAX(math) FROM student;
//求最小值
SELECT MIN(math) FROM student;
//求和
SELECT SUM(math) FROM student;
//求平均
SELECT AVG(math) FROM student;

注意

聚合函数计算时会排除掉值为null的数据

(7)分组查询

一般和聚合函数合用

SELECT AVG(math) FROM student GROUP BY male;

where和having的区别

/*
1.where在执行分组操作前限定,having在执行分组操作后限定
2.where后不可跟聚合函数
3.having子句中可以使用字段别名,而where不能使用
*/

SELECT SUM(math) AS 数学 FROM `student` GROUP BY male HAVING 数学>150;

(8)分页

LIMIT 开始索引,每页条数

公式:开始索引=(当前页码-1)*每页条数

只有mysql的分页是limit,其他数据库软件不一样

8约束

对表中数据进行限定,保证数据的正确性、有效性、完整性。分为:

主键约束(primarykey)、非空约束(notnull)、唯一约束(unique)、外键约束(foreignkey)

1)非空约束

//创建表时新增索引
CREATE TABLE stu(
	id int NOTNULL,
	name varchar(20)
)

//建表后新增索引
ALTER TABLE stu MODIFY name VARCHAR(20) NOTNULL;

//删除索引
ALTER TABLE stu MODIFY name VARCHAR(20);

2)唯一索引

//新增索引
ALTER TABLE stu MODIFY id INT UNIQUE;

//新增索引方式二
ALTER TABLE stu ADD UNIQUE(id);

//删除索引
ALTER TABLE stu DROP INDEX id;

唯一索引里的值可以为多个null

3)主键索引

//新增
ALTER TABLE student MODIFY id INT PRIMARY KEY;

//删除
ALTER TABLE student DROP PRIMARY KEY;

//新增自增
ALTER TABLE student MODIFY id INT AUTO_INCREMENT;

//删除自增
ALTER TABLE student MODIFY id INT;

非空且唯一

4)外键约束

//创建方式一
CREATE TABLE employee(
	dep_id INT,
	CONSTRAINT enp_dep_fk FOREIGN KEY (dep_id) REFERENCES department(id)
);
//需要注意,department.id必须是主键,否则报错;外键名enp_dep_fk可省略

//创建方式二
ALTER TABLE employee ADD CONSTRAINT enp_dep_fk FOREIGN KEY (dep_id) REFERENCES department(id);

//删除外键
ALTER TABLE employee DROP FOREIGN KEY enp_dep_fk;

//创建带级联的外键
ALTER TABLE employee ADD CONSTRAINT enp_dep_fk FOREIGN KEY (dep_id) REFERENCES department(id) ON UPDATE CASCADE ON DELETE CASCADE;

9数据库设计的范式

1)函数依赖

A属性值可确定唯一B属性值,则B依赖于A

2)完全依赖

A为属性组,B属性值的确定需依赖A属性组中所有的属性值

3)部分依赖

A为属性组,B属性值的确定需依赖A属性组中部分的属性值

4)传递依赖

C属性值依赖于B属性值,B属性值依赖于A属性值,那么C属性值传递依赖于A属性值

5)码

属性或属性组被其他属性完全依赖,那么这个属性或属性组称为码

6)主属性和非主属性

码是主属性,其他的属性是非主属性

范式 特点
第一范式 数据冗余,存在函数依赖,出现新增异常和删除异常
第二范式 消除非主属性对主属性的部分函数依赖,但仍出现新增异常和删除异常
第三范式 所有主属性不依赖于其他非主属性,消除传递依赖

10备份和还原

1)备份

mysql dump -u用户名 -p密码 数据库名称 >路径

2)还原

//登陆数据库、创建数据库、使用数据库

//执行命令,其中a.sql是备份的数据库文件
source a.spl

9多表查询

1)笛卡儿积

两个集合A、B,取这两个集合的所有组合情况

2)隐式内联接

SELECT
	t1.time,t1.gender,t1.name
FROM
	emp t1,dep t2
WHRER
	t1.dept_id=t2.id;

内联接查询的是两张表的交集

3)显式内联接

SELECT * FROM exp INNER JOIN dept ON emp.dep_id=dept.id;

4)左外联接

SELECT 字段列表 FROM 表1 LEFT JOIN 表2 ON 条件;

查询的是左表所有的数据交集部分

5)右外联接

SELECT 字段列表 FROM 表1 RIGHT JOIN 表2 ON 条件;

查询的是右表所有的数据交集部分

6)子查询

(1)子查询结果单列、单行

SELECT * FROM emp WHERE salary=(SELECT MAX(salary) FROM emp);

(2子查询结果单列、多行

SELECT * FROM emp WHERE id IN (SELECT id FROM emp WHERE salary>5000);

(3)子查询结果多列、多行

SELECT
	* 
FROM
	(SELECT * FROM emp WHERE salary>5000) t1,dep t2 
WHERE
	t1.dept_id=t2.id;

10事务

一个包含多个步骤的操作,要么成功,要么失败

START TRANSACTION;//开启事务
……
COMMIT;//提交

1)事务提交的两种方式

(1)自动提交

mysql默认自动提交,一个增、删、改操作时,会自动提交一次事务

(2)手动提交

需开启事务再提交,oracle默认是手动提交

2)修改事务提交的方式

(1)查看

SELECT @@autocommit;

1为自动提交,0为手动提交

(2)修改

SET @@autocommit=0;

3)事务的四大特征

原子性:不可分割的最小单位,要么成功要么失败

持久性:提交后会持久性保存

隔离性:事务之间相互独立

一致性:数据操作前后总量不变

4)事务隔离级别

(1)事务操作存在的问题

脏读:一个事务读取到另一个事务没有提交的数据

不可重复读:同一事务,两次读到的数据不同

幻读:一个事务操作数据表中的所有记录,另一个事务添加一条数据,则第一个事务读不到自己的修改

(2)隔离级别

隔离级别 存在问题
read uncommitted 脏读、不可重复读、幻读
read committed(oracle默认) 不可重复读、幻读
repeatable(mysql默认) 幻读
serializable

级别从小到大,安全性越来越高,效率越来越低

(3)查询隔离级别

SELECT @@tx_isolation;

(4)设置隔离级别

SET GLOBAL TRANSACTION ISOLATION LEVAL 级别字符串;

11管理用户

1)查看用户

USE mysql;
SELECT host,user,password FROM user;

2)创建用户

CREATE user '用户名'@'主机名' IDENTIFIED BY '密码';

3)删除用户

DROP user '用户名'@'主机名';

4)修改密码

UPDATE user SET password=PASSWORD('新密码') WHERE user='用户名';

5)忘记root密码

(1)停止mysql,net stop mysql;

(2)使用无验证方式启动mysql,mysql --skip -grant-tables

(3)在cmd中输入mysql,无需输入账号密码进入

(4)改密码

(5)重启mysql

6)查看权限

SHOW GRANTS FOR '用户名'@'主机名';

7)授予权限

GRANT 权限列表 ON 数据库名,表名 TO '用户名'@'主机名';

//授予全部权限
GRANT All ON *.* TO 'zhanghuan'@'%';

权限分别是select,delete,update,all

8)撤销权限

REVOKE 权限列表 ON 数据库名,表名 FROM '用户名'@'主机名';

JDBC

简单来说,java语言操作数据库。官方定义一套操作所有关系型数据库的规则(接口),由各个数据库厂商实现这套接口,提供给开发者驱动数据库的jar包。

1快速入门

(1)导入jar包

复制jar包到新建的libs文件夹,add as library

(2)注册驱动

(3)获取数据库连接对象Connection

(4)定义sql

(5)获取执行sql语句的对象statement

(6)执行sql,接收返回结果

(7)处理结果

(8)释放资源

2常用对象

对象
DriverMannager 驱动管理对象
Connection 数据库连接对象
Statement 执行sql的对象
ResultSet 结果集对象
PreparedSteatment 执行sql的对象

3DriverMannager

(1)注册驱动

//driver类的成员方法
static void registerDriver(Driver driver);

mysql5之后的驱动可省略注册

//源码摘取自driver
static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
//写入该句则完成注册
Class.forName("com.mysql.jdbc.Driver");

(2)获取数据库连接

static Connection getConnection(String url,String user,String password);

url格式 jdbc:mysql://localhost:3306/db3,连接本机数据库可省略localhost:3306

4Connection

(1)获取执行sql的对象

Statement createStatement();
PreparedStatement PrepareStatement(String sql);

(2)获取数据库连接

开启:setAutoCommit(boolean autoCommit),参数欸false,开启事务

提交:commit()

回滚:rollback()

5Statement

(1)boolean execute(String sql)

执行任何sql语句,不常用

(2)int executeUpdate(String sql)

执行DML语句(insert,update,delete)。执行DDL时,返回值为0;返回值为影响的行数,可通过影响的行数判断是否执行成功,返回值>0执行成功,反之执行失败。

(3)ResultSet executeQuery(String sql)

执行DQL语句(select)

6ResultSet结果集对象

//游标向下移动一行,判断当前位置是否位于最后一行,如果是返回值false
boolean next();

//获取数据,可传入两种类型的参数,传入int类型时,该参数代表列号;传入String类型时,该参数代表列名
int getInt(参数);
String getString(参数);
import java.sql.*;

public class TestCalculator {
    public static void main(String[] args) throws ClassNotFoundException {
        //注册
        Class.forName("com.mysql.jdbc.Driver");
        try (Connection con = DriverManager.getConnection("jdbc:mysql:///test1","root","")) {//连接数据库

            String sql="select * from student";
            //获取执行sql的对象
            Statement st=con.createStatement();
            //执行sql语句
            ResultSet rs=st.executeQuery(sql);
            while (rs.next()){
                System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3)+" "+rs.getString(4)+" "+rs.getString(5));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

7PreparedSteatment

在拼接sql时,当有一些sql特殊关键字参数与字符串拼接时,会造成安全问题,此时使用PreparedSteatment来解决

PreparedStatement Connection.PrepareStatement(String sql);
import java.sql.*;

public class TestCalculator {
    public static void main(String[] args) throws ClassNotFoundException {
        //注册
        Class.forName("com.mysql.jdbc.Driver");
        try (Connection con = DriverManager.getConnection("jdbc:mysql:///test1","root","")) {//连接数据库

            String sql="select * from student where id=?";
            
            //获取执行sql的对象
            PreparedStatement st=con.prepareStatement(sql);
            //给问号赋值
            st.setString(1,"1");
            //执行sql语句
            ResultSet rs=st.executeQuery();
            while (rs.next()){
                System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3)+" "+rs.getString(4)+" "+rs.getString(5));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

8JDBCutils

(1)获取配置文件路径

import java.net.URL;

public class JDBCutils {
    public static void main(String[] args) {
        ClassLoader cl=JDBCutils.class.getClassLoader();
        URL res=cl.getResource("jdbc.properties");//jdbc.properties文件必须在根目录下才可读出
        String path=res.getPath();
        System.out.println(path);// /C:/Users/admin/IdeaProjects/untitled1/out/production/untitled1/jdbc.properties
    }
}

(2)完整实现

//配置文件jdbc.properties
url=jdbc:mysql:///test1
user=root
password=
driver=com.mysql.jdbc.Driver
//JDBCutils
import java.io.FileReader;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

public class JDBCutils {
    static  String url=null;
    static String user=null;
    static String password=null;
    static String driver=null;
    static{
        try {
            //获取配置文件路径
            ClassLoader cl=JDBCutils.class.getClassLoader();
            URL res=cl.getResource("jdbc.properties");//jdbc.properties文件必须在根目录下才可读出
            String path=res.getPath();

            //读取配置文件
            Properties p=new Properties();
            p.load(new FileReader(path));
            url=p.getProperty("url");
            user=p.getProperty("user");
            password=p.getProperty("password");
            driver=p.getProperty("driver");

            //注册驱动
            Class.forName(driver);
        }catch (Exception e){
            System.out.println(e);
        }
    }
    public static Connection getConnection(){//获取连接
        Connection con=null;
        try {
            con = DriverManager.getConnection(url, user, password);
        }catch (Exception e){
            System.out.println(e);
        }
        return con;
    }

    public static void close(ResultSet res, Statement st,Connection conn){//释放资源
        if(res!=null){
            try {
                res.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
//使用JDBCutils
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Hello{
    public static void main(String[] args) {
        Connection con=JDBCutils.getConnection();
        PreparedStatement st=null;
        ResultSet rs=null;

        String sql="select * from student where id=?";
        try{
            st = con.prepareStatement(sql);
            st.setString(1,"2");
            rs=st.executeQuery();
            while (rs.next()){
                System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3)+" "+rs.getString(4));
            }
        }catch (Exception e){
            System.out.println(e);
        }finally {
            JDBCutils.close(rs,st, con);
        }
    }

}

9事务

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

public class Hello{
    public static void main(String[] args) {
        Connection con=JDBCutils.getConnection();
        Statement st=null;
        ResultSet rs=null;


        try{
            con.setAutoCommit(false);//开启事务
            st = con.createStatement();
            int res1=st.executeUpdate("update employee set salary=salary+500 where id=1");
            System.out.println(res1);
            int res2=st.executeUpdate("update employee set salary=salary-500 where id=2");
            System.out.println(res2);
            con.commit();//提交事务
        }catch (Exception e){
            try {
                con.rollback();//回滚事务
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            System.out.println(e);
        }finally {
            JDBCutils.close(rs,st, con);
        }
    }

}

10数据库连接池

当初始化后,容器被创建,容器会申请一些连接对象,当用户访问数据库时,从池中取出连接对象进行连接;用户访问完后,将连接对象归还给容器

(1)c3p0

//1.导入两个jar包,注意需先导入mysql驱动包
//2.定义配置文件,名称c3p0.properties或c3p0-config.xml,放在src即可
//3.获取连接对象new ComboPooledDataSource()
//4.获取连接getConnection
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

public class Hello{
    public static void main(String[] args) {
        DataSource ds = new ComboPooledDataSource();//创建数据库连接池
        Connection con=null;
        Statement st=null;
        ResultSet rs=null;
        try{
            con=ds.getConnection();//获取连接
            System.out.println(con);
            st=con.createStatement();
            rs=st.executeQuery("select * from student");
            while (rs.next()){
                System.out.println(rs.getString(1));
            }
        }catch (Exception e){
            System.out.println(e);
        }finally {
            JDBCutils.close(rs,st,con);
        }
    }

}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 这是默认配置信息 -->
    <default-config>
        <!-- 连接四大参数配置 -->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/test1</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password"></property>
        <!-- 池参数配置 -->
        <property name="acquireIncrement">3</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">2</property>
        <property name="maxPoolSize">10</property>
    </default-config>

    <!-- 专门为oracle提供的配置信息 -->
    <named-config name="oracle-config">
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">123</property>
        <property name="acquireIncrement">3</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">2</property>
        <property name="maxPoolSize">10</property>
    </named-config>
</c3p0-config>

(2)druid

//1.导入jar包
//2.定义配置文件
//3.加载配置文件
//4.配置文件手动传入,并获取连接对象
//5.获取连接
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class Hello{
    public static void main(String[] args) throws IOException {
        Properties p=new Properties();
        p.load(Hello.class.getClassLoader().getResourceAsStream("druid.properties"));
        try {
            DataSource ds = DruidDataSourceFactory.createDataSource(p);//创建连接对象
            Connection con=ds.getConnection();//获取连接
            Statement st=con.createStatement();
            ResultSet rs=st.executeQuery("select * from student");
            while (rs.next()){
                System.out.println(rs.getString(1));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

封装工具类

# druid.properties文件的配置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test1
username=root
password=
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大超时时间
maxWait=3000
//DRUIDutils
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

public class DRUIDutils {
    static Properties p=new Properties();
    static{
        try {
            p.load(DRUIDutils.class.getClassLoader().getResourceAsStream("druid.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection(){//获取连接
        Connection con=null;
        try {
            con=getDataSource().getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return con;
    }
    public static DataSource getDataSource() throws Exception {//获取datasource
        return DruidDataSourceFactory.createDataSource(p);
    }
    public static void close(ResultSet res, Statement st, Connection conn){//释放资源
        if(res!=null){
            try {
                res.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(Statement st, Connection conn){//释放资源重载方法
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}
//测试DRUIDutils
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

public class Hello{
    public static void main(String[] args) throws IOException {
        Connection con=null;
        Statement st=null;
        ResultSet rs=null;
        try {
            con=DRUIDutils.getConnection();//获取连接
            st=con.createStatement();
            rs=st.executeQuery("select * from student");
            while (rs.next()){
                System.out.println(rs.getString(1));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DRUIDutils.close(rs,st,con);
        }
    }

}

(3)SpringJDBC

Spring框架对JDBC的简单封装,提供一个JDBCTemplate对象简化JDBC的代码

//1.导入jar包,共5个
//2.创建JdbcTemplate对象,依赖于数据源DataSource
JdbcTemplate template=new JdbcTemplate(ds)
//3.调用JdbcTemplate的方法进行CRUD操作
import org.springframework.jdbc.core.JdbcTemplate;

public class Hello{
    public static void main(String[] args) throws Exception {
        JdbcTemplate template=new JdbcTemplate(DRUIDutils.getDataSource());
        String sql="update employee set salary=5000 where id=?";
        int rs=template.update(sql,1);//执行sql
        System.out.println(rs);
    }

}

常用CRUD操作

update();//执行DML语句,增删改语句
queryFormap();//查询结果封装乘map集合,结果集长度只可是1
queryForList();//查询结果封装成list集合
query();//查询结果封装成JavaBean对象
queryForObject();//查询结果封装成对象,查询聚合函数
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;
import java.util.Map;

public class Hello{
    public static void main(String[] args) throws Exception {
        JdbcTemplate template=new JdbcTemplate(DRUIDutils.getDataSource());
        String sql=null;

        //queryForMap
        sql="select * from student where id=1";
        Map<String, Object> m=template.queryForMap(sql);
        System.out.println(m);
        //{id=1, male=男, name=周杰伦, math=78, english=81}

        //queryForList
        //将每一条记录封装成一个map集合,再将map集合封装到list集合中
        sql="select * from student";
        List<Map<String,Object>> list_of_map=template.queryForList(sql);
        System.out.println(list_of_map);

        //query
        //将数据封装成javabean对象并返回一个javabean对象的list集合
        sql="select * from student";
        List<student> list_of_bean=template.query(sql,new BeanPropertyRowMapper<student>(student.class));
        System.out.println(list_of_bean);

        //queryForObject
        //执行包含聚合函数的sql
        sql="select count(*) from student";
        Long count=template.queryForObject(sql,Long.class);
        System.out.println(count);
    }
    @Test//可单独运行方法
    public void run(){
        System.out.println("hello");
    }

}

Tomcat

1JAVAEE

java语言在企业计数规范的总和,一共规定了12项大的规范

2主流服务软件

软件名 特点
weblogic oracle公司,收费
websophere ibm公司,收费
jboss jboss公司,收费
tomcat apache组织,免费

3tomcat文件目录

目录 功能
bin 二进制执行文件
conf 配置文件
lib 依赖jar包
logs 日志文件
temp 临时文件
webapps 存放的web项目
work 运行时数据

4启动和关闭

1)启动

bin目录下,运行startup.bat,在localhost:8080访问

可能遇到问题

(1)黑窗口一闪而过

未正确配置java环境变量JAVA_HOME

(2)启动报错

8080端口被占用,要么杀进程,要么在conf.server.xml修改端口号

2)关闭

bin目录下,运行shutdown.bat或者在服务窗口ctrl+c

5部署

1)将项目放到webapps目录下

项目可打包成war,将war包防止到webapps目录下

2)配置conf/server.xml文件

新增一行<Contex docBase="D\hello" path"/hehe/">

3)在conf/Catalina/localhost下创建任意名的xml文件

文件内容是<Contex docBase="D\hello" >,连接中访问的path路径就是xml的文件名

6动态项目的目录结构

--项目根目录
	--WEB-INF
	--web,xml//web项目的核心配置文件
	--classes//放置字节码文件的目录
	--lib//放置依赖的jar包

7将tomcat部署到IDEA中

1)配置tomcat

run->edit configrations->templates->tomcat server->local

把tomcat的安装路径设置上

2)创建JAVAEE项目

file->new project->java enterprise

选中web application后点击下一步

输入项目名点击下一步,然后运行


servlet

运行在服务器上的小程序,本质上是一个接口

1快速开始

1.创建javaee项目
2.定义类,实现Servlet
3.实现抽象方法
4.配置url,如配置web.xml文件
//创建一个实现Servlet的类
import javax.servlet.*;
import java.io.IOException;

public class abc implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service……");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}
//web.xml将新建的实现类注册进去,并配置url
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>demo01</servlet-name>
        <servlet-class>abc</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>demo01</servlet-name>
        <url-pattern>/demo01</url-pattern>
    </servlet-mapping>
</web-app>

2执行原理

1)服务器接收客户端浏览器的请求后,会解析请求的url路径,获取访问的servlet资源路径

2)查找web.xml文件是否由对应的内容,如果由有将其对应的类加载到内存,并执行其方法

3servlet生命周期

1)被创建

创建后会执行一次实现类的init方法,默认情况是在第一次访问实现类对应的url时才会被创建,这里可以在web.xml文件中配置成服务器启动时创建

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>demo01</servlet-name>
        <servlet-class>abc</servlet-class>
        <load-on-startup>2</load-on-startup><!--正数或0表示服务启动时加载类,负数表示访问url时加载类-->
    </servlet>
    <servlet-mapping>
        <servlet-name>demo01</servlet-name>
        <url-pattern>/demo01</url-pattern>
    </servlet-mapping>
</web-app>

2)提供服务

每次调用servlet时,其service方法被执行一次

3)被销毁

在servlet被销毁前,执行destroy方法

总之,servlet是单例的,不要哦在servlet中定义变量,即使定义了,也不要修改值

4注解配置url

在servlet3.0中,支持注解配置url,不再需要web.xml

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

@WebServlet("/demo")//注解配置url
public class abc implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init……");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service……");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

5IDEA中的tomcat

1)IDEA为每一个tomcat部署的项目单独建立一份配置文件

2)IDEA会将工作空间里的项目复制到tomcat上部署

3)WEB-INF目录下的资源无法被访问

4)端点调试,需要使用小虫子启动

5servlet的实现类

1)GenericServlet

该类是servlet的实现类,有一个抽象方法service

//源码摘取
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

2)HttpServlet

常需重写doGet和doPost方法

//源码摘取
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getMethod();
    long lastModified;
    if (method.equals("GET")) {
        lastModified = this.getLastModified(req);
        if (lastModified == -1L) {
            this.doGet(req, resp);
        } else {
            long ifModifiedSince;
            try {
                ifModifiedSince = req.getDateHeader("If-Modified-Since");
            } catch (IllegalArgumentException var9) {
                ifModifiedSince = -1L;
            }

            if (ifModifiedSince < lastModified / 1000L * 1000L) {
                this.maybeSetLastModified(resp, lastModified);
                this.doGet(req, resp);
            } else {
                resp.setStatus(304);
            }
        }
    } else if (method.equals("HEAD")) {
        lastModified = this.getLastModified(req);
        this.maybeSetLastModified(resp, lastModified);
        this.doHead(req, resp);
    } else if (method.equals("POST")) {
        this.doPost(req, resp);
    } else if (method.equals("PUT")) {
        this.doPut(req, resp);
    } else if (method.equals("DELETE")) {
        this.doDelete(req, resp);
    } else if (method.equals("OPTIONS")) {
        this.doOptions(req, resp);
    } else if (method.equals("TRACE")) {
        this.doTrace(req, resp);
    } else {
        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[]{method};
        errMsg = MessageFormat.format(errMsg, errArgs);
        resp.sendError(501, errMsg);
    }

}

6url定义

1)/xx

2)/xx/xx

3)*.do


HTTP

定义的客户端与服务端通信的数据格式

特点:

基于TCP/IP协议,默认端口为80,基于请求、响应模型,无状态

版本

1.0每次请求、响应会重新建立连接,1.1复用连接

1请求消息的数据格式

1)请求行

2)请求头

3)请求空行

4)请求体

2GET和POST

GET请求的参数在请求行的url中,url里的数据长度有限制

POST请求的参数在请求体中,长度无限制

3请求头中的refer

标记该请求的跳转来源,用于防盗链和统计

4request对象基础体系结构

ServletRequest	接口
	|继承
HttpServletRequest	接口
	|继承
org.appache.catalina.connector.RequestFacade	tomcat创建的实现类

5request的功能

1)获取获取请求消息数据

import javax.servlet.*;
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("/demo1")
public class abc extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1)获取请求方式
        String m=req.getMethod();
        System.out.println(m);//GET
        //2)获取虚拟目录
        String cp=req.getContextPath();
        System.out.println(cp);//
        //3)获取servlet路径
        String sp=req.getServletPath();
        System.out.println(sp);///demo1
        //4)获取get请求参数
        String qs=req.getQueryString();
        System.out.println(qs);//null
        //5)获取uri
        String uri=req.getRequestURI();
        StringBuffer url=req.getRequestURL();
        System.out.println(uri);//demo1
        System.out.println(url);//http://localhost:8081/demo1
        //6)获取协议版本
        String ptc=req.getProtocol();
        System.out.println(ptc);//HTTP/1.1
        //7)获取客户机ip地址
        String rma=req.getRemoteAddr();
        System.out.println(rma);//0:0:0:0:0:0:0:1
    }

}

2)获取请求头数据

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet("/demo1")
public class abc extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Enumeration<String> headernames=req.getHeaderNames();
        while (headernames.hasMoreElements()){
            System.out.println(headernames.nextElement());//获取请求头的键
        }
        /*
        host
        connection
        cache-control
        upgrade-insecure-requests
        user-agent
        ……
         */
    }

}
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet("/demo1")
public class abc extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String agent=req.getHeader("user-agent");//获取请求头某个键对应的值
        System.out.println(agent);
        //Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36 Edg/81.0.416.62
    }

}

3)获取请求体数据

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

@WebServlet("/demo1")
public class abc extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("dopost....");
        BufferedReader br=req.getReader();//获取字符输入流
        char[] data=new char[1024];
        int len;
        while ((len=br.read(data))!=-1){
            System.out.println(data);
        }
        //username=2323&password=232323
    }


}
import javax.servlet.*;
        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("/demo1")
public class abc extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("dopost....");
        ServletInputStream sis=req.getInputStream();//获取字节输入流
        byte[] b=new byte[1024];
        int len;
        while ((len=sis.read(b))!=-1){
            System.out.println(new String(b));
        }
        //username=2323&password=232323
    }

}

4)其他方法

import javax.servlet.*;
        import javax.servlet.annotation.WebServlet;
        import javax.servlet.http.HttpServlet;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

@WebServlet("/demo1")
public class abc extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取参数值
        String username=req.getParameter("username");
        System.out.println(username);//zhanghuan
        
        //获取参数值的数组
        String[] vls=req.getParameterValues("hobby");
        System.out.println(Arrays.toString(vls));//[basketball, football]
        
        //获取参数的键集合
        Enumeration<String> names=req.getParameterNames();
        while (names.hasMoreElements()){
            System.out.println(names.nextElement());
        }
        /*
        username
        password
        hobby
         */
        
        //获取参数的键值对
        Map<String,String[]> mp=req.getParameterMap();
        Set<Map.Entry<String, String[]>> set=mp.entrySet();
        for(Map.Entry<String,String[]> i:set){
            System.out.println(i.getKey()+"="+Arrays.toString(i.getValue()));
        }
        /*
        username=[zhanghuan]
        password=[2323]
        hobby=[basketball, football]
         */
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

//不管是get方式还是post方式,这些获取参数的方法都生效

5)乱码问题

在tomcat8以上,get方式提交的值无乱码问题,而post方式提交的值存在乱码

需要在doPost方法里加上

req.setCharacterEncoding("utf-8");

6)请求转移

一种在服务器内部的资源跳转方式,因此浏览器的url不会发生变化,由于在服务器内部转移,所以只能转发到服务器内部的servlet对象,转发过程中是服务器自发与客户端浏览器无关

req.getRequestDispatcher("/demo2").forward(req,resp);

7)共享数据

域对象:一个有作用范围的对象,可在范围内共享数据

request域:一次请求范围,一般用于请求转发的多个资源中共享数据

//设置共享值
void setAttribute(String var1, Object var2);

//获取共享值
Object getAttribute(String var1);

//删除共享值
void removeAttribute(String var1);

//获取整个web应用的域对象
ServletContext getServletContext();

6)登陆案例

//目录结构
--src
	--dao
		userdao.java
	--doMain
		user.java
	--uitil
		JDBCutils.java
	--web
		loginServlet.java
	duoid.properties
--web
	--WEB-INFO
		--lib//这里放jar包,如果放错位置控制太不会报错,页面上会报500错误
	index.jsp
//JDBCutils.java
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;

public class JDBCutils {
    static Properties p=new Properties();
    static {
        try {
            InputStream is=JDBCutils.class.getClassLoader().getResourceAsStream("druid.properties");
            p.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static DataSource getDataSource() {
        DataSource ds=null;
        try {
            ds = DruidDataSourceFactory.createDataSource(p);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ds;
    }
    public static Connection getConnection(){
        Connection con=null;
        try {
            con=getDataSource().getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return con;
    }
}
//Userdao.java
package dao;

import doMain.User;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import util.JDBCutils;

public class Userdao {
    private JdbcTemplate tmplate=new JdbcTemplate(JDBCutils.getDataSource());
    public User login(User loginuser){
        try {
            String sql="select * from user where username=? and password=?";
            User user=tmplate.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class),loginuser.getUsername(),loginuser.getPassword());
            return user;
        } catch (DataAccessException e) {
            e.printStackTrace();
            return null;
        }
    }
}
//user.java
package doMain;

public class User {
    private Integer id;
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
//LoginServlet.java
package web;

import dao.Userdao;
import doMain.User;

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("/loginservlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User loginuser=new User();
        loginuser.setUsername(req.getParameter("username"));
        loginuser.setPassword(req.getParameter("password"));
        Userdao dao=new Userdao();
        System.out.println(loginuser);
        User user=dao.login(loginuser);
        if(user==null){
            System.out.println("登陆失败");
        }else {
            System.out.println("登陆成功");
        }
        System.out.println("dopost");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}
<!--index.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Login</title>
  </head>
  <body>
  <form action="/login_war_exploded/loginservlet" method="post">
    <input type="text" name="username" placeholder="username"><br>
    <input type="text" name="password" placeholder="password"><br>
    <input type="submit" value="提交">
  </form>
  </body>
</html>

7)BeanUtils

主要提供了对于JavaBean进行各种操作,比如对象,属性复制等等。使用前需导入导入commons-beanutils-1.8.3 包和commons-logging-1.1.3 包

注意方法 描述
public static void setProperty(Object bean, String name, Object value) 设置指定属性的值
public static String getProperty(Object bean, String name) 获取指定属性的值
public static void populate(Object bean, Map<String, ? extends Object> properties) 将map数据拷贝到javabean中
import doMain.User;
import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;


public class test {
    @Test
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        User user=new User();
        Map<String,String> map=new HashMap<>();//Map的第二个泛型可以是数组,执行populate时会取数组的第一个元素
        map.put("username","zhanghuan");
        map.put("password","123456");
        BeanUtils.populate(user,map);
        System.out.println(user);//User{id=null, username='zhanghuan', password='123456'}
    }
}
/*
JavaBean
1.类必须被public修饰
2.必须提供空参数构造器
3.成员变量必须使用private修饰
4.提供公共的setter和getter方法
*/

6响应

由响应行、响应头、响应空行、响应体组成

1)响应行格式

协议/版本 响应状态码 状态码解释

2)状态码表示信息

状态码 含义
1XX 服务器接收客户端消息,但没完成,等待一段时间后,发送1XX状态码
2XX 成功
3XX 重定向,304表示访问缓存,302表示重定向
4XX 客户端错误,404请求路径没有对应的资源,405请求方式没有对应的doXX方法
5XX 服务器错误,500服务器内部错误

6)响应头

(1)Content-Type

指定数据格式及编码

(2)Content-disposition

指定以什么格式打开响应体,in-line当前页面打开,attachment;filename=xxx以附件形式打开响应体,用于下载

7)响应体

传输的数据

8)获取虚拟目录

req.getContextPath();

9)重定向

package web;

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("/index")
public class indexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //方式一
        /*
        resp.setStatus(302);
        resp.setHeader("location",req.getContextPath()+"/login");
         */
        
        //方式二
        resp.sendRedirect(req.getContextPath()+"/login");

    }
}

特点:

地址栏里的地址会发生变化,可访问其他站点的资源,发送了两次请求

10)字符输出流

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;
import java.io.PrintWriter;

@WebServlet("/login")
public class loginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置writer的字符编码
        resp.setCharacterEncoding("utf-8");

        //给客户端指定字符编码方式一
        //resp.setHeader("Content-Type","text/html;charset=utf-8");

        //给客户端指定字符编码方式二
        resp.setContentType("text/html;charset=utf-8");

        //获取writer
        PrintWriter pr=resp.getWriter();
        //向响应体写入数据
        pr.write("这是登陆页");
    }
}

11)验证码案例

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Random;

public class randomPic {
    static String[] strs=null;

    public static String getRandomString(){
        String str="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        String result_str="";
        Random rd=new Random();
        for (int i = 0; i <4 ; i++) {
            int num=rd.nextInt(61);
            result_str+=Character.toString(str.charAt(num));
        }
        return result_str;
    }

    public static void drawImg(String str,OutputStream os,int width,int height){
        Random rd=new Random();

        //创建画布
        BufferedImage img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        //创建画笔
        Graphics g=img.createGraphics();
        //设置画笔颜色
        g.setColor(Color.PINK);
        //用画笔填充画布
        g.fillRect(0,0,width, height);

        //在画布上写字符串
        g.setColor(Color.BLUE);
        Font f=new Font(null,Font.PLAIN,25);
        g.setFont(f);//设置字体大小
        strs=str.split("");//获取随机字符串
        for (int i = 0; i <strs.length ; i++) {
            g.drawString(strs[i],width/4*i+8,rd.nextInt(height/4)+height/2);
        }

        //在画布上画干扰线
        for (int i = 0; i <10 ; i++) {
            g.drawLine(rd.nextInt(width),rd.nextInt(height),rd.nextInt(width),rd.nextInt(height));
        }

        //将图片写入到流中
        try {
            boolean jpg = ImageIO.write(img, "jpg", os);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
import doMain.randomPic;

import javax.imageio.ImageIO;
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("/login")
public class loginServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String str=randomPic.getRandomString();//获取随机字符串
        System.out.println(str);
        ImageIO.setUseCache(false);//使用内存来存储临时文件,无此句可能报错
        randomPic.drawImg(str,resp.getOutputStream(),100,50);

    }
}

12)ServletContex

代表整个web应用,可以和程序容器(服务器)通信

该对象有3个功能:

获取MIME类型,域对象,获取文件正式路径

(1)获取ServletContex对象

//1.通过req对象获取
req.getServletContex();
//2.通过HttpServlet对象获取
this.getServletContex();

(2)获取MIME类型

MIME类型:互联网通信中定义的一种文件类型,格式为:大类型/小类型

String getMimeType(String var1);

(3)域对象方法

//设置属性
void setAttribute(String var1, Object var2);
//获取属性
Object getAttribute(String var1);
//删除属性
void removeAttribute(String var1);

(4)获取正式路径

String getRealPath(String var1);

注意:这里获取路径的文件默认是web目录下的所有文件,如果要获取的文件是src下的,需要进入WEB-INF/classes目录下获取

13)下载案例

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

@WebServlet("/download")
public class downloadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext sc=this.getServletContext();
        String contenttype=sc.getMimeType("2.jpg");
        resp.setContentType( contenttype);
        resp.setHeader("content-disposition","attachment;filename=2.jpg");
        //文件名如果是中文需要特殊将中文进行编码

        String path=sc.getRealPath("/imgs/1.jpg");
        InputStream is= new FileInputStream(path);
        ServletOutputStream os=resp.getOutputStream();
        int len;
        byte[] b=new byte[1024];
        while ((len=is.read(b))!=-1){
            os.write(b,0,len);
        }
        os.close();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

7cookie

客户端会话技术

//创建cookie
Cookie c=new Cookie("name","zhanghuan");
//发送cookie
response.addCookie(c);
//获取cookie
Cookie[] cs=request.getCookies();

1)特点:

(1)一次可发送多个cookie

(2)默认情况下,浏览器关闭cookie销毁

(3)可设置cookie的存活时间

Cookie c=new Cookie("name","zhanghuan");
c.setMaxAge(30);//设置cookie存活时间为30秒
//setMaxAge的参数为int类型,负数表示删除cookie,0表示浏览器关闭cookie销毁

(4)cookie的键值对在tomcat8之后支持中文,但最好还是不要存中文,可对中文进行编码

URLEncoder.encode(String s, String enc);//s是需要编码的字符串,enc是编码格式,返回一个字符串
URLDecoder.decode(String s, String enc);//s是需要解码的字符串,enc是解码格式,返回一个字符串

2)cookie共享问题

(1)默认情况下,同一服务器下的不同项目不可共享,如果要共享需设置

setPath(String path);
//传入path为“/”,表示共享

(2)默认情况下,不同服务器下的项目不可共享,如果要共享需设置

setDomain(String path);
//与path匹配上的一级域名,可共享该cookie

8session

服务端会话技术

//创建session
HttpSession s=request.getSession();
//设置session
s.setAttribute("name","zhanghuan");
//获取session值
s.getAttribute("name");
//删除session
s.removeAttribute("name");

1)存活时间

在服务器存放的session数据能保留30分钟,服务器关闭或session对象调用invalidate方法会销毁session,要修改session在服务器的存活时间,需要到conf目录下的web.xml修改配置

<session-config>
	<session-timeout>30</session-timeout>
</session-config>

2)服务器或浏览器关闭后对session的影响

(1)浏览器关闭

session依赖于cookie,浏览器关闭后未设置过期时间的cookie会被清除掉,再次打开浏览器发送请求后,服务器读取不到名为JSESSIONID的cookie,便把该次请求当作一个新请求并重新分配session;要解决这个问题,需要给名为JSESSIONID的cookie设置过期时间

(2)服务器关闭

在IDEA中session会发生变化,在tomcat中会自动完成session的钝化、活化操作,session不会发生变化

3)session和cookie的比较

session cookie
位置 服务器 浏览器
可存入的数据大小 无限制 有限制
安全性 安全 不安全

9验证码登陆案例

//获取动态验证码的servlet服务
package web;

import midware.randomPic;

import javax.imageio.ImageIO;
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("/getvalidpicServlet")
public class getvalidpicServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String str= randomPic.getRandomString();
        System.out.println(str);
        HttpSession s=request.getSession();
        s.setAttribute("validcode",str);
        ImageIO.setUseCache(false);
        randomPic.drawImg(str,response.getOutputStream(),100,50);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
<!--登陆页面-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <form action="<%=request.getContextPath()%>/login">
    <table>
      <tr>
        <td>用户名</td>
        <td><input type="text" name="username"></td>
      </tr>
      <tr>
        <td>密码</td>
        <td><input type="text" name="password"></td>
      </tr>
      <tr>
        <td>验证码</td>
        <td><input type="text" name="validcode"></td>
      </tr>
      <tr>
        <td colspan="2"><img id="vpic" alt=""></td>
      </tr>
      <tr>
        <td colspan="2"><input id="sub" type="submit"></td>
      </tr>
    </table>
  </form>
  </body>
</html>
<script>
  window.onload=function () {
    picsrc()
    document.getElementById("vpic").onclick=function () {
      picsrc()
    }
  }
  function picsrc() {
    var vpic=document.getElementById("vpic")
    var date=new Date()
    vpic.setAttribute("src","<%=request.getContextPath()%>/getvalidpicServlet?a="+date.getSeconds())
  }
</script>
//登陆的servl服务
package web;

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("/login")
public class loginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取传过来的数据
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        String validcode=req.getParameter("validcode");

        //获取session中存放的验证码
        HttpSession s=req.getSession();
        String session_valid=(String)s.getAttribute("validcode");

        //响应
        resp.setCharacterEncoding("utf-8");
        resp.setHeader("Content-Type","text/html;charset=utf-8");
        if(validcode.equalsIgnoreCase(session_valid)){
            if(username.equals("zhanghuan") && password.equals("123")){
                resp.getWriter().write("欢迎你,"+"zhanghuan");
            }else{
                resp.getWriter().write("登陆失败,账号或密码错误");
            }
        }else{
            resp.getWriter().write("登陆失败,验证码错误");
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

10JSP

java服务端页面,可定义html标签,也可定义java代码,本质是一个servlet

1)指令

用于配置jsp页面,导入资源文件

格式

<%@ 指令名 属性名=属性值…… %>

指令分类

(1)page

配置jsp页面常用4个属性

属性 功能
contentType 设置页面的MIME属性
import 导入java包
errorPage 发生错误时跳转到另一个目标页面
isErrorPage 标志该页面是否可使用exception对象

(2)incluede

页面包含

<%@include file="abc.jsp"%>

(3)taglib

导入标签库资源

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

2)脚本

<% 代码 %>//定义内容在service方法中
<%! 代码 %>//定义内容在jsp转换的java类中的成员位置
<%= 代码 %>//定义内容输出到页面上

3)注释

<!---->//只能注释html代码
<%---->//能注释所有内容,注释后的内容不会在页面上出现

4)内置对象

不需要创建,可直接使用的对象

对象名 真实类型 说明
pageContex pageContex 可获取其他8个对象,当前页面数据共享
request HttpServletRequest 一次请求数据共享
session HttpSession 一次会话数据共享
application ServletContext 所有用户数据共享
response HttpServletResponse 响应对象
page Object 当前页面对象
out JspWriter 输出对象
config ServletConfig Servlet配置对象
exception Throwable 异常对象

out和response.getWriter().write()都能输出到页面上,但后者输出的内容在前者之前


MVC

解释 实现元素 功能
M 模型 JavaBean 查询数据库,封装对象
V 视图 JSP 展示数据
C 控制器 Servlet 获取用户输入,调用模型,将数据交给视图进行展示

优点

耦合性低,方便维护,重用性高

缺点

使得项目架构复杂


EL表达式

Expression Langarage表达式语言,用于替换、简化JSP中的java代码

忽略el表达式

1)设置jsp中page的属性isELIgnored=""设置为true

2)\${ 表达式 }

1运算符

类型 详细
算术运算符 + - * / div % mod
比较运算符 > < == >= <= !=
逻辑运算符 & and | or ! not
定运算符 empty

empty用于判断字符串、集合、数组对象是否为null并且长度为0,是返回为true

${ empty list }
${ not empty list }

2域对象获取值

//1.从指定域中获取指定值
${域名称.键名}

//2.依次从最小域中找是否有对应键的值
${键名}

3获取对象属性值

${对象.属性名}

4隐式对象

el表达式有11个隐式对象,可通过pageContext获取其他8个对象

${ pageContext.request.contextPath }

JSTL

JavaServer Pages Tag Library jsp标准标签库,用于替换、简化JSP中的java代码

使用步骤:

1.导入jstl的两个java包

2.JSP中通过指令引入标签库<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

3.页面中使用标签

1if

相当于java中的if语句

<c:if test="true">
  该标签内test属性值为true,会显示出来
</c:if>
<c:if test="false">
  该标签内test属性值为false,不会显示出来
</c:if>

2choose

相当于java中的switch语句

<%
request.setAttribute("num",1);
%>
<c:choose>
  <c:when test="${num==1}">星期一</c:when>
  <c:when test="${num==2}">星期二</c:when>
  <c:when test="${num==3}">星期三</c:when>
  <c:when test="${num==4}">星期四</c:when>
  <c:when test="${num==5}">星期五</c:when>
  <c:when test="${num==6}">星期六</c:when>
  <c:when test="${num==7}">星期七</c:when>
  <c:otherwise>输入错误</c:otherwise>
</c:choose>

3forEach

相当于java中的for语句

<%--1.完成重复性操作--%>
  <table>
    <th> 变量i的值</th>
    <th> 循环次数</th>
    <th> 循环索引</th>
    <c:forEach begin="1" end="5" var="i" step="1" varStatus="s">
      <tr>
        <td> ${i}</td>
        <td> ${s.count}</td>
        <td> ${s.index}</td>
      </tr>
    </c:forEach>
  </table>
  <%--运行结果
    变量i的值	循环次数	循环索引
    1	1	1
    2	2	2
    3	3	3
    4	4	4
    5	5	5
  --%>

<%--2.遍历容器--%>
  <%
  String[] ar={"a","b","c"};
  request.setAttribute("ar",ar);
  %>
<c:forEach items="${ar}" var="str">
  ${str}<br>
</c:forEach>

Filter过滤器

访问服务器资源时,过滤器可以将请求拦截下来,完成同一特殊功能。用于完成一些通用操作,如:登陆验证、统一编码处理、敏感字符过滤等

1创建步骤

1)创建类实现Filter接口

2)实现抽象方法,在doFilter里调用chain.doFilter(req, resp),放行请求

3)将该实现类进行注册

<!--web.xml-->
<filter>
	<filter-name>allFilter</filter-name>
	<filter-class>allFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>allFilter</filter-name>
    <url-pattern>*</url-pattern>
</filter-mapping>
//另一种方式时在类上面新增注解
@WebFilter(filterName = "/*")

2生命周期方法

方法名 解释
init 服务器启动后,会创建Filter对象,然后调用init方法,只执行一次,用于加载资源
doFilter 每次请求被拦截资源时,会执行,执行多次
destroy 在服务器关闭后,Filter对象被销毁;如果是正常关闭,会执行destroy方法,只执行一次,用于释放资源

3拦截路径配置

1)具体资源路径

@WebFilter("/index.jsp")

2)拦截目录

@WebFilter("/user/*")

3)后缀名拦截

@WebFilter("*.jsp")

4拦截方式配置

1)注解上配置

@WebFilter(value="*.jsp",dispatcherTypes=DispatcherType.REQUEST)

2)web.xml配置

<filter>
	<filter-name>allFilter</filter-name>
	<filter-class>allFilter</filter-class>
	<dispatcher>REQUEST</dispatcher>
</filter>

3)拦截类型

类型 含义
DispatcherType.REQUEST 直接访问时过滤
DispatcherType.FORWARD 转发访问时过滤
DispatcherType.INCLUDE 包含时过滤
DispatcherType.ERROR 发生错误时过滤
DispatcherType.ASYNC 异步时过滤

5多个过滤器执行的先后顺序

1)注解配置的过滤器

安装类名字符串比较规则比较,值小的先执行

2)web.xml配置

谁定义在上面,谁先执行

6过滤器验证登陆案例思路

请求过来时,看这个请求访问的资源,如果是登陆相关的就通过,如果不是就判断用户登陆状态;如果用户已登陆,放行通过;为登陆,跳转到登陆界面

代理模式

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@WebFilter("/*")
public class allFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        ServletRequest proxy_req=(ServletRequest)Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //利用代理对参数进行过滤
                if(method.getName().equals("getParameter")){
                    String value=(String) method.invoke(req,args);
                    value=value.replaceAll("zhanghuan","张欢");
                    System.out.println(value);
                    return value;
                }
                return method.invoke(req,args);
            }
        });
        chain.doFilter(proxy_req,resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

监听器

监听观察某个事件(程序)的发生情况,当被监听的事件真的发生了的时候,事件发生者(事件源) 就会给注册该事件的监听者(监听器)发送消息,告诉监听者某些信息,同时监听者也可以获得一份事件对象,根据这个对象可以获得相关属性和执行相关操作

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;//监听ServletContext的创建和销毁
import javax.servlet.annotation.WebListener;

@WebListener//注册监听器
public class ServletContexListener1 implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {//监听到创建后执行
        System.out.println("ServletContext创建了……");
        
        //获取初始化参数
        String str=sce.getServletContext().getInitParameter("name");
        System.out.println(str);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {//监听到销毁后执行

    }
}

注册监听器也可在web.xml中配置

<listener>
    <listener-class>com.ygj.control.onLineCount</listener-class>
</listener>

初始化参数

在web.xml中配置

<init-param>
    <param-name>username</param-name>
    <param-value>moonlit</param-value>
</init-param>

可通过HttpServlet.getInitParameter(String Param)拿到


Redis

非关系型数据库,键值对数据,value有5种不同的数据类型,分别是字符串(string),哈希(hash),列表(list),集合(set),有序集合(sortedset)

1操作

类型 操作 命令 说明
字符串(string) set key value
get key
del key
哈希(hash) hset key field value
hget key field
hgetall key 获取所有的field和value
hdel key field
列表(list) lpush key value
rpush key value
lrange key start end
lpop key
rpop key
集合(set) sadd key value
smembers key
srem key value
有序集合(sortedset) zadd key score value
zrange key start end
zrem key value
通用 keys * 查看所有的键
type key 查看某一键的数据类型
del key 删除键

2持久化

将内存种的数据保存到硬盘上

(1)RDB

默认方式,无需配置。一定时间间隔中,检测key变化情况,然后持久化数据

save 900 1
save 300 10
save 60 10000
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed

(2)AOF

日志记录方式,可以记录每一条命令的操作,每一次命令操作后,持久化数据

# enable the append only mode: when this mode is enabled Redis will append
# every write operation received in the file appendonly.aof.
appendonly no#改为yes

# appendfsync always
appendfsync everysec#每秒持久化一次
# appendfsync no

3Jedis

通过java操作redis数据库,需导入2个jar包

(1)各类型数据操作

import redis.clients.jedis.Jedis;

import java.util.Map;

public class test01 {
    static Jedis j=new Jedis("localhost",6379);//空参数默认值"localhost",6379
    
    public static void main(String[] args) throws InterruptedException {
        string_value();
        hash_value();
        list_value();
        set_value();
        sortedset_value();
        j.close();//关闭连接

    }
    public static void string_value() throws InterruptedException {
        //设置键值对
        j.set("name","asdsdsd");
        System.out.println(j.get("name"));//asdsdsd

        //删除键值对
        j.del("name");
        System.out.println(j.get("name"));//null

        //设置具有过期时间的键值对
        j.setex("age", 5, "25");
        System.out.println(j.get("age"));//25
        Thread.sleep(10000);
        System.out.println(j.get("age"));//null
        j.close();
    }
    public static void hash_value(){
        //设置
        j.hset("myhashset","name","zhanghuan");
        System.out.println(j.hget("myhashset","name"));//zhanghuan

        //获取map
        Map<String,String> map=j.hgetAll("myhashset");
        System.out.println(map);//{name=zhanghuan, age=25}

        //删除map下的键
        j.hdel("myhashset","name","age");
        System.out.println(j.hgetAll("myhashset"));//{}
    }
    public static void list_value(){
        //压入
        j.lpush("mylist","a");
        j.rpush("mylist","b");
        System.out.println(j.lrange("mylist",0,-1));//[a, b]

        //弹出
        System.out.println(j.lpop("mylist"));//a
        System.out.println(j.rpop("mylist"));//b
    }
    public static void set_value(){
        //存
        j.sadd("myset","大毛");
        j.sadd("myset","小毛");

        //取
        System.out.println(j.smembers("myset"));//[小毛, 大毛]

        //删除指定值
        j.srem("myset","大毛");
        System.out.println(j.smembers("myset"));//[小毛]sortedset
    }
    public static void sortedset_value(){
        //存
        j.zadd("mysortedset",10,"小黄");
        j.zadd("mysortedset",18,"小黑");
        j.zadd("mysortedset",14,"小白");

        //取
        System.out.println(j.zrange("mysortedset",0,-1));//[小黄, 小白, 小黑]

        //删除
        j.zrem("mysortedset","小白");
        System.out.println(j.zrange("mysortedset",0,-1));//[小黄, 小黑]
    }
}

(2)封装连接池对象

#jedis.properties
host=127.0.0.1
port=6379
MaxTotal=50
MaxIdle=10
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;


import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class JedisPoolUtils {
    private static JedisPool pool;
    static {
        //读取配置文件
        InputStream is=JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
        Properties p=new Properties();
        try {
            p.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //创建配置对象
        GenericObjectPoolConfig<String> config=new GenericObjectPoolConfig<>();
        config.setMaxIdle(Integer.parseInt(p.getProperty("MaxIdle")));
        config.setMaxTotal(Integer.parseInt(p.getProperty("MaxTotal")));

        //生成连接池
        pool=new JedisPool(config,p.getProperty("host"),Integer.parseInt(p.getProperty("port")));
    }
    public static Jedis getJedis(){
        return pool.getResource();
    }
}

4省市二级联动案例

1)数据库

类型 字段名 解释
int CRI_ID id
varchar CRI_CODE 6位编码,区分省、市,前3位代表省,第4位代表市,后2位代表取
varchar CRI_NAME 省、市、区名称

2)目录结构

-src
	-dao
		-impl
			cn_regionDaoimpl.java
		cn_regionDao.java
	-domain
		Cn_region.java
	-service
		-impl
			getCitiesServiceimpl.java
			getProvincesServiceimpl.java
		getCitiesService.java
		getProvincesService.java
	-utils
		JDBCutils.java
		JEDISPOOLutils.java
	-web
		getCitiesServlet.java
		getProvincesServlet.java
	duid.properties
	jedis.properties
	
web
	-WEB-INF
		-lib
		web.xml
	index.jsp

3)文件内容

//cn_regionDaoimpl.java
package dao.impl;

import dao.cn_regionDao;
import doMain.Cn_region;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import utils.JDBCutils;

import java.util.ArrayList;
import java.util.List;

public class cn_regionDaoimpl implements cn_regionDao {
    static private JdbcTemplate template=new JdbcTemplate(JDBCutils.getDataSource());

    @Override
    public List<Cn_region> findAll() {

        List<Cn_region> list=template.query("select CRI_ID,CRI_CODE,CRI_NAME from cn_region_info",new BeanPropertyRowMapper<Cn_region>(Cn_region.class));
        return list;
    }

    @Override
    public List<Cn_region> getProvinces() {
        List<Cn_region> alllist=findAll();
        List<Cn_region> r_list=new ArrayList<Cn_region>();
        String CRI_CODE_last_3;//最后3位,用来判断是否是省
        for (Cn_region item:
                alllist) {
            CRI_CODE_last_3=item.getCRI_CODE().substring(3,6);
            if(CRI_CODE_last_3.equals("000")){
                r_list.add(item);
            }
        }
        return r_list;
    }

    @Override
    public List<Cn_region> getCites(String province_code) {
        List<Cn_region> alllist=findAll();
        List<Cn_region> r_list=new ArrayList<Cn_region>();
        String CRI_CODE_first_3;//截取前三位
        String CRI_CODE_4;//截取第四位
        String CRI_CODE_last_2;//最后两位
        for (Cn_region item:
                alllist) {
            CRI_CODE_first_3=item.getCRI_CODE().substring(0,3);
            CRI_CODE_4=item.getCRI_CODE().substring(3,4);
            CRI_CODE_last_2=item.getCRI_CODE().substring(4,6);
            if( CRI_CODE_first_3.equals (province_code) && !CRI_CODE_4.equals ("0") && CRI_CODE_last_2.equals("00")){
                r_list.add(item);
            }
        }
        return r_list;
    }

    @Override
    public List<Cn_region> getCity_areas() {
        return null;
    }
}

//cn_regionDao.java
package dao;

import doMain.Cn_region;

import java.util.List;

public interface cn_regionDao {
    public List<Cn_region> findAll();
    public List<Cn_region> getProvinces();
    public List<Cn_region> getCites(String province_code);
    public List<Cn_region> getCity_areas();
}
//Cn_region.java
package doMain;

public class Cn_region {
    private int CRI_ID;
    private String CRI_CODE;
    private String CRI_NAME;

    public int getCRI_ID() {
        return CRI_ID;
    }

    public String getCRI_CODE() {
        return CRI_CODE;
    }

    public String getCRI_NAME() {
        return CRI_NAME;
    }

    public void setCRI_ID(int CRI_ID) {
        this.CRI_ID = CRI_ID;
    }

    public void setCRI_CODE(String CRI_CODE) {
        this.CRI_CODE = CRI_CODE;
    }

    public void setCRI_NAME(String CRI_NAME) {
        this.CRI_NAME = CRI_NAME;
    }

    @Override
    public String toString() {
        return "Cn_region{" +
                "CRI_ID=" + CRI_ID +
                ", CRI_CODE='" + CRI_CODE + '\'' +
                ", CRI_NAME='" + CRI_NAME + '\'' +
                '}';
    }
}

//getCitiesServiceimpl.java
package service.impl;

import dao.impl.cn_regionDaoimpl;
import doMain.Cn_region;
import org.codehaus.jackson.map.ObjectMapper;
import redis.clients.jedis.Jedis;
import service.getCitiesService;
import utils.JEDISPOOLutils;

import java.io.IOException;
import java.util.List;

public class getCitiesServiceimpl implements getCitiesService {
    @Override
    public String findAll(String province_code){
        cn_regionDaoimpl dao=new cn_regionDaoimpl();
        List<Cn_region> list=dao.getCites (province_code);
        //序列化
        ObjectMapper maper=new ObjectMapper();
        String json= null;
        try {
            json = maper.writeValueAsString (list);
        } catch (IOException e) {
            e.printStackTrace ( );
        }
        return json;
    }

    @Override
    public String findAllJson(String province_code){
        //先从redis中查找数据,如果没有再从数据库中查找
        Jedis jedis= JEDISPOOLutils.getJedis ();
        String cities= jedis.hget ("cities",province_code);
        String json;
        if(cities==null || cities.length ()==0){
            json=findAll (province_code);
            jedis.hset("cities",province_code,json);
        }else {
            json=cities;
        }
        jedis.close ();
        return json;
    }
}

//getProvincesServiceimpl.java
package service.impl;

import dao.impl.cn_regionDaoimpl;
import doMain.Cn_region;
import org.codehaus.jackson.map.ObjectMapper;
import redis.clients.jedis.Jedis;
import service.getProvincesService;
import utils.JEDISPOOLutils;

import java.io.IOException;
import java.util.List;

public class getProvincesServiceimpl implements getProvincesService {
    @Override
    public String findAll() {
        cn_regionDaoimpl dao=new cn_regionDaoimpl();
        List<Cn_region> list=dao.getProvinces ();
        //序列化
        ObjectMapper maper=new ObjectMapper();
        String json= null;
        try {
            json = maper.writeValueAsString (list);
        } catch (IOException e) {
            e.printStackTrace ( );
        }
        return json;
    }

    @Override
    public String findAllJson(){
        //先从redis中查找数据,如果没有再从数据库中查找
        Jedis jedis=JEDISPOOLutils.getJedis ();
        String provinces= jedis.get ("provinces");
        String json;
        if(provinces==null || provinces.length ()==0){
            json=findAll ();
            jedis.set("provinces",json);
        }else {
            json=provinces;
        }
        jedis.close ();
        return json;
    }
}

//getCitiesService.java
package service;

import doMain.Cn_region;

import java.io.IOException;
import java.util.List;

public interface getCitiesService {
    public String findAll(String province_code);
    public String findAllJson(String province_code);
}

//getProvincesService.java
package service;

import doMain.Cn_region;

import java.io.IOException;
import java.util.List;

public interface getProvincesService {
    public String findAll();
    public String findAllJson();
}

//getCitiesServlet.java
package web;

import service.impl.getCitiesServiceimpl;


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("/getCitiesServlet")
public class getCitiesServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {

        //获取省份id
        String province_id=request.getParameter ("province_id").substring (0,3);

        //获取数据
        getCitiesServiceimpl getCitiesServiceimpl=new getCitiesServiceimpl();
        String json=getCitiesServiceimpl.findAllJson (province_id);

        //返回
        response.setCharacterEncoding ("utf-8");
        response.setHeader ("contentype","application/json;charset=utf-8");
        response.getWriter ().write (json);
    }

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

//getProvincesServlet.java
package web;

import service.impl.getProvincesServiceimpl;

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;
import java.util.List;

@WebServlet("/getProvincesServlet")
public class getProvincesServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取数据
        getProvincesServiceimpl getProvincesServiceimpl=new getProvincesServiceimpl();
        String json=getProvincesServiceimpl.findAllJson ();

        //返回
        response.setCharacterEncoding ("utf-8");
        response.setHeader ("contentype","application/json;charset=utf-8");
        response.getWriter ().write (json);

    }

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

<%--index.jsp--%>
<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2020/5/1
  Time: 下午 06:32
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <div class="container">
    <div class="row">
      <div class="col-md-3">
        <div class="panel">
          <div class="panel-body">
            <select class="form-control" id="select1">
            <option value="0">请选则</option>
          </select>
          </div>
        </div>
      </div>
      <div class="col-md-3">
        <div class="panel">
          <div class="panel-body">
            <select class="form-control" id="select2">
              <option value="0">请选则</option>
            </select>
          </div>
        </div>
      </div>
    </div>
  </div>
  </body>
  <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  <script>
    <%--"${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/getProvincesServlet"--%>
    $(function () {
      $.ajax({
        method:"post",
        url:"http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/getProvincesServlet",
        success:function (data) {
          //cri_ID,cri_NAME,cri_CODE
          console.log(data)
          obj=JSON.parse(data)
          for(var i=0;i<obj.length;i++){
            $("#select1").append("<option value="+obj[i]["cri_CODE"]+">"+obj[i]["cri_NAME"]+"</option>")
          }
        }
      })
      $("#select1").change(function () {
        province_id=$(this).val()
        if($(this).val()!="0"){
          $.ajax({
            methd:"get",
            data:{"province_id":province_id},
            url:"http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/getCitiesServlet",
            success:function (data) {
              obj=JSON.parse(data)
              $("#select2").children().remove()
              $("#select2").append('<option value="0">请选则</option>')
              for(var i=0;i<obj.length;i++){
                $("#select2").append("<option value="+obj[i]["cri_CODE"]+">"+obj[i]["cri_NAME"]+"</option>")
              }
            }
          })
        }else{
          $("#select2").children().remove()
          $("#select2").append('<option value="0">请选则</option>')
        }
      })
    })
  </script>
</html>


Maven

为解决项目开发过程中,导入jar包冲突问题。通过导入jar包的坐标,编译时从仓库中找到对应的包完成编译

1安装及环境配置

1)解压安装包

2)配置环境变量

MAVEN_HOME指向解压后的安装包位置

注意:

maven运行需要java环境,确保环境变量中有JAVA_HOME

2仓库

分为本地仓库、远程仓库、中央仓库。maven会先在本地仓库找jar包,如未找到再去远程仓库找。

要为maven指定本地仓库,需要在conf/setting.xml中配置

<localRepository>C:\Users\admin\Desktop\maven_repository</localRepository>

路径中不要有中文

3)配置镜像

修改目录下conf下的setting.xml在mirrors标签中,添加文末这一段

<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

3maven项目标准目录结构

src/main/java	//核心代码部分
src/main/resources	//配置文件部分
src/test/java	//测试代码部分
src/test/resources	//测试配置文件部分
src/main/webapp	//静态资源,如js,css,图片等

4命令

命令 功能
mvn clean 删除编译信息
mvn compile 编译项目
mvn test 编译测试代码
mvn package 项目编译,并打成war包
man install 项目编译,并打成war包,将项目复制到本地库

5maven生命周期

生命周期 操作 命令
清理生命周期 清除项目编译信息 clean
默认生命周期 编译 compile
测试 test
打包 package
安装 install
发布 deploy
站点生命周期

6项目对象模型pom和依赖管理模型dependency

1)项目对象模型pom

包含项目自身信息,项目运行依赖的jar包,项目运行环境信息(JDK,tomcat信息)

2)依赖管理模型dependency

包含公司组织名称、项目名、版本号

<dependency>
			<!-- junit的项目名称 -->
			<groupId>junit</groupId>
			<!-- junit的模块名称 -->
			<artifactId>junit</artifactId>
			<!-- junit版本 -->
			<version>4.9</version>
			<!-- 依赖范围:单元测试时使用junit -->
			<scope>test</scope>
</dependency>

7idea下使用maven

1)配置集成环境

在settins搜索maven,将maven的解压目录配置上即可

2)创建maven项目

(1)新建项目,选中maven,点击下一步,填写项目信息,在点击下一步至finish

(2)创建项目后,里面缺少的标准目录需要自行添加,并标记为标准目录

(3)webapp的目录,需要进行静态标记。project structure->modules->web->web resource dirictory中加入包的目录

注意

创建web项目,勾选create from archetype后,选中org.apache.maven.archetpes.maven-archetype-webapp

3)项目中导入jar包

在pom.xml中配置

 <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
    </dependency>
  </dependencies>

注意

如果导入jar包后,项目中仍无法识别导入的包,可能与maven版本有关系

4)设置包的作用范围

 <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <!--导入的servlet和jsp的包要配置范围provided-->

这里的scope里包含的就是包的作用范围

依赖范围 编译 测试 运行 案例
compile 影响 影响 影响 spring-core
test 影响 junit
provided 影响 影响 servlet-api
runtime 影响 影响 jdbc驱动
system 影响 影响 本地的maven库之外的库

5)配置运行环境

 <build>
      <plugins>
          <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
              <path>/</path> <!--项目访问路径。当前配置的访问是localhost:9090/, 如果配置是/aa,则访问路径为localhost:9090/aa -->
              <port>9090</port>
              <uriEncoding>UTF-8</uriEncoding><!-- 非必需项 -->
            </configuration>
          </plugin>
      </plugins>
  </build>

运行时指向tomcat7:run,不然会报错

标签:java,String,javax,2020,import,servlet,public,JAVAWEB
From: https://www.cnblogs.com/sylvesterzhang/p/18089849

相关文章

  • 2020-5-23-Spring
    简介、耦合、控制反转、依赖注入、注解方式反转控制和依赖注入、Spring整合Junit、银行转账案例、代理、AOP面向切面编程、JDBCTemplate简介1核心内容IOC反向控制、AOP面向切面编程2优势方便解耦,简化编程AOP编程支持声明式事务支持方便程序的测试方便集成各种优秀的框架......
  • 2020-1-1-GIT使用经验汇总
    Git安装、创建版本库、同步操作、分支管理、查看版本记录、远程仓库相关操作安装sudoapt-getinstallgit设置用户名和邮箱gitconfig--globaluser.name"yourname"gitconfig--globaluser.email"[email protected]"创建版本库1.创建目录mkdirlearniggitcdlearn......
  • 2020-1-3-ekyll安装使用
    jekyll是一个博客工具,将markdown文件生成静态网页,具有较好的迁移性。安装依赖包RubyRubyGemsNodeJsPython安装完成后重启电脑配置gem镜像$gemsources--addhttps://gems.ruby-china.com/--removehttps://rubygems.org/$gemsources-l安装jeckyll-pagination$g......
  • 2020-1-9-js新特性第二部分
    实现map函数、嵌套函数和闭包、arguments对象、函数参数、关系操作符、遍历数组foreach方法、map对象与object对象的区别、promise对象、生成器实现Map函数传入处理函数和数组,返回值为将数组内的数按照函数规则处理后新生成的数组window.onload=function(){functio......
  • 2020-1-6-js新特性第一部分
    var、let、const的区别,对象被定义为常量不受保护,自执行函数注意事项,箭头函数特点,对象扩展运算和对象解构运算,label语句,for...in...和for...of...的区别var、let、const的区别varletconst作用域函数花括号内全局是否可重复声明可以不可以不可以声明后是......
  • 基于JavaWeb的鲜牛奶订购系统—开题报告
    一、研究解决的问题本系统使用Java作为开发语言,基于JavaWebB/S架构进行设计,前端技术HTML+CSS+Vue,后端技术SpringBoot,数据库采用MySql,并在win10操作平台完成开发。系统用户角色分为订奶用户,供奶商家和管理员三个部分。其中,订奶用户可以浏览住址所在区的订奶信息,登录后拥有管理......
  • 9.JavaWeb& javaScript基础
    目录导语:一、JavaWeb概述二、JavaScript基础概念:功能:1.基本语法(1)与html结合方式(2)注释(3)数据类型(4)变量(5)运算符(6)流程控制语句:(7)JS特殊语法:案例:99乘法表2.基本对象(1)Function:函数(方法)对象(2)Array:数组对象(3)Boolean(4)Date:日期对象(5)Math:数学对象(6)Number(7)String(8......
  • AST20201网络编程
    Web编程实验JavaScript-2将所有完成的html、CSS和图像文件保存在名为lab4_yourname的文件夹中,其中包含的子文件夹必要时组织文件夹。压缩文件夹并在截止日期前提交给Moodle在Moodle中指定。注意,您需要确保所有图像路径/链接都可以工作适当地放在您提交的文件夹和子文件夹中。任务......
  • 探索GHD22020-2充电模块的奥秘
    随着科技的飞速发展,充电技术也在不断创新和进步。GHD22020-2高频充电模块,以其卓越的性能和高效的充电效率,成为了市场上的一颗璀璨明珠。GHD22020-2高频充电模块采用了先进的高频充电技术,能够实现快速、稳定的充电效果。相比传统充电方式,它拥有更高的充电效率,大大缩短了充电时......
  • YUV与RGB转换公式(BT601、BT709、BT2020)
    1、在图像处理中经常需要对图像数据进行转换,最常见的莫过于YUV2RGB。并且这个转化在不同的标准下有不同的转化公式。2、如果公式不匹配,则会导致转换后的图像效果有偏差。3、full_range下Y\U\V的取值范围都为[0,255];limit_range(也叫part_range)下Y的取值范围为[16,235],UV的......