国产另类ts人妖一区二区_欧美肥老太做爰视频_快穿高h肉_国产欧美综合在线

當前位置: 首頁 / 技術干貨 / 正文
SpringMVC源碼解析(四)

2023-03-09

視圖 handleradapter 處理器 對象 返回

  4 處理器適配器HandlerAdapter

  4.1 HandlerAdapter源碼分析

  1.在DispatcherServlet類中的doDispatch(request, response)方法中調用getHandlerAdapter(mappedHandler.getHandler())獲取處理器適配器。

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

// 確定當前請求的處理程序適配器。
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
}
// ...
}
// ...
}

  2.getHandlerAdapter(Object handler)方法的具體實現(xiàn)見下源代碼。根據(jù)Handler找到支持它的HandlerAdapter對象。

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

  3.在SimpleControllerHandlerAdapter類中實現(xiàn)了HandlerAdapter接口中的三個抽象方法。

public class SimpleControllerHandlerAdapter implements HandlerAdapter {

@Override
public boolean supports(Object handler) {
// 判斷找到的handler是否為Controller類型。HelloController類實現(xiàn)了Controller接口,所以處理器能夠找到該類
return (handler instanceof Controller);
}

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 通過handler處理器,調用控制器的handlerRequest方法,來處理相應的請求
return ((Controller) handler).handleRequest(request, response);
}

/**
* 與HttpServlet的getLastModified方法的約定相同。在請求處理之前調用。

* 返回值將作為Last-Modified報頭發(fā)送給HTTP客戶端,并與客戶端返回的If-Modified-Since報頭進行比較。只有在進行了修改后,內容才會重新生成。

* 參數(shù):request - 當前HTTP請求

* 返回:上次修改基礎資源的時間,或-1表示必須始終重新生成內容
*/
@Override
@SuppressWarnings("deprecation")
public long getLastModified(HttpServletRequest request, Object handler) {
if (handler instanceof LastModified) {
return ((LastModified) handler).getLastModified(request);
}
return -1L;
}

}

  4.從SimpleControllerHandlerAdapter類中handle方法可以看出,通過HandlerAdapter執(zhí)行Handler對象,最終得到ModelAndView對象。

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// handler處理器執(zhí)行handleRequest方法,主要作用是找到HelloController類中重寫的handleRequest重寫的業(yè)務邏輯方法
return ((Controller) handler).handleRequest(request, response);
}

  4.2 HandlerAdapter的執(zhí)行

  DispatcherServlet會根據(jù)handlerMapping傳過來的controller與已經(jīng)注冊好了的HandlerAdapter相匹配,看哪一種HandlerAdapter是支持該controller類型的,如果找到了其中一種HandlerAdapter是支持傳過來的controller類型,那么該HandlerAdapter會調用自己的handle方法,handle方法運用Java反射機制執(zhí)行controller的具體方法來獲得ModelAndView。

  5 視圖解析器ViewResolver

  SpringMVC用于處理視圖最重要的兩個接口是ViewResolver和View。ViewResolver的主要作用是把一個邏輯上的視圖名稱解析為一個真正的視圖,SpringMVC中用于把View對象呈現(xiàn)給客戶端的是View對象本身,而ViewResolver只是把邏輯視圖名稱解析為對象的View對象。View接口的主要作用是用于處理視圖,然后返回給客戶端。

  5.1 ViewResolver源碼分析

  1.內部資源視圖解析器InternalResourceViewResolver類,進行頁面渲染時,需要使用jstl標準標簽庫。

public class InternalResourceViewResolver extends UrlBasedViewResolver {
// 在進行頁面渲染時,需要使用jstl的標準標簽庫
private static final boolean jstlPresent = ClassUtils.isPresent(
"javax.servlet.jsp.jstl.core.Config", InternalResourceViewResolver.class.getClassLoader());

// ...
}

  2.InternalResourceViewResolver類的父類UrlBasedViewResolver類,根據(jù)返回頁面的名稱拼接前綴和后綴,最終形成一個完整頁面的路徑。例如:/WEB-INF/hello.jsp。

public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {

public static final String REDIRECT_URL_PREFIX = "redirect:"; // 重定向

public static final String FORWARD_URL_PREFIX = "forward:"; // 轉發(fā)

@Nullable
private Class<?> viewClass;

private String prefix = ""; // 前綴

private String suffix = ""; // 后綴

// ...

protected AbstractUrlBasedView buildView(String viewName) throws Exception {
AbstractUrlBasedView view = instantiateView();
view.setUrl(getPrefix() + viewName + getSuffix());
view.setAttributesMap(getAttributesMap());

String contentType = getContentType();
if (contentType != null) {
view.setContentType(contentType);
}

String requestContextAttribute = getRequestContextAttribute();
if (requestContextAttribute != null) {
view.setRequestContextAttribute(requestContextAttribute);
}

Boolean exposePathVariables = getExposePathVariables();
if (exposePathVariables != null) {
view.setExposePathVariables(exposePathVariables);
}
Boolean exposeContextBeansAsAttributes = getExposeContextBeansAsAttributes();
if (exposeContextBeansAsAttributes != null) {
view.setExposeContextBeansAsAttributes(exposeContextBeansAsAttributes);
}
String[] exposedContextBeanNames = getExposedContextBeanNames();
if (exposedContextBeanNames != null) {
view.setExposedContextBeanNames(exposedContextBeanNames);
}

return view;
}

protected View applyLifecycleMethods(String viewName, AbstractUrlBasedView view) {
ApplicationContext context = getApplicationContext();
if (context != null) {
Object initialized = context.getAutowireCapableBeanFactory().initializeBean(view, viewName);
if (initialized instanceof View) {
return (View) initialized;
}
}
return view;
}
}

  5.2 ViewResolver解析流程

  1.將SpringMVC控制器中的返回結果封裝成一個ModelAndView對象。

  2.通過SpringMVC中的視圖解析器,使用ViewResolver對控制器返回的ModelAndView對象進行解析,將邏輯視圖轉換成物理視圖。

  3.調用View接口中的render()方法對物理視圖進行渲染。

  6 SpringMVC執(zhí)行流程分析

  1.SpringMVC執(zhí)行流程圖

  2.SpringMVC執(zhí)行步驟

  1.客戶端瀏覽器發(fā)送請求給服務器中的前端控制器DispatcherServlet;

  2.用戶根據(jù)請求中的url路徑,通過HandlerMapping處理器映射器,找到匹配的Controller;

  3.HandlerMapping返回一個處理器執(zhí)行鏈,包括N個攔截器與1個Controller的處理器。并把處理器執(zhí)行鏈,返回給前端控制器DispatcherServlet;

  4.前端控制器DispatcherServlet得到處理器執(zhí)行鏈之后,把Controller的Handler發(fā)送給HandlerAdapter處理器適配器;

  5.HandlerAdapter根據(jù)supports(Object handler)方法,也就是內部的匹配規(guī)則,判斷該處理器Handler是否實現(xiàn)了Controller接口;

  6.Handler處理器找到具體的方法handler.handleRequest(request, response),根據(jù)請求執(zhí)行Controller類中的方法;

  7.Controller類執(zhí)行完畢,然后返回一個ModelAndView對象給Handler處理器;

  8.Handler處理器把ModelAndView對象返回給HandlerAdapter;

  9.HandlerAdapter把ModelAndView對象返回給前端控制器DispathcerServlet;

  10.DispathcerServlet把ModelAndView對象傳遞給ViewResolver視圖解析器,根據(jù)jsp頁面的名稱拼接路;

  11.ViewResolver視圖解析器返回給DispathcerServlet前端控制器;

  12.DispathcerServlet拿到jsp路徑,由web容器對jsp頁面進行視圖渲染;

  13.Web容器把響應結果返回給瀏覽器。

  3.SpringMVC核心組件

QQ截圖20230309160031

好程序員公眾號

  • · 剖析行業(yè)發(fā)展趨勢
  • · 匯聚企業(yè)項目源碼

好程序員開班動態(tài)

More+
  • HTML5大前端 <高端班>

    開班時間:2021-04-12(深圳)

    開班盛況

    開班時間:2021-05-17(北京)

    開班盛況
  • 大數(shù)據(jù)+人工智能 <高端班>

    開班時間:2021-03-22(杭州)

    開班盛況

    開班時間:2021-04-26(北京)

    開班盛況
  • JavaEE分布式開發(fā) <高端班>

    開班時間:2021-05-10(北京)

    開班盛況

    開班時間:2021-02-22(北京)

    開班盛況
  • Python人工智能+數(shù)據(jù)分析 <高端班>

    開班時間:2021-07-12(北京)

    預約報名

    開班時間:2020-09-21(上海)

    開班盛況
  • 云計算開發(fā) <高端班>

    開班時間:2021-07-12(北京)

    預約報名

    開班時間:2019-07-22(北京)

    開班盛況
IT培訓IT培訓
在線咨詢
IT培訓IT培訓
試聽
IT培訓IT培訓
入學教程
IT培訓IT培訓
立即報名
IT培訓

Copyright 2011-2023 北京千鋒互聯(lián)科技有限公司 .All Right 京ICP備12003911號-5 京公網(wǎng)安備 11010802035720號