Spring mvc 框架
-
DispatcherServlet
前端控制器 ---- 整個(gè)流程控制的中心,由它調(diào)用其它組件處理用戶的請(qǐng)求
-
三大組件
-
HandlerMapping
處理器映射器 ---- 根據(jù)用戶請(qǐng)求url找到處理器(Handler),springmvc提供了不同的映射器實(shí)現(xiàn)不同的映射方式,例如:配置文件方式,實(shí)現(xiàn)接口方式,注解方式等
-
HandlAdapter
處理器適配器 ---- 通過HandlerAdapter對(duì)處理器進(jìn)行執(zhí)行,通過擴(kuò)展適配器可以對(duì)更多類型的處理器進(jìn)行執(zhí)行
-
ViewResolver
視圖解析器 ---- 負(fù)責(zé)將處理結(jié)果生成View視圖,View Resolver首先根據(jù)邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對(duì)象,最后對(duì)View進(jìn)行渲染將處理結(jié)果通過頁面展示給用戶
-
-
Handler
處理器 ---- 繼DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler對(duì)具體的用戶請(qǐng)求進(jìn)行處理
默認(rèn)支持的參數(shù)類型
-
HttpServletRequest
通過request對(duì)象獲取請(qǐng)求信息
-
HttpServletResponse
通過response處理響應(yīng)信息
-
HttpSession
通過session對(duì)象得到session中存放的對(duì)象
-
-
View
視圖 ---- springmvc框架提供了很多的View視圖類型的支持,包括:jstlView、freemarkerView、pdfView等。我們最常用的視圖就是jsp
視圖對(duì)象
ModelAndView
-
Model
Model是一個(gè)接口,在參數(shù)里直接聲明model即可,Model對(duì)象可以向頁面?zhèn)鬟f數(shù)據(jù),View對(duì)象則可以使用String返回值替代
-
ModelMap
ModelMap是Model接口的實(shí)現(xiàn)類,也可以通過ModelMap向頁面?zhèn)鬟f數(shù)據(jù),使用Model和ModelMap的效果一樣,如果直接使用Model,springmvc會(huì)實(shí)例化ModelMap
配置
-
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- 指定Spring 配置文件位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- Spring隨服務(wù)器啟動(dòng)而啟動(dòng) --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--spring mvc 前端控制器--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- spring MVC配置文件 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <!-- /* 攔截所有jsp js png css 全部攔截 --> <!-- *.action *.do 攔截已a(bǔ)ction,do結(jié)尾的請(qǐng)求 --> <!-- /* 攔截所有(不包含jsp)(包含js png css) --> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
-
dispatcher-servlet.xml
<!-- 組件掃描器,自動(dòng)掃描注解組件 --> <!-- 配置掃描包,多個(gè)包之間用,分隔 --> <context:component-scan base-package="com.lirui.springmvc"/> <!-- 處理器映射器 --> <!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>--> <!-- 處理器適配器 --> <!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>--> <!-- 注解驅(qū)動(dòng),代替以上兩種方式 --> <mvc:annotation-driven /> <!-- 視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置邏輯視圖的前綴 --> <property name="prefix" value="/WEB-INF/jsp/"/> <!-- 配置邏輯視圖的后綴 --> <property name="suffix" value=".jsp"/> <!-- 前綴+邏輯視圖名+后綴 --> </bean>
-
定義controller
@Controller public class Test1Controller { @RequestMapping("/test1") public ModelAndView getList() { ModelAndView mav = new ModelAndView(); mav.addObject("key", request域中的數(shù)據(jù)); mav.setViewName("視圖路徑"); return mav; }
Handler支持的參數(shù)類型
-
默認(rèn)支持的參數(shù)類型
-
HttpServletRequest
通過request對(duì)象獲取請(qǐng)求信息
-
HttpServletResponse
通過response處理響應(yīng)信息
-
HttpSession
通過session對(duì)象得到session中存放的對(duì)象
-
-
綁定簡單類型
當(dāng)請(qǐng)求的參數(shù)名稱和處理器形參名稱一致時(shí)會(huì)將請(qǐng)求參數(shù)與形參進(jìn)行綁定,可以使用@RequestParam處理簡單類型的綁定
@RequestParam(value = "name",required = true,defaultValue = "value")
? value:參數(shù)名稱,即入?yún)⒌恼?qǐng)求參數(shù)名字
? required :是否必須,默認(rèn)是true,表示請(qǐng)求中一定要有相應(yīng)的參數(shù),否則將報(bào)錯(cuò)
? defaultValue :默認(rèn)值
-
綁定pojo對(duì)象
如果提交的參數(shù)很多,或者提交的表單中的內(nèi)容很多的時(shí)候,可以使用簡單類型接受數(shù)據(jù),也可以使用pojo接收數(shù)據(jù)。pojo對(duì)象中的屬性名和表單中input的name屬性一致
綁定包裝pojo對(duì)象
-
自定義參數(shù)綁定
實(shí)現(xiàn)參數(shù)格式的修改,例如由于日期數(shù)據(jù)有很多種格式,springmvc沒辦法把字符串轉(zhuǎn)換成日期類型。所以需要自定義參數(shù)綁定
-
自定義Converter
實(shí)現(xiàn)Converter接口
-
配置
方式一
<!-- 配置注解驅(qū)動(dòng) --> <!-- 如果配置此標(biāo)簽,可以不用配置... --> <mvc:annotation-driven conversion-service="conversionService" /> <!-- 轉(zhuǎn)換器配置 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="cn.itcast.springmvc.converter.DateConverter" /> </set> </property> </bean>
方式二
<!--注解適配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer" ref="customBinder"></property> </bean> <!-- 自定義webBinder --> <bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="conversionService" ref="conversionService" /> </bean> <!-- 轉(zhuǎn)換器配置 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="cn.itcast.springmvc.convert.DateConverter" /> </set> </property> </bean> //此方法需要獨(dú)立配置處理器映射器、適配器,不再使用<mvc:annotation-driven/>
-
-
高級(jí)參數(shù)綁定
-
數(shù)組
提交的數(shù)組,可以直接使用數(shù)組接收,或者pojo的數(shù)組屬性接收。兩種方式任選其一即可
-
list
jsp頁面name屬性必須是list屬性名+下標(biāo)+元素屬性
接收List類型的數(shù)據(jù)必須是pojo的屬性,如果方法的形參為ArrayList類型無法正確接收到數(shù)據(jù)
-
@RequestMapping()注解
-
URL路徑映射
@RequestMapping(value="xxx")或@RequestMapping("/xxx"),value的值是數(shù)組,可以將多個(gè)url映射到同一個(gè)方法,例如:@RequestMapping(value = { "xxx", "xxxx" })
-
添加在類上面
在class上添加@RequestMapping(url)指定通用請(qǐng)求前綴, 限制此類下的所有方法請(qǐng)求url必須以請(qǐng)求前綴開頭
-
請(qǐng)求方法限定
限定GET方法:@RequestMapping(method =RequestMethod.GET)
限定POST方法:@RequestMapping(method =RequestMethod.POST)
GET和POST都可以:@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})
Controller方法返回值
-
ModelAndView
controller方法中定義ModelAndView對(duì)象并返回,對(duì)象中可添加model數(shù)據(jù)、指定view
-
Void
在Controller方法形參上可以定義request和response,使用request或response指定響應(yīng)結(jié)果
-
使用request轉(zhuǎn)發(fā)頁面
request.getRequestDispatcher("頁面路徑").forward(request,response);
-
可以通過response頁面重定向:
response.sendRedirect("url")
-
可以通過response指定響應(yīng)結(jié)果,例如響應(yīng)json數(shù)據(jù)如下:
response.getWriter().print("{\"abc\":123}");
-
-
String
controller方法返回字符串可以指定邏輯視圖名,通過視圖解析器解析為物理視圖地址
-
Redirect重定向
return "redirect:xxx"
-
forward轉(zhuǎn)發(fā)
return "forward:xxx"
-
異常處理
? 系統(tǒng)中異常包括兩類:預(yù)期異常和運(yùn)行時(shí)異常RuntimeException,前者通過捕獲異常從而獲取異常信息,后者主要通過規(guī)范代碼開發(fā)、測試通過手段減少運(yùn)行時(shí)異常的發(fā)生。
? 系統(tǒng)的dao、service、controller出現(xiàn)都通過throws Exception向上拋出,最后由springmvc前端控制器交由異常處理器(HandlerExceptionResolver)進(jìn)行異常處理。
-
自定義異常處理器
實(shí)現(xiàn)接口HandlerExceptionResolver
public class CustomHandlerExceptionResolver implements HandlerExceptionResolver { @Nullable @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, @Nullable Object o, Exception e) { String msg; if (e instanceof CustomException) { msg = ((CustomException) e).getMsg(); } else { msg = e.getMessage(); } ModelAndView mav = new ModelAndView(); mav.addObject("error", msg); mav.setViewName("error"); return mav; } }
-
配置
//dispatcher-servlet.xml文件 <!-- 配置異常處理器 --> <bean class="com.lirui.springmvc.exeception.CustomHandlerExceptionResolver"/>
上傳圖片
-
配置虛擬目錄
在tomcat上配置圖片虛擬目錄,在tomcat下conf/server.xml中添加:
<Context docBase="D:\develop\upload\temp"path="/pic" reloadable="false"/>
訪問http://localhost:8080/pic即可訪問D:\develop\upload\temp下的圖片。也可以通過
eclipse配置
-
加入jar文件
commons-fileupload.jar
commons-io.jar
修改jsp頁面,添加
enctype="multipart/form-data"
-
采用參數(shù)
MultipartFile pictureFile
接收文件,pictureFile名稱與jsp文件上傳控件name名稱一致String fileName = UUID.randomUUID().toString().replace("-", ""); String pictureName = pictureFile.getOriginalFilename(); String type = FilenameUtils.getExtension(pictureName); fileName = fileName + "." + type; pictureFile.transferTo(new File("E:\\Learn\\pic\\" + fileName));
-
配置文件上傳解析器
//dispatcher-servlet.xml <!-- 文件上傳,id必須設(shè)置為multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 設(shè)置文件上傳大小 --> <property name="maxUploadSize" value="5000000" /> </bean>
Json解析
-
注解
@RequestBody ---- 用于讀取http請(qǐng)求的內(nèi)容(字符串),通過springmvc提供的HttpMessageConverter接口將讀到的內(nèi)容(json數(shù)據(jù))轉(zhuǎn)換為java對(duì)象并綁定到Controller方法的參數(shù)上
@ResponseBody ---- 用于將Controller的方法返回的對(duì)象,通過springmvc提供HttpMessageConverter接口轉(zhuǎn)換為指定格式的數(shù)據(jù)如:json,xml等,通過Response響應(yīng)給客戶端
-
添加json解析器
如果不使用注解驅(qū)動(dòng)<mvc:annotation-driven/>,就需要給處理器適配器配置json轉(zhuǎn)換器
在springmvc.xml配置文件中,給處理器適配器加入json轉(zhuǎn)換器:
<!--處理器適配器 --> <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>
RESTful支持
使用注解@RequestMapping("item/{id}")聲明請(qǐng)求的url,{xxx}叫做占位符,請(qǐng)求的URL可以是“item /1”或“item/2”
使用(@PathVariable() Integer id)獲取url上的數(shù)據(jù)
如果@RequestMapping中表示為"item/{id}",id和形參名稱一致,@PathVariable不用指定名稱。如果不一致,例如"item/{ItemId}"則需要指定名稱@PathVariable("itemId")。
- @PathVariable是獲取url上數(shù)據(jù)的。@RequestParam獲取請(qǐng)求參數(shù)的(包括post表單提交)
- 如果加上@ResponseBody注解,就不會(huì)走視圖解析器,不會(huì)返回頁面,目前返回的json數(shù)據(jù)。如果不加,就走視圖解析器,返回頁面
攔截器
Spring Web MVC 的處理器攔截器類似于Servlet 開發(fā)中的過濾器Filter,用于對(duì)處理器進(jìn)行預(yù)處理和后處理
-
攔截器定義(實(shí)現(xiàn)HandlerInterceptor接口)
public class HandlerInterceptor1 implements HandlerInterceptor { // controller執(zhí)行后且視圖返回后調(diào)用此方法 // 這里可得到執(zhí)行controller時(shí)的異常信息 // 這里可記錄操作日志 @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {} // controller執(zhí)行后但未返回視圖前調(diào)用此方法 // 這里可在返回用戶前對(duì)模型數(shù)據(jù)進(jìn)行加工處理,比如這里加入公用信息以便頁面顯示 @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {} // Controller執(zhí)行前調(diào)用此方法 // 返回true表示繼續(xù)執(zhí)行,返回false中止執(zhí)行 // 這里可以加入登錄校驗(yàn)、權(quán)限攔截等 @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { return true; } }
?
-
攔截器配置
<!-- 配置攔截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 所有的請(qǐng)求都進(jìn)入攔截器 --> <mvc:mapping path="/**" /> <!-- 配置具體的攔截器 --> <bean class="xxx" /> </mvc:interceptor> <mvc:interceptor> <!-- 所有的請(qǐng)求都進(jìn)入攔截器 --> <mvc:mapping path="/**" /> <!-- 配置具體的攔截器 --> <bean class="xxx" /> </mvc:interceptor> </mvc:interceptors>
-
攔截器處理流程
preHandle按攔截器定義順序調(diào)用
postHandler按攔截器定義逆序調(diào)用
afterCompletion按攔截器定義逆序調(diào)用
?
postHandler在攔截器鏈內(nèi)所有攔截器返成功調(diào)用
afterCompletion只有preHandle返回true才調(diào)用
springmvc與struts2不同
- springmvc的入口是一個(gè)servlet即前端控制器,而struts2入口是一個(gè)filter過濾器。
- springmvc是基于方法開發(fā)(一個(gè)url對(duì)應(yīng)一個(gè)方法),請(qǐng)求參數(shù)傳遞到方法的形參,可以設(shè)計(jì)為單例或多例(建議單例),struts2是基于類開發(fā),傳遞參數(shù)是通過類的屬性,只能設(shè)計(jì)為多例。
- Struts采用值棧存儲(chǔ)請(qǐng)求和響應(yīng)的數(shù)據(jù),通過OGNL存取數(shù)據(jù), springmvc通過參數(shù)解析器是將request請(qǐng)求內(nèi)容解析,并給方法形參賦值,將數(shù)據(jù)和視圖封裝成ModelAndView對(duì)象,最后又將ModelAndView中的模型數(shù)據(jù)通過request域傳輸?shù)巾撁妗sp視圖解析器默認(rèn)使用jstl