国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

【SpringMVC】SpringMVC初學詳解篇

2019-11-06 08:48:59
字體:
來源:轉載
供稿:網(wǎng)友

      SPRingMVC是一個基于MVC的Web框架,是spring框架的一個模塊,使用了MVC架構模式的思想,將web層進行職責解耦。首先讓我們整體看一下SpringMVC處理請求的流程:

發(fā)起請求到前端控制器(DispatcherServlet)前端控制器請求HandlerMapping查找Handler,可以根據(jù)xml配置、注解進行查找處理器映射器HandlerMapping向前端控制器返回Handler前端控制器調用處理器適配器去執(zhí)行Handler處理器適配器去執(zhí)行HandlerHandler執(zhí)行完成給適配器返回ModelAndView處理器適配器向前端控制器返回ModelAndView(springmvc框架的一個底層對象,包括Model和view)前端控制器請求視圖解析器去進行視圖解析,根據(jù)邏輯視圖名解析成真正的視圖(jsp)視圖解析器向前端控制器返回View前端控制器進行視圖渲染,視圖渲染將模型數(shù)據(jù)(在ModelAndView對象中)填充到request域前端控制器向用戶響應結果

源碼分析】

      首先是SpringMVC的入口類DispatcherServlet,該類其實是一個servlet類,(可以從web.xml文件的配置中直接點擊進去查看類源碼),前端控制器接收到請求之后,會調用它的doService方法,然后調用doDispatch方法,重點就是doDispatch方法,源碼如下:

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);			// 如果請求方式為multipart,則通過multipart進行解析			multipartRequestParsed = processedRequest != request;			// Determine handler for the current request.(上圖中的步驟2:通過調用getHandler方法,調用處理器映射器HandlerMapping查找Handler,詳見方法二)			mappedHandler = getHandler(processedRequest, false);			if (mappedHandler == null || mappedHandler.getHandler() == null) {				noHandlerFound(processedRequest, response);				return;			}			// Determine handler adapter for the current request.(根據(jù)處理器得到相應的適配器)			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;				}			}                                //執(zhí)行預處理			if (!mappedHandler.applyPreHandle(processedRequest, response)) {				return;			}			try {				// Actually invoke the handler.(上圖中步驟4:請求處理器適配器HandlerAdapter執(zhí)行Handler)				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());			}			finally {				if (asyncManager.isConcurrentHandlingStarted()) {					return;				}			}			applyDefaultViewName(request, mv);			// 執(zhí)行相應的后處理			mappedHandler.applyPostHandle(processedRequest, response, mv);		}		catch (Exception ex) {			dispatchException = ex;		}		//該方法詳情見方法三(上圖中的步驟8、9、10)		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);		}	}}

②方法二(getHandler方法源碼)

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

③方法三(processDispatchResult方法源碼)

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,			HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {		boolean errorView = false;		if (exception != null) {			if (exception instanceof ModelAndViewDefiningException) {				logger.debug("ModelAndViewDefiningException encountered", exception);				mv = ((ModelAndViewDefiningException) exception).getModelAndView();			}			else {				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);				mv = processHandlerException(request, response, handler, exception);				errorView = (mv != null);			}		}		// Did the handler return a view to render?(上圖中的步驟8:通過render方法,請求視圖解析器view Resolver解析視圖,具體源碼如方法四)		if (mv != null && !mv.wasCleared()) {			render(mv, request, 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");			}		}		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {			// Concurrent handling started during a forward			return;		}		if (mappedHandler != null) {			mappedHandler.triggerAfterCompletion(request, response, null);		}	}

④方法四(render方法源碼)

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {	// Determine locale for request and apply it to the response.	Locale locale = this.localeResolver.resolveLocale(request);	response.setLocale(locale);	View view;	if (mv.isReference()) {		// We need to resolve the view name.		view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);		if (view == null) {			throw new ServletException(					"Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" +							getServletName() + "'");		}	}	else {		// No need to lookup: the ModelAndView object contains the actual View object.		view = mv.getView();		if (view == null) {			throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +					"View object in servlet with name '" + getServletName() + "'");		}	}	// Delegate to the View object for rendering.	if (logger.isDebugEnabled()) {		logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");	}	view.render(mv.getModelInternal(), request, response);}

【優(yōu)點】

      1、清晰的角色劃分:前端控制器(DispatcherServlet)、請求到處理器映射(HandlerMapping)、處理器適配器(HandlerAdapter)、視圖解析器(ViewResolver)、處理器或頁面控制器(Controller)、驗證器(   Validator)、命令對象(Command  請求參數(shù)綁定到的對象就叫命令對象)、表單對象(Form Object提供給表單展示和提交到的對象就叫表單對象)。

      2、和Spring其他框架無縫集成,是其它Web框架所不具備的;

      3、可適配,通過HandlerAdapter可以支持任意的類作為處理器;

      4、可定制性,HandlerMapping、ViewResolver等能夠非常簡單的定制;

      5、功能強大的數(shù)據(jù)驗證、格式化、綁定機制;

      6、強大的JSP標簽庫,使JSP編寫更容易。

【缺點】

      1.SpringMVC與servlet API耦合,難以脫離servlet容器獨立運行,降低了SpringMVC框架的可擴展性。

      2.太過細化的角色劃分,太過繁瑣,降低了應用的開發(fā)效率。

【入門小程序】

開發(fā)環(huán)境:eclipse、MySQL、JDK、tomcat、引入如下圖所示jar包(點擊鏈接下載jar包)

程序結構如下:

①Items類:

package cn.itcast.ssm.po;import java.util.Date;public class Items {	private Integer id;	private String name;	private Float price;	private String pic;	private Date createtime;	private String detail;	// get和set方法略	}

②Web.xml代碼:

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"	xmlns="http://java.sun.com/xml/ns/javaee"	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"	id="WebApp_ID" version="3.0">	<display-name>mySpringMVC</display-name>	<!-- springmvc前端控制器 -->	<servlet>		<servlet-name>springmvc</servlet-name>		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>		<!-- contextConfigLocation配置springmvc加載的配置文件(配置處理器映射器、適配器等等)如果不配置,默認加載的是WEB-INF/servlet名稱-servlet.xml -->		<init-param>			<param-name>contextConfigLocation</param-name>			<param-value>classpath:springmvc.xml</param-value>		</init-param>	</servlet>	<!-- 第一種:*.action,訪問以.action結尾 由DispatcherServlet進行解析 第二種:/,所以訪問的地址都由DispatcherServlet進行解析,對于靜態(tài)文件的解析需要配置不讓DispatcherServlet進行解析 		使用此種方式可以實現(xiàn) RESTful風格的url 第三種:/*,這樣配置不對,使用這種配置,最終要轉發(fā)到一個jsp頁面時, 仍然會由DispatcherServlet解析jsp地址,不能根據(jù)jsp頁面找到handler,會報錯。 -->	<servlet-mapping>		<servlet-name>springmvc</servlet-name>		<url-pattern>*.action</url-pattern>	</servlet-mapping>	<welcome-file-list>		<welcome-file>index.html</welcome-file>		<welcome-file>index.htm</welcome-file>		<welcome-file>index.jsp</welcome-file>		<welcome-file>default.html</welcome-file>		<welcome-file>default.htm</welcome-file>		<welcome-file>default.jsp</welcome-file>	</welcome-file-list></web-app>

③Springmvc.xml代碼:

<beans xmlns="http://www.springframework.org/schema/beans"	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"	xmlns:context="http://www.springframework.org/schema/context"	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"	xsi:schemaLocation="http://www.springframework.org/schema/beans 		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 		http://www.springframework.org/schema/mvc 		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 		http://www.springframework.org/schema/context 		http://www.springframework.org/schema/context/spring-context-3.2.xsd 		http://www.springframework.org/schema/aop 		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 		http://www.springframework.org/schema/tx 		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">	<!-- **************************************************************************************** -->	<!-- 配置Handler -->	<bean name="/queryItems.action" class="cn.itcast.ssm.controller.ItemsController1" />	<!-- **************************************************************************************** -->	<!-- **************************************************************************************** -->	<!-- 處理器映射器 -->	<!-- 將bean的name作為 URL進行查詢,需要在配置Handler時指定beanname(就是url) -->	<bean		class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />	<!-- **************************************************************************************** -->	<!-- **************************************************************************************** -->	<!-- 處理器適配器 -->	<!-- 所有的處理器適配器都實現(xiàn)HandlerAdapter接口,該接口中有boolean supports(Object handler); 		方法,通過這個supports方法來判斷尋找相應的Handler -->	<bean		class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />	<!-- **************************************************************************************** -->	<!-- **************************************************************************************** -->	<!-- 視圖解析器 -->	<!--解析jsp解析,默認使用jstl標簽,classpath下的得有jstl的包 -->	<bean		class="org.springframework.web.servlet.view.InternalResourceViewResolver">	</bean>	<!-- **************************************************************************************** --></beans>

④controller代碼:

package cn.itcast.ssm.controller;import java.util.ArrayList;import java.util.List;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;import cn.itcast.ssm.po.Items;/** * 實現(xiàn)controller接口的處理器 *  * @author happy * */public class ItemsController1 implements Controller {	@Override	public ModelAndView handleRequest(HttpServletRequest request,			HttpServletResponse response) throws Exception {		// 調用Services查找數(shù)據(jù)庫,查詢商品列表,這里使用靜態(tài)數(shù)據(jù)模擬		List<Items> itemsList = new ArrayList<Items>();		// 想List中填充靜態(tài)數(shù)據(jù)		Items items_1 = new Items();		items_1.setName("聯(lián)想筆記本");		items_1.setPrice(6000f);		items_1.setDetail("ThinkPad T430 聯(lián)想筆記本電腦!");		Items items_2 = new Items();		items_2.setName("蘋果手機");		items_2.setPrice(5000f);		items_2.setDetail("iphone6蘋果手機!");		itemsList.add(items_1);		itemsList.add(items_2);		// 返回ModelAndView		ModelAndView modelAndView = new ModelAndView();		// 相當于request的setAttribute,在jsp頁面中通過itemsList取數(shù)據(jù)		modelAndView.addObject("itemsList", itemsList);		// 指定視圖		modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");		return modelAndView;	}}

⑤itemsList.jsp代碼:

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>查詢商品列表</title></head><body> <form action="${pageContext.request.contextPath }/item/queryItem.action" method="post">查詢條件:<table width="100%" border=1><tr><td><input type="submit" value="查詢"/></td></tr></table>商品列表:<table width="100%" border=1><tr>	<td>商品名稱</td>	<td>商品價格</td>	<td>生產日期</td>	<td>商品描述</td>	<td>操作</td></tr><c:forEach items="${itemsList }" var="item"><tr>	<td>${item.name }</td>	<td>${item.price }</td>	<td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>	<td>${item.detail }</td>		<td><a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a></td></tr></c:forEach></table></form></body></html>


上一篇:重在堅持

下一篇:單源最短路徑

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 延川县| 南阳市| 庄河市| 龙州县| 竹北市| 独山县| 监利县| 天台县| 芦溪县| 介休市| 漠河县| 屏边| 曲麻莱县| 潮州市| 突泉县| 察哈| 辉县市| 龙里县| 从化市| 兴安盟| 黎川县| 梅州市| 宁陕县| 宜兰市| 峡江县| 广平县| 玛纳斯县| 新野县| 司法| 南康市| 连城县| 广安市| 永和县| 龙岩市| 周口市| 顺昌县| 怀柔区| 巴林右旗| 东辽县| 连山| 北安市|