轉:SpringMVC淺談

由於項目文案須要,因而乎翻閱spring相關資料。頓覺該篇不錯詳盡易懂,特轉載之。javascript

轉載出處:css

http://blog.csdn.net/gane_cheng/article/details/52787040html

http://www.ganecheng.tech/blog/52787040.html (瀏覽效果更好)前端

 

Spring是一個開源框架,Spring是於2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson建立。簡單來講,Spring是一個開源的控制反轉(Inversion of Control ,IoC)和麪向切面(AOP)的容器框架。它的主要目得是簡化企業開發。java

1. Spring框架包括什麼?

這裏寫圖片描述

Spring 框架是一個分層架構,由 7 個定義良好的模塊組成。Spring 模塊構建在覈心容器之上,核心容器定義了建立、配置和管理 bean 的方式。程序員

Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程序的 MVC 實現。經過策略接口,MVC 框架變成爲高度可配置的,MVC 容納了大量視圖技術,其中包括 JSP、Velocity、Tiles、iText 和 POI。web

1.1. MVC在B/S系統 下的應用

MVC是一個設計模式,MVC在B/S系統 下的應用:spring

這裏寫圖片描述

1.2. SpringMVC框架

這裏寫圖片描述

執行步驟:數據庫

第一步:發起請求到前端控制器(DispatcherServlet)apache

第二步:前端控制器請求HandlerMapping查找 Handler 能夠根據xml配置、註解進行查找

第三步:處理器映射器HandlerMapping向前端控制器返回Handler

第四步:前端控制器調用處理器適配器去執行Handler

第五步:處理器適配器去執行Handler

第六步:Handler執行完成給適配器返回ModelAndView

第七步:處理器適配器向前端控制器返回ModelAndView                 ModelAndView是SpringMVC框架的一個底層對象,包括 Model和view

第八步:前端控制器請求視圖解析器去進行視圖解析                 根據邏輯視圖名解析成真正的視圖(jsp)

第九步:視圖解析器向前端控制器返回View

第十步:前端控制器進行視圖渲染                 視圖渲染將模型數據(在ModelAndView對象中)填充到request域

第十一步:前端控制器向用戶響應結果

組件:

一、前端控制器DispatcherServlet(不須要程序員開發) 做用接收請求,響應結果,至關於轉發器,中央處理器。 有了DispatcherServlet減小了其它組件之間的耦合度。

二、處理器映射器HandlerMapping(不須要程序員開發) 做用:根據請求的url查找Handler

三、處理器適配器HandlerAdapter 做用:按照特定規則(HandlerAdapter要求的規則)去執行Handler

四、處理器Handler(須要程序員開發) 注意:編寫Handler時按照HandlerAdapter的要求去作,這樣適配器才能夠去正確執行Handler

五、視圖解析器View resolver(不須要程序員開發) 做用:進行視圖解析,根據邏輯視圖名解析成真正的視圖(view)

六、視圖View(須要程序員開發jsp) View是一個接口,實現類支持不一樣的View類型(jsp、freemarker、pdf...)

1.3. 配置前端控制器

在web.xml中配置前端控制器。

<!-- SpringMVC前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- contextConfigLocation配置SpringMVC加載的配置文件(配置處理器映射器、適配器等等) 若是不配置contextConfigLocation,默認加載的是/WEB-INF/servlet名稱-serlvet.xml(springmvc-servlet.xml) --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 第一種:*.action,訪問以.action結尾 由DispatcherServlet進行解析 第二種:/,因此訪問的地址都由DispatcherServlet進行解析,對於靜態文件的解析須要配置不讓DispatcherServlet進行解析 使用此種方式能夠實現 RESTful風格的url 第三種:/*,這樣配置不對,使用這種配置,最終要轉發到一個jsp頁面時, 仍然會由DispatcherServlet解析jsp地址,不能根據jsp頁面找到handler,會報錯。 --> <url-pattern>*.action</url-pattern> </servlet-mapping> 

1.4. 配置處理器適配器(非註解方式)

在classpath下的springmvc.xml中配置處理器適配器

<!-- 處理器適配器 全部處理器適配器都實現 HandlerAdapter接口 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> <!-- 另外一個非註解的適配器 --> <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/> 

查看源碼

SimpleControllerHandlerAdapter.java

public class SimpleControllerHandlerAdapter implements HandlerAdapter { public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response); } } public interface Controller { ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; } 

HttpRequestHandlerAdapter.java

public class HttpRequestHandlerAdapter implements HandlerAdapter { public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { ((HttpRequestHandler) handler).handleRequest(request, response); return null; } } public interface HttpRequestHandler { void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; } 

1.5. 配置處理器Handler(非註解方式)

編寫Handler類

方式①:須要實現 Controller接口,才能由org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter適配器執行。

public class ItemsController1 implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { //調用Service查找 數據庫,查詢商品列表,這裏使用靜態數據模擬 List<Items> itemsList = new ArrayList<Items>(); //向list中填充靜態數據 Items items_1 = new Items(); items_1.setName("聯想筆記本"); items_1.setPrice(6000f); items_1.setDetail("ThinkPad T430 聯想筆記本電腦!"); 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的setAttribut,在jsp頁面中經過itemsList取數據 modelAndView.addObject("itemsList", itemsList); //指定視圖 modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp"); return modelAndView; } } 

方式②:須要實現 HttpRequestHandler接口,才能由org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter 適配器執行。

public class ItemsController2 implements HttpRequestHandler { @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //調用Service查找 數據庫,查詢商品列表,這裏使用靜態數據模擬 List<Items> itemsList = new ArrayList<Items>(); //向list中填充靜態數據 Items items_1 = new Items(); items_1.setName("聯想筆記本"); items_1.setPrice(6000f); items_1.setDetail("ThinkPad T430 聯想筆記本電腦!"); Items items_2 = new Items(); items_2.setName("蘋果手機"); items_2.setPrice(5000f); items_2.setDetail("iphone6蘋果手機!"); itemsList.add(items_1); itemsList.add(items_2); //設置模型數據 request.setAttribute("itemsList", itemsList); //設置轉發的視圖 request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response); //使用此方法能夠經過修改response,設置響應的數據格式,好比響應json數據 /* response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json串");*/ } } 

將編寫Handler在spring容器加載。

<!-- 配置Handler --> <bean id="itemsController1" name="/queryItems.action" class="cn.itcast.ssm.controller.ItemsController1" /> <!-- 配置另一個Handler --> <bean id="itemsController2" class="cn.itcast.ssm.controller.ItemsController2" /> 

1.6. 配置處理器映射器(非註解方式)

在classpath下的springmvc.xml中配置處理器映射器

處理器映射器: org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping

另外一個映射器: org.springframework.web.servlet.handler.SimpleUrlHandlerMapping

<!-- 處理器映射器① 將bean的name做爲url進行查找 ,須要在配置Handler時指定beanname(就是url) 全部的映射器都實現 HandlerMapping接口。 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> 
<!--處理器映射器② 簡單url映射 --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <!-- 對itemsController1的Handler進行url映射,url是/queryItems1.action --> <prop key="/queryItems1.action">itemsController1</prop> <prop key="/queryItems2.action">itemsController1</prop> <prop key="/queryItems3.action">itemsController2</prop> </props> </property> </bean> 

1.7. 配置視圖解析器

須要配置解析jsp的視圖解析器。

<!-- 視圖解析器 解析jsp解析,默認使用jstl標籤,classpath下的得有jstl的包 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置jsp路徑的前綴 --> <property name="prefix" value="/WEB-INF/jsp/"/> <!-- 配置jsp路徑的後綴 --> <property name="suffix" value=".jsp"/> </bean> 

1.8. DispatcherSerlvet.properties

這裏寫圖片描述

前端控制器從上邊的文件中加載處理映射器、適配器、視圖解析器等組件,若是不在springmvc.xml中配置,使用默認加載的。

# Default implementation classes for DispatcherServlet's strategy interfaces. # Used as fallback when no matching beans are found in the DispatcherServlet context. # Not meant to be customized by application developers. org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver #處理器映射器 org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping #處理器適配器 org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator #視圖解析器 org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager 

手動在配置文件中配置處理器Handler,處理器映射器HandlerMapping,若是在文件太多的狀況下會比較麻煩。並且每次都要實現Controller接口和HttpRequestHandler接口,而且只有一個實現方法。每次爲了一個方法去實現接口,會形成Handler類愈來愈多。太麻煩。SpringMVC提供了註解模式開發處理器Handler,大大下降了工做量,提升了易用性。

1.9. 註解模式開發處理器Handler

註解模式的處理器映射器HandlerMapping和處理器適配器HandlerAdapter須要這樣配置。

使用註解的映射器和註解的適配器。(註解的映射器和註解的適配器必須配對使用)

<!--註解映射器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!--註解適配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> 
<!-- 使用 mvc:annotation-driven代替上邊註解映射器和註解適配器配置 mvc:annotation-driven默認加載不少的參數綁定方法, 好比json轉換解析器就默認加載了,若是使用mvc:annotation-driven不用配置上邊的RequestMappingHandlerMapping和RequestMappingHandlerAdapter 實際開發時使用mvc:annotation-driven --> <!-- <mvc:annotation-driven></mvc:annotation-driven> --> 

編寫Handler,無需繼承任何接口,僅需加入@Controller註解

//使用Controller標識 它是一個控制器 @Controller public class ItemsController3 { //商品查詢列表 //@RequestMapping實現 對queryItems方法和url進行映射,一個方法對應一個url //通常建議將url和方法寫成同樣 @RequestMapping("/queryItems") public ModelAndView queryItems()throws Exception { //調用Service查找 數據庫,查詢商品列表,這裏使用靜態數據模擬 List<Items> itemsList = new ArrayList<Items>(); //向list中填充靜態數據 Items items_1 = new Items(); items_1.setName("聯想筆記本"); items_1.setPrice(6000f); items_1.setDetail("ThinkPad T430 聯想筆記本電腦!"); 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的setAttribut,在jsp頁面中經過itemsList取數據 modelAndView.addObject("itemsList", itemsList); //指定視圖 modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp"); return modelAndView; } 

在spring容器中加載Handler(使用註解掃描方式加載)

<!-- 對於註解的Handler能夠單個配置 實際開發中建議使用組件掃描 --> <!-- <bean class="cn.itcast.ssm.controller.ItemsController3" /> --> <!-- 能夠掃描Controller、Service、... 這裏讓掃描Controller,指定Controller的包 --> <context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan> 

使用以上配置,就能夠運行起來SpringMVC程序了。

1.10. 註解方式開發總結

對標記@Controller類中標識有@RequestMapping的方法進行映射。在@RequestMapping裏邊定義映射的url。使用註解的映射器不用在xml中配置url和Handler的映射關係。

註解處理器適配器和註解的處理器映射器是配對使用。理解爲不能使用非註解映射器進行映射。

<mvc:annotation-driven></mvc:annotation-driven>能夠代替下邊的配置:

<!--註解映射器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!--註解適配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> 

視圖解析器配置前綴和後綴:

<!-- 視圖解析器 解析jsp解析,默認使用jstl標籤,classpath下的得有jstl的包 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置jsp路徑的前綴 --> <property name="prefix" value="/WEB-INF/jsp/"/> <!-- 配置jsp路徑的後綴 --> <property name="suffix" value=".jsp"/> </bean> 

程序中不用指定前綴和後綴:

//沒有前綴和後綴時 modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp"); //有前綴和後綴時 modelAndView.setViewName("items/itemsList"); 

1.11. SpringMVC源碼分析

經過前端控制器源碼分析SpringMVC的執行過程。

第一步:前端控制器接收請求

調用doDiapatch

public class DispatcherServlet extends FrameworkServlet { 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); multipartRequestParsed = processedRequest != request; // Determine handler for the current request. mappedHandler = getHandler(processedRequest, false); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. 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; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } try { // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } finally { if (asyncManager.isConcurrentHandlingStarted()) { return; } } applyDefaultViewName(request, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } 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); } } } } 

第二步:前端控制器調用處理器映射器查找 Handler

// Determine handler for the current request. mappedHandler = getHandler(processedRequest, false); public class DispatcherServlet extends FrameworkServlet { 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; } } 

第三步:調用處理器適配器執行Handler,獲得執行結果ModelAndView

// Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 

第四步:視圖渲染,將model數據填充到request域。

視圖解析,獲得view:

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

render(mv, request, response);

    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); } // We need to resolve the view name. view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); 

調用view的渲染方法,將model數據填充到request域

渲染方法:

view.render(mv.getModelInternal(), request, response);

    protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception { for (Map.Entry<String, Object> entry : model.entrySet()) { String modelName = entry.getKey(); Object modelValue = entry.getValue(); if (modelValue != null) { request.setAttribute(modelName, modelValue); if (logger.isDebugEnabled()) { logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() + "] to request in view with name '" + getBeanName() + "'"); } } else { request.removeAttribute(modelName); if (logger.isDebugEnabled()) { logger.debug("Removed model object '" + modelName + "' from request in view with name '" + getBeanName() + "'"); } } } } 

1.12. Controller的@RequestMapping

① url映射

定義Controller方法對應的url,進行處理器映射使用。

② 窄化請求映射

@Controller // 爲了對url進行分類管理 ,能夠在這裏定義根路徑,最終訪問url是根路徑+子路徑 // 好比:商品列表:/items/queryItems.action @RequestMapping("/items") public class ItemsController { } 

③ 限制http請求方法

出於安全性考慮,對http的連接進行方法限制。 若是限制請求爲post方法,進行get請求,則會報錯。

//限制http請求方法,只能夠post @RequestMapping(value="/editItems",method={RequestMethod.POST}) public ModelAndView editItems()throws Exception { } 

1.13. Controller方法的返回值

在編寫控制器Handler能夠有三種返回值。

  • 返回ModelAndView
  • 返回String
  • 返回void

① 返回ModelAndView

須要方法結束時,定義ModelAndView,將model和view分別進行設置。

② 返回String

若是Controller方法返回String,能夠有如下三種形式。

(1)、表示返回邏輯視圖名。

真正視圖(jsp路徑)=前綴+邏輯視圖名+後綴

@RequestMapping(value="/editItems",method={RequestMethod.POST,RequestMethod.GET}) public String editItems(Model model)throws Exception { //調用Service根據商品id查詢商品信息 ItemsCustom itemsCustom = itemsService.findItemsById(1); //將商品信息放到model model.addAttribute("itemsCustom", itemsCustom); return "items/editItems"; } 

(2)、redirect重定向

redirect重定向特色:瀏覽器地址欄中的url會變化。修改提交的request數據沒法傳到重定向的地址。由於重定向後從新進行request(request沒法共享)

return "redirect:items/queryItems.action"; 

(3)、forward頁面轉發

經過forward進行頁面轉發,瀏覽器地址欄url不變,request能夠共享。

return "forward:items/queryItems.action"; 

③ 返回void

在Controller方法形參上能夠定義request和response,使用request或response指定響應結果:

(1)、使用request轉向頁面,以下:

request.getRequestDispatcher("頁面路徑").forward(request, response); 

(2)、也能夠經過response頁面重定向:

response.sendRedirect("url"); 

(3)、也能夠經過response指定響應結果,例如響應json數據以下:

response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json串"); 

1.14. Controller參數綁定

SpringMVC參數綁定過程

從客戶端請求key/value數據,通過參數綁定,將key/value數據綁定到Controller方法的形參上。

SpringMVC中,接收頁面提交的數據是經過方法形參來接收。而不是在Controller類定義成員變量接收!!!!(與Struts2明顯不一樣的實現邏輯)

這裏寫圖片描述

(1) 默認支持的類型

直接在Controller方法形參上定義下邊類型的對象,就可使用這些對象。在參數綁定過程當中,若是遇到下邊類型直接進行綁定。

① HttpServletRequest

經過request對象獲取請求信息

② HttpServletResponse

經過response處理響應信息

③ HttpSession

經過session對象獲得session中存放的對象

④ Model/ModelMap

model是一個接口,modelMap是一個接口實現 。

做用:將model數據填充到request域。

(2) 簡單類型

經過@RequestParam對簡單類型的參數進行綁定。

若是不使用@RequestParam,要求request傳入參數名稱和Controller方法的形參名稱一致,方可綁定成功。

若是使用@RequestParam,不用限制request傳入參數名稱和Controller方法的形參名稱一致。

經過required屬性指定參數是否必需要傳入,若是設置爲true,沒有傳入參數,則會報錯。

// @RequestParam裏邊指定request傳入參數名稱和形參進行綁定。 // 經過required屬性指定參數是否必需要傳入 // 經過defaultValue能夠設置默認值,若是id參數沒有傳入,將默認值和形參綁定。 public String editItems(Model model,@RequestParam(value = "id", required = true) Integer items_id) throws Exception { } 

(3) pojo綁定

頁面中input的name和Controller的pojo形參中的屬性名稱一致,將頁面中數據綁定到pojo對應的屬性。

頁面定義:

這裏寫圖片描述

Controller的pojo形參的定義:

這裏寫圖片描述

須要說明的是:簡單類型的參數綁定和pojo參數綁定互不影響。

// @RequestParam裏邊指定request傳入參數名稱和形參進行綁定。 // 經過required屬性指定參數是否必需要傳入 // 經過defaultValue能夠設置默認值,若是id參數沒有傳入,將默認值和形參綁定。 public String editItems(Model model,@RequestParam(value = "id", required = true) Integer items_id, Items item) throws Exception { } 

1.15. SpringMVC 和 Struts2 的區別

一、SpringMVC基於方法開發的,struts2基於類開發的。

SpringMVC將url和Controller方法映射。映射成功後SpringMVC生成一個Handler對象,對象中只包括了一個method。 方法執行結束,形參數據銷燬。 SpringMVC的Controller開發相似Service開發。

二、SpringMVC能夠進行單例開發,而且建議使用單例開發,struts2經過類的成員變量接收參數,沒法使用單例,只能使用多例。(緣由就是第一句)

三、通過實際測試,struts2速度慢,在於使用struts標籤,若是使用struts建議使用jstl。

1.16. SpringMVC 上傳文件

在頁面form中提交enctype="multipart/form-data"的數據時,須要SpringMVC對multipart類型的數據進行解析。

在springmvc.xml中配置multipart類型解析器。

<!-- 文件上傳 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 設置上傳文件的最大尺寸爲5MB --> <property name="maxUploadSize"> <value>5242880</value> </property> </bean> 
<form id="itemForm" action="${pageContext.request.contextPath }/items/editItemsSubmit.action" method="post" enctype="multipart/form-data"> <input type="hidden" name="id" value="${items.id }"/> 修改商品信息: <table width="100%" border=1> <tr> <td>商品圖片</td> <td> <c:if test="${items.pic !=null}"> <img src="/pic/${items.pic}" width=100 height=100/> <br/> </c:if> <input type="file" name="items_pic"/> </td> </tr> <tr> <td colspan="2" align="center"><input type="submit" value="提交"/> </td> </tr> </table> </form> 
@RequestMapping("/editItemsSubmit") public String editItemsSubmit(Model model,HttpServletRequest request,Integer id, MultipartFile items_pic//接收商品圖片 ) throws Exception { } 

1.17. RESTful支持

RESTful架構,就是目前最流行的一種互聯網軟件架構。它結構清晰、符合標準、易於理解、擴展方便,因此正獲得愈來愈多網站的採用。

RESTful(即Representational State Transfer的縮寫)實際上是一個開發理念,是對http的很好的詮釋。

一、對url進行規範,寫RESTful格式的url

非REST的url:http://...../queryItems.action?id=001&type=T01 REST的url風格:http://..../items/001 特色:url簡潔,將參數經過url傳到服務端

二、http的方法規範

不論是刪除、添加、更新。。使用url是一致的,若是進行刪除,須要設置http的方法爲delete,同理添加。。。

後臺Controller方法:判斷http方法,若是是delete執行刪除,若是是post執行添加。

三、對http的contentType規範

請求時指定contentType,要json數據,設置成json格式的type。。

Controller中設置

定義方法,進行url映射使用REST風格的url,將查詢商品信息的id傳入Controller .

輸出json使用@ResponseBody將java對象輸出json。

//查詢商品信息,輸出json ///itemsView/{id}裏邊的{id}表示佔位符,經過@PathVariable獲取佔位符中的參數, //若是佔位符中的名稱和形參名一致,在@PathVariable能夠不指定名稱 @RequestMapping("/itemsView/{id}") public @ResponseBody ItemsCustom itemsView(@PathVariable("id") Integer id)throws Exception { //調用Service查詢商品信息 ItemsCustom itemsCustom = itemsService.findItemsById(id); return itemsCustom; } 

@RequestMapping(value="/ itemsView/{id}"):{×××}佔位符,請求的URL能夠是「/viewItems/1」或「/viewItems/2」,經過在方法中使用@PathVariable獲取{×××}中的×××變量。

@PathVariable用於將請求URL中的模板變量映射到功能處理方法的參數上。 若是RequestMapping中表示爲"/ itemsView /{id}",id和形參名稱一致,@PathVariable不用指定名稱。

REST方法的前端控制器配置

在web.xml配置:

<!-- SpringMVC前端控制器,rest配置 --> <servlet> <servlet-name>springmvc_rest</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- contextConfigLocation配置SpringMVC加載的配置文件(配置處理器映射器、適配器等等) 若是不配置contextConfigLocation,默認加載的是/WEB-INF/servlet名稱-serlvet.xml(springmvc-servlet.xml) --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc_rest</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> 

對靜態資源的解析

配置前端控制器的url-pattern中指定/,對靜態資源的解析出現問題:

在springmvc.xml中添加靜態資源解析方法。

<!-- 靜態資源解析 包括 :js、css、img、.. --> <mvc:resources location="/js/" mapping="/js/**"/> <mvc:resources location="/img/" mapping="/img/**"/> 

1.18. SpringMVC攔截器

攔截定義

定義攔截器,實現HandlerInterceptor接口。接口中提供三個方法。

public class HandlerInterceptor1 implements HandlerInterceptor { //進入 Handler方法以前執行 //用於身份認證、身份受權 //好比身份認證,若是認證經過表示當前用戶沒有登錄,須要此方法攔截再也不向下執行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //return false表示攔截,不向下執行 //return true表示放行 return false; } //進入Handler方法以後,返回modelAndView以前執行 //應用場景從modelAndView出發:將公用的模型數據(好比菜單導航)在這裏傳到視圖,也能夠在這裏統一指定視圖 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } //執行Handler完成執行此方法 //應用場景:統一異常處理,統一日誌處理 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } 

攔截器配置

SpringMVC配置相似全局的攔截器,SpringMVC框架將配置的相似全局的攔截器注入到每一個HandlerMapping中。

<!--攔截器 --> <mvc:interceptors> <!--多個攔截器,順序執行 --> <!-- 登錄認證攔截器 --> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.itcast.ssm.interceptor.LoginInterceptor"></bean> </mvc:interceptor> <mvc:interceptor> <!-- /**表示全部url包括子url路徑 --> <mvc:mapping path="/**"/> <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors> 

根據測試結果,對攔截器應用。

好比:統一日誌處理攔截器,須要該 攔截器preHandle必定要放行,且將它放在攔截器連接中第一個位置。

好比:登錄認證攔截器,放在攔截器連接中第一個位置。權限校驗攔截器,放在登錄認證攔截器以後。(由於登錄經過後才校驗權限)

1.19. 參考文獻

http://v.itcast.cn/course/8.html

相關文章
相關標籤/搜索