天天看點

SpringMVC詳解五、@ResponseBody、@RequestBody、HttpEntity、ResponseEntity、檔案上傳、HandlerInterceptor攔截器及異常處理1、檔案上傳2、使用@ResponseBody将傳回的資料轉成json(***重點***)3、使用@RequestBody接收請求體資料4、使用HttpEntity參數擷取請求頭和請求體5、使用ResponseEntity傳回值操作響應頭和響應體:下載下傳檔案6、HandlerInterceptor攔截器7、異常處理

1、MultipartFile :檔案上傳

2、使用@ResponseBody将傳回的資料轉成json

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

3、使用@RequestBody接收請求體資料

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

5、使用ResponseEntity傳回值操作響應頭和響應體:下載下傳檔案

6、HandlerInterceptor攔截器

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.2、Controller中的代碼:

@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、打開浏覽器測試如下:

SpringMVC詳解五、@ResponseBody、@RequestBody、HttpEntity、ResponseEntity、檔案上傳、HandlerInterceptor攔截器及異常處理1、檔案上傳2、使用@ResponseBody将傳回的資料轉成json(***重點***)3、使用@RequestBody接收請求體資料4、使用HttpEntity參數擷取請求頭和請求體5、使用ResponseEntity傳回值操作響應頭和響應體:下載下傳檔案6、HandlerInterceptor攔截器7、異常處理
SpringMVC詳解五、@ResponseBody、@RequestBody、HttpEntity、ResponseEntity、檔案上傳、HandlerInterceptor攔截器及異常處理1、檔案上傳2、使用@ResponseBody将傳回的資料轉成json(***重點***)3、使用@RequestBody接收請求體資料4、使用HttpEntity參數擷取請求頭和請求體5、使用ResponseEntity傳回值操作響應頭和響應體:下載下傳檔案6、HandlerInterceptor攔截器7、異常處理

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;
	}
           

6、HandlerInterceptor攔截器

6.1、HandlerInterceptor攔截器的介紹

攔截器,可以攔截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包下載下傳

繼續閱讀