第一天:springmvc的基礎知識
什麼是springmvc?
springmvc框架原理(掌握)
前端控制器、處理器映射器、處理器適配器、視圖解析器
springmvc入門程序
目的:對前端控制器、處理器映射器、處理器適配器、視圖解析器學習
非註解的處理器映射器、處理器適配器
註解的處理器映射器、處理器適配器(掌握)
springmvc和mybatis整合(掌握)
springmvc註解開發:(掌握)
經常使用的註解學習
參數綁定(簡單類型、pojo、集合類型(明天講))
自定義參數綁定(掌握)
springmvc和struts2區別
次日:springmvc的高級應用
參數綁定(集合類型)
數據回顯
上傳圖片
json數據交互
RESTful支持
攔截器
springmvc是spring框架的一個模塊,springmvc和spring無需經過中間整合層進行整合。html
springmvc是一個基於mvc的web框架。前端
mvc是一個設計模式,mvc在b/s系統 下的應用:java
第一步:發起請求到前端控制器(DispatcherServlet)mysql
第二步:前端控制器請求HandlerMapping查找 Handler 能夠根據xml配置、註解進行查找jquery
第三步:處理器映射器HandlerMapping向前端控制器返回Handler程序員
第四步:前端控制器調用處理器適配器去執行Handlerweb
第五步:處理器適配器去執行Handlerajax
第六步:Handler執行完成給適配器返回ModelAndViewspring
第七步:處理器適配器向前端控制器返回ModelAndView, ModelAndView是springmvc框架的一個底層對象,包括 Model和viewsql
第八步:前端控制器請求視圖解析器去進行視圖解析 根據邏輯視圖名解析成真正的視圖(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...)
以案例做爲驅動。
springmvc和mybaits使用一個案例(商品訂單管理)。
功能需求:商品列表查詢
數據庫環境:mysql5.1
java環境:
jdk1.7.0_72
eclipse indigo
springmvc版本:spring3.2
須要spring3.2全部jar(必定包括spring-webmvc-3.2.0.RELEASE.jar)
在web.xml中配置前端控制器。
在classpath下的springmvc.xml中配置處理器適配器
經過查看原代碼:
此適配器能執行實現 Controller接口的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; } }
將編寫Handler在spring容器加載。
在classpath下的springmvc.xml中配置處理器映射器
須要配置解析jsp的視圖解析器。
訪問地址:http://localhost:8080/springmvcfirst1208/queryItems.action
處理器映射器根據url找不到Handler,報下邊的錯誤。說明url錯誤。
處理器映射器根據url找到了Handler,轉發的jsp頁面找到,報下邊的錯誤,說明jsp頁面地址錯誤了。
處理器映射器:
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
另外一個映射器:
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
多個映射器能夠並存,前端控制器判斷url能讓哪些映射器映射,就讓正確的映射器處理。
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
要求編寫的Handler實現 Controller接口。
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
要求編寫的Handler實現 HttpRequestHandler接口。
//使用此方法能夠經過修改response,設置響應的數據格式,好比響應json數據
/* response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json串"); */
前端控制器從上邊的文件中加載處理映射器、適配器、視圖解析器等組件,若是不在springmvc.xml中配置,使用默認加載的。
在spring3.1以前使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping註解映射器。
在spring3.1以後使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping註解映射器。
在spring3.1以前使用org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter註解適配器。
在spring3.1以後使用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> -->
使用註解的映射器和註解的適配器。(註解的映射器和註解的適配器必須配對使用)
//使用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; }
<!-- 對於註解的Handler能夠單個配置
實際開發中建議使用組件掃描
-->
<!-- <bean class="cn.itcast.ssm.controller.ItemsController3" /> -->
<!-- 能夠掃描controller、service、...
這裏讓掃描controller,指定controller的包
-->
<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
訪問:http://localhost:8080/springmvcfirst1208/queryItems.action
經過前端控制器源碼分析springmvc的執行過程。
第一步:前端控制器接收請求
調用doDiapatch
第二步:前端控制器調用處理器映射器查找 Handler
第三步:調用處理器適配器執行Handler,獲得執行結果ModelAndView
第四步:視圖渲染,將model數據填充到request域。
視圖解析,獲得view:
調用view的渲染方法,將model數據填充到request域
渲染方法:
經過入門程序理解springmvc前端控制器、處理器映射器、處理器適配器、視圖解析器用法。
前端控制器配置:
第一種:*.action,訪問以.action結尾 由DispatcherServlet進行解析
第二種:/,因此訪問的地址都由DispatcherServlet進行解析,對於靜態文件的解析須要配置不讓DispatcherServlet進行解析
使用此種方式能夠實現 RESTful風格的url
處理器映射器:
非註解處理器映射器(瞭解)
註解的處理器映射器(掌握)
對標記@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"/>
實際開發使用:mvc:annotation-driven
視圖解析器配置前綴和後綴:
程序中不用指定前綴和後綴:
使用springmvc和mybatis完成商品列表查詢。
springmvc+mybaits的系統架構:
第一步:整合dao層
mybatis和spring整合,經過spring管理mapper接口。
使用mapper的掃描器自動掃描mapper接口在spring中進行註冊。
第二步:整合service層
經過spring管理 service接口。
使用配置方式將service接口配置在spring配置文件中。
實現事務控制。
第三步:整合springmvc
因爲springmvc是spring的模塊,不須要整合。
數據庫環境:mysql5.1
java環境:
jdk1.7.0_72
eclipse indigo
springmvc版本:spring3.2
所須要的jar包:
數據庫驅動包:mysql5.1
mybatis的jar包
mybatis和spring整合包
log4j包
dbcp數據庫鏈接池包
spring3.2全部jar包
jstl包
參考:
工程結構:
mybatis和spring進行整合。
mybatis本身的配置文件。
配置:
數據源
SqlSessionFactory
mapper掃描器
將生成的文件拷貝至工程 中。
針對綜合查詢mapper,通常狀況會有關聯查詢,建議自定義mapper
sql語句:
SELECT * FROM items WHERE items.name LIKE '%筆記本%'
讓spring管理service接口。
建立applicationContext-service.xml,文件中配置service。
在applicationContext-transaction.xml中使用spring聲明式事務控制方法。
建立springmvc.xml文件,配置處理器映射器、適配器、視圖解析器。
<!-- 能夠掃描controller、service、...這裏讓掃描controller,指定controller的包--> <context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan> <!--註解映射器 --> <!-- <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> <!-- 視圖解析器 解析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>
參考入門程序。
將mapper、service、controller加載到spring容器中。
建議使用通配符加載上邊的配置文件。
在web.xml中,添加spring容器監聽器,加載spring容器。
操做流程:
一、進入商品查詢列表頁面
二、點擊修改,進入商品修改頁面,頁面中顯示了要修改的商品(從數據庫查詢), 要修改的商品從數據庫查詢,根據商品id(主鍵)查詢商品信息
三、在商品修改頁面,修改商品信息,修改後,點擊提交
mapper:
根據id查詢商品信息
根據id更新Items表的數據
不用開發了,使用逆向工程生成的代碼。
接口功能:
根據id查詢商品信息
修改商品信息
方法:
商品信息修改頁面顯示
商品信息修改提交
n url映射
定義controller方法對應的url,進行處理器映射使用。
n 窄化請求映射
n 限制http請求方法
出於安全性考慮,對http的連接進行方法限制。
若是限制請求爲post方法,進行get請求,報錯:
n 返回ModelAndView
須要方法結束時,定義ModelAndView,將model和view分別進行設置。
n 返回string
若是controller方法返回string,
一、表示返回邏輯視圖名。
真正視圖(jsp路徑)=前綴+邏輯視圖名+後綴
二、redirect重定向
商品修改提交後,重定向到商品查詢列表。
redirect重定向特色:瀏覽器地址欄中的url會變化。修改提交的request數據沒法傳到重定向的地址。由於重定向後從新進行request(request沒法共享)
三、forward頁面轉發
經過forward進行頁面轉發,瀏覽器地址欄url不變,request能夠共享。
n 返回void
在controller方法形參上能夠定義request和response,使用request或response指定響應結果:
一、使用request轉向頁面,以下:
request.getRequestDispatcher("頁面路徑").forward(request, response);
二、也能夠經過response頁面重定向:
response.sendRedirect("url")
三、也能夠經過response指定響應結果,例如響應json數據以下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
從客戶端請求key/value數據,通過參數綁定,將key/value數據綁定到controller方法的形參上。
springmvc中,接收頁面提交的數據是經過方法形參來接收。而不是在controller類定義成員變動接收!!!!
直接在controller方法形參上定義下邊類型的對象,就可使用這些對象。在參數綁定過程當中,若是遇到下邊類型直接進行綁定。
經過request對象獲取請求信息
經過response處理響應信息
經過session對象獲得session中存放的對象
model是一個接口,modelMap是一個接口實現 。
做用:將model數據填充到request域。
經過@RequestParam對簡單類型的參數進行綁定。
若是不使用@RequestParam,要求request傳入參數名稱和controller方法的形參名稱一致,方可綁定成功。
若是使用@RequestParam,不用限制request傳入參數名稱和controller方法的形參名稱一致。
經過required屬性指定參數是否必需要傳入,若是設置爲true,沒有傳入參數,報下邊錯誤:
參考教案 對其它簡單類型綁定進行測試。
頁面中input的name和controller的pojo形參中的屬性名稱一致,將頁面中數據綁定到pojo。
頁面定義:
controller的pojo形參的定義:
對於controller形參中pojo對象,若是屬性中有日期類型,須要自定義參數綁定。
將請求日期數據串傳成 日期類型,要轉換的日期類型和pojo中日期屬性的類型保持一致。
因此自定義參數綁定將日期串轉成java.util.Date類型。
須要向處理器適配器中注入自定義的參數綁定組件。
一、springmvc基於方法開發的,struts2基於類開發的。
springmvc將url和controller方法映射。映射成功後springmvc生成一個Handler對象,對象中只包括了一個method。方法執行結束,形參數據銷燬。springmvc的controller開發相似service開發。
二、springmvc能夠進行單例開發,而且建議使用單例開發,struts2經過類的成員變量接收參數,沒法使用單例,只能使用多例。
三、通過實際測試,struts2速度慢,在於使用struts標籤,若是使用struts建議使用jstl。
在web.xml添加post亂碼filter
在web.xml中加入:
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
以上能夠解決post請求亂碼問題。
對於get請求中文參數出現亂碼解決方法有兩個:
修改tomcat配置文件添加編碼與工程編碼一致,以下:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
另一種方法對參數進行從新編碼:
String userName new
String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
ISO8859-1是tomcat默認編碼,須要將tomcat編碼後的內容按utf-8編碼
--------------------------------------------------------------------------------------------------------------------------------------------------
複習:
springmvc框架: DispatcherServlet前端控制器:接收request,進行response HandlerMapping處理器映射器:根據url查找Handler。(能夠經過xml配置方式,註解方式) HandlerAdapter處理器適配器:根據特定規則去執行Handler,編寫Handler時須要按照HandlerAdapter的要求去編寫。 Handler處理器(後端控制器):須要程序員去編寫,經常使用註解開發方式。 Handler處理器執行後結果 是ModelAndView,具體開發時Handler返回方法值類型包括 :ModelAndView、String(邏輯視圖名)、void(經過在Handler形參中添加request和response,相似原始 servlet開發方式,注意:能夠經過指定response響應的結果類型實現json數據輸出) View resolver視圖解析器:根據邏輯視圖名生成真正的視圖(在springmvc中使用View對象表示) View視圖:jsp頁面,僅是數據展現,沒有業務邏輯。 註解開發: 使用註解方式的處理器映射器和適配器: <!--註解映射器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!--註解適配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> 在實際開發,使用<mvc:annotation-driven>代替上邊處理器映射器和適配器配置。 @controller註解必需要加,做用標識類是一個Handler處理器。 @requestMapping註解必需要加,做用: 一、對url和Handler的方法進行映射。 二、能夠窄化請求映射,設置Handler的根路徑,url就是根路徑+子路徑請求方式 三、能夠限制http請求的方法 映射成功後,springmvc框架生成一個Handler對象,對象中只包括 一個映射成功的method。 註解開發中參數綁定: 將request請求過來的key/value的數據(理解一個串),經過轉換(參數綁定的一部分),將key/value串轉成形參,將轉換後的結果傳給形參(整個參數綁定過程)。 springmvc所支持參數綁定: 一、默認支持不少類型,HttpServletRequest、response、session、 model/modelMap(將模型數據填充到request域) 二、支持簡單數據類型,整型、字符串、日期。。 只要保證request請求的參數名和形參名稱一致,自動綁定成功 若是request請求的參數名和形參名稱不一致,可使用@RequestParam(指定request請求的參數名),@RequestParam加在形參的前邊。 三、支持pojo類型 只要保證request請求的參數名稱和pojo中的屬性名一致,自動將request請求的參數設置到pojo的屬性中。 注意:形參中即有pojo類型又有簡單類型,參數綁定互不影響。 自定義參數綁定: 日期類型綁定自定義: 定義的Converter<源類型,目標類型>接口實現類,好比: Converter<String,Date>表示:將請求的日期數據串轉成java中的日期類型。 注意:要轉換的目標類型必定和接收的pojo中的屬性類型一致。 將定義的Converter實現類注入處處理器適配器中。 <mvc:annotation-driven conversion-service="conversionService"> </mvc:annotation-driven> <!-- conversionService --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 轉換器 --> <property name="converters"> <list> <bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/> </list> </property> </bean> springmvc和struts2區別: springmvc面向方法開發的(更接近service接口的開發方式),struts2面向類開發。 springmvc能夠單例開發,struts2只能是多例開發。
上午:
在商品查詢和商品修改功能案例驅動下進行學習:
包裝類型pojo參數綁定(掌握)。
集合類型的參數綁定:數組、list、map..
商品修改添加校驗,學習springmvc提供校驗validation(使用的是hibernate校驗框架)
數據回顯
統一異常處理(掌握)
下午:
上傳圖片
json數據交互
RESTful支持
攔截器
商品查詢controller方法中實現商品查詢條件傳入。
第一種方法:在形參中 添加HttpServletRequest request參數,經過request接收查詢條件參數。
第二種方法:在形參中讓包裝類型的pojo接收查詢條件參數。
分析:
頁面傳參數的特色:複雜,多樣性。條件包括 :用戶帳號、商品編號、訂單信息。。。
若是將用戶帳號、商品編號、訂單信息等放在簡單pojo(屬性是簡單類型)中,pojo類屬性比較多,比較亂。
建議使用包裝類型的pojo,pojo中屬性是pojo。
頁面參數:
商品名稱:<input name="itemsCustom.name" />
注意:itemsCustom和包裝pojo中的屬性一致便可。
controller方法形參:
public ModelAndView queryItems(HttpServletRequest request,ItemsQueryVo itemsQueryVo) throws Exception
商品批量刪除,用戶在頁面選擇多個商品,批量刪除。
關鍵:將頁面選擇(多選)的商品id,傳到controller方法的形參,方法形參使用數組接收頁面請求的多個商品id。
controller方法定義:
頁面定義:
一般在須要批量提交數據時,將提交的數據綁定到list<pojo>中,好比:成績錄入(錄入多門課成績,批量提交),
本例子需求:批量商品修改,在頁面輸入多個商品信息,將多個商品信息提交到controller方法中。
controller方法定義:
一、進入批量商品修改頁面(頁面樣式參考商品列表實現)
二、批量修改商品提交
使用List接收頁面提交的批量數據,經過包裝pojo接收,在包裝pojo中定義list<pojo>屬性
頁面定義:
也經過在包裝pojo中定義map類型屬性。
在包裝類中定義Map對象,並添加get/set方法,action使用包裝對象接收。
包裝類中定義Map對象以下:
Public class QueryVo { private Map<String, Object> itemInfo = new HashMap<String, Object>(); //get/set方法.. }
頁面定義以下:
<tr> <td>學生信息:</td> <td> 姓名:<inputtype="text"name="itemInfo['name']"/> 年齡:<inputtype="text"name="itemInfo['price']"/> .. .. .. </td> </tr>
Contrller方法定義以下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{ System.out.println(queryVo.getStudentinfo()); }
項目中,一般使用較可能是前端的校驗,好比頁面中js校驗。對於安全要求較高點建議在服務端進行校驗。
服務端校驗:
控制層conroller:校驗頁面請求的參數的合法性。在服務端控制層conroller校驗,不區分客戶端類型(瀏覽器、手機客戶端、遠程調用)
業務層service(使用較多):主要校驗關鍵業務參數,僅限於service接口中使用的參數。
持久層dao:通常是不校驗的。
springmvc使用hibernate的校驗框架validation(和hibernate沒有任何關係)。
校驗思路:
頁面提交請求的參數,請求到controller方法中,使用validation進行校驗。若是校驗出錯,將錯誤信息展現到頁面。
具體需求:
商品修改,添加校驗(校驗商品名稱長度,生產日期的非空校驗),若是校驗出錯,在商品修改頁面顯示錯誤信息。
hibernate的校驗框架validation所須要jar包:
在ItemsCustom.java中添加校驗規則:
在CustomValidationMessages.properties配置校驗錯誤信息:
//在須要校驗的pojo前邊添加@Validated,在須要校驗的pojo後邊添加BindingResult bindingResult接收校驗出錯信息
//注意:@Validated和BindingResult bindingResult是配對出現,而且形參順序是固定的(一前一後)。
在controller中將錯誤信息傳到頁面便可。
頁面顯示錯誤信息:
在pojo中定義校驗規則,而pojo是被多個 controller所共用,當不一樣的controller方法對同一個pojo進行校驗,可是每一個controller方法須要不一樣的校驗。
解決方法:
定義多個校驗分組(實際上是一個java接口),分組中定義有哪些規則
每一個controller方法使用不一樣的校驗分組
提交後,若是出現錯誤,將剛纔提交的數據回顯到剛纔的提交頁面。
一、springmvc默認對pojo數據進行回顯。
pojo數據傳入controller方法後,springmvc自動將pojo數據放到request域,key等於pojo類型(首字母小寫)
使用@ModelAttribute指定pojo回顯到頁面在request中的key
二、@ModelAttribute還能夠將方法的返回值傳到頁面
在商品查詢列表頁面,經過商品類型查詢商品信息。
在controller中定義商品類型查詢方法,最終將商品類型傳到頁面。
頁面上能夠獲得itemTypes數據。
三、使用最簡單方法使用model,能夠不用@ModelAttribute
使用最簡單方法使用model。
model.addAttribute("id", id);
系統中異常包括兩類:預期異常和運行時異常RuntimeException,前者經過捕獲異常從而獲取異常信息,後者主要經過規範代碼開發、測試經過手段減小運行時異常的發生。
系統的dao、service、controller出現都經過throws Exception向上拋出,最後由springmvc前端控制器交由異常處理器進行異常處理,以下圖:
springmvc提供全局異常處理器(一個系統只有一個異常處理器)進行統一異常處理。
對不一樣的異常類型定義異常類,繼承Exception。
思路:
系統遇到異常,在程序中手動拋出,dao拋給service、service給controller、controller拋給前端控制器,前端控制器調用全局異常處理器。
全局異常處理器處理思路:
解析出異常類型
若是該 異常類型是系統 自定義的異常,直接取出異常信息,在錯誤頁面展現
若是該 異常類型不是系統 自定義的異常,構造一個自定義的異常類型(信息爲「未知錯誤」)
springmvc提供一個HandlerExceptionResolver接口
@Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { //handler就是處理器適配器要執行Handler對象(只有method) // 解析出異常類型 // 若是該 異常類型是系統 自定義的異常,直接取出異常信息,在錯誤頁面展現 // String message = null; // if(ex instanceof CustomException){ // message = ((CustomException)ex).getMessage(); // }else{ //// 若是該 異常類型不是系統 自定義的異常,構造一個自定義的異常類型(信息爲「未知錯誤」) // message="未知錯誤"; // } //上邊代碼變爲 CustomException customException = null; if(ex instanceof CustomException){ customException = (CustomException)ex; }else{ customException = new CustomException("未知錯誤"); } //錯誤信息 String message = customException.getMessage(); ModelAndView modelAndView = new ModelAndView(); //將錯誤信息傳到頁面 modelAndView.addObject("message", message); //指向錯誤頁面 modelAndView.setViewName("error"); return modelAndView; }
在controller、service、dao中任意一處須要手動拋出異常。
若是是程序中手動拋出的異常,在錯誤頁面中顯示自定義的異常信息,若是不是手動拋出異常說明是一個運行時異常,在錯誤頁面只顯示「未知錯誤」。
在商品修改的controller方法中拋出異常 .
在service接口中拋出異常:
若是與業務功能相關的異常,建議在service中拋出異常。
與業務功能沒有關係的異常,建議在controller中拋出。
上邊的功能,建議在service中拋出異常。
在修改商品頁面,添加上傳商品圖片功能。
在 頁面form中提交enctype="multipart/form-data"的數據時,須要springmvc對multipart類型的數據進行解析。
在springmvc.xml中配置multipart類型解析器。
上邊的解析內部使用下邊的jar進行圖片上傳。
經過圖形界面配置:
也能夠直接修改tomcat的配置:
在conf/server.xml文件,添加虛擬 目錄 :
注意:在圖片虛擬目錄 中,必定將圖片目錄分級建立(提升i/o性能),通常咱們採用按日期(年、月、日)進行分級建立。
修改:商品修改controller方法:
json數據格式在接口調用中、html頁面中較經常使用,json格式比較簡單,解析還比較方便。
好比:webservice接口,傳輸json數據.
一、請求json、輸出json,要求請求的是json串,因此在前端頁面中須要將請求的內容轉成json,不太方便。
二、請求key/value、輸出json。此方法比較經常使用。
springmvc中使用jackson的包進行json轉換(@requestBody和@responseBody使用下邊的包進行json轉),以下:
在註解適配器中加入messageConverters
<!--註解適配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean>
注意:若是使用<mvc:annotation-driven /> 則不用定義上邊的內容。
使用jquery的ajax提交json串,對輸出的json結果進行解析。
使用jquery的ajax提交key/value串,對輸出的json結果進行解析。
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。。
查詢商品信息,返回json數據。
定義方法,進行url映射使用REST風格的url,將查詢商品信息的id傳入controller .
輸出json使用@ResponseBody將java對象輸出json。
@RequestMapping(value="/ itemsView/{id}"):{×××}佔位符,請求的URL能夠是「/viewItems/1」或「/viewItems/2」,經過在方法中使用@PathVariable獲取{×××}中的×××變量。
@PathVariable用於將請求URL中的模板變量映射到功能處理方法的參數上。
若是RequestMapping中表示爲"/ itemsView /{id}",id和形參名稱一致,@PathVariable不用指定名稱。
在web.xml配置:
配置前端控制器的url-parttern中指定/,對靜態資源的解析出現問題:
在springmvc.xml中添加靜態資源解析方法。
定義攔截器,實現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攔截器針對HandlerMapping進行攔截設置,若是在某個HandlerMapping中配置攔截,通過該 HandlerMapping映射成功的handler最終使用該 攔截器。
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="handlerInterceptor1"/>
<ref bean="handlerInterceptor2"/>
</list>
</property>
</bean>
<bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
<bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
通常不推薦使用。
springmvc配置相似全局的攔截器,springmvc框架將配置的相似全局的攔截器注入到每一個HandlerMapping中。
測試多個攔截器各各方法執行時機。
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle
HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion
總結:
preHandle方法按順序執行,
postHandle和afterCompletion按攔截器配置的逆向順序執行。
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion
總結:
攔截器1放行,攔截器2 preHandle纔會執行。
攔截器2 preHandle不放行,攔截器2 postHandle和afterCompletion不會執行。
只要有一個攔截器不放行,postHandle不會執行。
HandlerInterceptor1...preHandle
攔截器1 preHandle不放行,postHandle和afterCompletion不會執行。
攔截器1 preHandle不放行,攔截器2不執行。
根據測試結果,對攔截器應用。
好比:統一日誌處理攔截器,須要該 攔截器preHandle必定要放行,且將它放在攔截器連接中第一個位置。
好比:登錄認證攔截器,放在攔截器連接中第一個位置。權限校驗攔截器,放在登錄認證攔截器以後。(由於登錄經過後才校驗權限)
一、用戶請求url
二、攔截器進行攔截校驗
若是請求的url是公開地址(無需登錄便可訪問的url),讓放行
若是用戶session 不存在跳轉到登錄頁面
若是用戶session存在放行,繼續操做。
@Controller public class LoginController { // 登錄 @RequestMapping("/login") public String login(HttpSession session, String username, String password) throws Exception { // 調用service進行用戶身份驗證 // ... // 在session中保存用戶身份信息 session.setAttribute("username", username); // 重定向到商品列表頁面 return "redirect:/items/queryItems.action"; } // 退出 @RequestMapping("/logout") public String logout(HttpSession session) throws Exception { // 清除session session.invalidate(); // 重定向到商品列表頁面 return "redirect:/items/queryItems.action"; } }
public class LoginInterceptor implements HandlerInterceptor { //進入 Handler方法以前執行 //用於身份認證、身份受權 //好比身份認證,若是認證經過表示當前用戶沒有登錄,須要此方法攔截再也不向下執行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //獲取請求的url String url = request.getRequestURI(); //判斷url是不是公開 地址(實際使用時將公開 地址配置配置文件中) //這裏公開地址是登錄提交的地址 if(url.indexOf("login.action")>=0){ //若是進行登錄提交,放行 return true; } //判斷session HttpSession session = request.getSession(); //從session中取出用戶身份信息 String username = (String) session.getAttribute("username"); if(username != null){ //身份存在,放行 return true; } //執行這裏表示用戶身份須要認證,跳轉登錄頁面 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); //return false表示攔截,不向下執行 //return true表示放行 return false; }
案例:
當前路徑:
<a href="/user/login">帶斜槓的路徑</a>
結果:http://localhost:8080/user/login
<a href="user/login">不帶斜槓的路徑</a>
結果:http://localhost:8080/user/user/login