Fork me on GitHub

Java学习笔记

补码:反码+1;
-n = ~n + 1; ~n(n取反)
int num = Integer.parseInt(bin,2); //把一个字符串转换成一个数字,
第二个参数是进制,第二个参数不写默认是十进制。
^ 异或 相同为1,不同为0
a=a^b b=a^b a=a^b 互换
基本类型:byte short char int long float double boolean
int 及int以下类型的每个元素默认值是0,浮点型的默认值是0.0,boolean默认false,引用类型默认null;
除了8种基本类型,其他的都是引用类型
long now = System.currentTimeMillis();//时间的计算,当前毫秒数,距离1970年到现在的毫秒数
在不超过float的情况下,字面量也是可以直接赋值的,超过的情况加F或f,最好大写;
默认的浮点直接量为double型,如果需要表示float类型的直接量,需要加F或f后缀
强制转换: int a = (int)b;
不满int 类型的,运算时自动转换成int类型进行计算

1
2
3
4
5
6
7
8
9
10
11
12
13
Random random = new Random(); //随机数,import java.util.Random;
c+random.nextInt(26); //0~25的随机数
int a = i++; //变量i使用完之后再自加1
int a = ++i; //使用变量i之前,i自加1
字符串相等表示: a.equals(b); //这里要注意空指针异常(NullPointerException),a不能为null
int [] arr = new int [3]; //定义完,不赋值,数组创建之后固定长度
int [][] arr = new int [4][]; //第一维的长度必须给[row][col]
System.arraycopy(arr1,0,arr2,0,arr1.length); //(被拷贝,起始位,拷贝后,起始位,拷贝长度)
String str= Arrays.toString(arr); //数组转为字符串
int [] arr = Arrays.copyOf(arr,arr.length+3); //数组扩容的简便方法
System.arraycopy(src,srePos,dest,destPos,length); //数组拷贝
Arrays.sort(arr); //正序,快速排序
Arrays.toString(arr); //转换成字符串

带符号右位移>>(前面补正数0或负数1) 无符号位移>>>(前面补0)
double d:保留小数:String.format(“%.2f”,d);前面补0:String.format(“%02d”,number);
System.exit(0); //结束java进程
三目运算符后面的类型会有一个小统一;99.9:9—–>99.9:9.0
递归:只要找到一层的规律,整个问题就解决了,代码简洁,容易产生栈溢出,能用递归做的事都能用循环,斐波那契
发散递归,效率极其慢(多个分支),使用递归要避免栈溢出,避免发散递归
好的算法的要求:正确可读健壮高效
栈:栈用于存放方法中的局部变量
堆:对象存储在堆中
方法区:方法区用于存放类的信息
import 包名+类名;

面向对象(OOP object oriented programming):封装,继承,多态

封装:

属性私有化,给外部提供访问属性的公有方法。
对象:类的实例化 属性和方法依赖对象存在 this代表当前对象
引用类型的数组,用之前不仅要给数组初始化(分配数组长度),还要给数组元素初始化(new 对象,否则空指针)
默认添加无参构造器,前提是该对象类无构造器
构造器:方法名和类名一致,并且没有返回值类型,每个类都有构造器,作用:给对象属性初始化
构造器可以相互调用,但是不能出现死循环。 this();调用自己的构造器(无参构造器)
习惯:实体类先把无参构造器写上(无论无参构造器需不需要)
局部代码块:局部位置,用于限定变量的生命周期
构造代码块:在类的成员位置,每次调用构造都执行,并且在构造方法前执行,多个构造方法中相同的代码存放到一起,对对象进行初始化
静态代码块:一般是对类进行初始化, 同一个类中,静态代码块在main方法前执行(不论顺序)
继承:java语言不支持多重继承,一个类只能继承一个父类,一个父类可以有多个子类
1.子类继承父类,就继承了父类所有的属性和方法
2.子类对象创建之前,先创建父类对象
3.子类构造器默认调用父类的无参构造器:super();
子类方法可调用super.方法();
private修饰的成员变量和方法仅仅只能在本类中调用;
public修饰的成员变量和方法可以在任何地方调用
protected:子类或同包能够访问
方法签名:方法名,参数
方法重载Overload:在一个类中,方法名一样,参数不一样(参数个数,类型,顺序不一样);静态方法不会重载
方法重写Override:方法签名(方法名,参数)相同
重写和返回值类型的关系:返回值类型必须一样;如果是引用类型,子类方法的返回值类型必须是父类的返回值
类型的子类或相同。
重写和访问控制符的关系:子类重写的方法必须比父类的方法更开放。
静态的方法不存在重写,父类的私有方法不能被重写
多态: Father f = new Child();
多态:编译看左边,运行看左边(成员变量,静态方法),运行看右边(成员方法)
在同一个类中,通过方法的重载实现多态

抽象:

抽象方法和抽象类
由abstract修饰的方法为抽象方法,抽象方法只有方法的定义,没有方法体实现,用一个分号结尾;
一个类中如果包含抽象方法,该类应该用abstract关键字声明为抽象类;
如果一个类继承了抽象类,必须重写其抽象方法(除非该类也声明为抽象类)

1
2
3
abstract class abs{
public abstract void method();
}

抽象类不可以实例化,即使一个类中没有抽象方法,也可以将它定义为抽象类
abstract和final关键字 不可以同时修饰一个类,final使得类不能被继承,而abstract修饰的类
如果不继承将没有任何意义
一个类继承了抽象类后必须重写其抽象方法
抽象类的意义:
1.为其子类提供一个公共的类型
2.封装子类中的重复内容(成员变量和方法)
3.定义有抽象方法,子类虽然有不同的实现,但该方法的定义是一致的

接口:

接口可以看成特殊的抽象类,即只包含抽象方法的抽象类

1
2
3
4
interface Runner(){
public static int DEFAULT_SPEED = 10;
public void run();
}

通过interface关键字定义接口
接口中不可以定义成员变量,但是可以定义常量
接口中只可以定义没有实现的方法(抽象方法)(可以省略 public abstract);
一个类可以通过implements关键字实现接口(多个接口用逗号分隔),
一个类实现了某个接口后,必须实现该接口中定义的所有方法。
接口可以作为一种类型声明变量,一个接口类型变量可以引用实现了该接口的类的对象,
通过该变量可以调用该接口中定义的方法(具体的实现类提供了方法的实现)。
例:Collection c = new ArrayList();(c只能用Collection中有的方法)
接口的继承:子接口继承了父接口中定义的所有方法

内部类:一个类(Inner)定义在另一个类(Outer)的内部,对外不具备可见性,Inner可以调用Outer的

如果一个类定义在了一个方法中,要调用该方法中的变量(该类与该变量同级,那么该变量要用final修饰)
成员和方法(包括private)
匿名内部类:Action action = new Action(){};

static:静态的,不依赖对象存在的

1.修饰属性:属性每次改变都保存,类名可直接调用该属性
2.修饰方法:静态方法内不能使用非静态属性及方法
3.修饰代码块:静态代码块最先调用,只调用一次。被加载就被执行
4.修饰类:内部类

final:

1.修饰属性:常量,不能被修改(常量命名规范:全部大写),引用类型的常量只需保证引用不变
2.修饰方法:不能被重写
3.修饰类:不能被继承
什么时候类会被加载?
1.实例化对象时 Child cd = new Child();
2.使用它的静态属性,方法
3.实例化子类对象时,父类会被加载
4.使用子类的静态属性,静态方法,父类会被加载
5.反射相关
类加载过程(1.创建类的对象2.调用类的静态属性和方法3.创建该类的子类对象时):(加载)Zi z = (实例化) new Zi();
用到某一个类就加载,懒惰式加载(只加载一次);
1.将类中的方法加载到方法区
2.将类中的静态属性开辟空间并初始化(0,null)
3.静态属性进行赋值操作并同时执行静态代码块(谁在前谁先执行)
对象实例化的过程:
1.在堆中开辟空间,给非静态属性开辟空间并初始化
2.给非静态属性赋值并同时执行非静态代码块,从上至下
3.最后调用构造器,递归调用(先父后本) 父类构造器在2之前

正则表达式

是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。其实就是一种规则
(反斜线)代表转义作用,\代表’\’
字符类:
[abc] a,b或c
[^abc] 任何字符,除了a,b或c
[a-zA-Z] a-z或A-Z,两头的字母包括在内(范围)
[0-9] 0-9的字符都包括
预定义字符类:
. 任何字符(字符本身.)
\d [0-9]
\w [a-zA-Z0-9]
\s 空白字符[\t\n\f\r]
边界匹配器:
^ 行的开头
$ 行的结尾
\b 单词边界,就是不是单词的地方
Greedy数量词:
x? x,一次或一次也没有
x* x,零次或多次
x+ x,一次或多次
x{n} x,恰好n次
x{n,} x,至少n次
x{n,m} x,至少n次,但是不超过m次

API

String

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
str.toUpperCase(); //转换成大写
str.toLowerCase(); //转换成小写
str.equals(str1);
str.equalsIgnoreCase(str1);
boolean str1.startsWith(str);; //返回布尔变量,以某个字符串开头
boolean str1.endsWith(str); //以某字符串结尾
str.isEmpty(); //判断字符串是否为空
boolean str1.contains(str); //包含某个字符串
int str1.indexOf(str); //返回指定字符串(字符)在此字符串中第一次出现处的索引
int str1.indexOf(str,num); //返回指定字符串在此字符串中从指定位置后第一次出现处的索引
int str1.lastIndexOf(str); //从后开始找返回str第一次出现的角标
String substring((int)start); //从指定位置开始截取字符串,默认到结尾
String substring(start,end); //从指定位置开始,指定位置结束截取字符串,包头不包尾
String str1.concat(str2); //字符串拼接
int str.compareTo(str1); //比较两字符串大小,1>;0=;-1<;
int str.compareToIgnoreCase(str1); //比较两字符串大小,忽略大小写
String str.replace(str1,str2); //在str字符串中,str2替换str1
String[] str.split(regex); //切割字符串
boolean str.matches(regex); //判断功能
String str.trim(); //去首尾空格
char charAt(index); //获取索引位置字符
char [] str.toCharArray(); //将字符串转换成字符数组
byte[] str.getBytes(); //把字符串转换为字节数组
static String.valueOf(x); //将各种类型的x转换为字符串

输出对象的时候,相当于调用对象的toString()方法
基本类型比较的是值是否相同;引用类型:比较的就是地址值是否相同
String的equals()方法是重写自Object类的,比较的是字符串的内容是否相同
java.util
Scanner sc = new Scanner(System.in);
boolean sc.hasNextXxx(); 判断是否是某种类型的元素
Xxx sc.nextXxx(); 获取该元素
String sc.nextLine();获取一个String类型的值;回车作为第二个字符串的开始
字符串是常量,一旦被赋值,就不能被改变。值被改变是因为字符串的指向改变了(引用)
字符串如果是变量相加,先开空间,再拼接;如果是常量相加,先加,在常量池里找,有则直接返回,没有创建
String s1 = “abc”; 创建一个对象常量池找
String s2 = new String(“abc”); 创建2个对象,栈—>堆—>常量池

StringBuilder

StringBuffer 线程安全的可变字符序列,一个类似于String的字符缓冲区,但不能修改
StringBuilder:与StringBuffer类似,不保证同步(效率高),一般用StringBuilder;

1
2
3
4
5
6
7
StringBuilder sb.append(str); //将任意类型加入到字符串缓冲区
StringBulider sb.deleteCharAt(index); //删除指定位置的字符,并返回sb本身
StringBuilder sb.delete(start,end); //删除从指定位置开始指定位置结束的内容,并返回本身
StringBuilder sb.replace(start,end,str);//从str开始到end结束用str替换
String sb.subString(start); //截取
String sb.subString(start,end);
StringBuilder sb.reverse(); //反转

StringBuilder–>String:String str = new String(sb);sb.toString;
String–>StringBuilder:StringBuilder sb = new StringBuilder(str);
形式参数:
基本类型:形式参数的改变不影响实际参数
引用类型:形式参数的改变直接影响实际参数
字符串是特殊的引用类型,只能当作基本类型来看,形参改变无影响
(因为字符串改变时,指向改变了。形参还是原来的指向)
StringBuilder(StringBuffer)形参为引用

Integer:

1
2
3
4
5
String bin = Integer.toBinaryString(i); //将i转成二进制字符串
String bin = Integer.toOctalString(i); //将i转成八进制字符串
String hex = Integer.toHexString(i); //将i转成十六进制字符串
int Integer.MAX_VALUE;
int Integer.MIN_VALUE;

1.Integer in = new Integer(str);int i = in.intValue(); //String–>int
2.int i = Integer.parseInt(str);
十进制到其他进制:
Integer.toString(100,x);
Integer.parseInt(100,x);

JDK5新特性

自动装箱:把基本类型转换为包装类类型
自动拆箱:把包装类类型转换为基本类型

类Math:

1
2
3
4
5
6
7
8
9
static final double PI; //圆周率π
static int abs(int num); //绝对值
static double ceil(double d); //向上取整
static double floor(double d); //向下取整
static max (int a ,int b ,); //最大值 min最小值
static double pow(double a,double b); //a的b次幂
static double random(); //随机数[0.0,1.0)
static int round(float a); //四舍五入
static double sqrt(a); //a的正平方根

类Date:

1
2
3
Date d = new Date(); util包下
Long d.getTime(); 获取时间,以毫秒为单位
Void d.setTime(time); 设置时间,通过毫秒值获取时间

类SimpleDateFormat

1
2
3
4
String str ="yyyy年MM月dd日HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(str);
Date-->String: String str = sdf.format(d);
String-->Date: Date d= sdf.parse(str);

类Calendar(日历类)

1
2
3
4
5
Calender calender = Calender.getInstance(); //得到当前时间
int year = calender.get(Calender.YEAR); //获取该时间的年
final void calender.set(int year,int month,int date); //设置时间
void calender.add(int field,int amount); //为该时间的某个量加上值
Calender-->Date: Date d = calender.getTime();

集合类

集合类(Collection):数组的长度是固定的,为了适应变化的数组,Java提供了集合类,
数组储存的是同一种类型的元素,而集合可以储存不同类型的元素。数组可以储存基本数据类型和引用数据类型
而集合只能储存引用数据类型
Collection(List有序,可重复;Set无序唯一):是集合的顶层接口,它的子体系有重复的,有唯一的,有有序的,有无序的。

1
2
3
4
5
6
7
8
9
10
Collection c = new ArrayList();
boolean c.add(obj); //添加一个元素
boolean c.add(Collection c); //添加一个集合的元素
boolean c.remove(obj); //移除一个元素(给定元素第一个,equals比较为true);
boolean c.removeAll(Collection c1); //移除一个集合的元素,只要有一个就return true;
boolean c.contains(obj); //判断集合中是否包含指定的元素
boolean c.containsAll(Collection c1); //判断集合中是否包含指定的集合元素(包含所有元素才叫包含)
void c.clear(); //移除所有元素
boolean c.isEmpty(); //判断集合是否为空
int c.size(); //集合的长度

集合–>数组:Object[] c.toArray();

迭代器方法:

1
2
3
4
Iterator it = c.iterator(); //获取迭代器
boolean it.hasNext(); //判断是否还有下一个元素
E it.next(); //返回迭代器的下一个元素
it.remove(); //迭代器删除元素

List集合的特点:有序(存储和取出的元素一致),可重复
List集合方法:
List list = new ArrayList();
void list.add(index,ele); 在指定位置添加元素,原位置及后续元素顺序向后移动
list.get(index); 获取指定位置的元素
ArrayList:底层数据结构是数组,增删慢,查询快,线程不安全,效率高
Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低
LinkedList:底层数据结构是链表,增删快,查询慢,线程不安全,效率高

LinkedList集合方法:

1
2
3
4
5
6
7
LinkedList link = new LinkedList();
void link.addFirst(obj); //集合开头添加元素
void link.addLast(obj); //集合结尾添加元素
obj link.getFirst(); //得到集合第一个元素
obj link.getLast(); //得到集合最后一个元素
obj link.removeFirst(); //返回被删元素
obj link.removeLast(); //返回被删元素

泛型(泛型类型必须是引用类型):是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型
泛型把运行时期的问题提前到了编译时期,避免了强制类型转换,优化程序设计,提高了程序的安全性
把泛型定义在类上:public class 类名<泛型类型1,泛型类型2…>
把泛型定义在方法上:public <泛型类型> 返回类型 方法名(泛型类型T);
把泛型定义在接口上: public interface 接口名<泛型类型1,泛型类型2…>;
增强for(JDK5新特性,本质为迭代器)(不能用集合方法删元素):

1
2
3
for(String s :arr){
System.out.println(s);
}

Set接口:无序(存储顺序和取出顺序不一致),唯一;有自己的存储顺序
TreeSet(排序和唯一):底层是二叉树结构,能够对元素按照某种规则进行排序

自然排序:

1
2
3
4
5
6
7
public class Point implements Comparable<Point>{
public int compareTo(Piont p){
int num = this.getX()-p.getX();
int num2 = num==0?this.getY()-p.getY():num;
return num2;
}
}

比较器排序:

1
2
3
4
5
6
Comparator<String> com1 = new Comparator<String>(){
public int compare(String o1,String o2){
return o1.length()-o2.length()
}
};
Collections.sort(list,com1);

HashSet:有自己的储存顺序,例如从小到大
Map集合:可以存储键值对的元素,将键映射到值的对象,一个映射不能包含重复的键;每个
键最多只能映射到一个值.Map集合存储元素是成对出现的,键是唯一的,值是可重复的

1
2
3
4
5
6
7
8
9
10
11
12
13
//10是容量,但是.size()还算要看放进去几个键值对。Collection中也一样
Map<Integer,String> map = new HashMap<Integer,String>(10);
V map.put(key,value); //添加元素,若已有key,value被覆盖,返回值为“前妻”。若无该key,返回null
V map.remove(key); //根据键删除键值对元素,并把删除掉的值返回
void map.clear(); //移除所有的键值对元素
int map.size(); //返回集合中键值对的对数
boolean map.containsKey(key); //判断集合是否包含指定的键
boolean map.containsValue(value); //判断集合是否包含指定的值
boolean map.isEmpty(); //判断集合是否为空
Set<Entry<String,Integer>> entryset = map.entrySet(); //获取键值对对象的集合
V map.get(key); //根据键获取值,无该键返回null
Set<K> keyset = map.keySet(); //获取集合中所有键的集合
Collection<V> values = map.values(); //获取集合中所有值的集合

LinkedHashMap:有序的Map
TreeMap:(TreeSet大部分方法调用了TreeMap中方法,无序(基于红黑树(red-black tree)数据结构实现, 按 key 排序.))
HashMap:使用哈希表(hash table)实现, 在 keys 和/或 values 之中,都是无序的.
HashTable:Hashtable 与HashMap实现方式一样,但Hashtable属于同步(synchronized)的.
Collections:是针对集合操作的工具类,有对集合进行排序和二分查找的方法
Vector和Hashtable,Properties是同步的,ArrayList和HashMap不是同步的
栈(Stack):先进后出;
E pop():移除栈顶部对象,并返回该值;E push(E item):把对象压入栈顶;E peek():查看栈顶对象;boolean empty():测试该栈是否为空
队列:先进先出:BlockingQueue queue = new ArrayBlockingQueue(10);
boolean b =queue.offer(i,5,TimeUnit.SECONDS);将对象添加至队尾;Integer num =queue.poll(5,TimeUnit.SECONDS);从队首删除并返回一个元素5,TimeUnit.SECONDS 可不写

异常处理:

1
2
3
4
5
6
7
try{
}catch(Exception e){
e.printStackTrace();
}finally{
}

多个异常处理:多个try{}catch{};一个try{}多个catch{};
运行时异常:RuntimeException类及其子类的实例,非检测异常
编译时异常:其他异常,必需处理
自定义异常:必须继承自Exception或RuntimeException
throws:方法上抛出异常对象
throw:方法内部抛出异常对象
子类重写父类的方法时,子类的方法必须抛出相同的异常或父类异常的子类或者不抛或者抛一部分
如果父类抛出多个异常,子类重写父类时,只能抛出相同的异常或者是它的子集,子类不能抛出
父类没有的异常,如果被重写的方法没有异常抛出,子类只能try{}catch(){},不能throws;
final:可以修饰类,成员方法,成员变量.修饰类,类不能被继承.
修饰方法,方法不能被重写.修饰变量,变量是常量
finally:异常处理的一部分,被finally控制的语句体一定会被执行,除非finally{}前有System.exit(0)了。
finalize:是Object类的一个方法,用于垃圾的回收

类File

File file = new File(“.”+File.separator+”demo.text”);
File file1 = new File(file,”a.text”);
创建功能:public boolean createNewFile():创建文件,如果存在这样的文件,就不创建了。
public boolean mkdir();创建文件夹,如果存在这样的文件夹就不创建;public boolean mkdirs();创建文件夹,如果父文件夹不存在,会帮你创建。
删除功能:public boolean delete();删除一个文件(夹),文件夹内不能包含文件(夹);删除成功返回true,失败返回false;
判断功能:public boolean isDirectory();判断是否目录;public boolean isFile();判断是否文件;public boolean exists();判断是否存在
获取功能:public String getName();获取名称;public long length();获取长度,字节数;public long lastModified();获取最后一次修改时间,毫秒值
public String[] list();获取指定目录下所有文件(夹)的名称数组;public File[] listFiles();获取指定目录下所有文件(夹)的File数组;
递归删除多级目录:

1
2
3
4
5
6
7
8
9
public static void deleteFile(File file){
if(file.isDirectory()){
File[] subs = file.listFiles();
for(File sub:subs){
deleteFile(sub);
}
}
file.delete();
}

IO流

InputStream(IS)(所有字节输入流的父类);
int read():读取一个字节,以int形式返回,返回值为-1,则读完;int read(byte[] d):读取d.length的字节存到d中,返回值为实际读到的字节量
OutputStream(OS)(所有字节输出流的父类);
void write(int d):写出一个字节;void write(byte[] d):将d的所有字节写出
字节流:
FileOutputStream(FOS):
构造函数:FileOutputStream(File file);向file写数据(重写模式)FileOutputStream(String filename);向名字为filename的文件写数据(重写模式);
void write(int d);void write(byte[] d);void write(byte[] d,int offset,int len);将d中从偏移量off开始的len字节写入此文件输出流
追加模式:FileOutputStream(File file,true);FileOutputStream(String filename,true);
FileInputStream(FIS):
FileInputStream(File file);FileInputStream(String name);int read();int read(byte[] d);
高级字节流:
缓冲字节输出流(BOS):BufferedOutputStream bos = new BufferedOutputStream(fos);所有字节被存入缓冲区等待一次性写出;bos.close();关闭流之前会将缓冲区内容写出;
void flush();清空缓冲区,将缓冲区中的数据强制写出;
缓冲字节输入流(BIS):BufferedInputStream bis = new FileInputStream(fis); bis.close();
int d = -1;
while((d=bis.read())!=-1){
System.out.print(d);
}
字符流:
Reader是字符输入流的父类;
int read();读取一个字符;int read(char[] chs);读取chs.length个字符到chs中,返回值为读到的字符量;
Writer是字符输出流的父类;
void write(int c);写出一个字符;void write(char[] chs);将给定chs写出;void write(char[] chs,int offset,int len);void write(String str);将给定字符串写出
字符转换流(字符流子类,实现字符流方法)(将字节流转换为字符流,可以设置字符集):
InputStreamReader:构造方法:InputStreamReader(InputStream in,String charsetName);InputStreamReader(InputStream in);
OutputStreamWriter:构造方法:OutputStreamWriter(OutputStream out,String charsetName);OutputStreamWriter(OutputStream out);
高级流:
缓冲字符输出流(PW):PrintWriter:PrintWriter(File file);PrintWriter(String fileName);PrintWriter(OutputStream os);PrintWriter(Writer writer);
PrintWriter(OutputStream os,boolean autoFlush);PrintWriter(Writer writer,boolean autoFlush);autoFlush判断是否自动行刷新.
void print/println(八种基本类型):通过该方法写出的内容会被实际写出;
缓冲字符输入流(BR):BufferedReader:构造方法:BufferedReader(Reader reader);String readLine();读一行
对象序列化(OOS):ObjectOutputStream oos = new ObjectOutputStream(fos);void writeObject(Object o);将对象转换为字节序列
需要序列化所属的类必须实现Serializable接口;关键字transient:被该关键字修饰的属性在序列化时,其值将被忽略(瘦身);
对象反序列化(OIS):ObjectInputStream ois = new ObjectInputStream(fis);Object readObject();将字节序列转换为对应对象;

输入输出到文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
public void Input()throws Exception{
InputStream in = new FileInputStream(new File("."+File.separator+"demo.txt"));
InputStreamReader isr = new InputStreamReader(in,"utf-8");
BufferedReader br = new BufferedReader(isr);
String s = null;
StringBuilder sb = new StringBuilder();
while((s=br.readLine())!=null){
System.out.println(s);
if(s.indexOf("881101") == 0) sb.append(s.substring(7, s.length())+",");
}
System.out.println(sb);
}
@Test
public void Output() throws Exception{
OutputStream out = new FileOutputStream(new File("."+File.separator+"demo.txt"),true);
OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
PrintWriter pw = new PrintWriter(osw,true);
pw.println("Hello");
}

多线程(t.start();后才执行run()方法):

进程与线程的区别:一个进程可以包含多个线程,进程有独立内存单元,线程共享内存单元
并发原理:获取时间片的线程被CPU运行,其他线程全部等待
使用Thread创建并启动线程(继承Thread并重写run()方法):

1
2
3
4
5
6
7
8
9
class MyThread extends Thread{
public void run(){
System.out.println("aaa");
}
}
public static void main(String[] args){
Thread t1 = new MyThread();
t1.start();
}

使用Runnable创建并启动线程(使用Runnable接口,定义其实现类):

1
2
3
4
5
6
7
8
9
10
class MyRunnable implements Runnable{
public void run(){
System.out.println("aa");
}
}
public static void main(String[] args){
Runnable r1 = new MyRunnable();
Thread t1 = new Thread(r1);
t1.start();
}

使用匿名内部类创建线程:

1
2
3
4
5
6
7
8
9
10
11
12
13
Thread t1 = new Thread(){
public void run(){
System.out.println("aa");
}
};
Thread t2 = new Thread(r);
Runnable r = new Runnable(){
public void run(){
System.out.println("aa");
}
};
t1.start();
t2.start();

Thread current = Thread.currentThread();获取运行当前代码片段的线程;Thread t = new Thread(“构造方法中加字符串自定义名字”);
long getId():返回该线程标识符;String getName():返回该线程名称;int getPriority():返回线程优先级;boolean isAlive():测试线程是否处于活动状态
设置线程优先级:void setPriority(int priority);
守护线程:void setDaemon(boolean);boolean isDaemon();当进程只有守护线程,所有守护线程终止,GC就是运行在一个守护线程上
sleep:static void sleep(long ms);使当前线程进入阻塞状态指定毫秒;
yield:static void yield():使当前线程主动让出时间片回到Runnable状态,等待分配时间片;void join():等待当前线程结束
synchronized(同步锁)关键字:将异步操作(并发)变为同步操作(你干完我再干)
多线程并发读写同一个临界变量(多线程共享实例变量/静态公共变量)时发生线程安全问题;
锁机制:
同步代码块:进入同步代码块或者方法会自动上锁,退出后自动解锁
synchronized(同步监视器–锁对象引用){ //代码块} 若方法所有代码需要同步也可以直接给方法上锁;好几个同步代码块用了this,第一个代码块进入了线程,其他代码块都不能用
多个需要同步的线程在访问该同步块时,看到的应该是同一个锁对象引用,否则达不到同步效果。通常我们会使用this来作为锁对象
静态方法锁的是类对象(this变为 类名.class),非静态方法锁的是当前方法所属对象;this指的是当前对象,
wait:等待机制;notify:锁机制;Thread.sleep(100);线程阻塞100毫秒
wait(锁里面的线程wait),notify(随机唤醒一个用到当前对象的线程)和notifyAll(唤醒所有当前对象上的线程)只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用;sleep是线程类(Thread)的方法,wait是Object类的方法;
BlockingQueue内部使用两条队列,允许两个线程同时向队列一个做存储,一个做取出操作,保证并发安全同时提高效率
线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,
其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步(下文统称为同步)。
线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。
线程池:ExecutorService threadPool = Executors.newFixedThreadPool(2); 线程池里能放2个线程
threadPool.execute(t1); 将线程放入线程池执行,如果要放进去5个,则先执行前2个,再执行2个,再执行1个
死锁:产生条件(同步嵌套):1.互斥条件2.请求和保持条件3.不剥夺条件4.环路等待条件

TCP通信:

Socket(套接字):用于描述IP地址和端口,每个服务软件都打开了一个Socket,并绑定到一个端口上。Socket和ServerSocket(用于服务器)类位于java.net包
获取本地地址和端口号:int getLocalPort();String getHostAddress();InetAddress getLocalAddress();
获取网络输入输出流:
Socket相当于一个邮箱,pw.println();把信放到邮箱;br.readLine();从邮箱拿信;
使用Socket完毕后使用void close()方法关闭(会同时关闭输入输出流)

服务器端(Server):创建监听服务–>等待连接—>进行通讯—>关闭连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
public class Server{
private ServerSocket server;
private List<PrintWriter> allOut;
public Server(){
try{
allOut = new ArrayList<PrintWriter>();
server = new ServerSocket(8088);
}catch(Exception e){
e.printStackTrace();
}
}
private synchronized void addOut(PrintWriter pw){
allOut.add(pw);
}
private synchronized void removeOut(PrintWriter pw){
allOut.remove(pw);
}
private synchronized void sendMessageToAllClient(String message){
for(PrintWriter pw:allOut){
pw.println(message);
}
}
public void start(){
try{
while(true){
System.out.println("等待客户端连接....");
Socket socket = server.accept();
ClientHandle clientHandle = new ClientHandle(socket);
Thread t = new Thread(clientHandle);
t.start();
}
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args){
Server server = new Server();
server.start();
}
private class ClientHandle implements Runnable{
private Socket socket;
private String host;
public ClientHandle(Socket socket){
this.socket=socket;
InetAddress address = socket.getInetAddress();
host = address.getHostAddress();
System.out.println(host+"上线了");
}
public void run(){
PrintWriter pw = null;
try{
OutputStream out = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
pw = new PrintWriter(osw,true);
addOut(pw);
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in,"utf-8");
BufferedReader br = new BufferedReader(isr);
String s = null;
while((s=br.readLine())!=null){
System.out.println(host+"说:"+s);
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
removeOut(pw);
socket.close();
System.out.println(host+"下线了!");
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}

客户端(Client):连接服务器–>进行通讯–>关闭连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class Client{
private Socket socket = new Socket();
public Client(){
try{
socket = new Socket("127.0.0.1",8088);
}catch(Exception e){
e.printStackTrace();
}
}
public void start(){
try{
ServerMessage message = new ServerMessage();
Thread t = new Thread(message);
t.start();
OutputStream out = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
PrintWriter pw = new PrintWriter(osw,true);
pw.println("服务端你好!");
Scanner sc = new Scanner(System.in);
while(true){
pw.println(sc.nextLine());
}
}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args){
Client client = new Client();
client.start();
}
private class ServerMessage implements Runnable{
public void run(){
try{
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in,"utf-8");
BufferedReader br = new BufferedReader(isr);
String s = null;
while((s=br.readLine())!=null){
System.out.println("服务器说"+s);
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}

枚举:enum;

枚举enum的方法,名字name(),排行ordinal() 0~n;将字符串变为对象valueOf(str);所有的方法要放在元素列表之后,元素列表后有东西,要加分号,构造方法要是私有的
元素后(比如SUN)加(参数)可以调用对应的构造方法;RED(30){}:相当于写了一个匿名内部类,调用了有参的构造方法;枚举只有一个成员时,就可以作为一种单例的实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public enum TrafficLamp{
RED(30){
public TrafficLamp nextLamp(){
return GREEN;
}
},GREEN(45){
public TrafficLamp nextLamp(){
return YELLOW;
}
},YELLOW(5){
public TrafficLamp nextLamp(){
return RED;
}
};
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time){
this.time=time;
}
}

数据库:

DDL(number(p,s),char/varchar2):用于建立、修改、删除数据库对象
DML:操作
DQL:查询
TCL:
DCL:
Oracle默认大写
DDL:
创建表:create table emp(id number(5),name varchar2(30),salary number(8,2))charset utf8;
修改表:alter table emp add(email varchar2(30));
alter table emp modify(email varchar2(20));
重命名表:rename emp to new_emp;
删除表:drop table emp;
删除序列:drop sequence seq;
删除列:alter table emp drop email;
DML:
插入新行:insert into emp (id,name,salary)values(1,‘张三’,3000);列名都不加默认所有
删除数据:delete from emp where id = 1; 不加条件删除所有
查找数据(select在Oracle中属于DML):select from emp; 选出所有的数据
select id,name ename from emp; 查看id,name列,并把输出的name列名改为ename
更新数据:update emp set name=’李斯’,salary=12000.0 where id=1;
rollback;回滚
commit;提交; 已commit的不能rollback;
desc emp; 查表结构
select str from dual; dual:伪表
select str from emp;
str:
concat(char1,char2); char1||char2||char3; 多个参数拼接
length(name); name的长度
upper(‘hello’); lower(‘hello’); initcap(‘hello’); 大小写,首字母大写
trim(‘e’ from ‘elle’); 去两边指定字符 ltrim去所有左边;rtrim去所有右边
lpad(sal,10,’$’);把sal左边补$到10位,如果sal中位数超过10位,将右边的截掉
substr(‘thinking’,1,2);从角标1开始截两位(最多取到结尾)如果该值是-4,则倒数第四位开始取
instr(‘demowho’,’who’,5,2);在demowho中找who第二次出现角标,从第5个角标开始找,无则返回0,区分大小写
round(456.789,2);四舍五入保留2位,第二个参数为-1时,保留到十位;trunc(用法与round一致)直接截取
mod(sal,1000); sal除以1000的值,当它的值为0时,返回的值为sal本身
ceil(456.789); 向上取整; floor(456.789); 向下取整
to_date(‘2008年08月08日’,’YYYY”年”MM”月”DD”日”‘); 将字符串转换为日期格式
to_char(sysdate,’YYYY-MM-DD HH:MM:SS’); 将日期转换成字符串,sysdate为当前时间
last_day(sysdate);返回这个月的最后一天
add_months(date,i); date加上i个月之后
months_between(date1,date2);两个月之间隔,有小数
next_day(date,char); 返回date日期数据的下一个周几,char=1为周日
nvl(a1,a2); 当a1为null时,返回a2的值否则返回a1;(将一个null值替换为非null值)
nvl2(a1,a2,a3); 当a1不为null时,函数返回a2,否则返回a3;
ename as “姓名”; 列加别名,as可省略
max(id):id最大值;min(id):id最小值;avg(sal):sal的平均值;sum(sal):sal的和值;
count(
):查看有几条记录
decode(1,2,3,4,5,6);1等于2返回3,否则等于4返回5….否则返回6;
case 1 when 2 then 3 when 4 then 5… else 6 end;
select name from emp where A str B;

1
>,<,>=,<=,!=,<>,=;!=等价于<>;and or ;and的优先级高于or;

name like ‘A%’; like(模糊查询)%表示0到多个字符; :标识单个字符
in(‘a’,’b’); in:等于列表中的其中之一即可 not in:不在列表范围内
between A and B; 在A~B之间(包含两端)

1
>any:大于最小 >all:大于最大 <any:小于最大 <all:小于最小

select distinct job from emp; distinct关键字,用于去除结果中的重复,必须紧跟在select后面
select name,id from emp order by id ASC,name DESC; order by:排序;ASC:正序;DESC:倒序;
select avg(sal) from emp group by deptno,class having max(sal)>4000; group by A,B:两个字段相同的看成一组;having必须跟在group by 后
from:执行顺序从后往前,从右到左
where:执行顺序从右到左;自上而下
group by:从左往右分组
where在group by前执行,having在group by 后执行
关联查询:关联查询必须要写链接条件,N张表进行链接查询,至少要有N-1个链接条件
select a.name,b.name from emp1 a,emp2 b where a.id = b.id;
外链接
自连接
子查询:通常是为了外层SQL提供数据支持的。嵌入在其他SQL语句中的查询语句
分页查询:pagesize:每页的条数;page:第几页;min:(page-1)pagesize+1;max:pagepagesize;select rownum from emp
序列:用来生成唯一数字值的数据库对象
create sequence emp start with 1 increment by 1;
emp.nextval:获取序列的下个值; emp.currval:获取序列的当前值
约束:not null(不为空);unique(唯一性约束);primary key(主键约束,唯一标识一行);
null与字符串拼接等于什么都没干;null与数字运算结果为null;

JDBC(Java Datebase Connectivity)

JDBC工作过程:
加载驱动,建立连接;创建语句对象;执行SQL语句;处理结果集;关闭连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1.Class.forName("oracle.jdbc.driver.OracleDriver");
2.Connection conn = null; conn = DriverManager.getConnection("jdbc:oracle:thin:@192.168.0.23:1521:tarena","hdsd0702","hdsd0702");
3.Statement state = conn.createStatement();
// String sql = "insert into userinfo (id,uasename,password,email,account)values (emp.nextval,?,?,?,?)"; PreparedStatement 是 Statement的子类
// PreparedStatement ps = conn.prepareStatement(sql);ps.setString(1,"test");ps.executeUpdate(); //(主要用于所有的SQL语句)
4.ResultSet rs = state.executeQuery(sql); //sql为String类型,是SQL语句
//获取结果集元素
while(rs.next()){
String name = rs.getString("name");
int id = rs.getInt("id");
}
ResultSetMetaData rsmd=rs.getMetadata(); //获取结果集元数据
int count = rsmd.getColumnCount();
for(int i=1;i<=count;i++){
colName=rsmd.getColumnName(i); //获取的字段
String str = rs.getString(colName); //由获取的字段得到结果集数据
}

Statement的方法:

1
2
3
ResultSet executeQuery(String sql); //该方法专门用来执行DQL语句,返回的ResultSet表示查询出来的结果集(主要用于select)
int executeUpdate(String sql); //该方法专门用来执行DML语句,返回的ResultSet表示查询出来的结果集(主要用于insert,delete,update)
boolean execute(String sql); //通常用来执行DDL,存在结果集,则返回true(主要用于create/drop/alter)

事务:操作在Connection中,默认为自动提交事务
conn.setAutoCommit(false);将自动提交关闭(事务)
conn.commit();提交事务; conn.rollback();回滚事务,已提交的不能rollback
state.addBatch(sql); 将SQL添加到批中,等待一起发送,提高网络效率,一般只执行DML操作,返回值为int影响了几条数据
配置文件:
InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream(“BeanUtils/config.properties”); 通过得到class文件的地址得到要找的资源
配置文件放在classpath的目录下,通过类加载器的方法加载配置文件,配置文件在该包下可以直接用config.properties,如果在该包的子包内resources/config.properties;

1
2
3
4
5
6
7
8
9
10
11
Properties prop = new Properties(); //和Map类类似,Properties多了一个从本地读取的功能;
prop.load(new FileInputStream("config.properties")); 得到prop的配置项
String str = prop.getProperty("url"); 根据key(name)获取value,赋给str
DBCP(DateBaseConnectionPool)连接池:
private static BasicDataSource cp = new BasicDataSource();
cp.setDriverClassName(driverName);
cp.setUrl(url);
cp.setUsername(username);
cp.setPassword(password);
cp.setMaxActive(maxactive); 最大连接数
cp.setMaxWait(maxwait); 最大等待时间

HTML

HTML:用HTML编写的文件,以.html或html为后缀
HTML5:是最宽松的版本,不用严格遵守XML语法,已经简化为<!DOCTYPE html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<head>
<title>标题</title>
<meta http-equiv="content-Type" content="text/html;charset=utf-8"> //改编码
<style type="text/css">
#body1 th{border-bottom:1px solid #848484;}
</style> //设置样式
//类型为javascript,用javascript语言写(js脚本)
<script type="text/javascript" language="javascript"></script>
<link></link>
</head>
<body>
<div> //块分区元素
//标题元素h1~h6;<p>段落元素
<h1>
<p><span>行内分区元素&lt;&gt;(<>)&nbsp;(/s)&copy;(@)</span></p><br/>
<img src="images/img.png"/> //加图片
//target="_blank"转到一个新开网页,不加就在原网页转
<a href="http://tmooc.cn" target="_blank">
<a href="#s1">第一章</a> //锚点,#代表返回到顶部
</h1>
<table><tr><td colspan="2" rowspan="2">表格单元</td></tr><tr><td></td></tr></table>
<thead></thead><tbody></tbody><tfoot></tfoot>
<ol><li></li></ol> //有序列表<ol>;无序列表<ul>;列表项<li>
</div>
</body>

CSS

CSS样式表:内联样式,内部样式,外部样式表;
特征:
继承性:大多数CSS的样式规则可以被继承
层叠性:可以定义多个样式表,不冲突时,多个样式表中的样式可层叠为一个
优先级:样式定义冲突时,按照不同样式规则的优先级来应用样式,相同的样式,如果重复定义,
以最后一次的定义为准(就近原则)
width和height指内容区域(element)的宽度和高度,增加padding和margin不会影响element尺寸,但会增加元素框总尺寸
元素选择器(div),id选择器(#id),类选择器(.class)
padding:内边距,border:边框,margin:外边距
CSS(Cascading Style Sheets)
外部样式:.css文件
{background-color:silver;background:red;
border-top/right/bottom/left:1px solid black(width style color);border-width/style/color:10px;
padding-top/right/bottom/left:10px; padding(margin):1px(top) 1px(right) 1px(bottom) 1px(left)(顺时针);
margin:0 auto(设置居中);background-image:url(“image/img1.jpg”);
background-repeat:repeat/repeat-x(水平重复)/repeat-y/(垂直重复)no-repeat(显示一次);
background-position:x% y%/x y/left/center/right/top/bottom;font-family:value1,value2(指定字体);font-size:1.2em;font-size:10pt;
font-size:35pt;font-weight:normal/bold;color:#ff0000(文本颜色);text-align:center/left/right(文本排列);
text-decoration:none/underline(文字修饰);line-height:25px(字体垂直居中用);text-indent:20px(首行文本缩进);
vertical-align:top/middle/bottom(表单垂直对其方式);border-collapse:separate/collapse(表单边框合并);
border-spacing:10px 20px(边框边距);float:none/left/right(div浮动);clear:none/left/right/both(元素哪边不允许出现浮动元素);
display:none/block/inline;cursor:default/pointer/crosshair/text/wait/help(光标属性);
(列表项标志)list-style-type:(无序列表)none(无标记)/disc(实心圆)/circle(空心圆)/square(实心方块)/
(有序列表)none(无标记)/decimal(数字)/lower-roman(小写罗马数字)/upper-roman(大写罗马数字);
list-style-image:url(img.jpg)(图像代表列表项标记);position:static/relative/absolute/fixed(定位);top/bottom/left/right:1px;
z-index:2(堆叠顺序,数值越大,在越上面);
}
伪类选择器:用于向某些选择器添加特殊的效果,使用冒号(:)作为结合符,结合符左边是其他选择器,右边是伪类
常用伪类:link,active,visited,hover,focus; #d1:hover{}
overflow:当内容溢出元素框时如何处理
{overflow:hidden(隐藏文本不显示);scroll(显示滚动条);auto(不超出不显示,超出显示滚动条)}

JS

JS(JavaScript):核心思想:一切都是对象
在浏览器运行的客户端语言,大小写敏感,一般使用分号结束,换行也行
所有的变量都用关键字var声明
注释: 单行:// 多行:/ /
boolean isNaN();不是一个数字
==只要值相等 ===不但值相等,类型也要相等 !==值不相等或者类型不相等
超链接在新窗口中打开,可重复:跳转超链接
超链接在新窗口中打开,不可重复:跳转超链接
数组排序:array.sort(compare);

1
2
3
1.function compare(a,b){return a-b;}
2.var compare=function(a,b){return a-b;};
3.var compare=new Function("a","b","return a-b;");

html调用js:
1.js插入html页面:

1
<input type="button" onclick="alert('HelloWorld');">

2.嵌入式:

1
2
3
4
5
<head>
<script type="text/javascript" language="javascript">
alert("HelloWorld");
</script>
</head>

3.文件调用方式:

1
2
3
<head>
<script tyle="text/javascript" language="javascript" src="myjs.js"></script>
</head>

html页面可以调用myjs里面的方法
数据类型的隐式转换:
数字+字符串:数字转换成字符串
数字+布尔值:true转换为1,false转换为0
字符串+布尔值:布尔值转换为字符串true或false
布尔值+布尔值:布尔值转换为数值1或0
数据类型转换函数:toString;parseInt(“6.12”);parseFloat;如果不能转换,则返回NaN(not a number)
null:可以通过给变量赋值null来清除变量的内容
undefined:声明了变量但从未赋值或变量属性不存在
==数值相等;===类型相等,数值相等

1
2
3
4
5
6
7
8
9
str.length;str.toLowerCase;str.toUpperCase;str.charAt(index);str.split(",");
str.charCodeAt(index); //返回指定位置字符的Unicode编码
str.indexOf(findstr,index); //index为开始查找的位置索引,可以省略
str.lastIndexOf(findstr,index);
str.substring(start,end); //截取子字符串,包头不包尾
str.replace(findstr,tostr); //替换子字符串
str.match(regexp); //返回匹配字符串的数组
str.search(regexp); //返回匹配字符串的首字符位置索引
var strArray = str.split(bystr,howmany); //返回分割后的字符串数组,howmany是返回数组最大长度可以省略

Array:

1
2
3
4
5
6
7
8
9
var week = new Array(7);
var test = new Array(100,"dhsj",true);
var test1 = [100,200,300];
week.length;
arr.join("-");
arr.toString();
arr.reverse();
arr.slice(start,[end]); //获取子数组
data.toFixed(num); //数值转换为字符串,并保留小数点后num

正则表达式:

1
2
3
4
var regExp = /pattern/flags;
//flags:g:设定当前匹配为全局模式;i:忽略匹配中的大小写检测;m:多行搜索模式
var regExp = new RegExp("pattern",["flags"]);
var isRight = reg.test(str); //检索str中指定的值返回true或false

Date对象:

1
2
3
4
5
6
7
8
9
10
11
var now = new Date();
var now2 = new Date("2013/3/20 11:20");
getDate();
getFullYear();
setDate();
setDay();
setFullYear();
toString();
toLocaleTimeString();
toLocaleDateString();
getDay();//星期中的某一天,返回值为0(日)-6(六)

函数:function func(){}
arguments:函数的参数数组 arguments.length:函数的参数个数 arguments[i]:第i个参数
Function对象:new Function(arg1,arg2,..,functionBody);
匿名函数:var func = function(arg1,arg2,…){func_body;};
eval(字符串计算):var str = “2+3”; eval(str);//5
Math.random(); //[0,1)
window.location.href=”https://www.baidu.com“; 当前窗口打开窗口
window.open(“https://www.baidu.com“); 新开窗口打开窗口; window.close();关闭当前窗口
2个return:onclick=”return method27();” var result = confirm(“您确定要删除吗?”);return result;
encodeURI:把字符串作为URI进行编码 var r1 = encodeURI(str);
decodeURI:对encodeURI()函数编码 var r2 = decodeURI(r1);
eval函数:用于计算某个字符串,以得到结果;或用于执行其中的JavaScript代码
函数触发动作:onmouseover,onmouseout,onclick,onfocus,onblur,onchange
定时器:
周期性:window.setInterval(func,1000); func:函数,执行语句;1000:时间周期,单位为毫秒;返回已经启动的定时器对象
window.clearInterval(tID):停止启动的定时器
一次性:window.setTimeout(func,1000);window.clearTimeout(tID);

DOM

DOM节点树:一切皆节点;var obj = document.getElementById(“d1”);
obj.nodeName;obj.nodeType;节点名称:nodeName;节点类型:nodeType;obj.innerText;obj.innerHTML;
obj.getAttribute(“name”);根据属性名称获取属性值obj.setAttribute(‘class’,’active’);obj.removeAttribute(“name”);
obj.src=”clock.jpg”;(将HTML标记,属性和CSS样式都对象化)obj.style.color=”red”;obj.style.fontSize = 20;
innerText:设置或获取位于对象起始和结束标签内的文本
innerHTML:设置或获取位于对象起始和结束标签内的HTML obj.innerHTML=”new text”;
页面加载时调用方法:
页面加载后启动:window.addEventListener(‘load’,timestart(函数名),false);
每个载入浏览器的HTML文档都会成为document对象,通过使用document对象,可以
从脚本中对HTML页面中的所有元素进行访问
标准DOM实现:var newNode = document.createElement(“img”);
HTML DOM实现(提供了封装好的对象):var newNode = new Image();Select,Option
var o = new Option(text,value);
Table对象:table.rows/cells.length;table.insertRow(index);返回Table对象table.deleteRow(index);
TableRow对象:table.rows[0].cells.length;table.rows[0].rowIndex/cells[0]/innerHTML/insertCell(index)/deleteCell(index);
TableCell对象:table.rows[0].cells[0].innerHTML/colSpan/rowSpan/cellIndex;
screen对象:
history对象:history.forward();前进按钮history.back();后退按钮history.go(-2);后退2次按钮
location对象:location.reload();location.href=”https://www.baidu.com";location.replace("https://www.baidu.com“);
DOM操作-查询:查询节点:
通过id查询:document.getElementById(“d1”);
通过层次(节点关系)查询:obj.firstChild;obj.lastChild;obj.previousSibling;obj.nextSibling;同级前后节点
obj.parentNode;obj.childNodes;查找多个节点,数组
通过标签名称查询:var pNodes = document(obj).getElementsByTagName(“p”);数组;pNodes[1].innerHTML;
通过name属性查询:
创建新节点:var newNode = document.createElement(“p”);返回新创建的节点
添加新节点:parentNode.appendChild(newNode); 新节点作为父节点的最后一个子节点存在
parentNode.insertBefore(newNode,refNode); 新节点位于refNode之前
删除节点:node.removeChild(childNode);删除某个节点,childNode必须是node的子节点
childNode.parentNode.removeChild(childNode); 删除自身
js代码中动态事件:btnObj.onclick = method;
事件:事件出发后将会产生一个event对象
鼠标事件:onclick/ondblclick/onmousedown/onmouseup/onmouseover/onmouseout/onmousemove(事件中实现显示坐标) = “method();”;
键盘事件:onkeydown/onkeyup
状态事件:onload/onunload/onchange/onfocus/onblur/onresize/onsubmit
取消事件:onXXX = “return false;”;
事件冒泡取消:event.cancelBubble = true;(js代码中不能直接使用event关键字,func(event))

Servlet

两层CS架构:客户端+DB 数据库作为Server移植性差,不适合大型引用
三层CS架构:客户端+应用服务器+DB 移植性好,适合大型引用,但是客户端需要单独安装
BS架构:Browser+WebServer+DB 数据库只负责数据管理,web服务器负责业务逻辑处理,浏览器负责提供操作页面
Servlet:server+let;服务器端的小程序,Sevlet是容器的一部分;sun公司制定的一种用来扩展Web服务器功能的组件规范
容器:符合一定规范,提供组件运行环境的一个程序
200表示请求成功202表示请求被接受但处理未完成400错误的请求
404错误:web服务器(容器)根据请求地址找不到对应资源
405错误:web服务器找不到servlet()方法处理请求(service方法名称写错等)
500错误:程序在运行过程出错
HTTP协议:w3c制定的一种应用层协议,一次请求一次连接
请求数据包:请求行,消息头,实体内容;响应数据包:状态行,消息头,实体内容
HttpServletRequest(客户端请求):读取和写入请求数据,取得和设置cookie,实现请求转发
HttpServletResponse:设置cookie,实现重定向
Servlet获取请求参数值(Name-Value(s))的方法:
String request.getParameter(String Name); String[] request.getParameterValues(String Name);(参数名相同多个参数值)
get请求:当需要向服务器请求指定的资源时使用的方法,不适用于提交请求(表单参数值在请求资源路径后面)
post请求:向服务器提交需要处理的数据,设置表单属性为post,可提交大量数据,不会将请求参数显示在浏览器地址栏(参数值在实体内容中);
解决post方式下乱码:(页面–>服务器)
1.表单所在页面按照指定字符集打开:
2.服务器端指定编码解码:request.setCharacterEncoding(“utf-8”);
解决get方式下乱码:(服务器–>页面)
1.表单所在页面按照指定字符集打开:
2.服务器端获取参数:String username = request.getParameter(Name);username = new String(username.getBytes(“iso-8859-1”),”utf-8”);iso-8859-1–>utf-8
解决输出内容(out.println();)乱码:response.setContentType(“text/html;charset=uft-8”);
编写Servlet的步骤:
1.创建web project
2.编写一个类,继承自HttpServlet
3.重写service()方法,编写输出内容
4.配置web.xml文件
5.部署该工程到tomcat中
6.启动tomcat
7.打开浏览器,输入 http://localhost:8080/应用名/地址
打开web项目下的WebRoot下的html文件:http://localhost:8080/应用名/demo.html 请求资源路径:应用名(appName)/demo.html

1
2
3
4
5
6
7
8
9
10
11
12
13
public class GetPost extends HttpServlet{
protected void service(HttpServletRequest req,HttpServletResponse resp)
throws ServletException,IOException{
//解决post乱码:
req.setCharacterEncoding("utf-8");
//解决输出内容乱码:
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
String text = req.getParameter("text");
out.println("<h1>"+text+","+select+"</h1>");
out.close();
}
}

或者:New–>Servlet–>doGet–>next–>URL:.do–>Finish–>doGet改为service,删除不需要部分
重定向:服务器向浏览器发送302状态码,Location消息头(重定向地址);response.sendRedirect(“list”);list为应用名之后的路径
重定向的地址是任意的,重定向后浏览器地址栏的地址会发生改变
转发:Servlet/JSP–>Servlet/JSP(一次请求一次响应,每次的request都不同,所以request.setAttribute只有一次效果)
转发的实现:1.绑定数据到reques对象;2.获得转发器;3.转发
1.实现绑定:request.setAttribute(String name,Object obj);name:绑定名;obj:绑定值;
2.获得转发器:RequestDispatchar rd = request.getRequestDispatchar(String path); 3.实现转发:rd.forward(request,response);
读取绑定:Object request.getAttribute(String name);
转发后地址栏地址不发生改变,转发过程在服务器内部,path必须是引用内部的某个地址,forward后的其他语句会执行
转发共享数据,重定向不共享数据
编程时的异常处理:利用转发跳转到指定页面;
通配符匹配:使用”
“匹配0个或多个字符(前面要加斜杠);前面不能使用斜杠,*.do匹配所有以.do结尾的请求
获取请求资源路径:String uri = request.getRequestURI();String action = uri.substring(uri.lastIndexOf(“/“)+1,uri.lastIndexOf(“.”));
action–>service/service.impl–>dao/dao.impl–>jdbc–>entity
Servlet线程安全:
ServletContext(Servlet上下文,一个Servlet程序只有一个):相当于Servlet中静态变量,因为Servlet创建后,服务器关闭才销毁
ServletContext sct =session.getServletContext();sct.setAttribute(“count”,count);

JSP(不需要经过部署):

JSP九大内置对象:request,response,session,application(Servlet上下文),out,pageContext,config,cookie,exception
Sun公司制定的一种服务器端动态页面技术的组件规范。JSP文件会被容器转换成一个Servlet类;避免Servlet大量输出out.print
JSP文件中可以包含以下内容:HTML(Css,Js),注释(,<%– –%>),
Java代码:JSP表达式:<%= %>;

平方根是<%=Math.sqrt(5) %>

;JSP小脚本(写java代码片段的):<% %>;JSP声明(成员属性或成员方法的声明):<%! %>;
指令:
page指令(用于导包,设置页面属性):<%@ page import=”java.util.*”(导包) pageEncoding=”utf-8”(容器读取文件时的解码) %>
<%@ page contentType=”text/html;charset=utf-8”%>客户端解码
include指令(将其他文件包含进来):<%@ include file=”url” %><%@ include file=”header.html” %>
隐含对象:request,response,out,session,application,pageContext,page,config,exception
创建静态JSP模板:JSP页面–>Preferences–>JSP Template–>New–>Name(随意)Context(jsp_new)Pattern(模板内容)
绝对路径以/开头,从应用名之后开始,相对路径从当前文件开始。String request.getContextPath();获取引用的部署名称

Cookie(客户端状态管理技术)

一次请求一次响应,判断是否为同一用户操作
创建Cookie:Cookie c = new Cookie(String name,String value);response.addCookie(c);
查询Cookie:Cookie[] request.getCookies(); String Cookie.getName()/getValue();
修改Cookie:c.setValue(String newValue);–>response.addCookie(c);同名Cookie覆盖
Cookie生存时间:void Cookie.setMaxAge(int seconds);seconds>0:保存指定时间;seconds=0:删除Cookie;seconds<0:Cookie保存到内存
Cookie编码:Cookie只能保存合法的ASCII字符,Cookie c = new Cookie(“city”,URLEncoder.encode(“北京”,”utf-8”));
Cookie解码:String value = c.getValue();value=URLDecoder.decode(value,”utf-8”);
Cookie路径:/appName/file/addCookie.jsp添加了一个Cookie,该Cookie的路径为/appName/file;c.setPath(“/appName”);response.addCookie(c);
客户端每次访问服务器(Servlet/JSP)都会把对应(根据路径)Cookie发送到服务器
发送Cookie的条件:要访问的地址必须是Cookie的路径或者子路径时,浏览器才会发送Cookie
Cookie可以被用户禁止,将状态保存在浏览器端不安全,敏感数据需要先加密,只能保存4kb左右,个数有限,只能保存字符串

Session(服务器状态管理技术):

服务器为每个浏览器创建Session对象,将SessionId(使用Cookie的方式)发送给浏览器,Session能够保存多种数据类型,安全,但占服务器内存
浏览器再次访问时会将SessionId发给服务器,服务器找到相应Session
获得Session:HttpSession s = request.getSession(boolean flag);HttpSession s = request.getSession();flag不写默认true;
flag为true时,一定得到一个Session对象(请求中有SessionId–>有对应Session–>get;else new)
flag为false:请求中有SessionId–>有对应Session–>get;else return null;
使用Session绑定对象:void s.setAttribute(String name,Object obj);
获取绑定对象:Object s.getAttribute(String name);
移除绑定对象:void s.removeAttribute(String name);
删除Session对象:s.invalidate();
Session验证:常用于登录验证(获取绑定对象,如果没有跳转回登录页面)
Session超时:Web服务器会将空闲时间过长的Session对象删除掉,缺省的超时时间一般为30分钟
修改Session的缺省时间限制:void s.setMaxInactiveInterval(int seconds);
或者修改tomcat中的conf/web.xml文件的设置

1
2
3
<session-config>
<session-timeout>30</session-timeout>
<session-config>

如果Cookie被浏览器禁用,就不能使用Session了(可以使用如URL重写的方式来发送SessionId)
URL重写:URL=response.encodeURL(String url)(链接地址和表单的提交);URL=response.encodeRedirectURL(String url)(重定向);
验证码:
JSP Session验证:

1
2
3
4
5
6
7
<%
Object uname = session.getAttribute("uname");
if(uname==null){
response.sendRedirect("login.jsp");
return;
}
%>

过滤器监听器

过滤器:小型,可插入的Web组件,用来拦截Servlet容器的请求和响应过程
编写过滤器:
1.编写一个Java类,实现Filter接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class CommentFilter implements Filter{
private String illegalWord;
//容器删除过滤器之前调用,只执行一次
public void destory(){
}
public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws IOException,ServletException{
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
PrintWrite out = resp.getWriter();
String comment = req.getParameter("comment");
if(comment.indexOf("damn")!=-1){
out.print("<h3>评论内容关闭</h3>");
}else{
//交给其他过滤器或者Servlet
chain.doFilter(req,resp);
}
}
//容器启动后,创建过滤器实例,然后调用init方法,只会调用一次,将FilterConfig对象作为参数传入
public void init(FilterConfig filterconfig)throws ServletException{
illegalWord = filterConfig.getInitParameter("illegalWord");
}
}

2.在doFilter方法中实现拦截处理逻辑
3.将过滤器添加到Web程序中(过滤器的优先级按照的先后顺序)

1
2
3
4
5
6
7
8
9
10
11
<filter>
<filter-name>filter1</filter-name>
<filter-class>web.xxxServlet<filter-class>
<filter>
<filter-mapping>
<filter-name>filter1<filter-name>
<url-pattern>/xxx</url-pattern> xxx与哪个Servlet路径一致,代表指针对这个路径的请求都要进行过滤
<!-- 初始化参数-->
<param-name>innegalStr</param-name>
<param-value>xxx</param-value>
</filter-mapping>

4.把过滤器和Web应用一起打包部署
Web客户端–>code1–>chain.doFilter()–>Servlet的service()–>code2–>Web客户端
读取初始化参数:String config.getInitParamter(“illegalStr”)
过滤器优点:可插拔性(增加或减少某个功能不会影响程序正常执行),将多个相同处理逻辑的模块写在过滤器里,方便代码维护
编写监听器:(ServletRequest,HttpSession,ServletContext)
1.编写Java类(根据监听事件选择相应监听器接口)

1
2
3
4
5
6
7
8
public class CouListener implements HttpSessionListener{
public void sessionCreate(HttpSessionEvent arg0){
HttpSession session = arg0.getSession();
ServletContext ctx = session.getServletContext();
}
}

2.注册监听器:

1
2
3
<listener>
<listener-class>web.CouListener</listener-class>
</listener>

EL JSTL

EL表达式:简单的计算规则,用于给JSP标签属性赋值,也可以直接用来输出(JSP中嵌套Java代码不利于维护)
作用:
访问Bean属性(pageContext,request,session,application):${对象名.属性名} ${对象名[“属性名”]} ${user.array[1]}:user中数组array第2个元素
request.setAttribute(“userAge”,”age”);—> ${user[userAge]} 相当于 ${user[“age”]}
取值时绑定名写错(找不到返回null)或没有赋值(找不到返回null),实际上输出空白(属性名不能写错,否则报错)
${user.name} 相当于 <% User user = (User)request.getAttribute(“user”); out.print(user.getName()); %>
指定查找范围:如在session中查找:${sessionScope.user.name} 要查找的Bean属性加Scope
输出简单运算结果:”+”,”-“,”*”,”/“,”%”;”+”号只能求和不能连接字符串;”&&”,”||”,”!”,”>”,”>=”,”<”,”<=”,”==”,”!=”,
empty:${empty null}返回true;空字符串,空集合,值为null,找不到对应的值;返回结果true;
获取请求参数:${param.username}等价于request.getParameter(“username”);${paramValues.city}等价于request.getParameterValues(“city”);
JSTL(JSP Standard Tag Library):JSP标准标签库
使用JSTL:
1.将对应jar包放到WEB-INF/lib目录下
2.使用taglib指令导入要使用的JSP标签<% @taglib uri=”http://java.sun.com/jsp/jstl/core“ prefix=”c” %> uri:JSP标签的命名空间 prefix:命名空间的前缀
if标签: //rs为记录test结果的临时变量
当test属性值为true时,执行标签体的内容.test属性可以使用EL表达式
var属性:指定一个绑定名称;scope属性:指定绑定的范围(page,request,session,application);var和scope要配合使用
choose标签:

1
2
3
4
5
<c:choose>
<c:when test=""></c:when>
......
<c:otherwise></c:otherwise>
</c:choose>

forEach标签

1
2
3
4
5
<c:forEach var="emp" items="${emps}" varStatus="s">
${emp.name}
${emp.gender}
${s.count/index}
</c:forEach>

items属性:指定要便利的集合,一般使用EL表达式来复制
var属性:指定一个绑定的名称,容器每次从集合中取一个对象,然后绑定到pageContext对象上
varStatus属性:指定一个绑定名称,绑定值是一个由容器创建的对象,该对象封装了当前迭代的状态
index返回正在被迭代的对象下标(从0开始),coun返回第几次迭代(从1开始)
开发自定义标签:参考jstl-1.2.jar的META-INF的c.tld
1.编写Java类,继承SimpleTagSupport类
2.在doTag方法中添加处理逻辑
3.配置标签说明文件

Ajax

Ajax(局部刷新):Asynchronous JavaScript and XML异步的JavaScript和XML
Ajax原理:
使用Ajax发送异步请求
1.获得Ajax对象(可单独在js文件中写,或者放在html的<script>中):

1
2
3
4
5
6
7
8
9
10
var xhr = getXhr();
function getXhr(){
var xhr = null;
if(window.XMLHttpRequest){
xhr=new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHttp');//针对IE
}
return xhr;
}

2.编写回调事件处理函数:

1
2
3
4
5
6
xhr.onreadystatechange=function(){
if(xhr.readyState==4&&xhr.status==200){
var txt =xhr.responseText;//out.print();
alert(txt);
}
};

3.创建请求-get:xhr.open(‘get’,’xx.do’,true);
创建请求-post:xhr.open(‘post’,’xx.do’,true);
xhr.setRequestHeader(‘content-type’,’application/x-www-form-urlencoded’);(添加消息头)

true:发送异步请求(发送请求时可做其他操作)false:发送同步请求(发送请求时不可做其他操作)
4.发送请求-get:xhr.send(null); get若要提交数据,在xhr.open的url后面追加(xx.do?name=value&name=value)
发送请求-get:xhr.send(name=value&name=value…);
异步对象的属性和方法:open(method,url)创建请求,method请求类型get post
send():发送请求;readyState:请求的状态;status:服务器返回的响应;readyState==4表示Ajax获得服务器返回的所有数据
解决get请求乱码(2种方式):IE的Ajax对象使用GBK对参数编码,其他浏览器使用UTF-8编码,服务器默认ios-8859-1解码
1.指定字符集解码;tomcat修改conf/server.mxl:
2.使用encodeURI对请求地址进行编码

JSON

JSON(导6个包,html):轻量级的数据交换格式,相对于XML,JSON解析速度更快,文档更小
结构:
1.名值对:{“name”:”Sally”,”city”:”北京”,”age”:25}
属性值可以是string,number,boolean(true,false),null,object.属性名必须使用双引号,属性值如果是字符串要用双引号
2.值的有序列表(数组,集合):[value,value,value…] (可以互相套用)
使用JSON实现数据交换:java对象–>JSON字符串(web服务器)–>JSON字符串(客户端)–>JavaScript对象
JSON对象–>JavaScript对象:
1.var str = ‘{“name”:”张三”,”age”,18}’; var obj = eval(“(“+str+”)”);
2.使用原生对象JSON提供的parse()方法:var obj = JSON.parse(str);
3.var obj = str.parseJSON();(需要用到JSON.js文件)
JS中JSON对象(obj)–>String字符串:var str = obj.toJSONString();(需json.js); var str = JSON.stringify(obj);

java对象–>JSON对象(通过拼接JSON字符串重构对象属性)
JSONObject obj = JSONObject.fromObject(emp); String jsonStr = obj.toString(); java对象–>JSON对象
JSONArray jsonArr = JSONObject.formObject(arr); String jsonStr = jsonArr.toString(); java数组(集合)–>JSON对象
JSON对象–>Java对象
Emp emp = (Emp)JSONObject.toBean(obj,Emp.class); List list = (List)JSONArray.toCollection(jsonArr,Emp.class);
缓存问题:IE浏览器在发送GET请求时,如果访问过该地址不再发送请求(Chrome,Firefox继续发请求);解决(请求后加随机数):xxx.do?Math.random();

jQuery

jQuery(write less,do more(html,要引入jQuery文件)):优秀的JS框架,轻量级的JS库,使用户的HTML页面保持代码和内容分离
jQuery编程步骤:1.引入jQuery的js文件2.使用选择器定位要操作的节点3.调用jQuery的方法进行操作
jQuery对象:链式编程(每次返回的都是jQuery对象);$(“div”);$(“#d1”);都是jQuery对象
DOM对象–>jQuery对象:$(DOM对象);
jQuery对象–>DOM对象:$obj.get(0)或者$obj.get()[0];$obj是jQuery对象
jQuery选择器:
基本选择器:#id(最快),.class(.s1),element(元素选择器div等)
层次选择器:
过滤选择器:first(第一个元素);last(最后一个元素);not(selector):把selector排除在外;even(挑选偶数行);even(挑选奇数行);
eq(index):下标等于index的元素;gt(index):下标大于index的元素;lt(index):下标小于index的元素;
例:$(“table tr:first”);$(“table tr:eq(1) td:eq(2)”);$(“table tr:not(#tr1)”);
内容过滤选择器:contains(text):匹配包含给定文本的元素;empty:匹配所有不包含子元素或者文本的空元素;
has(selector):匹配含有选择器所匹配的元素;parent:匹配含有子元素或者文本的元素
可见性过滤选择器:hidden:匹配所有不可见元素,或type为hidden的元素;visible:匹配所有的可见元素;还有属性,子元素过滤器
表单过滤选择器:enabled,disabled,checked,selected
表单选择器:input,text,password,radio,checkbox,submit,image,reset,button,file,hidden
利用选择器定位节点:$(“div”);$(“#di”);相当于<div id="d1"></div>
调用方法操作节点:$(“#d1”).css(“font-size”,”30px”); //修改id=d1的样式
合并选择器(selector1,selector2…):例如$(“#d1,.s1,p”);
从节点select1中找子节点(h或者子子等节点)select2(select1空格select2):例如$(“#d1 div”);
只查找直接子节点,不查找间接子节点(select1>select2):$(“#d1>div”);
select1+select(+表示下一个兄弟节点)$(“#d1+div”);d1的类型为div,查找它同级的之后的一个div
select1~select2(~表示下面所有兄弟):$(‘#d2~div’);d1的类型为div,查找它同级的之后的所有div
jQuery操作DOM:
html():读取或修改节点的HTML内容;$(“#d1”).html() 相当于 document.getElementById(“d1”).innerHTML;
text():读取或修改节点的文本内容:$(“#d1”).text();
val():读取或修改节点的value属性值:$(“#d1”).val(“空白格”); 相当于 document.getElementById(“d1”).value=”空白格”;
attr():读取或者修改节点的属性:$(“#d1”).attr(“style”,”color:red;”);
创建DOM节点:$(‘body’).append(‘<div>...</div>‘); 放在body最后一个节;$(“#d1”).before(“<p>hello</p>“);var $obj=$(“#d2”).clone(true);
append():作为最后一个子节点添加进来;prepend():作为第一个子节点添加进来;after():作为下一个兄弟节点添加进来;
before():作为上一个兄弟节点添加进来;remove():移除;remove(selector):按选择器定位后删除;empty():清空节点;
clone():复制节点;clone(true):将处理代码一块复制
样式操作:
attr(“class”,””):获取和设置;addClass(“”):追加样式;removeClass(“”):移除样式;removeClass():移除所有样式;
toggleClass(“”):切换样式;hasClass(“”):是否有某个样式;css(“”):读取css的值;css(“”,””):设置多个样式;
遍历节点:
children():只考虑直接子节点;next():下一个兄弟节点;prev():上一个兄弟节点;siblings:其他兄弟;
find(selector):查找满足选择器的所有后代;parent():父节点;
分离js代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
window.onload = function(){
var obj = document.getElementById("d1");
obj.onclick=function(){
this.innerHTML="this很重要";
}
}
$(function(){
$("#d1").click(
function(){
$(this).html('helle Ajax');
}
);
}
);

两种方式完成的操作是等价的,都是在页面加载后,为div添加点击事件.
使用jQuery实现事件绑定:$obj.bind(‘click’,fn)相当于$obj.click(fn);
取消事件冒泡:e.stopPropagation()
jQuery动画:效果很好;显示(显示之前要display:none):$(“#d1”).show(3000,f1),隐藏:$(“#d2”).hide(3000,function(){…}),f1为回调函数,可不写
上下滑动:slideDown()/slideUp();淡入:fadeIn(),淡出fadeOut,自定义动画;他们的用法都同show()/hide()
load():将服务器返回的数据字节添加到符合要求的节点之上;$obj.load(请求地址,请求参数);
jQuery对Ajax的支持:使用$.load(),$.get(),$.post(),$.ajax()方法发送异步请求(3种方法)

1
2
3
4
5
1.$(function(){
$("#d1").click(function(){
$(this).load('salary.do','eId='+eId);
});
});

1
2
3
2.function quoto(){
$.post('quoto.do','eId='+eId,function(data){...},'json');
}

$.get(请求地址,请求参数,回调函数,服务器返回的数据类型)
data是服务器返回的数据,json是返回数据格式的说明,如果data是json字符串,会自动转换为相应的javascript对象
修改post请求为get请求时,相关参数不变,要在请求地址后面追加一个随机数欺骗IE浏览器

1
2
3
4
5
3.function quoto(){
$.ajax(
{ url:"quoto.do",type:"post",dataType:"json",success:function(data){...},error:function(){...} }
);
}

JQuery发送ajax请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$.ajax({
cache: false, //cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取
async: false, //async : false,表示同步,同步会等待执行完成,直到success 执行完成!如果是true,倒是有可能先执行alert("谁先");
url: "/mall/UserServlet", //要发送到servlet的url
data: {method: "ajaxValidateVerifyCode", verifyCode: value}, //要发送到servlet的数据(ajax格式),method是方法名,后面的是属性名,属性值
type: "POST", //method为post
dataType: "json", //数据类型为json
success: function(flag) { //如果发送成功后,flag为servlet的值,resp.getWriter().print(flag);
if(!flag) {
$("#verifyCodeError").css("display", "");
$("#verifyCodeError").text("错误的验证码!");
bool = false;
}
}
});

反射

反射:反射就是把java类中的各种成分映射成相应的java类
Class(反射的基石)–>Class类代表java类
Class cla1 = Date.class(字节码得到对象)
得到字节码对应对象的3种方法:1.类名.class;2.对象.getClass();例如:new Date().getClass();3.Class.forName(“类名”);例如Class.forName(“java.lang.String”);
3种方法得到的对象是同一个对象,无论用来得到该对象的对象(对象.getClass();)是否是同一个。用 == 比较两个字节码是否是同一个因为是字节码,一种只有一份
Class.forName(“java.lang.String”);//得到类的字节码;字节码:把字节码加载到内存中,再用字节码复制出一个个对象
9个预定义的Class实例对象,8个基本类型(cls.isPrimitive())+void
int.class==Integer.TYPE;int类型得到的对象和Integer类型得到的基本类型对象是同一个(8种)
数组类型(每种数组都有各自Class实例对象)的Class实例对象:cls.isArray();
只要在源程序中出现的类型都有各自的Class实例对象,例如:int[],void…
Field:类的成员变量
Field fieldY = pt1.getClass().getField(“y”); //由pt1.getClass()得到这个类,再getField(“y”)得到该类的成员变量(只能得到public不能得到private);
Field fieldY = pt1.getClass().getDeclareField(“y”);//得到私有的成员变量需要用getDeclareField(“y”);
上面虽然得到了私有的成员变量,但是不能用,还要调用一个方法:fieldY.setAccessible(true);暴力反射
fieldY.get(pt1);得到pt1对象的该成员方法的值,Object类型;fieldY.set(obj,newValue);设置该对象该变量的值
field.getType();得到该变量的字节码;field.set(pt1,value);设置pt1对象的field变量的值;
Method:方法;得到一个Method对象就得到了一个Method方法
Method method = String.class().getMethod(name,parameterTypes); //先得到字节码对象,再根据方法名和参数得到方法
method.invoke(str,1);该方法被str调用,参数是1;如果调用静态方法:method.invoke(null,1);
这里如果参数是一个数组,不能直接写成数组,jdk1.4会自动把数组拆成几个参数,要写成:new Object[] {new int[]{1,2,3}}或者(Object)new int[]{1,2,3};int[]就没关系,因为int[]不是Object[]类型
Contructor:构造器
得到所有构造方法:Constructor constructors[] = Class.forName(“java.lang.String”).getConstructors();
得到单个构造方法:Constructor constructor = Class.forName(“java.lang.String”).getConstructors(StringBuffer.class,…);根据参数类型来确定是哪个构造方法
创建实例对象(反射方式):String obj = (String)constructor.newInstance(new StringBuffer(“abc”));//得到的是obj对象,需要强转,获得构造器,创建对象
String obj = (String)Class.forName(“java.lang.String”).newInstance();//得到默认的构造方法并创建实例对象
Package:包
数组的反射:clazz.isArray();Array.getLength(obj);Array.get(obj.i);//java.lang.reflect.Array;
反射的作用:实现框架功能,通过配置文件获取类完整名,通过反射得到该类,实现功能
Struts:
你去调用别人的类,框架就是别人的类来调用你的类,框架就像房子一样,
IntroSpector(内省)–>JavaBean–>特殊的Java类,主要用于传递数据信息,这种类中的方法主要用来访问私有的字段,且方法名符合某种命名规则
类要在两个模块间传递多个信息,可以将这些信息封装到一个JavaBean中,信息用私有字段储存,get,set方法来确定
一个类有get和set方法就可以当做JavaBean来操作
JavaBean的属性名:Age–>age:如果第一个字母是大写的,则把第一个字母变成小写的;
例子:gettime–>time;setTime–>time;getCPU–>CPU;
JDK中提供了对JavaBean进行操作的一些API,这套API就成为内省,用内省这套api操作JavaBean比用普通类的方法更方便
在程序中把一个类当做JavaBean来看,就是调用IntroSpector.getBeanInfo方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息
BeanUtils工具包
BeanUtils.getProperty(pt1,”x”);得到pt1对象的x属性;pt1.getX();
BeanUtils.setProperty(pt1,”brithday.time”,”1111”);设置pt1对象的brithday的time属性的值为1111;pt1.getBrithday().setTime(“111”);

Spring

Spring容器实现了IOC和AOP机制,这些机制可以简化Bean对象的创建和Bean对象之间的解耦;
Bean的实例化:
1.用构造器来实例化:
2.使用静态工厂方法实例化:
3.使用实例工厂方法实例化:
IOC(Inversion of Control控制反转)概念:程序中对象的获取方式发生反转,由最初的new方式创建,转变为由第三方框架创建、注入。
IOC控制由DI(依赖注入)方式实现。DI是实现IOC的主要技术途径。
DI主要有两种注入方式:Setter注入和构造器注入

1
2
3
4
5
6
7
8
9
10
11
12
<bean id="dataSource" class="dao.JDBCDataSource">
<!-- 注入属性 -->
<property name="driver" value="oracle.jdbc.OracleDriver"/>
......
<!-- 注入Bean对象 -->
<property name="userDAO"><bean class="com.dao.OracleYserDao"></bean></property>
<property name="pwd" value="123456"/>
</bean>
<!-- 构造器注入 -->
<bean id="userDAO" class="dao.OracleDriver">
<constructor-argindex="0" ref="dataSource"/>
</bean>

自动装配:byName,byType

1
<bean id="userService" class="service.userService" autowire="byType"/>

上述配置中,如果userService中有其他变量在bean容器中,可以按照类型注入;
List注入,Set注入,Map注入,Properties注入

1
2
3
4
<property name="friends"><list><value>1</value><value>2</value></list></property>
<property name="friends"><set><value>1</value><value>2</value></set></property>
<property name="friends"><map><entry key="1" value="1"></entry><entry key="2" value="2"></entry></map></property>
<property name="friends"><props><prop key="1">1</prop><prop key="2">2</prop></props></property>

组件扫描:发现组件类定义前有特定的注解标记时,就将该组件纳入到Spring容器。等价于原有XML配置中的<bean>定义功能

1
<context:component-scan base-package="org.example"/>

自动扫描的注解标记:
@Component 通用注解
@Name 通用注解
@Repository 持久化层组件注解
@Service 业务层组件注解
@Controller 控制层组件注解
@Scope(“prototype”) 默认的作用域是”singleton”
指定依赖注入关系:
@Resource 默认首先按名称匹配注入,然后类型匹配注入 @Resource(name=”empDao1”)
@Autowired 默认按类型匹配注入,多匹配Bean时,@Autowired @Qualifier(“mysqlUserDao”)
注入Spring表达式: @Value(“#{jdbcProps.url}”)
web.xml配置:

1
2
3
4
5
6
7
8
<!-- 配置Spring的监听器,用于初始化ApplicationContext对象 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>

AOP:面向切面编程,主要处理共通逻辑(日志记录,性能统计,安全控制,事务处理,异常处理等),将共通逻辑从普通代码逻辑中分离出来;
对业务逻辑各个部分进行隔离,降低耦合度;
AOP针对业务处理过程中的切面进行提取;面对的是处理过程中的某个步骤或阶段
AOP实现原理:主要基于动态代理技术,当Spring采用AOP配置后,Spring容器返回的目标对象,实质上是Spring利用动态代理技术生成的一个代理类型。
代理类重写了原目标组件方法的功能,在代理类中调用方面对象功能和目标对象功能。
两种动态代理实现:目标有接口,没有接口实现
方面:封装共通处理的组件,该组件被作用到其他目标组件方法上。
目标:被一个或多个方面所作用的对象
切入点:用于指定哪些组件和方法使用方面功能,在Spring中利用一个表达式指定切入目标。
Spring框架提供的5种通知:

1
2
3
4
5
6
7
8
9
10
11
try{
//前置通知--执行方面
//环绕通知前置部分
//执行目标组件方法
//环绕通知后置部分
//后置通知--执行方面
}catch(){
//异常通知--执行方面
}finally{
//最终通知--执行方面
}

开发步骤:
创建方面组件:创建一个类,充当方面组件,实现通用业务逻辑
声明方面组件:在applicationContext.xml中开启AOP注解扫描:

1
<aop:aspectj-autoproxy proxy-target-class="true"/>

使用 @Component注解标识需要声明为方面组件的类,将其纳入Spring管理
使用 @Aspect注解标识需要声明为方面组件的类
使用方面组件:在方面组件的方法上,使用注解将方面组件作用到目标组件的方法上,并设置通知类型以确认方面组件调用的时机。
前置通知: @Before(“within(“com.yh.controller..*”)”)
后置通知: @AfterReturning(“within(“controller…”)”)
最终通知: @After(“within(“controller…”)”)
环绕通知” @Around(“within(“controller…”)”)
异常通知: @AfterThrowing(pointcut=”within(“controller…”)”,throwing=”e”)

Transaction(事务):
事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。
事务的结束有两种,当事务中的所以步骤全部成功执行时,事务提交。如果其中一个步骤失败,将发生回滚操作,撤消之前到事务开始时的所有操作。
二.事务的 四个特征(ACID(Atomicity、Consistency、Isolation、Durability ))
事务具有四个特征:原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )和持续性( Durability )。这四个特性简称为 ACID 特性。
1 、原子性
事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
2 、一致性
事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。
3 、隔离性
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4 、持续性
也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
数据库系统必须维护事务的以上特性 ( ACID)。
在相同线程中进行相互嵌套调用的事务方法工作于相同的事务中。如果这些相互嵌套调用的方法工作在不同的线程中,不同线程下的事务方法工作在独立的事务中。

Spring MVC:控制层(Controller)

M-Model模型:负责业务逻辑,包含两层:业务数据和业务处理逻辑,entity,DAO,Service
V-View视图:显示界面和用户交互,JSP
C-Controller控制器:M和V之间的桥梁,用于控制流程
DispatcherServlet控制器配置(前端控制器):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

SpringMVC执行流程:
浏览器向Tomcat服务器发起Web请求–>将Web请求交给DispatcherServlet处理–>DispatcherServlet根据HandlerMapping中的urlMappings(RequestMapping)将Web请求
转到相应Controller–>处理请求,返回ModelAndView–>Spring核心控制器收到ModelAndView中的视图,利用ViewResolver中的前后缀到相应jsp文件。

1
2
3
4
5
6
7
<!-- 视图处理器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"
value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

当使用注解的方式时:开启 @RequestMapping注解映射,需要在Spring的XML配置文件进行配置:
Spring MVC Web请求提交数据到控制器有下面几种方法(接受请求参数值):
1.使用HttpServletRequest获取:String name = req.getParameter(“name”);
Spring会自动将表单参数注入到方法参数(名称一致)使用 @RequestParam注解,映射不一致的名称;优点:参数类型自动转换
2.使用 @RequestParam注解: @RequestParam(“pwd”)String password;
3.使用自动机制封装成Bean对象:定义User实体,属性名与

表单组件的name相同;User要放在方法参数中
当Controller组件处理后,需要向JSP传值时,用下面方法(向页面传值):
1.直接使用HttpServletRequest和Session
2.使用ModelAndView对象: return new ModelAndView(“success”,data);
1
2
3
4
5
6
7
8
//Model数据会利用HttpServletRequest的Attribute传值到success.jsp中
@RequestMapping("/login.do")
public ModelAndView login(String name,String pass){
User user = userService.login(name,pwd);
Map<String,Object> data = new HashMap<String,Object>();
data.put("user",user);
return new ModelAndView("success",data);
}

3.使用ModelMap参数对象:在Controller处理方法中追加一个ModelMap类型参数model,model.addAttribute(“user”,user);

1
2
3
4
5
6
7
8
//ModelMap数据会利用HttpServletRequest的Attribute传值到success.jsp中
@RequestMapping("/login.do")
public String login(String name,String pass ,ModelMap model){
User user = userService.login(name,pwd);
model.addAttribute("user",user);
model.put("name",name);
return "success";
}

4.使用 @ModelAttribute注解:在Controller方法的参数部分或Bean属性方法上使用 @ModelAttribute(“user”)User user

1
2
3
4
@ModelAttribute("name")
public String getName(){
return name;
}

如果Collection中的方法return的不是url而是一个user对象,那么springmvc默认访问的URL是前缀+ @RequestMapping +后缀;user对象作为值传入页面
Session存储:req.getSession().setAttribute(“loginUser”,user);

Spring对Ajax的支持
Spring MVC提供了JSON响应的支持,很方便地将数据转换成JSON格式字符串给客户端JavaScript返回。在SpringMVC中与JSON响应相关的注解为 @ResponseBody
jar包支持:jackson-annotations-2.4.1.jar、jackson-core-2.4.1.jar、jackson-databind-2.4.1.jar
配置文件中定义开启对 @ResponseBody应用的支持;该注解可将基本类型数据,Map,集合或数组,实体对象,实体对象集合做成json
案例:

1
2
3
4
5
6
@ResponseMapping("/test1")
@ResponseBody
public boolean f1(){
//业务代码处理
return true;
}

Struts2:控制层(Controller)

Struts2是轻量级的MVC框架,主要解决了请求分发的问题,重心在控制层(action)和表现层(OGNL)
Struts2是在Struts1(与JSP/Servlet耦合非常紧密)和WebWork的技术基础上进行合并的全新MVC框架,以Xwork为核心,可以理解为WebWork的升级版;
Struts2核心包:commons-fileupload,freemarker,ognl,struts2-core,xwork-core
配置前端控制器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 配置Struts2的主过滤器 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<package name="default" namespace="/" extends="struts-default">
<!-- 全局的Result配置 -->
<global-results>
<result name="loginUI">/WEB-INF/jsp/userAction/loginUI.jsp</result>
<result name="noPrivilegeError">/noPrivilegeError.jsp</result>
</global-results>
<!-- 首页 {1}指的是第一个*指代内容-->
<action name="home_*" class="homeAction" method="{1}">
<result name="{1}">/WEB-INF/jsp/homeAction/{1}.jsp</result>
<result name="{1}" type="redirectAction">home_{1}?id=${topicId}</result>
</action>
</package>

业务控制器Action中返回的字符串要与struts.xml–>action–>result的name属性匹配;
页面向Action传参:
基本属性注入:在Action中定义基本属性,并提供set方法(页面向Action传参)和get方法(Action向页面传参)
域模型注入:在Action中定义实体对象属性,并提供set(页面向Action传参)、get方法(Action向页面传参)
域模型注入时,表单中文本框制定表达式”对象名.属性名”
OGNL:一门功能强大的表达式语言,类似于EL;
Struts2默认采用OGNL表达式访问Action的数据(Struts2也支持EL表达式),实际上是通过ValueStack对象来访问的Action
EL:${user.userName} 等价于 OGNL:
OGNL表达式(数组/集合、Map):
ValueStack:封装了Action的数据,并允许JSP通过OGNL来对其进行访问
EL表达式也可以访问ValueStack中的数据;
获取Session的方式:
1.ActionContext.getContext().getSession();返回值类型为:Map
2.ServletActionContext.getRequest().getSession();返回值类型为HttpSession
3.让Action实现SessionAware接口,实现void setSession(Map session)方法,Struts2会在实例化Action后调用该方法,通过方法参数将Session对象注入进来,我们要
定义成员变量接收注入进来的Session对象,推荐这种方法,采用注入思想更为灵活,面向接口编程,符合主流规范。
Result组件:用于向页面输出一些内容(每个Result实际上就是一个类,实现了共同的接口Result),转发(dispatcher,默认的result,将请求转给JSP),重定向(redirectAction)
UI标签: 生成一个文本框,根据OGNL表达式userName访问ValueStack,并将取得的结果设置为文本框的默认值
单选框,多选框,下拉框的设置:
根据OGNL(list属性值)创建的Map生成一组radio,其中Map的key可以生成radio的value值,Map的value
生成radio的label值。根据OGNL的取值(M)来与生成的radio的value比较,与哪个radio的value值一致,将其勾选。
动态单选框:
根据list初始化一组radio,根据name与listKey比较进行勾选。
多选框和单选框用法类似,也分为静态和动态两种区别在于将radio改为checkbox;下拉选标签也类似,将radio改为select
拦截器:
1.创建拦截器组件
创建一个类,实现Interceptor接口,并实现intercept方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class CheckPrivilegeInterceptor extends AbstractInterceptor{
public String intercept(ActionInvocation invocation) throws Exception {
//如果有权限就放行
if(user.hasPrivilegeByUrl(privUrl)){
return invocation.invoke();//执行action和result
}
//如果没有权限就转到提示页面
else{
return "noPrivilegeError";
}
}
}

2.注册拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<!-- 声明有这么个拦截器 -->
<interceptor name="checkPrivilege" class="cn.itcast.oa.util.CheckPrivilegeInterceptor"></interceptor>
<!-- 往往一个Action需要引用很多个拦截器,那么可以将这些拦截器打包成栈,直接引用这个栈即可,这样可以简化对拦截器的引用,
拦截器只是为了方便,在使用上等同于拦截器。可以将默认的拦截器(我们不需要在Action中做任何处理就相当于引用了这个拦截器)
改成我们定义的:name="defaultStack"-->
<interceptor-stack name="myStack">
<interceptor-ref name="checkPrivilege"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
</package>

3.引用拦截器:如果哪个Action希望被拦截器扩展,需要在此action配置下,引用拦截器

1
2
3
4
<action name="home_*" class="homeAction" method="{1}">
<interceptor-ref name="checkPrivilege"/>//可以写多个
<result name="{1}">/WEB-INF/jsp/homeAction/{1}.jsp</result>
</action>

拦截器是在实例化Action,调用业务方法之前开始调用的。
设置当前包下所有Action默认引用的拦截器:
多个拦截器拦截Action的顺序满足先进后出的原则。

Hibernate(数据访问层)

概念:是数据访问层的框架,对JDBC进行了封装,是针对数据库访问提出的面向对象的解决方案(ORM);
使用Hibernate可以直接访问对象,将访问转换成SQL执行对象–>数据库
Hibernate:采用数据库与Entity映射,对JDBC封装程度较重,自动生成SQL,对于基本的操作,开发效率高
MyBatis:采用SQL与Entity映射,对JDBC封装程度较轻,自己写SQL,更具灵活性
Hibernate与MyBatis共同点:对JDBC进行了封装,采用ORM思想解决了Entity和数据库的映射问题
ORM思想:Object Relation Mapping对象关系映射(java对象和关系数据库直接的映射)
主配置文件:hibernate.cfg.xml;配置数据库连接参数,框架参数,映射关系文件;实体类,映射关系文件
Hibernate常用API:
Configuration,SessionFactory,Session,Transaction,Query
Hibernate主键生成方式:
sequence:是采用序列方式生成主键,适用于Oracle数据库;
identity:采用数据库自增长机制生成主键,适用于Oracle之外的其他数据库
native:根据当前配置的数据库方言,自动选择sequence或者identity
increment:Hibernate提供的一种生成主键方式,获取当前表中主键的最大值,然后加1作为新的主键(在并发量高时,可能会生成重复的主键)
assigned:Hibernate不负责生成主键,需要程序员自己处理主键的生成。
uuid/hilo:采用uuid或hilo算法生成一个主键值,这个主键值是一个不规则的长数字
创建Session工具类:Configuration conf=new Configuration().configure(“/hibernate.cfg.xml”);SessionFactory = conf.buildSessionFactory();
session = SessionFactory.openSession();session.save(e);
开启事务:Transaction ts = session.beginTransaction();回滚事务:ts.rollback();
一级缓存:Hibernate创建每个Session对象时,都会给该Session分配一块独立的缓存区(一级缓存,Session级缓存),用于存放该Session查询出来的对象。
Session取数据时,会优先向缓存区取数据,没有才去数据库查询,降低数据库访问次数,提高代码效率。
一级缓存是Session独享,每个Session不能访问其他Session的缓存区,Session的save、update、delete操作会触发缓存更新。线程不安全
延迟加载(提升内存资源利用率,降低对数据库访问次数):在使用Hibernate方法查询数据时,返回的是一个空对象(只有id),只有在使用这个对象时,才会触发查询数据库,写入数据
使用延迟加载要避免Session提前关闭,要在视图层保持session的开启
关联映射:
一对多关联:通过增/删/改/查一,自动增/删/改/查多

1
2
3
4
5
<!-- replies属性,本类与Reply的一对多-->
<set name="replies">
<key column="topicId"></key>
<one-to-many class="Reply"/>
</set>

多对一关联:

1
2
<!-- topic属性,本类与Topic的多对一-->
<many-to-one name="topic" class="Topic" column="topicId"></many-to-one>

多对多关联:

1
2
3
4
5
6
7
8
9
10
<!-- users属性,本类与User的多对多(Role类) -->
<set name="users" table="itcast_user_role">
<key column="roleId"></key>
<many-to-many class="User" column="userId"></many-to-many>
</set>
<!-- roles属性,本类与Role的多对多(User类) -->
<set name="roles" table="itcast_user_role" lazy="false">
<key column="userId"></key>
<many-to-many class="Role" column="roleId"></many-to-many>
</set>

一对一关联:
继承关联:
级联操作:通过关联映射,在对一方进行增删改查时,连带增删改关联的另一方数据。(cascade=”save-update/delete/all”)
二级缓存:SessionFactory级别的缓存(全局),二级缓存的数据是Session间共享的。
实体查询:

1
2
3
4
5
6
7
8
9
public void testQueryAllDept(){
String hql="from Employee";
//hql="from com.sh.Entity";
Query query=session.createQuery(hql);
List<Employee> list= query.list();
//...
}

有条件的 实体查询 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void testQueryAllDept(){
String hql="from Deptas model where mode.deptName like '%部%' ";
//hql="from com.sh.Entity";
Query query=session.createQuery(hql);
List<Employee> list= query.list();
//...
}
public void testQueryDeptByGt(){
String hql="from Dept model where model.createDate> '2012-03-10'";
Query query=session.createQuery(hql);
List<Employee> list= query.list();
}
// delete 删除
public void testDelDeptByHql(){
Transaction tr=session.beginTransaction();
String hql="delete Dept as model where model.deptId=6";
Query query=session.createQuery(hql);
query.executeUpdate();
tr.commit();
}

属性查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public void testQueryDeptName(){
String hql="select model.deptName from Dept as model";
Query query=session.createQuery(hql);
List<String> deptNameList=query.list();
//...
}
public void testQueryDeptName(){
String hql="select model.deptName,model.createDate from Dept as model";
Query query=session.createQuery(hql);
List<Object[]> prsList=query.list();
for(){
}
//...
}
//采用对象进行 保存 查询的字段(要添加 对应字段的构造方法)
public void testQueryDeptName(){
String hql="select new Dapt(model.deptName,model.createDate) from Dept as model";
Query query=session.createQuery(hql);
List<Dept> deptList=query.list();
for(Dept d:deptList){
d.setDeptName("test");
session.saveOrUpdate(dept);
}
//...
}
//如果采用对象 保存上面查询出来的对象 如果对其进行更新的操作 是不会成功的
public void testSaveDept(){
Transction tr=session.beginTransactino();
String hql="select new Dept(model.deptName,model.createDate) from Dept as model";
Query query=session.createQuery();
List<Dept> deptList=query.list();
for(Dept dept:deptList){
System.out.println(dept.deptName);
dept.setDetpName("test");
session.saveOrUpdate(dept);
}
tr.commit();
// 最后 根本就没有更新 而是 在数据库中 插入 新的记录
}

查询单个对象:

1
2
3
4
5
6
7
public void testQueryUn(){
String hql="select model.deptName from Dept as model where model.deptId=2";
Query query=session.createQuery(hql);
query.setMaxResults(1);
String deptName=(String)query.uniqueResult();
System.out.println(deptNamae);
}

绑定参数:
1.使用 “:”加参数名 绑定参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void testQueryByParamsName(){
//使用 ":参数名" 来传递参数
String hql="from Dept as model where
odel.deptName=:deptName and model.createDate=:createDate";
Query query=session.createQuery(hql);
query.setString("deptName","test");
query.setString("ceateDate","2000-02-10");
List<Dept> deptList=query.list();
for(){}
//...
}

2.使用 “?” 按照位置来绑定参数

1
2
3
4
5
6
7
8
9
public void testQueryByParamsID(){
String hql="from Dept as model where model.deptName=? and model.createDate=?";
Query query=session.createQuery(hql);
query.setString(0,"test");
query.setString(1,"2000-02-02");
List<Dept> list=query.list();
for(){}
//..
}

3.采用setEntity() 将参数和一个持久化对象进行绑定

1
2
3
4
5
6
7
8
9
10
11
public void testQueryByDept(){
Dept dept=(Dept)Session.get(Dept.clas,new Integer(2));
String hql="select Employee as model where model.dept=?"
Query query=session.createQuery(hql);
query.setEntity(0,dept);
List<Employee> empList=query.list();
for(){}
//..
}

Spring对Dao编写的支持:提供了一套抽象的Dao类:
JdbcTemplate:封装常用JDBC方法,封装了连接获取以及连接释放等工作,避免忘记关闭连接等错误;
queryForInt(),queryForObject(),query(),update(),execute();(JdbcTemplate方法)
HibernateTemplate:封装常用Hibernate方法
JdbcDaoSupport:JDBC数据访问对象基类
HibernateDaoSupport:Hibernate数据访问对象的基类
基于JDBC技术编写DAO组件的两种模式:
1.DAO继承JdbcDaoSupport,通过getJdbcTemplate()方法获取JdbcTemplate对象,需要在DAO实现类中注入一个DataSource对象来完成JdbcTemplate的实例化

2.DAO不继承JdbcDaoSupport,在Spring容器中配置一个JdbcTemplate的bean,然后注入给DAO实现类(更优雅)

1
2
3
4
5
6
7
8
9
10
11
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="..."/>
<property name="url" value="..."/>
<property name="username" value="..."/>
<property name="password" value="..."/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="myDataSource"/>
</bean>
@resource
private JdbcTemplate template; //写在Dao中的

mybatis(持久层框架):

mybatis让程序员将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句
mybatis可以将向preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象(HashMap,JavaBean,基本数据类型)。(输出映射)
1.sqlMaoConfig.xml(是mybatis的全局配置文件,名称是不固定的)配置了数据源,事务等mybatis运行环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 和Spring整合后environments配置将废除 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="config/User.xml"/>
<!-- 通过resource方法,一次加载一个映射文件 -->
<mapper resource="config/UserMapper.xml"/>
<mapper resource="config/OrdersMapperCustom.xml"/>
</mappers>

根据数据表编写实体类,然后配置映射文件(n个)(配置sql语句)
mapper.xml(映射文件)mapper.xml,mapper.xml
User.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="mybatis.po.User">
select * from user where id = #{id}
</select>
<select id="findUserByName" parameterType="java.lang.String" resultType="mybatis.po.User">
select * from user where username like '%${value}%'
</select>
<insert id="insertUser" parameterType="mybatis.po.User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
insert into user (id,username,birthday,sex,address)value(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
<update id="updateUser" parameterType="mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id = #{id}
</update>
</mapper>

UserMapper.xml:

1
2
3
4
5
6
<mapper namespace="mybatis.mapper.UserMapper">
<cache/>
<select id="findUserById" parameterType="int" resultType="mybatis.po.User">
select * from user where id = #{id}
</select>
</mapper>

2.SqlSessionFactory(会话工厂)
作用:创建SqlSession
dao开发方法:
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.delete(“test.deleteUser”,id);
User user = sqlSession.selectOne(“test.findUserById”,id);
sqlSession.insert(“test.insertUser”, user);
mapper代理开发方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package mybatis.mapper;
public interface UserMapper {
//根据id查询用户信息,抛异常有利于健壮性
public User findUserById(int id)throws Exception;
//用户信息综合查询
public List<UserCustom> findUserList(UserQueryVo userQueryVo)throws Exception;
//用户信息综合查询总数
public int findUserCount(UserQueryVo userQueryVo)throws Exception;
//根据id查询用户信息,使用resultMap输出
public User findUserByIdResultMap(int id) throws Exception;
//根据用户名列查询用户列表
public List<User> findUserByName(String name)throws Exception;
//添加用户信息
public void insertUser(User user)throws Exception;
//删除用户信息
public void deleteUser(int id) throws Exception;
//更新用户
public void updateUser(User user)throws Exception;
}
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建UserMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用userMapper的方法
User user = userMapper.findUserById(1);

3.SqlSession(会话),是一个接口,面向用户(程序员)的接口
作用:操作数据库(发出sql增删改查)
4.Executor(执行器),是一个接口(基本执行器,缓存执行器)
作用:SqlSession内部通过执行器操作数据库
5.mapped statement(底层封装对象)
作用:对操作数据库存储封装,包括sql语句,输入参数,输出结果类型
6.动态sql:与JSTL相似,允许我们在XML中构建不同的SQL语句
判断元素:if,choose
关键字元素:where:简化查询语句中where部分的条件判断。
set:用在更新操作的时候,作用和where相似;trim

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<select id="findByCondition" parameterType="Emp" resultType="Emp">
select * from EMP
<where>
<if test="deptno!=null">
DEPTNO=#{deptno}
</if>
<choose>
<when test="sal>2000">
and SAL>=#{sal}
</when>
<otherwise>
and SAL>=2000
</otherwise>
</choose>
</where>
</select>
<update id="updateEmp" parameterType="Emp">
update EMP
<set>
<if test="ename!=null">
ENAME=#{ename},
</if>
<if test="deptno!=null">
DEPTNO=#{deptno}
</if>
</set>
where EMPNO=#{empno}
</update>

循环元素:foreach:实现了循环逻辑,可以进行一个集合的迭代

1
2
3
4
5
6
7
8
9
<select id="findByDeptNos" resultType="Emp" parameterType="Emp">
select * from EMP
<if test="deptnos!=null">
where DEPTNO in
<foreach collection="deptnos" item="dno" open="(" close=")" separator=",">
#{dno}
</foreach>
</if>
</select>

7.关系映射
主键自动递增:MySQL、SQLServer数据库都支持字段自动递增功能,在使用MyBatis时,有时要返回MySQL、SQLServer数据库自动增长的主键值

1
2
3
<insert id="addDept" parameterType="Dept" keyProperty="deptno" useGeneratedKeys="true">
insert into T_DEPT (DNAME,LOC)values(#{dname},#{loc})
</insert>

<insert>元素指定了自动激增属性设置后,MyBatis会在插入操作后将自动生成的主键值给keyProperty指定的属性赋值
非自动递增:Oracle不支持自动递增,采用序列生成主键值

1
2
3
4
5
6
<insert id="addDept" parameterType="Dept">
<selectKey keyProperty="deptno" order="before" resultType="java.lang.Integer">
select dept_seq.nextval from dual
</selectKey>
insert into T_DEPT (DEPTNO,DNAME,LOC)values(#{deptno},#{dname},#{loc})
</insert>

关联映射作用:获取两个或以上关联表的数据
嵌套查询映射(查两次):

1
2
3
4
5
6
7
8
9
<select id="findById" parameterType="java.lang.Integer" resultMap="empMap">
select * from EMP where EMPNO=#{id}
</select>
<select id="selectDept" parameterType="java.lang.Integer" resultType="Dept">
select * from DEPT where DEPTNO=#{id}
</select>
<resultMap type="Emp" id="empMap">
<association property="dept" column="DEPTNO" javaType="Dept" select="selectDept" />
</resultMap>

嵌套结果映射(查一次):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id="findById" parameterType="java.lang.Integer" resultMap="empMap">
select e.empno,e.ename,e.job,e.mgr,e.sal,e.comm,d.dname,d.loc from EMP e join DEPT d on(d.deptno=e.deptno)
where e.EMPNO=#{id}
</select>
<resultMap type="Emp" id="empMap">
<id column="EMPNO" property="empno"></id>
<result column="ENAME" property="ename"></result>
<result column="JOB" property="job"></result>
<result column="SAL" property="sal"></result>
<result column="COMM" property="comm"></result>
<association property="dept" javaType="Dept">
<id column="DEPTNO" property="deptno"></id>
<result column="DNAME" property="dname"></result>
<result column="LOC" property="loc"></result>
</association>
</resultMap>

mybatis开发dao两种方式:
原始dao开发方法(程序需要编写dao接口和dao实现类)(掌握)
mybatis的mapper接口(相当于dao接口)代理开发方法(掌握)
mybatis配置文件SqlMapConfig.xml
mybatis核心:
mybatis输入映射(掌握)parameterType:指定输入参数类型可以简单类型、pojo、hashmap。。
mybatis输出映射(掌握)resultType,resultMap
mybatis的动态sql(掌握)

高级知识:
订单商品数据模型分析
高级结果集映射(一对一,一对多,多对多)
mybatis延迟加载
mybatis查询缓存(一级缓存,二级缓存)
mybatis和spring进行整合(掌握)
mybatis逆向工程

mybatis和hibernate本质区别和应用场景:
hiberbate:是一个标准ORM框架(对象关系映射)。入门门槛较高的,不需要程序员写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难的。
应用场景:适用于需求变化不多的中小型项目,比如说:后台管理系统,erp,orm,oa….
mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全的ORM框架,
虽然程序员自己写sql,mybatis也可以实现映射(输入映射,输出映射)。使用于需求变化较多的项目,比如:互联网项目。
企业进行技术选型:以低成本 高回报作为技术选型的原则,根据项目组的技术力量进行选择。
说白点,hibernate不需要写sql,mybatis需要写sql

Spring与MyBatis整合:
SqlSessionFactoryBean:为整合应用提供SqlSession对象;在applicationContext.xml中定义格式如下:

1
2
3
4
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="mapperLocations" value="classpath:org/yh/entity/*.xml"/>
</bean>

MapperFactoryBean:根据Mapper接口获取我们想要的Mapper对象

1
2
3
4
5
6
<bean id="deptMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!--指定Mapper接口,用来返回Mapper对象 -->
<property name="mapperInterface" value="org.yh.mapper.DeptMapper" />
<!--指定SqlSessionFactoryBean对象,用于提供SqlSession -->
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

MapperScannerConfigurer:通过这个组件会自动扫描各个Mapper接口,并注册对应的MapperFactoryBean对象
basePackage用于指定Mapper接口所在的包,将Mapper接口注册为对象,多个包之间可以用逗号或者分号分隔。

1
2
3
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.yh.mapper" />
</bean>

基于SqlSessionTemplate的DAO配置信息:

1
2
3
4
5
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<!--扫描DAO并注入template,可以用注解方式实现 -->
<context:component-scan base-package="org.yh.dao" />

DAO实现与之前单独MyBatis一致

单元测试:
导包:项目–>右键–>Properties–>Java Build Path–>Libraries–>Add Library–>JUnit–>next–>Junit4–>finish
测试方法前加 @Test ;测试的时候,代码内(测试加了 @Test 的所有方法)/要测试的方法名(测试当前方法)–>右键–>Run As –>JUnit Test

Basic–>OOP(object oriented programming面向对象)–>SE(standard edition标准版)–>ORACLE—>MYSQL–>JDBC(JavaDateBaseConnection)–>HTML–>
CSS(层叠样式表)–>JS(JavaScripe)–>servlet–>JSP–>Ajax–>JQuery–>Spring–>MyBatis–>Struts–>Hibernate–>Struts

垃圾回收(GC Gabage Collection):

内存由 Perm(Permanent Generation,持久带,放JVM自己的反射对象,比如类对象和方法对象等)和 Heap(堆) 组成. 其中Heap = {Old + NEW = { Eden , from, to } }
JVM内存模型中分两大块,一块是 NEW Generation, 另一块是Old Generation. 在New Generation中,有一个叫Eden的空间,主要是用来存放新生的对象,
还有两个Survivor Spaces(from,to), 它们用来存放每次垃圾回收后存活下来的对象。 在Old Generation中,主要存放应用程序中生命周期长的内存对象
垃圾回收描述:
在New Generation块中,垃圾回收一般用Copying的算法,速度快。每次GC的时候,存活下来的对象首先由Eden拷贝到某个Survivor Space,
当Survivor Space空间满了后, 剩下的live对象就被直接拷贝到Old Generation中去。因此,每次GC后,Eden内存块会被清空。
在Old Generation块中,垃圾回收一般用mark-compact的算法,速度慢些,但减少内存要求.垃圾回收分多级,0级为全部(Full)的垃圾回收,会回收OLD段中的垃圾;
1级或以上为部分垃圾回收,只会回收NEW中的垃圾,内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。
1.增加Heap的大小虽然会降低GC的频率,但也增加了每次GC的时间。并且GC运行时,所有的用户线程将暂停,也就是GC期间,Java应用程序不做任何工作。
标记-清除(Mark-Sweep),复制(Copying),标记-整理(Mark-Compact),

内存溢出

jvm管理的内存大致包括三种不同类型的内存区域:Permanent Generation space(永久保存区域)、Heap space(堆区域)、Java Stacks(Java栈)。

第一种OutOfMemoryError: PermGen space
发生这种问题的原意是程序中使用了大量的jar或class,使java虚拟机装载类的空间不够,与Permanent Generation space有关。解决这类问题有以下两种办法:

  1. 增加java虚拟机中的XX:PermSize和XX:MaxPermSize参数的大小,其中XX:PermSize是初始永久保存区域大小,XX:MaxPermSize是最大永久保存区域大小。如针对tomcat6.0,在catalina.sh 或catalina.bat文件中一系列环境变量名说明结束处(大约在70行左右) 增加一行:
    JAVA_OPTS=” -XX:PermSize=64M -XX:MaxPermSize=128m”
    如果是windows服务器还可以在系统环境变量中设置。
  2. 清理应用程序中web-inf/lib下的jar,如果tomcat部署了多个应用,很多应用都使用了相同的jar,可以将共同的jar移到tomcat共同的lib下,减少类的重复加载。

第二种OutOfMemoryError: Java heap space
发生这种问题的原因是java虚拟机创建的对象太多,在进行垃圾回收之间,虚拟机分配的到堆内存空间已经用满了,与Heap space有关。解决这类问题有两种思路:

  1. 检查程序,看是否有死循环或不必要地重复创建大量对象。找到原因后,修改程序和算法。
  2. 增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。如:set JAVA_OPTS= -Xms256m -Xmx1024m

第三种OutOfMemoryError:unable to create new native thread
这种错误在Java线程个数很多的情况下容易发生

如果想要堆溢出,比较简单,可以循环创建对象或大的对象;
如果想要栈溢出,可以递归调用方法,这样随着栈深度的增加,JVM 维持着一条长长的方法调用轨迹,直到内存不够分配,产生栈溢出。
另外,Java虚拟机的堆大小如何设置:命令行

1
2
3
4
 java –Xms128m //JVM占用最小内存
–Xmx512m //JVM占用最大内存
XX:PermSize=64m //最小堆大小
XX:MaxPermSize=128m //最大堆大小

SVN 修改账号密码: C:\Users\HP\AppData\Roaming\Subversion\auth 路径下的文件删除(该文件是隐藏的,需要设置,隐藏可见)

「真诚赞赏,手留余香」