SpringMVC學習
響應數據和結果視圖
返回值分類
返回字符串
-
Controller方法返回字符串可以指定邏輯視圖的名稱,根據視圖解析器爲物理視圖的地址。
@RequestMapping(value="/hello") public String sayHello() { System.out.println("Hello SpringMVC!!"); // 跳轉到XX頁面 return "success"; }
-
具體的應用場景
@Controller @RequestMapping("/user") public class UserController { /** * 返回String * @param model * @return */ @RequestMapping("/testString") public String testString(Model model){ System.out.println("testString方法執行了..."); // 模擬從數據庫中查詢出User對象 User user = new User(); user.setUsername("美美"); user.setPassword("123"); user.setAge(30); // model對象 model.addAttribute("user",user); return "success"; } }
返回值是void
-
如果控制器的方法返回值編寫成void,執行程序報404的異常,默認查找JSP頁面沒有找到。
- 默認會跳轉到@RequestMapping(value="/initUpdate") initUpdate的頁面。
-
可以使用請求轉發或者重定向跳轉到指定的頁面
/** * 是void * 請求轉發一次請求,不用編寫項目的名稱 */ @RequestMapping("/testVoid") public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("testVoid方法執行了..."); // 編寫請求轉發的程序 // request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response); // 重定向 // response.sendRedirect(request.getContextPath()+"/index.jsp"); // 設置中文亂碼 response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); // 直接會進行響應 response.getWriter().print("你好"); return; }
返回值是ModelAndView對象
-
ModelAndView對象是Spring提供的一個對象,可以用來調整具體的JSP視圖
/** * 返回ModelAndView * @return */ @RequestMapping("/testModelAndView") public ModelAndView testModelAndView(){ // 創建ModelAndView對象 ModelAndView mv = new ModelAndView(); System.out.println("testModelAndView方法執行了..."); // 模擬從數據庫中查詢出User對象 User user = new User(); user.setUsername("小鳳"); user.setPassword("456"); user.setAge(30); // 把user對象存儲到mv對象中,也會把user對象存入到request對象 mv.addObject("user",user); // 跳轉到哪個頁面 mv.setViewName("success"); return mv; }
SpringMVC框架提供的轉發和重定向
-
forward請求轉發
- controller方法返回String類型,想進行請求轉發也可以編寫成
/** * 使用關鍵字的方式進行轉發或者重定向 * @return */ @RequestMapping("/testForwardOrRedirect") public String testForwardOrRedirect(){ System.out.println("testForwardOrRedirect方法執行了..."); 請求的轉發 return "forward:/WEB-INF/pages/success.jsp"; }
-
redirect重定向
-
controller方法返回String類型,想進行重定向也可以編寫成
/** * 使用關鍵字的方式進行轉發或者重定向 * @return */ @RequestMapping("/testForwardOrRedirect") public String testForwardOrRedirect(){ System.out.println("testForwardOrRedirect方法執行了..."); // 重定向 return "redirect:/index.jsp"; }
-
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/**"/>
-
-
使用@RequestBody獲取請求體數據
<script> // 頁面加載,綁定單擊事件 $(function(){ $("#btn").click(function(){ // alert("hello btn"); // 發送ajax請求 $.ajax({ // 編寫json格式,設置屬性和值 url:"user/testAjax", contentType:"application/json;charset=UTF-8", data:'{"username":"hehe","password":"123","age":30}', dataType:"json", type:"post", success:function(data){ // data服務器端響應的json的數據,進行解析 alert(data); alert(data.username); alert(data.password); alert(data.age); } }); }); }); </script>
-
使用@ResponseBody註解把JavaBean對象轉換成json字符串,直接響應
-
要求方法需要返回JavaBean的對象
/** * 模擬異步請求響應 */ @RequestMapping("/testAjax") public @ResponseBody User testAjax(@RequestBody User user){ System.out.println("testAjax方法執行了..."); // 客戶端發送ajax的請求,傳的是json字符串,後端把json字符串封裝到user對象中 System.out.println(user); // 做響應,模擬查詢數據庫 user.setUsername("haha"); user.setAge(40); // 做響應 return user; }
-
json字符串和JavaBean對象互相轉換的過程中,需要使用jackson的jar包
```xml
<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實現文件上傳
SpringMVC傳統方式文件上傳
-
SpringMVC框架提供了MultipartFile對象,該對象表示上傳的文件,要求變量名稱必須和表單file標籤的 name屬性名稱相同。
-
代碼:
/** * SpringMVC文件上傳 * @return */ @RequestMapping("/fileupload2") public String fileuoload2(HttpServletRequest request, MultipartFile upload) throws Exception { System.out.println("springmvc文件上傳..."); // 使用fileupload組件完成文件上傳 // 上傳的位置 String path = request.getSession().getServletContext().getRealPath("/uploads/"); // 判斷,該路徑是否存在 File file = new File(path); if(!file.exists()){ // 創建該文件夾 file.mkdirs(); } // 說明上傳文件項 // 獲取上傳文件的名稱 String filename = upload.getOriginalFilename(); // 把文件的名稱設置唯一值,uuid String uuid = UUID.randomUUID().toString().replace("-", ""); filename = uuid+"_"+filename; // 完成文件上傳 upload.transferTo(new File(path,filename)); return "success"; }
-
配置文件解析器對象
<!--配置文件解析器對象,要求id名稱必須是multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="10485760" /> </bean>
SpringMVC跨服務器方式文件上傳
-
搭建圖片服務器
- 根據文檔配置tomcat9的服務器,現在是2個服務器
- 導入image項目,作爲圖片服務器使用
-
實現SpringMVC跨服務器方式文件上傳
- 導入開發需要的jar包
<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>
-
編寫控制器
/** * 跨服務器文件上傳 * @return */ @RequestMapping("/fileupload3") public String fileuoload3(MultipartFile upload) throws Exception { System.out.println("跨服務器文件上傳..."); // 定義上傳文件服務器路徑 String path = "http://localhost:9090/uploads/"; // 說明上傳文件項 // 獲取上傳文件的名稱 String filename = upload.getOriginalFilename(); // 把文件的名稱設置唯一值,uuid String uuid = UUID.randomUUID().toString().replace("-", ""); 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找異常處理器進 行異常的處理。
SpringMVC的異常處理
-
自定義異常類
/** * 自定義異常類 */ public class SysException extends Exception{ // 存儲提示信息的 private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public SysException(String message) { this.message = message; } }
-
自定義異常處理器
/** * 異常處理器 */ public class SysExceptionResolver implements HandlerExceptionResolver{ /** * 處理異常業務邏輯 * @param request * @param response * @param handler * @param ex * @return */ public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 獲取到異常對象 SysException e = null; if(ex instanceof SysException){ e = (SysException)ex; }else{ e = new SysException("系統正在維護...."); } // 創建ModelAndView對象 ModelAndView mv = new ModelAndView(); mv.addObject("errorMsg",e.getMessage()); mv.setViewName("error"); return mv; } }
-
配置異常處理器
<!--配置異常處理器--> <bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>
SpringMVC框架中的攔截器
攔截器的概述
- SpringMVC框架中的攔截器用於對處理器進行預處理和後處理的技術。
- 可以定義攔截器鏈,連接器鏈就是將攔截器按着一定的順序結成一條鏈,在訪問被攔截的方法時,攔截器鏈 中的攔截器會按着定義的順序執行。
- 攔截器和過濾器的功能比較類似,有區別
- 過濾器是Servlet規範的一部分,任何框架都可以使用過濾器技術。
- 攔截器是SpringMVC框架獨有的。
- 過濾器配置了/*,可以攔截任何資源。
- 攔截器只會對控制器中的方法進行攔截。
- 攔截器也是AOP思想的一種實現方式
- 想要自定義攔截器,需要實現HandlerInterceptor接口。
自定義攔截器步驟
-
創建類,實現HandlerInterceptor接口,重寫需要的方法
/** * 自定義攔截器 */ public class MyInterceptor1 implements HandlerInterceptor{ /** * 預處理,controller方法執行前 * return true 放行,執行下一個攔截器,如果沒有,執行controller中的方法 * return false不放行 * @param request * @param response * @param handler * @return * @throws Exception */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor1執行了...前1111"); // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); return true; } /** * 後處理方法,controller方法執行後,success.jsp執行之前 * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor1執行了...後1111"); // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /** * success.jsp頁面執行後,該方法會執行 * @param request * @param response * @param handler * @param ex * @throws Exception */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor1執行了...最後1111"); } }
-
在springmvc.xml中配置攔截器類
<!--配置攔截器-->
<mvc:interceptors>
<!--配置攔截器-->
<mvc:interceptor>
<!--要攔截的具體的方法-->
<mvc:mapping path="/user/*"/>
<!--不要攔截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置攔截器對象-->
<bean class="cn.itcast.controller.cn.itcast.interceptor.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不能再跳轉頁面了
配置多個攔截器
-
再編寫一個攔截器的類
** * 自定義攔截器 */ public class MyInterceptor2 implements HandlerInterceptor{ /** * 預處理,controller方法執行前 * return true 放行,執行下一個攔截器,如果沒有,執行controller中的方法 * return false不放行 * @param request * @param response * @param handler * @return * @throws Exception */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor1執行了...前2222"); // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); return true; } /** * 後處理方法,controller方法執行後,success.jsp執行之前 * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor1執行了...後2222"); // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /** * success.jsp頁面執行後,該方法會執行 * @param request * @param response * @param handler * @param ex * @throws Exception */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor1執行了...最後2222"); } }
-
配置2個攔截器
<!--配置攔截器--> <mvc:interceptors> <!--配置攔截器--> <mvc:interceptor> <!--要攔截的具體的方法--> <mvc:mapping path="/user/*"/> <!--不要攔截的方法 <mvc:exclude-mapping path=""/> --> <!--配置攔截器對象--> <bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor1" /> </mvc:interceptor> <!--配置第二個攔截器--> <mvc:interceptor> <!--要攔截的具體的方法--> <mvc:mapping path="/**"/> <!--不要攔截的方法 <mvc:exclude-mapping path=""/> --> <!--配置攔截器對象--> <bean class="cn.itcast.controller.cn.itcast.interceptor.MyInterceptor2" /> </mvc:interceptor> </mvc:interceptors>