找工作复习2

PS:

 

java规定如果两个对象equals返回true,那么这两个对象的hashCode码必须一致。

 

PS: 事务的四种隔离级别

事务的特性:

原子性,是一个最小逻辑操作单元 !

一致性,事务过程中,数据处于一致状态。

持久性, 事务一旦提交成功,对数据的更改会反映到数据库中。

隔离性, 事务与事务之间是隔离的。

PS:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

----------------------------------------------------------

单例模式

http://blog.csdn.net/abc19900828/article/details/39479377

classpath环境变量

  1. classpath的作用: 作用是指定类搜索路径,要使用已经编写好的类,前提当然是能够找到它们了,一旦配置了classpath路径信息的时候,jvm与java编译器都会根据classpath指定的路径去寻找class文件。

==========================================

 逻辑运算

“&”和“&&”的区别:单与时,左边无论真假,右边都进行运算;双与时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。

========================================= 

PS:”&”、“|”、“^”除了可以作为逻辑运算符也可以作为位运算符。

----------------------------运算符的优先级-----------------------

/*判断闰年,能被4整除,不能被400整除,或能被400整除的*/
private static boolean getResult(int year) {
        // TODO Auto-generated method stub
        if((year%4==0&&year%100!=0)||year%400==0){
            return true;
        }
        return false;
    }

 

 

==================生成指定区间的随机数=======================

nextInt(4)将产生0,1,2,3这4个数字中的任何一个数字注意这里不是0-4,而是0-3。

int MAX = 40;
        int MIN = 30;
        Random random = new Random();
        System.out.println(random.nextInt(MAX-MIN+1)+MIN);

=================构造代码块===========================================

1:给对象进行初始化。对象一建立就运行并且优先于构造函数。

 

作用

1:给对象进行初始化。对象一建立就运行并且优先于构造函数。

2:与构造函数区别

1:构造代码块和构造函数的区别,构造代码块是给所有对象进行统一初始化, 构造函数给对应的对象初始化。

    2:构造代码块的作用:它的作用就是将所有构造方法中公共的信息进行抽取。

例如孩子一出生统一哭

==================this==========================================

PS:this只能在非静态中(没有static修饰的)函数使用

this是什么

       1:在构造函数中打印this

       2:创建对象,打印对象名p

       3:this和p是一样的都是内存地址值。//p是对象的引用

       4:this代表所在函数所属对象的引用

=====================重写=======================================

 1: 函数名必须相同

    2:参数列表必须相同

3: 子类重写父类的函数的时候,函数的访问权限必须大于等于父类的函数的访

问权限否则编译报错

4:子类重写父类的函数的时候,返回值类型必须是父类函数的返回值类型或该返回值类型的子类。不能返回比父类更大的数据类型: 如子类函数返回值类型是Object

======================继承=========================

为什么子类一定要访问父类的构造函数呢

1:子类继承了父类的属性,如果要使用父类的属性必须初始化,创建子类对象,必须先初始化父类属性

              必须调用父类的构造方法。

           2:为什么调用父类无参的构造函数

设计java语言之时,只知道编译器会默认添加无参的构造函数,有参的无法确定。

              但是可以通过super关键字显式调用父类指定构造函数。

           3:为什么super()this()语句要放在构造函数的第一行

              子类可能会用到父类的属性,所以必须先初始化父类。

======================构造函数=========================

Demo类被加载,执行main方法,Son.class加载,发现有父类Father类,于是Father类也加载进内存。类加载完毕,创建对象,父类的构造方法会被调用(默认自动无参),

如果父类没有无参,则报错

============API

PS1:

 

StringBuffer : 由于String是不可变的,所以导致String对象泛滥,在频繁改变字符串对象的应用中,需要使用可变的字符串缓冲区类。

 

  1. 默认缓冲区的容量是16。

==========

 

1.1   线程的状态

 

创建:新创建了一个线程对象。

可运行:线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取cpu的执行权。

运行:就绪状态的线程获取了CPU执行权,执行程序代码。

阻临时塞: 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。

死亡:线程执行完它的任务时。

============后台线程=================

 当所有的非后台线程结束时,程序也就终止了同时还会杀死进程中的所有后台线程,也就是说,只要有非后台线程还在运行,程序就不会终止,执行main方法的主线程就是一个非后台线程。

=============ArrayList=================

PS: ArrayList  底层采用数组实现,默认10。每次增长60%,((oldCapacity * 3)/2 + 1) 查询快,增删慢。

============Collections================

1.对list集合中的元素进行位置的置换。

swap(list,x,y);

=======================Arrays------------------------

2. 复制数组。

 copyOf();

1, 复制部分数组。

copyOfRange():

2, 比较两个数组是否相同。

equals(int[],int[]);

==============Hashset存储元素==================

HashSet到底是如何判断两个元素重复。

通过hashCode方法和equals方法来保证元素的唯一性,add()返回的是boolean类型

判断两个元素是否相同,先要判断元素的hashCode值是否一致,只有在该值一致的情况下,才会判断equals方法,如果存储在HashSet中的两个对象hashCode方法的值相同equals方法返回的结果是true,那么HashSet认为这两个元素是相同元素,只存储一个(重复元素无法存入)。

=====================

 

 

Set<Map.Entry<K,V>> entrySet()

面向对象的思想将map集合中的键和值映射关系打包为一个对象,就是Map.Entry

,将该对象存入Set集合,Map.Entry是一个对象,那么该对象具备的getKey,getValue获得键和值。

 

================List的set方法,交换两个对象的值=============================

 

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;

/*
需求: 使用LinkedList存储一副扑克牌,然后实现洗牌功能。
*/
//扑克类
class Poker{
    
    String  color; //花色
    
    String num;    //点数

    public Poker(String color, String num) {
        super();
        this.color = color;
        this.num = num;
    }

    
    @Override
    public String toString() {
        return "{"+color+num+"}";
    }
}

public class Demo2 {
    
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        //list.
        LinkedList pokers = createPoker();
        shufflePoker(pokers);
        showPoker(pokers);
    }
    
    
    //洗牌的功能
    public static void shufflePoker(LinkedList pokers){
        //创建随机数对象
        Random random = new Random();
        for(int i = 0 ; i <100; i++){ 
            //随机产生两个索引值
            int index1 = random.nextInt(pokers.size());
            int index2 = random.nextInt(pokers.size());
            //根据索引值取出两张牌,然后交换两张牌的顺序
            Poker poker1 = (Poker) pokers.get(index1);
            Poker poker2 = (Poker) pokers.get(index2);
            pokers.set(index1, poker2);
            pokers.set(index2, poker1);
        }
        
    }
    
    
    
    //显示扑克牌
    public static void showPoker(LinkedList pokers){
        for(int i = 0 ; i<pokers.size() ; i++){
            System.out.print(pokers.get(i));
            //换行
            if(i%10==9){
                System.out.println();
            }
        }
    
    }
    //生成扑克牌的方法
    public static LinkedList createPoker(){
        //该集合用于存储扑克对象。
        LinkedList list = new LinkedList();        
        //定义数组存储所有的花色与点数
        String[] colors = {"黑桃","红桃","梅花","方块"};
        String[] nums = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
        for(int i = 0 ; i < nums.length ; i++){
            for(int j = 0 ; j<colors.length ; j++){
                list.add(new Poker(colors[j], nums[i]));
            }
        }
        return list;
    }
    
    
}

====================正则表达式=================================

PS:功能主要有四个:

1.匹配,

public static void checkQQ2()         
{                                     
String qq = "12345";              
String reg = "[1-9][0-9]{4,14}";  
boolean b = qq.matches(reg);      
System.out.println("b="+b);                                 
}                     

 

2.切割,split()

3.替换,

String str = "联系我:13567012119联系我:13567012119联系我:13567012119联系我:13567012119联系我:13567012119联系我:13567012119";
        String reg= "1[34578]\\d{9}";
        str =    str.replaceAll(reg,"******");
        System.out.println("替换后的帖子

 

String str = "联系我:13567012119联系我:13567012119联系我:13567012119联系我:13567012119联系我:13567012119联系我:13567012119";
        String regex = "联系我";
        str = str.replaceAll(regex , "zhh");
        System.out.println(str);//zhh:13567012119zhh:13567012119zhh:13567012119zhh:13567012119zhh:13567012119zhh:13567012119

 

4.获取,

    public static void getDemo()
    {
        String str = "da jia zhu yi le,ming tian bu fang jia,xie xie!";
        //想要获取由3个字母组成的单词。
        //刚才的功能返回的都是一个结果,只有split返回的是数组,但是它是把规则作为分隔符,不会获取符合规则的内容。
        //这时我们要用到一些正则对象。
        String reg = "\\b[a-z]{3}\\b";
        Pattern p = Pattern.compile(reg);
        Matcher m = p.matcher(str);
        while(m.find())
        {
            System.out.println(m.start()+"...."+m.end());
            System.out.println("sub:"+str.substring(m.start(),m.end()));
            System.out.println(m.group());
        }
//        System.out.println(m.find());//将规则对字符串进行匹配查找。
//        System.out.println(m.find());//将规则对字符串进行匹配查找。
//        System.out.println(m.group());//在使用group方法之前,必须要先找,找到了才可以取。
    }

http://www.cnblogs.com/ggjucheng/p/3423731.html  看正则

=============路径分隔符================

PS:在Windows中分隔符为     '\',在Unix/Linux中分隔符为             '/'     

========================================

PS:    读文件流

 

PS: 在创建文件的时候追加。

// 1:打开文件输出流,流的目的地是指定的文件

       FileOutputStream fos = new FileOutputStream(path,true);

// 2.复制文件

public static void copyFile2(String srcPath, String destPath)
            throws IOException {
        // 打开输入流,输出流
        FileInputStream fis = new FileInputStream(srcPath);
        FileOutputStream fos = new FileOutputStream(destPath);

        // 读取和写入信息
        int len = 0;

        // 使用字节数组,当做缓冲区
        byte[] byt = new byte[1024];
        while ((len = fis.read(byt)) != -1) {
            fos.write(byt, 0, len);
        }

        // 关闭流
        fis.close();
        fos.close();
    }

PS:其实就是就是在fis和fos提供的缓冲流

 上述程序中我们为了提高流的使用效率,自定义了字节数组,作为缓冲区.Java其实提供了专门的字节流缓冲来提高效率.

BufferedInputStream和BufferedOutputStream

BufferedOutputStream和BufferedOutputStream类可以通过减少读写次数来提高输入和输出的速度。它们内部有一个缓冲区,用来提高处理效率。查看API文档,发现可以指定缓冲区的大小。其实内部也是封装了字节数组。没有指定缓冲区大小,默认的字节是8192。

显然缓冲区输入流和缓冲区输出流要配合使用。首先缓冲区输入流会将读取到的数据读入缓冲区,当缓冲区满时,或者调用flush方法,缓冲输出流会将数据写出。

注意:当然使用缓冲流来进行提高效率时,对于小文件可能看不到性能的提升。但是文件稍微大一些的话,就可以看到实质的性能提升了。

 

=========编码和解码===================

PS:字符流的出现是因为,字节流再处理非字节流时字符的信息不太方便。(char)

字符流 = 字节流 + 编码(解码)     主要是为了保存文本文件

PS:字符流的copy

 

public static void main(String[] args) throws Exception {
        String path1 = "c:/a.txt";
        String path2 = "c:/b.txt";

        copyFile(path1, path2);
    }

public static void copyFile3(String path1, String path2) throws Exception {
        Reader reader = new FileReader(path1);
        Writer writer = new FileWriter(path2);

        int ch = -1;
        char [] arr=new char[1024];
        while ((ch = reader.read(arr)) != -1) {
            writer.write(arr,0,ch);
        }

        reader.close();
        writer.close();
    }

 

PS:字符缓冲流是为了 char 【】 的原因, 使用装饰者模式,可以整行整行的读

public class Demo7 {
    public static void main(String[] args) throws IOException {
        // 关联源文件
        File srcFile = new File("c:\\linux大纲.txt");
        // 关联目标文件
        File destFile = new File("d:\\linux大纲.txt");
        // 实现拷贝
        copyFile(srcFile, destFile);

    }

    private static void copyFile(File srcFile, File destFile)
            throws IOException {
        // 创建字符输入流
        FileReader fr = new FileReader(srcFile);
        // 创建字符输出流
        FileWriter fw = new FileWriter(destFile);

        // 字符输入流的缓冲流
        BufferedReader br = new BufferedReader(fr);
        // 字符输出流的缓冲流
        BufferedWriter bw = new BufferedWriter(fw);

        String line = null;
        // 一次读取一行
        while ((line = br.readLine()) != null) {
            // 一次写出一行.
            bw.write(line);
            // 刷新缓冲
            bw.flush();
            // 进行换行,由于readLine方法默认没有换行.需要手动换行
            bw.newLine();
        }
        // 关闭流
        br.close();
        bw.close();
    }
}

==============其他流============

1.1.2 由于上述ObjectOutput和ObjectInput是接口,所以需要使用具体实现类。

PS:主要是用来序列化对象的

ObjectOutput

 ObjectOutputStream被写入的对象必须实现一个接口:Serializable

否则会抛出:NotSerializableException

ObjectInput

     ObjectInputStream    该方法抛出异常:ClassNotFountException 

ObjectOutputStream和ObjectInputStream 对象分别需要字节输出流和字节输入流对象来构建对象。也就是这两个流对象需要操作已有对象将对象进行本地持久化存储。

1.1.1.    SequenceInputStream 序列流,对多个流进行合并。

序列化和反序列化Cat对象。
public class Demo3 {
    public static void main(String[] args) throws IOException,
            ClassNotFoundException {
        Cat cat = new Cat("tom", 3);
        FileOutputStream fos = new FileOutputStream(new File("c:\\Cat.txt"));
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(cat);
        System.out.println(cat);
        oos.close();
        // 反序列化
        FileInputStream fis = new FileInputStream(new File("c:\\Cat.txt"));
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object readObject = ois.readObject();
        Cat cat2 = (Cat) readObject;
        System.out.println(cat2);
        fis.close();
}

class Cat implements Serializable {
    public String name;
    public int age;

    public Cat() {

    }

    public Cat(String name, int age) {

        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Cat [name=" + name + ", age=" + age + "]";
    }

}

注意:序列化不适用于静态变量,因为静态变量并不属于对象的实例变量的一部分。静态变量随着类的加载而加载,是类变量。由于序列化只适用于对象。

基本数据类型可以被序列化

1.1.3 打印流

注意: 打印流的三种方法

       void print(数据类型 变量)

   println(数据类型 变量)

   printf(String format, Object... args)

      可以自定数据格式

    print 和println方法的区别在于,一个换行一个不换行

    print 方法和write方法的却别在于,print提供自动刷新.

    普通的write方法需要调用flush或者close方法才可以看到数据.

JDK1.5之后Java对PrintStream进行了扩展,增加了格式化输出方式,可以使用printf()重载方法直接格式化输出。但是在格式化输出的时候需要指定输出的数据类型格式。

 

1.1.1.  PrintWriter

是一个字符打印流。构造函数可以接收四种类型的值。

1,字符串路径。

2,File对象。

对于1,2类型的数据,还可以指定编码表。也就是字符集。

3,OutputStream

4,Writer

对于3,4类型的数据,可以指定自动刷新。

注意:该自动刷新值为true时,只有三个方法可以用:println,printf,format.

如果想要既有自动刷新,又可执行编码。如何完成流对象的包装?

PrintWrter pw =

new PrintWriter(new OutputSteamWriter(new FileOutputStream("a.txt"),"utf-8"),true);

如果想要提高效率。还要使用打印方法。

PrintWrter pw =

newPrintWriter(new  BufferdWriter(new OutputSteamWriter(

newFileOutputStream("a.txt"),"utf-8")),true);

1.1.1.    DataInputStream  重要    根据不同的数据类型进行数据的保存

以及DataOutputStream

 

查看API文档DataInputStream的信息。发现从底层输入流中读取基本 Java 数据类型。查看方法,有读一个字节,读一个char读一个double 的方法,

 

DataInputStream 从数据流读取字节,并将它们转换为正确的基本数据类型值或字符串。

该流有操作基本数据类型的方法.

有读的,那么必定有对应的写的就是DataOutputStream 将基本类型的值或字符串转换为字节,并且将字节输出到数据流。

DataInputStream类继承FilterInputStream类,并实现了DataInput接口。DataOutputStream

类继承FilterOutputStream 并实现了DataOutput 接口。

例如:

DataInputStream

操作基本数据类型的方法:

int readInt():一次读取四个字节,并将其转成int值。

boolean readBoolean():一次读取一个字节。

short readShort();

long readLong();

剩下的数据类型一样。

String readUTF():按照utf-8修改版读取字符。注意,它只能读writeUTF()写入的字符数据。

DataOutputStream

DataOutputStream(OutputStream):

操作基本数据类型的方法:

writeInt(int):一次写入四个字节。

注意和write(int)不同。write(int)只将该整数的最低一个8位写入。剩余三个8位丢弃。

writeBoolean(boolean);

writeShort(short);

writeLong(long);

剩下是数据类型也也一样。

writeUTF(String):按照utf-8修改版将字符数据进行存储。只能通过readUTF读取。

 

 

测试:   DataOutputStream

       使用DataOutputStream写数据文件。

public static void testDataInputStream() throws Exception {

       DataOutputStream out = new DataOutputStream(new FileOutputStream(

              "c:/a.txt"));

 

       out.writeBoolean(true);

       out.writeByte(15); // 0x05 1 个字节

       out.writeBytes("abc"); // 0x 0041 2个字节

       out.writeChar('X'); // ??

       out.writeChars("xyz");

       out.writeLong(111);

       out.writeUTF("中国");

 

       out.close();

 

       DataInputStream in = new DataInputStream(

              new FileInputStream("c:/a.txt"));

       System.out.println(in.readBoolean());

       System.out.println(in.readByte());

      

       System.out.println(in.readByte());

       System.out.println(in.readByte());

       System.out.println(in.readByte());

      

       System.out.println(in.readChar());

      

       System.out.println(in.readChar());

       System.out.println(in.readChar());

       System.out.println(in.readChar());

      

       System.out.println(in.readLong());

      

       System.out.println(in.readUTF());

       in.close();

    }

 ==========================

计算机中存储的都是二进制,但是要显示的时候,就是我们看到的却可以有中国 ,a  1 等字符

计算机中是没有存储字符的,但是我们却看到了。计算机在存储这些信息的时候,根据一个有规则的编号,当用户输入a 有a对映的编号,就将这个编号存进计算机中这就是编码。

PS:每个字符都有  相应的   码表,字符都保存在字节保存。有码表才能看见这么多东西。

1.1. 编码:

字符串---》字节数组

String类的getBytes() 方法进行编码,将字符串,转为对映的二进制,并且这个方法可以指定编码表。如果没有指定码表,该方法会使用操作系统默认码表。

注意:中国大陆的Windows系统上默认的编码一般为GBK。在Java程序中可以使用System.getProperty("file.encoding")方式得到当前的默认编码。

1.2. 解码:

字节数组---》字符串

String类的构造函数完成。

String(byte[] bytes)  使用系统默认码表

String(byte[],charset)指定码表

注意:我们使用什么字符集(码表)进行编码,就应该使用什么字符集进行解码,否则很有可能出现乱码(兼容字符集不会)。

// 编码操作与解码操作。
    public static void main(String[] args) throws Exception {
        String value = System.getProperty("file.encoding");
        System.out.println("系统默认的编码为 " + value);

        String str = "中";

        // 编码操作
        byte[] bytes = str.getBytes();
        byte[] bytes2 = str.getBytes("gbk");// d6d0
        byte[] bytes3 = str.getBytes("utf-8");// e4b8ad

        System.out.println(Arrays.toString(bytes)); // [-42, -48]
        System.out.println(Arrays.toString(bytes2));// [-42, -48]
        System.out.println(Arrays.toString(bytes3));// [-28, -72, -83]

        // 解码操作
        // 编码gbk,解码utf-8乱码。
        String str2 = new String(bytes2, "utf-8");
        System.out.println(str2);

        // 编码utf-8 解码gbk,乱码
        str2 = new String(bytes3, "gbk");
        System.out.println(str2);
        // gbk兼容gb2312所以,没有问题。
        str = new String("中国".getBytes("gb2312"), "gbk");
        System.out.println(str);
    }

 

==============Socket编程(网络编程)===============

网络通讯的三要素:
1. IP
2. 端口号。
3. 协议.

-------------------------------

IP地址的分类:
A类地址 = 一个网络号 + 三个主机号 2^24 政府单位
B类地址 = 两个网络号+ 两个主机号 2^16 事业单位(学校、银行..)
C类地址= 三个网络号+ 一个主机号 2^8 私人使用..

-----------------------------------

PS:Socket就是IP和 端口描述

 

UDP通讯协议的特点:
1. 将数据极封装为数据包,面向无连接。
2. 每个数据包大小限制在64K中
3.因为无连接,所以不可靠
4. 因为不需要建立连接,所以速度快
5.udp 通讯是不分服务端与客户端的,只分发送端与接收端。

TCP通讯协议特点:
1. tcp是基于IO流进行数据 的传输 的,面向连接。
2. tcp进行数据传输的时候是没有大小限制的。
3. tcp是面向连接,通过三次握手的机制保证数据的完整性。 可靠协议。
4. tcp是面向连接的,所以速度慢。
5. tcp是区分客户端与服务端 的。

package cn.itcast.tcp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;


/*
2.  实现登陆与注册 功能。  
    客户端与服务端连接的时候,就要提示客户端请选择功能。
    
    客户端注册的时候,用户名与密码都是发送给服务端 的,服务端需要把数据保存到服务端的文件上。
    
    登陆: 登陆的时候客户端输入用户名与密码发送给服务端,服务端需要校验,返回结果给客户端。
*/

public class LoginClinet {
    
    public static void main(String[] args) throws IOException {        
        Socket socket = new Socket(InetAddress.getLocalHost(),9090);
        //获取socket的输出流对象
        OutputStreamWriter  socketOut = new OutputStreamWriter(socket.getOutputStream());
        
        //获取到socket的输入流对象
        BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        
        //获取到键盘的输入流对象
        BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));
        while(true){
            System.out.println("请选择功能: A(登陆)  B(注册)");
            String option = keyReader.readLine();
            if("a".equalsIgnoreCase(option)){
                getInfo(socketOut, keyReader, option);
                //读取服务器反馈的信息
                String line = socketReader.readLine();
                System.out.println(line);
            }else if("b".equalsIgnoreCase(option)){
                getInfo(socketOut, keyReader, option);
                //读取服务器反馈的信息
                String line = socketReader.readLine();
                System.out.println(line);
            }

        }
        
        
    }

    public static void getInfo(OutputStreamWriter  socketOut,BufferedReader keyReader, String option)
            throws IOException {
        System.out.println("请输入用户名:");
        String userName = keyReader.readLine();
        System.out.println("请输入密码:");
        String password = keyReader.readLine();
        String info = option +" "+userName+" "+password+"\r\n";
        socketOut.write(info);
        socketOut.flush();
    }
    
}
package cn.itcast.tcp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

public class LoginServer extends Thread {

    Socket socket;

    static File file = new File("F:\\users.properties");

    public LoginServer(Socket socket) {
        this.socket = socket;
    }

    static {
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
    while(true){
            
            try {
                // 获取socket的输入流对象
                BufferedReader bufferedReader = new BufferedReader(
                        new InputStreamReader(socket.getInputStream()));
                // 获取socket的输出流对象
                OutputStreamWriter socketOut = new OutputStreamWriter(
                        socket.getOutputStream());
    
                // 读取客户端输入的信息
                String info = bufferedReader.readLine();
                String[] datas = info.split(" ");
                // 获取到用户 的选择功能
                String option = datas[0];
                // 注册
                String userName = datas[1];
    
                String password = datas[2];
    
                if ("a".equalsIgnoreCase(option)) {
                    // 登陆
                    Properties properties = new Properties();
                    // 加载配置文件
                    properties.load(new FileReader(file));
                    if (properties.containsKey(userName)) {
                        String tempPass = properties.getProperty(userName);
                        if (password.equals(tempPass)) {
                            socketOut.write("欢迎" + userName + "登陆成功\r\n");
    
                        } else {
                            socketOut.write("密码错误\r\n");
                        }
    
                    } else {
                        socketOut.write("用户名不存在,请重新输入...\r\n");
                    }
    
                    socketOut.flush();
    
                } else if ("b".equalsIgnoreCase(option)) {
    
                    // 创建一个配置文件类
                    Properties properties = new Properties();
                    //加载原来的配置文件
                    properties.load(new FileReader(file));
                    if (!properties.containsKey(userName)) {
                        // 不存在该用户名
                        properties.setProperty(userName, password);
                        // 生成一个配置文件
                        properties.store(new FileWriter(file), "users");
                        socketOut.write("注册成功..\r\n");
                    } else {
                        // 存在用户名
                        socketOut.write("用户名已经被注册,请重新输入\r\n");
                    }
                    socketOut.flush();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9090);
        while (true) {
            Socket socket = serverSocket.accept();
            new LoginServer(socket).start();
        }

    }

}

=================静态代码块==============================================

静态代码块:

静态代码块是静态代码块所属的类被加载到内存的时候执行的。


静态代码块的应用场景: 以后主要用于准备一个项目的初始化工作。
比如: 从配置配置文件中读取数据库用户名与密码。

=====================对象的拷贝===========================

2    对象拷贝
2.1    对象的浅拷贝
浅复制(浅克隆)被复制对象的所有变量都含有与原来对象相同的值,而所有的对其他对象的引用仍然只指向原来的对象,换言之,浅复制仅仅复制锁考虑的对象,而不复制它所引用的对象。

public class Student implements Cloneable{
         String name;
         int age;
     Student(String name,int age){
          this.name=name;
          this.age=age;
     }
     
     public Object clone(){
          Object o =null;
          try{
           o=super.clone();//Object中的clone()识别出你要复制的哪一个对象
          }
          catch(CloneNotSupportedException e){
           System.out.println(e.toString());
          }
          return o;
     }
 
 public static void main(String[] args){
      Student s1 = new Student("zhang",18);
      Student s2 = (Student)s1.clone();
      s2.name="li";
      s2.age=20;
      System.out.println("name="+s1.name+","+"age="+s1.age);//修改学生2后不影响学生1的值
   }
}


2.2    对象深拷贝
深复制(深克隆)被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量,那些引用其他对象的变量将指向被复制过的新对象,而不再试原有的那些被引用的对象,换言之,深复制把要复制的对象所引用的对象都复制了一遍。
把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做“解冻”或者“回鲜(depicking)”过程。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
public Object deepClone()
{
 //将对象写到流里
     ByteArrayOutoutStream bo=new ByteArrayOutputStream();
     ObjectOutputStream oo=new ObjectOutputStream(bo);
     oo.writeObject(this);
     //从流里读出来
     ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
     ObjectInputStream oi=new ObjectInputStream(bi);
     return(oi.readObject());
}

 

====================默认值==============================================

PS:成员变量有默认值,而局部变量没有默认值

===================Mysql======================================

1. select * from student where sage is null;

===============存储过程======================

存储过程特点

                                     1)执行效率非常快!存储过程是在数据库的服务器端执行的!!!

                                     2)移植性很差!不同数据库的存储过程是不能移植。

DELIMITER $       -- 声明存储过程的结束符
CREATE PROCEDURE pro_test()           --存储过程名称(参数列表)
BEGIN             -- 开始
    -- 可以写多个sql语句;          -- sql语句+流程控制
    SELECT * FROM employee;
END $            -- 结束 结束符

-- 执行存储过程
CALL pro_test();          -- CALL 存储过程名称(参数);

参数:

IN:   表示输入参数,可以携带数据带存储过程中

OUT: 表示输出参数,可以从存储过程中返回结果

INOUT: 表示输入输出参数,既可以输入功能,也可以输出功能

PS: SQL

为什么要优化:
     随着实际项目的启动,数据库经过一段时间的运行,最初的数据库设置,会与实际数据库运行性能会有一些差异,这时我们         就需要做一个优化调整。

数据库优化这个课题较大,可分为四大类:
       》主机性能
       》内存使用性能
       》网络传输性能
       》SQL语句执行性能【软件工程师】


下面列出一些数据库SQL优化方案:


(01)选择最有效率的表名顺序(笔试常考) 
      数据库的解析器按照从右到左的顺序处理FROM子句中的表名, 
      FROM子句中写在最后的表将被最先处理,
      在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表放在最后,
      如果有3个以上的表连接查询,那就需要选择那个被其他表所引用的表放在最后。
      例如:查询员工的编号,姓名,工资,工资等级,部门名
      select emp.empno,emp.ename,emp.sal,salgrade.grade,dept.dname
      from salgrade,dept,emp
      where (emp.deptno = dept.deptno) and (emp.sal between salgrade.losal and salgrade.hisal)          
      1)如果三个表是完全无关系的话,将记录和列名最少的表,写在最后,然后依次类推
      2)如果三个表是有关系的话,将引用最多的表,放在最后,然后依次类推


(02)WHERE子句中的连接顺序(笔试常考)  
      数据库采用自右而左的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之左,
      那些可以过滤掉最大数量记录的条件必须写在WHERE子句的之右。  
      例如:查询员工的编号,姓名,工资,部门名  
      select emp.empno,emp.ename,emp.sal,dept.dname
      from emp,dept
      where (emp.deptno = dept.deptno) and (emp.sal > 1500)   
      
(03)SELECT子句中避免使用*号
      数据库在解析的过程中,会将*依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间
      select empno,ename from emp;

(04)用TRUNCATE替代DELETE
   
(05)尽量多使用COMMIT
      因为COMMIT会释放回滚点

(06)用WHERE子句替换HAVING子句
      WHERE先执行,HAVING后执行
     
(07)多使用内部函数提高SQL效率
     
(08)使用表的别名
      salgrade s
     
(09)使用列的别名
      ename e
    
总之,数据库优化不是一天的课题,你得在长期工作实践中,进行反复测试与总结,希望学员们日后好好领会

 

-------------------------------------JDBC就是发送sql语句的技术--------------------------------------------------------------

2.4 JDBC接口核心的API

                                     java.sql.*   和  javax.sql.*

 

                            |- Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商要来实现此接口。

                                     |- connect(url, properties):  连接数据库的方法。

                                                        url: 连接数据库的URL

                                                                 URL语法: jdbc协议:数据库子协议://主机:端口/数据库

                                                                 user: 数据库的用户名

                                                                 password: 数据库用户密码

                            |- DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序

                                     |-registerDriver(driver)  : 注册驱动类对象

                                     |-Connection getConnection(url,user,password);  获取连接对象

 

                            |- Connection接口: 表示java程序和数据库的连接对象。

                                               |- Statement createStatement() : 创建Statement对象

                                               |- PreparedStatement prepareStatement(String sql)  创建PreparedStatement对象

                                               |- CallableStatement prepareCall(String sql) 创建CallableStatement对象

 

                            |- Statement接口: 用于执行静态的sql语句

                                               |- int executeUpdate(String sql)  : 执行静态的更新sql语句(DDL,DML)

                                               |- ResultSet executeQuery(String sql)  :执行的静态的查询sql语句(DQL)

 

                                     |-PreparedStatement接口:用于执行预编译sql语句

                                                        |- int executeUpdate() : 执行预编译的更新sql语句(DDL,DML)

                                                        |-ResultSet executeQuery()  : 执行预编译的查询sql语句(DQL)

 

                                               |-CallableStatement接口:用于执行存储过程的sql语句(call xxx)

                                                                 |-ResultSet executeQuery()  : 调用存储过程的方法

 

 

                            |- ResultSet接口:用于封装查询出来的数据

                                               |- boolean next() : 将光标移动到下一行

                                               |-getXX() : 获取列的值

-------------------------------------------------------

 

1. 注意:静态方法不可以使用中定义的泛型

因为类中的泛型需要在对象初始化时指定具体的类型,而静态优先于对象存在。那么类中的静态方法就需要单独进行泛型声明,声明泛型一定要写在static后,返回值类型之前

2. 反射麻烦--》内省麻烦-》BeanUtil

开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。

 sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils。

3. 路径

a.在Eclipse中,当前路径是工程的根目录

b  classpath路径

1.1.1.    classpath路径说明

在Java程序中,一般情况下使用绝对路径还是相对路径都不太合适,因为Java程序的jar包所放的位置不确定,执行java程序时当前的路径也不确定,所以不合适。一般在Java程序中我们会把资源放到classpath中,然后使用classpath路径查找资源。

 

Classpath路径:就是使用classpath目前的路径。

1.1.2.    获取classpath中的资源(InputStream)

public static void main(String[] args) throws Exception {
    Class clazz = new ClassPathTest().getClass();
    
    // 开头的'/'表示classpath的根目录,这个是表示从classpath的根目录中开始查找资源
    InputStream in = clazz.getResourceAsStream("/cn/itcast/my.properties");

    // 如果开头没有'/',表示从当前这个class所在的包中开始查找
    InputStream in2 = clazz.getResourceAsStream("my.properties");
}

---------------------------JavaScript---------------------------------

PS:isNaN()判断是否是一个数字

3. XML

4.2 XML解析方式(原理不同)

                            DOM解析

Domj4读取xml文件
                节点:
                    Iterator  Element.nodeIterator();  //获取当前标签节点下的所有子节点(不包含孙节点)

                标签:
                      Element  Document.getRootElement();  //获取xml文档的根标签        
                     Element   ELement.element("标签名") //指定名称的第一个子标签
                      Iterator<Element> Element.elementIterator("标签名");// 指定名称的所有子标签
                        List<Element>     Element.elements(); //获取所有子标签
                        
                属性:
                    String   Element.attributeValue("属性名") //获取指定名称的属性值
                     Attribute    Element.attribute("属性名");//获取指定名称的属性对象    
                            Attribute.getName()  //获取属性名称
                            Attibute.getValue()  //获取属性值
                        List<Attribute>     Element.attributes();  //获取所有属性对象
                        Iterator<Attribute>        Element.attibuteIterator(); //获取所有属性对象

                文本:
                            Element.getText();  //获取当前标签的文本
                            Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容
2 Dom4j修改xml文档
        2.1 写出内容到xml文档
                XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
                wirter.write(Document);

        2.2 修改xml文档的API
            增加: 
                    DocumentHelper.createDocument()  增加文档
                    addElement("名称")  增加标签
                    addAttribute("名称",“值”)  增加属性
            修改:
                    Attribute.setValue("值")  修改属性值
                    Element.addAtribute("同名的属性名","值")  修改同名的属性值
                    Element.setText("内容")  修改文本内容
            删除
                    Element.detach();  删除标签  
                    Attribute.detach();  删除属性

 

                            SAX解析

总结:
                1)Dom4j修改xml文档
                     new XMLWrier();
                        ......
                2)xPath技术: 快速查询xml节点
                        selectNodes()
                        selectSinglNode();
                    xpath表达式语言        
                3)  SAX解析
                        SAXParser parse
                            parser()
                    DefaultHandler类:
                            startElement();
                            characters();
                            endElement();

 

4.3 XML解析工具

                                     DOM解析原理:

                                                        1)JAXP (oracle-Sun公司官方)

                                                        2)JDOM工具(非官方)

                                                        3)Dom4J工具(非官方)

                                                                 三大框架(默认读取xml的工具就是Dom4j)

                                                        .......

 

                                     SAX解析原理:

                                                        1)Sax解析工具(oracle-sun公司官方)

===================================

DOM解析原理:一次性把xml文档加载进内存,然后在内存中构建Document树。  对内存要求比较要。    

                              缺点: 不适合读取大容量的xml文件,容易导致内存溢出。

SAX解析原理: 加载一点,读取一点,处理一点。对内存要求比较低。

============DOM解析    vs   SAX解析               ========

        

DOM解析

SAX解析

原理: 一次性加载xml文档,不适合大容量的文件读取

原理: 加载一点,读取一点,处理一点。适合大容量文件的读取

DOM解析可以任意进行增删改成

SAX解析只能读取

DOM解析任意读取任何位置的数据,甚至往回读

SAX解析只能从上往下,按顺序读取,不能往回读

DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。

SAX解析基于事件的编程方法。java开发编码相对复杂。

 

=============

 5.常见的市面上web服务软件

                                          javase的规范,包含IO流,线程,集合,socket编程。。。。

                                     WebLogic: BEA公司的产品。 收费的。支持JavaEE规范。

                                     WebSphere: IBM公司的产品。收费的。支持JavaEE规范

                                     JBoss: Redhat公司的产品。收费的。支持JavaEE规范

                                     Tomcat: 开源组织Apache的产品。免费的。支持部分的JavaEE规范。(servlet、jsp。jdbc,但        ejb, rmi不支持)

 

==============

Web应用的目录结构

                   |- WebRoot :   web应用的根目录

                                     |- 静态资源(html+css+js+image+vedio)
                                     |- WEB-INF : 固定写法。

                                               |-classes: (可选)固定写法。存放class字节码文件

                                               |-lib: (可选)固定写法。存放jar包文件。

                                               |-web.xml   

注意:

                            1)WEB-INF目录里面的资源不能通过浏览器直接访问

                            2)如果希望访问到WEB-INF里面的资源,就必须把资源配置到一个叫web.xml的文件中。

====================================

6.HTTP

HttpServletResponse她也是一个对象,封装响应的信息。

PS:也就是请求和响应是在一起执行的

 HTTP请求

1)GET方式提交

                                               a)地址栏(URI)会跟上参数数据。以?开头,多个参数之间以&分割。

GET /day09/testMethod.html?name=eric&password=123456 HTTP/1.1

Host: localhost:8080

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3

Accept-Encoding: gzip, deflate

Referer: http://localhost:8080/day09/testMethod.html

Connection: keep-alive

 

                                               b)GET提交参数数据有限制,不超过1KB。

                                               c)GET方式不适合提交敏感密码。

                                               d)注意: 浏览器直接访问的请求,默认提交方式是GET方式

                            2)POST方式提交

                                     a)参数不会跟着URI后面。参数而是跟在请求的实体内容中。没有?开头,多个参数之间以&分割。

POST /day09/testMethod.html HTTP/1.1

Host: localhost:8080

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3

Accept-Encoding: gzip, deflate

Referer: http://localhost:8080/day09/testMethod.html

Connection: keep-alive

 

name=eric&password=123456

 

                                               b)POST提交的参数数据没有限制。

                                               c)POST方式提交敏感数据。

===============================================================================

7.servlet 初始化  : 构造函数-》init-》service-》destory

 Servlet的自动加载

                            默认情况下,第一次访问servlet的时候创建servlet对象。如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么导致用户第一次访问sevrlet的时候比较慢。

 

                            改变servlet创建对象的时机: 提前到加载web应用的时候!!!

 

                            在servlet的配置信息中,加上一个<load-on-startup>即可!!

                  

<servlet>

    <servlet-name>LifeDemo</servlet-name>

    <servlet-class>gz.itcast.c_life.LifeDemo</servlet-class>

    <!-- 让servlet对象自动加载 -->

    <load-on-startup>1</load-on-startup>  注意: 整数值越大,创建优先级越低!!

  </servlet>

 

ServletConfig对象

                     9.1 作用

                            ServletConfig对象: 主要是用于加载servlet的初始化参数。在一个web应用可以存在多个ServletConfig对象(一个Servlet对应一个ServletConfig对象)

ServletContext对象

                     10.1 引入

                   ServletContext对象 ,叫做Servlet的上下文对象。表示一个当前的web应用环境。一个web应用中只有一                                                           个ServletContext对象。

                     10.2 对象创建和得到

                            创建时机:加载web应用时创建ServletContext对象。

                            得到对象: 从ServletConfig对象的getServletContext方法得到

====================================================================

软件中的会话

                   一次会话: 打开浏览器 -> 访问一些服务器内容 -> 关闭浏览器

 

3.4 Cookie的细节
            1)void setPath(java.lang.String uri)   :
设置cookie的有效访问路径。有效路径指的是cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器时就会带着cookie信息,否则不带cookie信息。
2)void setMaxAge(int expiry) : 设置cookie的有效时间。 正整数:表示cookie数据保存浏览器的缓存目录(硬盘中),数值表示保存的时间。 负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!! 零:表示删除同名的cookie数据 3)Cookie数据类型只能保存非中文字符串类型的。可以保存多个cookie,但是浏览器一般只允许存放300个Cookie,
每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。

Cookie的局限:

                                     1)Cookie只能存字符串类型。不能保存对象

                                     2)只能存非中文。

                                     3)1个Cookie的容量不超过4KB。

 

                            如果要保存非字符串,超过4kb内容,只能使用session技术!!!

 
总结:
                1)会话管理: 浏览器和服务器会话过程中的产生的会话数据的管理。

                2)Cookie技术:
                        new Cookie("name","value")
                        response.addCookie(coookie)
                        request.getCookies()
                3)Session技术
                        request.getSession();
                        
                        setAttrbute("name","会话数据");
                        getAttribute("会话数据")

===================Web加载资源

 

 

 

    4.4 Sesson细节
            1)java.lang.String getId()  : 得到session编号
            2)两个getSession方法:
                    getSession(true) / getSession()  : 创建或得到session对象。没有匹配的session编号,自动创建新的session对象。
                    getSession(false):              得到session对象。没有匹配的session编号,返回null
            3)void setMaxInactiveInterval(int interval)  : 设置session的有效时间
                        session对象销毁时间:
                            3.1 默认情况30分服务器自动回收
                            3.2 修改session回收时间
                            3.3 全局修改session有效时间

 

 

 

8.JSP

 Jsp的执行过程

                            问题: 访问http://localhost:8080/day12/01.hello.jsp  如何显示效果?

 

                            1)访问到01.hello.jsp页面,tomcat扫描到jsp文件,在%tomcat%/work把jsp文件翻译成java源文件

                                                        (01.hello.jsp   ->   _01_hello_jsp.java) (翻译)

                            2)tomcat服务器把java源文件编译成class字节码文件 (编译)

                                               (_01_hello_jsp.java  ->  _01_hello_jsp.class)

                            3)tomcat服务器构造_01_hello_jsp类对象

                            4)tomcat服务器调用_01_hello_jsp类里面方法,返回内容显示到浏览器。

第一次访问jsp:

                                     走(1)(2)(3)(4)

         第n次访问jsp:

                                     走(4)

        

注意:

                            1)jsp文件修改了或jsp的临时文件被删除了,要重新走翻译(1)和编译(2)的过程

===================================

为什么Jsp就是servlet!!!  因为Jsp继承字HttpServlet

                            jsp翻译的java文件:

                                     public final class _01_hello_jsp extends org.apache.jasper.runtime.HttpJspBase

    implements org.apache.jasper.runtime.JspSourceDependent {

 

                                     HttpJspBase类:

                            public abstract class org.apache.jasper.runtime.HttpJspBase extends javax.servlet.http.HttpServlet implements javax.servlet.jsp.HttpJspPage {

 

                     结论: Jsp就是一个servlet程序!!!

                            servlet的技术可以用在jsp程序中

                            jsp的技术并不是全部适用于servlet程序!

 

                    

                     Servlet的生命周期:

                                   1)构造方法(第1次访问)

                                   2)init方法(第1次访问)

                                   3)service方法

                                   4)destroy方法           

                     Jsp的生命周期

                                   1)翻译: jsp->java文件

                                   2)编译: java文件->class文件(servlet程序)

                                   3)构造方法(第1次访问)

                                   4)init方法(第1次访问):_jspInit()

                                   5)service方法:_jspService()

                                   6)destroy方法:_jspDestroy()

 =================Struts======================

PS:struts其实也是servlet封装,提高开发效率!

也可以说,Struts2 = struts1  +  xwork

Struts2执行流程

服务器启动:

         1. 加载项目web.xml

         2. 创建Struts核心过滤器对象, 执行filter à  init()

                   struts-default.xml,    核心功能的初始化

struts-plugin.xml,     struts相关插件

struts.xml                        用户编写的配置文件

 

访问:

         3. 用户访问Action, 服务器根据访问路径名称,找对应的aciton配置, 创建action对象

         4. 执行默认拦截器栈中定义的18个拦截器

         5. 执行action的业务处理方法

 

 

 

-----------------------------------------------------------------

拦截器(先睹为快):

         拦截器功能与过滤器功能类似。

         区别:

                   共同点: 都拦截资源!

                   区别:

                            过滤器,拦截器所有资源都可以;  (/index.jsp/servlet/img/css/js)

                            拦截器,只拦截action请求。

                           

                            拦截器是struts的概念,只能在struts中用。

                            过滤器是servlet的概念,可以在struts项目、servlet项目用。

 

 

// 面试题: 拦截器什么时候执行? (访问/启动)  先执行action类创建,先执行拦截器?

         // --》 1. 用户访问时候按顺序执行18个拦截器;

         //---》 2. 先执行Action类的创建,再执行拦截器; 最后拦截器执行完,再执行业务方法

 =============================================================

 

PS:如果没有.action,不做处理。

================值栈==================

 

 

=====================拦截器===================

拦截器

1.1 概述

ü  基本概念

Intercetor, 即为拦截器。

1) 在Struts2中,把每一个功能都用一个个的拦截器实现;用户想用struts的哪个功能的时候,可以自由组装使用。

2)Struts2中,为了方法用户对拦截器的引用,提供了拦截器栈的定义,里面可以包含多个拦截器。   文件夹(文件, 文件2)  拦截器栈(拦截器,拦截器2)

3)Struts2中,如果用户没有指定执行哪些拦截器,struts2有一个默认执行的栈,defaultStack;

            一旦如果用户有指定执行哪些拦截器,默认的拦截器栈就不会被执行

 

拦截器的设计,就是基于组件设计的应用!

 ===================Hibernate===================================

 

Hibernate  Api

|-- Configuration       配置管理类对象

         config.configure();    加载主配置文件的方法(hibernate.cfg.xml)

                                                        默认加载src/hibernate.cfg.xml

         config.configure(“cn/config/hibernate.cfg.xml”);   加载指定路径下指定名称的主配置文件

         config.buildSessionFactory();   创建session的工厂对象

 

|-- SessionFactory     session的工厂(或者说代表了这个hibernate.cfg.xml配置文件)

         sf.openSession();   创建一个sesison对象

         sf.getCurrentSession();  创建session或取出session对象

 

|--Session       session对象维护了一个连接(Connection), 代表了与数据库连接的会话。

                               Hibernate最重要的对象: 只用使用hibernate与数据库操作,都用到这个对象

                   session.beginTransaction(); 开启一个事务; hibernate要求所有的与数据库的操作必须有事务的环境,否则报错!

 

=========================对象的状态==========================================

 

对象的状态

举例: User   user   = new User();

 

Hibernate中对象的状态: 临时/瞬时状态、持久化状态、游离状态。

ü  临时状态

特点:

直接new出来的对象; 

不处于session的管理;

数据库中没有对象的记录;

ü  持久化状态

当调用session的save/saveOrUpdate/get/load/list等方法的时候,对象就是持久化状态。

处于持久化状态的对象,当对对象属性进行更改的时候,会反映到数据库中!

特点:

处于session的管理;

数据库中有对应的记录;

ü  游离状态

特点

             不处于session的管理;

                   数据库中有对应的记录

                   Session关闭后,对象的状态;

=================一级缓存=======================================

二、一级缓存

为什么要用缓存?

         目的:减少对数据库的访问次数!从而提升hibernate的执行效率!

Hibernate中缓存分类:

         一级缓存

         二级缓存

 

ü  概念

1)Hibenate中一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数!  只在session范围有效! Session关闭,一级缓存失效!

2)当调用sessionsave/saveOrUpdate/get/load/list/iterator方法的时候,都会把对象放入session的缓存中。

3)Session的缓存由hibernate维护, 用户不能操作缓存内容; 如果想操作缓存内容,必须通过hibernate提供的evit/clear方法操作。

特点:

         只在(当前)session范围有效,作用时间短,效果不是特别明显!

         在短时间内多次操作数据库,效果比较明显!

 

ü  缓存相关几个方法的作用

session.flush();       让一级缓存与数据库同步

                   session.evict(arg0);    清空一级缓存中指定的对象

                   session.clear();       清空一级缓存中缓存的所有对象

 

在什么情况用上面方法?

                   批量操作使用使用:

                             Session.flush();   // 先与数据库同步

                             Session.clear();   // 再清空一级缓存内容

=================懒加载=================================

三、懒加载

ü  面试题3: get、load方法区别?

get: 及时加载,只要调用get方法立刻向数据库查询

load:默认使用懒加载,当用到数据的时候才向数据库查询。

 

ü  懒加载:(lazy)

概念:当用到数据的时候才向数据库查询,这就是hibernate的懒加载特性。

                   目的:提供程序执行效率!

ü  lazy 值

         true   使用懒加载

         false   关闭懒加载

         extra   (在集合数据懒加载时候提升效率)

在真正使用数据的时候才向数据库发送查询的sql;

如果调用集合的size()/isEmpty()方法,只是统计,不真正查询数据!

                           

 

ü  懒加载异常

n  Session关闭后,不能使用懒加载数据!

n  如果session关闭后,使用懒加载数据报错:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

                   如何解决session关闭后不能使用懒加载数据的问题?

                            // 方式1: 先使用一下数据

                   //dept.getDeptName();

                  // 方式2:强迫代理对象初始化

                   Hibernate.initialize(dept);

                  // 方式3:关闭懒加载

                            设置lazy=false;

                   // 方式4在使用数据之后,再关闭session

========================二级缓存==============================================

三、二级缓存

Hibernate提供的缓存

         有一级缓存、二级缓存。 目的是为了减少对数据库的访问次数,提升程序执行效率!

 

一级缓存:

         基于Session的缓存,缓存内容只在当前session有效,session关闭,缓存内容失效!

         特点:

                   作用范围较小! 缓存的事件短。

                   缓存效果不明显。

概述

二级缓存:

         Hibernate提供了基于应用程序级别的缓存, 可以跨多个session,即不同的session都可以访问缓存数据。 这个换存也叫二级缓存。

         Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!如果用户想用二级缓存,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影响代码。

         如果用户觉得hibernate提供的框架框架不好用,自己可以换其他的缓存框架或自己实现缓存框架都可以

===============================Spring============================================

Spring框架

2.1 专业术语了解

PS:依赖注入和控制反转其实是一个概念

 

 

 

组件/框架设计

侵入式设计

                   引入了框架,对现有的类的结构有影响;即需要实现或继承某些特定类。

                   例如:     Struts框架

非侵入式设计

         引入了框架,对现有的类结构没有影响。

         例如:Hibernate框架 / Spring框架

控制反转:

         Inversion on Control , 控制反转 IOC

         对象的创建交给外部容器完成,这个就做控制反转.

        

         依赖注入,  dependency injection

                   处理对象的依赖关系

 

         区别:

   控制反转, 解决对象创建的问题 【对象创建交给别人】

         依赖注入,

                   在创建完对象后, 对象的关系的处理就是依赖注入 【通过set方法依赖注入】

AOP

         面向切面编程。切面,简单来说来可以理解为一个类,由很多重复代码形成的类。

         切面举例:事务、日志、权限;

============================================================

PS:使用注解解决依赖注入的问题。

===================================================

 

========================代理===============================

在Spring的AOP编程中,
    如果加入容器的目标对象有实现接口,用JDK代理;
    如果目标对象没有实现接口,用Cglib代理;

 

静态代理,

         1) 代理对象,要实现与目标对象一样的接口;

动态代理,

         1)代理对象,不需要实现接口;

         2)代理对象的生成,是利用JDKAPI, 动态的在内存中构建代理对象(需要我们指定创建 代理对象/目标对象 实现的接口的类型;);

         3)  动态代理, JDK代理, 接口代理;

Cglib代理,也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。

========================AOP====================================

Aop  aspect object programming  面向切面编程

         功能: 让关注点代码与业务代码分离!

关注点,

         重复代码就叫做关注点;

切面,

          关注点形成的类,就叫切面(类)!

          面向切面编程,就是指 对很多功能都有的重复的代码抽取,再在运行的时候网业务方法上动态植入“切面类代码”。

切入点,

         执行目标对象方法,动态植入切面代码。

         可以通过切入点表达式,指定拦截哪些类的哪些方法; 给指定的类在运行的时候植入切面类代码。

 

========================事务的控制================================

编程式事务控制

         自己手动控制事务,就叫做编程式事务控制。

         Jdbc代码:

                   Conn.setAutoCommite(false);  // 设置手动控制事务

         Hibernate代码:

                   Session.beginTransaction();    // 开启一个事务

         【细粒度的事务控制: 可以对指定的方法、指定的方法的某几行添加事务控制】

         (比较灵活,但开发起来比较繁琐: 每次都要开启、提交、回滚.)

 

声明式事务控制

         Spring提供了对事务的管理, 这个就叫声明式事务管理。

         Spring提供了对事务控制的实现。用户如果想用Spring的声明式事务管理,只需要在配置文件中配置即可; 不想使用时直接移除配置。这个实现了对事务控制的最大程度的解耦。

         Spring声明式事务管理,核心实现就是基于Aop。

         【粗粒度的事务控制: 只能给整个方法应用事务,不可以对方法的某几行应用事务。】

         (因为aop拦截的是方法。)

 

         Spring声明式事务管理器类:

                   Jdbc技术:DataSourceTransactionManager

                   Hibernate技术:HibernateTransactionManager

=============================事物的属性==================================================

 

介绍事务的属性: http://blog.sina.com.cn/s/blog_4b5bc0110100z7jr.html

介绍事物:http://www.cnblogs.com/fjdingsd/p/5273008.html

=========================SpringMVC====================================

PS:DispatcherServlet是选择并决定将要发送给哪个控制器

 

 

 

PS:SpringMVC是spring的后续产品

 

============================================

springmvcstruts2的区别

1)springmvc的入口是一个servlet,即前端控制器,例如:*.action

   struts2入口是一个filter过虑器,即前端过滤器,例如:/*

2)springmvc是基于方法开发,传递参数是通过方法形参,可以设计为单例

   struts2是基于类开发,传递参数是通过类的属性,只能设计为多例

3)springmvc通过参数解析器是将request对象内容进行解析成方法形参,将响应数据和页面封装成

   ModelAndView对象,最后又将模型数据通过request对象传输到页面

struts采用值栈存储请求和响应的数据,通过OGNL存取数据

====================MyBatis工作流程==========================

 mybatis工作流程

1)通过Reader对象读取src目录下的mybatis.xml配置文件(该文本的位置和名字可任意)

2)通过SqlSessionFactoryBuilder对象创建SqlSessionFactory对象

3)从当前线程中获取SqlSession对象

4)事务开始,在mybatis中默认

5)通过SqlSession对象读取StudentMapper.xml映射文件中的操作编号,从而读取sql语句

6)事务提交,必写

7)关闭SqlSession对象,并且分开当前线程与SqlSession对象,让GC尽早回收

 

SpringAOP编程中,

         如果加入容器的目标对象有实现接口,用JDK代理;

         如果目标对象没有实现接口,用Cglib代理;

posted on 2017-09-20 17:23  biyangqiang  阅读(245)  评论(0编辑  收藏  举报

导航