主要名詞解釋
DispatcherServlet 前端控制器 相當於一個轉發器
入口:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception
HandlerMapping 處理器映射器
核心方法HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
對HandlerExecutionChain稍微解釋下,並不是我一開始理解的由很多個Handler組成的鏈,而是一個Hanler和多個攔截器interceptor
源碼爲證:
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
private final Object handler;
private HandlerInterceptor[] interceptors;
private List<HandlerInterceptor> interceptorList;
private int interceptorIndex = -1;
HandlerAdapter 處理器適配器
核心方法:
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
ViewResolver 視圖解析器
核心方法
View resolveViewName(String viewName, Locale locale) throws Exception;
ModelAndView 模型和視圖的結合體 是一個底層對象
部分源碼方便理解
public class ModelAndView {
/** View instance or view name String */
private Object view;
/** Model Map */
private ModelMap model;
View 視圖
核心方法:渲染
void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
Handler處理器也就是Controller
源碼如下:
public interface Controller {
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
非註解的處理器映射器(多個處理器映射器可共存)
1、BeanNameUrlHandlerMapping
Bean的Name作爲URL 的處理器映射器
示範:
<bean name="/queryItems.action" class="com.study.controller.ItemsController" />
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
- SimpleUrlHandlerMapping
簡單URL處理器映射器
示範:
<bean id="id1" class="com.study.controller.ItemsController1" />
<bean id="id2" class="com.study.controller.ItemsController2" />
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mapping">
<props>
<!-- 在這裏面進行配置 -->
<prop key="/url1">id1</prop>
<prop key="/url2">id2</prop>
<!-- 一個id可以對應多個key -->
<prop key="/url3">id1</prop>
</props>
</property>
</bean>
非註解的處理器適配器
- SimpleControllerHandlerAdapter
簡單Controller處理器適配器
直接實現Controller接口
<bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
示範創建一個ItemsController處理器:
public class ItemsController implements Controller {
/*
* 自己的Controller實現Controller接口中handleRequest方法
*/
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
// 此處採用代碼方式建對象提供測試,實際中通過和MyBatis等框架整合查詢數據庫得到數據並由ORM(對象關係映射)轉換成對象進行操作
// 像商品列表中添加三條數據
List<Item> itemlist = new ArrayList<Item>();
itemlist.add(new Item("蘋果", 5.2));
itemlist.add(new Item("香蕉", 1.5));
itemlist.add(new Item("梨子", 3.4));
// ModelAndView 是模型和視圖的結合體
// model中添加的Object會被添加到request請求域,使用addObject(String,Object)相當於request.setAttribute(String,Object)
ModelAndView mav = new ModelAndView();
// 將商品列表對象放入ModelAndView
mav.addObject("itemlist", itemlist);
// 設置邏輯視圖名
mav.setViewName("ListItems.jsp");
return mav;
}
}
- HttpRequestHandlerAdapter
實現HttpRequestHandler接口
示範創建一個處理器ItemsController2
使用此方法可以針對於返回JSON數據的情況可以操response
res.setCharacterEncoding("utf-8");
res.setContentType("application/json;charset=utf-8");
res.getWriter().write("你的JSON字符串");
public class ItemsController2 implements HttpRequestHandler {
/*
* 自己的Controller實現Controller接口中handleRequest方法
*/
@Override
public void handleRequest(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// 此處採用代碼方式建對象提供測試,實際中通過和MyBatis等框架整合查詢數據庫得到數據並由ORM(對象關係映射)轉換成對象進行操作
// 像商品列表中添加三條數據
List<Item> itemlist = new ArrayList<Item>();
itemlist.add(new Item("蘋果", 5.2));
itemlist.add(new Item("香蕉", 1.5));
itemlist.add(new Item("梨子", 3.4));
//Model填充
req.setAttribute("itemlist", itemlist);
//ViewResolver
req.getRequestDispatcher("ListItems.jsp").forward(req, res);
//可以針對只需要返回JSON字符串的情況
// res.setCharacterEncoding("utf-8");
// res.setContentType("application/json;charset=utf-8");
// res.getWriter().write("你的JSON字符串");
}
}
基於註解的處理器映射器
版本區別
注意點:Spring MVC 3.1版本之前使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
3.1版本之後使用
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
基於註解的處理器適配器
版本區別
注意點:Spring MVC 3.1版本之前使用org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
3.1版本之後使用
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
<!--
註解方式配置第二種做法 使用mvc:annotation-driven
兩種方式任選其一
區別點在於
mvc:annotation-driven方式默認加載了很多參數綁定方法,比如JSON解析器就默認加載了
實際開發中使用mvc:annotation-driven這種方式
-->
<!-- <mvc:annotation-driven></mvc:annotation-driven> -->
註解的處理器映射器需要搭配註解的處理器適配器同時使用
註解方式和非註解方式同時使用並搶佔同一個URL的時候按照xml中配置的先後順序,先配置的處理器映射器被使用
註解語法
1、@Controller
使用@Controller註解標誌該類爲一個Controller
2、@RequestMapping(“url”)
使用@RequestMapping(“/myurl.action”)註解標誌下面的方法映射到“/myurl.action”
示範如下
@Controller
public class ItemsController3 {
/*
* 註解開發Handler
*/
@RequestMapping("/queryItems.action")
public ModelAndView queryItems() throws Exception{
// 此處採用代碼方式建對象提供測試,實際中通過和MyBatis等框架整合查詢數據庫得到數據並由ORM(對象關係映射)轉換成對象進行操作
// 像商品列表中添加三條數據
List<Item> itemlist = new ArrayList<Item>();
itemlist.add(new Item("蘋果", 5.2));
itemlist.add(new Item("香蕉", 1.5));
itemlist.add(new Item("梨子", 3.4));
// ModelAndView 是模型和視圖的結合體
// model中添加的Object會被添加到request請求域,使用addObject(String,Object)相當於request.setAttribute(String,Object)
ModelAndView mav = new ModelAndView();
// 將商品列表對象放入ModelAndView
mav.addObject("itemlist", itemlist);
// 設置邏輯視圖名
mav.setViewName("ListItems.jsp");
return mav;
}
}
開發完Handler需要將Handler配置到springmvcconfig.xml
單個配置方式如下
<bean class="com.study.controller.ItemsController3" />
掃描包內組件的方式如下
<context:component-scan base-package="com.study.controller"></context:component-scan>
深入源碼分析Spring MVC框架
只複製了關鍵步驟代碼其他代碼省略
- 請求到達Spring MVC框架
入口如下
類名:DispatcherServlet
方法名:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception
- 上述方法中執行
HandlerExecutionChain mappedHandler = null;
...
mappedHandler = getHandler(processedRequest);
根據Request拿到HandlerExecutionChain
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
通過HandlerExecutionChain中的getHandler()方法拿到Handler
ModelAndView mv = null;
.....
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
- 通過HandlerAdapter中的handle方法執行處理器中的處理並返回ModelAndView
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
調用該方法來執行轉發結果、也就是進行最後一步視圖渲染
在processDispatchResult方法中調用render(mv, request, response);方法
在render方法中調用了view.render(mv.getModelInternal(), request, response);
View對象中的render方法並沒有處理,只是個接口
然後AbstractView這個抽象類實現了View接口
如下圖
然後AbstractUrlBasedView 繼承了AbstractView
public abstract class AbstractUrlBasedView extends AbstractView implements InitializingBean {
然後內置解析器 InternalResourceView繼承了 AbstractUrlBasedView
public class InternalResourceView extends AbstractUrlBasedView {
我們的JSP頁面最終調用的是InternalResourceView內置的視圖解析器
項目包已壓縮爲ZIP文件,大小8M地址http://xingxunxinxi.com/source/SpringMVC_Study.zip