java学习

目录

8、标识符

9、变量与注释

10、运算符

11、scanner

12、逻辑语句

13、方法(函数):

14、面向对象

15、构造方法constructor

16、内存底层

17、this

18、static

19、package、import(java的类管理机制)

20、继承

21、组合

22、Object 类

23、(可以看作是)父类对象的引用super

24、封装encasulation

25、多态polymorphism

26、抽象方法、抽象类

27、接口interface(定义规范、标准,int a等默认是常量) 

28、内部类(定义在一个类内部的类)

 29、数组

30、String类 (不可变Unicode字符序列)

 31、可变字符序列(StringBuilder和StringBuffer,idea缩写SB)

32、包装类(把基本数据类型变成对象) 

33、Date(时间),DateFormat(时间和字符串转化),Calendar类

34、异常机制

35、可视化bug追踪

 36、List容器

37、Set容器 

38、map容器(成对存储,按照键值对的形式存储)

39、自定义泛型(给容器贴标签)

40、IO流技术(input,out)

41、Apache IO包(官网http://www.apache.org)

42、多线程(JAVA语言的重要特性)

43、线程同步(synchronized,产生同步阻塞)

44、生产者消费者模式 

 45、线程池

46、ThreadLocal(面试常见)

 47、学习要求

48、设计模式

49、动态代理模式 

 ​编辑

 51、注意事项

52、JDBC

53、maven 

54、MyBatis

55、web核心

56、jsp

57、会话跟踪技术 

58、Filter&Listener

59、AJAX 

60、json 

61、vue 

 62、Element

63、案例及代码 

1、JVM是java virtual machine,即虚拟计算机,负责java程序的运行,针对不同操作系统有不同版本的JVM,实现java的跨平台 

2、JRE是java runtime environment,即java运行时环境,包括JVM加上核心类库和相关文件

3、JDK是java development kit,即java开发工具包,包括JRE和java开发工具,下载链接Oracle 甲骨文中国 | 云应用和云平台

4、安装容易出事故,一个是要下载jdk安装,我下成了jre导致不能编译,郁闷了好久,另一个是把txt文件名改成java之后还要用记事本打开写代码,我第一次本来装对了,但是因为不知道用记事本打开写代码,以为没装好,卸载重装,这才装成了jre

5、运行:用文本编辑器编写java源程序(.java)(用记事本写代码)->用编辑器把源程序编译成字节码文件(javac这个文件)->用虚拟机解锁运行(java calss文件,不能加后缀名)

6、引用方法(每次改完代码要保存才能生效)

public class hello {(此时文件名必须是hello.java,这里要区分大小写)

public static void main (string[]args){(建立main方法,然后在里面写代码)

System.out.println("hello");(注意两个英文点和分号,S要大写,有ln表示换行,直接print()不换行)

}

}

7、dos命令与idea使用(右键win图标点运行输cmd)

cd 文件夹或文件名:进入此目录

cd,,:进入父目录

dir:查看目录下文件 

cls:清空屏幕

上,下键:切换之前输入的命令

tab:快速补齐命令

idea下载:JetBrains: Essential tools for software developers and teams

ctrl+z:返回上一步

左键所在行行标:添加断点,再点一下取消断点

按run下面绿色按钮:调试,执行到断点自动停下,会显示调用的栈帧和当前变量的值,调试按钮在栈帧显示的上面

7166c3a73cba4125a7b3832d19cd934a.png

点run条上下拉或ctrl+shift+alt+上下键:上下移动

右键任一类或scr等->open in->explorer:打开文件所在位置

双击shift:查找所有项目和所有类

ctrl+shift+alt+t:先选中一个变量名再用,可以给这个变量重命名(万能重构键)

ctrl+f:文件内查找,在所有的文件中查找再加shift

ctrl+r:文件内替换,所有文件再加shift

选中一个变量名+alt+一直按j:第一行开始,一行一行选中这个变量,从最后一行开始取消选中则按alt+shift+一直按j

alt+左键拖拽:多列选中

f2:定位到下一个错误(上下按错误或警告的严重程度区分)

shift+f2:定位到上一个错误

表达式后面打.if:用if包围表达式,.while同理

new表达式后面打.var:快速声明变量并赋值

选中表达式+ctrl+alt+t:选择代码块包围这个表达式

alt+insert:选择生成类中的方法

光标在有错代码的那行+alt+enter:系统给出修改建议

ctrl+e:展开最近打开的文件

alt+7:展现文件结构

ctrl+shift+t:切换到测试类

eclipse下载:2020-12 R | Eclipse Packages

alt+/:呼出自动补齐

 syso:System.out.println();

ctrl+/:注释与取消注释

ctrl+shift+/:星号注释

ctrl+shift+\:取消星号注释

ctrl+shift+o:自动导包

alt+shift+s:呼出生成get方法代码,相当于idea的生成,constructor生成构造器

ctrl+z:代码回退

ctrl+y:代码前进

左键双击行号:打断点

f6:单步执行,步过

f5:步入方法内部执行

f7:执行完当前方法的代码并跳回main

f8:自动执行到下一个断点所在处,如果没有断点则全部执行完

点击右上角图标:切换视图

8、标识符

不能出现除字母,数字,_,$外的符号,且开头不能是数字,区分大小写,不能是java的关键字

表示类名,每个单词首字母大写,如GoodMen(注意系统类如String也是按这个规则命名

表示方法和变量,第一个单词小写,从第二个单词开始首字母大写,如eatFood(如int)

可以用汉字命名(加上汉字就要去调成ANSI,否则报错)

9、变量与注释

本质是可操作的存储空间,空间位置确定,可以通过变量名访问这个空间操纵变量的值,数据类型定义空间大小

byte一位整型,同char,float(单精度类型,精确到7位小数),double(双精度类型,小数默认是这个类型,给float赋值加F,如3.14F)同c

314E-2即314*10^-2

short,int,long同c语言,整数默认为int,如果要写超过int范围的数要在后面加L,如7000000000000L,可以用1L乘其他数转为long

0b开头数字是二进制,0是八进制,0x是十六进制

自动类型转换是表数小的转成表数大的,如long(8字节)可以转为float(4字节),整形赋值只要不超过对象的表数范围就能直接赋值

强制转换char a=(char)('c'+2),结果是'e'

unicode编码包括世界上所有字符,两个字节表示一个字符,包括英文,UTF-8是变长编码,英文1字节,汉字3字节

char是字符型,数据应该是一个unicode字符,如'高',转义字符如'\\'表示反斜杠,'\"'表示引号,其他同c

字符串是String类,用“”赋值

boolean是布尔型,占1或4字节,只能赋值true和false,不能用0,1代替,有boolean flag,用if(flag)和if(flag==true)判断是一样的,打印也是true,false

//后的所在行都是注释(单行注释)

被/*   */包起来的是注释(多行注释,不能嵌套)

/**    */围起来的也是注释,通常写在类前面,后期可以用来生成API(文档注释)

10、运算符

+,-,*,/,整数除法向下取整,a++(值为原来的a),--a(值为减1的a)同c

a+=b为a=a+b,-=,*=,/=,%=同c

==,!=,>,<,>=,<=同c

逻辑与&(两个操作数为true才为true),逻辑或|(两个操作数有一个是true就是true),逻辑非!(取反),短路与&&(只要有一个是false就是false),短路或||(只要有一个是true就是true),逻辑异或^(相同为false,不同为true)

按位取反~,按位与&(3&7=3,与是二进制编码同时为1才取1,结果是11,3的编码),按位或|,按位异或(注意不是乘方!3^7=4)^,左移(乘2)<<,右移(除2取商)>>

字符串加法"结果是"+3+4会把3,4转成字符串再连接,结果是"结果是34",想要正确的加法运算可以"结果是"+(3+4)

a=x?b:c,x为true则a=b,x为false则a=c

11、scanner

在声明类前写

import java.util.Scanner;

再在main里写(建立变量后可以读输入)

Scanner scanner=new Scanner(System.in);

String username=scanner.nextLine();读取一行输入

使用nextInt等不读也不跳过分隔符(如\n)后,想用nextLine,要先用一个nextLine读掉分隔符

1.sc.next()

1)一定是在输入有效字符串后才结束输入。一但输入有效字符后,遇到空格键(\s)、Tab键(\t)或Enter键(\r)直接结束输入。

2)从1)我们可以知道sc.next()输入法是不能接收:空格键(\s)、Tab键(\t)或Enter键(\r)字符的

2.sc.nextLine()
1)回车键(\r)前的所有字符都能接收,遇到回车键(\r)结束输入;

2)从1)可知sc.nextLine是不能接收回车键的(\r),即一个sc.nextLine只接收一行字符串不含回车键;

要读取char,我们使用next().charAt(0)

9edf8ee376384e048b35aa0a97dc56a3.png

3d5d7a011f5949398e18b46e80d5c90a.png

12、逻辑语句

if(){}else{},if(){}else if(){}else{}用法同c

switch(a){

case 1:

System.out.println("hello");

break;

default:break;

}和c一样,a=1会执行这个case的代码,如果没有break还会执行default的代码,但是a可以是整数,枚举,字符串case "cc":

char a='a';
switch (a)
{
default:
case 'b':
System.out.println("b");
break;
case 'c':
System.out.println("c");
break;
}

正常且结果是b

while(){},for(int i=0;i<100;i++){}用法同c

break退出循环,continue退出本次循环并继续下一次循环

13、方法(函数):

public static int add(int a,int b){}

可以写在main后面,main前面不需要声明,此外除了要加前缀,和c完全一样,注意写return

方法重载需要形参类型,个数,或者顺序不同,只有返回值,或者形参名称不同不构成重载

14、面向对象:基本特征封装、继承、多态、抽象

程序运行三步骤:编辑源程序、编译生成字节码、解释运行字节码(编译器负责,javac.exe,一个类生成一个.class文件,在同一个java文件中也生成多个)

类存在磁盘中,对象、正在执行的东西存在内存中

通过new把类加载到内存中

分实体类(存储数据)和过程类(处理数据)

3ea9e4e870814cea94753fd05ed7c311.png

初始化:把类从磁盘加载到内存->立即初始化静态成员(包括静态块)->在堆中开辟空间,初始化非静态成员

右键最上面的文件夹,new一个Module(项目下的子项目),然后在它的src上右键new一个class

140e2562fb154791a6409b516d5a27e5.jpg

 类包括属性field,负责静态特征(数据),整形默认0,浮点0.0,字符'\u0000',布尔false,引用null

方法method,负责动态行为(操作数据)

构造器consttuctor,负责初始化对象

每个类可以有一个自己的main方法(每个类都是独立的java文件且类名与文件名相同),idea打一个m即可召唤

在main里可以创建这个类(class)的变量(即对象,英文object或instance)

注意声明对象要调用构造函数,然后才能改值

student stu01=new student();

方法前不加static,则每个对象都有这个方法,调用如stu01.study(),这个函数可以直接使用对象的成员,不用stu01.name,如果加static,则不出现在每个对象中,调用如study();

d341c3d0ca574f3b92ae83afcf1a1380.jpg

 同属于一个src下的类可以互相调用,如在一个类的main中声明另一个类的对象,并调用这个类的函数,或者继承另一个类的对象作为自己的成员

15、构造方法constructor

用于对象的初始化,java要用new关键字调用构造器(方法名必须与类名相同),返回值只能设定为本类且不能写return(只写类名,不写返回值类型,void也不能写),如果没有定义构造器,编译器会给一个无参的构造器,如果有则编译器不会自动添加

构造方法的重载和普通方法一样

public class point {
    double x;
    double y;
    String mz;
    public  point(double x1,double y1)
    {

        x=x1;y=y1;
    }
    public  point(double x1,double y1,String id)
    {

        x=x1;y=y1;mz=id;
    }
    public static void main(String[] args) {
        point p1=new point(1.23,2.34);
        System.out.println(""+p1.x+p1.y+p1.mz);
        point p2=new point(1.23,2.34,"tkl");
        System.out.println(""+p2.x+p2.y+p2.mz);
    }
}

a899ddfce9c841d49c24b84fdc1fac6d.png

 分配对象空间,并将对象成员初始化为0或null->执行属性值的显式初始化->执行构造方法,初始化对象->返回对象的地址给相关的变量

16、内存底层

栈存方法的信息,堆存对象,堆包括方法区(也叫静态区,存类的信息)

栈用于描述方法执行,每个方法被调用都会创建一个栈(存局部变量、操作数、方法出口等)

栈由系统分配,速度快,是一个连续的内存空间,后进先出

JVM为每个线程创建一个栈,存该线程执行方法的信息,属于线程私有,不同线程不能共享

堆存创建好的对象和数组(如person类的对象p1的各成员,数组也是对象)

堆是不连续的内存空间,分配灵活,速度慢

JVM只有一个堆,所有线程共享

方法区是java虚拟机规范,可以有不同的实现(JDK8是元数据空间和堆结合)

方法区用来存程序中永远不变或唯一的内容(类信息(如p1.name=“数据”,则p1在main的栈中,指向name,name在堆中,“数据”在方法区中,name指向“数据”)、静态变量、字符串常量等)

方法区给每个类分配空间,存这个类的代码、静态成员(包括静态成员变量和静态成员函数)、常量池(存字符串常量等)

JVM只有一个方法区,所有线程共享

17、this

本质:当前对象的地址,在普通方法中,指向调用该方法的对象,构造方法中,指向正要初始化的对象(如构造函数形参和成员同名时,可以用this.name表示类的name成员

类的非静态方法的栈中存调用的显示参数如本对象name和默认传递的this

this的重要用法是在构造方法中调用其他构造器,且必须位于方法的第一行(注意不能调用自己类型的构造器,形成递归)

 public Person(int _age,String _name)
    {
        name=_name;
        age=_age;

    }
 public Person(String pwd,String name)
    { this(12,name);
        System.out.println(""+this.name);

        this.pwd=pwd;
        this.name=name;

    }

18、static,final

加了final则无法修改,参考:http://t.csdnimg.cn/f6dRY

用于声明静态成员变量(类变量),从属于类,只有一份,在类被载入时被显式初始化

一般用类名.类属性/方法调用

在static方法中不能直接访问非static的成员(要用p1.name访问)

可以用静态初始化块对类初始化,可以初始化static成员,不能直接访问非static成员

static String company="中南大学";

static{
company="\\湖南大学";
}

19、package、import(java的类管理机制)

package(包机制)右键scr->new->package(名字一般是域名倒着写)->所有这个package里的类在第一行要加上package com.sss; (这里的每个点代表一层package) 点这个package->new->class新建的也要

可以在不同的package里建同名的类,可以在package里再建package

不导入时访问其他包的类要写出完整包名和类名

com.sss.car car=new com.sss.car();//car类在com.sss包里,含有public int a,不写public默认私有
car.a=1;
System.out.println(car.a);

JDK中含有java.lang,包括String等类,java.awt抽象窗口工具集,java.net与网络相关操作的类,java.io提供多种输入输出功能的类,java.util实用工具类(如Date)

import(引入类)

使用其他包的类时用来避免写完整包名和类名(import这个类的完整包名+类名,或者包名.*,导入这个包的所有类),java默认导入java.lang下的所有类

如果导入两个同名的类,只能用包名+类名区分

静态导入(import static):导入指定类的静态属性和静态方法,以直接使用它们

import static java.lang.Math.*;//这里*表示导入Math类的所有静态成员

System.out.println(Math.random());//正常的调用方法
System.out.println(random()+" "+PI);

0.4456957375216152
0.9001632877614474  3.141592653589793

20、继承

一个java文件中可以有多个类,但是只有与文件同名的类的main方法能工作

public class Testextend {
public static void main(String[] args) {

System.out.println("sd");
Student a=new Student("ww");
System.out.println(a instanceof Student);//把a转换成Student实例,成功返回true,两个都成功
System.out.println(a instanceof Person);
}
}

class Person{
String name;
int height;
public void rest(){
System.out.println("xxx");
}

}
class Student extends Person//类继承语法,Java的类只能有一个父类(单继承),接口可以多继承,子类继承父类可获得父类所有属性和方法,但是父类非公开的成员不能直接访问

定义类时若没有用extends,则它的父类是java.lang,object

{

int hing;
String major;
public Student (Student name)
{
this.name="666";
this.height=3;
}

}

方法重写(直接在子类中写同名方法即可覆盖从父类继承来的方法):子类通过重写父类方法,改变自己行为,要求方法名、形参列表相同+返回值类型和声明异常类型,子类小等于父类+访问权限,子类大等于父类

fianl关键字:修饰变量时,此变量后续不能被改变

修饰方法时,此方法不能被子类重写,但是可以被重载(成为常量)

修饰类时,此类不能被继承

21、组合、包含

包含把某类对象作为自己的成员,两者关系为包含

组合把父类对象作为子类成员(注意要Person p=new person();声明成员)

可以用this.p.name访问父类成员

is a关系用继承,has a关系用组合

22、Object 类

写出

class Employee extends Object//按住ctrl,鼠标移到Object上左键进去看源码

打印地址用的是Object类的toString方法(不写时默认调用),可以参照源码修改它的返回值,注意可以直接以字符串为返回值 

e1.equal(e2)比较e1,e2是否相等,重写equal记得一定要重写hashCode()

hashcode()方法返回一个int型的哈希码,有可能是负数,在hashmap中用到

equals为true,那么,hashcode必须相等,这个规定主要是为了HasgMap在存取时不会发生悖论

23、(可以看作是)父类对象的引用super

 可以通过super.tosSring访问父类中被子类覆盖的方法或属性

一个类的构造方法的第一行如果没有显式调用super()或this(),java会默认调用super(),含义是调用父类的无参数构造方法,可以省略不写

super本质是:当前对象的父类型特征(子类创建的整个过程只创建了一个对象,实际上没有创建父类对象)

在每一次继承时,都会调用其父类的构造方法,一直到Object类,然后当前对象获得Object属性,一层层的获得父类属性

24、封装encasulation

使程序高内聚(类内部复杂的数据处理尽量自己完成,不让外部知道)、低耦合(尽量方便外部调用者的使用)、提高代码安全性、提高代码复用性

private私有,自己类才能访问(如private int a;即属性一般用private,本类的辅助性方法也是)

default没有修饰符修饰,只有同一个包的类能访问

protected可以被同一个包的类和其他包的子类访问

public可以被该项目的所有包的所有类访问(提供相应的get/set/is(bool特有的get方法)方法访问私有的属性,提供对应属性的赋值与读取操作(可以右键选生成,按ctrl再点可多选))

25、多态polymorphism

有两种方式:子类对父类方法的覆盖、同类中方法的重载

同一个方法调用,由于对象不同可能有不同行为

多态是方法的多态,不是属性的,存在的必要条件:继承、方法重写、父类引用指向子类对象(用该父类引用调用子类重写)

类Student继承自类Person,含有

public void say(){
System.out.println("ssss");
}

类sstudent继承自类Person,含有

public void say(){
System.out.println("6666");
}(这两个say()都是对Person中say方法的重写)

调用多态的类含有

static void psay(Person a)一定要调用父类对象的say方法
{
a.say();
}

public static void main(String[] args) {
Student aa=new Student();
psay(aa);
sstudent bb=new sstudent();
psay(bb);
}

结果是

ssss
6666

子类对象可以自动转为父类对象,这时只能调用父类写出来的方法。(或者再强制转为子类对象再调用)

26、抽象方法、抽象类

抽象方法使用abstract修饰,没有方法体,只有声明,定义的是“规范”,告诉子类必须给抽象方法具体的实现 

抽象类是含有抽象方法的类(加abstract定义出来),通过它可以严格限制子类的设计,使子类之间更加通用,抽象类不能通过new实例化

有抽象方法的类只能定义成抽象类,抽象类不能实例化,可以包含正常类的各种成员,只能用来被继承,抽象方法必须被子类实现 

如讲解多态时的Person类可以写作

abstract class Person{
String name;
int height;
public void rest(){
System.out.println("xxx");
}
public abstract void say();
}

一样可以实现say方法的功能

27、接口interface(定义规范、标准,int a等默认是常量) 

全面实现了规范和具体实现的分离,普通类是具体实现,抽象类(方法)是具体实现、规范,接口是规范

子类通过implements实现接口中的规范

接口不能创建实例,但可用于声明引用变量类型

一个类实现接口,必须实现接口中所有方法,这些方法只能是public的

jdk1.8(不含8)前接口只能含静态常量、抽象方法,之后可以包含普通的静态方法、默认方法

默认方法用default关键字,一个接口可以用多个默认方法(也叫扩展方法)

子类实现接口时可以调用接口中的默认方法,也可以重写(不强制要求重写,新定义时对原来的实现没有影响) 

接口中还可以定义静态方法,通过接口名调用,如果实现类中定义了同名的方法,那就是完全不同的方法了,直接属于实现类,通过类名直接调用

父类方法和接口默认方法名冲突时,父类优先

多个接口中默认方法有相同名字,子类必须重写这些默认方法

package com.sss.t;

public class car {
    public static void main(String[] args) {
        sx a=new sx();//sx类同时有两个方法
        a.fly();
        a.help();a.ff1();
        fx b=new sx();//当成fx类时不能用help方法
        b.fly();b.ff1();
        sl c2=new sx();//不能用fly和ff1,但是还能识别来自fx类的high常量
        c2.help();
        sxx d=new sxx();
        d.fly();
        d.help();
        d.testc();d.ff1();
        fx.ff2();//用接口名直接调用静态方法
        sx.ff2();//实现类中的同名方法和接口中的方法完全不同
    }
}
interface fx{
    void fly();
    int high=100;//视为常量
    default void ff1()//默认方法前加default
    {
        System.out.println("ff1");
    }
    static void ff2()
    {
        System.out.println("ff2");
    }
    default void ff3()
    {
        System.out.println("ff3");
    }
}
interface sl{
    void help();

}
interface jk{
    default void ff3(){
        System.out.println("3333");
    }
}
interface c1 extends fx,sl{//接口多继承,不能继承fx中的ff2静态方法,可以继承默认方法
    void testc();

}
class sx implements fx,sl,jk {//同时实现多个接口,要同时实现它们的方法
    public void fly(){
        System.out.println("sss");
        System.out.println(high);
    }
    public void help(){
        System.out.println("www");
        System.out.println(high);
    }
    public static void ff2()
    {
        System.out.println("6666");
    }
   public void ff3()//同时继承fx和jk中的默认方法ff3,必须重写这个方法
    {
        System.out.println("3333");
    }
}
class sxx implements c1{//必须实现新定义和继承到的方法
    public void fly(){
        System.out.println("aaa");
        System.out.println(high);
    }
    public void help()
    {
        System.out.println("bbb");
    }
    public void testc(){
        System.out.println("ccc");
    }
}

28、内部类(定义在一个类内部的类)

内部类可以直接访问外部类的所有属性和方法(包括私有属性),被视为外部类的成员(静态内部类是静态成员,不能访问外部类的普通成员),但外部类不能访问内部类的私有属性

内部类只能让外部类直接访问

内部类(成员内部类(非静态内部类,静态内部类),匿名内部类,局部内部类)//内部类组成

匿名内部类适合只要用一次的类

局部内部类定义在方法内部,作用域仅限于本方法,在实际开发中应用很少 

package com.sss.t.sss2;
//定义内部类
public class outer1 {
    private int age=19;
    private static int b=200;
   private void show()
    {
        System.out.println("age"+age);
    }
    public void look()
    {
        System.out.println("step1");
        //局部内部类,作用仅限于本方法
        class inner3{
            public void run()
            {
                System.out.println("局部内部类");
            }
        }
        //调用语法
        new inner3().run();
        inner3 aa=new inner3();
        aa.run();
    }
    class inner1{//非静态内部类,不能有静态方法、属性、静态初始化块
        private int age=20;
        public void test1()
        {
            System.out.println("内部类"+age);//内部类直接访问
            System.out.println("外部类"+outer1.this.age);//通过 外部类名.this访问外部类
            outer1.this.show();
        }
    }
    static class inner2{
       public void test1(){
           System.out.println(b);//静态内部类只能访问外部类的静态属性/方法
       }
    }
}
package com.sss.t.sss2;
//调用内部类
public class tester1 {
    public void test1(a3 a)
    {
        System.out.println("匿名内部类");
        a.run();
    }
    public static void main(String[] args) {
        //非静态内部类的对象必须寄存在一个外部类对象里,先建外部类对象,再用外部类对象创建内部类对象
        outer1.inner1 inner1=new outer1().new inner1();
        inner1.test1();
        outer1.inner2 inner2=new outer1. inner2();//注意语法不同
        inner2.test1();
        tester1 tc=new tester1();
        tc.test1(new a3() {
            @Override
            public void run() {//在用时创建一个匿名内部类并重写run方法,只存在一次
                System.out.println("匿名内部类成功");
            }
        });
        outer1 outer1=new outer1();
        outer1.look();
    }
}
interface a3{
    void run();
}

/*结果
内部类20
外部类19
age19
200
匿名内部类
匿名内部类成功
step1
局部内部类
局部内部类
*/

 29、数组

本质是相同类型数据的有序集合,长度是确定的,创建后大小不可变,元素类型必须相同,数组类型可以为任何数据类型,包括基本类型和引用,数组也是对象,数组中的元素相当于对象的成员变量

多维数组是以数组为元素的数组

为了能用Arrays.sort方法,类要实现Compareable接口,实现compareTo方法,在相等时返回0,其他看情况返回1或-1

new自建类数组后,使用数组每个元素还要再new,否则元素默认为null,会报空指针错误

package com;

import java.util.Arrays;
import java.util.StringJoiner;

public class test02 {
}
class user{
    private int age;
    private String name;

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

    @Override
    public String toString() {
        return new StringJoiner(", ", user.class.getSimpleName() + "[", "]")
                .add("age=" + age)
                .add("name='" + name + "'")
                .toString();
    }

    public static void main(String[] args) {

        user[] users=new user[3];//是引用类型,默认是null
        users[0]=new user(11,"ss");
        user[] userss={new user(11,"aa"),new user(12,"bb"),new user(13,"cc")};
        System.out.println(userss.length);//可以直接读取长度
        for (user a:userss)
        {
            System.out.println(a);
        }
        System.arraycopy(userss,1,users,0,2);//从userss的1下标开始拷贝2个放到users从下标0开始的位置上
        for (user a:users)
        {
            System.out.println(a);
        }
        int[] a=new int[6];
        int b[]=new int [7];
        int c[]={2,1,0};
        //这些语法都可以定义数组
        a[0]=99;//下标从0开始

        for (int i=0;i<c.length;i++)
        {
            System.out.println(c[i]);
        }
        for(int i:c)//本质相同,是遍历数组c的简便写法(增强for循环)

        {
            System.out.println(i);//遍历时i为数组元素值
        }
        Arrays.sort(c);//排序
        System.out.println(Arrays.binarySearch(c,2));//二分查找指定元素,找到返回下标
        Arrays.fill(c,100);//在数组c快速填充100
        System.out.println(Arrays.toString(c));//用Arrays.toString快速显示数组内容,仅对基本类型有用

        int[][] aa=new int[2][];
        aa[0]=new int[2];aa[0][0]=1;aa[0][1]=2;
        aa[1]=new int[]{1,2,3,4};
        for (int i=0;i<aa.length;i++)
        {
            for (int j=0;j<aa[i].length;j++)
            {
                System.out.print(aa[i][j]+"\t");
            }
            System.out.println(Arrays.toString(aa[i]));//可以不嵌套循环,循环打印这个即可
        }
        //Object可以打包多个变量,并可以用于构成表格
        Object[] a1={1000,"1000"};
        Object[] a2={1001,"1001"};
        Object[][] emp=new Object[3][];
        emp[0]=a1;emp[1]=a2;emp[2]=new Object[]{1002,"1002"};
        for (int i=0;i<emp.length;i++)
        {
            System.out.println(Arrays.toString(emp[i]));
        }
    }
}

结果是
/*
3
user[age=11, name='aa']
user[age=12, name='bb']
user[age=13, name='cc']
user[age=12, name='bb']
user[age=13, name='cc']
null
2
1
0
2
1
0
2
[100, 100, 100]
1	2	[1, 2]
1	2	3	4	[1, 2, 3, 4]
[1000, 1000]
[1001, 1001]
[1002, 1002]
*/

30、String类 (不可变Unicode字符序列)

位于java.lang包,java程序默认导入这个包下所有类,java没有内置的字符类型,而是在标准java类库中提供预定义的类String,每个“”括起来的字符串都是String类的一个实例

2a67124125f74dceb1e1247e510098d4.png

比较规则:

不能直接用==比较,要用equals方法比较!!!!

1.如果 字符串1的第n位的ASCII码值 等于 字符串2的第n位的ASCII码值 则 继续比较下一位

2.如果 字符串1的第n位的ASCII码值 大于 字符串2的第n位的ASCII码值 则 输出结果:1,表示字符串1 > 字符串2;

3.如果 字符串1的第n位的ASCII码值 小于 字符串2的第n位的ASCII码值 则 输出结果:-1 表示字符串1 < 字符串2;

4.如果 每一位的ASCII码值都相等,而且长度相同, 则 输出结果:0 表示字符串1 == 字符串2;

5.如果 字符串1是字符串2的前m位,例如 abcd 与abcdef 比较, 则 字符串1<字符串2. 原因是,到第5位时,字符串1的ASCII值是0,而字符串2的ASCII值为'e',即十进制的101,当然是字符串2大了. 具体到 cds和lesoqd 从第一位开始,'c'和'l'比较,当然是'c' < 'l'了,所以,"cds" < "lesoqd
 

package com;

import java.util.Arrays;

public class test01 {

    public static void main(String[] args) {
         String aa="122a";
         String bb=new String("122a");
         String cc="122a";
         String dd="122A";
        //aa==cc,它们都是栈中的引用,指向堆中的字符串常量池中的”122“
        //aa!=bb,bb是在堆中新开一个指向”122“的区域,引用bb再指向这个区域
        System.out.println(aa==bb);//f
        System.out.println(aa==cc);//t
        System.out.println(aa.equals(bb));//比的是字符串常量值是否相同,t
        System.out.println(aa.equalsIgnoreCase(dd));//忽略大小写比较,t
        String ee="0123456789 How are you";
        System.out.println(ee.charAt(4)+"   "+ee.length());//位置4的字符是4,长度22
        char[] ff=ee.toCharArray();//字符串转为数组(这里的字符是unicode字符,支持汉字)
        System.out.println(Arrays.toString(ff));//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,  , H, o, w,  , a, r, e,  , y, o, u]
        String[] gg=ee.split("o");//可以传入正则表达式,这里遇到逗号拆出一个新字符串进字符串数组
        System.out.println(Arrays.toString(gg));
        System.out.println(ee.indexOf("o")+"  "+ee.indexOf("he"));//从头向后找到第一个后返回开始位置12,找不到返回-1
        System.out.println(ee.lastIndexOf("o"));//从后往前第一个,找到返回20
        System.out.println(ee.contains("you")+" "+ee.contains("he"));//t    f看是否包含
        System.out.println(ee.startsWith("0123")+" "+ee.endsWith("you"));//t t看是否以指定字符串开头,结尾
        String hh=ee.replace(' ','&');//0123456789&How&are&you返回一个全新的字符串
        System.out.println(hh);
        hh=ee.substring(4);//从4位开始截取ee,456789 How are you
        System.out.println(hh);
        System.out.println(ee.substring(4,10));//截取4到10位,不包括10位,456789
        System.out.println(ee.toLowerCase()+"   "+ee.toUpperCase());//字母全转小写/大写
        hh="  h ou  ";
        System.out.println(hh.trim());//去除首尾空格,中间不变
    }
}

 31、可变字符序列(StringBuilder和StringBuffer,idea缩写SB)

String是不可变字符序列,StringBuilder和StringBuffer是可变字符序列

StringBuffer线程安全,要做线程同步检查,效率较低

StringBuilder线程不安全,不做线程同步检查,效率较高,建议采用该类 

String用final数组存,这两个不带final,Buffer各方法都带synchronized,做线程同步检查

package com;

public class test03 {
    public static void main(String[] args) {
        StringBuilder aa=new StringBuilder();
        StringBuffer bb=new StringBuffer();
        aa.append('a');
        aa.append('b').append("cdw");//往字符串追加内容,可以叠加用
        System.out.println(aa);//abcdw
        System.out.println(aa.insert(0,'a').insert(0,'b'));//baabcdw,插到指定位置上
        System.out.println(aa.delete(0,2));//abcdw,包头不包尾
        System.out.println(aa.deleteCharAt(0).deleteCharAt(0));//cdw,一个一个删
        System.out.println(aa.reverse());//wdc,字符串逆序
    }
}

32、包装类(把基本数据类型变成对象) 

Byte、Short、Integer、Long、Float、Double、Boolean、Character

更推荐用包装类代替int等,因为int默认赋值0,而0可能有实际含义

包装类默认值null,可以区分是否有实际含义

parseInt、intValue返回值都是int型即整数类型而不是整数类对象,valueOf返回值是整数类对象

package com;

public class test04 {
    public static void main(String[] args) {
        Integer aa=Integer.valueOf(100);//基本转对象
        aa=100;//编译器自动装箱,这样写也可以
        int bb=aa.intValue();//对象转基本
        bb=aa;//编译器自动拆箱,如果aa为null会异常,确保aa非空
        System.out.println(Integer.parseInt("123"));//字符串必须纯数字才能转,否则报错
        System.out.println(aa.toString());//包装类转字符串
        System.out.println(Integer.MAX_VALUE+"  "+Integer.MIN_VALUE);//看最大最小表示
        Integer cc=300;Integer dd=300;
        System.out.println(cc==dd);//f,整形,char型对应的包装类缓存-128到127的对象
       Integer ee=100;Integer ff=100;//需要时直接让引用指过去,所以两个100是t,
        System.out.println(ee==ff);//不在这个范围会new一个对象,所以两个300是f
        Byte gg=1;Float jj=1000.232f;
        Short hh=199;Double kk=13213.24;
        Long ii= Long.valueOf(10000);
        Boolean ll=false;Character mm='下';
    }
}

33、Date(时间),DateFormat(时间和字符串转化),Calendar类

c59a1069fe514b609b4ed7bc765273d4.png

9df3dd0873774cfa83d766687768af83.png

package com;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class test05 {
    public static void main(String[] args) throws ParseException {
        System.out.println(System.currentTimeMillis());//显示从1970.1.1到现在经过的毫秒数
        Date aa=new Date();//默认当前时间,传数字可以显示别的时间
        System.out.println(aa+" "+aa.getTime());//gettime显示毫秒
        //idea中被线划掉的方法被废弃了,可以但是不建议用
        DateFormat bb=new SimpleDateFormat("当前时间是yyyy-dd-MM hh:mm:ss");
        //指定格式,固定用年替换yyyy,月MM,日dd,年中天数D,时hh,分mm,秒ss
        String cc=bb.format(aa);
        System.out.println(cc);
        String dd="当前时间是2020-12-12 11:11:11";
        Date ee=bb.parse(dd);//字符串按指定规则转时间对象
        System.out.println(ee);
        Calendar ff=new GregorianCalendar();//默认当前
        ff.set(Calendar.YEAR,2222);//修改日历
        int gg=ff.get(Calendar.YEAR);//获取年
        System.out.println(gg);
        System.out.println(ff.getTime());//返回Data对象
        System.out.println(ff.getTimeInMillis());//返回对应的毫秒数
        ff.add(Calendar.DATE,1213);//日历计算,负数就是减
        System.out.println(ff.getTime());
    }
}

34、异常机制

异常处理使程序在出现问题时依然可以正确的执行完

抛出异常:执行一个方法时,若发生异常,这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给JRE

捕获异常:JRE得到该异常后,寻找对应的代码来处理该异常,JRE在方法的调用栈中查找,从生成异常的方法开始回溯,直到找到对应的异常处理代码为止 

 ffc58e101cd247b09ef3b43dc5425108.png

error不需要自己处理,checked编译时会处理,Runtime如除以0需要自己处理 

 ArithmeticException数学错误

 NullPointerException空指针异常

NumberFormatException数字格式化异常

ArrayIndexOutOfBoundsException数组下标越界

ClassCastException类型转换异常

FileNotFoundException找不到对应的文件

CheckedException在编译期必须处理,通过try-catch-finally处理,先执行try语句,碰到异常就抛出异常对象并进入catch语句处理异常,没有异常就不执行catch,最后都要执行finally语句

package com;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class test06 {
    public static void main(String[] args)throws ParseException//第二种,声明式抛出
    {
        //第一种,通过try-catch处理
        FileReader aa=null;
        try {
             aa=new FileReader("d:/a.txt");
            char bb=(char) aa.read();
            char cc=(char) aa.read();
            System.out.println(""+bb+cc);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            if (aa!=null){
                try {
                    aa.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        DateFormat dd=new SimpleDateFormat("yyyy-MM-dd");
        String ee="2011-11-23";
        Date ff=dd.parse(ee);
        System.out.println(ff);
        //第三种try-witch-resource:自动关闭实现了AutoCloseable接口的类
        //可以只try-catch,不写finally
        //其实是语法糖,编译器帮忙转换成try-catch-finally
        try (FileReader gg=new FileReader("d:/a.txt")){
            char bb=(char) gg.read();
            char cc=(char) gg.read();
            System.out.println(""+bb+cc);
        } catch (Exception e)//catch可以简化写,随便设一个变量即可
        {
            e.printStackTrace();
        }
        System.out.println(test());
    }
    //任何执行try中return语句之前,都会先执行finally语句(除非不存在)
    //如果finally语句中也有return,执行finally的return
    public static int test()
    {
        int a=10;
        System.out.println("bz1");
        try {
            System.out.println("bz2");
            a=20;
            return a;
        }catch (Exception e)
        {
            e.printStackTrace();
            return 0;
        }
        finally {
            a=40;
            System.out.println("bz3");
            return a;//这句存在就返回40,不存在就返回20
        }
        
    }
}

35、可视化bug追踪

自定义异常:从Exctption类或它的子类派生一个子类

如果继承Exception类,则为受检查异常,必须进行处理,如果不想处理,可以让自定义异常类继承RuntimeException类

自定义异常类要包括一个默认构造器和一个带有详细信息的构造器 

搜索先精细后粗放,先复制编译器显示的异常内容进行搜索

package com;

import java.util.Scanner;

public class test07 {
    public static void main(String[] args)//throws Exception
    {

        Scanner bb=new Scanner(System.in);
        int cc=bb.nextInt();
        //bb.nextLine();
        String dd=bb.nextLine();//把/n当一行读取了
        System.out.println(""+cc+"  "+dd);
        person aa=new person();
        //搜集关键词Scanner nextInt() nextLine() 跳过 没有执行
        aa.set(-11);
        //此时显示Exception in thread "main" com.bhmnl: txl
    }
}
//自定义不合法年龄异常类
class bhmnl extends RuntimeException{
    public bhmnl(){}//要提供两种构造方法
    public bhmnl(String nl){
       super(nl);
    }
}
class person{
    private String name;
    private int age;
    public void set(int age)//throws bhmnl
    {//继承Exception需要try-catch或者声明抛出,继承RuntimeException不需要
        if(age<0){throw new bhmnl("txl");}
        this.age=age;
    }
}

 36、List容器

java容器整体结构: ArrayList类和LinkedList类实现List接口,HashSet类实现Set接口,List接口和Set接口继承Collection接口,这三个接口表示存储单个元素

容器中内容存在内存中,程序崩溃、掉电丢失数据

还有HashMap类实现Map接口,这个接口表示存储成对的内容(键值对)

List特点:有序,可重复

a81b2f04d1a145c18ba5a66366fb582b.png

b4026f43ce804b3fb36ef97a2de374ce.png

6e0497e34442434fa934be8213e853b2.png

 f53fe6dccacc422c8b504732acb7a9bf.png

package com;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class test08 {
    public static void main(String[] args) {
        //list对象可以new成ArrayList、LInkedList、Vector中的任一个
        //三种new都可以实现下面的所有操作
        //ArrayList底层由数组实现,查询效率高,增删效率低,线程不安全,常用
        //LinkedList底层由双向链表实现,查询效率低,增删效率高,线程不安全
        //Vector底层用数组实现List,相关方法增加了同步检查,线程安全,效率低

        List list=new LinkedList();
        System.out.println(list.isEmpty());//true
        list.add("sss");
        list.add(111);
        System.out.println(list);
        System.out.println(list.isEmpty());
        System.out.println(list.size());//1
        System.out.println(list.contains("sss"));//是否包含sss,true
        list.remove("sss");//移除元素,"sss"这个对象还在,只是被移出容器了
        System.out.println(list);
        Object[] aa=list.toArray();
        System.out.println(Arrays.toString(aa));
        list.clear();//清空
        System.out.println(list);
        //上面的方法多位于Collection接口中,下面是List独有的方法
        //特点:索引有序、可重复放相同元素,按索引排序
        List bb=new ArrayList();
        bb.add("a");bb.add("b");bb.add("c");bb.add("d");
        System.out.println(bb);
        bb.add(2,"bb");//在指定的索引位置加元素
        System.out.println(bb);//[a, b, bb, c, d]
        bb.remove(2);//删除索引位置元素
        System.out.println(bb);
        bb.set(2,"bbb");//修改索引位置元素
        System.out.println(bb);//[a, b, bbb, d]
        System.out.println(bb.get(2));//获取索引位置元素,bbb
        bb.add("b");
        System.out.println(bb.indexOf("b"));//1,左向右第一个
        System.out.println(bb.lastIndexOf("b"));//4,右向左第一个
        List cc=new ArrayList();
        cc.add("a");cc.add("b");cc.add("c");
        System.out.println(bb.containsAll(cc));//f,看bb是否包含cc所有元素
        bb.addAll(cc);//把cc所有元素加入bb
        System.out.println(bb);//[a, b, bbb, d, b, a, b, c]
        bb.retainAll(cc);//把bb变成原来的bb和cc的交集
        System.out.println(bb);//[a, b, b, a, b, c]
        bb.removeAll(cc);//把bb中的cc元素全移出,包括重复的
        System.out.println(bb);//[]
    }
}

37、Set容器 

 特点:无序,不可重复,List的Collection接口方法可以直接使用,两个容器间的操作同List

HashSet基于HashMap,利用Map里面键对象不可重复的特点实现不可重复

package com;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;

public class test09 {
    public static void main(String[] args) {
        Set aa= new HashSet();
        aa.add("a");aa.add("b");aa.add("a");
        System.out.println(aa);//[a, b],已存在的不会再加
        aa.removeAll(aa);
        Emp bb=new Emp(1111,"111");
        Emp cc=new Emp(1111,"1112");
        Emp dd=new Emp(1121,"111");
        aa.add(bb);aa.add(cc);aa.add(dd);//根据equals判断是否重复
        System.out.println(aa);//[Emp[id=1121, name='111'], Emp[id=1111, name='111']]
    }
}
class Emp{
    private int id;
    private String name;

    public Emp(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Emp emp = (Emp) o;
        return id == emp.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", Emp.class.getSimpleName() + "[", "]")
                .add("id=" + id)
                .add("name='" + name + "'")
                .toString();
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

38、map容器(成对存储,按照键值对的形式存储)

getOrDefault(c, 0)取键c对应的值,如果找不到就返回0(设置的默认值是0)

3e5454a946ae4636bc03a91813bae3c5.png

 0d5f222ee51b404297b9531640f3bec9.png

键(key)和值(value)都是对象,通过键来标识,键对象不能重复(equals方法判断重复)

Map接口有HashMap、TreeMap、HashTable、Properties等实现类

HashMap线程不安全,效率高,允许key或value为null,常用

HashTable线程安全,效率低,不允许key或value为null

HashMap用哈希表实现,原理图如下

52df471dda66406f854676d2b2bb680b.jpg

969afbf8b6af49ecbfd1daa0165c3d1a.jpg早期jdk使用拿key对象的hashcode值对key数组的length取余的方法进行hash()计算数组位置,效率不高

后用hashcode&(length-1)位运算计算位置,效率高

package com;

import java.util.*;

public class test10 {
    public static void main(String[] args) {
        Map aa=new HashMap();//也可以用HashTable替换
        aa.put(1,"one");aa.put(2,"two");aa.put(3,"three");
        //1,2,3是键,字符串是值
        System.out.println(aa.get(2));//获取键对应的值
        aa.put(2,"二");//如果键重复,则替换旧的值(equals方法判断重复)
        System.out.println(aa.get(2));//二
        System.out.println(aa.size());//3,返回大小
        System.out.println(aa.isEmpty());//f,是否为空
        System.out.println(aa.containsKey(3));//t,是否包含3这个键
        System.out.println(aa.containsValue("one"));//t,是否包含“one”这个值
        aa.remove(3);//从容器中移出3这个键所在的键值对
        System.out.println(aa);//{1=one, 2=二}
        Map bb=new HashMap();
        bb.put("yi","11");bb.put("er","22");bb.put("san",33);
        aa.putAll(bb);//把bb中所有内容加入aa
        System.out.println(aa);//{yi=11, 1=one, san=33, 2=二, er=22}
        Map<String,String> map=new HashMap<>();//泛型,限制键和值的类型都是字符串
        map.put("yi1","one");map.put("er2","two");map.put("san3","three");
        Set<String> key=map.keySet();//把所有key返回到Set容器
        for (String tem:key)
        {
            System.out.println(tem+" "+map.get(tem));//按key遍历Map方法
        }
        Collection<String> value=map.values();//读取所有值
        //这个函数返回值是Collection<String>,可以强转为(Set<String>)进Set容器
        for (String tem:value)
        {
            System.out.println(tem);//遍历值
        }
        //使用EntrySet遍历key和value
        Set<Map.Entry<String,String>> entrySet=map.entrySet();
        //一个Entry对象就是一个键值对,包含一个键和一个值,Entry是Map的内部类
        for (Map.Entry tem:entrySet)
        {
            System.out.println(tem.getKey()+" "+tem.getValue());//可以获取
        }
        //遍历List、Set
        List<String> list=new ArrayList<>();
        list.add("111");list.add("211");list.add("13");
        for (int i=0;i<list.size();i++)//通过索引遍历list,只适用于List
        {
            System.out.println(list.get(i));
        }
        for (String tem:list)//增强for循环遍历,Set也能用
        {
            System.out.println(tem);
        }
        //使用迭代器Iterator对象,Set也能用
        for (Iterator<String> iter=list.iterator();iter.hasNext();)//判断有无下一个,会自动递增不用写
        {
            String tem=(String) iter.next();//强转或者指定迭代器泛型
            System.out.println(tem);
        }
        //边遍历边删除,容器的size会变
        //使用迭代器处理这种情况,它始终指向下一个元素,不关心容器整体的变化
        //要全部使用迭代器的方法
        System.out.println(list);
        for (Iterator<String> iterator =list.iterator();iterator.hasNext();)
        {
            String tem=iterator.next();
            if (tem.startsWith("1")){
                iterator.remove();//使用迭代器.remove,不能用list的remove
            }
        }
        System.out.println(list);
    }
}

 存储表格信息实操

package com;

import java.util.*;

//用容器存储表格信息
public class test11 {
    public static void main(String[] args) {
        test02();
    }
    //Map对应一行数据,几行数据就用几个Map,再用List存各行的Map表示一个表格
    public static void test01()
    {
        Map<String,Object> m1=new HashMap<>();
        m1.put("id",1001);m1.put("title","java");m1.put("time","12-11");
        Map<String,Object> m2=new HashMap<>();
        m2.put("id",1011);m2.put("title","java1");m2.put("time","12-12");
        List<Map<String,Object>> list=new ArrayList();
        list.add(m1);list.add(m2);
        for (int i=0;i<list.size();i++)
        {
            Map<String,Object> tem=list.get(i);
            System.out.println(tem.get("id")+" "
            +tem.get("title")+" "+tem.get("time"));
        }
    }
    //List+Javabean(Java对象),每个对象对应一行记录
     public static void test02()
     {
         xx xx1=new xx(1001,"java","12-11");
         xx xx2=new xx(1002,"java1","12-12");
         List<xx> list=new ArrayList<>();
         list.add(xx1);list.add(xx2);
         for (xx tem:list)
         {
             System.out.println(tem);
         }
     }
}
class xx{
    private int id;
    private String title;
    private String time;

    public xx(int id, String title, String time) {
        this.id = id;
        this.title = title;
        this.time = time;
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", xx.class.getSimpleName() + "[", "]")
                .add("id=" + id)
                .add("title='" + title + "'")
                .add("time='" + time + "'")
                .toString();
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }
}

39、自定义泛型(给容器贴标签)

泛型的本质是“数据类型的参数化”,处理的数据类型不是固定的,可以作为参数传入

传入的类型只能是引用,基本数据类型不行

使代码可读性更好(不用强转)

程序更安全,编译能过就没有类型转换异常

泛型主要用于编译阶段,编译后的字节码class文件不包括泛型中的类型信息,类型转换仍然是普通的强制转换

泛型主要是方便写代码,更好的安全性检测,认识泛型标记便于读代码

7d6a8ad9d77942428ec9999496f031b2.png

40、IO流技术(input,out)

b0546aa16d3d40bc8e214f32279bd171.png

e4962b3f591b4d0eaca5d01069f1d38a.png

0c2b6177bc4d43c8930d6be9bc0c7640.png

 a5372b1c2f214dbea6c0a79b02086435.png

9253785bbc8c43538af5675811ba36fe.png

 输入、输出流的划分是相对程序而言的,并不是相对数据源 

文件字节流可以处理所有文件,但是处理unicode字符可能乱码,以字节为单位

文件字符流用于处理文本文件(txt结尾,word,pdf不是),以字符为单位

f723d89d828b4082bbde2a562758cbd6.png

在copy1方法中演示

834ff44561364953a2d668778c79b420.png

内部是一个数组 

b2b9dcbc73b74f55992ce445f6dd3276.png

 d5362651994145758cb1a5e65ef1a687.png

 处理基本数据类型和字符串,采用装饰器修饰new FileInputStream(wj)

e5eb34d3462a4a0b923c38756f5817a5.png

ab05f10c9e5f4104b4a887151f6134ac.png

h'f 

上面的接口是一个空接口,用于标记是否可以序列化

1dc49d4b8fdb4d7a8b160dd096050c88.png

转换流:可以把字节流转为字符流 ,使两者对的上

随意访问文件流:用RandomAccessFile类可以不按顺序随意的访问、读写文件,正常需要按照先后顺序读取

54556331ab9947f9bdce5c7584b992d9.png

070f56f4392946739eaaf7dd149f9914.png

 38e24d2108554009aebc46014f4333dd.png

809cb0104a834195a28a98f84d62f533.png

06dc32d924f8485fb8af4760d2bdf310.png

 BufferedReader reader = new BufferedReader(new FileReader(filePath));

String line = reader.readLine()

String[] numbers = line.split("\\s+"); 

每读到一个空格就终止读取到当前数组元素上

package com;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;

public class test13 {
    public static void main(String[] args) {
        FileInputStream file=null;
        FileReader fi1=null;
        FileOutputStream file1=null;
        FileWriter fi2=null;
        try {
            copytxt("d:/a.txt","d:/ad.txt");
             file=new FileInputStream("d:/a.txt");
            int s1=file.read();
            System.out.println(s1);//97,a的编码
            System.out.println(file.read());//98,如果文件已经结束,返回-1
            //把文件内容删光再写,new时清空一次
            file1=new FileOutputStream("d:/ac.txt");
            file1.write('1');
            file1.write('2');//12
            fi1=new FileReader("d:/a.txt");
            fi2=new FileWriter("d:/ac.txt");
            int tem=0;
            while ((tem=fi1.read())!=-1)
            {
                fi2.write(tem);
            }


        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        finally {
            //流对象用完后,必须关闭,否则总占用系统资源,最后造成系统崩溃
            //实际是通过操作系统打开文件,如果不关,程序结束文件还是一直打开
            //为了避免在执行close前发生异常跳出try导致不能关文件,把关文件代码放finally
               try {
                  if (file == null) {
                       file.close();
                   }
               } catch (IOException e) {
                   throw new RuntimeException(e);
               }

            try {
                if (file1!=null){
                file1.close();}//两种流对象都要关
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                if (fi1!=null){
                    fi1.close();}//两种流对象都要关
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                if (fi2!=null){
                    fi2.close();}//两种流对象都要关
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        //try-with-resource写法
        try(FileInputStream file2=new FileInputStream("d:/a.txt");
           //o流对象在这里new会清空文件内容,导致不能读
        ) {
            //在try里打开的流都会被自动调用close方法(编译器自动生成相关的finally)
            int s1=file2.read();
            System.out.println(s1+"kk");
            System.out.println(file2.read()+"kk");
            FileOutputStream file3=new FileOutputStream("d:/ab.txt");
            file3.write('1');//把文件内容删光再写
            file3.write('1');
            //利用字符串转字符数组
            file3.write("dfwdfs".getBytes(StandardCharsets.UTF_8));//11dfwdfs

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        copy1("d:/作业/QQ图片20221012223506.png","d:/作业/le.png");
        zjszl("adafdsf".getBytes());
        writeData("d:/ab.txt");//打开文件是一堆乱码,正常现象
        readData("d:/ab.txt");//这样可以正确读取
        writeObject("d:/ac.txt");
        readObject("d:/ac.txt");
        syfwwjl();
        zhl();
    }
    public static void copy(String wj1,String wj2)//因为是字节码,也适用于图片拷贝
    {
        try (FileInputStream aa=new FileInputStream(wj1);
        FileOutputStream bb=new FileOutputStream(wj2);
        ){

            byte[] buffer=new byte[1024];//用于缓存
            while (aa.read(buffer)!=-1)//把读取的内容放入数组
            {
                bb.write(buffer);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void copy1(String wj1,String wj2)//使用缓冲字节流
    {
        try(
                FileInputStream f1=new FileInputStream(wj1);
                FileOutputStream f2=new FileOutputStream(wj2);
                BufferedInputStream f3=new BufferedInputStream(f1);
                BufferedOutputStream f4=new BufferedOutputStream(f2);
                )
        {
          int tem=0;
          while ((tem=f1.read())!=-1)
          {
              f4.write(tem);
          }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void copytxt(String wj1,String wj2)//缓存字符流
    {   //注意这里的写法
        try(BufferedReader fi1=new BufferedReader(new FileReader(wj1));
        BufferedWriter fi2=new BufferedWriter(new FileWriter(wj2));
        ) {
          String tem="";
          while ((tem=fi1.readLine())!=null)//这里用null
          {
              fi2.write(tem);
              fi2.newLine();//没有它会连成一行
          }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void zjszl(byte[] bytes)//测试字节数组流
    {
        int tem=0,num=0;
        try (ByteArrayInputStream fi1=new ByteArrayInputStream(bytes);
        ){
            while ((tem=fi1.read())!=-1)
            {
                System.out.println((char) tem);
                num++;
            }
            System.out.println(num);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void writeData(String wj)//数据流
    {
        try (DataOutputStream dos=new DataOutputStream(new FileOutputStream(wj));
        ){
            dos.writeChar('w');
            dos.writeInt(1213);
            dos.writeBoolean(true);
            dos.writeDouble(1213.24);
            dos.writeUTF("是法国");
            dos.flush();//手动刷新缓冲区,将流中数据写入文件
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void readData(String wj)//数据流
    {
        try (DataInputStream dis=new DataInputStream(new FileInputStream(wj))){
            //读取数据时,要和写入的顺序保持一致,否则不能正确读取数据
            System.out.println(dis.readChar());
            System.out.println(dis.readInt());
            System.out.println(dis.readBoolean());
            System.out.println(dis.readDouble());
            System.out.println(dis.readUTF());

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void writeObject(String wj)//对象流
    {
        try (ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(wj))){
            //把对象通过流输入文件
            ArrayList<usere> list=new ArrayList<>();
            list.add(new usere(1001,"aaa","a123"));
            list.add(new usere(1002,"bbb","b123"));
            list.add(new usere(1003,"ccc","c123"));
            //传入的所有类都要实现Serializable接口,如ArrayList也实现了
            oos.writeObject(list);
            oos.flush();

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void readObject(String wj)//对象流
    {
        try (ObjectInputStream ois=new ObjectInputStream(new FileInputStream(wj));){
            ArrayList<usere> list=(ArrayList) ois.readObject();
            for (usere u:list)
            {//未序列化的pwd会显示null
                System.out.println(u.getId()+","+u.getName()+","+u.getPwd());
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    public static void zhl()//转换流
    {
        try (BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
        ){
            //System.in是字节流,通过InputStreamReader转为字符流, OutputStreamWriter同理
            String str=br.readLine();
            while (!"exit".equals(str))//用exit结束循环
            {
                bw.write("输入:"+str);
                bw.newLine();
                bw.flush();//没有清空不能及时显示输出
                str=br.readLine();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void syfwwjl()//随意访问文件流
    {
        try (RandomAccessFile raf=new RandomAccessFile("d:/ae.txt","rw");){
            int[] data={10,213,453,57,23257,789};
            for (int i=0;i<data.length;i++)
            {
                raf.writeInt(data[i]);
            }
            raf.seek(4);//从4号位开始读
            System.out.println(raf.readInt());
            raf.seek(8);
            raf.writeInt(3232);//替换
            for (int i=0;i<data.length;i++)
            {
                raf.seek(i*4);
                System.out.println(raf.readInt());
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
 class usere implements Serializable
{
    private int id;
    private String name;
    transient private String pwd;//表示不参与序列化

    public usere(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}

41、Apache IO包(官网http://www.apache.org)

d84fc49b70984d66a7688fe1373df4e2.png

增加装饰,可以为类增加新功能 

官网->see all projects->commoms->IO->download->下载zip->解压放到桌面->idea的文件->项目结构->库->点加号->java->选择commons所在路径->找到jar文件(名字最短的那个)->确定->选择要加入的模块

package com;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

public class test14 {
    public static void main(String[] args) {
        iphone iphone=new iphone("iphone");
        iphone.show();
        siphone siphone=new siphone(iphone);//传入iphone,对它进行装饰
        siphone.show();
        write();
        read();
        readURL("http://www.apache.org");
        copy();
        拷贝目录();
    }
    public static void write()
    {
        StringBuilder aa=new StringBuilder();
        for (int i=0;i<100;i++)
        {
            aa.append(Math.random()+"\n");
        }
        try {//gbk是一种编码,读写的编码方法要相同
            FileUtils.write(new File("d:/a.txt"),aa.toString(),"gbk");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void read()
    {
        try {
           List<String> nr= FileUtils.readLines(new File("d:/a.txt"),"gbk");
           for (String tem:nr)
           {
               System.out.println(tem);
           }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void readURL(String wz)
    {
        try {
            URL url=new URL(wz);//返回HTML源码
            InputStream is=url.openStream();
           String con=IOUtils.toString(is,"UTF-8");
            System.out.println(con);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void copy()
    {
        File a1=new File("d:/a.txt");
        File b1=new File("d:/aa.txt");
        try {
            FileUtils.copyFile(a1,b1);//把a1拷到b1上
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void 拷贝目录()
    {
        File dir=new File("d:/aaa");
        File dir1=new File("d:/bbb");
        try {
            FileUtils.copyDirectory(dir, dir1, new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    if (pathname.isDirectory()||pathname.getName().endsWith("b.txt"))
                    {return true;}//用于文件过滤,false的文件不会被拷贝
                    else {//可拷贝目录或以b.txt结尾的文件
                        return false;
                    }
                }
            });//可以传匿名内部类
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}
class iphone
{
    private String nane;

    public iphone(String nane) {
        this.nane = nane;
    }
    public void  show()
    {
        System.out.println(nane);
    }

}
class siphone
{
    iphone iphone;

    public siphone(com.iphone iphone) {
        this.iphone = iphone;
    }
    public void show()
    {
        System.out.println("装饰器");
        iphone.show();
    }
}

42、多线程(JAVA语言的重要特性)

程序是一个静态概念,对应操作系统一个可执行文件,运行程序时产生进程fc7b4baaec4f43d384b68cc5366707a2.png

6c00569b99024a178f1f5303dfe59baf.png

ab6d3be19ab2416bb247b53959e426d6.png java线程分为green threads和native threads

 05248bc1fce9405cb165172d98d93683.png

072acca3dceb4978a1cbac0f6794f83f.png

476fe7155a484545a7e0589e8c72ab8b.png

 990437d6b6d542c3b3af409d105a2b88.png

就绪->运行由系统决定 

package com.dxc;
//继承Thread类实现多线程
public class test01 extends Thread {
    public static void main(String[] args) {
       test01 test=new test01();//创建线程对象
        test.start();//启动线程,即可执行run方法,但是必须用start调用
        test01 test1=new test01();
        test1.start();//可以启动多个线程
        //两个线程来回切换,谁先谁后不一定
    }

    @Override
    public void run() {
        //重写run方法,它是线程体
        for (int i=0;i<10;i++)
        {//getName返回系统自动起的线程名称
            System.out.println(this.getName()+"  "+i);
        }
        super.run();
    }
}

package com.dxc;
//使用lambda表达式创建线程
public class test03 {
    public static void main(String[] args) {
        //通过匿名内部类创建
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i=0;i<10;i++)
                {//getName返回系统自动起的线程名称
                    System.out.println(Thread.currentThread().getName()+"  "+i);
                    //Thread.currentThread()获取当前线程对象
                }
            }
        }).start();

        new Thread(()->{//接口中仅一个方法时可用,此时{}中就是run方法代码
            for (int i=0;i<10;i++)
            {//getName返回系统自动起的线程名称
                System.out.println(Thread.currentThread().getName()+"  "+i);
                //Thread.currentThread()获取当前线程对象
            }
        }).start();
    }

}
package com.dxc;
//通过Runnable接口创建多线程,接口只有一个run方法
//可以继承其他类
public class test02 implements Runnable{
    boolean live=true;//通过设一个变量终止线程
    public void run() {
        //重写run方法,它是线程体
        int i=0;
        while (live)
        {
            //getName返回系统自动起的线程名称
            System.out.println(Thread.currentThread().getName()+"  "+i);
            //Thread.currentThread()获取当前线程对象
            try {
                Thread.sleep(100);//睡眠到时间自动加入就绪状态
                Thread a=new Thread(new test());
                a.setName(Thread.currentThread().getName()+"    a");
                a.setPriority(10);//设置优先级
                a.start();
                a.join();//当前线程必须等a线程执行完才能继续执行

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            Thread.yield();//由运行状态进入就绪状态
            i++;
        }

    }

    public void js()
    {live=false;}
    public static void main(String[] args) {
        //把实现了Runnable接口的对象作为参数传入
        test02 t1=new test02();
        Thread t2=new Thread(t1);
        t2.setName("t2");//设置线程名字
        Thread t3=new Thread(t1);
        t3.setName("t3");
        System.out.println(t2.isAlive()+"  "+t3.isAlive());
        t2.start();
        System.out.println(t2.isAlive()+"  "+t3.isAlive());
        t3.start();
        for (int i=0;i<10;i++)
        {//getName返回系统自动起的线程名称
            System.out.println("主线程  "+i);
            //Thread.currentThread()获取当前线程对象
        }
        System.out.println(t2.isAlive()+"  "+t3.isAlive());
        t1.js();//不知道为啥,结束线程后两者仍然为true
        System.out.println(t2.isAlive()+"  "+t3.isAlive());
    }
}
class test implements Runnable {

    @Override
    public void run() {
        for (int i=0;i<10;i++)
        {
            System.out.println(Thread.currentThread().getName()+"  test  "+i);
        }
    }
}

43、线程同步(synchronized,产生同步阻塞)

ae8a2d402d4c4df5b3563ca8f41e518f.png

 07bf8831aaf3480cadb851450d8915e2.png

35bcace5d0c04557ac2469177f9371ca.png

43ec8f6916c64d0baada45365eb9d1b3.png

package com.dxc;

public class test04 {
    public static void main(String[] args) {
        Account a1=new Account(100,"aa");
        qq a2=new qq(a1,80);
        qq a3=new qq(a1,60);
        a2.start();
        a3.start();
    }
}
class Account{
    int money;
    String name;

    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}
class qq extends Thread
{
    Account account;
    int qds;
    int zgds;
    public qq(Account account,int qds){
        this.account=account;
        this.qds=qds;

    }

    @Override
    public void run() {
      synchronized (account){
          //synchronized块,把多线程中要被修改的对象相关代码放入
          //也就是同步代码块
          if(account.money-qds<0)
          {
              return;
          }
          try {
              Thread.sleep(1000);//睡了1秒,两个线程都判断可以取
          } catch (InterruptedException e) {
              throw new RuntimeException(e);
          }
          account.money-=qds;
          zgds+=qds;
      }
        System.out.println(this.getName()+"余额"+account.money);
        System.out.println(this.getName()+"共取走"+zgds);
    }
}

44、生产者消费者模式 

1efe6b8fe398422f9b811b9d31a63e91.png 0c3b997265f940c19545db1de843c5c0.png

 7fc047f3b03143fca16637baf6575b09.png

package com.dxc;
//手写生产者消费者模式
public class test05 {
    public static void main(String[] args) {
         mtk mtk=new mtk();
         shengchanzhe shengchanzhe=new shengchanzhe(mtk);
         xiaofeizhe xiaofeizhe=new xiaofeizhe(mtk);
         shengchanzhe.start();
         xiaofeizhe.start();
    }
}
class mt{
    int id;

    public mt(int id) {
        this.id = id;
    }
}
class mtk{
    int zhanding=0;
    mt[] ms=new mt[10];
    public synchronized void push(mt mt) {
        while (zhanding == ms.length) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        this.notify();//随机唤醒等待池中一个线程,否则一直呆在等待池中
        ms[zhanding] = mt;
        zhanding++;
    }
    public synchronized mt pop()
    {
        while (zhanding==0)
        {
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        this.notify();
        zhanding--;
        return ms[zhanding];
    }
}
class shengchanzhe extends Thread{
    mtk ss=null;
    public shengchanzhe(mtk mtk)
    {
        this.ss=mtk;
    }
    public void run()
    {
        for (int i=0;i<10;i++)
        {
            System.out.println("生产馒头"+i);
            mt m=new mt(i);
            ss.push(m);
        }
    }

}
class xiaofeizhe extends Thread{
    mtk ss=null;
    public xiaofeizhe(mtk ss)
    {
        this.ss=ss;
    }
    public void run()
    {
        for (int i=0;i<10;i++)
        {
            mt m=ss.pop();
            System.out.println("消费者"+m.id);
        }
    }
}

 45、线程池

e657b6cd3082419cbd520159eb4f65f6.png

09a1070a1edd460daffab20081e20539.png

7c26cae480174ab59a64362a35ffb500.png

965e58db8a0d409899dde83b5358bbba.png

9f8987c2a33648d6bca6489e8bd79646.png

92316a42fbcf469fbd1f506228087a78.png

 f0dff568c5bc4b23916ebdfcd3317d62.png

 42f6f5e614d74feb9bd3b3de8f79b1d1.png

 585f3223d97e48a38efe0ce372ea4353.png

import java.util.concurrent.*;

public class test06 {
    public static void main(String[] args) {
        ThreadPoolExecutor executor=new ThreadPoolExecutor(5,10,200,
                TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(5));//选择毫秒
        for (int i=0;i<10;i++)
        {
            mytask mytask=new mytask(i);
            executor.execute(mytask);
            System.out.println("线程池中线程数"+executor.getPoolSize()+
            "队列中任务数"+executor.getQueue().size()+
                    "已执行任务数"+executor.getCompletedTaskCount());
        }
        executor.shutdown();
        //四种内置线程池
       // ExecutorService executorService= Executors.newCachedThreadPool();
       // ExecutorService executorService= Executors.newFixedThreadPool(12);
        //ExecutorService executorService= Executors.newSingleThreadExecutor();
        ScheduledExecutorService executorService= Executors.newScheduledThreadPool(30);
        executorService.schedule(()->{//延时执行任务
            System.out.println("2秒后再见");
        },2,TimeUnit.SECONDS);
        for (int i=0;i<20;i++)
        {
            mytask mytask=new mytask(i);
            executorService.execute(mytask);
        }
        executorService.shutdown();
    }
}
class mytask implements Runnable
{
    private int number;
   public mytask(int number)
    {
        this.number=number;
    }

    @Override
    public void run() {
        System.out.println("正在执行"+number);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("执行完毕"+number);
    }
}

46、ThreadLocal(面试常见)

400d691673d6443dbcb707a2823d8eb0.png

d8322a9eb7d14f50860780d46711c3ce.png

4722583bfbf0496496505a57e0156c7d.png

75f4f0ee4e294887b914c1d272aa4d75.png

5084cba7bd0c4625b6c04d398475d0af.png

图中实线是强引用,虚线是弱引用

3da8b797e6584f809dcad4fc211617e7.png

6a55bf5c905d4c5f9347824e9743571b.png

3761634385ed41b29dad56864ef71dc3.png

a7376423815f443cb6bd53abe69d2ced.png

package com.dxc;

public class test06 extends Thread{
    public static ThreadLocal<Integer> ss=new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return new Integer(100);//100是初始值
        }
    };
    public static int getnum(){
        ss.set(ss.get()+1);
        return ss.get();
    }
    public static ThreadLocal<Integer> ss1=new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return new Integer(10);//10是初始值
        }
    };
    public static int getnum1(){
        ss1.set(ss1.get()+10);
        return ss1.get();
    }
    public void run()
    {
        for (int i=0;i<3;i++)
        {
            System.out.println(Thread.currentThread().getName()+"num:"+getnum()+" num1:"+getnum1());
        }
        //没有ss、ss1指向的ThreadLocal对象是只被弱引用关联的
        ss.remove();//用完ThreadLocal就remove
        ss1.remove();//避免内存泄漏
    }

    public static void main(String[] args) {
        new test06().start();
        new test06().start();
        new test06().start();
    }
}

 47、学习要求

9b5e33c39cb5460fa5c352b7392334f1.png

 自我介绍:我的职业发展是什么、我的优势是什么、我的劣势是什么、我要补充哪些不足、我对工作是什么态度

简历:最重要的是项目经验和职业技能

900d0b8bd8fa4a668d5765f744e3e3ee.png

html、css、js也要学 

48、设计模式

084b657d3c904a05a6b86bc34aca1f0d.png

fd2b798272514f6698ccf0f9cc74ef7f.png

3cc07888cd5b4047b001c441a7fc6798.png 440bd22da238433b8ea4f0907ef0ff54.png

 58a3d3b9294946cca9f08f30918bc436.png

 dff05fc102214725aa94565e185e6799.png

a562d641b5e248c0863757d071a79c3a.png382b8fed7fd34e0194f5fa76d3d80979.png 03b7df21207947f0806110f1c02922ab.png

 027b4139ca1e4c999b91c8d8c0b2114a.png

 3e63dd3186974894b7b36c3df2f6b49c.png

2a6073e019cf41ef9c21b6a05234ee78.png

0b9b9da9d5764ad79d60ffddbd42c78e.png 66fedd6956fd48d7b673811bb52d61ce.png

 b2d74e5fa6f64a11bda89c8a8523057d.png

e380fb2516eb4ae2ae6752086fd4e3ab.png

d04d6d19437b4bce8620477b21fba94d.png 820a8f4c1d11406aa63648cc173c74f6.png

a045032f70c0445880d84705148e4b3e.png 最重要

2a43f58aaa7a4044b99f666df2e49e00.png

 68c63c7cb7514f31b4c624d9ca3ac387.png

9e1860e331de4972952f195f116ab4e7.png 4c710991c44e4be1852265b4fd2e03f2.png

7adab0b778bf48828e501ba128980aea.png f577b48c70ef4144b15c620b30e4fcd9.png

94830e0557ad40db95eebafac46bed70.png

aabd5d69181e4a9989fcc3f4b22f2262.png

49、动态代理模式 

 4ec35ef52dfc431f88b5101e0ac293f7.png

09e98cad26b8489780e46384b6788c98.png 65f0ddb7e52045349f76ea26b38cce6d.png

5ca6da49b57c4687a5d0b69a3e5cfc1c.png a142d5171ef546d9a76b127afc311ff7.png

61013ff8124d4fcf9ff332d2ddadae49.png 84baecd11873458195e05ba97e6df31a.png

7e26b0bf56a547fd8a0c499de5752dff.png b2470bee0fab483e8c68ea9b20a0c531.png

79082f0f404b4bc987d315447d7a79c6.png bd187909644e42e09f60d527e41927a4.png

cea157184c6648caa4964f2a9dce6461.png 38dbf56c3e004e6aae9513b9b5c25aeb.png

02d484c0422d4df9af8251b40eda7a05.png

f66af63cdfe64fc0806167f5dddfaeda.png

cec00ec0b90d4729a0f063f0e3b7611d.png

 b0c124276d014e7bb6d9e2ad9f5084b6.png

ab093694f8c1428fa5b245f7ef255b8e.png f46ec6837ea34670aeea57892238bc56.png

f796759515174092a56012b7f346003d.png

e2e529461acb4f68b6c84bd10a6214f8.png

9c4f6e41f4ab429497ae039d4c47c51d.png

96003182ea774d0c847820b99603ef3b.png

92f21c3d3d4e4a7bad5f5a82bc4443f1.png

50、NIO、BIO、AIO

5ac0e858b6ad47db8890f66f9c0c7290.png

04f6bd564c4641b7934b9b36a7410a6d.png

 2fb168f275084009b86b0d62bed5ea89.png

 de7e01e02f494de1b36e761b5316084c.png

27e86a479d1c49a98b76d299987c5f2e.png fe1ece1d8148499a9be904cf01067f97.png

 68070bb040df4327823eb5b6350800b0.png

d6a8e0db3f8e4cb8b717a13e2d211430.png cf1aa629fe534a3fa5d5d041ffcf2ab5.png

a8d2533d73944251957f38ffd6b4c343.png fde7f8dc4bd045019ed918cd49da37ce.png

e4aa4a275a96444790af5cbf64199c1d.png 4af7180acecf46e78db32e80f2408b08.png

41b7bdb4b3344b7d9adb7da05e943e0a.png 9a40926d94f44a3e935d8c1bf4476911.png

文件读取 

2561d021690d4546bd20ac140ed33783.png

 文件写入

 28eee81b84444a499d4233cc30e13158.png

32d76ff52397491d96ef4be9151e8206.png

23438fd9636b4591afb00213dd043032.png

3d8658d3549a4ab9b679dccad7f3d023.png

db6f7f8236e3490cadbf1ec85bc7cbf3.png

114711f3d07749e6af74eabe04e4953b.png

35a98b4eed7843338ab2f61a7a030c59.png

991f26f2acdc4c928c0fbc22a57cebc3.png

86a4a3264914478dacb138c682563814.png

2aec17f5216e4217b98b9f3cc9946e42.png f1ba1818efc8422fbafcc159a087e054.png

a7c12e8f86a74d1c90bfd341f8f5d652.png

7a68f6e1182e49b8825f338809dc0a25.png

9bef3933ba3f477a84a5e3ce78e2ec30.png

9d69b2de918142de85b646720e3c2066.png f1bbb9fae8bf472cb8bd9a43ada55ad2.png

26b7c548005c4a3092c49f6911a36787.png

ca48e3ff49a740e090b3abaf7da64d89.png  

9c895e2761314464b28e463ab4704fbe.png deb4dd238bb04bc18d36855a64babb5f.png

e767954901a742729421d76ab288dc1c.png b9f6cd629ff64a89aa4a2ef6323c6fd9.png

 51、注意事项

a、 java比较字符串数组是看它们的地址是否相同,不看内容是否相同,比较内容时用String或char数组

b、注意用nextLine跨行读取会出现数组超限,无法读取下一行,建议单独写一个方法进行读取

c、注意需要回溯到任意位置时要保存前面的内容,用StringBuilder等引用类型使方法可以修改它

d、需要重复输出某串,应该先把它读出来

e、可以用字符串比较规则如是否大于“80”判断最高位是否为0:8的码1000

f、进制转换有下面的方法

75e0fa4caabd4772876c4752fc28821d.png

Integer.valueOf(s, radix) 将s以radix进制的形式转换成十进制数,返回值为Integer型

Integer.parseInt(s, radix) 将s以radix进制的形式转换成十进制数,返回值为int型,用法和Integer.valueOf一样,就返回值类型不同而已

BigInteger(string, base).toString(to) 使用BigInteger将string以base进制的形式转换成to进制

BigInteger(string, base) 将string以base进制的形式解析为BigInteger类型

BigInteger.toString(to) 将BigInteger转换成to进制的String类型
g、用数组下标记录天数,元素值记录缩短到这一天要用的资源数,初始化存这天缩短一天用的资源数,然后递推,把天数大的资源数加到小的上,直到超过资源总数,得到最小能缩到哪天

h、unordered_map<int,unordered_map<int,set<int>>> attrName_attrVal_users; // 存储 属性名-属性值-用户DN 

的存储方法好过  class yonghu{public int DN;public int[] sx;public int[] zhi;}存法

<属性编号><操作符><属性值>,  断言操作符为 :,表示匹配具有该属性且值与之相等的用户;反断言操作符为 ~,表示匹配具有该属性且值与之不等的用户,返回DN。

前者可以从set中直接读取满足要求的DN,后者必须在每个对象中搜索属性及它的值,找到了才能把DN放进去,前者效率更高

i、逆拓扑算最迟开始时间容易忘记减完后比较原来的时间早还是减完的时间早,没有取最早出错

j、对于下面的图解,应该自己编一个经过所有过程的样例,考虑所有情况

或者用一维数组存待填充内容,用一个二维数组记录每个坐标对应一维数组的下标,填充时根据这个数组的坐标到一维数组取数

b068611a994244e4b6f7ab2f85f995ce.png

k、一个地区被标记后七天封控,要把七天都写如该地区对应的set容器,否则在计算某人是否有风险时再推七天很难覆盖前几天有风险的人

l、比较都用equals方法,不要用==

52、JDBC

下载JDBC看这个:http://t.csdnimg.cn/hQGas

配置JDBC看这个:http://t.csdnimg.cn/Hldfo

8d36ec60153d4a9bb0a2b61e96e67c1d.png

e0b0501955c446699307afccecd7267e.png

5b0ddeb834d845d7ae290ef53c324482.png

8e07802e9ced40ef9fc662db0b0cc77c.png

f8d33e270a6345a1b329b7a81c4bfacf.png 44dee002e04142a08597d4b908881c52.png

3cf276caa5a94384b56d67e8c8c791ce.png 77f6368cb30a41b3bce5a4bf5cdb9cfd.png

注意mysql列的编号从1开始 

1527ee101f024cdd801d2d762108c92d.png

7de034fbdcb340ae91aca12888142d5f.png

55a2487f3df64e8dabed5da2e482c607.png

3edae719c7e44eca873c9a4284aef809.png 360e0c7ac54a4e4ca28b18598795cdf3.png

druid也要设置库 

import com.alibaba.druid.pool.DruidDataSourceFactory;

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

public class Druid {
    public static void main(String[] args) throws Exception {
        System.out.println(System.getProperty("user.dir"));//找到当前位置,复制完粘贴到load里
        //加载配置文件
        Properties prop=new Properties();
        prop.load(new FileInputStream("C:\\Users\\29803\\IdeaProjects\\pro01/src/druid.properties"));
        //prop.load(new FileInputStream("D:\\java/druid.properties"));//扔在d盘也能加载到
        //获取连接池对象
        DataSource dataSource= DruidDataSourceFactory.createDataSource(prop);
        //获取数据库连接
        Connection connection=dataSource.getConnection();
        System.out.println(connection);
    }
}

import java.sql.*;

public class jdbc {
    public static void main(String[] args) throws Exception {//抛出所有异常
        //Class.forName("com.mysql.cj.jdbc.Driver");//注册驱动,我使用的8.1(5之后的版本)版本已经自动注册,不用写
        String url="jdbc:mysql://127.0.0.1:3306/db1?useSSL=false&useServerPrepStmts=true",
                name="root",password="2980313058";
        //useSSL=false用来消除使用SSL提示,useServerPrepStmts=true用来开启PreparedStatement预编译功能
        //我使用的版本不会报此提示,想再加其他参数用&隔开
        Connection conn= DriverManager.getConnection(url,name,password);
        Statement stat=conn.createStatement();
        String sql="UPDATE tb1  SET birth='1141-11-11' WHERE username='aaaa';";
        int count=stat.executeUpdate(sql);
        //count返回受影响的行数
        System.out.println(count);
        //JDBC事务管理
        try {
            conn.setAutoCommit(false);
            int c1=stat.executeUpdate("UPDATE tb1  SET birth='1121-11-11' WHERE username='aaaa';");
            System.out.println("c1 "+c1);
            int c2=stat.executeUpdate("UPDATE tb1  SET birth='1131-11-11' WHERE username='aaaa';");
            //int i=3/0;
            System.out.println("c2 "+c2);
            conn.commit();//不要忘了提交!
        } catch (Exception e) {//删掉SQL前缀,遇到任何异常都回滚
            conn.rollback();
        }
        //JDBC查询
        sql="SELECT * FROM tb1;#查询全部列数据,可以用*代替列名列表,开发时不要用";
        ResultSet re=stat.executeQuery(sql);
        while (re.next())//向下移动光标并判断是否为有效行
        {
            //注意每行数据编号从1开始!
            int id=re.getInt(1);
            String name1=re.getString(2);
            String mm=re.getString(3);
            String nn=re.getString("birth");//也可以用列的名称查
            System.out.println(id+" "+name1+" "+mm+" "+nn);
        }
        //sql注入演示
        //数据库存在的数据
        String name1="aaaa";
        String pwd="12";
        //数据库不存在的数据,两个都可以成功登录
        name1="123424";
        pwd="' or '1'='1";
        sql="SELECT * FROM tb1 WHERE username='"+name1+"'AND password='"+pwd+"';";
        System.out.println(sql);//sql语句遭到篡改
        //防sql注入
        sql="SELECT * FROM tb1 WHERE username=?AND password=?;";
        PreparedStatement pp=conn.prepareStatement(sql);
        System.out.println(pp);
        pp.setString(1,name1);
        pp.setString(2,pwd);//把密码中的引号转译为文本引号
        System.out.println(pp);
        //re=stat.executeQuery(sql);
        re=pp.executeQuery();//防sql注入的赋值方法
        if(re.next())
        {
            System.out.println("登录成功");
        }
        else {
            System.out.println("登录失败");
        }
        //释放资源,re也要放
        re.close();
        stat.close();
        conn.close();
    }
}

c5bde78fb6064e7a827c184d0437a643.png

1fd3ca6aceac478799c728dfa7ef9db6.png

8ddd8d37c2774f90a859e0b533625d4c.png 76a37e9ddb7c40ab8751f5e413b3c9cc.png

e695c810e4624236942d18045c4e3b8c.png

53、maven 

创建maven项目看这个:http://t.csdnimg.cn/qZ48G

每次创建新项目都要重新配置一次maven路径!!!! 

213372c232e7485ba8a2c4efc14ffc53.png

37e766686bf942489cad9d37c8a8755f.png 7a3c35a4c7d8490b82ad004adcbf5b4d.png

99e298ae533443faa7dd233a1932eef5.png d2b77a4962884e149651093001d886a4.png

b44395116e634d778f50eee55979b1d3.png

ec96dde4c10244fdb5bf12e81aa20ecf.png 76041fca27bd4a41b36b3f9ee7271648.png

4eb53b90c8ab458da96c1ca2589b4cef.png 创建java项目ff0294c1f9f246beb482d30df02ab59e.png

创建javaweb项目

64e458756a794b9d96edf391524cc429.png a47ea01dc8fb4c72b99931032966d3de.png

执行maven命令 

15a720f6182d4e35b3241087bb13c53b.png

9e92d39ef4df4665a5958f005a31d3d1.png

cb466a7f968a47feb06f2c91f53b6e19.png

查找坐标:Maven Repository: Search/Browse/Explore (mvnrepository.com) 

进去直接搜索后复制坐标,或者浏览器搜mysql maven进入这个网站

拷好坐标后,点右上角这个按钮下载jar包 

0df8ab5e7e19456a9d1fd0168f074e98.png

如果加载不出来,按它刷新 

2631b213a92b4ad9afcdfaed4f7ec86c.png

或者这样设置,自动生效

a925c8b540c242a1a757563228eb4f3c.png

1446b07e2e2d417d8ad1e5388dc2be87.png 编译环境:main模块下有效

测试环境:test模块下有效 <scope>test</scope>

运行环境:实际运行时有效

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
  <!--当前项目的坐标 -->
    <groupId>org.example</groupId>
    <artifactId>maven</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
  
    <dependencies>  <!--依赖的意思 -->

        <!--导入mysql驱动jar包 -->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.32</version>
            <scope>compile</scope>
            <!--三种环境下有效,不写scope默认是它 -->
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.9</version>
        </dependency>


    </dependencies>

</project>

54、MyBatis

建议来官网查怎么配置配置_MyBatis中文网

326c0408675f4d7d8deda3bfc54365c5.png

370aa7c201ab477ab21dc4ddceeb8f8f.png

f3ebea470be8479b97edbec73a68c685.png

创建配置文件

c98787f432ac43e1b38c9ae7b2d0e7fa.png

idea连接数据库

没有database侧栏看这个:http://t.csdnimg.cn/Xol9x

注意:需要同时安装database navigator和maven helper才能正常用database navigator执行sql语句! 

b34a87a3fce747f096c05af7139497b3.png ab5872909d8c42dbb91342e5aa29c868.png

5a6887544edb4ab4871abafc0fdd902f.png 必须使用/分割才能形成包结构

39802d4831ca41618a7960ca06a72d8d.png 鼠标把xml文件拖进去

不能通过复制得到,重构要建三层文件夹再拖进去

7b3c0bd71826498e8b824bc806819de3.png

7463900f3fe046118663fb0a0228a8d7.png

mybatis-config.xml是mybatis核心配置文件 

environment配置用来连接多个数据库,如development和test环境可以连接不同的数据库,通过default切换数据库连接

010683f8c11d44309063944e54cdeebb.png

4a094bbfb8824f0b93359a63b0fb4cde.png 界面红鸟是映射文件,蓝鸟是接口

想添加sql语句时,随便起个函数名字,然后选中后按alt+enter,这个插件会帮忙在配置文件定义这个语句

f7625255e9a3479a84d9e6c4bfa775d1.png

cf6e0d6638124fd1aa535fe84ef696db.png

df420a627f4547199cbb7513dfab40fa.png

e058d490d447449ba3372adc2adeaad8.png

82569e390b2c4a40a79c699e542c93b6.png

8201f530419a4c69893e80785364110d.png 3e8f9e23b0264bea9257dcb884ced05f.png

705ad7596df54222850ad1937f304d99.png

9d1c2e7b11b44c8cb7b7d1dac74965dc.png 更新数据库后,database navigator需要点左下蓝色图标才能刷新查询结果

38f65563ddef4899bc41b30af957897b.png

9c3f41c112614e61a3ee394ab729682b.png 1287d6d6d4534b2686ede11a7889190c.png

9b34b4e170d2432f86a247a2372ac40f.png

b0cb6bedb37a475cbd674b2f6cfc1be4.png 5acaa5da1a194fa1958164c8cb77e9f1.png

64e2e967089c4fdea413333a6127e407.png 71b54770ebb846db94e95483d4e7c7a3.png

代码及执行

<?xml version="1.0" encoding="UTF-8" ?>
<!--mybatis-config.xml -->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
<!--起别名,扫描zndx包。这样包里的类可以直接用,注意必须在environment上面起别名-->
        <package name="com.zndx"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库连接信息 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="2980313058"/>
            </dataSource>
        </environment>
    </environments>

    <!--加载sql映射文件,mapper是映射的意思,平级可以这样加载:userMapper.xml -->
    <mappers>
        <!--这里路径要改对-->
        <!--<mapper resource="com/zndx/mapper/userMapper.xml"/>-->
        <!--Mapper代理模式用包扫描加载映射文件-->
        <package name="com.zndx.mapper"/>
    </mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!--userMapper.xml-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace名称空间,设置为接口位置 -->
<mapper namespace="com.zndx.mapper.userMapper">
    <!--id是sql语句唯一标识
     resultType是返回结果的类型,这里要返回user对象
     注意数据库表的名称和user类的属性名称不同时,不能自动封装,要手动封装!!!
     起别名例如select brand_name as brandName from tb_user;
     定义sql片段例如(要写在mapper配置里面),缺点是不灵活
     <sql id="brand_column">
         brand_name as brandName
    </sql>
    <select id="ss" resultType="user">
        select <include refid="brand_column"/> from tb_user;
    </select>
     -->

<!--    <select id="selectAll" resultType="com.zndx.user">-->
    <resultMap id="userresultMap" type="user">
        <!--id是映射自己的名字,type指定跟user类映射,里面有id标签,跟主键映射,有result标签和一般字段映射-->
        <result column="brand_name" property="username"/>
        <!--column是表的列名,property是类的属性名-->
    </resultMap>
    <select id="ss" resultMap="userresultMap">
        select * from tb_user;
    </select>
<!--起别名后,这里可以直接用user-->
    <select id="selectAll" resultType="user">
        select * from tb_user;
    </select>

<!--占位符#{}:把语句中此部分替换为?,防sql注入,${}:拼sql,会出现sql注入,用来传不固定的列名、表名-->
<!--参数类型parameterType可以省略不写,&lt是小于号转义字符,或者使用cdata区,打CD-->
    <select id="searchByIdUser" parameterType="int" resultType="user">
        select * from tb_user where id <![CDATA[
         <
        ]]> #{id};
    </select>

    <select id="selectbycondition" resultType="user">
        select * from tb_user where username like #{username} and password = #{password};
    </select>

    <select id="selectbyconditions" resultType="user">
     <!--if里面写的是接口参数名-->
        select * from tb_user
        <!--where 1=1-->
        <!--恒等式后跟and,缺哪一个都不会出错-->
        <!--使用mybatis提供的where标签包裹最好-->
        <where>
        <if test="addr!=null and addr!=''">
            and addr like #{addr}
        </if>
         <!--and不能写外面,不然空时出错-->
        <if test="username!=null and username!=''">
           and username like #{username}
        </if>
        </where>
    </select>


    <select id="selectbyconditionsingle" resultType="com.zndx.user">
        select * from tb_user
        <where>
        <choose><!--相当于switch-->
            <when test="id!=null">
                id=#{id}
            </when>
            <when test="username!=null and username!=''">
                username=#{username}
            </when>
            <when test="password!=null and password!=''">
                password=#{password}
            </when>
            <when test="gender!=null and gender!=''">
                gender=#{gender}
            </when>
            <when test="addr!=null and addr!=''">
                addr=#{addr}
            </when>
            <!--otherwise保险措施,但是最好的方法是用where标签-->
<!--            <otherwise>-->
<!--                1=1-->
<!--            </otherwise>-->
        </choose>
        </where>
    </select>

    <insert id="add" useGeneratedKeys="true" keyProperty="id">
<!--useGeneratedKeys="true" keyProperty="id"把主键id的值返回给对象-->
      insert into tb_user(username,password,gender,addr)
        values(#{username},#{password},#{gender},#{addr});
    </insert>

    <update id="update">
       update tb_user
<!--用set标签避免无被修改参数和addr不需要修改时逗号多余的问题-->
        <set>
        <if test="username!=null and username!=''">
            username=#{username},
        </if>
        <if test="password!=null and username!=''">
            password=#{password},
        </if>
        <if test="gender!=null and gender!=''">
            gender=#{gender},
        </if>
        <if test="addr!=null and addr!=''">
            addr=#{addr}
        </if>
        </set>
         where id=#{id};
    </update>

    <delete id="delByIdInt">
        delete from tb_user where id=#{id};
    </delete>
    <delete id="delByIdInts">
<!--mybatis会把传入的数组封装为map,默认名字是array,可以用@Param("ids")改名-->
        delete from tb_user where id in
        <!--separator是分隔符,item="id"根据id删,open在循环开头补字符,close在结尾补字符-->
        <foreach collection="array" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
        ;
    </delete>
</mapper>

package com.zndx.mapper;
import com.zndx.user;
import org.apache.ibatis.annotations.*;

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

public interface userMapper {
    //明确要返回多个对象时,返回集合
    List<user> selectAll();
    user searchByIdUser(int id);
    // 条件查询可以把参数封对象里,只要xml占位符名称和对象属性名相同即可完成对应
    //或者封map里,map键名和占位符同名即可对应
    //或者用@Param(占位符名)填在参数前面完成对应,替换的是arg0名称
    user selectbycondition(@Param("username")String username,@Param("password")String password);
    //传多个参数时,mybatis会把每个值封进map,键名称就是@Param注解设置的名称,如果没有注解
    //会把每个值封两次,键分别是arg0(1,2递增),param0(递增),在映射文件中可以用这些名称使用值,但不推荐
    //如果传入Collection类型,按map("Collection",内容),map("arg0",内容)封装
    //如果传入List,按map("Collection",内容),map("arg0",内容),map("list",内容)封装
    //如果传入array,按map("arg0",内容),map("array",内容封装)
    user selectbycondition (user user);
    user selectbycondition(Map map);
    //多条件动态查询:用户不会完整填写所有条件
    List<user> selectbyconditions(@Param("addr") String addr,@Param("username")String username);
    List<user> selectbyconditionsingle(Map map);
    void add(user user);
    int update(user user);
    //按id删除
    int delByIdInt(int id);
    //按id批量删除
    int delByIdInts( int[] ids);
    //通过注解完成简单开发,另外还有@Update(),@Delete(),@Insert()等
    @Select("select * from tb_user;")
    List<user> zhujiechazhao();
}
package com.zndx;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.zndx.mapper.userMapper;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//写测试用例
public class test {
    public static void main(String[] args) throws Exception {
        //这里直接粘贴官网代码,没有import导致报错
        //1、加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "mybatis-config.xml";//这里忘记改了,用官网复制的值导致报错
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //2、获取sqlSession对象,用它执行sql
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //2.1调用id依然存在硬编码问题
        List<user> users= sqlSession.selectList("com.zndx.mapper.userMapper.selectAll");//这里id写错了导致报错
        //2.2获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        users=userMapper.selectAll();
        System.out.println(users);
        System.out.println(userMapper.searchByIdUser(2));
        System.out.println(1+""+userMapper.selectbycondition("李四","234"));
        user a=new user();a.setUsername("李四");a.setPassword("234");
        System.out.println(2+""+userMapper.selectbycondition(a));
        Map<String,String> map=new HashMap<>();
        map.put("username","%四");map.put("password","234");
        System.out.println(3+""+userMapper.selectbycondition(map));
        String addr="",use="%%";
        users=userMapper.selectbyconditions(addr,use);
        System.out.println(users);
        map.clear();
        map.put("gender","男");
        map.clear();
        System.out.println(userMapper.selectbyconditionsingle(map));
        //insert
        a.setUsername("周六");a.setPassword("520");a.setGender("女");a.setAddr("tj");
        userMapper.add(a);
        System.out.println(a.getId());
        sqlSession.commit();
        //因为insert采用事务方式,要手动提交,或者在获取对象时设置自动提交
        a.setId(4);a.setUsername("刘七");a.setPassword("521");a.setGender("男");a.setAddr("南定");
        int b=userMapper.update(a);
        System.out.println(b);//修改成功返回1,失败返回0
        sqlSession.commit();//这里也要提交
        a.setId(7);a.setUsername("赵八");a.setAddr(null);
        System.out.println(userMapper.update(a));
        sqlSession.commit();//这里也要提交
        System.out.println(userMapper.delByIdInt(8));
        sqlSession.commit();//这里也要提交
        int[] ids={9,12,13,14,15,16,17,18,19,20,21,22};
        System.out.println(userMapper.delByIdInts(ids));//返回影响行数
        sqlSession.commit();//这里也要提交
        System.out.println(userMapper.zhujiechazhao());
        //3、释放资源
        sqlSession.close();
    }
}

项目结构

138b4fc8ec96477b942199cbad1aa8b3.png

运行结果

1417384ca06641319f8dd257fbbb5159.png a45a4fffa4b947c39ba4b70f53715e7d.png

55、web核心

感谢大佬的api文档:http://t.csdnimg.cn/xnMkM

20742266cdfa4dbeb1d708470481daf4.png

2fa2d8f218444203b64536fbfbdb41f9.png

88186520223f4b1f8f3f19269cf027ab.png

cf3105d3d22c4a93a4b8528168374c08.png

5044e9ad76284df9b7c77cdb903eaf88.png 38cca68bd73345c39cd2acbc0cd1076c.png

50a08bdedc7c4ebc9dfe50d4be373ade.png 建议正常关闭,强制关可能丢失数据e5dd4fded161402180bea71bcac04ea9.png

dd9860c8dad743289df857b30660edac.png 60f431e91d174524bdfd4bb52e787fd5.png

8a8bbbb6d8ce4cc3831d0b0c09268026.png c3115750fc984367838d463fdea83e9d.png

eecf8fcf63d542a28cf05a9445493539.png d357ceefb0ca44fbb2c3ec10b03b6754.png

25ac449034614388aa22161224e6deb5.png

03c09ef8589b48779fcff34db4dca516.png 5a9234b98d3846bfa362aa6ae7072798.png

c7ebeb40cadd47fe89376582e3b258e1.png 753436ea14014e4a964a22197e633371.png

多次run tomcat 会出现Failed to initialize end point associated with ProtocolHandler错误,停止这些进程即可

tomcat默认在网址头后访问webapp里面的文件,如 localhost/html.html,其中的html.html文件正好在webapp目录下

在idea的终端页面输入mvn tomcat7:run命令启动tomcat,再按ctrl+c才能正常关闭tomcat,按红点是强制关闭

在当前模块的pom.xml设置访问的虚拟目录

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.example</groupId>
        <artifactId>maven</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>tomcat</artifactId>
<!--两种打包方式:jar(默认值)和war(web项目)-->
    <packaging>war</packaging>
    <name>tomcat Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
<!--导入servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
<!--因为tomcat里已经有了servlet,运行环境再导入会报错,需要排除-->
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>tomcat</finalName>
        <!--tomtat插件部署-->
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>80</port>
               <!--这个aa就是虚拟目录!!-->
                    <path>/aa</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

1efe117fb041408db33ffc1679edb10c.png 31ec285772254d378ea9a0d2ce9b499f.png

e40219160d9c412f952bfc9c86ed75d5.png 7640ae06668b49bfa701493fdd6585dd.png

9fd2cbf3d0b44a2887ec0ccecfe3d960.png d16106b78dee4256a97aec65e8dfa55e.png

fa7572413bae46aaa87faf336e012d4b.png

0c9257da27c0458cb039b12e8a6970c6.png  

精确匹配和目录匹配同时存在时,输入精确匹配的路径会访问到精确匹配的servlet 

配置/会导致无法访问静态资源,不要这样配

8c26dcdea59848e6beed21802886eb5f.png

73a84684103a4b8db76249624e3322d3.png

d6fa46b13f294278b8f3fb3b26a392d8.png

66a6094b4ca442668b52c635e2aab3b7.png f73750474d7149dd9389361f2c2cc8e5.png

85700267d0604e65818f771842ea57cd.png社区版设置不了

a9083e9ed5b848d6bfe8178d16bcf910.png 虽然我的tomcat版本是8,但是idea的tomcat插件仅支持到tomcat7,所以还是有这个问题

ef626c6c56984986a60967042774d662.png 04800893be80467cac3f2bab304438a3.png

14bb7425ff5b465794bde3ea6b41aabc.png

6dc8a07eaec54ec99e680191127789fd.png 37025b7123354c1f87c1ecb3585364c8.png

b2b4daa1c6214eb69e1deacfd88d4643.png

923d10fb4c124c72b37942b73ed15f03.png 721519f7482b4bc1a2690c83211fce40.png

58c28e16d6de4f218423b7e307b9fb3f.png

e8f9388f38234c81a8927b1aac6aa368.png

package com.zndx.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
//SqlSessionFactory只能创建一次,多了浪费资源
//利用这个工具类完成
public class sqlsessionfactoryutils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        //静态代码块随类加载自动执行,且只执行一次
        //1获取SqlSessionFactory对象
        String resource = "mybatis-config.xml";//这里忘记改了,用官网复制的值导致报错
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    public static SqlSessionFactory sqlSessionFactoryget()
    {
        return sqlSessionFactory;
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<div id="logindiv">
    <form action="/aa/loginServlet" method="post" id="form">
        <h1 id="loginMsg">登录</h1>
        <p>username:<input id="username" name="username" type="text"></p>
        <p>password:<input id="password" name="password" type="password"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">
            <a href="register.html">没有账号?来注册</a>
        </div>
    </form>
</div>
</body>
</html>
import com.zndx.mapper.userMapper;
import com.zndx.utils.sqlsessionfactoryutils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.zndx.*;

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.InputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        if(method.equals("POST"))
        {
            System.out.println("post...");
            //解决post中文乱码
            req.setCharacterEncoding("UTF-8");
        }
        //接受用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(method.equals("GET"))
        {
            System.out.println("get...");//浏览器输url是get方式,在控制台打印这句话
            //解决get中文乱码,这行代码post也能用
            username=new String(username.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
            password=new String(password.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
        }

        //1获取SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
        //2、获取sqlSession对象,用它执行sql
        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //3获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //4获取user对象
        user user=userMapper.select(username,password);
        //5释放资源
        sqlSession.close();
        //6获取字符输出流并设置字符集
        resp.setContentType("text/html;charset=utf-8");//告诉浏览器传的是html和需要的字符集
        PrintWriter printWriter=resp.getWriter();//获取的这个流不需要关闭
       //7显示登录结果
       if(user!=null)
       {
           printWriter.write("登录成功");
       }
       else {
           printWriter.write("登录失败");
       }

    }

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
<div id="registerdiv">
    <form action="/aa/RegisterServlet" method="post" id="form">
        <h1 id="loginMsg">注册</h1>
        <p>username:<input id="username" name="username" type="text"></p>
        <p>password:<input id="password" name="password" type="password"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">
            <a href="login.html">注册好了?来登录</a>
        </div>
    </form>
</div>
</body>
</html>
import com.zndx.mapper.userMapper;
import com.zndx.utils.sqlsessionfactoryutils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.zndx.*;

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.InputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet("/RegisterServlet")//复制过来没改路径,跟login重名报错
// A child container failed during start
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        if(method.equals("POST"))
        {
            System.out.println("post...");
            //解决post中文乱码
            req.setCharacterEncoding("UTF-8");
        }
        //接受用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(method.equals("GET"))
        {
            System.out.println("get...");//浏览器输url是get方式,在控制台打印这句话
            //解决get中文乱码,这行代码post也能用
            username=new String(username.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
            password=new String(password.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
        }

        //1获取SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
        //2、获取sqlSession对象,用它执行sql
        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //3获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //4获取user对象s
        Map<String,String> map=new HashMap<>();
        map.put("username",username);
        List<user> list=userMapper.selectbyconditionsingle(map);
        //5获取字符输出流并设置字符集
        resp.setContentType("text/html;charset=utf-8");//告诉浏览器传的是html和需要的字符集
        PrintWriter printWriter=resp.getWriter();//获取的这个流不需要关闭
       //6显示注册结果
       if(list.isEmpty())
       {
           user user=new user();
           user.setUsername(username);
           user.setPassword(password);
           int a=userMapper.add(user);
           sqlSession.commit();//又忘记提交事务了
           System.out.println("add:"+a);
           printWriter.write("注册成功");
       }
       else {
           printWriter.write("注册失败");
       }
        //7释放资源
        sqlSession.close();
    }

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

56、jsp

d6b4fcc70e78441888f6229bb132550b.png

0931fd6cb9c74d319ba5720e611a521c.png

32a5f0dff6794a6d8d5f6d99ae35c141.png

b7c4d07520f140ecb07ab7df29dffb94.png a0db8625e8df49e39efb487f8257bef2.png

d19364bc619543b085e79809aa375fae.png 0e2401f5f68d4af2bf7658282fe1d70e.png

el表达式不能用看这个:http://t.csdnimg.cn/AJqqJ 

7e988eb178044ddba2440920d855c9f1.png

574a825a69fc4c4cbc9d339b1367b2d7.png dd461d0371f544e186ee291838e3e993.png

3bcbd5f8866a4f98b9348f1310fcb635.png

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%-- 启用el表达式,没有的话会把el表达式直接当文字显示 --%>
<html>

<body>
<c:if test="${msg!=null}">
<h1>true</h1>
</c:if>
<%-- forEach只能用来遍历对象,工作原理是输入对象的属性名,然后找到对应的get方法获取值 --%>
<c:forEach items="${b}" var="aa" varStatus="s">
<%--0开始的序号 --%>
<h2>${s.index}</h2>
<%-- 1开始的序号 --%>
<h2>${s.count}</h2>
<h2>${aa.id}</h2>
<h2>${aa.gender}</h2>
<h2>${aa.password}</h2>
</c:forEach>
<c:forEach begin="1" end="10" step="1" var="i">
<a href="#">${i}</a>
</c:forEach>
<h2>Hello World123!</h2>
<%
System.out.println("hello jsp");
show();
Integer i=-3;
%>
 ${a}
 ${msg}
<%
if(i>0)
{
%>
<h1><%=i.intValue()+1%></h1>
<%
}
else
{
%>
<h1><%=i.intValue()-1%></h1>
<%
}
%>

<%=
"hello1\n"
%>
<%=
i
%>

<%!
static void show(){System.out.println(name);}
static String name="Aaaa";
%>
<br>
</body>
</html>
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.BufferedReader;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.zndx.user;

@WebServlet(urlPatterns = "/demo2",loadOnStartup = -1)
public class httpser extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //请求转发,内部不需要写虚拟目录
        req.setAttribute("msg","hello");//转发前存储数据
        req.removeAttribute("name");
        Map a=new HashMap();
        a.put("msg","11");a.put("aaa","22");
        req.setAttribute("a",a);
        user b=new user();
        b.setId(1);b.setGender("boy");b.setPassword("213");
        List<user> bb=new ArrayList<>();
        bb.add(new user(1,"11","12","boy","123"));
        bb.add(b);
        req.setAttribute("b",bb);
        //原来是转发到/demo0的/index.jsp
        req.getRequestDispatcher("/index.jsp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //需要利用post表单访问

        //req.setCharacterEncoding("UTF-8");//post设置字符输入流的编码,解决中文输入错误
        //可能是因为req.getReader()只能调用一次,下面的代码调用后req.getParameterMap()无法调用,显示全null
//        BufferedReader reader = req.getReader();
//        String s = reader.readLine();
//        System.out.println(s);
          doGet(req,resp);//Map<String,String[]> map=req.getParameterMap();可以统一操作

//        Map<String,String[]> map=req.getParameterMap();
//        //System.out.println(map);
//        for (String key:map.keySet())
//        {
//            System.out.print("key "+key);
//            String[] value=map.get(key);
//            for (String value1:value)
//            {
//                System.out.println(" value "+value1+" ");
//            }
//            System.out.println();
//        }
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doDelete(req, resp);
    }
}

f21b8aef6c674678ad20ecda7674d5c8.png

e9b19b55b8454ff280efe94416a39a51.png

加入service层是为了提高代码复用性 

09b7ad8fc4fc477685b754668b753b51.png d8a67e53b480475c8a6a0cb1f30fbb8f.png

a2197800e56f45e0b58e4068957603cc.png 9b74101fba964953a051a09cf2c281d7.png

57、会话跟踪技术 

f58ab182735740e3a3ea1de6239ef89e.png 3e665d874d3a47748bfa57732556c7df.png

1e4d9b0c6c4e493aa4a8503c8b56c462.png d935284ff0b64b2d8ee493704424e388.png

session可以保存在服务器硬盘中,关服务器再打开仍然有效,但是浏览器关闭后再打开,就获取不到相同的session,而cookie可以设置存活时间,存用户端硬盘里,关浏览器再打开仍然有效 

a1161a1afce641ac8f03d76b41e5bf58.png d03c9d2a6fd94f3096f3b713a3ec63f8.png

54d703da50c1430a8976e968cf5de3c2.png 72c1baf8704d47299998a1bc20ebdbc2.png

1efc7a4d03d44e1aad6cacc56df377b2.png ca45a56385ff463c830e4533891b70db.png

a12b30b95335426d9f76382716e6964e.png 89e1d9588cc942b190555ca123c4719a.png

7ed6a43fa3c94aeaa95e1bab2257a4f9.png 要自己加工具类:http://t.csdnimg.cn/7MTOk5b300a1c6c5f4898921df4ff2d0d5011.png

7b831ac4c2dc419d91d0a94f28d987a7.png

9f433c6030084057bcf88d6a812982fe.png

cea4d56914094128be6ec66a9287cd98.png

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%-- 启用el表达式,没有的话会把el表达式直接当文字显示 --%>
<%-- 不输入资源时,默认访问index --%>
<!--html5的标识-->
<%-- html.jsp --%>
<!DOCTYPE html>
<html lang="en">
<head>
    <!--页面的字符集-->
    <meta charset="UTF-8">
    <title>html快速入门</title>
</head>
<!--html语法松散,如"red"不加引号,不写</font>都可以正确执行-->
<!--被干掉的标签表示过时了,它们的任务应该让css完成-->
<body>
<center><h1>这是最大的标题字体</h1></center>
<hr>
<!--html表示颜色
1、英文单词,不方便
2、rgb(1,2,3), 三原色取值在0~255之间
3、十六进制三原色,推荐,取值在00~ff之间"#ff0000"
-->
<center><font color="ff0000" size="5" face="楷体"> <p>head标题  html快速入门 显示在网页上面,这些文字写在body里<br></p>
  <p>另外html的标签不区分大小写</p>
    <b>b标签功能<br></b>
    <i>i标签功能<br></i>
    <u>u标签功能<br></u>
    <h2>${finish},欢迎您</h2>
</font>
</center>
<hr>
<!--资源路径:
1、绝对路径:例如完整的图片链接和d盘完整的文件路径
2、相对路径:相对位置关系
例如此文件路径com/zndx/html/html.html
图片路径com/zndx/html/a.gif
此时可以把前面相同的路径写成./,而./本身又可以省略,最后写a.gif就可以了
如果图片在html目录下的img目录中,img/a.gif
如果在zndx目录下的img目录中,../img/a.gif,其中../表示往上推一层目录
尺寸单位:数字表示像素,20%表示占body窗体的20%
-->
<%--默认从虚拟目录下开始访问,所以要填html/,否则找不到资源 --%>
<img src="html/a.gif" width="200" height="300">
<img src="https://pic35.photophoto.cn/20150511/0034034892281415_b.jpg" width="100" height="100">
<audio src="html/c.mp3" controls></audio>
<video src="html/b.mp4" controls width="200" height="300"></video>
<a target="_blank" href="https://blog.csdn.net/sunxiaofre/article/details/55805420?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169636590316800184194099%2522%252C%2522scm
%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=169636590316800184194
099&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ec
pm-2-55805420-null-null.142^v94^insert_down1&utm_term=htmlfont%E6%A0%87%E7%AD%BE%E8%A2%AB%E4%BB%80%
E4%B9%88%E6%9B%BF%E6%8D%A2%E4%BA%86&spm=1018.2226.3001.4187">好好学习!</a>
<ol type="i">
    <li>aa</li>
    <li>bb</li>
    <li>cc</li>
</ol>
<ul type="circle">
    <li>aa</li>
    <li>bb</li>
    <li>cc</li>
</ul>
<table border="1" cellspacing="0" width="500" >
    <tr align="center">
<!--        <th>id</th>-->
<!--        让第一个单元格占两个位置-->
        <th  colspan="2">username</th>
        <th>gender</th>
    </tr>
    <tr align="center">
        <td>1</td>
        <td rowspan="2"><img src="html/a.gif" width="50" height="50"></td>
        <td>boy</td>
    </tr>
    <tr align="center" >
        <td>2</td>
<!--        <td>李四</td>-->
        <td>女</td>
    </tr>
</table>
<div>这是div</div>
<div>这是div</div>
<span>这是span</span>
<span>这是span</span>
<!--action:指定表单数据提交的URL,#表示提交给当前html页面
表单数据想被提交,还要再指定应该name属性
method:指定表单提交方式
1、get:默认值,把请求参数拼接在url后面,请求参数因url长度有限而有限制,例如下面执行后
http://localhost:63342/maven/html/html.html?username=2098516801%40qq.com#
2、post:请求在http协议的请求体中,请求参数无限制
-->
<form action="#" method="get">
    <input type="text" name="username">
<!--    其中username为键,提交数据作为值,传到服务端-->
    <input type="submit">
</form>

<form action="#" method="post">
    <input type="hidden" name="id" value="123">
<!--    使点击用户名时选中username输入框-->
    <label for="username">用户名:</label>
    <input type="text" name="username" id="username"><br>
    密码:<input type="password" name="password"><br>
    性别:<input type="radio" name="gender" value="1" id="m"> <label for="m">男</label>
    <input type="radio" name="gender" value="0" id="n"> <label for="n">女</label><br>
<!--    name值相同才能得到互斥效果,必须有value区分两个选项,不然到服务端都是on-->
    爱好:<input type="checkbox" name="hobby" value="1"> 旅游
    <input type="checkbox" name="hobby" value="2"> 电影
    <input type="checkbox" name="hobby" value="3"> 游戏<br>
     头像:<input type="file"><br>
     城市:<select name="city">
<!--    提交的数据以value为准,没有value填aa等-->
    <option value="aa1">aa</option>
    <option>bb</option>
    <option>cc</option>
     </select><br>
    个人描述:<textarea cols="5" rows="20" name="desc"></textarea><br>
<!--    20行,每行五字符-->
    <input type="reset">
    <input type="submit" value="免费注册"><!--value修改文本内容-->
    <input type="button" value="一个按钮">

</form>
</body>
</html>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%-- 启用el表达式,没有的话会把el表达式直接当文字显示 --%>
<%-- 不输入资源时,默认访问index --%>
<%-- login.jsp --%>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<div id="logindiv">
    <form action="/aa/loginServlet" method="post" id="form">
        <h1 id="loginMsg">登录</h1>
         <div id="error">${error}${finish}</div>
        <p>username:<input id="username" name="username" type="text" value="${cookie.username.value}"></p>
        <p>password:<input id="password" name="password" type="password" value="${cookie.password.value}"></p>
        <p>remember:<input id="remember" name="remember" type="checkbox" value="1"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">
            <a href="register.jsp">没有账号?来注册</a>
        </div>
    </form>
</div>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%-- 启用el表达式,没有的话会把el表达式直接当文字显示 --%>
<%-- 不输入资源时,默认访问index --%>
<%-- register.jsp --%>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>

<body>
<div id="registerdiv">
    <form action="/aa/RegisterServlet" method="post" id="form">
        <h1 id="loginMsg">注册</h1>
        <div id="error">${error}</div>
        <p>username:<input id="username" name="username" type="text"></p>
        <p>password:<input id="password" name="password" type="password"></p>
        <p><input name="check" type="text" id="check"><img src="/aa/checkServlet" id="checkcode"></p>
                <a href="#" id="change">看不清?</a>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">
            <a href="login.html">注册好了?来登录</a>
        </div>
    </form>
</div>
<script>
 document.getElementById("change").onclick=function()
    {//加上new Date().getMilliseconds()使每次url不一样,避免缓存图片而无法刷新
        document.getElementById("checkcode").src="/aa/checkServlet?"+ new Date().getMilliseconds();
    }
</script>
</body>
</html>
import com.zndx.mapper.userMapper;
import com.zndx.service.userservice;
import com.zndx.utils.sqlsessionfactoryutils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.zndx.*;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet("/RegisterServlet")//复制过来没改路径,跟login重名报错
// A child container failed during start
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        if(method.equals("POST"))
        {
            System.out.println("post...");
            //解决post中文乱码
            req.setCharacterEncoding("UTF-8");
        }
        //接受用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String check = req.getParameter("check");
        HttpSession session1 = req.getSession();
        String checkcode = (String)session1.getAttribute("checkcode");
        if(!checkcode.equalsIgnoreCase(check))
        {
            //存失败数据到req
            req.setAttribute("error","验证码错误");
            //转发请求
            req.getRequestDispatcher("/register.jsp").forward(req,resp);
            return;
        }
        //获取cookie数组
        Cookie[] cookies=req.getCookies();
        //遍历数组
        for (Cookie cookie:cookies)
        {
            String name=cookie.getName();
            if(name.equals("username"))
            {
                String value = cookie.getValue();
                //解码
                value= URLDecoder.decode(value,"utf-8");
                System.out.println(name+" "+value);
                break;
            }
        }
        //获取session
        HttpSession session = req.getSession();
        //取出值
        Object username1 = session.getAttribute("username");
        System.out.println(username1);
        //删除这个键值对
        session.removeAttribute("username");
        //删除session
        session.invalidate();
        if(method.equals("GET"))
        {
            System.out.println("get...");//浏览器输url是get方式,在控制台打印这句话
            //解决get中文乱码,这行代码post也能用
            username=new String(username.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
            password=new String(password.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
        }

        //1获取SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
        //2、获取sqlSession对象,用它执行sql
        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //3获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //4获取user对象s
        Map<String,String> map=new HashMap<>();
        map.put("username",username);
//        List<user> list=userMapper.selectbyconditionsingle(map);
//同理,调用service层实现功能
        List list= userservice.selectbyname(username);
        //5获取字符输出流并设置字符集
        resp.setContentType("text/html;charset=utf-8");//告诉浏览器传的是html和需要的字符集
        PrintWriter printWriter=resp.getWriter();//获取的这个流不需要关闭
       //6显示注册结果
       if(list.isEmpty())
       {
           user user=new user();
           user.setUsername(username);
           user.setPassword(password);
           int a=userMapper.add(user);
           sqlSession.commit();//又忘记提交事务了
           System.out.println("add:"+a);
           printWriter.write("注册成功");
           //存成功数据到req
           req.setAttribute("finish","注册成功,请登录");
           //转发请求
           req.getRequestDispatcher("/login.jsp").forward(req,resp);
       }
       else {
           printWriter.write("注册失败");
           //存失败数据到req
           req.setAttribute("error","用户名已存在");
           //转发请求
           req.getRequestDispatcher("/register.jsp").forward(req,resp);
       }
        //7释放资源
        sqlSession.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
import com.zndx.mapper.userMapper;
import com.zndx.utils.sqlsessionfactoryutils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.zndx.*;
import com.zndx.service.*;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
//web层
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        if(method.equals("POST"))
        {
            System.out.println("post...");
            //解决post中文乱码
            req.setCharacterEncoding("UTF-8");
        }
        //接受用户名、密码和复选框值
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String remember = req.getParameter("remember");

        if(method.equals("GET"))
        {
            System.out.println("get...");//浏览器输url是get方式,在控制台打印这句话
            //解决get中文乱码,这行代码post也能用
            username=new String(username.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
            password=new String(password.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
        }

//        //1获取SqlSessionFactory对象
//        SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
//        //2、获取sqlSession对象,用它执行sql
//        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
//        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
//        //3获取userMapper接口的代理对象(Mapper代理法)
//        userMapper userMapper=sqlSession.getMapper(userMapper.class);
//        //4获取user对象
//        user user=userMapper.select(username,password);
//        //5释放资源
//        sqlSession.close();
        //上面的都可以写到service层里,这里调用即可
        user user=userservice.select(username,password);
        //6获取字符输出流并设置字符集
        resp.setContentType("text/html;charset=utf-8");//告诉浏览器传的是html和需要的字符集
        PrintWriter printWriter=resp.getWriter();//获取的这个流不需要关闭
       //7显示登录结果
       if(user!=null)
       {
           printWriter.write("登录成功");
           if("1".equals(remember))
           {//因为1永不为空,避免remember为空调用不了equals的异常
               //转码,以支持中文
               String username1= URLEncoder.encode(username,"utf-8");
               String encode = URLEncoder.encode(password, "utf-8");
               //创建cookie对象
               Cookie cookie=new Cookie("username",username1);
               Cookie cookie1=new Cookie("password",encode);
               //设置cookie存活时间,一周七天
               cookie.setMaxAge(60*60*24*7);
               cookie1.setMaxAge(60*60*24*7);
               //发送cookie
               resp.addCookie(cookie);
               resp.addCookie(cookie1);
           }
           //跳转到html.jsp
           //创建session对象
           HttpSession session = req.getSession();
           //设置session
           session.setAttribute("username",username);
           //动态获取虚拟目录
           String contextPath = req.getContextPath();
           //响应重定向
           resp.sendRedirect(contextPath+"/htmlServlet");
       }
       else {
           printWriter.write("登录失败");
           //存失败数据到req
           req.setAttribute("error","用户名或密码错误");
           //转发请求
           req.getRequestDispatcher("/login.jsp").forward(req,resp);
       }

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
package com.zndx.mapper;

import com.zndx.user;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;
//Dao层/mapper层
public interface userMapper {
    //明确要返回多个对象时,返回集合
    @ResultMap("userresultMap")//使用这个映射
    List<user> selectAll();
    user searchByIdUser(int id);
    // 条件查询可以把参数封对象里,只要xml占位符名称和对象属性名相同即可完成对应
    //或者封map里,map键名和占位符同名即可对应
    //或者用@Param(占位符名)填在参数前面完成对应,替换的是arg0名称
    user selectbycondition(@Param("username")String username,@Param("password")String password);
    //传多个参数时,mybatis会把每个值封进map,键名称就是@Param注解设置的名称,如果没有注解
    //会把每个值封两次,键分别是arg0(1,2递增),param0(递增),在映射文件中可以用这些名称使用值,但不推荐
    //如果传入Collection类型,按map("Collection",内容),map("arg0",内容)封装
    //如果传入List,按map("Collection",内容),map("arg0",内容),map("list",内容)封装
    //如果传入array,按map("arg0",内容),map("array",内容封装)
    user selectbycondition (user user);
    user selectbycondition(Map map);
    //多条件动态查询:用户不会完整填写所有条件
    List<user> selectbyconditions(@Param("addr") String addr,@Param("username")String username);
    List<user> selectbyconditionsingle(Map map);
    int add(user user);
    int update(user user);
    //按id删除
    int delByIdInt(int id);
    //按id批量删除
    int delByIdInts( int[] ids);
    //通过注解完成简单开发,另外还有@Update(),@Delete(),@Insert()等
    @Select("select * from tb_user;")
    List<user> zhujiechazhao();
    @Select("select * from tb_user where username=#{username} and password=#{password}")
    user select(@Param("username")String username,@Param("password")String password);
}
package com.zndx.service;

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

import com.zndx.*;
import com.zndx.mapper.userMapper;
import com.zndx.utils.sqlsessionfactoryutils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
//service层
public class userservice {
    private static SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
    //如果不用静态方法,web层要
    // userservice userservice=new userservice();(做属性)
    // userservice.select(username,password);
    public static user select(String username, String password)
    {
        //1获取SqlSessionFactory对象
        //SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
        //2、获取sqlSession对象,用它执行sql
        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //3获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //4获取user对象
        user user=userMapper.select(username,password);
        //5释放资源
        sqlSession.close();
        return user;
    }

    public static  List<user> selectbyname(String username)
    {
        //1获取SqlSessionFactory对象
        //SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
        //2、获取sqlSession对象,用它执行sql
        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //3获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //4获取user对象s
        Map<String,String> map=new HashMap<>();
        map.put("username",username);
        List<user> list=userMapper.selectbyconditionsingle(map);
        return list;
    }
}
package com.zndx.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
//SqlSessionFactory只能创建一次,多了浪费资源
//利用这个工具类完成
public class sqlsessionfactoryutils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        //静态代码块随类加载自动执行,且只执行一次
        //1获取SqlSessionFactory对象
        String resource = "mybatis-config.xml";//这里忘记改了,用官网复制的值导致报错
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    public static SqlSessionFactory sqlSessionFactoryget()
    {
        return sqlSessionFactory;
    }
}
<?xml version="1.0" encoding="UTF-8" ?>
<!--userMapper.xml-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace名称空间,设置为接口位置 -->
<mapper namespace="com.zndx.mapper.userMapper">
    <!--id是sql语句唯一标识
     resultType是返回结果的类型,这里要返回user对象
     注意数据库表的名称和user类的属性名称不同时,不能自动封装,要手动封装!!!
     起别名例如select brand_name as brandName from tb_user;
     定义sql片段例如(要写在mapper配置里面),缺点是不灵活
     <sql id="brand_column">
         brand_name as brandName
    </sql>
    <select id="ss" resultType="user">
        select <include refid="brand_column"/> from tb_user;
    </select>
     -->

<!--    <select id="selectAll" resultType="com.com.com.zndx.user">-->
    <resultMap id="userresultMap" type="user">
        <!--id是映射自己的名字,type指定跟user类映射,里面有id标签,跟主键映射,有result标签和一般字段映射-->
        <result column="brand_name" property="username"/>
        <!--column是表的列名,property是类的属性名-->
    </resultMap>
    <select id="ss" resultMap="userresultMap">
        select * from tb_user;
    </select>
<!--起别名后,这里可以直接用user-->
    <select id="selectAll" resultType="user">
        select * from tb_user;
    </select>

<!--占位符#{}:把语句中此部分替换为?,防sql注入,${}:拼sql,会出现sql注入,用来传不固定的列名、表名-->
<!--参数类型parameterType可以省略不写,&lt是小于号转义字符,或者使用cdata区,打CD-->
    <select id="searchByIdUser" parameterType="int" resultType="user">
        select * from tb_user where id <![CDATA[
         <
        ]]> #{id};
    </select>

    <select id="selectbycondition" resultType="user">
        select * from tb_user where username like #{username} and password = #{password};
    </select>

    <select id="selectbyconditions" resultType="user">
     <!--if里面写的是接口参数名-->
        select * from tb_user
        <!--where 1=1-->
        <!--恒等式后跟and,缺哪一个都不会出错-->
        <!--使用mybatis提供的where标签包裹最好-->
        <where>
        <if test="addr!=null and addr!=''">
            and addr like #{addr}
        </if>
         <!--and不能写外面,不然空时出错-->
        <if test="username!=null and username!=''">
           and username like #{username}
        </if>
        </where>
    </select>


    <select id="selectbyconditionsingle" resultType="com.zndx.user">
        select * from tb_user
        <where>
        <choose><!--相当于switch-->
            <when test="id!=null">
                id=#{id}
            </when>
            <when test="username!=null and username!=''">
                username=#{username}
            </when>
            <when test="password!=null and password!=''">
                password=#{password}
            </when>
            <when test="gender!=null and gender!=''">
                gender=#{gender}
            </when>
            <when test="addr!=null and addr!=''">
                addr=#{addr}
            </when>
            <!--otherwise保险措施,但是最好的方法是用where标签-->
<!--            <otherwise>-->
<!--                1=1-->
<!--            </otherwise>-->
        </choose>
        </where>
    </select>

    <insert id="add" useGeneratedKeys="true" keyProperty="id">
<!--useGeneratedKeys="true" keyProperty="id"把主键id的值返回给对象-->
      insert into tb_user(username,password,gender,addr)
        values(#{username},#{password},#{gender},#{addr});
    </insert>

    <update id="update">
       update tb_user
<!--用set标签避免无被修改参数和addr不需要修改时逗号多余的问题-->
        <set>
        <if test="username!=null and username!=''">
            username=#{username},
        </if>
        <if test="password!=null and username!=''">
            password=#{password},
        </if>
        <if test="gender!=null and gender!=''">
            gender=#{gender},
        </if>
        <if test="addr!=null and addr!=''">
            addr=#{addr}
        </if>
        </set>
         where id=#{id};
    </update>

    <delete id="delByIdInt">
        delete from tb_user where id=#{id};
    </delete>
    <delete id="delByIdInts">
<!--mybatis会把传入的数组封装为map,默认名字是array,可以用@Param("ids")改名-->
        delete from tb_user where id in
        <!--separator是分隔符,item="id"根据id删,open在循环开头补字符,close在结尾补字符-->
        <foreach collection="array" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
        ;
    </delete>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!--mybatis-config.xml -->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
<!--起别名,扫描zndx包。这样包里的类可以直接用,注意必须在environment上面起别名-->
        <package name="com.zndx"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库连接信息 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false&amp;useServePrepStmts=true"/>
                <property name="username" value="root"/>
                <property name="password" value="2980313058"/>
            </dataSource>
        </environment>
    </environments>

    <!--加载sql映射文件,mapper是映射的意思,平级可以这样加载:userMapper.xml -->
    <mappers>
        <!--这里路径要改对-->
        <!--<mapper resource="com/zndx/mapper/userMapper.xml"/>-->
        <!--Mapper代理模式用包扫描加载映射文件-->
        <package name="com.zndx.mapper"/>
    </mappers>
</configuration>

58、Filter&Listener

b6a8be9db3c546df899b939c0318be8f.png

77355dc1dd28419aacf7fbfc9f8805f0.png d3d635de37b1498aaa767b49842c41a0.png

8b18ef85b70d4f249077767c43af648e.png d8083dec846143cb93a4498b2278788c.png

package Filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import com.zndx.*;
@WebFilter("/*")
public class LoginFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       //类型不一样,先强转
       HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
        //判断访问资源是否与登录注册有关
        String[] urls={"/login.jsp","/register.jsp","/loginServlet","/RegisterServlet","/checkServlet"};
        //获取当前访问资源路径
        String url = httpServletRequest.getRequestURL().toString();
        System.out.println(url);
        for (String u:urls)
        {
            if(url.contains(u))
            {
                System.out.println("jin");
                filterChain.doFilter(servletRequest,servletResponse);
                //无关资源再执行下面的代码没有意义,直接返回
                return;
            }
        }
        HttpSession session = httpServletRequest.getSession();
        //session.invalidate();
        Object user=session.getAttribute("username");
        if (user!=null)
        {
            //登录过了,放行
            System.out.println("loginfilter...");
            System.out.println(user);
            filterChain.doFilter(servletRequest,servletResponse);
        }
        else
        {//没有登录,存错误信息并跳到登录界面
            httpServletRequest.setAttribute("error","你还没登录");
            httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest,servletResponse);
        }
    }

    @Override
    public void destroy() {

    }
}

6aa44b0dc9294adf84648ca9325c834d.png

59、AJAX 

5e43c9fd817e44f48c2f6ec856314df9.png

 6dee1c4151cf43d8bcf5ff054acb31ed.png

a3cd60fa914f4138af23bfa3f3e27822.png 1b645c2e628a4fadbafaf7101d43d67b.png

17d4fec16dcb499aad5081eae4009349.png去这里拿axios:http://t.csdnimg.cn/nMkUX 4c0f70d580ea45568e358740bf4c7c6c.png

1babe77fb73e4929872d89ed1ab6c2ad.png f78ded021b1645bda4d2b5625408f109.png

60、json 

bb83cff4b8ac4e84a7f97a238a5c8445.png

2bb1ede465754d168cbf12c0234bfe57.png 8f98882c6a6946f7b5905a7c0ccc18c4.png

fc676e8771ad448e8e206e0ab4bc6880.png

c623b3a5db3d4f39bd81500e1190db55.png 8d4769b453da47c3ad03cae567d7190a.png

6812f57cabc04b9b8a4824db46d84c3e.png 14ac9a1174e54cf9b8d01c2d7520bc56.png

ffd65a29fbe44460a68f8173582ad9b7.png

61、vue 

f475cad26233404cbe697f34422a0a5b.png c3e2ee93e42e4858a865de88f1be86d5.png

de7b4a54257f48f9a0c4813c9e3775ca.png ed4628bc5e3946f594a311bba8fe7d25.png

8563e38be51246a0a12191c1a63b56a6.png

8ccfb52830b943ada7c5d4e4f59a11ff.png 55492ae8823140de8af321e02ae139c4.png

51e62978d1214f53bd06ae2f6814c015.png 633b712e0d814f8a8f3a84eadb5da90e.png

3a573742ec164691af5e20f804bf68d5.png 82eea8ca37314fdab3cb0ca31ed5990e.png

7189b3be79104c2daeb484eccc57101a.png a818f2c98804423e8a196b8b9523fad0.png

 62、Element

官网:组件 | Element

安装参考:http://t.csdnimg.cn/AhIqI

 http://t.csdnimg.cn/eWJnJ

http://t.csdnimg.cn/CB2dz

770a64c71bbb4612bf7dd19a4a6b10dc.png 54fe2eaace804f5f8626aafbb5e8f5d2.png

0ba0174d93f64909b3996f83c6550ec7.png

84c2511037024b59a1a52ab6d50d7305.png

ca07de241b90494e984cd7b36b0ab9b3.png 164430da240444cfb638122976af0c54.png

1104a1e3d85644bcb373d2318083c44e.png a44f02afdc914a85add64d19aa7097ae.png

f4aed3277b964d9abf3258b6678b6f2f.png

8785f04ff5e34c50be64a242bd176a19.png 57be996cc9ff4dc48ba0de4a6d5c4458.png

913dd5d354524eec9212dbc0a8377b62.png e54e22a7152e46179f28289e3bc7aa6e.png

63、案例及代码 

运行演示:还有一些奇奇怪怪的问题,不过好歹是可以用的

项目结构: 

635fb205ab014bc6a0aa054b7fb546f7.png3e776b64bcdf4bf5ad6de101658177db.png

73a2775aad484af9b067864f0f9786a9.png55a16408851246208a1d6c7169404903.png

配置环境:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.example</groupId>
        <artifactId>maven</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>tomcat</artifactId>
<!--两种打包方式:jar(默认值)和war(web项目)-->
    <packaging>war</packaging>
    <name>tomcat Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
<!--导入servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
<!--因为tomcat里已经有了servlet,运行环境再导入会报错,需要排除-->
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat</artifactId>
            <version>8.5.55</version>
            <type>pom</type>
        </dependency>

        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
<!--因为tomcat里已经有了jsp,运行环境再导入会报错,需要排除-->
            <scope>provided</scope>
        </dependency>

        <dependency>
<!--方便copy等操作-->
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.7</version>
        </dependency>
<!--引入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>
<!--引入json、java转换库-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

    </dependencies>
    <build>
        <finalName>tomcat</finalName>
        <!--tomtat插件部署,配置了tomcat则不用导入-->
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>80</port>
               <!--这个aa就是虚拟目录!!-->
                    <path>/aa</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
<?xml version="1.0" encoding="UTF-8" ?>
<!--mybatis-config.xml -->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
<!--起别名,扫描zndx包。这样包里的类可以直接用,注意必须在environment上面起别名-->
        <package name="com.zndx"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库连接信息 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false&amp;useServePrepStmts=true"/>
                <property name="username" value="root"/>
                <property name="password" value="2980313058"/>
            </dataSource>
        </environment>
    </environments>

    <!--加载sql映射文件,mapper是映射的意思,平级可以这样加载:userMapper.xml -->
    <mappers>
        <!--这里路径要改对-->
        <!--<mapper resource="com/zndx/mapper/userMapper.xml"/>-->
        <!--Mapper代理模式用包扫描加载映射文件-->
        <package name="com.zndx.mapper"/>
    </mappers>
</configuration>

基本类:

package com.zndx;

import java.util.StringJoiner;

public class user {
   private Integer id;
   private String username;
   private String password;
   private String gender;
   private String addr;

    public user() {
        this.id = null;
        this.username = "";
        this.password = "";
        this.gender = "";
        this.addr = "";
    }

    public user(Integer id, String username, String password, String gender, String addr) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.gender = gender;
        this.addr = addr;
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", user.class.getSimpleName() + "[", "]")
                .add("id=" + id)
                .add("username='" + username + "'")
                .add("password='" + password + "'")
                .add("gender='" + gender + "'")
                .add("addr='" + addr + "'")
                .toString();
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }
}
package com.zndx;

import java.util.List;
import java.util.StringJoiner;

//分页查询的javabean
public class PageBean <T>{
    //总记录数
    private int totalcount;
    //每页的数据
    private List<T> page;
    public int getTotalcount() {
        return totalcount;
    }

    public void setTotalcount(int totalcount) {
        this.totalcount = totalcount;
    }

    public List<T> getPage() {
        return page;
    }

    public void setPage(List<T> page) {
        this.page = page;
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", PageBean.class.getSimpleName() + "[", "]")
                .add("totalcount=" + totalcount)
                .add("page=" + page)
                .toString();
    }
}

package com.zndx.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
//SqlSessionFactory只能创建一次,多了浪费资源
//利用这个工具类完成
public class sqlsessionfactoryutils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        //静态代码块随类加载自动执行,且只执行一次
        //1获取SqlSessionFactory对象
        String resource = "mybatis-config.xml";//这里忘记改了,用官网复制的值导致报错
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    public static SqlSessionFactory sqlSessionFactoryget()
    {
        return sqlSessionFactory;
    }

}

dao层:

<?xml version="1.0" encoding="UTF-8" ?>
<!--userMapper.xml-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace名称空间,设置为接口位置 -->
<mapper namespace="com.zndx.mapper.userMapper">
    <!--id是sql语句唯一标识
     resultType是返回结果的类型,这里要返回user对象
     注意数据库表的名称和user类的属性名称不同时,不能自动封装,要手动封装!!!
     起别名例如select brand_name as brandName from tb_user;
     定义sql片段例如(要写在mapper配置里面),缺点是不灵活
     <sql id="brand_column">
         brand_name as brandName
    </sql>
    <select id="ss" resultType="user">
        select <include refid="brand_column"/> from tb_user;
    </select>
     -->

<!--    <select id="selectAll" resultType="com.com.com.zndx.user">-->
    <resultMap id="userresultMap" type="user">
        <!--id是映射自己的名字,type指定跟user类映射,里面有id标签,跟主键映射,有result标签和一般字段映射-->
        <result column="brand_name" property="username"/>
        <!--column是表的列名,property是类的属性名-->
    </resultMap>
    <select id="ss" resultMap="userresultMap">
        select * from tb_user;
    </select>
<!--起别名后,这里可以直接用user-->
    <select id="selectAll" resultType="user">
        select * from tb_user;
    </select>

<!--占位符#{}:把语句中此部分替换为?,防sql注入,${}:拼sql,会出现sql注入,用来传不固定的列名、表名-->
<!--参数类型parameterType可以省略不写,&lt是小于号转义字符,或者使用cdata区,打CD-->
    <select id="searchByIdUser" parameterType="int" resultType="user">
        select * from tb_user where id <![CDATA[
         <
        ]]> #{id};
    </select>

    <select id="selectbycondition" resultType="user">
        select * from tb_user where username like #{username} and password = #{password};
    </select>

    <select id="selectbyconditions" resultType="user">
     <!--if里面写的是接口参数名-->
        select * from tb_user
        <!--where 1=1-->
        <!--恒等式后跟and,缺哪一个都不会出错-->
        <!--使用mybatis提供的where标签包裹最好-->
        <where>
        <if test="addr!=null and addr!=''">
            and addr like #{addr}
        </if>
         <!--and不能写外面,不然空时出错-->
        <if test="username!=null and username!=''">
           and username like #{username}
        </if>
        </where>
    </select>


    <select id="selectbyconditionsingle" resultType="com.zndx.user">
        select * from tb_user
        <where>
        <choose><!--相当于switch-->
            <when test="id!=null">
                id=#{id}
            </when>
            <when test="username!=null and username!=''">
                username=#{username}
            </when>
            <when test="password!=null and password!=''">
                password=#{password}
            </when>
            <when test="gender!=null and gender!=''">
                gender=#{gender}
            </when>
            <when test="addr!=null and addr!=''">
                addr=#{addr}
            </when>
            <!--otherwise保险措施,但是最好的方法是用where标签-->
<!--            <otherwise>-->
<!--                1=1-->
<!--            </otherwise>-->
        </choose>
        </where>
    </select>
<!--    分页查询-->
    <select id="selectbypage" resultType="com.zndx.user">
        select * from tb_user limit #{begin},#{size};
    </select>
    <!--条件分页查询-->
    <select id="selectbypageandcondition" resultType="com.zndx.user">
        select * from tb_user
        <where>
            <if test="user.username!=null and user.username!=''">
                and username like #{user.username}
            </if>
            <if test="user.gender!=null and user.gender!=''">
                and gender like #{user.gender}
            </if>
            <if test="user.addr!=null and user.addr!=''">
                and addr like #{user.addr}
            </if>
        </where>
        limit #{begin},#{size};
    </select>
    <select id="selectotalcountandcondition" resultType="java.lang.Integer">
        select count(*) from tb_user
        <where>
            <if test="username!=null and username!=''">
                and username like #{username}
            </if>
            <if test="gender!=null and gender!=''">
                and gender like #{gender}
            </if>
            <if test="addr!=null and addr!=''">
                and addr like #{addr}
            </if>
        </where>
    </select>
    <insert id="add" useGeneratedKeys="true" keyProperty="id">
<!--useGeneratedKeys="true" keyProperty="id"把主键id的值返回给对象-->
      insert into tb_user(username,password,gender,addr)
        values(#{username},#{password},#{gender},#{addr});
    </insert>

    <update id="update">
       update tb_user
<!--用set标签避免无被修改参数和addr不需要修改时逗号多余的问题-->
        <set>
        <if test="username!=null and username!=''">
            username=#{username},
        </if>
        <if test="password!=null and username!=''">
            password=#{password},
        </if>
        <if test="gender!=null and gender!=''">
            gender=#{gender},
        </if>
        <if test="addr!=null and addr!=''">
            addr=#{addr}
        </if>
        </set>
         where id=#{id};
    </update>

    <delete id="delByIdInt">
        delete from tb_user where id=#{id};
    </delete>
    <delete id="delByIdInts">
<!--mybatis会把传入的数组封装为map,默认名字是array,可以用@Param("ids")改名-->
        delete from tb_user where id in
        <!--separator是分隔符,item="id"根据id删,open在循环开头补字符,close在结尾补字符-->
        <foreach collection="array" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
        ;
    </delete>
</mapper>
package com.zndx.mapper;

import com.zndx.user;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;
//Dao层/mapper层
public interface userMapper {
    //明确要返回多个对象时,返回集合
    @ResultMap("userresultMap")//使用这个映射
    List<user> selectAll();
    user searchByIdUser(int id);
    // 条件查询可以把参数封对象里,只要xml占位符名称和对象属性名相同即可完成对应
    //或者封map里,map键名和占位符同名即可对应
    //或者用@Param(占位符名)填在参数前面完成对应,替换的是arg0名称
    user selectbycondition(@Param("username")String username,@Param("password")String password);
    //传多个参数时,mybatis会把每个值封进map,键名称就是@Param注解设置的名称,如果没有注解
    //会把每个值封两次,键分别是arg0(1,2递增),param0(递增),在映射文件中可以用这些名称使用值,但不推荐
    //如果传入Collection类型,按map("Collection",内容),map("arg0",内容)封装
    //如果传入List,按map("Collection",内容),map("arg0",内容),map("list",内容)封装
    //如果传入array,按map("arg0",内容),map("array",内容封装)
    user selectbycondition (user user);
    user selectbycondition(Map map);
    //多条件动态查询:用户不会完整填写所有条件
    List<user> selectbyconditions(@Param("addr") String addr,@Param("username")String username);
    List<user> selectbyconditionsingle(Map map);
    int add(user user);
    int update(user user);
    //按id删除
    int delByIdInt(int id);
    //按id批量删除
    int delByIdInts( int[] ids);
    //通过注解完成简单开发,另外还有@Update(),@Delete(),@Insert()等
    @Select("select * from tb_user;")
    List<user> zhujiechazhao();
    @Select("select * from tb_user where username=#{username} and password=#{password}")
    user select(@Param("username")String username,@Param("password")String password);
    List<user> selectbypage(@Param("begin") int begin,@Param("size") int size);//分页查询
    @Select("select count(*) from tb_user")
    int selectotalcount();//查询总条数

    List<user>selectbypageandcondition(@Param("begin") int begin,@Param("size") int size,@Param("user")user user);//分页查询

    int selectotalcountandcondition(user user);//查询总条数
}

service层:

package com.zndx.service;

import com.zndx.PageBean;
import com.zndx.user;

import java.util.List;

public interface userservice {
    user select(String username, String password);
    List<user> selectbyname(String username);
    List<user> selectall();
    void add(user user);
    void deletebyids(int[] ids);
    //分页查询,current:当前页面,pagesize:每页展示条数
    PageBean<user> selectbypage(int current,int pagesize);
    PageBean<user> selectbypageandcondition(int current,int pagesize,user user);
    void update(user user);
    void deletebyid(int id);
}
package com.zndx.service.impl;

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

import com.zndx.*;
import com.zndx.mapper.userMapper;
import com.zndx.service.*;
import com.zndx.utils.sqlsessionfactoryutils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
//service层
public class userservice implements com.zndx.service.userservice {
    private static SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
    //如果不用静态方法,web层要
    // userservice userservice=new userservice();(做属性)
    // userservice.select(username,password);
    public  user select(String username, String password)
    {
        //1获取SqlSessionFactory对象
        //SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
        //2、获取sqlSession对象,用它执行sql
        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //3获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //4获取user对象
        user user=userMapper.select(username,password);
        //5释放资源
        sqlSession.close();
        return user;
    }

    public   List<user> selectbyname(String username)
    {
        //1获取SqlSessionFactory对象
        //SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
        //2、获取sqlSession对象,用它执行sql
        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //3获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //4获取user对象s
        Map<String,String> map=new HashMap<>();
        map.put("username",username);
        List<user> list=userMapper.selectbyconditionsingle(map);
        sqlSession.close();
        return list;
    }

    @Override
    public List<user> selectall() {
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        List<user> list=userMapper.selectAll();
        sqlSession.close();
        return list;
    }

    @Override
    public void add(user user) {
        SqlSession sqlSession=sqlSessionFactory.openSession(true);//这里设置为true,自动提交事务
        //获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        userMapper.add(user);
        sqlSession.close();
    }


    public void deletebyids(int[] ids) {
        for (int i=0;i<ids.length;i++)
        {
            System.out.println("ids:"+ids[i]);
        }
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        userMapper.delByIdInts(ids);
        //一定记得提交事务
        sqlSession.commit();
        //回收资源
        sqlSession.close();
    }

    @Override
    public PageBean<user> selectbypage(int current, int pagesize) {
        //获取开始位置和每页查询数
        int begin=(current-1)*pagesize;
        int size=pagesize;
        //System.out.println(begin+" "+size);
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        List<user> selectbypage = userMapper.selectbypage(begin,size);
        //System.out.println(selectbypage);
        int selectotalcount = userMapper.selectotalcount();
        //封装pagebean对象
        PageBean<user> tmp=new PageBean<>();
        tmp.setPage(selectbypage);
        tmp.setTotalcount(selectotalcount);
        //回收资源
        sqlSession.close();
        return tmp;
    }

    @Override
    public PageBean<user> selectbypageandcondition(int current, int pagesize,user user) {
        //获取开始位置和每页查询数
        int begin=(current-1)*pagesize;
        int size=pagesize;
        //添加模糊查询语句
        String username = user.getUsername();
        if(username!=null&&!username.equals(""))
        {
            user.setUsername("%"+username+"%");
        }
        String gender = user.getGender();
        if(gender!=null&&!gender.equals(""))
        {
            user.setGender("%"+gender+"%");
        }
        String addr = user.getAddr();
        if(addr!=null&&!addr.equals(""))
        {
            user.setAddr("%"+addr+"%");
        }
        //System.out.println(begin+" "+size);
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //System.out.println(begin+", "+size+", "+user);
        List<user> selectbypage = userMapper.selectbypageandcondition(begin,size,user);
        //System.out.println(selectbypage);
        int selectotalcount = userMapper.selectotalcountandcondition(user);
        //System.out.println(selectotalcount);
        //封装pagebean对象
        PageBean<user> tmp=new PageBean<>();
        tmp.setPage(selectbypage);
        tmp.setTotalcount(selectotalcount);
        //回收资源
        sqlSession.close();
        //System.out.println(tmp);
        return tmp;
    }

    @Override
    public void update(user user) {
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        userMapper.update(user);
        sqlSession.commit();
        sqlSession.close();
    }
    public void deletebyid(int id) {
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        userMapper.delByIdInt(id);
        sqlSession.commit();
        sqlSession.close();
    }
}

servlet层:

package Servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//用来代替HttpServlet,用url最后一段路径实现方法分发
public class BaseServlet extends HttpServlet {
    @Override
    public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        //获取请求路径
        String requestURI = req.getRequestURI();
        //获取最后一段请求路径,即方法名
        int index=requestURI.lastIndexOf('/');
        String name=requestURI.substring(index+1);//不+1会带上/
        //获取UserServlet的字节码文件(class)
        //因为这个方法被UserServlet调用,因此this代表UserServlet
        //谁调用this,this指向谁
        //利用反射
        Class<? extends BaseServlet> aClass = this.getClass();
        //获取方法method对象
        try {
            Method method = aClass.getMethod(name, HttpServletRequest.class, HttpServletResponse.class);
            //执行方法
            method.invoke(this,req,res);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }


    }
}
package Servlet;

import com.alibaba.fastjson.JSON;
import com.zndx.PageBean;
import com.zndx.service.userservice;
import com.zndx.user;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.List;
@WebServlet("/user/*")
public class UserServlet extends BaseServlet{
    com.zndx.service.userservice userservice=new com.zndx.service.impl.userservice();
    //声明用接口名,实现用接口的实现类,便于切换实现类
    public void selectall(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //查询数据库
        List<user> list=userservice.selectall();
        //将集合转化为JSON数据,即序列化
        String jsonString = JSON.toJSONString(list);
        //响应数据
        resp.setContentType("text/json;charset=utf-8");//告诉浏览器传的是html和需要的字符集,防止中文乱码
        resp.getWriter().write(jsonString);
    }

    public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取新用户数据
        req.setCharacterEncoding("UTF-8");
        BufferedReader reader = req.getReader();
        String s = reader.readLine();//读取json字符串
        //System.out.println(s);
        user user = JSON.parseObject(s, user.class);//转为user对象
        user.setGender(new String(user.getGender()));
        System.out.println("??"+user+" "+user.getUsername());
        //查询数据库
        List<user> list=userservice.selectbyname(user.getUsername());
        if(list==null||list.isEmpty())
        {
            userservice.add(user);
            //响应成功标识
            resp.setContentType("text/json;charset=utf-8");//告诉浏览器传的是html和需要的字符集,防止中文乱码
            resp.getWriter().write("新增用户成功!");
        }
        else {
            //响应失败标识
            System.out.println(list);
            resp.setContentType("text/json;charset=utf-8");//告诉浏览器传的是html和需要的字符集,防止中文乱码
            resp.getWriter().write("新增用户失败!");
        }
    }
    public void deletebyids(HttpServletRequest req,HttpServletResponse resp)throws ServletException, IOException
    {
        req.setCharacterEncoding("UTF-8");
        BufferedReader reader = req.getReader();
        String s = reader.readLine();//读取json字符串
        int[] ids = JSON.parseObject(s, int[].class);//转为user对象
        userservice.deletebyids(ids);
        //响应成功标识
        resp.setContentType("text/json;charset=utf-8");//告诉浏览器传的是html和需要的字符集,防止中文乱码
        resp.getWriter().write("批量删除成功!");
    }
    //分页查询
    public void selectbypage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int current=0,pagesize=0;
        String c=req.getParameter("current");
        String p=req.getParameter("pagesize");
        //System.out.println(p+" "+c);
        current=new Integer(c);
        pagesize=Integer.parseInt(p);
        //System.out.println(current+"  "+pagesize);
        //查询数据库
        PageBean<user> pageBean=userservice.selectbypage(current,pagesize);
        //将集合转化为JSON数据,即序列化
        String jsonString = JSON.toJSONString(pageBean);
       //System.out.println(pageBean);
        //响应数据
        resp.setContentType("text/json;charset=utf-8");//告诉浏览器传的是html和需要的字符集,防止中文乱码
        resp.getWriter().write(jsonString);
    }
    public void selectbypageandcondition(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int current=0,pagesize=0;
        //从url获取分页查询数据
        String c=req.getParameter("current");
        String p=req.getParameter("pagesize");
        //System.out.println(p+" "+c);
        current=new Integer(c);
        pagesize=Integer.parseInt(p);
        //从data获取条件查询数据
        req.setCharacterEncoding("UTF-8");
        BufferedReader reader = req.getReader();
        String s = reader.readLine();//读取json字符串
        //System.out.println(s);
        user user = JSON.parseObject(s, user.class);//转为user对象
        //System.out.println(current+"  "+pagesize);
        //查询数据库
        PageBean<user> pageBean=userservice.selectbypageandcondition(current,pagesize,user);
        //将集合转化为JSON数据,即序列化
        String jsonString = JSON.toJSONString(pageBean);
        //System.out.println(pageBean);
        //响应数据
        resp.setContentType("text/json;charset=utf-8");//告诉浏览器传的是html和需要的字符集,防止中文乱码
        resp.getWriter().write(jsonString);
    }
    public void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从data获取条件查询数据
        req.setCharacterEncoding("UTF-8");
        BufferedReader reader = req.getReader();
        String s = reader.readLine();//读取json字符串
        user user=JSON.parseObject(s, com.zndx.user.class);
        //System.out.println(user);
        userservice.update(user);
        //响应成功标识
        resp.setContentType("text/json;charset=utf-8");//告诉浏览器传的是html和需要的字符集,防止中文乱码
        resp.getWriter().write("修改成功!");
    }
    public void deletebyid(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从data获取条件查询数据
        req.setCharacterEncoding("UTF-8");
        BufferedReader reader = req.getReader();
        String s = reader.readLine();//读取json字符串
        int user=JSON.parseObject(s, int.class);
        System.out.println(user);
        //System.out.println(user);
        userservice.deletebyid(user);
        //响应成功标识
        resp.setContentType("text/json;charset=utf-8");//告诉浏览器传的是html和需要的字符集,防止中文乱码
        resp.getWriter().write("删除成功!");
    }
}

user.html:

<!DOCTYPE html>
<html lang="utf-8">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <style>
    .el-table .warning-row {
      background: oldlace;
    }

    .el-table .success-row {
      background: #f0f9eb;
    }
  </style>
</head>
<body>
<script src="js/axios.js"></script>
<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">
<div id="app">
  <!-- 搜索表单 -->
  <el-form :inline="true" :model="user" class="demo-form-inline">
    <el-form-item label="用户名">
      <el-input v-model="user.username" placeholder="用户名"></el-input>
    </el-form-item>
    <el-form-item label="性别">
      <el-select v-model="user.gender" placeholder="性别">
        <el-option label="男" value="男"></el-option>
        <el-option label="女" value="女"></el-option>
        <el-option label="空" value=""></el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="地区">
      <el-input v-model="user.addr" placeholder="地区"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">查询</el-button>
    </el-form-item>
  </el-form>
<!-- 按钮 -->
  <el-button type="danger" @click="deletebyids">批量删除</el-button>
  <el-button type="primary"  @click="news()">新增</el-button>

  <!-- <el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button> -->
<!-- 添加数据对话框表单 -->
<el-dialog
  title="新增用户"
  :visible.sync="dialogVisible"
  width="50%"
  :before-close="handleClose">
  <el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
    <el-form-item label="用户名" prop="username">
      <span id="usernamerr" class="error" style="display: none"><font color="ff0000">用户名已存在!</font></span>
      <el-input  v-model="ruleForm.username" autocomplete="off"></el-input>
    </el-form-item>
    <el-form-item label="性别" prop="gender">
      <el-input  v-model="ruleForm.gender" autocomplete="off"></el-input>
    </el-form-item>
    <el-form-item label="密码" prop="password">
      <el-input type="password" v-model="ruleForm.password" autocomplete="off"></el-input>
    </el-form-item>
    <el-form-item label="确认密码" prop="checkPassword">
      <el-input type="password" v-model="ruleForm.checkPassword" autocomplete="off"></el-input>
    </el-form-item>
    <el-form-item label="地区" prop="addr">
      <el-input v-model.number="ruleForm.addr"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
      <el-button @click="resetForm('ruleForm')">重置</el-button>
      <el-button @click="dialogVisible = false">取消</el-button>
    </el-form-item>
  </el-form>
  <!-- <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
  </span> -->
</el-dialog>

<!-- 修改数据对话框表单 -->
<el-dialog
  title="修改用户"
  :visible.sync="updateVisible"
  width="50%"
  :before-close="handleClose">
  <el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
    <el-form-item label="用户名" prop="username">
      <span id="usernamerr" class="error" style="display: none"><font color="ff0000">用户名已存在!</font></span>
      <el-input  v-model="ruleForm.username" autocomplete="off"></el-input>
    </el-form-item>
    <el-form-item label="性别" prop="gender">
      <el-input  v-model="ruleForm.gender" autocomplete="off"></el-input>
    </el-form-item>
    <el-form-item label="密码" prop="password">
      <el-input type="password" v-model="ruleForm.password" autocomplete="off"></el-input>
    </el-form-item>
    <el-form-item label="确认密码" prop="checkPassword">
      <el-input type="password" v-model="ruleForm.checkPassword" autocomplete="off"></el-input>
    </el-form-item>
    <el-form-item label="地区" prop="addr">
      <el-input v-model.number="ruleForm.addr"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="updateform('ruleForm')">提交</el-button>
      <el-button @click="updateform('ruleForm')">重置</el-button>
      <el-button @click="updateVisible = false">取消</el-button>
    </el-form-item>
  </el-form>
  <!-- <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
  </span> -->
</el-dialog>
<!-- 表格 -->
  <template>
    <el-table
            :data="tableData"
            style="width: 100%"
            :row-class-name="tableRowClassName"
            @selection-change="handleSelectionChange">
          <el-table-column
            type="selection"
            width="55">
          </el-table-column>
     <el-table-column
      type="index"
      width="50">
    </el-table-column>
    <el-table-column
              prop="id"
              label="id"
              align="center">
      </el-table-column>
      <el-table-column
              prop="username"
              label="用户名"
              width="180"
              align="center">
              <!-- prop取数据
              删掉width="180"自动占全屏
              -->
      </el-table-column>
      <el-table-column
              prop="password"
              label="密码"
              width="180"
              align="center">
      </el-table-column>
      <el-table-column
              prop="gender"
              label="性别"
              align="center">
      </el-table-column>
      <el-table-column
              prop="addr"
              label="地址"
              align="center">
      </el-table-column>
      <el-table-column
              align="center">
              <template slot-scope="scope">
                <!-- 利用scope.$index获取当前数组坐标 -->
                <el-button type="primary" @click="update(scope.$index)">修改</el-button>
              <el-button type="danger" @click="deletebyid(scope.$index)">删除</el-button>
            </template>
      </el-table-column>
    </el-table>

    
  </template>
  <!-- 分页工具条 -->
  <div class="block">
    <!-- <span class="demonstration">完整功能</span> -->
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="currentPage"
      :page-sizes="[5, 10, 15, 20]"
      :page-size="pagesize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total">
    </el-pagination>
  </div>
</div>
<script>
 
  new Vue({
  el:"#app",
  mounted(){
            console.log("页面加载完后执行");
            //页面加载完后,发送异步请求查询数据
            this.selectall();
           },
    methods: {
      selectall(){
      var _this=this;
                // axios(
                //      {
                //        method:"post",
                //        url:"http://localhost/aa/user/selectall",
                //        data:"username=lisi"
                //      }
                //      ).then(function(resp)
                //      {//这里this默认为window对象,所以要在外面保留this到里面用
                //         _this.tableData=resp.data;
                //      })
                // axios(
                //      {
                //        method:"post",
                //        url:"http://localhost/aa/user/selectbypageandcondition?current="+_this.currentPage+"&pagesize="+_this.pagesize,
                //        data:this.user
                //      }
                //      ).then(function(resp)
                //      {//这里this默认为window对象,所以要在外面保留this到里面用
                //         _this.tableData=resp.data.page;
                //         _this.total=resp.data.totalcount;
                //      })
                axios(
                     {
                       method:"post",
                       url:"http://localhost/aa/user/selectbypageandcondition?current="+_this.currentPage+"&pagesize="+_this.pagesize,
                       data:this.user
                     }
                     ).then(resp=>{
                     
                        this.tableData=resp.data.page;
                        this.total=resp.data.totalcount;
                     })
                     
    },
      tableRowClassName({row, rowIndex}) {
        if (rowIndex%4 === 1) {
          return 'warning-row';
        } else if (rowIndex%4 === 3) {
          return 'success-row';
        }
        return '';
      },//复选框选中后执行的方法
      handleSelectionChange(val) {
        this.multipleSelection = val;
        console.log(this.multipleSelection);
      },
      onSubmit() {
        console.log('submit!');
        this.selectall();
      },//点叉号关闭时提示
      handleClose(done) {
        this.$confirm('确认关闭?你将丢失已填写的数据')
          .then(_ => {
            done();
          })
          .catch(_ => {});
      },
      news(){
        this.dialogVisible = true
        this.ruleForm.username=""
        this.ruleForm.gender=""
        this.ruleForm.addr=""
        this.ruleForm.id=null
      },
      submitForm(formName) {
        // this.$refs[formName].validate((valid) => {
        //   if (valid) {
        //     alert('submit!');
        //   } else {
        //     console.log('error submit!!');
        //     return false;
        //   }
        // });
        //点击提交完后,发送异步请求添加数据
        var _this=this;
        console.log(this.usernameok)
        console.log(this.genderok)
        console.log(this.passwordok)
        if(this.usernameok!=1||this.genderok!=1||this.passwordok!=1)
        {
          //弹出消息提示框
          this.$message({
                          showClose: true,
                          message: '请按要求填写表格!',
                          type: 'warning'
                          });
          return;
        }
                axios(
                     {
                       method:"post",
                       url:"http://localhost/aa/user/add",
                       data:_this.ruleForm
                     }
                     ).then(function(resp)
                     {//这里this默认为window对象,所以要在外面保留this到里面用
                      console.log(resp.data)
                        if(resp.data=="新增用户成功!")
                        { console.log(resp.data)
                          document.getElementById("usernamerr").style.display='none';
                          //关闭窗口
                          _this.dialogVisible=false;
                          //重新查询
                          _this.selectall();
                          //弹出消息提示框
                          _this.$message({
                          showClose: true,
                          message: '新增用户成功!',
                          type: 'success'
                          });
                        }
                        else{
                          document.getElementById("usernamerr").style.display='';
                        }
                     })
      },update(index){
        this.updateVisible=true
        var user= this.tableData[index]
        this.ruleForm.username=user.username
        this.ruleForm.gender=user.gender
        this.ruleForm.addr=user.addr
        this.ruleForm.id=user.id
        //console.log(this.resetForm)
      },updateform(formName) {
        // this.$refs[formName].validate((valid) => {
        //   if (valid) {
        //     alert('submit!');
        //   } else {
        //     console.log('error submit!!');
        //     return false;
        //   }
        // });
        //点击提交完后,发送异步请求添加数据
        var _this=this;
        console.log(this.usernameok)
        console.log(this.genderok)
        console.log(this.passwordok)
        if(this.usernameok!=1||this.genderok!=1||this.passwordok!=1)
        {
          //弹出消息提示框
          this.$message({
                          showClose: true,
                          message: '请按要求填写表格!',
                          type: 'warning'
                          });
          return;
        }
                axios(
                     {
                       method:"post",
                       url:"http://localhost/aa/user/update",
                       data:_this.ruleForm
                     }
                     ).then(function(resp)
                     {//这里this默认为window对象,所以要在外面保留this到里面用
                      console.log(resp.data)
                        if(resp.data=="修改成功!")
                        { console.log(resp.data)
                          
                          //关闭窗口
                          _this.updateVisible=false;
                          //重新查询
                          _this.selectall();
                          //弹出消息提示框
                          _this.$message({
                          showClose: true,
                          message: '修改用户成功!',
                          type: 'success'
                          });
                        }
                        
                     })
      },deletebyid(index){
        let id=this.tableData[index].id;
        axios(
                     {
                       method:"post",
                       url:"http://localhost/aa/user/deletebyid",
                       data:id
                     }
                     ).then(resp=>{
                     
                        //这里this默认为window对象,所以要在外面保留this到里面用
                      console.log(resp.data)
                        if(resp.data=="删除成功!")
                        { console.log(resp.data)
                          
                          //重新查询
                          this.selectall();
                          //弹出消息提示框
                          this.$message({
                          showClose: true,
                          message: '删除用户成功!',
                          type: 'success'
                          });
                        }
                     })
      }
      ,//批量删除
      deletebyids(){
       //console.log(this.multipleSelection)
       
        this.$confirm('此操作将永久删除这些用户, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
           //获取要删除的id
           for(let i=0;i<this.multipleSelection.length;i++)
       {
        this.selectedids[i]=this.multipleSelection[i].id;
       }

var _this=this;
axios(
             {
               method:"post",
               url:"http://localhost/aa/user/deletebyids",
               data:_this.selectedids
             }
             ).then(function(resp)
             {//这里this默认为window对象,所以要在外面保留this到里面用
              console.log(resp.data)
                if(resp.data=="批量删除成功!")
                { 
                  
                  //弹出消息提示框
                  _this.$message({
                  showClose: true,
                  message: "批量删除成功!",
                  type: 'success'
                  });
                  //重新查询
                  _this.selectall();
                }
                
             })
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });          
        });
       
       }
      ,
      resetForm(formName) {
        this.$refs[formName].resetFields();
      },handleSizeChange(val) {
        console.log(`每页 ${val} 条`);
        this.pagesize=val;
        this.selectall();
      },
      handleCurrentChange(val) {
        console.log(`当前页: ${val}`);
        this.currentPage=val;
        this.selectall();
      },
      
    },
    data() {
      var validateusername = (rule, value, callback) => {
        if (!value) {
          callback(new Error('用户名不能不填'));
          this.usernameok=0
        }
        setTimeout(() => {this.usernameok=1
        }, 1000);
      };
      var checkAge = (rule, value, callback) => {
        if (!value) {
          return callback(new Error('性别不能不填'));
          this.genderok=0
        }
        setTimeout(() => {
          if (value!="男"&&value!="女") {
            callback(new Error('请填男或女'));
            this.genderok=0
          } else {//console.log(value)
            // if (value < 18) {
            //   callback(new Error('必须年满18岁'));
            // } else {
              this.genderok=1
              callback();
              
            //}
          }
        }, 1000);
      };
      var validatePass = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('请输入密码'));
          this.passwordok=0
        } else {
          if (this.ruleForm.checkPassword !== '') {
            this.$refs.ruleForm.validateField('checkPass');
          }
          callback();
          
        }
      };
      var validatePass2 = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('请再次输入密码'));
          this.passwordok=0
        } else if (value !== this.ruleForm.password) {
          callback(new Error('两次输入密码不一致!'));
          this.passwordok=0
        } else {
          this.passwordok=1
          callback();
          
        }
      };
      return {
        tableData: [],//复选框对应的数据
        multipleSelection: [],
        usernameok:0,
        genderok:0,
        passwordok:0,
        //被选中的id
        selectedids:[],
        //当前页码
        currentPage: 1,
        //每页查询数
        pagesize:5,
        total:100,
        //搜索表单数据
        user: {
        username: '',
        addr: '',
        gender:'',
        id:''
      },//控制对话框是否显示
      dialogVisible: false,
      updateVisible: false,
      ruleForm: {
        username: '',
        addr: '',
        gender:'',
        id:''
        },
        rules: {
          username: [
            { validator: validateusername, trigger: 'blur' }
          ],
          password: [
            { validator: validatePass, trigger: 'blur' }
          ],
          checkPassword: [
            { validator: validatePass2, trigger: 'blur' }
          ],
          gender: [
            { validator: checkAge, trigger: 'blur' }
          ]
        }
      }
    }
        
    }
    );
</script>
</body>
</html>

注册、登录、cookie、session:

package Servlet;

import com.zndx.service.impl.userservice;
import com.zndx.*;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
//web层
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
    private static userservice userservice=new userservice();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        if(method.equals("POST"))
        {
            System.out.println("post...");
            //解决post中文乱码
            req.setCharacterEncoding("UTF-8");
        }
        //接受用户名、密码和复选框值
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String remember = req.getParameter("remember");

        if(method.equals("GET"))
        {
            System.out.println("get...");//浏览器输url是get方式,在控制台打印这句话
            //解决get中文乱码,这行代码post也能用
            username=new String(username.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
            password=new String(password.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
        }

//        //1获取SqlSessionFactory对象
//        SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
//        //2、获取sqlSession对象,用它执行sql
//        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
//        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
//        //3获取userMapper接口的代理对象(Mapper代理法)
//        userMapper userMapper=sqlSession.getMapper(userMapper.class);
//        //4获取user对象
//        user user=userMapper.select(username,password);
//        //5释放资源
//        sqlSession.close();
        //上面的都可以写到service层里,这里调用即可
        user user= userservice.select(username,password);
        //6获取字符输出流并设置字符集
        resp.setContentType("text/html;charset=utf-8");//告诉浏览器传的是html和需要的字符集
        PrintWriter printWriter=resp.getWriter();//获取的这个流不需要关闭
       //7显示登录结果
       if(user!=null)
       {
           //给前端响应
           printWriter.write("登录成功");
           if("1".equals(remember))
           {//因为1永不为空,避免remember为空调用不了equals的异常
               //转码,以支持中文
               String username1= URLEncoder.encode(username,"utf-8");
               String encode = URLEncoder.encode(password, "utf-8");
               //创建cookie对象
               Cookie cookie=new Cookie("username",username1);
               Cookie cookie1=new Cookie("password",encode);
               //设置cookie存活时间,一周七天
               cookie.setMaxAge(60*60*24*7);
               cookie1.setMaxAge(60*60*24*7);
               //发送cookie
               resp.addCookie(cookie);
               resp.addCookie(cookie1);
           }
           //跳转到html.jsp
           //创建session对象
           HttpSession session = req.getSession();
           //设置session
           session.setAttribute("username",username);
           //动态获取虚拟目录
           String contextPath = req.getContextPath();
           //响应重定向
           resp.sendRedirect(contextPath+"/htmlServlet");
       }
       else {
           printWriter.write("登录失败");
           //存失败数据到req
           req.setAttribute("error","用户名或密码错误");
           //转发请求
           req.getRequestDispatcher("/login.jsp").forward(req,resp);
       }

    }

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

import com.zndx.mapper.userMapper;
import com.zndx.service.impl.userservice;
import com.zndx.utils.sqlsessionfactoryutils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import com.zndx.*;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet("/RegisterServlet")//复制过来没改路径,跟login重名报错
// A child container failed during start
public class RegisterServlet extends HttpServlet {
    private static userservice userservice=new userservice();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        if(method.equals("POST"))
        {
            System.out.println("post...");
            //解决post中文乱码
            req.setCharacterEncoding("UTF-8");
        }
        //接受用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String check = req.getParameter("check");
        HttpSession session1 = req.getSession();
        String checkcode = (String)session1.getAttribute("checkcode");
        if(!checkcode.equalsIgnoreCase(check))
        {
            //存失败数据到req
            req.setAttribute("error","验证码错误");
            //转发请求
            req.getRequestDispatcher("/register.jsp").forward(req,resp);
            return;
        }
        //获取cookie数组
        Cookie[] cookies=req.getCookies();
        //遍历数组
        for (Cookie cookie:cookies)
        {
            String name=cookie.getName();
            if(name.equals("username"))
            {
                String value = cookie.getValue();
                //解码
                value= URLDecoder.decode(value,"utf-8");
                System.out.println(name+" "+value);
                break;
            }
        }
        //获取session
        HttpSession session = req.getSession();
        //取出值
        Object username1 = session.getAttribute("username");
        System.out.println(username1);
        //删除这个键值对
        session.removeAttribute("username");
        //删除session
        session.invalidate();
        if(method.equals("GET"))
        {
            System.out.println("get...");//浏览器输url是get方式,在控制台打印这句话
            //解决get中文乱码,这行代码post也能用
            username=new String(username.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
            password=new String(password.getBytes("ISO-8859-1"), StandardCharsets.UTF_8);
        }

        //1获取SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = sqlsessionfactoryutils.sqlSessionFactoryget();
        //2、获取sqlSession对象,用它执行sql
        //这个是单独的连接,不能放到工具类里,让用户共享一个连接,会出问题
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //3获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        //4获取user对象s
        Map<String,String> map=new HashMap<>();
        map.put("username",username);
//        List<user> list=userMapper.selectbyconditionsingle(map);
//同理,调用service层实现功能
        List list= userservice.selectbyname(username);
        //5获取字符输出流并设置字符集
        resp.setContentType("text/html;charset=utf-8");//告诉浏览器传的是html和需要的字符集
        PrintWriter printWriter=resp.getWriter();//获取的这个流不需要关闭
       //6显示注册结果
       if(list.isEmpty())
       {
           user user=new user();
           user.setUsername(username);
           user.setPassword(password);
           int a=userMapper.add(user);
           sqlSession.commit();//又忘记提交事务了
           System.out.println("add:"+a);
           printWriter.write("注册成功");
           //存成功数据到req
           req.setAttribute("finish","注册成功,请登录");
           //转发请求
           req.getRequestDispatcher("/login.jsp").forward(req,resp);
       }
       else {
           printWriter.write("注册失败");
           //存失败数据到req
           req.setAttribute("error","用户名已存在");
           //转发请求
           req.getRequestDispatcher("/register.jsp").forward(req,resp);
       }
        //7释放资源
        sqlSession.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!DOCTYPE html>
<html lang="en">
<!--login.html-->
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<div id="logindiv">
    <form action="/aa/loginServlet" method="post" id="form">
        <h1 id="loginMsg">登录</h1>

        <p>username:<input id="username" name="username" type="text"></p>
        <p>password:<input id="password" name="password" type="password"></p>
        <p>remember:<input id="remember" name="remember" type="checkbox" value="1"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">
            <a href="register.html">没有账号?来注册</a>
        </div>
    </form>
</div>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%-- 启用el表达式,没有的话会把el表达式直接当文字显示 --%>
<%-- 不输入资源时,默认访问index --%>
<%-- login.jsp --%>
<!DOCTYPE html>
<html lang="en">
<!--login.jsp-->
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<div id="logindiv">
    <form action="/aa/loginServlet" method="post" id="form">
        <h1 id="loginMsg">登录</h1>
         <div id="error">${error}${finish}</div>
        <p>username:<input id="username" name="username" type="text" value="${cookie.username.value}"></p>
        <p>password:<input id="password" name="password" type="password" value="${cookie.password.value}"></p>
        <p>remember:<input id="remember" name="remember" type="checkbox" value="1"></p>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">
            <a href="register.jsp">没有账号?来注册</a>
        </div>
    </form>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<!--register.html-->
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>

<body>
<div id="registerdiv">
    <form action="/aa/RegisterServlet" method="post" id="form">
        <h1 id="loginMsg">注册</h1>
        <p>username:<input id="username" name="username" type="text"></p>
        <span id="usernamerr" class="error" style="display: none">用户名已存在</span>
        <p>password:<input id="password" name="password" type="password"></p>
        <p><input name="check" type="text" id="check"><img src="/aa/checkServlet"></p>
        <a href="#" id="change">看不清?</a>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">
            <a href="login.html">注册好了?来登录</a>
        </div>
    </form>
</div>
<script>
    //给用户名输入框绑定一个失去焦点事件
    document.getElementById("username").onblur=function()
    {
        var username=this.username;
        //发送Ajax请求
        //创建核心对象
    var xhttp;
    if(window.XMLHttpRequest)
    {
        xhttp=new XMLHttpRequest();
    }
    else
    {//IE5,IE6
        xhttp=new ActiveXObject("MicroSoft.XMLHttp");
    }
    //发送请求,只能填绝对路径
    xhttp.open("Post","http://localhost/aa/ajaxServlet");
    xhttp.send();
    //获取响应
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            //alert(this.responseText)
            console.log(this.responseText);
            if(this.responseText!="注册成功")
            { console.log("jin1");
              document.getElementById("usernamerr").style.display='';
            }
            else
            {console.log("jin2");
                document.getElementById("usernamerr").style.display='none';
            }
       }
    };
    }
</script>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page isELIgnored="false" %>
<%-- 启用el表达式,没有的话会把el表达式直接当文字显示 --%>
<%-- 不输入资源时,默认访问index --%>
<%-- register.jsp --%>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
    <!--register.jsp-->
</head>

<body>
<div id="registerdiv">
    <form action="/aa/RegisterServlet" method="post" id="form">
        <h1 id="loginMsg">注册</h1>
        <div id="error">${error}</div>
        <p>username:<input id="username" name="username" type="text"></p>
        <p>password:<input id="password" name="password" type="password"></p>
        <p><input name="check" type="text" id="check"><img src="/aa/checkServlet" id="checkcode"></p>
                <a href="#" id="change">看不清?</a>
        <div id="subDiv">
            <input type="submit" class="button" value="login up">
            <input type="reset" class="button" value="reset">
            <a href="login.html">注册好了?来登录</a>
        </div>
    </form>
</div>
<script>
 document.getElementById("change").onclick=function()
    {//加上new Date().getMilliseconds()使每次url不一样,避免缓存图片而无法刷新
        document.getElementById("checkcode").src="/aa/checkServlet?"+ new Date().getMilliseconds();
    }
</script>
</body>
</html>

测试代码:

注意:下面这段代码演示了mybatis的使用方法

package com.zndx;
import com.alibaba.fastjson.JSON;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.zndx.mapper.userMapper;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//写测试用例
public class test {
    public static void main(String[] args) throws Exception {
        //这里直接粘贴官网代码,没有import导致报错
        //1、加载mybatis的核心配置文件,获取SqlSessionFactory
        String resource = "mybatis-config.xml";//这里忘记改了,用官网复制的值导致报错
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //2、获取sqlSession对象,用它执行sql
        SqlSession sqlSession=sqlSessionFactory.openSession(false);//这里设置为true,自动提交事务
        //2.1调用id依然存在硬编码问题
        List<user> users= sqlSession.selectList("com.zndx.mapper.userMapper.selectAll");//这里id写错了导致报错
        //2.2获取userMapper接口的代理对象(Mapper代理法)
        userMapper userMapper=sqlSession.getMapper(userMapper.class);
        users=userMapper.selectAll();
        System.out.println(users);
        System.out.println(userMapper.searchByIdUser(2));
        System.out.println(1+""+userMapper.selectbycondition("李四","234"));
        user a=new user();a.setUsername("李四");a.setPassword("234");
        System.out.println(2+""+userMapper.selectbycondition(a));
        Map<String,String> map=new HashMap<>();
        map.put("username","%四");map.put("password","234");
        System.out.println(3+""+userMapper.selectbycondition(map));
        String addr="",use="%%";
        users=userMapper.selectbyconditions(addr,use);
        System.out.println(users);
        map.clear();
        map.put("gender","男");
        map.clear();
        System.out.println(userMapper.selectbyconditionsingle(map));
        //insert
        a.setUsername("周");a.setPassword("520");a.setGender("女");a.setAddr("tj");
        userMapper.add(a);
        System.out.println(a.getId());
        sqlSession.commit();
        //因为insert采用事务方式,要手动提交,或者在获取对象时设置自动提交
        a.setId(4);a.setUsername("刘七");a.setPassword("521");a.setGender("男");a.setAddr("南定");
        int b=userMapper.update(a);
        System.out.println(b);//修改成功返回1,失败返回0
        sqlSession.commit();//这里也要提交
        a.setId(7);a.setUsername("赵八");a.setAddr(null);
        System.out.println(userMapper.update(a));
        sqlSession.commit();//这里也要提交
        System.out.println(userMapper.delByIdInt(8));
        sqlSession.commit();//这里也要提交
        int[] ids={9,12,13,14,15,16,17,18,19,20,21,22};
        System.out.println(userMapper.delByIdInts(ids));//返回影响行数
        sqlSession.commit();//这里也要提交
        System.out.println(userMapper.zhujiechazhao());
        System.out.println("jg: "+userMapper.select("zhangsan","123")); a.setUsername("周");a.setPassword("520");a.setGender("女");a.setAddr("tj");
        System.out.println(userMapper.add(a));;
        System.out.println(a.getId());
        //3、释放资源
        sqlSession.close();

        user user=new user();
        user.setId(1);user.setPassword("111");user.setUsername("aaa");
        user.setGender("bb");
        String jsonString = JSON.toJSONString(user);
        System.out.println(jsonString);
        user user1=JSON.parseObject("{\"addr\":\"\",\"gender\":\"bb\",\"id\":1,\"password\":\"111\",\"username\":\"aaa\"}",user.class);
        System.out.println(user1);

    }
}

<!--html5的标识-->
<!DOCTYPE html>
<html lang="en">
<head>
    <!--页面的字符集-->
    <meta charset="UTF-8">
    <title>html快速入门</title>
</head>
<!--html语法松散,如"red"不加引号,不写</font>都可以正确执行-->
<!--被干掉的标签表示过时了,它们的任务应该让css完成-->
<body>
<center><h1>这是最大的标题字体</h1></center>
<hr>
<!--html表示颜色
1、英文单词,不方便
2、rgb(1,2,3), 三原色取值在0~255之间
3、十六进制三原色,推荐,取值在00~ff之间"#ff0000"
-->
<center><font color="ff0000" size="5" face="楷体"> <p>head标题  html快速入门 显示在网页上面,这些文字写在body里<br></p>
  <p>另外html的标签不区分大小写</p>
    <b>b标签功能<br></b>
    <i>i标签功能<br></i>
    <u>u标签功能<br></u>
</font>
</center>
<hr>
<!--资源路径:
1、绝对路径:例如完整的图片链接和d盘完整的文件路径
2、相对路径:相对位置关系
例如此文件路径com/zndx/html/html.html
图片路径com/zndx/html/a.gif
此时可以把前面相同的路径写成./,而./本身又可以省略,最后写a.gif就可以了
如果图片在html目录下的img目录中,img/a.gif
如果在zndx目录下的img目录中,../img/a.gif,其中../表示往上推一层目录
尺寸单位:数字表示像素,20%表示占body窗体的20%
-->
<img src="./a.gif" width="200" height="300">
<img src="https://pic35.photophoto.cn/20150511/0034034892281415_b.jpg" width="100" height="100">
<audio src="c.mp3" controls></audio>
<video src="b.mp4" controls width="200" height="300"></video>
<a target="_blank" href="https://blog.csdn.net/sunxiaofre/article/details/55805420?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169636590316800184194099%2522%252C%2522scm
%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=169636590316800184194
099&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ec
pm-2-55805420-null-null.142^v94^insert_down1&utm_term=htmlfont%E6%A0%87%E7%AD%BE%E8%A2%AB%E4%BB%80%
E4%B9%88%E6%9B%BF%E6%8D%A2%E4%BA%86&spm=1018.2226.3001.4187">好好学习!</a>
<ol type="i">
    <li>aa</li>
    <li>bb</li>
    <li>cc</li>
</ol>
<ul type="circle">
    <li>aa</li>
    <li>bb</li>
    <li>cc</li>
</ul>
<table border="1" cellspacing="0" width="500" >
    <tr align="center">
<!--        <th>id</th>-->
<!--        让第一个单元格占两个位置-->
        <th  colspan="2">username</th>
        <th>gender</th>
    </tr>
    <tr align="center">
        <td>1</td>
        <td rowspan="2"><img src="a.gif" width="50" height="50"></td>
        <td>boy</td>
    </tr>
    <tr align="center" >
        <td>2</td>
<!--        <td>李四</td>-->
        <td>女</td>
    </tr>
</table>
<div>这是div</div>
<div>这是div</div>
<span>这是span</span>
<span>这是span</span>
<!--action:指定表单数据提交的URL,#表示提交给当前html页面
表单数据想被提交,还要再指定应该name属性
method:指定表单提交方式
1、get:默认值,把请求参数拼接在url后面,请求参数因url长度有限而有限制,例如下面执行后
http://localhost:63342/maven/html/html.html?username=2098516801%40qq.com#
2、post:请求在http协议的请求体中,请求参数无限制
-->
<form action="#" method="get">
    <input type="text" name="username">
<!--    其中username为键,提交数据作为值,传到服务端-->
    <input type="submit">
</form>

<form action="#" method="post">
    <input type="hidden" name="id" value="123">
<!--    使点击用户名时选中username输入框-->
    <label for="username">用户名:</label>
    <input type="text" name="username" id="username"><br>
    密码:<input type="password" name="password"><br>
    性别:<input type="radio" name="gender" value="1" id="m"> <label for="m">男</label>
    <input type="radio" name="gender" value="0" id="n"> <label for="n">女</label><br>
<!--    name值相同才能得到互斥效果,必须有value区分两个选项,不然到服务端都是on-->
    爱好:<input type="checkbox" name="hobby" value="1"> 旅游
    <input type="checkbox" name="hobby" value="2"> 电影
    <input type="checkbox" name="hobby" value="3"> 游戏<br>
     头像:<input type="file"><br>
     城市:<select name="city">
<!--    提交的数据以value为准,没有value填aa等-->
    <option value="aa1">aa</option>
    <option>bb</option>
    <option>cc</option>
     </select><br>
    个人描述:<textarea cols="5" rows="20" name="desc"></textarea><br>
<!--    20行,每行五字符-->
    <input type="reset">
    <input type="submit" value="免费注册"><!--value修改文本内容-->
    <input type="button" value="一个按钮">

</form>
<div id="app">
    <table >
        <tr>
            <th>id</th>
            <th>username</th>
            <th>password</th>
            <th>gender</th>
            <th>addr</th>
        </tr>
        <tr align="center" v-for="(user1,i) in user">
            <td>{{i+1}}</td>
            <td>{{user1.username}}</td>
            <td>{{user1.password}}</td>
            <td>{{user1.gender}}</td>
            <td>{{user1.addr}}</td>
        </tr>
</div>
<table id="usertable" border="1" cellspacing="0" width="100%">
    <tr>
        <th>username</th>
        <th>password</th>
        <th>gender</th>
        <th>addr</th>
    </tr>
    <tr align="center">
        <td></td>
        <td></td>
        <td></td>
        <td></td>
    </tr>
</table>

<script src="axios.js"></script>
<script src="../js/vue.js"></script>
<script>
    //页面加载完后,发送ajax请求
    window.onload=function()
    {
        axios(
        {
            method:"post",
            url:"http://localhost/aa/selectAllServlet",
            data:"username=lisi"
        }
        ).then(function(resp)
       {
        //alert("jin");
        let users=resp.data;
        let table="<tr>\n" +
        "        <th>username</th>\n" +
        "        <th>password</th>\n" +
        "        <th>gender</th>\n" +
        "        <th>addr</th>\n" +
        "    </tr>";
        for(let i=0;i<users.length;i++)
        {
            let user=users[i];
            table+="<tr align=\"center\">\n" +
            "        <td>"+user.username+"</td>\n" +
            "        <td>"+user.password+"</td>\n" +
            "        <td>"+user.gender+"</td>\n" +
            "        <td>"+user.addr+"</td>\n" +
            "    </tr>";
        }
        document.getElementById("usertable").innerHTML=table;
       }
       )
    }
</script>

<script>
   new Vue(
        {
            el:"#app",
            data(){
                return{
                    user:[]
                }
            },
            mounted(){
                //页面加载完后,发送异步请求查询数据
                var _this=this;
                axios(
                     {
                       method:"post",
                       url:"http://localhost/aa/selectAllServlet",
                       data:"username=lisi"
                     }
                     ).then(function(resp)
                     {//这里this默认为window对象,所以要在外面保留this到里面用
                        _this.user=resp.data;
                     })
            }
        }
    )
</script>

</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>css</title>
<!--  内部样式-->
  <style>
/*<!--哪个范围小哪个生效-->*/
  span{
  color:red;
  }
  #name{
  color:blue;
  }
  .cls{
  color:pink;
  }
</style>
    <link href="../css/css.css" rel="stylesheet">
</head>
<body>
<!--内联样式-->
<div style="color:red">hello css</div>
<span>hello css</span><br>
<span id="name">name</span>
<div class="cls">divclass</div>
<span class="cls">spanclass</span>
<p>hello css</p>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <div class="aa">这是div</div><br>
<div class="aa">这是div</div><br>
<img src="https://pic35.photophoto.cn/20150511/0034034892281415_b.jpg" id="bb" width="200" height="300">
  <form action="#" method="post">
    爱好:<input type="checkbox" name="hobby" value="1"> 旅游
    <input type="checkbox" name="hobby" value="2"> 电影
    <input type="checkbox" name="hobby" value="3"> 游戏<br>
  </form>
  <!-- 事件绑定方法1 -->
  <input type="button" value="一个按钮" onclick="on()">
<!-- 事件绑定方法2,推荐 -->
  <input type="button" value="两个按钮" id="oo">
  <script>
   function on()
  {
    alert("dd");
  }
  var age3=document.getElementById("oo");
  age3.onclick= function()
  {
    alert("dd");
  };
  </script>
  <!-- 表单验证 -->
  <form action="#" method="get" id="form">
   <table>
    <tr>
      <td>用户名</td>
      <td class="inputs">
        <input name="username" type="text" id="username">
        <br>
        <span id="username_err" class="err" style="display: none;">用户名不行</span>
      </td>
    </tr>
    <tr>
      <td>密码</td>
      <td class="inputs">
        <input name="password" type="text" id="password">
        <br>
        <span id="password_err" class="err" style="display: none;">密码不行</span>
      </td>
    </tr>
    <tr>
      <td>手机号</td>
      <td class="inputs">
        <input name="tel" type="text" id="tel">
        <br>
        <span id="tel_err" class="err" style="display: none;">手机号不行</span>
      </td>
    </tr>
    <tr>
      <td>
        <input id="submit" type="submit" name="submit" value="submit">
      </td>
    </tr>
   </table>
  </form>
  <script>
    var u=document.getElementById("username");
    u.onblur=cu;
    function cu(){
      let u1=u.value.trim();
      if(u1.length<6||u1.length>12)
      {
        document.getElementById("username_err").style.display='';
        return true;
      }
      else{
        document.getElementById("username_err").style.display='none';
        return false;
      }
    }
    var p=document.getElementById("password");
    p.onblur=cp;
    function cp(){
      let u1=p.value.trim();
      if(u1.length<6||u1.length>12)
      {
        document.getElementById("password_err").style.display='';
        return true;
      }
      else{
        document.getElementById("password_err").style.display='none';
        return false;
      }
    var s=document.getElementsByName("submit");
    s.onsubmit=function(){
      return cu&&cp&&ct;
    }
    }
    var t=document.getElementById("tel");
    t.onblur=ct
    function ct(){
      let u1=t.value.trim();
      if(u1.length!=11)
      {
        document.getElementById("tel_err").style.display='';
        return true;
      }
      else{
        document.getElementById("tel_err").style.display='none';
        return false;
      }

    }
  </script>
<!--在script标签里写JavaScript语句,一般放body最下面-->
<script>
  var age1=20;
    var age2="20";
    console.log(age1==age2);
    //显示为true,因为js比较时先比较类型是否相同,不同则进行类型转换,再比较值是否相同
    console.log(age1===age2);//三个等号是全等号
    //显示false,全等于比较发现类型不同直接返回false
  //js类型转换
  //string转数字:按字面值转,如“20”转为20,发现非数字的字符,转为NaN
  //boolen转数字,true转1,false转0
  //数字number类型转boolen:0和NaN转false,其他转为true
  //空字符串(只有两个引号)string转为false,其他的转为true
  //null转为false,undeinfed转为false
  var age3=+"abc";//+不是加,是正号,表示要把字符串abc转数字
  console.log(age3);
 console.log(parseInt(age2)+1);//推荐parseInt方法转数字,+是加号,显示21
  console.log("age3"+1);//+在连接不同类型时,也是连接符号
  age3=+true;
  console.log(age3);
  console.log(parseInt(age3));//parseInt(true)显示是NaN,只接受变量
  age1="aa";//可以用if(age1)代替if(age1!=null&&age1.length>0)进行判断
  age1="";
  age1=null;
  age1=undefined;
  if(age1)//因为if需要用boolen类型判断,所以会转为boolen
  {
    console.log("转为true");//20显示这个
  }
  else
  {
    console.log("转为false");
  }
  function add(a,b)
  {
    return a+b;
  }
  age1=add(1,2);
  console.log(age1);
  var add1=function(a,b)
  {
    return a+b;
  }
  age1=add1(1,2,3);//可以传任意个参数,但是只有1,2能被a,b接受,结果是3
  console.log(age1);
  age1=add1(1);//此时b是NaN,结果是NaN
  console.log(age1);
  age1=new Array(1,2,3);
  console.log(age1);
  //JavaScript数组相当于java的集合,变长变类型
  age1=[2,3,4];//这种定义数组的方法常用
  console.log(age1);
  age1[0]="wqwqe";//访问数组,变类型
  age1[10]="qq";//变长,不会数组超限,中间七个显示为undefined*7
  console.log(age1);
  for(let i=0;i<age1.length;i++)
  {
    console.log(age1.length+" "+age1[i]);//length=11包括了undefined的7个
  }
  //其他方法去w3school看
  age1.push("aa");//在age1[11]添加元素,不会补到undefined上
  console.log(age1);
  age1.splice(3,7);//从3号位开始删掉后面七个,把七个undefined删掉
  console.log(age1);
  age1[5]=new String("abc");//在数组中显示为String,表示一个String对象
  console.log(age1[5]);//正常显示
  age1[6]="abcd";//这两种定义在数组中都正常显示
  age1[7]='abcde';
  console.log(age1[7].length);//length是一个属性,不是函数
  age1[8]="   aaaaa    ";
  console.log(1+age1[8]+1);
  age1[8]=age1[8].trim();//trim去除字符串前后空格
  console.log(1+age1[8].trim()+1);
  console.log(age1);
  //自定义对象
  var person={
    name:"zhangsan",
    age:23,
    eat:function()
    {
      console.log("eat")
    }
  };
  console.log(person);
  person.eat();
//<!--弹出警告框-->
//window对象的window.可以省略
   //window.alert("aa");
   // alert("hello js");
   var flag=confirm("确认嘛");//点确定返回true,取消返回false
   if(flag)
   {
    console.log("点了确认");
   }
   else if(!flag)
   {
     console.log("点了取消");
   }
   //一定时间后执行,只执行1次
  // setTimeout(function(){
  //   console.log("过去了1秒");
  // },1000);
  // //每过一定时间执行1次,和上面的定时器同时开始计时
  // setInterval(function(){
  //   console.log("过去1秒");
  // },1000);
  // flag=confirm("要不要跳转");
  // if(flag)
  // location.href="https://fanyi.baidu.com/";
  age3=document.getElementById("bb");
  console.log(age3);
  age3.src="./a.gif";
  console.log(age3.src);
  age2=document.getElementsByTagName("div");
  //style:设置元素css样式
  //innerHTML:设置元素内容
  //这两个是通用属性,每个HTML标签都有,其他的查w3school
  console.log(age2.length);
  for(let i=0;i<age2.length;i++)
  {
    age2[i].style.color="red";
    age2[i].innerHTML="666";
     console.log(age2[i]);
  }
  age2=document.getElementsByClassName("aa");
  console.log(age2.length);
  age2=document.getElementsByName("hobby");
  for(let i=0;i<age2.length;i++)
  {
    age2[i].checked=true;
     console.log(age2[i]);
  }
  console.log("a"+age2.length);
  //正则表达式
  var reg=/^\w{6,12}$/
  console.log(reg.test("aaa")+" "+reg.test("aaaaaa"));
  </script>
<!-- <script src="../js/js.js"></script> -->
<!--script不能自闭合-->
</body>

</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--action要填虚拟目录+资源路径-->
<!--先输入http://localhost/aa/req.html访问表单-->
<!--提交表单后跳到这里http://localhost/aa/demo2-->
<!--这个表单修改后要在localhost/aa/req.html刷新,不能在localhost/aa/demo2重新输入,否则不会更新到新的HTML页面-->
<form action="/aa/demo2" method="post">
    <input type="text" name="name">
    <br>
    <input type="password" name="pass">
    <br>
    <input type="checkbox" name="hobby" value="1" >aa<br>
    <input type="checkbox" name="hobby" value="2" >bb
    <br>
    <input type="submit">
    
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script src="js/axios.js"></script>
    <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">
    <!-- src必须单独写,否则不能运行下面的代码 -->
    <div id="app">
      <input v-model="username">
      <input v-model="url"><br>
      <input v-model="count"><br>
      <a v-bind:href="url">height</a><br>
      <input type="button" value="a button" v-on:click="show()"><br>
      <!-- 简化写法 -->
      <a :href="url">height</a><br>
      <input type="button" value="a button" @click="show()"><br>
      <div v-if="count==3">div1</div>
      <div v-else-if="count==4">div2</div>
      <div v-else>div3</div><br>
      <div v-show="count==3">v-show</div>
      <!--插值表达式-->
        {{username}}
        <div v-for="addr in addrs">
            {{addr}}
        </div>
        <div v-for="(addr,i) in addrs">
           {{i+1}}--{{addr}}
        </div>
    </div>
    <script>
        //创建Vue核心对象,注意V要大写!!!
        new Vue(
            {
                el:"#app",
                data(){
                    return{
                    username:"a",//可以这样设模型初始值
                    url:"register.html",
                    count:3,
                    addrs:["aa","bb","cc"]
                  }
                },
                // data:function()
                // {
                //   return{
                //     username:"a"
                //   }
                // }
                methods:{
                    show()
                    {
                      alert("a button");
                    }
                },
                mounted(){
                    alert("mounted");
                }
            }
        );
    </script>
    <script>
    axios(
        {
            method:"get",
            url:"http://localhost/aa/ajaxServlet?username=zhangsan"
        }
    ).then(function(resp)
    {
        //alert("jin");
        console.log(resp.data);
    }
    )

    axios(
        {
            method:"post",
            url:"http://localhost/aa/ajaxServlet",
            data:"username=lisi"
        }
    ).then(function(resp)
    {
        //alert("jin");
        console.log(resp.data);
    }
    )
    //注意axios没有括号!!!
    axios.post("http://localhost/aa/ajaxServlet","username=mm").then(function(resp)
    {
        //alert("jin1");
        console.log(resp.data);
    }
    )

    axios.get("http://localhost/aa/ajaxServlet?username=zz").then(function(resp)
    {
        //alert("jin2");
        console.log(resp.data);
    }
    )
</script>
<script>
    
    //创建核心对象
    var xhttp;
    if(window.XMLHttpRequest)
    {
        xhttp=new XMLHttpRequest();
    }
    else
    {//IE5,IE6
        xhttp=new ActiveXObject("MicroSoft.XMLHttp");
    }
    //发送请求,只能填绝对路径
    xhttp.open("Get","http://localhost/aa/ajaxServlet?username=wangwu");
    xhttp.send();
    //获取响应
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            console.log(this.responseText);
       }
    };
   
</script>
<script>
  var json={
    "name":"lisi",
    "addr":["bj","sh","sz"],
    "age":23
  };
  console.log(json.name);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <style>
    .el-row {
      margin-bottom: 20px;
    &:last-child {
      margin-bottom: 0;
    }
    }
    .el-col {
      border-radius: 4px;
    }
    .bg-purple-dark {
      background: #99a9bf;
    }
    .bg-purple {
      background: #d3dce6;
    }
    .bg-purple-light {
      background: #e5e9f2;
    }
    .grid-content {
      border-radius: 4px;
      min-height: 36px;
    }
    .row-bg {
      padding: 10px 0;
      background-color: #f9fafc;
    }
  </style>
  <style>
    .el-header {
      background-color: #B3C0D1;
      color: #333;
      line-height: 60px;
    }

    .el-aside {
      color: #333;
    }
  </style>
</head>
<body>
<script src="js/axios.js"></script>
<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">
<div id="app">
  <el-row>
    <el-button>默认按钮</el-button>
    <el-button type="primary">主要按钮</el-button>
    <el-button type="success">成功按钮</el-button>
    <el-button type="info">信息按钮</el-button>
    <el-button type="warning">警告按钮</el-button>
    <el-button type="danger">危险按钮</el-button>
  </el-row>

  <el-row>
    <el-button plain>朴素按钮</el-button>
    <el-button type="primary" plain>主要按钮</el-button>
    <el-button type="success" plain>成功按钮</el-button>
    <el-button type="info" plain>信息按钮</el-button>
    <el-button type="warning" plain>警告按钮</el-button>
    <el-button type="danger" plain>危险按钮</el-button>
  </el-row>

  <el-row>
    <el-button round>圆角按钮</el-button>
    <el-button type="primary" round>主要按钮</el-button>
    <el-button type="success" round>成功按钮</el-button>
    <el-button type="info" round>信息按钮</el-button>
    <el-button type="warning" round>警告按钮</el-button>
    <el-button type="danger" round>危险按钮</el-button>
  </el-row>

  <el-row>
    <el-button icon="el-icon-search" circle></el-button>
    <el-button type="primary" icon="el-icon-edit" circle></el-button>
    <el-button type="success" icon="el-icon-check" circle></el-button>
    <el-button type="info" icon="el-icon-message" circle></el-button>
    <el-button type="warning" icon="el-icon-star-off" circle></el-button>
    <el-button type="danger" icon="el-icon-delete" circle></el-button>
  </el-row>

  <el-row>
    <el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col>
  </el-row>
  <el-row>
    <el-col :span="12"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="12"><div class="grid-content bg-purple-light"></div></el-col>
  </el-row>
  <el-row>
    <el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="8"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
  </el-row>
  <el-row>
    <el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
  </el-row>
  <el-row>
    <el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
  </el-row>
  <el-row>
    <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple"></div></el-col>
    <el-col :span="3"><div class="grid-content bg-purple-light"></div></el-col>
  </el-row>


  <el-container style="height: 500px; border: 1px solid #eee">
    <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
      <el-menu :default-openeds="['1', '3']">
        <el-submenu index="1">
          <template slot="title"><i class="el-icon-message"></i>导航一</template>
          <el-menu-item-group>
            <template slot="title">分组一</template>
            <el-menu-item index="1-1">选项1</el-menu-item>
            <el-menu-item index="1-2">选项2</el-menu-item>
          </el-menu-item-group>
          <el-menu-item-group title="分组2">
            <el-menu-item index="1-3">选项3</el-menu-item>
          </el-menu-item-group>
          <el-submenu index="1-4">
            <template slot="title">选项4</template>
            <el-menu-item index="1-4-1">选项4-1</el-menu-item>
          </el-submenu>
        </el-submenu>
        <el-submenu index="2">
          <template slot="title"><i class="el-icon-menu"></i>导航二</template>
          <el-menu-item-group>
            <template slot="title">分组一</template>
            <el-menu-item index="2-1">选项1</el-menu-item>
            <el-menu-item index="2-2">选项2</el-menu-item>
          </el-menu-item-group>
          <el-menu-item-group title="分组2">
            <el-menu-item index="2-3">选项3</el-menu-item>
          </el-menu-item-group>
          <el-submenu index="2-4">
            <template slot="title">选项4</template>
            <el-menu-item index="2-4-1">选项4-1</el-menu-item>
          </el-submenu>
        </el-submenu>
        <el-submenu index="3">
          <template slot="title"><i class="el-icon-setting"></i>导航三</template>
          <el-menu-item-group>
            <template slot="title">分组一</template>
            <el-menu-item index="3-1">选项1</el-menu-item>
            <el-menu-item index="3-2">选项2</el-menu-item>
          </el-menu-item-group>
          <el-menu-item-group title="分组2">
            <el-menu-item index="3-3">选项3</el-menu-item>
          </el-menu-item-group>
          <el-submenu index="3-4">
            <template slot="title">选项4</template>
            <el-menu-item index="3-4-1">选项4-1</el-menu-item>
          </el-submenu>
        </el-submenu>
      </el-menu>
    </el-aside>

    <el-container>
      <el-header style="text-align: right; font-size: 12px">
        <el-dropdown>
          <i class="el-icon-setting" style="margin-right: 15px"></i>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item>查看</el-dropdown-item>
            <el-dropdown-item>新增</el-dropdown-item>
            <el-dropdown-item>删除</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
        <span>王小虎</span>
      </el-header>

      <el-main>
        <el-table :data="tableData">
          <el-table-column prop="date" label="日期" width="140">
          </el-table-column>
          <el-table-column prop="name" label="姓名" width="120">
          </el-table-column>
          <el-table-column prop="address" label="地址">
          </el-table-column>
        </el-table>
      </el-main>
    </el-container>
  </el-container>
</div>
<script>
  new Vue({
  el:"#app",
    data() {
      const item = {
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      };
      return {
        tableData: Array(20).fill(item)
      }
    }
  })
</script>

</body>
</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值