SpringMVC響應檢視丶檔案上傳丶異常處理丶攔截器
SpringMVC響應資料和結果檢視
返回值分類
-
返回字串
- Controller方法返回字串可以指定邏輯檢視的名稱,根據檢視解析器為物理檢視的地址。
- 引數可以寫一個Model來儲存域物件中的值
- 應用例子:
@Controller @RequestMapping("/user") public class UserController { /** * 請求引數的繫結 */ @RequestMapping(value="/update") public String initUpdate(Model model) { // 模擬從資料庫中查詢的資料 User user = new User(); user.setUsername("張三"); user.setPassword("123"); model.addAttribute("user", user); //此處返回一個邏輯檢視的字串 return "list"; } }
-
返回值是void
- 如果控制器的方法返回值編寫成void,執行程式報404的異常,預設查詢JSP頁面沒有找到。
- 預設會跳轉到@RequestMapping(value="/update") 即update的頁面。
- 可以使用請求轉發或者重定向或者直接寫回內容跳轉到指定的頁面
- 例子:
@RequestMapping(value="/login") public void login(HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("請求轉發或者重定向"); // 請求轉發 // request.getRequestDispatcher("/WEB-INF/pages/login.jsp").forward(request, response); // 重定向 // response.sendRedirect(request.getContextPath()+"/login1.jsp"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); // 直接響應資料 response.getWriter().print("你好"); return; }
- 如果控制器的方法返回值編寫成void,執行程式報404的異常,預設查詢JSP頁面沒有找到。
-
返回值是ModelAndView物件
- ModelAndView物件是Spring提供的一個物件,可以用來調整具體的JSP檢視
- 例子:
/** * 返回ModelAndView物件 * 可以傳入檢視的名稱(即跳轉的頁面),還可以傳入物件。 * @return * @throws Exception */ @RequestMapping(value="/findAll") public ModelAndView findAll() throws Exception { ModelAndView mv = new ModelAndView(); // 設定跳轉到list.jsp的頁面 mv.setViewName("list"); // 模擬從資料庫中查詢所有的使用者資訊 List<User> users = new ArrayList<>(); User user1 = new User(); user1.setUsername("張三"); user1.setPassword("123"); User user2 = new User(); user2.setUsername("趙四"); user2.setPassword("456"); users.add(user1); users.add(user2); // 新增物件,相當與向域物件中新增鍵值對 mv.addObject("users", users); return mv; }
SpringMVC中的轉發以及重定向
-
Forward轉發
- controller方法返回String型別,想進行請求轉發也可以編寫成
/** * 使用forward關鍵字進行請求轉發 * "forward:轉發的JSP路徑",不走檢視解析器了,所以需要編寫完整的路徑 * 也可以轉發到某個方法之上 * @return * @throws Exception */ @RequestMapping("/delete") public String delete() throws Exception { System.out.println("delete方法執行了..."); // return "forward:/WEB-INF/pages/success.jsp"; return "forward:/user/findAll"; }
-
Redirect重定向
- controller方法返回String型別,想進行重定向也可以編寫成
/** * 重定向 * @return * @throws Exception */ @RequestMapping("/count") public String count() throws Exception { System.out.println("count方法執行了..."); return "redirect:/add.jsp"; // return "redirect:/user/findAll"; // ps:不用再專案名稱(虛擬目錄) // 重定向(相當於瀏覽器直接訪問)不能訪問WEB-INF下的資源 }
ResponseBody響應json資料
-
DispatcherServlet會攔截到所有的資源,導致一個問題就是靜態資源(img、css、js)也會被攔截到,從而
不能被使用。解決問題就是需要配置靜態資源不進行攔截,在springmvc.xml配置檔案新增如下配置- mvc:resources標籤配置不過濾
- location元素表示webapp目錄下的包下的所有檔案
- mapping元素表示以/static開頭的所有請求路徑,如/static/a 或者/static/a/b
<!-- 設定靜態資源不過濾 --> <mvc:resources location="/css/" mapping="/css/**"/> <!-- 樣式 --> <mvc:resources location="/images/" mapping="/images/**"/> <!-- 圖片 --> <mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
-
使用@RequestBody獲取請求體資料(ajax的非同步json資料)
@RequestMapping("/testJson") public void testJson(@RequestBody String body) { System.out.println(body); }
-
使用@RequestBody註解把json的字串轉換成JavaBean的物件
/** * 獲取請求體的資料 * @param body */ @RequestMapping("/testJson") //可以自動把json字串轉換為javabean物件(需要匯入jar包或者依賴) public void testJson(@RequestBody User user) { System.out.println(user); }
-
使用@ResponseBody註解把JavaBean物件轉換成json字串,直接響應
@RequestMapping("/testJson") public @ResponseBody User testJson(@RequestBody User user) { System.out.println(user); user.setAddressName("上海"); return user; }
-
json字串和JavaBean物件互相轉換的過程中,需要使用jackson的jar包
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency>
SpringMVC實現檔案上傳
普通檔案上傳
-
匯入jar包或者依賴
<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.4</version> </dependency>
-
編寫檔案上傳的jsp檔案
- 三個關鍵點:
- 上傳方式:post
- form的enctype為:multipart/form-data
- 檔案的type是file
檔案上傳 <form action="user/fileupload" method="post" enctype="multipart/form-data"> 選擇檔案:<input type="file" name="upload"/><br/> <input type="submit" value="上傳檔案"/> </form>
- 三個關鍵點:
-
編寫檔案上傳的Controller控制器
/** * 檔案上傳 * @throws Exception */ @RequestMapping(value="/fileupload") public String fileupload(HttpServletRequest request) throws Exception { // 先獲取到要上傳的檔案目錄 String path = request.getSession().getServletContext().getRealPath("/uploads"); // 建立File物件,一會向該路徑下上傳檔案 File file = new File(path); // 判斷路徑是否存在,如果不存在,建立該路徑 if(!file.exists()) { file.mkdirs(); } // 建立磁碟檔案項工廠 DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload fileUpload = new ServletFileUpload(factory); // 解析request物件 List<FileItem> list = fileUpload.parseRequest(request); // 遍歷 for (FileItem fileItem : list) { // 判斷檔案項是普通欄位,還是上傳的檔案 if(fileItem.isFormField()) { }else { // 上傳檔案項 // 獲取到上傳檔案的名稱 String filename = fileItem.getName(); // 上傳檔案 fileItem.write(new File(file, filename)); // 刪除臨時檔案 fileItem.delete(); } } return "success"; }
-
SpringMVC的檔案上傳
-
SpringMVC框架提供了MultipartFile物件,該物件表示上傳的檔案,要求變數名稱必須和表單file標籤的name屬性名稱相同。
-
程式碼:
/** * SpringMVC方式的檔案上傳 * * @param request * @return * @throws Exception */ @RequestMapping(value="/fileupload2") public String fileupload2(HttpServletRequest request,MultipartFile upload) throws Exception { System.out.println("SpringMVC方式的檔案上傳..."); // 先獲取到要上傳的檔案目錄 String path = request.getSession().getServletContext().getRealPath("/uploads"); // 建立File物件,一會向該路徑下上傳檔案 File file = new File(path); // 判斷路徑是否存在,如果不存在,建立該路徑 if(!file.exists()) { file.mkdirs(); } // 獲取到上傳檔案的名稱 String filename = upload.getOriginalFilename(); //獲取uuid String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase(); // 把檔案的名稱唯一化 filename = uuid+"_"+filename; // 上傳檔案 upload.transferTo(new File(file,filename)); return "success"; }
-
配置檔案解析器物件
<!-- 配置檔案解析器物件,要求id名稱必須是multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--配置上傳檔案的最大大小--> <property name="maxUploadSize" value="10485760"/> </bean>
SpringMVC跨伺服器方式檔案上傳
-
搭建一個圖片伺服器(模擬)
- 複製並開啟一個tomcat,改變一下埠號如:8088
- 在webapp下的root檔案下新建一個uploads資料夾
-
實現springmvc的跨伺服器檔案上傳
- 匯入需要的jar(jersey)
<dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> <version>1.18.1</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.18.1</version> </dependency>
-
編寫檔案上傳的jsp
<h3>跨伺服器的檔案上傳</h3> <form action="user/fileupload3" method="post" enctype="multipart/form-data"> 選擇檔案:<input type="file" name="upload"/><br/> <input type="submit" value="上傳檔案"/> </form>
-
編寫控制器
/** * SpringMVC跨伺服器方式的檔案上傳 * * @param request * @return * @throws Exception */ @RequestMapping(value="/fileupload3") public String fileupload3(MultipartFile upload) throws Exception { System.out.println("SpringMVC跨伺服器方式的檔案上傳..."); // 定義圖片伺服器的請求路徑 String path = "http://localhost:9090/day02_springmvc5_02image/uploads/"; // 獲取到上傳檔案的名稱 String filename = upload.getOriginalFilename(); String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase(); // 把檔案的名稱唯一化 filename = uuid+"_"+filename; // 向圖片伺服器上傳檔案 // 建立客戶端物件 Client client = Client.create(); // 連線圖片伺服器 WebResource webResource = client.resource(path+filename); // 上傳檔案 webResource.put(upload.getBytes()); return "success"; }
SpringMVC的異常處理
-
異常處理的思路:
- Controller呼叫service,service呼叫dao,異常都是向上丟擲的,最終有DispatcherServlet找異常處理器進
行異常的處理。
- Controller呼叫service,service呼叫dao,異常都是向上丟擲的,最終有DispatcherServlet找異常處理器進
-
SpringMVC的異常處理
-
自定義異常類
public class SysException extends Exception{ //定義一個唯一的serialVersionUID private static final long serialVersionUID = 4055945147128016300L; // 異常提示資訊 private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public SysException(String message) { this.message = message; } }
-
自定義異常處理器
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; /** * 異常處理器 * @author rt */ public class SysExceptionResolver implements HandlerExceptionResolver{ /** * 跳轉到具體的錯誤頁面的方法 */ public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ex.printStackTrace(); SysException e = null; // 獲取到異常物件 if(ex instanceof SysException) { e = (SysException) ex; }else { e = new SysException("請聯絡管理員"); } ModelAndView mv = new ModelAndView(); // 存入錯誤的提示資訊 mv.addObject("message", e.getMessage()); // 跳轉的Jsp頁面 mv.setViewName("error"); return mv; } }
-
配置異常處理器
<!-- 配置異常處理器 --> <bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>
-
SpringMVC框架中的攔截器
攔截器的概述
-
SpringMVC框架中的攔截器用於對處理器進行預處理和後處理的技術。
-
可以定義攔截器鏈,聯結器鏈就是將攔截器按著一定的順序結成一條鏈,在訪問被攔截的方法時,攔截器鏈
中的攔截器會按著定義的順序執行。 - 攔截器和過濾器的功能比較類似,有區別
- 過濾器是Servlet規範的一部分,任何框架都可以使用過濾器技術。
- 攔截器是SpringMVC框架獨有的。
- 過濾器配置了/*,可以攔截任何資源。
- 攔截器只會對控制器中的方法進行攔截。
- 攔截器也是AOP思想的一種實現方式
- 想要自定義攔截器,需要實現HandlerInterceptor介面。
自定義攔截器步驟
- 建立類,實現HandlerInterceptor介面,重寫需要的方法
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* 自定義攔截器1
* @author rt
*/
public class MyInterceptor1 implements HandlerInterceptor{
/**
* controller方法執行前,進行攔截的方法
* return true放行
* return false攔截
* 可以使用轉發或者重定向直接跳轉到指定的頁面。
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler)
throws Exception {
System.out.println("攔截器執行了...");
return true;
}
}
- 在springmvc.xml中配置攔截器類
<!-- 配置攔截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 哪些方法進行攔截 -->
<mvc:mapping path="/user/*"/>
<!-- 哪些方法不進行攔截
<mvc:exclude-mapping path=""/>
-->
<!-- 註冊攔截器物件 -->
<bean class="cn.xxx.demo1.MyInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
HandlerInterceptor介面中的方法
- preHandle方法是controller方法執行前攔截的方法
- 可以使用request或者response跳轉到指定的頁面
- return true放行,執行下一個攔截器,如果沒有攔截器,執行controller中的方法。
- return false不放行,不會執行controller中的方法。
- postHandle是controller方法執行後執行的方法,在JSP檢視執行前。
- 可以使用request或者response跳轉到指定的頁面
- 如果指定了跳轉的頁面,那麼controller方法跳轉的頁面將不會顯示。
- postHandle方法是在JSP執行後執行
- request或者response不能再跳轉頁面了
配置多個攔截器
<!-- 配置攔截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 哪些方法進行攔截 -->
<mvc:mapping path="/user/*"/>
<!-- 哪些方法不進行攔截
<mvc:exclude-mapping path=""/>
<!-- 註冊攔截器物件 -->
<bean class="cn.itcast.demo1.MyInterceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<!-- 哪些方法進行攔截 -->
<mvc:mapping path="/**"/>
<!-- 註冊攔截器物件 -->
<bean class="cn.itcast.demo1.MyInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
攔截器的指定流程
前置攔截器執行了!!
controller執行了!!!
後置方法執行了!!!
跳轉頁面執行
最終的方法執行了