概述
- 是Spring為展現(xiàn)層提供的基于MVC設(shè)計(jì)理念的Web框架,通過(guò)一套MVC注解,讓POJO成為處理請(qǐng)求的控制器,而無(wú)需實(shí)現(xiàn)任何接口
- 支持REST風(fēng)格的URL請(qǐng)求
- 采用松散耦合的可插拔組件結(jié)構(gòu),比其他MVC框架更具擴(kuò)展性和靈活性
- SpringMVC的IOC容器是Spring的IOC容器的子容器,故而可引用Spring的IOC中的bean,反之則不行
運(yùn)行流程
- 當(dāng)前端發(fā)出請(qǐng)求時(shí),首先進(jìn)入到DispatcherServlet(中央控制器),把請(qǐng)求的地址傳給HandlerMapping處理器映射器中進(jìn)行比對(duì)(Handler即包含了我們請(qǐng)求的Controller類(lèi)和Method方法的對(duì)象)
- 未找到則表示靜態(tài)資源,進(jìn)入defaultServlet處理器,返回前端
- 找到則表示動(dòng)態(tài)資源,調(diào)用AdapterMap數(shù)據(jù)適配器,獲取該資源的執(zhí)行列表(目標(biāo)方法,攔截器方法),并返回處理器執(zhí)行鏈(HandlerExecutionChain)給中央控制器
- 中央控制器將結(jié)果交給HandlerAdapter處理器適配器,依次執(zhí)行執(zhí)行列表的方法,返回邏輯視圖ModelAndView給中央控制器
- 將結(jié)果交給ViewResolver視圖解析器,遍歷生成具體的View物理視圖
- 中央控制器調(diào)用render方法渲染視圖,即將數(shù)據(jù)文件轉(zhuǎn)化成可視化界面返回前端
步驟
- 導(dǎo)入jar包,在web.xml中配置中央控制器DispatcherServlet,加入SpringMVC配置文件
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置中央控制器的初始化參數(shù):配置文件的位置和名稱(chēng) -->
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 默認(rèn)為WEB-INF/<servlet-name>-servlet.xml -->
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<!-- 配置servlet被加載的先后順序 -->
<!-- 為負(fù)數(shù)或者沒(méi)有設(shè)置,則容器會(huì)當(dāng)Servlet被請(qǐng)求時(shí)再加載 -->
<!-- 為正整數(shù)或者0時(shí),表示容器在應(yīng)用啟動(dòng)時(shí)就加載并初始化這個(gè)servlet -->
<!-- 值越小,servlet的優(yōu)先級(jí)越高,就越先被加載。值相同時(shí),容器就會(huì)自己選擇順序來(lái)加載 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 編寫(xiě)處理請(qǐng)求的處理器并標(biāo)識(shí)@Controller,編寫(xiě)視圖
- 使用@RequestMapping("/地址") //映射請(qǐng)求的URL,可放在類(lèi)與方法上,方法返回值進(jìn)入視圖解析器(使用@GetMapping("/地址")響應(yīng)get請(qǐng)求,@PostMapping("/地址")響應(yīng)post請(qǐng)求)
<!--注解驅(qū)動(dòng),以使得訪問(wèn)路徑與方法的匹配可以通過(guò)注解配置-->
<mvc:annotation-driven />
<!-- 在配置dispatchServlet時(shí)配置<url-pattern>/</url-pattern>攔截所有請(qǐng)求,這時(shí)候dispatchServlet完全取代了default servlet,將不會(huì)再訪問(wèn)容器中原始默認(rèn)的servlet,而對(duì)靜態(tài)資源的訪問(wèn)就是通過(guò)容器默認(rèn)servlet處理的,故而這時(shí)候靜態(tài)資源將不可訪問(wèn),使用下列標(biāo)簽訪問(wèn)靜態(tài)資源 -->
<mvc:default-servlet-handler/>
- 在SpringMVC配置文件中配置要掃描的包,配置視圖解析器
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/響應(yīng)地址前綴/"></property>
<property name="suffix" value=".后綴"></property>
</bean>
REST
- 資源表現(xiàn)層狀態(tài)轉(zhuǎn)換,是一種互聯(lián)網(wǎng)軟件架構(gòu)
- 資源:網(wǎng)絡(luò)上的一個(gè)實(shí)體即一個(gè)具體信息,可為一段文字,一張圖片,一種服務(wù),總之是一個(gè)具體的存在,可以用URI指向它,每種資源對(duì)應(yīng)一個(gè)特定的URI,訪問(wèn)URI可獲取這個(gè)資源
- 表現(xiàn)層:把資源具體呈現(xiàn)出來(lái)的形式,就為表現(xiàn)層,如txt、json、html、二進(jìn)制等
- 狀態(tài)轉(zhuǎn)化:每發(fā)出一次請(qǐng)求,就代表客戶端和服務(wù)器的一次交互過(guò)程,http為無(wú)狀態(tài)協(xié)議,所有的狀態(tài)保存在服務(wù)器中,因此要想操作服務(wù)器,必須通過(guò)某種手段,讓服務(wù)器發(fā)生狀態(tài)轉(zhuǎn)化。Http協(xié)議里有四種基本操作:GET用來(lái)獲取資源,POST用來(lái)新建資源,PUT用來(lái)更新資源,DELETE用來(lái)刪除資源
注解
-
@RequestMapping
- 為控制器指定可處理那些請(qǐng)求,進(jìn)而確定執(zhí)行那個(gè)方法
- 定義類(lèi)上:提供初步的請(qǐng)求映射信息
- 定義方法上:提供細(xì)分的映射信息
- 屬性
- value:請(qǐng)求url
- method:請(qǐng)求方法(RequestMethod.get,RequestMethod.post)多值用數(shù)組
- params:請(qǐng)求參數(shù)
- 值可使用簡(jiǎn)單表達(dá)式,例!p表示請(qǐng)求參數(shù)不能包含p
- params={“name”,“age!=10”} 參數(shù)age不為10
- heads:請(qǐng)求頭
- 值可使用簡(jiǎn)單表達(dá)式,heads={“Accept-Language=en-US,zh”}
- 可聯(lián)合使用,使請(qǐng)求更加精確化
- 支持Ant風(fēng)格匹配符
- 匹配文件名中的一個(gè)字符 ?
- 匹配文件名中的任意字符 *
- 匹配多層路徑 **
- @PathVariable 用來(lái)將URL中的占位符參數(shù)綁定到目標(biāo)方法的參數(shù)中
- @RequestMapping("/a/{id}")
- @PathVariable(“id”)
- @RequestMapping("/a/{id}")
- HiddenHttpMethodFilter 過(guò)濾器將請(qǐng)求轉(zhuǎn)換為標(biāo)準(zhǔn)的http方法,使瀏覽器form表單支持put,delete請(qǐng)求
<filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>- CharacterEncodingFilter 過(guò)濾器用于處理中文
<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> -
@RequestParam
- 用來(lái)映射url中請(qǐng)求參數(shù)
- 定義在方法形參前,給形參賦值
- 屬性
- value:請(qǐng)求參數(shù)的參數(shù)名
- required:該參數(shù)是否必須,默認(rèn)為true
- defaultValue:請(qǐng)求參數(shù)默認(rèn)值
-
@RequestHeader
- 映射請(qǐng)求頭信息
- 將請(qǐng)求報(bào)頭的屬性值綁定到處理方法的形參中
- 請(qǐng)求頭包含若干屬性,服務(wù)器可據(jù)此獲知客戶端信息
- 屬性
- value:請(qǐng)求頭參數(shù)的參數(shù)名
-
@CookieValue
- 映射Cookie信息
- 屬性與RequestParam相同
-
@ResponseBody
- 標(biāo)注在方法上
- 將java對(duì)象轉(zhuǎn)為json格式的數(shù)據(jù)
- 將controller的方法返回的對(duì)象通過(guò)適當(dāng)?shù)霓D(zhuǎn)換器轉(zhuǎn)換為指定的格式之后,寫(xiě)入到response對(duì)象的body區(qū),通常用來(lái)返回JSON或XML數(shù)據(jù)(用于異步獲取數(shù)據(jù))
- 在使用此注解之后不會(huì)再走視圖處理器,而是直接將數(shù)據(jù)寫(xiě)入到輸入流中,他的效果等同于通過(guò)response對(duì)象輸出指定格式的數(shù)據(jù)
- 所需jar包:jackson-annotations-2.9.0.pr2.jar,jackson-core-2.9.0.pr2.jar,jackson-databind-2.9.0.pr2.jar
- 使用fastJSON.jar 對(duì)象轉(zhuǎn)json:JSON.toJSONString(對(duì)象)
- 使用fastJSON.jar json轉(zhuǎn)對(duì)象:JSON.parseObject(json,對(duì)象.class)
-
@RequestBody
- 標(biāo)注在形參上
- 將前臺(tái)發(fā)送過(guò)來(lái)的JSON或XML數(shù)據(jù)封裝為對(duì)應(yīng)的 JavaBean 對(duì)象,封裝時(shí)使用到的一個(gè)對(duì)象是系統(tǒng)默認(rèn)配置的 HttpMessageConverter 進(jìn)行解析,然后封裝到形參上
- GET、POST方式提交
- 表單屬性 enctype
- 可選 application/x-www-form-urlencoded
- 不能處理 multipart/form-data 格式的數(shù)據(jù)
- 必須 application/json,application/xml 格式的數(shù)據(jù)
- 表單屬性 enctype
- PUT方式提交
- 表單屬性 enctype
- 必須 application/x-www-form-urlencoded
- 不能處理 multipart/form-data 格式的數(shù)據(jù)
- 表單屬性 enctype
-
@initBinder
- 提供數(shù)據(jù)綁定,可對(duì)WebDataBinder對(duì)象進(jìn)行初始化
- 標(biāo)注方法不能有返回值
-
@NumberFormat
- 對(duì)數(shù)字類(lèi)型的屬性格式化
-
@DateTimeFormat
- 對(duì)日期類(lèi)型屬性格式化
- pattern屬性:yyyy-MM-dd hh:mm:ss
處理器參數(shù)
POJO
- 普通Java類(lèi),具有一部分getter/setter方法的那種類(lèi)就可以稱(chēng)作POJO,實(shí)際意義就是普通的JavaBeans(簡(jiǎn)單的實(shí)體類(lèi)),特點(diǎn)就是支持業(yè)務(wù)邏輯的協(xié)助類(lèi)
- SpringMVC會(huì)按請(qǐng)求參數(shù)名與pojo屬性名進(jìn)行自動(dòng)匹配,自動(dòng)填充屬性值。且支持級(jí)聯(lián)屬性
servlet原生API
- HttpServletRequest
- HttpServletResponse
- HttpSession
- java.security.Principal
- Locale
- InputStream
- OutputStream
- Reader
- Writer
處理器處理模型數(shù)據(jù)
Map,Model或ModelMap類(lèi)型
- 使用org.springframework.ui.Model接口存儲(chǔ)模型數(shù)據(jù)
- 過(guò)程:在調(diào)用方法前會(huì)創(chuàng)建一個(gè)隱含的模型對(duì)象作為存儲(chǔ)容器,如果參數(shù)是Map或Model類(lèi)型,則將模型的引用傳遞給參數(shù),從而通過(guò)參數(shù)對(duì)象訪問(wèn)模型中的數(shù)據(jù)或向模型中添加新屬性數(shù)據(jù)
- 添加Map.put(“對(duì)象名”,對(duì)象值)、Model.addAttribute(“對(duì)象名”,對(duì)象值)
- 返回String類(lèi)型
ModelAndView類(lèi)型
- 包含視圖與模型信息
- ModelAndView ret = new ModelAndView(); //實(shí)例化
- ret.add(“對(duì)象名”,對(duì)象值) //添加數(shù)據(jù)到ModelAndView中
- SpringMVC會(huì)把ModelAndView的Model中的數(shù)據(jù)放到request域?qū)ο笾?/li>
- 返回ModelAndView類(lèi)型
@SessionAttributes
- 用于在多個(gè)請(qǐng)求之間公用某個(gè)模型屬性數(shù)據(jù)
- 標(biāo)注在控制器類(lèi)上,使屬性暫存在HttpSession中,屬性就可在session中獲取
- 屬性
- value={屬性名}
- types={屬性類(lèi)型.class}
@ModelAttribute
- 標(biāo)注在方法上,使每個(gè)目標(biāo)方法執(zhí)行之前被SpringMVC調(diào)用將標(biāo)注方法的屬性賦值給對(duì)應(yīng)參數(shù)
- 標(biāo)注在pojo類(lèi)型形參前,使形參為被@ModelAttribute標(biāo)注的方法的屬性
- 注:在標(biāo)注方法中放入map中的鍵與目標(biāo)方法形參一致(首字母小寫(xiě))
視圖解析器
- 對(duì)于返回String,View,ModeMap等類(lèi)型,SpringMVC會(huì)在內(nèi)部將它們裝配成一個(gè)ModelAndView對(duì)象,包含邏輯名和模型對(duì)象的視圖,借助視圖解析器最終得到視圖對(duì)象View
- 視圖的作用是渲染模型數(shù)據(jù),將模型里的數(shù)據(jù)以某種形式呈現(xiàn)給客戶
- 視圖對(duì)象由視圖解析器負(fù)責(zé)實(shí)例化。由于視圖是無(wú)狀態(tài)的,所以他們不會(huì)有線程安全的問(wèn)題。所謂視圖是無(wú)狀態(tài)的,是指對(duì)于每一個(gè)請(qǐng)求,都會(huì)創(chuàng)建一個(gè)View對(duì)象
- JSP是最常見(jiàn)的視圖技術(shù),結(jié)合JSTL使用
- 常用視圖解析器實(shí)現(xiàn)類(lèi)
- BeanNameViewResolver:將邏輯視圖解析為一個(gè)bean,bean的id等于邏輯視圖名,自動(dòng)根據(jù)我們的視圖名找到對(duì)應(yīng)的視圖Bean進(jìn)行解析
- InternalResourceViewResolver:將視圖名解析為一個(gè)url文件,會(huì)把 Controller 處理器方法返回的模型屬性都存放到對(duì)應(yīng)的 request 屬性中,然后通過(guò) RequestDispatcher 在服務(wù)器端把請(qǐng)求 forword 重定向到目標(biāo) URL
- 多個(gè)解析器可通過(guò)order屬性來(lái)指定優(yōu)先級(jí),越小優(yōu)先級(jí)越高
轉(zhuǎn)向與重定向
- 一般情況下控制器方法返回字符串類(lèi)型的值會(huì)被視圖解析器處理
- 若返回字符串帶有前綴,則做特殊處理,把其后字符串作為url
- 重定向:在返回值前加redirect:
- 轉(zhuǎn)向:在返回值前加forward:
配置文件標(biāo)簽
- <mvc:annotation-driven/> //注解驅(qū)動(dòng)
- 自動(dòng)注冊(cè) RequestMappingHandlerMapping,RequestMappingHandlerAdapter 與 ExceptionHandlerExceptionResolver 三個(gè)bean(3.1以上)
- 自動(dòng)為我們將掃描到的@Component,@Controller,@Service,@Repository等注解標(biāo)記的組件注冊(cè)到工廠中,來(lái)處理我們的請(qǐng)求,而<context:component-scan/>標(biāo)簽是告訴Spring 來(lái)掃描指定包下的類(lèi),并注冊(cè)被上述注解標(biāo)記的組件
- <mvc:default-servlet-handler/>
- 會(huì)在Spring MVC上下文中定義一個(gè)org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它會(huì)像一個(gè)檢查員,對(duì)進(jìn)入DispatcherServlet的URL進(jìn)行篩查,如果發(fā)現(xiàn)是靜態(tài)資源的請(qǐng)求,就將該請(qǐng)求轉(zhuǎn)由Web應(yīng)用服務(wù)器默認(rèn)的Servlet處理,如果不是靜態(tài)資源的請(qǐng)求,才由DispatcherServlet繼續(xù)處理
- 一般Web應(yīng)用服務(wù)器默認(rèn)的Servlet名稱(chēng)是"default",因此DefaultServletHttpRequestHandler可以找到它。如果你所有的Web應(yīng)用服務(wù)器的默認(rèn)Servlet名稱(chēng)不是"default",則需要通過(guò)default-servlet-name屬性顯示指定
- <mvc:view-controller>
- 發(fā)送的請(qǐng)求不想通過(guò)controller,只想直接地跳轉(zhuǎn)到目標(biāo)頁(yè)面
- path=“訪問(wèn)的路徑”(相當(dāng)于RequestMapping(“訪問(wèn)的路徑”))
- view-name=“跳轉(zhuǎn)的視圖” (相當(dāng)于return “跳轉(zhuǎn)的視圖”)
- 必須配置 <mvc:annotation-driven />
- 與處理器相同則失效
文件上傳
所需jar包:commons-fileupload-1.3.2.jar,commons-io-2.5.jar
SpringMVC通過(guò)即插即用的MultipartResolver接口實(shí)現(xiàn),實(shí)現(xiàn)類(lèi)為CommonsMultipartResolver
-
CommonsMultipartResolver配置
- defaultEncoding必須與jsp頁(yè)面pageEncoding屬性一致
- jsp頁(yè)面表單屬性enctype 必須 enctype=“multipart/form-data”
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"></property> <!--文件大小限定--> <property name="maxUploadSize" value="5242880"></property> </bean> controller層形參類(lèi)型為MultipartResolver
獲取上傳文件名方法:getOriginalFilename()
獲取文件輸入流:getInputStream()
將文件寫(xiě)入磁盤(pán):transferTo(路徑)
獲取隨機(jī)數(shù) UUID uuid=UUID.randomUUID()
定義為上傳文件名String filePreName=uuid.toString().replaceAll("-", “”)
文件下載
- 1.可通過(guò)鏈接直接下載特定的后綴的文件
- 2.通過(guò)附件方式
- 創(chuàng)建一個(gè)文件輸入流 InputStream is=new FileInputStream(文件路徑)
- 轉(zhuǎn)成字符數(shù)組 byte[] data=new byte[is.available()]
- 寫(xiě)入流 is.read(data);
- 實(shí)例化頭部對(duì)象 HttpHeaders headers=new HttpHeaders()
- 轉(zhuǎn)碼 String name=new String(readFileName.getBytes(“UTF-8”),“ISO8859-1”)
- 設(shè)置附件 headers.setContentDispositionFormData(“attachment”, name)
- 設(shè)置資源類(lèi)型headers.setContentType(MediaType.APPLICATION_OCTET_STREAM)
- 數(shù)據(jù)加入到附件中 ResponseEntity<byte[]> entity=new ResponseEntity<byte[]>(data, headers, HttpStatus.OK)
攔截器
- 與過(guò)濾器不同的是攔截器攔截動(dòng)態(tài)資源,即所有被@RequestMapping,@GetMapping ,@PostMapping標(biāo)注的資源
- 實(shí)現(xiàn)HandlerInterceptor接口
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) //目標(biāo)方法之前執(zhí)行,返回true表示放行
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) //目標(biāo)方法執(zhí)行結(jié)束之后執(zhí)行
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) //頁(yè)面銷(xiāo)毀時(shí)執(zhí)行
- 攔截器配置
<mvc:interceptors>
<!--自定義攔截器-->
<bean class="攔截器類(lèi)路徑"></bean>
<!--選擇攔截-->
<mvc:interceptor>
<!--攔截路徑,**代表路徑及子路徑-->
<mvc:mapping path="/**"/>
<!--不攔截路徑-->
<mvc:exclude-mapping path="/路徑"/>
<bean class="攔截器類(lèi)路徑"></bean>
</mvc:interceptor>
</mvc:interceptors>
異常處理
- 通過(guò)HandlerExceptionResolver接口處理異常,包括Handler映射,數(shù)據(jù)綁定以及目標(biāo)方法執(zhí)行發(fā)生的異常
- ExceptionHandlerExceptionResolver實(shí)現(xiàn)類(lèi)通過(guò)<mvc:annotation-driven/>加載
- @ControllerAdvice //標(biāo)注在自定義處理異常類(lèi)上
- 先找當(dāng)前Handler中的@ExceptionHandler,若未找到匹配的異常類(lèi),則去ControllerAdvice標(biāo)記的類(lèi)中查找
- @ExceptionHandler({異常類(lèi).class}) //標(biāo)注在異常方法上發(fā)生此異常類(lèi)自動(dòng)執(zhí)行方法處理異常,處理內(nèi)部異常
- @ControllerAdvice //標(biāo)注在自定義處理異常類(lèi)上
- ResponseStatusExceptionResolver實(shí)現(xiàn)類(lèi)
- @ResponseStatus //標(biāo)注在繼承此類(lèi)的類(lèi)上或發(fā)生異常的方法上
- value:狀態(tài)碼
- reason:信息
- @ResponseStatus //標(biāo)注在繼承此類(lèi)的類(lèi)上或發(fā)生異常的方法上
- DefaultHandlerExceptionResolver實(shí)現(xiàn)類(lèi)處理特殊異常,例請(qǐng)求方法異常
- SimpleMappingExceptionResolver實(shí)現(xiàn)類(lèi)
- 可將不同的異常映射到不同的jsp頁(yè)面(通過(guò)exceptionMappings屬性的配置),同時(shí)我們也可以為所有的異常指定一個(gè)默認(rèn)的異常
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 定義默認(rèn)的異常處理頁(yè)面,當(dāng)該異常類(lèi)型的注冊(cè)時(shí)使用 -->
<property name="defaultErrorView" value="error"></property>
<!-- 定義異常處理頁(yè)面用來(lái)獲取異常信息的變量名,默認(rèn)名為exception -->
<property name="exceptionAttribute" value="ex"></property>
<!-- 定義需要特殊處理的異常,用類(lèi)名或完全路徑名作為key,異常也頁(yè)名作為值 -->
<property name="exceptionMappings">
<props>
<prop key="IOException">error/ioexp</prop>
<prop key="java.sql.SQLException">error/sqlexp</prop>
</props>
</property>
</bean>
導(dǎo)入其他配置文件
- 1.通過(guò)<import resource=“文件”/>導(dǎo)入
- 2.在web.xml中引入
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:文件路徑</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
最后
感謝你看到這里,看完有什么的不懂的可以在評(píng)論區(qū)問(wèn)我,覺(jué)得文章對(duì)你有幫助的話記得給我點(diǎn)個(gè)贊,每天都會(huì)分享java相關(guān)技術(shù)文章或行業(yè)資訊,歡迎大家關(guān)注和轉(zhuǎn)發(fā)文章!