Spring MVC 适配器模式

找到DispatcherServlet类中的`doDispatch`体,我们可以看到,它的作用是相当于在Servlet的 doService调用的。 也就是用来传递request给我们编写的Controller并执行相应的方法、返回ModeView对象。 

 执行的代码片段: 
1
2
3
4
...
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
...

mappedHandler.getHandler()得到的是Controller对象
而此处并非采用直接 调用.handlerRequest或者MultiActionController中编写的自定义方法,而采用了一个HandlerAdapter的接口。

此处采用了适配器模式, 由于Controller的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用Controller方法,需要在代码中写成如下形式:

1
2
3
4
5
6
7
8
if(mappedHandler.getHandler() instanceof MultiActionController){
((MultiActionController)mappedHandler.getHandler()).xxx
}else if(mappedHandler.getHandler() instanceof XXX){
...
}else if(...){
...
}
...

这样假设如果我们增加一个HardController,就要在代码中加入一行 if(mappedHandler.getHandler() instanceof HardController) , 这种形式就使得程序难以维护,也违反了设计模式中的开闭原则 – 对扩展开放,对修改关闭。

因此Spring定义了一个适配接口,使得每一种Controller有一种对应的适配器实现类, 让适配器代替controller执行相应的方法。这样在扩展Controller 时,只需要增加一个适配器类就完成了SpringMVC的扩展了.

​ 实现一套代码来模拟springMVC:

1
2
3
4
5
//定义一个Adapter接口
public interface HandlerAdapter {
public boolean supports(Object handler);
public void handle(Object handler);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//以下是三种Controller实现
public interface Controller {
}
public class HttpController implements Controller{
public void doHttpHandler(){
System.out.println("http...");
}
}
public class SimpleController implements Controller{
public void doSimplerHandler(){
System.out.println("simple...");
}
}
public class AnnotationController implements Controller{
public void doAnnotationHandler(){
System.out.println("annotation...");
}
}
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 class SimpleHandlerAdapter implements HandlerAdapter {
public void handle(Object handler) {
((SimpleController)handler).doSimplerHandler();
}
public boolean supports(Object handler) {
return (handler instanceof SimpleController);
}
}
public class HttpHandlerAdapter implements HandlerAdapter {
public void handle(Object handler) {
((HttpController)handler).doHttpHandler();
}
public boolean supports(Object handler) {
return (handler instanceof HttpController);
}
}
public class AnnotationHandlerAdapter implements HandlerAdapter {
public void handle(Object handler) {
((AnnotationController)handler).doAnnotationHandler();
}
public boolean supports(Object handler) {
return (handler instanceof AnnotationController);
}
}
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
//模拟一个DispatcherServlet
import java.util.ArrayList;
import java.util.List;
public class DispatchServlet {
public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();
public DispatchServlet(){
handlerAdapters.add(new AnnotationHandlerAdapter());
handlerAdapters.add(new HttpHandlerAdapter());
handlerAdapters.add(new SimpleHandlerAdapter());
}
public void doDispatch(){
//此处模拟SpringMVC从request取handler的对象,仅仅new出.
//不论实现何种Controller,适配器总能经过适配以后得到想要的结果
// HttpController controller = new HttpController();
// AnnotationController controller = new AnnotationController();
SimpleController controller = new SimpleController();
//得到对应适配器
HandlerAdapter adapter = getHandler(controller);
//通过适配器执行对应的controller对应方法
adapter.handle(controller);
}
public HandlerAdapter getHandler(Controller controller){
for(HandlerAdapter adapter: this.handlerAdapters){
if(adapter.supports(controller)){
return adapter;
}
}
return null;
}
public static void main(String[] args){
new DispatchServlet().doDispatch();
}
}

Spring MVC HandlerAdapter ,有下面几个子类:

img

这几个子类,分别用于适配不同的Handler(我们写的请求处理代码)。

如果Handler是一个简单的Servlet(这是在web.xml配置自定义的Servlet时的方式),那么就使用SimpleServletHandlerAdapter

1
2
3
4
5
6
7
8
9
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
((Servlet) handler).service(request, response);
return null ;
}

如果Handler是一个简单的Controller的实例,就是用SimpleControllerHandlerAdapter来适配(在Spring2.5时,一般会采用这种方式):

1
2
3
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return ((Controller) handler).handleRequest(request, response);
}

如果使用了注解方式,就使用AnnotationMethodHandlerAdapter.

从上面的可以采用的几种处理HttpRequest的写法上来看,这几种Handler分别属于不同的类,也就是处理的接口是不同的。然而在DispatcherServlet中,只用了一个接口,采用了适配器模式,来屏蔽掉这种差异,在适配器的内部,进行接口的转换工作。

热评文章