前端控制器是整个mvc框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。前端控制器既可以使用filter实现(struts2采用这种方式),也可以使用servlet来实现(spring mvc框架)。
dispatcherservlet 作为前置控制器是web服务器的入口,是spring mvc最重要的一个类,通过它的生命周期可以加深对web服务器的理解。
servlet的生命周期
首先我们回忆一下servlet的生命周期:
servlet生命周期分为三个阶段:【servlet生命周期与工作原理详解】
1.初始化阶段 调用init()方法。servlet被装载后,servlet容器创建一个servlet实例并且调用servlet的init()方法进行初始化。在servlet的整个生命周期内,init()方法只被调用一次。
2.响应客户请求阶段 调用service()方法
3.终止阶段 调用destroy()方法
servlet初始化阶段
在下列时刻servlet容器装载servlet:
1.servlet容器启动时自动装载某些servlet,实现它只需要在web.xml文件中的<servlet></servlet>之间添加如下代码:
<loadon-startup>1</loadon-startup>
2.在servlet容器启动后,客户首次向servlet发送请求
3.servlet类文件被更新后,重新装载servlet
dispatcherservlet的结构
复习了上述知识后我们来看看dispatcherservlet的结构:
dispatcherservlet继承自抽象类:frameworkservlet,间接继承了httpservlet (frameworkservlet继承自httpservletbean,而httpservletbean继承自httpservlet )
servlet的初始化
1
2
3
4
5
6
7
8
9
10
11
|
protected void initstrategies(applicationcontext context) {
initmultipartresolver(context); //文件上传解析,如果请求类型是multipart将通过multipartresolver进行文件上传解析;
initlocaleresolver(context); //本地化解析
initthemeresolver(context); //主题解析
inithandlermappings(context); //通过handlermapping,将请求映射到处理器
inithandleradapters(context); //通过handleradapter支持多种类型的处理器
inithandlerexceptionresolvers(context); //如果执行过程中遇到异常将交给handlerexceptionresolver来解析
initrequesttoviewnametranslator(context); //直接解析请求到视图名
initviewresolvers(context); //通过viewresolver解析逻辑视图名到具体视图实现
initflashmapmanager(context); //flash映射管理器
}
|
servlet如何处理请求:
servlet的service方法处理http请求。
frameworkservlet.java 定义了servlet的service和destroy方法,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/**
* override the parent class implementation in order to intercept patch
* requests.
*/
@override
protected void service(httpservletrequest request, httpservletresponse response)
throws servletexception, ioexception {
string method = request.getmethod();
if (method.equalsignorecase(requestmethod.patch.name())) {
processrequest(request, response);
}
else {
super .service(request, response);
}
}
|
我们知道http请求类型有七种(外加一个option选项),定义如下:
1
2
3
4
|
public enum requestmethod {
get, head, post, put, patch, delete, options, trace
}
|
frameworkservlet的service()处理不同的请求,我们以常见的post来说明:
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
|
/**
* process this request, publishing an event regardless of the outcome.
* <p>the actual event handling is performed by the abstract
* {@link #doservice} template method.
*/
protected final void processrequest(httpservletrequest request, httpservletresponse response)
throws servletexception, ioexception {
long starttime = system.currenttimemillis();
throwable failurecause = null ;
localecontext previouslocalecontext = localecontextholder.getlocalecontext();
localecontext localecontext = buildlocalecontext(request);
requestattributes previousattributes = requestcontextholder.getrequestattributes();
servletrequestattributes requestattributes = buildrequestattributes(request, response, previousattributes);
webasyncmanager asyncmanager = webasyncutils.getasyncmanager(request);
asyncmanager.registercallableinterceptor(frameworkservlet. class .getname(), new requestbindinginterceptor());
initcontextholders(request, localecontext, requestattributes);
try {
doservice(request, response);
}
catch (servletexception ex) {
failurecause = ex;
throw ex;
}
catch (ioexception ex) {
failurecause = ex;
throw ex;
}
catch (throwable ex) {
failurecause = ex;
throw new nestedservletexception( "request processing failed" , ex);
}
finally {
resetcontextholders(request, previouslocalecontext, previousattributes);
if (requestattributes != null ) {
requestattributes.requestcompleted();
}
if (logger.isdebugenabled()) {
if (failurecause != null ) {
this .logger.debug( "could not complete request" , failurecause);
}
else {
if (asyncmanager.isconcurrenthandlingstarted()) {
logger.debug( "leaving response open for concurrent processing" );
}
else {
this .logger.debug( "successfully completed request" );
}
}
}
publishrequesthandledevent(request, starttime, failurecause);
}
}
|
frameworkservlet 抽象定义了处理流程,留待子类来实现该方法,完成具体的请求处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/**
* subclasses must implement this method to do the work of request handling,
* receiving a centralized callback for get, post, put and delete.
* <p>the contract is essentially the same as that for the commonly overridden
* {@code doget} or {@code dopost} methods of httpservlet.
* <p>this class intercepts calls to ensure that exception handling and
* event publication takes place.
* @param request current http request
* @param response current http response
* @throws exception in case of any kind of processing failure
* @see javax.servlet.http.httpservlet#doget
* @see javax.servlet.http.httpservlet#dopost
*/
protected abstract void doservice(httpservletrequest request, httpservletresponse response)
throws exception;
|
具体实现如下:
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
|
/**
* exposes the dispatcherservlet-specific request attributes and delegates to {@link #dodispatch}
* for the actual dispatching.
*/
@override
protected void doservice(httpservletrequest request, httpservletresponse response) throws exception {
if (logger.isdebugenabled()) {
string resumed = webasyncutils.getasyncmanager(request).hasconcurrentresult() ? " resumed" : "" ;
logger.debug( "dispatcherservlet with name '" + getservletname() + "'" + resumed +
" processing " + request.getmethod() + " request for [" + getrequesturi(request) + "]" );
}
// keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
map<string, object> attributessnapshot = null ;
if (webutils.isincluderequest(request)) {
attributessnapshot = new hashmap<string, object>();
enumeration<?> attrnames = request.getattributenames();
while (attrnames.hasmoreelements()) {
string attrname = (string) attrnames.nextelement();
if ( this .cleanupafterinclude || attrname.startswith( "org.springframework.web.servlet" )) {
attributessnapshot.put(attrname, request.getattribute(attrname));
}
}
}
// make framework objects available to handlers and view objects.
request.setattribute(web_application_context_attribute, getwebapplicationcontext());
request.setattribute(locale_resolver_attribute, this .localeresolver);
request.setattribute(theme_resolver_attribute, this .themeresolver);
request.setattribute(theme_source_attribute, getthemesource());
flashmap inputflashmap = this .flashmapmanager.retrieveandupdate(request, response);
if (inputflashmap != null ) {
request.setattribute(input_flash_map_attribute, collections.unmodifiablemap(inputflashmap));
}
request.setattribute(output_flash_map_attribute, new flashmap());
request.setattribute(flash_map_manager_attribute, this .flashmapmanager);
try {
dodispatch(request, response);
}
finally {
if (webasyncutils.getasyncmanager(request).isconcurrenthandlingstarted()) {
return ;
}
// restore the original attribute snapshot, in case of an include.
if (attributessnapshot != null ) {
restoreattributesafterinclude(request, attributessnapshot);
}
}
}
|
重头戏,作为请求分发器的实现:
功能:1. 把请求分发到handler(按照配置顺序获取servlet的映射关系获取handler);2. 根据servlet已安装的 handleradapters 去查询第一个能处理的handler;3. handler激发处理请求
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
83
84
85
86
87
88
89
|
/**
* process the actual dispatching to the handler.
* <p>the handler will be obtained by applying the servlet's handlermappings in order.
* the handleradapter will be obtained by querying the servlet's installed handleradapters
* to find the first that supports the handler class.
* <p>all http methods are handled by this method. it's up to handleradapters or handlers
* themselves to decide which methods are acceptable.
* @param request current http request
* @param response current http response
* @throws exception in case of any kind of processing failure
*/
protected void dodispatch(httpservletrequest request, httpservletresponse response) throws exception {
httpservletrequest processedrequest = request;
handlerexecutionchain mappedhandler = null ;
boolean multipartrequestparsed = false ;
webasyncmanager asyncmanager = webasyncutils.getasyncmanager(request);
try {
modelandview mv = null ;
exception dispatchexception = null ;
try {
processedrequest = checkmultipart(request);
multipartrequestparsed = (processedrequest != request);
// determine handler for the current request.
mappedhandler = gethandler(processedrequest);
if (mappedhandler == null || mappedhandler.gethandler() == null ) {
nohandlerfound(processedrequest, response);
return ;
}
// determine handler adapter for the current request.
handleradapter ha = gethandleradapter(mappedhandler.gethandler());
// process last-modified header, if supported by the handler.
string method = request.getmethod();
boolean isget = "get" .equals(method);
if (isget || "head" .equals(method)) {
long lastmodified = ha.getlastmodified(request, mappedhandler.gethandler());
if (logger.isdebugenabled()) {
logger.debug( "last-modified value for [" + getrequesturi(request) + "] is: " + lastmodified);
}
if ( new servletwebrequest(request, response).checknotmodified(lastmodified) && isget) {
return ;
}
}
if (!mappedhandler.applyprehandle(processedrequest, response)) {
return ;
}
try {
// actually invoke the handler.
mv = ha.handle(processedrequest, response, mappedhandler.gethandler());
}
finally {
if (asyncmanager.isconcurrenthandlingstarted()) {
return ;
}
}
applydefaultviewname(request, mv);
mappedhandler.applyposthandle(processedrequest, response, mv);
}
catch (exception ex) {
dispatchexception = ex;
}
processdispatchresult(processedrequest, response, mappedhandler, mv, dispatchexception);
}
catch (exception ex) {
triggeraftercompletion(processedrequest, response, mappedhandler, ex);
}
catch (error err) {
triggeraftercompletionwitherror(processedrequest, response, mappedhandler, err);
}
finally {
if (asyncmanager.isconcurrenthandlingstarted()) {
// instead of posthandle and aftercompletion
mappedhandler.applyafterconcurrenthandlingstarted(processedrequest, response);
return ;
}
// clean up any resources used by a multipart request.
if (multipartrequestparsed) {
cleanupmultipart(processedrequest);
}
}
}
|
servlet销毁
1
2
3
4
5
6
7
8
9
10
11
12
|
/**
* close the webapplicationcontext of this servlet.
* @see org.springframework.context.configurableapplicationcontext#close()
*/
@override
public void destroy() {
getservletcontext().log( "destroying spring frameworkservlet '" + getservletname() + "'" );
// only call close() on webapplicationcontext if locally managed...
if ( this .webapplicationcontext instanceof configurableapplicationcontext && ! this .webapplicationcontextinjected) {
((configurableapplicationcontext) this .webapplicationcontext).close();
}
}
|
小结:
本文因篇章限制,仅仅介绍了请求处理的流程,没有对代码进行深入的分析,接下来的文章将从细微处着手,分析spring的代码之美。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/davidwang456/p/4090058.html