您好,登錄后才能下訂單哦!
springmvc的原理是什么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
一、spring mvc 設計思想與體系結構組成
知識點
jsp 執行過程回顧
spring mvc執行流程解析
mvc 體系結構
1、回顧servlet 與jsp 執行過程
流程說明:
請求Servlet
處理業務邏輯
設置業務Model
forward jsp Servlet
jsp Servlet 解析封裝html 返回
提問:這個是一個MVC應用場景嗎?
spring mvc本質上還是在使用Servlet處理,并在其基礎上進行了封裝簡化了開發流程,提高易用性、并使用程序邏輯結構變得更清晰
基于注解的URL映謝
http表單參數轉換
全局統一異常處理
攔截器的實現
2、spring mvc 執行流程:
整個過程是如何實現的?
dispatchServlet 如何找到對應的Control?
如何執行調用Control 當中的業務方法?
回答這些問題之前我們先來認識一下spring mvc 體系結構
3、spring mvc 體系結構
HandlerMapping 'h?ndl? 'm?p??
url與控制器的映謝
HandlerAdapter 'h?ndl? ?'d?pt?
控制器執行適配器
ViewResolver vju? ri?'z?lv?
視圖倉庫
view
具體解析視圖
HandlerExceptionResolver 'h?ndl? ?k'sep?(?)n ri?'z?lv?
異常捕捕捉器
HandlerInterceptor 'h?ndl? ?nt?'sept?
攔截器
配置一個spring mvc 示例演示 驗證上述流程
創建一個Controller 類
配置DispatchServlet
創建spring-mvc.xml 文件
配置SimpleUrlHandlerMapping
配置InternalResourceViewResolver
體系結構UML
二、mvc 執行流程解析
知識點:
mvc 具體執行流程
HandlerMapping詳解
HandlerAdapter 詳解
ViewResolver與View詳解
HandlerExceptionResolver詳解
HandlerInterceptor 詳解
mvc 各組件執行流程
2、HandlerMapping 詳解
其為mvc 中url路徑與Control對象的映射,DispatcherServlet 就是基于此組件來尋找對應的Control,如果找不到就會報Not Found mapping 的異常。
HandlerMapping 接口方法
HandlerMapping 接口結構
目前主流的三種mapping 如下:
BeanNameUrlHandlerMapping: 基于ioc name 中已 "/" 開頭的Bean時行 注冊至映謝.
SimpleUrlHandlerMapping:基于手動配置 url 與control 映謝
RequestMappingHandlerMapping:基于@RequestMapping注解配置對應映謝
演示基于 BeanNameUrlHandlerMapping 配置映謝。
編寫mvc 文件
<!--簡單控制器-->
<bean id="/user.do" class="com.tuling.mvc.control.BeanNameControl"/>
// beanname control 控制器
public class BeanNameControl implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
request.getRequestDispatcher("/WEB-INF/page/userView.jsp").forward(request, response);
}
}
當IOC 中實例化這些類之后 DispatcherServlet 就會通過org.springframework.web.servlet.DispatcherServlet#getHandler() 方法基于request查找對應Handler。 但找到對應的Handler之后我們發現他是一個Object類型,并沒有實現特定接口。如何調用Handler呢?
3、HandlerAdapter詳解
這里spring mvc 采用適配器模式來適配調用指定Handler,根據Handler的不同種類采用不同的Adapter,其Handler與 HandlerAdapter 對應關系如下:
Handler類別 | 對應適配器 | 描述 |
Controller | SimpleControllerHandlerAdapter | 標準控制器,返回ModelAndView |
HttpRequestHandler | HttpRequestHandlerAdapter | 業務自行處理 請求,不需要通過modelAndView 轉到視圖 |
Servlet | SimpleServletHandlerAdapter | 基于標準的servlet 處理 |
HandlerMethod | RequestMappingHandlerAdapter | 基于@requestMapping對應方法處理 |
HandlerAdapter 接口方法
HandlerAdapter 接口結構圖
演示基于Servlet 處理 SimpleServletHandlerAdapter
<!-- 配置控制器 -->
<bean id="/hello.do" class="com.tuling.mvc.control.HelloServlet"/>
<!-- 配置適配器 -->
<bean class="org.springframework.web.servlet.handler.SimpleServletHandlerAdapter"/>
// 標準Servlet
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("hello luban ");
}
}
上述例子中當IOC 中實例化這些類之后 DispatcherServlet 就會通過
org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter() 方法查找對應handler的適配器 ,如果找不到就會報 No adapter for handler 。
4、ViewResolver 與View 詳解
找到應的Adapter 之后就會基于適配器調用業務處理,處理完之后業務方會返回一個ModelAndView ,在去查找對應的視圖進行處理。其在org.springframework.web.servlet.DispatcherServlet#resolveViewName() 中遍歷 viewResolvers 列表查找,如果找不到就會報一個 Could not resolve view with name 異常。
在下一步就是基于ViewResolver.resolveViewName() 獲取對應View來解析生成Html并返回 。對應VIEW結構如下:
至此整個正向流程就已經走完了,如果此時程序處理異常 MVC 該如何處理呢?
5、HandlerExceptionResolver詳解
該組件用于指示 當出現異常時 mvc 該如何處理。 dispatcherServlet 會調用org.springframework.web.servlet.DispatcherServlet#processHandlerException() 方法,遍歷 handlerExceptionResolvers 處理異常,處理完成之后返回errorView 跳轉到異常視圖。
演示自定義異常捕捉
public class SimpleExceptionHandle implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
return new ModelAndView("error");
}
}
<!-- 演示異常配置 -->
<bean class="com.tuling.mvc.control.SimpleExceptionHandle"/>
HandlerExceptionResolver 結構
除了上述組件之外 spring 中還引入了 我Interceptor 攔截器 機制,類似于Filter。
6、HandlerInterceptor 詳解
演示HandlerInterceptor
public class SimpleHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
<!--配置interceptor 組件-->
<bean class="com.tuling.mvc.control.SimpleHandlerInterceptor"></bean>
其實現機制是基于 HandlerExecutionChain 分別在 doDispatch 方法中執行以下方法:
preHandle :業務處理前執行
postHandle:業務處理后(異常則不執行)
afterCompletion:視圖處理后
具體邏輯源碼參見:org.springframework.web.servlet.DispatcherServlet#doDispatch 方法。
三、注解配置
演示基于注解配置mvc mapping
<context:component-scan base-package="com.tuling.mvc.control" />
<!-- 注解驅動 -->
<mvc:annotation-driven/>
<!-- 視圖倉庫 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/" />
<property name="suffix" value=".jsp" />
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
</bean>
// 注解方法
@RequestMapping("/hello.do")
public ModelAndView hello() {
ModelAndView mv = new ModelAndView("userView");
mv.addObject("name", "luban");
return mv;
}
提問 為什么基于 <mvc:annotation-driven/> 配置就能實現mvc 的整個配置了,之前所提到的 handlerMapping 、與handlerAdapter 組件都不適用了?
只要查看以類的源就可以知曉其中原因:
認識 NamespaceHandler 接口
查看 MvcNamespaceHandler
查看AnnotationDrivenBeanDefinitionParser
結論:
在<mvc:annotation-driven /> 對應的解析器,自動向ioc 里面注冊了兩個BeanDefinition。分別是:RequestMappingHandlerMapping與BeanNameUrlHandlerMapping
關于springmvc的原理是什么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。