什麼是SpringMVC
Spring MVC是Spring Framework的一部分,是基於Java實現MVC的輕量級Web框架。
檢視官方文件:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web
Spring的web框架圍繞DispatcherServlet [ 排程Servlet ] 設計。
DispatcherServlet的作用是將請求分發到不同的處理器
SpringMVC執行原理
簡要分析執行流程:
-
DispatcherServlet表示前置控制器,是整個SpringMVC的控制中心。使用者發出請求,DispatcherServlet接收請求並攔截請求。
-
HandlerMapping為處理器對映。DispatcherServlet呼叫HandlerMapping,HandlerMapping根據請求url查詢Handler。
-
HandlerExecution表示具體的Handler,其主要作用是根據url查詢控制器,如上url被查詢控制器為:hello。
-
HandlerExecution將解析後的資訊傳遞給DispatcherServlet,如解析控制器對映等。
-
HandlerAdapter表示處理器介面卡,其按照特定的規則去執行Handler。
-
Handler讓具體的Controller執行。
-
Controller將具體的執行資訊返回給HandlerAdapter,如ModelAndView。
-
HandlerAdapter將檢視邏輯名或模型傳遞給DispatcherServlet。
-
DispatcherServlet呼叫檢視解析器(ViewResolver)來解析HandlerAdapter傳遞的邏輯檢視名。
-
檢視解析器將解析的邏輯檢視名傳給DispatcherServlet。
-
DispatcherServlet根據檢視解析器解析的檢視結果,呼叫具體的檢視。
-
最終檢視呈現給使用者。
註解開發MVC
配置web.xml
註冊DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?> <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_4_0.xsd" version="4.0"> <!--1.註冊servlet--> <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--通過初始化引數指定SpringMVC配置檔案的位置,進行關聯--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!-- 啟動順序,數字越小,啟動越早 --> <load-on-startup>1</load-on-startup> </servlet> <!--所有請求都會被springmvc攔截 --> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
/ 和 /* 的區別:
< url-pattern > / </ url-pattern > 不會匹配到.jsp, 只針對我們編寫的請求;即:.jsp 不會進入spring的 DispatcherServlet類 。
< url-pattern > /* </ url-pattern > 會匹配 *.jsp,會出現返回 jsp檢視 時再次進入spring的DispatcherServlet 類,導致找不到對應的controller所以報404錯。
-
注意web.xml版本問題,要最新版!
-
註冊DispatcherServlet
-
關聯SpringMVC的配置檔案
-
啟動級別為1
-
對映路徑為 / 【不要用/*,會404】
新增Spring MVC配置檔案
在resource目錄下新增springmvc-servlet.xml配置檔案,配置的形式與Spring容器配置基本類似,為了支援基於註解的IOC,設定了自動掃描包的功能,具體配置資訊如下:
<?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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 自動掃描包,讓指定包下的註解生效,由IOC容器統一管理 --> <context:component-scan base-package="com.kuang.controller"/> <!-- 讓Spring MVC不處理靜態資源 --> <mvc:default-servlet-handler /> <!-- 支援mvc註解驅動 在spring中一般採用@RequestMapping註解來完成對映關係 要想使@RequestMapping註解生效 必須向上下文中註冊DefaultAnnotationHandlerMapping 和一個AnnotationMethodHandlerAdapter例項 這兩個例項分別在類級別和方法級別處理。 而annotation-driven配置幫助我們自動完成上述兩個例項的注入。 --> <mvc:annotation-driven /> <!-- 檢視解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!-- 字首 --> <property name="prefix" value="/WEB-INF/jsp/" /> <!-- 字尾 --> <property name="suffix" value=".jsp" /> </bean> </beans>
在檢視解析器中我們把所有的檢視都存放在/WEB-INF/目錄下,這樣可以保證檢視安全,因為這個目錄下的檔案,客戶端不能直接訪問。
建立Controller
@Controller @RequestMapping("/HelloController") public class HelloController { //真實訪問地址 : 專案名/HelloController/hello @RequestMapping("/hello") public String sayHello(Model model){ //向模型中新增屬性msg與值,可以在JSP頁面中取出並渲染 model.addAttribute("msg","hello,SpringMVC"); //web-inf/jsp/hello.jsp return "hello"; } }
-
@Controller是為了讓Spring IOC容器初始化時自動掃描到;
-
@RequestMapping是為了對映請求路徑,這裡因為類與方法上都有對映所以訪問時應該是/HelloController/hello;
-
方法中宣告Model型別的引數是為了把Action中的資料帶到檢視中;
-
方法返回的結果是檢視的名稱hello,加上配置檔案中的前字尾變成WEB-INF/jsp/hello.jsp。
建立檢視層
在WEB-INF/ jsp目錄中建立hello.jsp , 檢視可以直接取出並展示從Controller帶回的資訊;
可以通過EL表示取出Model中存放的值,或者物件;
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>SpringMVC</title> </head> <body> ${msg} </body> </html>
小結
實現步驟其實非常的簡單:
-
新建一個web專案
-
匯入相關jar包
-
編寫web.xml , 註冊DispatcherServlet
-
編寫springmvc配置檔案
-
接下來就是去建立對應的控制類 , controller
-
最後完善前端檢視和controller之間的對應
-
測試執行除錯.
RestFul 風格
使用RESTful操作資源 :
可以通過不同的請求方式來實現不同的效果!如下:請求地址一樣,但是功能可以不同!
http://127.0.0.1/item/1 查詢,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 刪除,DELETE
測試使用
@PathVariable 註解
在Spring MVC中可以使用 @PathVariable 註解,讓方法引數的值對應繫結到一個URI模板變數上。
@Controller public class RestFulController { //對映訪問路徑 @RequestMapping("/commit/{p1}/{p2}") public String index(@PathVariable int p1, @PathVariable int p2, Model model){ int result = p1+p2; //Spring MVC會自動例項化一個Model物件用於向檢視中傳值 model.addAttribute("msg", "結果:"+result); //返回檢視位置 return "test"; } }
我們來修改下對應的引數型別,再次測試
@RequestMapping("/commit/{p1}/{p2}") public String index(@PathVariable int p1, @PathVariable String p2, Model model){ String result = p1+p2; //Spring MVC會自動例項化一個Model物件用於向檢視中傳值 model.addAttribute("msg", "結果:"+result); //返回檢視位置 return "test"; }
使用method屬性指定請求型別
用於約束請求的型別,可以收窄請求範圍。指定請求謂詞的型別如GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE等
例如:
//對映訪問路徑,必須是POST請求 @RequestMapping(value = "/hello",method = {RequestMethod.POST}) public String index2(Model model){ model.addAttribute("msg", "hello!"); return "test"; }
如果我們使用瀏覽器位址列進行訪問預設是Get請求,會報錯405:
也可以通過註解處理 HTTP 請求的方法:@GetMapping;@PostMapping;@PutMapping;@DeleteMapping;@PatchMapping,效果是一樣的
@GetMapping("/add/{a}/{b}") public String test(@PathVariable int a,@PathVariable String b, Model model) { String res=a+b; model.addAttribute("msg","get結果為"+res); return "test"; } @PostMapping("/add/{a}/{b}") public String test2(@PathVariable int a,@PathVariable String b, Model model) { String res=a+b; model.addAttribute("msg","method方法結果為"+res); return "test"; }
資料處理及跳轉
跳轉
@Controller public class ResultSpringMVC2 { @RequestMapping("/rsm2/t1") public String test1(){ //轉發 return "test"; } @RequestMapping("/rsm2/t2") public String test2(){ //重定向 return "redirect:/index.jsp"; //return "redirect:hello.do"; //hello.do為另一個請求/ } }
資料處理
處理提交資料
1、提交的域名稱和處理方法的引數名一致
提交資料 : http://localhost:8080/hello?name=kuangshen
處理方法 :
@RequestMapping("/hello") public String hello(String name){ System.out.println(name); return "hello"; }
2、提交的域名稱和處理方法的引數名不一致
提交資料 : http://localhost:8080/hello?username=kuangshen
處理方法 :
//@RequestParam("username") : username提交的域的名稱 . @RequestMapping("/hello") public String hello(@RequestParam("username") String name){ System.out.println(name); return "hello"; }
3、提交的是一個物件
要求提交的表單域和物件的屬性名一致 , 引數使用物件即可
1、實體類
public class User { private int id; private String name; private int age; //構造 //get/set //tostring() }
2、提交資料 : http://localhost:8080/mvc04/user?name=kuangshen&id=1&age=15
3、處理方法 :
@RequestMapping("/user") public String user(User user){ System.out.println(user); return "hello"; }
資料顯示到前端
通過Model
@RequestMapping("/ct2/hello") public String hello(@RequestParam("username") String name, Model model){ //封裝要顯示到檢視中的資料 //相當於req.setAttribute("name",name); model.addAttribute("msg",name); System.out.println(name); return "test"; }
通過ModelAndView
public class ControllerTest1 implements Controller { public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { //返回一個模型檢視物件 ModelAndView mv = new ModelAndView(); mv.addObject("msg","ControllerTest1"); mv.setViewName("test"); return mv; } }
通過ModelMap
@RequestMapping("/hello") public String hello(@RequestParam("username") String name, ModelMap model){ //封裝要顯示到檢視中的資料 //相當於req.setAttribute("name",name); model.addAttribute("name",name); System.out.println(name); return "hello"; }
亂碼問題
輸入中文測試,發現亂碼
SpringMVC給我們提供了一個過濾器 , 可以在web.xml中配置 .
修改了xml檔案需要重啟伺服器!
<filter> <filter-name>encoding</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>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
明天任務:進行ssm框架的整合