面试指南(全部内容取自网络,侵删)

面试总结

1. Collection集合接口

1.1 Collection接口

是最基本的接口,派生了两个子接口Set和List前端

1.2 Set接口

无序且不可重复java

1.2.1 HashSet接口

基于HashMap实现,全部元素都是保存在HashMap的key中,而value中保存了PRESENT。程序员

1.3 List接口

有序且可重复web

1.3.1 ArrayList,LinkedList接口(线程不安全)

总结面试

  • ArrayList内部结构是数组(Array),查找高效,修改低效。
  • LinkedList接口内部是链表Linked,查找低效,修改高效
  • ArrayList特色是有序可重复的,实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
  • ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,因此最大的缺点就是插入删除时很是麻烦
  • LinkedList 采用的将对象存放在独立的空间中,并且在每一个空间中还保存下一个连接的索引,可是缺点就是查找很是麻烦 要丛第一个索引开始
  • 对于随机访问get和set,ArrayList以为优于LinkedList,由于LinkedList要移动指针。
  • 对于新增和删除操做add和remove,LinedList比较占优点,由于ArrayList要移动数据。
  • 在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动。
  • ArrayList更适合读取数据,linkedList更多的时候添加或删除数据。

2. Map接口

Map也是接口,但没有继承Collection接口。该接口描述了从不重复的键到值的映射。Map接口用于维护键/值对算法

2.1HashMap(线程不一样步)(Hashtable为线程安全)

基于哈希表实现,特色就是键值对的映射关系。一个key对应一个Value。HashMap中元素的排列顺序是不固定的。更加适合于对元素进行插入、删除和定位。spring

2.1.1 HashMap和Hashtable的区别

HashMap和Hashtable都实现了Map接口,但决定用哪个以前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。sql

  • HashMap几乎能够等价于Hashtable,除了HashMap是非synchronized的,并能够接受null(HashMap能够接受为null的键值(key)和值(value),而Hashtable则不行)。
  • HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程能够共享一个Hashtable;而若是没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
  • 另外一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。因此当有其它线程改变了HashMap的结构(增长或者移除元素),将会抛出ConcurrentModificationException,但迭代器自己的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并非一个必定发生的行为,要看JVM。这条一样也是Enumeration和Iterator的区别。
  • 因为Hashtable是线程安全的也是synchronized,因此在单线程环境下它比HashMap要慢。若是你不须要同步,只须要单一线程,那么使用HashMap性能要好过Hashtable。
  • HashMap不能保证随着时间的推移Map中的元素次序是不变的。

2.1.2 让HashMap同步

Map m = Collections.synchronizeMap(hashMap);数据库

2.2 TreeMap(线程不一样步)

基于红黑树实现。TreeMap中的元素保持着某种固定的顺序。更加适合于对元素的顺序遍历。编程

3. 迭代器(Iterator和加强for循环)

迭代器是一种模式,它可使得对于序列类型的数据结构的遍历行为与被遍历的对象分离

3.1 Iterator

Iterator对集合类中的任何一个实现类,均可以返回这样一个Iterator对象。能够适用于任何一个类。
由于集合类(List和Set等)能够装入的对象的类型是不肯定的,从集合中取出时都是Object类型,用时都须要进行强制转化,这样会很麻烦,用上泛型,就是提早告诉集合肯定要装入集合的类型,这样就能够直接使用而不用显示类型转换.很是方便.

3.2 foreach

优点在于更加简洁,更不容易出错,没必要关心下标的起始值和终止值

forEach不是关键字,关键字仍是for,语句是由iterator实现的,他们最大的不一样之处就在于remove()方法上
若是在循环的过程当中调用集合的remove()方法,就会致使循环出错,由于循环过程当中list.size()的大小变化了,就致使了错误。 因此,若是想在循环语句中删除集合中的某个元素,就要用迭代器iterator的remove()方法,由于它的remove()方法不只会删除元素,还会维护一个标志,用来记录目前是否是可删除状态,例如,你不能连续两次调用它的remove()方法,调用以前至少有一次next()方法的调用。

3.3 区别

  • 采用ArrayList对随机访问比较快,而for循环中的get()方法,采用的便是随机访问的方法,所以在ArrayList里,for循环较快
  • 采用LinkedList则是顺序访问比较快,iterator中的next()方法,采用的便是顺序访问的方法,所以在LinkedList里,使用iterator较快
  • 从数据结构角度分析,for循环适合访问顺序结构,能够根据下标快速获取指定元素.而Iterator 适合访问链式结构,由于迭代器是经过next()和Pre()来定位的.能够访问没有顺序的集合.
  • 而使用 Iterator 的好处在于可使用相同方式去遍历集合中元素,而不用考虑集合类的内部实现(只要它实现了 java.lang.Iterable 接口),若是使用 Iterator 来遍历集合中元素,一旦再也不使用 List 转而使用 Set 来组织数据,那遍历元素的代码不用作任何修改,若是使用 for 来遍历,那全部遍历此集合的算法都得作相应调整,由于List有序,Set无序,结构不一样,他们的访问算法也不同.
  • map接口没有迭代器,能够Set keySet() :获取到全部的键,存储到一个Set集合中,并返回该集合,由于Set有迭代器,每次迭代出来的是一个键,再根据键来获得值。

4. String与StringBuffer

简单地说,就是一个变量和常量的关系。StringBuffer对象的内容能够修改;而String对象一旦产生后就不能够被修改,从新赋值实际上是两个对象

4.1 String

在String类中没有用来改变已有字符串中的某个字符的方法,因为不能改变一个Java字符串中的某个单独字符,因此在JDK文档中称String类的对象是不可改变的。然而,不可改变的字符串具备一个很大的优势:编译器能够把字符串设为共享的。

是对象不是原始类型.
为不可变对象,一旦被建立,就不能修改它的值.
对于已经存在的String对象的修改都是从新建立一个新的对象,而后把新的值保存进去.
String 是final类,即不能被继承.

4.2 StringBuffer

是一个可变对象,当对他进行修改的时候不会像String那样从新创建对象
它只能经过构造函数来创建,
StringBuffer sb = new StringBuffer();
注意:不能经过赋值符号对他进行赋值.
sb = "welcome to here!";//error
对象被创建之后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer
中赋值的时候能够经过它的append方法.
sb.append("hello");

可预先分配指定长度的内存块创建一个字符串缓冲区。这样使用StringBuffer类的append方法追加字符 比 String使用 + 操做符添加字符 到 一个已经存在的字符串后面有效率得多。由于使用 + 操做符每一次将字符添加到一个字符串中去时,字符串对象都须要寻找一个新的内存空间来容纳更大的字符串,这无凝是一个很是消耗时间的操做。添加多个字符也就意味着要一次又一次的对字符串从新分配内存。使用StringBuffer类就避免了这个问题。

4.3区别

  • 三者在执行速度方面的比较:StringBuilder > StringBuffer > String
  • StringBuilder:线程非安全的;StringBuffer:线程安全的
  • 若是要操做少许的数据用 = String;单线程操做字符串缓冲区 下操做大量数据 = StringBuilder;多线程操做字符串缓冲区 下操做大量数据 = StringBuffer
  • 若是常常须要对一个字符串进行修改,例如插入、删除等操做,使用StringBuffer要更加适合一些。

5. 线程

5.1 进程和线程的区别

  • 进程:每一个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。

  • 线程:同一类线程共享代码和数据空间,每一个线程有独立的运行栈和程序计数器(PC),线程切换开销小。

  • 线程和进程同样分为五个阶段:建立、就绪、运行、阻塞、终止。

  • 多进程是指操做系统能同时运行多个任务(程序)。

  • 多线程是指在同一程序中有多个顺序流在执行。

线程

5.2 五种状态(生命周期)

  • 新建状态(New):当线程对象对建立后,即进入了新建状态,如:Thread t = new MyThread();

  • 就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经作好了准备,随时等待CPU调度执行,并非说执行了t.start()此线程当即就会执行;

  • 运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的惟一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

  • 阻塞状态(Blocked):处于运行状态中的线程因为某种缘由,暂时放弃对CPU的使用权,中止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的缘由不一样,阻塞状态又能够分为三种:

  • 1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

  • 2.同步阻塞 -- 线程在获取synchronized同步锁失败(由于锁被其它线程所占用),它会进入同步阻塞状态;

  • 3.其余阻塞 -- 经过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程从新转入就绪状态。

  • 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

5.2 实现方法

一种是继承Thread类,另一种是实现Runable接口

5.2.1 扩展java.lang.Thread类

class MyThread extends Thread { 
         private int i = 0;
         @Override
         public void run() {
             for (i = 0; i < 100; i++) {
                 System.out.println(Thread.currentThread().getName() + " " + i);
            }
        }
    }
public class ThreadTest {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            if (i == 30) {
                Thread myThread1 = new MyThread();     // 建立一个新的线程  myThread1  此线程进入新建状态
                Thread myThread2 = new MyThread();     // 建立一个新的线程 myThread2 此线程进入新建状态
                myThread1.start();                     // 调用start()方法使得线程进入就绪状态
                myThread2.start();                     // 调用start()方法使得线程进入就绪状态
            }
        }
    }
}

继承Thread类,经过重写run()方法定义了一个新的线程类MyThread,其中run()方法的方法体表明了线程须要完成的任务,称之为线程执行体。当建立此线程类对象时一个新的线程得以建立,并进入到线程新建状态。经过调用线程对象引用的start()方法,使得该线程进入到就绪状态,此时此线程并不必定会立刻得以执行,这取决于CPU调度时机。

5.2.2 实现Runnable接口

class MyRunnable implements Runnable {
    private int i = 0;
    @Override
    public void run() {
        for (i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }
}
public class ThreadTest {

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            if (i == 30) {
                Runnable myRunnable = new MyRunnable(); // 建立一个Runnable实现类的对象
                Thread thread1 = new Thread(myRunnable); // 将myRunnable做为Thread target建立新的线程
                Thread thread2 = new Thread(myRunnable);
                thread1.start(); // 调用start()方法使得线程进入就绪状态
                thread2.start();
            }
        }
    }
}

5.3 线程控制

5.3.1 join()

让一个线程等待另外一个线程完成才继续执行。如A线程线程执行体中调用B线程的join()方法,则A线程被阻塞,知道B线程执行完为止,A才能得以继续执行。

5.3.2 sleep()

让当前的正在执行的线程暂停指定的时间,并进入阻塞状态。在其睡眠的时间段内,该线程因为不是处于就绪状态,所以不会获得执行的机会。即便此时系统中没有任何其余可执行的线程,出于sleep()中的线程也不会执行。所以sleep()方法经常使用来暂停线程执行。

当调用了新建的线程的start()方法后,线程进入到就绪状态,可能会在接下来的某个时间获取CPU时间片得以执行,若是但愿这个新线程必然性的当即执行,直接调用原来线程的sleep(1)便可。

5.3.3 后台线程(Daemon Thread)

后台线程主要是为其余线程(相对能够称之为前台线程)提供服务,或“守护线程”。如JVM中的垃圾回收线程。

生命周期:后台线程的生命周期与前台线程生命周期有必定关联。主要体如今:当全部的前台线程都进入死亡状态时,后台线程会自动死亡

5.3.4改变线程的优先级/setPriority()

每一个线程在执行时都具备必定的优先级,优先级高的线程具备较多的执行机会。每一个线程默认的优先级都与建立它的线程的优先级相同。main线程默认具备普通优先级。

设置线程优先级:setPriority(int priorityLevel)。参数priorityLevel范围在1-10之间

5.3.5 线程让步:yield()

当某个线程调用yiled()方法从运行状态转换到就绪状态后,CPU从就绪状态线程队列中只会选择与该线程优先级相同或优先级更高的线程去执行。

5.4 线程安全

是指多线程环境下对共享资源的访问可能会引发此共享资源的不一致性。所以,为避免线程安全问题,应该避免多线程环境下对此共享资源的并发访问。

5.4.1 同步方法

对共享资源进行访问的方法定义中加上synchronized关键字修饰,使得此方法称为同步方法。能够简单理解成对此方法进行了加锁,其锁对象为当前方法所在的对象自身。多线程环境下,当执行此方法时,首先都要得到此同步锁(且同时最多只有一个线程可以得到),只有当线程执行完此同步方法后,才会释放锁对象,其余的线程才有可能获取此同步锁,以此类推...

public synchronized void run() { }

使用同步方法时,使得整个方法体都成为了同步执行状态,会使得可能出现同步范围过大的状况,因而,针对须要同步的代码能够直接另外一种同步方式——同步代码块来解决。

synchronized (obj) { }

5.5 wait()/notify()/notifyAll()线程通讯

这三个方法主要都是用于多线程中,都是Object类中的本地方法。

在实际的多线程编程中,只有同步锁对象调这三个方法,才能完成对多线程间的线程通讯。

  • wait():致使当前线程等待并使其进入到等待阻塞状态。直到其余线程调用该同步锁对象的notify()或notifyAll()方法来唤醒此线程。

  • notify():唤醒在此同步锁对象上等待的单个线程,若是有多个线程都在此同步锁对象上等待,则会任意选择其中某个线程进行唤醒操做,只有当前线程放弃对同步锁对象的锁定,才可能执行被唤醒的线程。

  • notifyAll():唤醒在此同步锁对象上等待的全部线程,只有当前线程放弃对同步锁对象的锁定,才可能执行被唤醒的线程。

须要注意的是:

  1. wait()方法执行后,当前线程当即进入到等待阻塞状态,其后面的代码不会执行;

  2. notify()/notifyAll()方法执行后,将唤醒此同步锁对象上的(任意一个-notify()/全部-notifyAll())线程对象,可是,此时还并无释放同步锁对象,也就是说,若是notify()/notifyAll()后面还有代码,还会继续进行,知道当前线程执行完毕才会释放同步锁对象;

  3. notify()/notifyAll()执行后,若是右面有sleep()方法,则会使当前线程进入到阻塞状态,可是同步对象锁没有释放,依然本身保留,那么必定时候后仍是会继续执行此线程,接下来同2;

  4. wait()/notify()/nitifyAll()完成线程间的通讯或协做都是基于不一样对象锁的,所以,若是是不一样的同步对象锁将失去意义,同时,同步对象锁最好是与共享资源对象保持一一对应关系;

  5. 当wait线程唤醒后并执行时,是接着上次执行到的wait()方法代码后面继续往下执行的。

5.6 currentThread()

做用就是获得当前线程的对象。

经过currentThread()咱们能够轻易的就获得当前线程的名称,咱们还能够经过线程对象,获得其余的属性。

注意:

currentThread()方法返回的是对当前正在执行的线程对象的引用,this表明的是当前调用它所在函数所属的对象的引用

6 数据库

6.1 存储引擎

MySQL经常使用存储引擎:InnoDB适用于频繁维护修改插入等数据表,MyISAM适合少改写,少插入的频繁读取的表。经常使用InnoDB存储引擎

6.2 事务

Innodb才支持事务

主要是为了解决并发状况下保持数据一致性的问题。

如下4个基本特征:

  • Atomic(原子性):事务中包含的操做被看作一个逻辑单元,这个逻辑单元中的操做要么所有成功,要么所有失败。

  • Consistency(一致性):只有合法的数据能够被写入数据库,不然事务应该将其回滚到最初状态。

  • Isolation(隔离性):事务容许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其余并行事务的修改相互独立。

  • Durability(持久性):事务结束后,事务处理的结果必须可以获得固化。

6.2.1 处理事务

Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务

处理事务:spring的事务是经过“声明式事务”的方式对事务进行管理,即在配置文件中进行声明,经过AOP将事务切面切入程序,最大的好处是大大减小了代码量,提升了工做效率。

6.3 left join、right join、inner join

百度一下

6.4 数据库优化

  1. 减小查询字段数
  2. 表关联尽可能用主键
  3. 查询条件尽可能避免模糊查询
  4. 避免使用排序字段,排序字段尽可能使用主键
  5. 尽可能使用限制查询条件
  6. 查询条件使用有效索引

7 项目相关

7.1 对MVC的理解

MVC是model-view-controler的简称。也就是模型-视图-控制器。mvc是一种设计模式,他强制性的把应用程序的输入、处理和输出分开。mvc中的模型、视图、控制器分别担任着不一样的任务。

视图:视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。

模型:模型表示业务数据和业务处理。至关于javaBean。一个模型能为多个视图提供数据。这提升了应用程序的重用性。

控制器:当用户单击web页面中的提交按钮时,控制器接收请求并调用相应的模型去处理请求。而后根据处理的结果调用相应的视图来显示处理的结构。

MVC的处理过程:首先控制器接收用户的请求,调用相应的模型来进行业务处理,并返回数据给控制器。控制器调用相应的视图来显示处理的结构。并经过视图呈现给用户。如在项目中要对应MVC的话;View对应项目中的jsp,controler对应action,model对应service+dao层的业务逻辑和持久层的操做。

7.2 框架的优势

7.2.1 Hibernate(持久层)

工做原理:

  1. 读取并解析配置文件
  2. 读取并解析映射信息,建立SessionFactory
  3. 打开Session
  4. 建立事务Transaction
  5. 持久化操做
  6. 提交事务
  7. 关闭Session
  8. 关闭SessionFactory

优化:
Hibernate对数据的缓存包括两个级:一级缓存,在Session的级别上进行,主要是对象缓存,以其id为键保存对象,在Session的生命期间存在;二级缓存,在SessionFactory的级别上进行,有对象缓存和查询缓存,查询缓存以查询条件为键保存查询结果,在SessionFactory的生命期间存在,默认地,Hibernate只启用一级缓存

优势:

  1. Hibernate是JDBC的轻量级的对象封装,它是一个独立的对象持久层框架。Hibernate能够用在任何JDBC可使用的场合,例如Java应用程序的数据库访问代码,DAO接口的实现类,甚至能够是BMP里面的访问数据库的代码。

  2. Hibernate是一个和JDBC密切关联的框架,因此Hibernate的兼容性和JDBC驱动,和数据库都有必定的关系,可是和使用它的Java程序,和App Server没有任何关系,也不存在兼容性问题。

  3. Hibernate不能用来直接和Entity Bean作对比,只有放在整个J2EE项目的框架中才能比较。而且即便是放在软件总体框架中来看,Hibernate也是作为JDBC的替代者出现的,而不是Entity Bean的替代者出现的。

  4. Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了很是轻量级的对象封装,使得Java程序员能够为所欲为的使用对象编程思惟来操控数据库。

  5. Hibernate能够应用在任何使用JDBC的场合。

  6. Hibernate 使用Java 反射机制而不是字节码加强程序来实现透明性。

  7. Hibernate 的性能很是好,由于它是个轻量级框架。映射的灵活性很出色。它支持各类关系数据库,从一对一到多对多的各类复杂关系。

7.2.2 mybatis(持久层)

  1. 易于上手和掌握。

  2. sql写在xml里,便于统一管理和优化。

  3. 解除sql与程序代码的耦合。

  4. 提供映射标签,支持对象与数据库的orm字段关系映射

  5. 提供对象关系映射标签,支持对象关系组建维护

  6. 提供xml标签,支持编写动态sql。

7.2.3 优点对比

  1. Mybatis优点MyBatis能够进行更为细致的SQL优化,能够减小查询字段。

  2. MyBatis容易掌握,而Hibernate门槛较高。

  3. Hibernate优点Hibernate的DAO层开发比MyBatis简单,Mybatis须要维护SQL和结果映射。

  4. Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。

  5. Hibernate数据库移植性很好,MyBatis的数据库移植性很差,不一样的数据库须要写不一样SQL。

  6. Hibernate有更好的二级缓存机制,可使用第三方缓存。MyBatis自己提供的缓存机制不佳。

7.2.4 Spring(控制层+业务层)

它基于IoC(Inversion of Control,反向控制)和AOP的构架多层j2ee系统的框架,但它不强迫你必须在每一层中必须使用Spring,由于它模块化的很好,容许你根据本身的须要选择使用它的某一个模块;它实现了很优雅的MVC,对不一样的数据访问技术提供了统一的接口,采用IoC使得能够很容易的实现bean的装配,提供了简洁的AOP并据此实现Transcation Managment,等等

  • 在项目中利用spring的ioc(控制反转或依赖注入),明确的定义组件接口(如UserDao),开发者能够独立开发各个组件,而后根据组件间的依赖关系组装(UserAction依赖于UserService,UserService依赖于Userdao)运行,很好的把struts(Action)和hibernate(dao的实现)结合起来;
  • spring的事务管理把hibernate对数据库的操做进行了事务配置

事务控制:

  • spring事务包括编程事务和声明式事务。在系统中使用了声明式的事务管理是用spring的AOP来实现的;配置了只读事务和回滚事务(传播行为为REQUIRED)当出现错误后进行事务回滚操做。在项目中经过aop切入事务到service层,这样作能使一次业务逻辑操做若是包括几个数据库操做都控制在一个事务中。
  1. 低侵入式设计,代码污染极低

  2. 独立于各类应用服务器,基于Spring框架的应用,能够真正实现Write Once,Run Anywhere的承诺

  3. Spring的DI机制下降了业务对象替换的复杂性,提升了组件之间的解耦

  4. Spring的AOP支持容许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用

  5. Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问

  6. Spring并不强制应用彻底依赖于Spring,开发者可自由选用Spring框架的部分或所有

7.2.5 struts2

工做原理:

  • 发送http请求
  • web服务器(tomcat、weblogic)
  • 执行struts核心过滤器StrutsprepareAndExecuteFilter
  • 加载struts配置文件中配置信息,找到对应的Action类并实例化
  • 执行各种拦截器和action中对应方法
  • 配置文件中找到返回结果
  • 转发到具体页面或其余操做
  1. 实现了MVC模式,层次结构清晰,使程序员只需关注业务逻辑的实现。

  2. 丰富的标签库,大大提升了开发的效率。

  3. Struts2提供丰富的拦截器实现。

  4. 经过配置文件,就能够掌握整个系统各个部分之间的关系。

  5. 异常处理机制,只需在配置文件中配置异常的映射,便可对异常作相应的处理。

  6. Struts2的可扩展性高。

  7. 面向切面编程的思想在Strut2中也有了很好的体现。最重要的体现就是拦截器的使用

7.2.6 springMVC

第一步:发起请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求HandlerMapping查找 Handler,能够根据xml配置、注解进行查找

第三步:处理器映射器HandlerMapping向前端控制器返回Handler

第四步:前端控制器调用处理器适配器去执行Handler

第五步:处理器适配器去执行Handler

第六步:Handler执行完成给适配器返回ModelAndView

第七步:处理器适配器向前端控制器返回ModelAndView,ModelAndView是springmvc框架的一个底层对象,包括Model和view

第八步:前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)

第九步:视图解析器向前端控制器返回View

第十步:前端控制器进行视图渲染,视图渲染将模型数据(在ModelAndView对象中)填充到request域

第十一步:前端控制器向用户响应结果工做流程:

优势:

  1. 进行更简洁的Web层的开发
  2. 天生与Spring框架集成(如IoC容器、AOP等)
  3. 提供强大的约定大于配置的契约式编程支持
  4. 很是灵活的数据验证、格式化和数据绑定机制
  5. 支持Restful风格

7.3 框架应用

  1. 在表示层中,首先经过jsp页面实现交互界面,负责传送请求(request)和接收响应(response),而后struts根据配置文件(struts。xml)将actionServlet接收到的request委派给响应的action处理。
  2. 在业务层中,管理服务组件的spring ioc容器负责向action提供业务模型(model)组件和组件的协做对象数据处理(dao)组件完成业务逻辑,并提供事务处理、缓冲池等容器组件以提高系统性能和保证数据的完整性。
  3. 在持久层中,则依赖于hibernate的对象化映射和数据库交互,处理dao组件请求的数据,并返回处理结果。
相关文章
相关标签/搜索