SpringMVC(博主轉載老師講義,只圖檢視方便)
Spring-MVC
一、MVC 概述
mvc是軟體開發中非常常見的分層設計,目的是使程式中的程式碼根據負責的功能分離,便於維護,當你更新檢視時,不用修改其他程式碼。
M: Model -- JavaBean 模型 V: View -- 檢視 C: Controller 控制器
二、SpringMVC
Springmvc 是spring 框架的一個模組,用於構建web應用程式,Springmvc是符合mvc設計的一個框架。
三、入門案例
-
準備依賴
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.14.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.3.14.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.14.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.3.14.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.14.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
-
配置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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 應用程式前端控制器 --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-
編寫spring-mvc配置檔案 ( spring-mvc.xml )
<?xml version="1.0" encoding="UTF-8"?> <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" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 掃描控制器所在包 --> <context:component-scan base-package="com.xingxue.mvc.controller"/> <!-- 開啟註解驅動 --> <mvc:annotation-driven/> <!-- 對於靜態資源 請求交給容器的預設servlet處理 --> <mvc:default-servlet-handler/> <!-- 檢視解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <!-- --> <property name="suffix" value=".jsp"/> </bean> </beans>
-
編寫控制器
package com.xingxue.mvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/test/") public class HelloController { @RequestMapping("/hello") public String test1( ) { return "hello"; } }
-
測試
四、請求對映( @RequestMapping )
1、基本請求對映
@RequestMapping("/test/") public class HelloController { @RequestMapping("/hello") public String test1( ) { return "hello"; } }
2、精準請求對映 ( value method param header 對映 Http訊息 )
@RequestMapping(value="/emp",method=RequestMethod.GET) public void getEmp() { System.out.println("get one resource"+id); } @RequestMapping(value="/emps",method=RequestMethod.GET) public void getEmps() { System.out.println("get all resource"); } @RequestMapping(value="/emp",method=RequestMethod.POST) public void save() { System.out.println("add one resource"); } @RequestMapping(value="/emp",method=RequestMethod.DELETE) public void delete() { System.out.println("delete one resource"); } @RequestMapping(value="/emp",method=RequestMethod.PUT) public void update() { System.out.println("update one resource"); }
3、ant請求對映
@RequestMapping(value="/user/?bc") public void abc() { System.out.println("abc"); } @RequestMapping(value="/user/*d") public void aaa() { System.out.println("aaa"); } @RequestMapping(value="/user/**/sb") public void bbb() { System.out.println("bbb"); } @RequestMapping(value="/user/**/?mvc*") public void ccc() { System.out.println("ccc"); }
Ant 資源地址支援3種統配符
? :資源名字中一個任意字元
* : 資源名字中的任意個字元
** : 匹配多層路徑
4、@PathVariable 註解
通過 @PathVariable 可以將 URL 中佔位符引數繫結到控 制器處理方法的入參中:URL 中的 {xxx} 佔位符可以通過
@PathVariable("xxx") 繫結到操作方法的入參中。
@RequestMapping(value="/emp/{id}",method=RequestMethod.GET) public void getEmp(@PathVariable("id") Integer id) { System.out.println("get one resource"+id); }
五、RestFul風格
REST:即 Representational State Transfer。(資源)表現層狀態轉化。是目前 最流行的一種網際網路軟體架構。它結構清晰、符合標準、易於理解、擴充套件方便, 所以正得到越來越多網站的採用
• 資源(Resources):網路上的一個實體,或者說是網路上的一個具體資訊。它 可以是一段文字、一張圖片、一首歌曲、一種服務,總之就是一個具體的存在。 可以用一個URI(統一資源定位符)指向它,每種資源對應一個特定的 URI 。要 獲取這個資源,訪問它的URI就可以,因此 URI 即為每一個資源的獨一無二的識 別符。 • 表現層(Representation):把資源具體呈現出來的形式,叫做它的表現層(Representation)。比如,文字可以用 txt 格式表現,也可以用 HTML 格 式、XML 格式、JSON 格式表現,甚至可以採用二進位制格式。 • 狀態轉化(State Transfer):每發出一個請求,就代表了客戶端和伺服器的一 次互動過程。HTTP協議,是一個無狀態協議,即所有的狀態都儲存在伺服器 端。因此,如果客戶端想要操作伺服器,必須通過某種手段,讓伺服器端發生“ 狀態轉化”(State Transfer)。而這種轉化是建立在表現層之上的,所以就是 “ 表現層狀態轉化”。具體說,就是 HTTP 協議裡面,四個表示操作方式的動 詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:GET 用來獲 取資源,POST 用來新建資源,PUT 用來更新資源,DELETE 用來刪除資源。
API 示例:
URL | HTTP Method | 作用 |
---|---|---|
–/order/1 | GET | :得到 id = 1 的 order |
–/order/1 | PUT | :更新id = 1的 order |
–/order | POST | :新增 order |
–/order/1 | DELETE | :刪除 id = 1的 order |
-/orders/1 | GET | : 1號使用者 全部訂單 |
SpringMVC對RestFul支援
HiddenHttpMethodFilter:瀏覽器 form 表單只支援 GET 與 POST 請求,而DELETE、PUT 等 method 並不支 持,Spring3.0 添加了一個過濾器,可以將這些請求轉換 為標準的 http 方法,使得支援 GET、POST、PUT 與 DELETE 請求。
配置 HiddenHttpMethodFilter
<!-- HiddenHttpMethodFilter: 支援restful 風格請求 --> <filter> <filter-name>RestFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>RestFilter</filter-name> <servlet-name>SpringMVC</servlet-name> </filter-mapping>
六、獲取請求資料
1、簡單資料型別
@RequestMapping("t1") public void test1(String name,int age ) { System.out.println("you input is "+name+ "\t" + age ); }
測試:http://localhost;8080/spring-web/params/t1?name=admin&age=11
2、pojo資料型別(支援級聯屬性注入)
@RequestMapping("t2") public void test2(User u) { System.out.println(u); } ---------------------------------------------------------------------------------------------- public class User { private String username; private int age; private Company company; //省略get set } public class Company{ private String cname; private String address; private String phone; //省略get set方法 }
測試:http://localhost;8080/spring-web/params/t2?username=admin&age=11&company.cname=baidu&company.address=beijing&company.phone=010-666666
3、@RequestParam
(此註解目的是 把請求引數繫結到入參 主要解決前後引數名字不一致的情況)
@RequestMapping("t3") public void test3(@RequestParam(value="fullname",required=true)String name,@RequestParam(value="phone")String tel ) { System.out.println("名字:"+name); System.out.println("電話:"+tel); }
測試:http://localhost:8080/spring-mvc/params/t3?fullname=kangkang&phone=188xxxxxx
4、@RequestHeader(獲得請求頭資訊) @CookieValue(獲得Cookie資訊)
@RequestMapping("t4") public void test4(@RequestHeader(value="connection",required=false)String header, @CookieValue(value="JSESSIONID",required=false) String sessid ) { System.out.println("Connection:"+header); System.out.println("sessionid:"+sessid); }
5、使用Servlet API作為入參
@RequestMapping("t5") public void test5(HttpServletRequest req,HttpServletResponse resp, HttpSession session) throws IOException { String n=req.getParameter("name"); resp.getWriter().write(n); resp.getWriter().flush(); }
以下是方法支援的 型別
•HttpServletRequest
•HttpServletResponse
•HttpSession
•java.security.Principal
•Locale
•InputStream
•OutputStream
•Reader
•Writer
總結:SpringMVC控制器方法入參非常靈活
七、頁面渲染
-
ModelAndView
直接翻譯為 模型和資料,其作用是儲存模型和資料,最終目的是把模型資料( Model )帶到檢視(View)中展現
@RequestMapping("t6") public ModelAndView t6() { ModelAndView mv = new ModelAndView(); mv.getModel().put("company", "baidu"); mv.getModel().put("phone", "010-666666"); mv.setViewName("hello"); return mv; }
-
Model
直接翻譯為 模型,其作用是提供資料,但是也僅僅提供資料,不參與跳轉檢視,跳轉檢視需要 return 確定,此Model不需要開發者手動建立,只需要宣告在方法的入參中即可,它由框架建立和注入以及傳送到檢視
@RequestMapping("t7") public String t7( Model md ) { md.addAttribute("company", "tengxun"); md.addAttribute("phone", "010=888888"); return "hello"; }
-
ModelMap Map
其作用和使用方法 與Model一致
@RequestMapping("t8") public String t8(ModelMap mp) { mp.addAttribute("company", "alibaba"); mp.addAttribute("phone", "010-999999"); return "hello"; } @RequestMapping("t9") public String t9(Map<String,Object> mp) { mp.put("company", "oralce"); mp.put("phone", "010-555555"); return "hello"; }
測試效果: ![1535214218514](C:\Users\ADMINI~1\AppData\Local\Temp\1535214218514.png)
八、轉發和重定向
區別:轉發一次請求,瀏覽器上地址不變 重定向兩次請求,瀏覽器地址改變
/*重定向到jsp*/ @RequestMapping("/t10") public String t10(){ return "redirect:/static/jsp/add.jsp"; } /*轉發向到jsp*/ @RequestMapping("/t10") public String t10(){ return "forward:/static/jsp/add.jsp"; } /*重定向到controller*/ @RequestMapping("/t11") public String t11(){ return "redirect:/param/t9"; } /*轉發到控制器controller*/ @RequestMapping("/t12") public String t12( ){ return "forward:/param/t8"; }
SpringMVC 預設採取的方式是轉發
重定向: redirect:/xxx
轉發:forward:/xxx
九、處理JSON資料
當前端請求方法後不需要跳轉頁面,而只是需要json資料,這時可以使用@ResponseBody註解,該註解的作用是把控制器方法的返回值 通過訊息轉換器 HttpMessageConverter 自動把方法的返回值 新增 到HttpResponse 響應訊息的body中。為此我們需要新增 json依賴
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.7</version> </dependency>
還需要開啟註解驅動 ,
<mvc:annotation-driven/>
•<mvc:annotation-driven /> 會自動注 冊RequestMappingHandlerMapping
、RequestMappingHandlerAdapter 與
ExceptionHandlerExceptionResolver 三個bean。
• 還將提供以下支援:
–支援使用 ConversionService 例項對錶單引數進行型別轉換
–支援使用 @NumberFormat annotation、@DateTimeFormat
註解完成資料型別的格式化
– 支援使用 @Valid 註解對 JavaBean 例項進行 JSR 303 驗證
–支援使用 @RequestBody 和 @ResponseBody 註解
@RequestMapping("/json") @ResponseBody() public User t11() { User user = new User(); user.setUsername("admin"); user.setAge(10); Address addr= new Address(); addr.setXian("奉節縣"); addr.setXiang("石崗鄉"); addr.setSheng("重慶市"); user.setAddr(addr ); return user; }
{"username":"admin","age":10,"addr":{"sheng":"重慶市","xian":"奉節縣","xiang":"石崗鄉"}}
十、檔案上傳
依賴
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
①準備上傳html頁面
<form action="/file/upload" method="post" enctype="multipart/form-data"> <input name="file" type="file"> <input type="submit" value="上傳" /> </form>
②準備控制器接受檔案
@Controller @RequestMapping("/file") public class FileController { @RequestMapping("/upload") public String fileUpoad(MultipartFile file, HttpServletRequest request){ System.out.println(file); String path=request.getServletContext().getRealPath("/")+"upload\\"; File f= new File(path); if(!f.exists()){ f.mkdirs(); } try { //儲存檔案方法 /d:/abc/mvc/upload/abc.png file.transferTo( new File(f, file.getOriginalFilename() ) ); } catch (IOException e) { return "error"; } System.out.println("ok..................."); return "success"; } }
③sping配置
<!--檔案上傳配置--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"/> <property name="maxUploadSize" value="104857600"/> </bean>
十 一、攔截器
1 、什麼是攔截器?
Spring MVC中的攔截器(Interceptor)類似於Servlet中的過濾器(Filter),它主要用於攔截使用者請求並作相應的處理。例如通過攔截器可以進行許可權驗證、記錄請求資訊的日誌、判斷使用者是否登入等。要使用Spring MVC中的攔截器,就需要對攔截器類進行定義和配置。通常攔截器類可以通過兩種方式來定義。通過實現HandlerInterceptor介面,或繼承HandlerInterceptor介面的實現類(如HandlerInterceptorAdapter)來定義。
2、實現攔截器
①編寫攔截器程式碼
以實現HandlerInterceptor介面方式為例,自定義攔截器類的程式碼如下:
public class CustomInterceptor implements HandlerInterceptor{ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception { System.out.println("開始攔截...."); return false; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("結束攔截...."); } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("整個攔截過程完成"); } }
preHandle() 方法:該方法會在控制器方法前執行,其返回值表示是否中斷後續操作。當其返回值為true時,表示繼續向下執行;當其返回值為false時,會中斷後續的所有操作(包括呼叫下一個攔截器和控制器類中的方法執行等)。
postHandle()方法:該方法會在控制器方法呼叫之後,且解析檢視之前執行。可以通過此方法對請求域中的模型和檢視做出進一步的修改。
afterCompletion()方法:該方法會在整個請求完成,即檢視渲染結束之後執行。可以通過此方法實現一些資源清理、記錄日誌資訊等工作。
② 註冊和配置攔截器
<!--配置攔截器--> <mvc:interceptors> <!-- 直接註冊 interceptors 下的攔截器為全域性的攔截器 --> <!--<bean class="com.ma.interceptor.CustomeInterceptor" />--> <!--攔截器1--> <mvc:interceptor> <!--配置攔截器的作用路徑--> <mvc:mapping path="/**"/> <mvc:exclude-mapping path=""/> <!--定義在<mvc:interceptor>下面的表示匹配指定路徑的請求才進行攔截--> <bean class="com.ma.interceptor.Intercptor1"/> </mvc:interceptor> <!--攔截器2--> <mvc:interceptor> <mvc:mapping path="/hello"/> <bean class="com.ma.interceptor.Interceptor2"/> </mvc:interceptor> </mvc:interceptors>
上面的程式碼中,mvc:interceptors元素用於配置一組攔截器,基子元素<bean>中定義的是全域性攔截器,它會攔截所有的請求;而mvc:interceptor元素中定義的是指定路徑的攔截器,它會對指定路徑下的請求生效。mvc:interceptor元素的子元素mvc:mapping用於配置攔截器作用的路徑,該路徑在其屬性path 中定義。如上述程式碼中 path 的屬性值“/**” 表示攔截所有路徑,“/hello” 表示攔截所有以 “/hello” 結尾的路徑。如果在請求路徑中包含不需要攔截的內容,還可以通過mvc:exclude-mapping元素進行配置。
③ 測試
3、攔截器 執行流程
請求 --> preHandle(前置處理) --> target(控制器方法) --> postHandle(後置處理) --> dispatcherServlet(渲染頁面) --> afterCompletion(結束處理)
十二、異常處理
在實際開發過程中,我們通常會把應用後端分為3層來開發,Controller(控制器) Service(服務層) Dao(資料訪問層),這3層都可能會有異常的發生,通常的做法是把異常,由 DAO 拋到 Service 再拋到 Controller,最後再控制其中處理異常。這樣可以把異常反饋給最頂層呼叫者處理。但是一個系統中有若干個Controller ,若干個方法,處理異常就變得十分難受了,Springmvc提供了一種全域性異常處理機制,允許我們在一個類中集中處理異常,控制器不需理會異常。
實現異常處理方式一:
@ExceptionHandler({IOException.class,NullPointerException.class } ) public String excpetionHandle(){ return "error"; }
註解中的異常型別可以給 單個 或 多個
這種處理方式,比較侷限,只能處理當前 Controller中的異常
實現全域性異常處理方式一:
①實現 HandlerExceptionResolver 介面
//確保 AppGolablException 例項加入IOC容器中 可以用xml配置和註解配置 @Component public class AppGolablException implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { //這裡無論什麼異常都到 error 頁面去 //當然這裡可以根據實際的異常型別做 不同的響應 ModelAndView mv = new ModelAndView("error"); return mv; } }
②丟擲異常
@RequestMapping("/ex") public String testex(){ throw new NullPointerException("hehe"); } @RequestMapping("/ex2") public String textex2() throws Exception{ throw new IOException("haha"); }
這時請求 ex 和 ex2 方法都會跳轉到 error頁面
實現全域性異常處理方式二: @ControllerAdvice + @ExceptionHandler
①編寫異常處理程式碼
@ControllerAdvice public class AppException { @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Exception.class) @ResponseBody public Object handleHttpMessageNotReadableException(Exception e) { System.out.println("------------"); return "50X"; } }
②控制器丟擲異常
@RequestMapping("/ex") public String testex(){ throw new NullPointerException("hehe"); } @RequestMapping("/ex2") public String textex2() throws Exception{ throw new IOException("haha"); }