天天看點

SpringMVC響應資料和結果視圖 & 實作檔案上傳 & 異常處理 & 攔截器 ->(個人學習記錄筆記)

@

目錄

  • springmvc
    • 1. 響應資料和結果視圖
      • 1.1 傳回值分類
        • 1.1.1 傳回字元串
        • 1.1.2 傳回值是void
        • 1.1.3 傳回值是ModelAndView對象
      • 1.2 SpringMVC架構提供的轉發和重定向
        • 1.2.1 forward請求轉發
        • 1.2.2 redirect重定向
      • 1.3 ResponseBody響應json資料
    • 2. 檔案上傳
      • 2.1 檔案上傳的回顧
      • 2.2 SpringMVC傳統方式檔案上傳
      • 2.3 SpringMVC跨伺服器方式檔案上傳
    • 3. 異常處理器
      • 3.1 異常處理思路
      • 3.2 SpringMVC的異常處理
    • 4. 攔截器
      • 4.1 攔截器的概述
      • 4.2 自定義攔截器步驟
      • 4.3 HandlerInterceptor接口中的方法
      • 4.4 配置多個攔截器

  1. Controller

    方法傳回字元串可以指定邏輯視圖的名稱,根據視圖解析器為實體視圖的位址。
<a href="user/testString" >testString</a>
           
/**
 * 傳回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";
}
           

  1. 如果控制器的方法傳回值編寫成

    void

    ,執行程式報404的異常,預設查找JSP頁面沒有找到。
    1. 預設會跳轉到

      @RequestMapping(value="/testVoid") testVoid.jsp

      的頁面。
  2. 可以使用請求轉發或者重定向跳轉到指定的頁面
/**
* 是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("你好");
}
           
  • WEB-INF可以轉發進去,但是不能直接重定向進去

  1. ModelAndView

    對象是

    Spring

    提供的一個對象,可以用來調整具體的

    JSP

    視圖
  2. 具體的代碼如下
/**
* 傳回ModelAndView對象
* 可以傳入視圖的名稱(即跳轉的頁面),還可以傳入對象。
* @return
* @throws Exception
*/
@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響應資料和結果視圖 &amp; 實作檔案上傳 &amp; 異常處理 &amp; 攔截器 ->(個人學習記錄筆記)
SpringMVC響應資料和結果視圖 &amp; 實作檔案上傳 &amp; 異常處理 &amp; 攔截器 ->(個人學習記錄筆記)

  1. controller

    方法傳回

    String

    類型,想進行請求轉發也可以編寫成
/**
* 使用forward關鍵字進行請求轉發
* "forward:轉發的JSP路徑",不走視圖解析器了,是以需要編寫完整的路徑
* @return
* @throws Exception
*/
@RequestMapping("/testForward")
public String testForwardOrRedirect(){
    System.out.println("testForward方法執行了...");

    // 請求的轉發
    return "forward:/WEB-INF/pages/success.jsp";
}
           

  1. controller方法傳回String類型,想進行重定向也可以編寫成
/**
 * 使用關鍵字的方式進行重定向
 * @return
 */
@RequestMapping("/testRedirect")
public String testForwardOrRedirect(){
    System.out.println("testRedirect方法執行了...");
    
    // 重定向
    return "redirect:/index.jsp";
}
           

  1. DispatcherServlet

    會攔截到所有的資源,導緻一個問題就是靜态資源

    (img、css、js)

    也會被攔截到,進而不能被使用。解決問題就是需要配置靜态資源不進行攔截,在

    springmvc.xml

    配置檔案添加如下配置
    1. mvc:resources

      标簽配置不過濾
      1. location

        元素表示

        webapp

        目錄下的包下的所有檔案
      2. 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 -->
           
  1. 使用

    @RequestBody

    擷取請求體資料
  2. @RequestBody

    注解把

    json

    的字元串轉換成

    JavaBean

    的對象
// 頁面加載,綁定單擊事件
$(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);
            }
        });

    });
});
           
/**
 * 模拟異步請求響應
 */
@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;
}
           
SpringMVC響應資料和結果視圖 &amp; 實作檔案上傳 &amp; 異常處理 &amp; 攔截器 ->(個人學習記錄筆記)
  1. @ResponseBody

    JavaBean

    對象轉換成

    json

    字元串,直接響應
    1. 要求方法需要傳回

      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;
 }
           
SpringMVC響應資料和結果視圖 &amp; 實作檔案上傳 &amp; 異常處理 &amp; 攔截器 ->(個人學習記錄筆記)
  1. 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>
           

  1. 導入檔案上傳的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>
           
  1. 編寫檔案上傳的JSP頁面
<h3>檔案上傳</h3>

<form action="user/fileupload" method="post" enctype="multipart/form-data">
	選擇檔案:<input type="file" name="upload"/><br/>
	<input type="submit" value="上傳檔案"/>
</form>

           
  1. 編寫檔案上傳的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";
}
           

  1. SpringMVC

    架構提供了

    MultipartFile

    對象,該對象表示上傳的檔案,要求變量名稱必須和表單file标簽的

    name

    屬性名稱相同。
  2. 代碼如下
/**
* 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();
	String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
	// 把檔案的名稱唯一化
	filename = uuid+"_"+filename;
	// 上傳檔案
	upload.transferTo(new File(file,filename));
	return "success";
}
           
  1. 配置檔案解析器對象
  • 10*1024*1024

<!-- 配置檔案解析器對象,要求id名稱必須是multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="maxUploadSize" value="10485760"/>
</bean>
           

  1. 搭建圖檔伺服器
    1. 根據文檔配置伺服器,現在是2個伺服器
    2. 導入資料中項目,作為圖檔伺服器使用
  2. 實作

    SpringMVC

    跨伺服器方式檔案上傳
    1. 導入開發需要的jar包
    2. 編寫控制器
<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>
           
<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";
}
           

  1. Controller

    調用

    service

    service

    dao

    ,異常都是向上抛出的,最終有

    DispatcherServlet

    找異常處理器進行異常的處理。

  1. 自定義異常類
package xyz.slienceme.exception;
public class SysException extends Exception{
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;
	}
}
           
  1. 自定義異常處理器
package xyz.slienceme.exception;
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;
	}
}
           
  1. 配置異常處理器
<!-- 配置異常處理器 -->
<bean id="sysExceptionResolver" class="xyz.slienceme.exception.SysExceptionResolver"/>
           

  1. SpringMVC

    架構中的攔截器用于對處理器進行預處理和後處理的技術。
  2. 可以定義攔截器鍊,連接配接器鍊就是将攔截器按着一定的順序結成一條鍊,在通路被攔截的方法時,攔截器鍊中的攔截器會按着定義的順序執行。
  3. 攔截器和過濾器的功能比較類似,有差別
    1. 過濾器是Servlet規範的一部分,任何架構都可以使用過濾器技術。
    2. 攔截器是SpringMVC架構獨有的。
    3. 過濾器配置了/*,可以攔截任何資源。
    4. 攔截器隻會對控制器中的方法進行攔截。
  4. 攔截器也是AOP思想的一種實作方式
  5. 想要自定義攔截器,需要實作

    HandlerInterceptor

    接口。

  1. 建立類,實作

    HandlerInterceptor

    接口,重寫需要的方法
package xyz.slienceme.demo1;
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;
	}
}
           
  1. springmvc.xml

    中配置攔截器類
<!-- 配置攔截器 -->
<mvc:interceptors>
	<mvc:interceptor>
		<!-- 哪些方法進行攔截 -->
		<mvc:mapping path="/user/*"/>
		<!-- 哪些方法不進行攔截
		<mvc:exclude-mapping path=""/>
		-->
		<!-- 注冊攔截器對象 -->
		<bean class="xyz.slienceme.demo1.MyInterceptor1"/>
	</mvc:interceptor>
</mvc:interceptors>
           

  1. preHandle

    方法是

    controller

    方法

    執行前攔截

    的方法
    1. 可以使用request或者response跳轉到指定的頁面
    2. return true放行

      ,執行下一個攔截器,如果沒有攔截器,執行controller中的方法。
    3. return false不放行

      ,不會執行controller中的方法。
  2. postHandle

    controller

    執行後執行

    的方法,在JSP視圖執行前。
    1. 如果指定了跳轉的頁面,那麼controller方法跳轉的頁面将不會顯示。
  3. postHandle

    方法是在

    JSP執行後執行

    1. request或者response不能再跳轉頁面了

  1. 再編寫一個攔截器的類
  2. 配置2個攔截器
<!-- 配置攔截器 -->
<mvc:interceptors>
	<mvc:interceptor>
		<!-- 哪些方法進行攔截 -->
		<mvc:mapping path="/user/*"/>
		<!-- 哪些方法不進行攔截
		<mvc:exclude-mapping path=""/>
		-->
		<!-- 注冊攔截器對象 -->
		<bean class="xyz.slienceme.demo1.MyInterceptor1"/>
	</mvc:interceptor>
	<mvc:interceptor>
		<!-- 哪些方法進行攔截 -->
		<mvc:mapping path="/**"/>
		<!-- 注冊攔截器對象 -->
		<bean class="xyz.slienceme.demo1.MyInterceptor2"/>
	</mvc:interceptor>
</mvc:interceptors>
           

注:(之前的前端筆記傳送門)

1. HTML初學

2. CSS初學

3. JavaScript初學

4. JQuery初學

5. HTML複學

6. CSS複學

7. JavaScript基礎 複學

8. JavaScript進階 複學

9. BootStrap簡單了解