您的位置 首页 java

Spring MVC使用原理详解及说明

spring MVC 使用原理详解及说明

Spring MVC使用原理详解及说明

一、SpringMVC框架简介

1) spring MVC属于 SpringFrameWork 的后续产品,已经融合在 Spring Web Flow 里面。

Spring 框架 提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,可以选择是使用内置的 Spring Web 框架还是 Struts 这样的 Web 框架。通过策略接口,Spring 框架是高度可配置的,而且包含多种视图技术,例如 JavaServer Pages JSP )技术、Velocity、 Tiles 、iText 和 POI。Spring MVC 框架并不知道使用的视图,所以不会强迫您只使用 JSP 技术。

Spring MVC 分离了 控制器 、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。

2) Spring的 MVC框架 主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。

Spring MVC使用原理详解及说明

1.1其执行流程图

Spring MVC使用原理详解及说明

执行过程如下:

1.用户发送请求至前端控制器 DispatcherServlet

2.DispatcherServlet收到请求调用处理器映射器HandlerMapping。

3.处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。

4.DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作

5.执行处理器Handler(Controller,也叫页面控制器)。

6. handler 执行完成返回ModelAndView

7.HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet

8.DispatcherServlet将ModelAndView传给ViewReslover视图解析器

9.ViewReslover解析后返回具体View

10.DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)。

11.DispatcherServlet响应用户。

Spring MVC使用原理详解及说明

二、SpringMVC组件解释

DispatcherServlet接口:

Spring提供的前端控制器,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的 Handler Mapping定位到具体的Controller。

HandlerMapping接口:

能够完成客户请求到Controller映射。

Controller接口:

需要为并发用户处理上述请求,因此实现Controller接口时,必须保证 线程 安全并且可重用。

Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。

从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。

ViewResolver接口:

Spring提供的视图解析器(ViewResolver)在Web应用中查找View对象,从而将相应结果渲染给客户。

Spring MVC使用原理详解及说明

2.1组件执行代码

1.请求到达前端控制器的第一站,先做些准备工作

/**

* 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 requestUri = urlPathHelper.getRequestUri(request);

logger.debug(“DispatcherServlet with name ‘” + getServletName() + “‘ processing ” + request.getMethod() +

” request for [” + requestUri + “]”);

}

//保护现场

// 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)) {

logger.debug(“Taking snapshot of request attributes before include”);

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));

}

}

}

//将框架相关信息存储至request,方便后面的处理器和视图用到

// 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 {

// Restore the original attribute snapshot, in case of an include.

if (attributesSnapshot != null) {

restoreAttributesAfterInclude(request, attributesSnapshot);

}

}

}

Spring MVC使用原理详解及说明

2.开始处理请求

//通过url查找HandlerMap中最相近的key(url),然后由key获取HandlerMapping对象

//通过处理器映射器获取处理器;

//通过查询处理器适配器获得

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

HttpServletRequest processedRequest = request;

HandlerExecutionChain mappedHandler = null;

int interceptorIndex = -1;

try {

ModelAndView mv;

boolean errorView = false;

try {

processedRequest = checkMultipart(request);

// Determine handler for the current request

//步骤3.1~3.4用于获取包含处理器Handler和拦截器AdapterIntercepters的处理器执行链HandlerExecutionChain

mappedHandler = getHandler(processedRequest, false);

if (mappedHandler == null || mappedHandler.getHandler() == null) {

noHandlerFound(processedRequest, response);

return;

}

// Determine handler adapter for the current request.

//步骤4.1~4.2,根据HandlerExecutionChain中的处理器Handler获取处理器适配器

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()) {

String requestUri = urlPathHelper.getRequestUri(request);

logger.debug(“Last-Modified value for [” + requestUri + “] is: ” + lastModified);

}

if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {

return;

}

}

// Apply preHandle methods of registered interceptors.

HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();

if (interceptors != null) {

for (int i = 0; i < interceptors.length; i++) {

HandlerInterceptor interceptor = interceptors[i];

if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);

return;

}

interceptorIndex = i;

}

}

// Actually invoke the handler.

//5.1~5.3通过处理器适配器HandlerApapter来调用处理器完成对请求的处理

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

// Do we need view name translation?

if (mv != null && !mv.hasView()) {

mv.setViewName(getDefaultViewName(request));

}

// Apply postHandle methods of registered interceptors.

if (interceptors != null) {

for (int i = interceptors.length – 1; i >= 0; i–) {

HandlerInterceptor interceptor = interceptors[i];

interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);

}

}

}

catch (ModelAndViewDefiningException ex) {

logger.debug(“ModelAndViewDefiningException encountered”, ex);

mv = ex.getModelAndView();

}

catch (Exception ex) {

Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);

mv = processHandlerException(processedRequest, response, handler, ex);

errorView = (mv != null);

}

// Did the handler return a view to render?

if (mv != null && !mv.wasCleared()) {

render(mv, processedRequest, response);

if (errorView) {

WebUtils.clearErrorRequestAttributes(request);

}

}

else {

if (logger.isDebugEnabled()) {

logger.debug(“Null ModelAndView returned to DispatcherServlet with name ‘” + getServletName() +

“‘: assuming HandlerAdapter completed request handling”);

}

}

// Trigger after-completion for successful outcome.

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);

}

catch (Exception ex) {

// Trigger after-completion for thrown exception.

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);

throw ex;

}

catch ( err or err) {

ServletException ex = new NestedServletException(“Handler processing failed”, err);

// Trigger after-completion for thrown exception.

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);

throw ex;

}

finally {

// Clean up any resources used by a multipart request.

if (processedRequest != request) {

cleanupMultipart(processedRequest);

}

}

}

Spring MVC使用原理详解及说明

3.1 getHandler(HttpServletRequest request),经由HandlerMapping对象获取HandlerExecutionChain(处理器和拦截器)

/**

* Return the HandlerExecutionChain for this request.

* <p>Tries all handler mappings in order.

* @param request current HTTP request

* @return the HandlerExecutionChain, or <code>null</code> if no handler could be found

*/

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {

for (HandlerMapping hm : this.handlerMappings) {

if (logger.isTraceEnabled()) {

logger.trace(

“Testing handler map [” + hm + “] in DispatcherServlet with name ‘” + getServletName() + “‘”);

}

HandlerExecutionChain handler = hm.getHandler(request);

if (handler != null) {

return handler;

}

}

return null;

}

Spring MVC使用原理详解及说明

3.2.1 getHandler(HttpServletRequest request),经由request获取处理器,获取处理器Handler后,再获取拦截器,最后组成HandlerExecutionChain

/**

* Look up a handler for the given request, falling back to the default

* handler if no specific one is found.

* @param request current HTTP request

* @return the corresponding handler instance, or the default handler

* @see #getHandlerInternal

*/

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {

Object handler = getHandlerInternal(request);

if (handler == null) {

handler = getDefaultHandler();

}

if (handler == null) {

return null;

}

// Bean name or resolved handler?

if (handler instanceof String) {

String handlerName = (String) handler;

handler = getApplicationContext().getBean(handlerName);

}

return getHandlerExecutionChain(handler, request);

}

Spring MVC使用原理详解及说明

3.2.2 根据查找到的处理器Handler和request获取包含Handler和AdaptedInterceptors的HandlerExecutionChain

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {

HandlerExecutionChain chain =

(handler instanceof HandlerExecutionChain) ?

(HandlerExecutionChain) handler : new HandlerExecutionChain(handler);

chain.addInterceptors(getAdaptedInterceptors());

String lookupPath = urlPathHelper.getLookupPathForRequest(request);

for (MappedInterceptor mappedInterceptor : mappedInterceptors) {

if (mappedInterceptor.matches(lookupPath, pathMatcher)) {

chain.addInterceptor(mappedInterceptor.getInterceptor());

}

}

return chain;

}

/**

* Return the adapted interceptors as HandlerInterceptor array.

* @return the array of HandlerInterceptors, or <code>null</code> if none

*/

protected final HandlerInterceptor[] getAdaptedInterceptors() {

int count = adaptedInterceptors.size();

return (count > 0) ? adaptedInterceptors.toArray(new HandlerInterceptor[count]) : null;

}

Spring MVC使用原理详解及说明

3.3.getHandlerInternal(HttpServletRequest request)获取Handler

/**

* Look up a handler for the URL path of the given request.

* @param request current HTTP request

* @return the handler instance, or <code>null</code> if none found

*/

@Override

protected Object getHandlerInternal(HttpServletRequest request) throws Exception {

String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);

Object handler = lookupHandler(lookupPath, request);

if (handler == null) {

// We need to care for the default handler directly, since we need to

// expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.

Object rawHandler = null;

if (“/”.equals(lookupPath)) {

rawHandler = getRootHandler();

}

if (rawHandler == null) {

rawHandler = getDefaultHandler();

}

if (rawHandler != null) {

// Bean name or resolved handler?

if (rawHandler instanceof String) {

String handlerName = (String) rawHandler;

rawHandler = getApplicationContext().getBean(handlerName);

}

validateHandler(rawHandler, request);

handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);

}

}

if (handler != null && logger.isDebugEnabled()) {

logger.debug(“Mapping [” + lookupPath + “] to ” + handler);

}

else if (handler == null && logger.isTraceEnabled()) {

logger.trace(“No handler mapping found for [” + lookupPath + “]”);

}

return handler;

}

Spring MVC使用原理详解及说明

3.4 lookupHandler(lookupPath, request)根据给定url path和request获取Handler

protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {

// Direct match?

Object handler = this.handlerMap.get(urlPath);

if (handler != null) {

// Bean name or resolved handler?

if (handler instanceof String) {

String handlerName = (String) handler;

handler = getApplicationContext().getBean(handlerName);

}

validateHandler(handler, request);

return buildPathExposingHandler(handler, urlPath, urlPath, null);

}

// Pattern match?

List<String> matchingPatterns = new ArrayList<String>();

for (String registeredPattern : this.handlerMap.keySet()) {

if (getPathMatcher().match(registeredPattern, urlPath)) {

matchingPatterns.add(registeredPattern);

}

}

String bestPatternMatch = null;

Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);

if (!matchingPatterns.isEmpty()) {

Collections.sort(matchingPatterns, patternComparator);

if (logger.isDebugEnabled()) {

logger.debug(“Matching patterns for request [” + urlPath + “] are ” + matchingPatterns);

}

bestPatternMatch = matchingPatterns.get(0);

}

if (bestPatternMatch != null) {

handler = this.handlerMap.get(bestPatternMatch);

// Bean name or resolved handler?

if (handler instanceof String) {

String handlerName = (String) handler;

handler = getApplicationContext().getBean(handlerName);

}

validateHandler(handler, request);

String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);

// There might be multiple ‘best patterns’, let’s make sure we have the correct URI template variables

// for all of them

Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>();

for (String matchingPattern : matchingPatterns) {

if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {

uriTemplateVariables

.putAll(getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath));

}

}

if (logger.isDebugEnabled()) {

logger.debug(“URI Template variables for request [” + urlPath + “] are ” + uriTemplateVariables);

}

return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);

}

// No handler found…

return null;

}

Spring MVC使用原理详解及说明

4.1 HandlerAdapter getHandlerAdapter(Object handler),根据Handler获取HandlerAdapter

/**

* Return the HandlerAdapter for this handler object.

* @param handler the handler object to find an adapter for

* @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.

*/

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {

for (HandlerAdapter ha : this.handlerAdapters) {

if (logger.isTraceEnabled()) {

logger.trace(“Testing handler adapter [” + ha + “]”);

}

if (ha.supports(handler)) {

return ha;

}

}

throw new ServletException(“No adapter for handler [” + handler +

“]: Does your handler implement a supported interface like Controller?”);

}

Spring MVC使用原理详解及说明

4.2 supports(Object handler)

public boolean supports(Object handler) {

return (handler instanceof Controller);

}

Spring MVC使用原理详解及说明

5.1 使用处理器完成对请求的处理

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)

throws Exception {

((Servlet) handler).service(request, response);

return null;

}

public void service(ServletRequest req, ServletResponse res)

throws ServletException, IOException

{

HttpServletRequest request;

HttpServletResponse response;

if (!(req instanceof HttpServletRequest &&

res instanceof HttpServletResponse)) {

throw new ServletException(“non-HTTP request or response”);

}

request = (HttpServletRequest) req;

response = (HttpServletResponse) res;

service(request, response);

}

Spring MVC使用原理详解及说明

5.2 service(HttpServletRequest req, HttpServletResponse resp)

protected void service(HttpServletRequest req, HttpServletResponse resp)

throws ServletException, IOException

{

String method = req.getMethod();

if (method.equals(METHOD_GET)) {

long lastModified = getLastModified(req);

if (lastModified == -1) {

// servlet doesn’t support if-modified-since, no reason

// to go through further expensive logic

doGet(req, resp);

} else {

long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);

if (ifModifiedSince < lastModified) {

// If the servlet mod time is later, call doGet()

// Round down to the nearest second for a proper compare

// A ifModifiedSince of -1 will always be less

maybeSetLastModified(resp, lastModified);

doGet(req, resp);

} else {

resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);

}

}

} else if (method.equals(METHOD_HEAD)) {

long lastModified = getLastModified(req);

maybeSetLastModified(resp, lastModified);

doHead(req, resp);

} else if (method.equals(METHOD_POST)) {

doPost(req, resp);

} else if (method.equals(METHOD_PUT)) {

doPut(req, resp);

} else if (method.equals(METHOD_DELETE)) {

doDelete(req, resp);

} else if (method.equals(METHOD_OPTIONS)) {

doOptions(req,resp);

} else if (method.equals(METHOD_TRACE)) {

doTrace(req,resp);

} else {

//

// Note that this means NO servlet supports whatever

// method was requested, anywhere on this server.

//

String errMsg = lStrings.getString(“http.method_not_implemented”);

Object[] errArgs = new Object[1];

errArgs[0] = method;

errMsg = MessageFormat.format(errMsg, errArgs);

resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);

}

}

Spring MVC使用原理详解及说明

5.3 doGet(HttpServletRequest req, HttpServletResponse resp)

protected void doGet(HttpServletRequest req, HttpServletResponse resp)

throws ServletException, IOException

{

String protocol = req.getProtocol();

String msg = lStrings.getString(“http.method_get_not_supported”);

if (protocol.endsWith(“1.1”)) {

resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);

} else {

resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);

}

}

Spring MVC使用原理详解及说明

三、普及MVC知识

MVC是一种设计模式

MVC的原理图:

M-Model 模型(完成业务逻辑:有javaBean构成,service+dao+entity)

V-View 视图(做界面的展示 jsp,html……)

C-Controller 控制器(接收请求—>调用模型—>根据结果派发页面)

springMVC是一个MVC的开源框架,springMVC=struts2+spring,springMVC就相当于是Struts2加上sring的整合,但是Spring MVC底层原理是DispatcherServlet,基于Spring提供的一款MVC框架组件,之后衍生出无XML的Spring Boot,后面讲解Spring Boot。

文章来源:智云一二三科技

文章标题:Spring MVC使用原理详解及说明

文章地址:https://www.zhihuclub.com/186524.shtml

关于作者: 智云科技

热门文章

网站地图