SpringMVC詳解五、@ResponseBody、@RequestBody、HttpEntity、ResponseEntity、文件上傳、HandlerInterceptor攔截器及異常處理


1MultipartFile :文件上傳

2、使用@ResponseBody返回的數據轉成json

        @JsonFormat修改時間在json中的格式

3、使用@RequestBody接收請求體數據

4、使用HttpEntity參數獲取請求頭請求體

5、使用ResponseEntity返回值操作響應頭和響應體:下載文件

6HandlerInterceptor攔截器

7、異常處理

1、文件上傳

文件上傳在SpringMVC中如何實現:

1、準備一個文件上傳的表單

2、導入文件上傳需要的jar

commons-fileupload-1.2.1.jar

commons-io-1.4.jar

3、配置文件上傳解析器: CommonsMultipartResolver

4、配置Controller控制器的代碼

1.1、準備一個文件上傳的表單


<body>
		<form action="${ pageContext.request.contextPath }/upload" 
			method="post" enctype="multipart/form-data">
			用戶名:<input type="text" name="username"/><br/>
			頭像:<input type="file" name="photo"/><br/>
			<input type="submit" />
		</form>
	</body>

1.2、導入文件上傳需要的jar

commons-fileupload-1.2.1.jar

commons-io-1.4.jar

commons-logging-1.1.3.jar

log4j-1.2.17.jar

spring-aop-4.0.0.RELEASE.jar

spring-beans-4.0.0.RELEASE.jar

spring-context-4.0.0.RELEASE.jar

spring-core-4.0.0.RELEASE.jar

spring-expression-4.0.0.RELEASE.jar

spring-web-4.0.0.RELEASE.jar

spring-webmvc-4.0.0.RELEASE.jar

1.3、配置文件上傳解析器

<!-- 配置在SpringMVC中解決文件上傳的協議的解析器
			id 必須是multipartResolver
	 -->
	<bean id="multipartResolver" 
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 配置字符集爲UTF-8 -->
		<property name="defaultEncoding" value="UTF-8" />
	</bean>


1.4、編寫文件上傳的Controller控制器中的代碼:

單個文件上傳:

@RequestMapping("/upload")
	public String upload(String username, MultipartFile photo) {
		System.out.println("名字" + username);
		try {
			if (!photo.isEmpty() && photo != null) {
				// 第二個\是轉義第一個\
				// photo.transferTo(new File("e:\\" +
				// photo.getOriginalFilename()));
				// 正常的是訪問磁盤路徑
				photo.transferTo(new File("e://" + photo.getOriginalFilename()));
			}
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "/index.jsp";
	}

多個文件上傳:

@RequestMapping(value = "/upload")
	public String upload(String username,
			@RequestParam(value = "photo") MultipartFile[] photo) {
		System.out.println("用戶名:" + username);
		for (MultipartFile multipartFile : photo) {
			// 說明有上傳的內容
			// isEmpty判斷是否爲空
			if (multipartFile != null && !multipartFile.isEmpty()) {
				try {
					// transferTo 將文件寫入到硬盤位置
					// getOriginalFilenameaqb
					multipartFile.transferTo(new File("e:\\"
							+ multipartFile.getOriginalFilename()));
				} catch (IllegalStateException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return "forward:/index.jsp";
	}

springmc的文件上傳就兩點:

參數:MultipartFile photo

方法:photo.transferTo(new File("e:\\" + photo.getOriginalFilename()));

2、使用@ResponseBody將返回的數據轉成json***重點***

2.1、使用的步驟如下:

1、導入json相關的包到web工程中

jackson-annotations-2.1.5.jar

jackson-core-2.1.5.jar

jackson-databind-2.1.5.jar

2、編寫一個請求的方式接收請求,並返回數據對象

3、在方法上添加註解@ResponseBody自動將返回值json

 

2.2Controller中的代碼:

@ResponseBody
	@RequestMapping(value = "/queryPersonById")
	public Person queryPersonById() {
		return new Person(19, "name10", new Date(), "[email protected]",
				new BigDecimal(100));
	}

	@ResponseBody
	@RequestMapping(value = "/personList")
	public List<Person> personList() {
		List<Person> list = new ArrayList<Person>();
		for (int i = 0; i < 10; i++) {
			list.add(new Person(i, "name" + i, new Date(), "[email protected]",
					new BigDecimal(100)));
		}
		return list;
	}

從上面可以看出:控制器也可以返回對象類型

2.3、打開瀏覽器測試如下:




2.4、使用@JsonFormat修改時間在json中的格式

1)、可以直接用在屬性上

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")

private Date birthDate;

 

2)、也可以直接用在getter()方法上

@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")

public Date getBirthDate() {

return birthDate;

}

 

@JsonFormat表示設置json轉換格式。

pattern="yyyy-MM-dd HH:mm:ss"表示日期類型返回以 yyyy-MM-dd  HH:mm:ss 格式yyyy-MM-dd表示年月日,HH:mm:ss表示時分秒

timezone = "GMT+8"表示時間爲格林時間+8小時

3、使用@RequestBody接收請求體數據

HTTP協議中,我們知道,請求體只存在於POST請求中才有。所以我們需要有一個表單。而且請求必須是post請求。

 

3.1、準備一個post請求的表單

 post請求,默認的請求參數都會以name=value&name=value的形式進行拼接,然後發送給服務器。


	<form action="${pageContext.request.contextPath }/requestBody" method="post">
			用戶名:<input type="text" name="username" /><br/>
			密碼:<input type="password" name="password" /><br/>
			<input type="submit" />
		</form>

3.2、在Controller中添加一個方法接收請求體

/**
	 * GET請求
	 * 	1、請求行
	 * 	2、請求頭
	 * POST請求
	 *  1、請求行
	 *  2、請求頭
	 *  	空行
	 *  3、請求體(請求的參數)
	 */
	// @RequestBody 它可以接收請求體的數據---請求體,只存在於post請求
	@RequestMapping(value = "/requestBody")

	public String requestBody(@RequestBody String body) {
		System.out.println("請求體的全部內容:" + body);
		return "forward:/index.jsp";
	}

4、使用HttpEntity參數獲取請求頭和請求體

頁面代碼:

<!-- post請求,默認的請求參數都會以name=value&name=value的形式進行拼接,然後發送給服務器。 -->
		<form action="${pageContext.request.contextPath }/httpEntity" method="post">
			用戶名:<input type="text" name="username" /><br/>
			密碼:<input type="password" name="password" /><br/>
			<input type="submit" />
		</form>

Controller代碼:

@RequestMapping(value = "/httpEntity")
	public String httpEntity(HttpEntity<String> httpEntity) {
		System.out.println("請求頭:" + httpEntity.getHeaders());
		System.out.println("請求體:" + httpEntity.getBody());
		return "forward:/index.jsp";
	}

5、使用ResponseEntity返回值操作響應頭和響應體:下載文件

@RequestMapping(value = "/download")
	public ResponseEntity<byte[]> download(HttpSession session) {
		try {
			ServletContext ctx = session.getServletContext();
			// 斜槓(斜線)表示到http://ip:port/工程名/	映射到代碼的WebContent目錄
			InputStream is = ctx.getResourceAsStream("/imgs/e.jpg");
			byte[] buffer;
			buffer = new byte[is.available()];
			//讀文件數據
			is.read(buffer);
			is.close();
			//獲取需要下載的文件的數據類型
			String mimeType = ctx.getMimeType("/imgs/e.jpg");
			
			// 響應頭
			HttpHeaders httpHeaders = new HttpHeaders();
			// 添加響應頭,告訴客戶端我回去的數據類型是什麼
			httpHeaders.add("Content-Type", mimeType);
			httpHeaders.add("Content-Disposition", "attachment; filename=e.jpg");
			// 第一個參數是你要返回的數據--我們要實現文件下載,就需要把下載的文件字節內容都放body中
			// 第二個參數是 響應頭
			// 第三個參數是你要返回的響應狀態碼和響應 狀態描述 符
			ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(
					buffer, httpHeaders, HttpStatus.OK);

			return responseEntity;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

6HandlerInterceptor攔截器

6.1HandlerInterceptor攔截器的介紹

攔截器,可以攔截Controller控制方法

 

6.2、單個HandlerInterceptor攔截器的示例

1、編寫一個類去實現HandlerInterceptor接口

2、到Spring的容器配置文件中去配置攔截器,讓SpringMVC知道都攔截哪些目標方法

 

 

攔截器類實現代碼:

public class FirstHandlerInterceptor implements HandlerInterceptor {
	/**
	 * 在攔截到目標方法前調用
	 */
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println("FirstHandlerInterceptor -- >>> preHandle" );
		//return false不放行
		//return true放行
		return true;
	}
	/**
	 * 在目標方法執行之後執行。
	 */
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("FirstHandlerInterceptor -- >>> postHandle" );
	}

	/**
	 * 在目標方法執行完。跳轉頁面渲染完之後
	 */
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("FirstHandlerInterceptor -- >>> afterCompletion" );
	}

}

配置攔截的地址:

	<!-- 配置多個攔截器標籤mvc:interceptors -->
	<mvc:interceptors>
		<!-- 配置一個攔截器標籤mvc:interceptor -->
		<mvc:interceptor>
			<!-- 攔截的地址 -->
			<mvc:mapping path="/hello"/>
			<!-- 攔截器具體實現類 -->
			<bean class="com.tcent.controller.FirstHandlerInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>	

FirstHandlerInterceptor類中去攔截hello方法

正常情況下,攔截器的執行順序:

 

FirstHandlerInterceptor -- >>> preHandle

目標方法執行…………

FirstHandlerInterceptor -- >>> postHandle

頁面渲染的代碼

FirstHandlerInterceptor -- >>> afterCompletion

6.3、單個攔截器異常時的執行順序

一:目標方法前返回false的情況:

 

1、目標方法前執行 返回false

2、這是目標方法不執行

3、目標方法之後不執行

4、這是渲染頁面不執行

5、頁面渲染完成!不執行

 

 

二:目標方法前返回true的情況,目標方法異常

 

1、目標方法前執行 返回true

2、這是目標方法異常

3、目標方法之後不執行

4、這是渲染頁面渲染異常頁面

5、頁面渲染完成!執行

 

 

三:目標方法前返回true的情況,目標方法後異常

 

1、目標方法前執行 返回true

2、這是目標方法執行

3、目標方法之後異常

4、這是渲染頁面渲染異常頁面

5、頁面渲染完成!執行

 

 

四:目標方法前返回true的情況,渲染頁面異常

 

1、目標方法前執行 返回true

2、這是目標方法執行

3、目標方法之後執行

4、這是渲染頁面異常

5、頁面渲染完成!執行

7、異常處理

7.1、使用@ExceptionHandler註解處理異常

//@ExceptionHandler可以攔截到本Controller中的異常
	@ExceptionHandler
	public ModelAndView exceptionHandler(Exception e) {
		System.out.println("exceptionHandler --- Exception");
		ModelAndView modelAndView = new ModelAndView("forward:/error.jsp");
		modelAndView.addObject("exception", e);
		return modelAndView;
	}
	
	//@ExceptionHandler可以攔截到本Controller中的異常
	@ExceptionHandler
	public ModelAndView exceptionHandler(RuntimeException e) {
		System.out.println("exceptionHandler --- RuntimeException");
		ModelAndView modelAndView = new ModelAndView("forward:/error.jsp");
		modelAndView.addObject("exception", e);
		return modelAndView;
	}
	
	//@ExceptionHandler可以攔截到本Controller中的異常
	@ExceptionHandler
	public ModelAndView exceptionHandler(ArithmeticException e) {
		System.out.println("exceptionHandler --- ArithmeticException");
		ModelAndView modelAndView = new ModelAndView("forward:/error.jsp");
		modelAndView.addObject("exception", e);
		return modelAndView;
	}

在同一個Controller中可以有多個@ExceptionHandler標註的異常處理方法。

SpringMVC會優先選擇異常信息精確的方法執行異常處理操作。

區別:

@ExceptionHandler可以攔截到Controller中的異常註解在方法上

@ControllerAdvice它可以處理所有Controller中產生的異常註解在類上

7.2、使用@ControllerAdvice註解處理異常

/**
 * @ControllerAdvice它可以處理所有Controller中產生的異常
 *
 */
@ControllerAdvice
public class ExceptionEHander2 {
	
	@ExceptionHandler
	public ModelAndView exceptionHandler(Exception e) {
		System.out.println("@ControllerAdvice --- Exception");
		ModelAndView modelAndView = new ModelAndView("forward:/error.jsp");
		modelAndView.addObject("exception", e);
		return modelAndView;
	}
	
	@ExceptionHandler
	public ModelAndView exceptionHandler(RuntimeException e) {
		System.out.println("@ControllerAdvice --- RuntimeException");
		ModelAndView modelAndView = new ModelAndView("forward:/error.jsp");
		modelAndView.addObject("exception", e);
		return modelAndView;
	}
	
	@ExceptionHandler
	public ModelAndView exceptionHandler(ArithmeticException e) {
		System.out.println("@ControllerAdvice --- ArithmeticException");
		ModelAndView modelAndView = new ModelAndView("forward:/error.jsp");
		modelAndView.addObject("exception", e);
		return modelAndView;
	}

}

7.3、異常處理優先順序

在局部異常處理和全局異常處理同時存在的時候,優先順序是:

1、局部優先---->>>>2、精確優化

7.4、使用SimpleMappingExceptionResolver類、簡單映射異常跳轉

說明:配置SimpleMappingExceptionResolver文件可以取代上面兩種註解方式

 

<!-- 配置SimpleMappingExceptionResolver簡單異常映射解析器 -->
	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<!-- 異常映射屬性 -->
		<property name="exceptionMappings">
			<props>
				<!-- 
					key寫上異常全類名
					在prop標籤中填寫指定的跳轉地址
				 -->
				<prop key="java.lang.Exception">forward:/error.jsp</prop>
				<prop key="java.lang.RuntimeException">forward:/error.jsp</prop>
				<prop key="java.lang.ArithmeticException">forward:/error.jsp</prop>
				<prop key="java.lang.NullPointerException">forward:/null.jsp</prop>
			</props>
		</property>
	</bean>

SpringMVC詳解四、自帶標籤庫及自定義參數轉換器


jar包下載


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章