目录
27、接口interface(定义规范、标准,int a等默认是常量)
31、可变字符序列(StringBuilder和StringBuffer,idea缩写SB)
33、Date(时间),DateFormat(时间和字符串转化),Calendar类
41、Apache IO包(官网http://www.apache.org)
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下面绿色按钮:调试,执行到断点自动停下,会显示调用的栈帧和当前变量的值,调试按钮在栈帧显示的上面
点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)
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把类加载到内存中
分实体类(存储数据)和过程类(处理数据)
初始化:把类从磁盘加载到内存->立即初始化静态成员(包括静态块)->在堆中开辟空间,初始化非静态成员
右键最上面的文件夹,new一个Module(项目下的子项目),然后在它的src上右键new一个class
类包括属性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();
同属于一个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);
}
}
分配对象空间,并将对象成员初始化为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类的一个实例
比较规则:
不能直接用==比较,要用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类
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在方法的调用栈中查找,从生成异常的方法开始回溯,直到找到对应的异常处理代码为止
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特点:有序,可重复
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)
键(key)和值(value)都是对象,通过键来标识,键对象不能重复(equals方法判断重复)
Map接口有HashMap、TreeMap、HashTable、Properties等实现类
HashMap线程不安全,效率高,允许key或value为null,常用
HashTable线程安全,效率低,不允许key或value为null
HashMap用哈希表实现,原理图如下
早期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文件不包括泛型中的类型信息,类型转换仍然是普通的强制转换
泛型主要是方便写代码,更好的安全性检测,认识泛型标记便于读代码
40、IO流技术(input,out)
输入、输出流的划分是相对程序而言的,并不是相对数据源
文件字节流可以处理所有文件,但是处理unicode字符可能乱码,以字节为单位
文件字符流用于处理文本文件(txt结尾,word,pdf不是),以字符为单位
在copy1方法中演示
内部是一个数组
处理基本数据类型和字符串,采用装饰器修饰new FileInputStream(wj)
h'f
上面的接口是一个空接口,用于标记是否可以序列化
转换流:可以把字节流转为字符流 ,使两者对的上
随意访问文件流:用RandomAccessFile类可以不按顺序随意的访问、读写文件,正常需要按照先后顺序读取
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)
增加装饰,可以为类增加新功能
官网->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语言的重要特性)
程序是一个静态概念,对应操作系统一个可执行文件,运行程序时产生进程
java线程分为green threads和native threads
就绪->运行由系统决定
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,产生同步阻塞)
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、生产者消费者模式
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、线程池
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(面试常见)
图中实线是强引用,虚线是弱引用
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、学习要求
自我介绍:我的职业发展是什么、我的优势是什么、我的劣势是什么、我要补充哪些不足、我对工作是什么态度
简历:最重要的是项目经验和职业技能
html、css、js也要学
48、设计模式
最重要
49、动态代理模式
50、NIO、BIO、AIO
文件读取
文件写入
51、注意事项
a、 java比较字符串数组是看它们的地址是否相同,不看内容是否相同,比较内容时用String或char数组
b、注意用nextLine跨行读取会出现数组超限,无法读取下一行,建议单独写一个方法进行读取
c、注意需要回溯到任意位置时要保存前面的内容,用StringBuilder等引用类型使方法可以修改它
d、需要重复输出某串,应该先把它读出来
e、可以用字符串比较规则如是否大于“80”判断最高位是否为0:8的码1000
f、进制转换有下面的方法
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、对于下面的图解,应该自己编一个经过所有过程的样例,考虑所有情况
或者用一维数组存待填充内容,用一个二维数组记录每个坐标对应一维数组的下标,填充时根据这个数组的坐标到一维数组取数
k、一个地区被标记后七天封控,要把七天都写如该地区对应的set容器,否则在计算某人是否有风险时再推七天很难覆盖前几天有风险的人
l、比较都用equals方法,不要用==
52、JDBC
下载JDBC看这个:http://t.csdnimg.cn/hQGas
配置JDBC看这个:http://t.csdnimg.cn/Hldfo
注意mysql列的编号从1开始
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();
}
}
53、maven
创建maven项目看这个:http://t.csdnimg.cn/qZ48G
每次创建新项目都要重新配置一次maven路径!!!!
创建java项目
创建javaweb项目
执行maven命令
查找坐标:Maven Repository: Search/Browse/Explore (mvnrepository.com)
进去直接搜索后复制坐标,或者浏览器搜mysql maven进入这个网站
拷好坐标后,点右上角这个按钮下载jar包
如果加载不出来,按它刷新
或者这样设置,自动生效
编译环境: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中文网
创建配置文件
idea连接数据库
没有database侧栏看这个:http://t.csdnimg.cn/Xol9x
注意:需要同时安装database navigator和maven helper才能正常用database navigator执行sql语句!
必须使用/分割才能形成包结构
鼠标把xml文件拖进去
不能通过复制得到,重构要建三层文件夹再拖进去
mybatis-config.xml是mybatis核心配置文件
environment配置用来连接多个数据库,如development和test环境可以连接不同的数据库,通过default切换数据库连接
界面红鸟是映射文件,蓝鸟是接口
想添加sql语句时,随便起个函数名字,然后选中后按alt+enter,这个插件会帮忙在配置文件定义这个语句
更新数据库后,database navigator需要点左下蓝色图标才能刷新查询结果
代码及执行
<?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可以省略不写,<是小于号转义字符,或者使用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();
}
}
项目结构
运行结果
55、web核心
感谢大佬的api文档:http://t.csdnimg.cn/xnMkM
建议正常关闭,强制关可能丢失数据
多次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>
精确匹配和目录匹配同时存在时,输入精确匹配的路径会访问到精确匹配的servlet
配置/会导致无法访问静态资源,不要这样配
社区版设置不了
虽然我的tomcat版本是8,但是idea的tomcat插件仅支持到tomcat7,所以还是有这个问题
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
el表达式不能用看这个:http://t.csdnimg.cn/AJqqJ
<%@ 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);
}
}
加入service层是为了提高代码复用性
57、会话跟踪技术
session可以保存在服务器硬盘中,关服务器再打开仍然有效,但是浏览器关闭后再打开,就获取不到相同的session,而cookie可以设置存活时间,存用户端硬盘里,关浏览器再打开仍然有效
要自己加工具类:http://t.csdnimg.cn/7MTOk
<%@ 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可以省略不写,<是小于号转义字符,或者使用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&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
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() {
}
}
59、AJAX
去这里拿axios:http://t.csdnimg.cn/nMkUX
60、json
61、vue
62、Element
官网:组件 | Element
安装参考:http://t.csdnimg.cn/AhIqI
63、案例及代码
运行演示:还有一些奇奇怪怪的问题,不过好歹是可以用的
项目结构:
配置环境:
<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&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可以省略不写,<是小于号转义字符,或者使用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>