6.SpringMVC
SpringMVC
檢視View
負責頁面的顯示;與使用者的互動。包含各種表單。實現檢視用到的技術有html/css/jsp/js等前端技術。
使用者互動:使用者滑鼠點選頁面;填寫頁面中各種表單........等等
模型Model
模型負責各個功能的實現(如登入、增加、刪除功能)。模型用JavaBean實現
控制器Controller
控制器負責將檢視與模型一一對應起來。相當於一個模型分發器。所謂分發就是:
①接收請求,並將該請求跳轉(轉發,重定向)到模型進行處理。
②模型處理完畢後,再通過控制器,返回給檢視中的請求處。建議使用Servlet實現控制器。
在配置檔案中配置SpringMVC
web.xml
<!-- 配置前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置SpringMVC核心檔案的位置 預設去WEB-INF下尋找--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/springmvc-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> <!-- 所有請求都會被攔截 --> </servlet-mapping>
springmvc-servlet.xml
<!-- 配置對映關係 --> <bean name="/hello.action" class="com.wiscom.demo.FirstController"></bean> <!-- 配置檢視解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"></property> <property name="suffix" value=".jsp"></property> </bean>
com.wiscom.demo.FirstController
package com.wiscom.demo; public class FirstController implements Controller{ public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception { // 處理資料和介面 ModelAndView mav = new ModelAndView(); // 新增資料 mav.addObject("msg1", "hello"); mav.addObject("msg2", "springmvc"); // 設定介面 mav.setViewName("first");//WEB-INF/first.jsp return mav; } }
first.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE HTML> <html> <head> </head> <body> welcome <hr> <p>${msg1}</p> <p>${msg2}</p> </body> </html>
使用註解方式配置SpringMVC
web.xml
<!-- 配置前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置SpringMVC核心檔案的位置 預設去WEB-INF下尋找--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/springmvc-servlet.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
springmvc-servlet.xml
<!-- 開啟包掃描 --> <context:component-scan base-package="com.wiscom.demo"></context:component-scan> <context:annotation-config></context:annotation-config> <!-- 開啟mvc註解配置 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 配置檢視解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"></property> <property name="suffix" value=".jsp"></property> </bean>
com.wiscom.demo.FirstController
package com.wiscom.demo; @Controller //將FirstController交由Spring進行管理 public class FirstController { @RequestMapping("/test01.action") public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } @RequestMapping("/test02.action") public String test02(){ // 返回的字串代表的是View的名稱 return "first"; } }
first.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE HTML> <html> <head> </head> <body> welcome <hr> <p>${msg1}</p> <p>${msg2}</p> </body> </html>
SpringMVC細節
可以在類上新增對映(@RequestMapping)
在類上新增@RequestMapping
在方法上新增@RequestMapping
@Controller //將FirstController交由Spring進行管理 @RequestMapping("/Detail02") public class FirstController { @RequestMapping("/test01.action") public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
@RequestMapping中的屬性
可以配置多個路徑
@RequestMapping({"/test01.action","/test01*.action"})
params:有這些屬性時被請求傳過來時才能夠被呼叫執行
@RequestMapping(value="/test03.action",params={"username","password"})
method:method設定為POST時,只能接受POST的資料
@RequestMapping(value="/test03.action",method=RequestMethod.POST)
常用POST,GET
headers:只有傳過來的請求包含相關頭部時才會被呼叫(很少使用)
@RequestMapping(value="/test03.action",headers={"host"})
註解屬舉例
指定要將當前處理器繫結到哪個訪問路徑上。
可以配置多個路徑。
@Controller //將FirstController交由Spring進行管理 public class FirstController { @RequestMapping({"/test01.action","/test01*.action"}) public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
params
params
有這些屬性時被請求傳過來時才能夠被呼叫執行
@Controller //將FirstController交由Spring進行管理 public class FirstController { @RequestMapping(value="/test03.action",params={"username","password"}) public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
method
method=RequestMethod.POST
method設定為POST時,只能接受POST的資料
@Controller //將FirstController交由Spring進行管理 public class FirstController { @RequestMapping(value="/test03.action",method=RequestMethod.POST) public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
headers
headers
只有傳過來的請求包含相關頭部時才會被呼叫
@Controller //將FirstController交由Spring進行管理 public class FirstController { @RequestMapping(value="/test03.action",headers={"host"}) public ModelAndView test01(){ ModelAndView mav = new ModelAndView(); mav.addObject("msg1", "pig"); mav.addObject("msg2", "fdsfd"); mav.setViewName("first"); return mav; } }
處理器方法支援的引數型別和返回值型別
支援的方法引數型別
HttpServletRequest
代表當前請求的物件
HttpServletResponse
代表當前響應的物件
HttpSession
代表當前會話的物件
WebRequest
SpringMVC提供的物件,相當於是request和session的合體,可以操作這兩個域中的屬性
InputStream OutputStream Reader Writer
代表request中獲取的輸入流和response中獲取的輸出流
@PathVariable
可以將請求路徑的指定部分獲取賦值給指定方法引數
@RequestParam
public void test05(@RequestParam(value="nn") String nnn){ System.out.println(nnn); }
可以將指定請求引數賦值給指定方法引數,如果不寫此註解,則預設會將同名的請求引數賦值給方法引數
@CookieValue
可以將請求中的指定名稱的cookie賦值給指定方法引數
@RequestHeader
以將請求引數中的指定名稱的頭賦值給指定方法引數
Model和ModelMap和java.util.Map
向這些Model ModelMap Map中存入屬性,相當於向模型中存入資料
MultipartFile
實現檔案上傳功能時,接收上傳的檔案物件
package com.wiscom.demo; @Controller //將FirstController交由Spring進行管理 @RequestMapping("/cbt") public class FirstController { @RequestMapping(value="/test01.action") // User中的屬性在請求中要按照順序傳送 public void test05(User user){ System.out.println(user); } @RequestMapping(value="/test02.action") public void test05(@RequestParam(value="nn") String nnn){ System.out.println(nnn); } @RequestMapping("/test03.action") public void test06(String[] like){ // System.out.println(like); System.out.println(Arrays.toString(like)); } }
支援的返回值型別
ModelAndView
可以返回一個ModelAndView物件,在其中封裝Model和View資訊
View
可以直接返回一個代表檢視的View物件
字串
直接返回檢視的名稱
void
如果返回值型別是void,則會自動返回和當前處理器路徑名相同的檢視名
@ResponseBody
當方法被@ResponseBody修飾時,預設將返回的物件轉為json寫入輸出
除以上之外返回的任何內容都會被當做模型中的資料來處理,而返回的檢視名等同於當前處理器路徑名
獲取Request Response物件
獲取請求引數
通過request物件獲取
@RequestMapping(value="/test03.action") public void test03(HttpServletRequest request,HttpServletResponse response){ // 返回的字串代表的是View的名稱 System.out.println(request); // 獲取請求引數 String username = request.getParameter("username"); int age = Integer.parseInt(request.getParameter("age")); String password = request.getParameter("password"); User user = new User(age,username,password); System.out.println(user); // System.out.println(response); System.out.println(username + "~~" +age); }
直接接收請求引數
@RequestMapping(value="/test04.action") public void test04(String username,int age){ // 返回的字串代表的是View的名稱 System.out.println(username + "~~" +age); }
自動封裝請求引數資訊到bean
@RequestMapping(value="/test05.action") public void test05(User user){ // 請求中的引數必須與bean中的屬性一一對應 System.out.println(user); }
處理複雜型別
FirstController.java
@RequestMapping(value="/test01.action") public void test05(User user){ System.out.println(user); }
test2.jsp
<form action="${pageContext.request.contextPath}/cbt/test01.action" method="get"> 年齡:<input type="text" name="age"> 姓名:<input type="text" name="username"> 密碼:<input type="text" name="password"> 狗齡:<input type="text" name="Dog.age"> 狗名:<input type="text" name="Dog.name"> <input type="submit" value="提交"> </form>
請求引數中的名稱和屬性名不同的處理@RequestParam
value
引數名字,即入參的請求引數名字,如value=“delId”
required
是否必須,預設是true,表示請求中一定要有相應的引數,否則將報400錯誤碼;
defaultValue
預設值,表示如果請求中沒有同名引數時的預設值
@RequestMapping(value="/test02.action") public void test05(@RequestParam(value="nn") String nnn){ System.out.println(nnn); }
請求引數中存在多個同名引數
FirstController.java
@RequestMapping("/test03.action") public void test06(String[] like){ // System.out.println(like); System.out.println(Arrays.toString(like)); }
test3.jsp
<form action="${pageContext.request.contextPath}/cbt/test03.action" method="get"> <input type="checkbox" name="like" value="wzry"/>王者榮耀 <input type="checkbox" name="like" value="lol"/>英雄聯盟 <input type="checkbox" name="like" value="dota"/>刀塔 <input type="checkbox" name="like" value="chij"/>絕地求生 <input type="submit" value="提交"> </form>
請求引數中的中文亂碼
SpringMVC提供了過濾器用來解決全站亂碼
只能解決post請求的亂碼
web.xml
<!-- 使用SpringMVC的過濾器來解決中文亂碼問題 針對於post提交 get提交無效 -->
<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>
get請求的亂碼處理
System.out.println(new String(username.getBytes("iso8859-1"),"utf-8"));
日期資料的處理
test2.jsp
<form action="${pageContext.request.contextPath}/cbrt/test02.action" method="get"> 年齡:<input type="text" name="age"> 姓名:<input type="text" name="username"> 日期:<input type="date" name="tday"> <input type="submit" value="提交"> </form>
FirstController.java
@InitBinder public void binding(ServletRequestDataBinder bind){ // 設定日期預設的解析格式 bind.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); } @RequestMapping(value="/test02.action") public void test02(String username,int age,Date tday){ // 2019-08-21 2019/08/21 System.out.println(username); System.out.println(age); System.out.println(tday); }
SpringMVC檔案上傳
檔案上傳的三個必要條件
表單必須是Post提交
表單必須是enctype="multipart/form-data"
檔案上傳項必須有name屬性
test2.jsp
<form action="${pageContext.request.contextPath}/cbrt/test02.action" method="post" enctype="multipart/form-data"> 年齡:<input type="text" name="age"> 姓名:<input type="text" name="username"> <input type="file" name="fx"> <input type="submit" value="提交"> </form>
springmvc-servlet.xml
在配置檔案中配置檔案上傳工具
<!-- 配置檔案上傳 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 上傳最大體積 --> <!-- <property name="maxUploadSize"></property> --> <!-- 上傳佔用最大記憶體大小 --> <!-- <property name="maxInMemorySize"></property> --> <!-- 上傳後存放臨時資料夾的位置 --> <!-- <property name="uploadTempDir"></property> --> </bean>
FirstController.java
實現檔案上傳
@RequestMapping(value="/test02.action") public void test02(String username,int age,MultipartFile fx) throws IOException{ // 向本地c盤存放客戶端上傳的檔案 getOriginalFilename:得到檔案的原始名稱 FileUtils.writeByteArrayToFile(new File("c://"+fx.getOriginalFilename()), fx.getBytes()); }
RESTFul風格的請求
普通的get請求
Url:localhost:XXXX/addUser.action?name=tom&age=18
restfull風格的請求
Url:localhost:XXXX/addUser/tom/18.action
FirstController.java
@Controller //將FirstController交由Spring進行管理 public class FirstController { @RequestMapping("/restful/{username}/{age}.action") public void restful(@PathVariable String username,@PathVariable int age){ System.out.println(username + "~" + age); } }
pringMVC中的重定向和轉發的實現
// 轉發 @RequestMapping("/test01.action") public String test01(){ return "forward:/index.jsp"; } // 轉發 @RequestMapping("/test02.action") public String test02(){ return "forward:/test01.action"; } // 重定向 @RequestMapping("/test03.action") public String test03(){ return "redirect:/index.jsp"; }
SpringMVC中session的使用
model中的域預設是request域
可以通過在類上加@SessionAttributes註解將他變為session域
@Controller //將FirstController交由Spring進行管理 @SessionAttributes("msg") public class FirstController { // 四大作用域 // request: 預設SpringMVC使用的就是request // session:可以在處理器的形參中直接獲取HttpSession物件 // 也可以先在處理器的形參中獲取HttpServletRequest,然後再間接的獲取session // servletContext:可以通過HttpServletRequest獲取session,在獲取servletContext // pageContext @RequestMapping("/test01.action") public String test01(Model model){ model.addAttribute("msg", "red apple"); return "first"; } }
異常處理
為當前Controller配置錯誤處理
當前Controller出錯時執行的方法
@ExceptionHandler
FirstController.java
@Controller public class FirstController { // 作為異常的攔截方法 @ExceptionHandler public void exceptionDemo(Exception e){ System.out.println(e.getMessage()); } }
註解方式配置全域性的錯誤處理
全域性出現異常時使用此方法處理
@ControllerAdvice
FirstController.java
@Controller @ControllerAdvice //為全域性配置異常攔截 public class FirstController { // 作為異常的攔截方法 @ExceptionHandler public void exceptionDemo(Exception e){ System.out.println(e.getMessage()); } }
實現返回一段資料 - AJAX
@RequestMapping("test07.action") @ResponseBody public Hero test07() throws IOException{ Hero hero = new Hero(); hero.setAge(16); hero.setName("張三丰"); hero.setJob("道士"); return hero; }