Spring MVC高級應用
1. 攔截器使用
監聽器、過濾器、攔截器對比
Servlet: 處理Request請求和Response響應
- 監聽器
實現了javax.servlet.ServletContextListener接口的服務器端組件,它隨Web應用的啓動而啓動,只初始化一次,然後會一直運行監視,隨Web應用的停止而銷燬。
作用1:做一些初始化的工作,web應用中spring容器啓動ContextLoadListener
作用2:監聽web的特定事件,比如HttpSession,ServletRequest的創建和銷燬;變量的創建、銷燬和修改等。比如統計在線人數,利用HttpSessionLisener等
配置在web.xml中
- 過濾器
對Request請求起到過濾的作用,作用在Servlet之前,如果配置爲/*可以對所有的資源訪問進行過濾處理
配置在web.xml中
- 攔截器
是Spring MVC、Struts等表現層框架自己的,不會攔截jsp/html/css/image的訪問等,只會攔截訪問的控制器方法(Handler)
執行的三個時機:
- 在Handler業務邏輯執行之前攔截一次
- 在Handler邏輯執行完畢但未跳轉頁面之前攔截一次
- 在跳轉頁面之後攔截一次
配置在表現層框架自己的配置文件中。
執行流程如下:
如果有多個攔截器呢?
攔截器編寫:
- 編寫一個攔截器
public class MyIntercepter implements HandlerInterceptor {
/**
*
* @param request
* @param response
* @param handler
* @return 返回值boolean代表是否放⾏,true代表放⾏,false代表中⽌
* @throws Exception
*/
@Override
public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
System.out.println("執行preHandle");
return true;
}
/**
* 會在handler⽅法業務邏輯執⾏之後尚未跳轉⻚⾯時執⾏
* @param request
* @param response
* @param handler
* @param modelAndView 封裝了視圖和數據,此時尚未跳轉⻚⾯呢,你可以在這⾥針對返回的數據和視圖信息進⾏修改
* @throws Exception
*/
@Override
public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
- 配置
<mvc:interceptors>
<mvc:interceptor>
<!--配置當前攔截規則-->
<mvc:mapping path="/**"/>
<!--排除哪些url攔截-->
<mvc:exclude-mapping path="/test"></mvc:exclude-mapping>
<bean class="com.mmc.mvc.interceptor.MyIntercepter"></bean>
</mvc:interceptor>
</mvc:interceptors>
2. 處理multipart形式的數據
上傳文件介紹:
- 引入依賴
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
- 配置文件上傳解析器
<!--配置⽂件上傳解析器,id是固定的multipartResolver-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--設置上傳⼤⼩,單位字節-->
<property name="maxUploadSize" value="1000000000"/>
</bean>
- 前端form
<form method="post" enctype="multipart/form-data" action="/demo/upload">
<input type="file" name="uploadFile"/>
<input type="submit" value="上傳"/>
</form>
- 後端接收代碼
@RequestMapping("/upload")
public String upload(MultipartFile uploadFile, HttpServletRequest request) throws IOException {
String originalFilename = uploadFile.getOriginalFilename();
System.out.println("原始文件名:"+originalFilename);
// 獲取⽂件的擴展名,如jpg
String extendName =
originalFilename.substring(originalFilename.lastIndexOf(".") + 1,
originalFilename.length());
String uuid = UUID.randomUUID().toString();
// 新的⽂件名字
String newName = uuid + "." + extendName;
String realPath=request.getServletContext().getRealPath("/uploads");
String datePath=new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File floder=new File(realPath+datePath);
if(!floder.exists()){
floder.mkdirs();
}
uploadFile.transferTo(new File(floder,newName));
return "success";
}
注意:前端input file的name的值要和後端接收的MultipartFile uploadFile的參數名稱保持一致。
3. 全局異常處理
// 可以讓我們優雅的捕獲所有Controller對象handler⽅法拋出的異常
@ControllerAdvice
public class GlobalExceptionResolver {
@ExceptionHandler(ArithmeticException.class)
public ModelAndView handleException(ArithmeticException exception,
HttpServletResponse response) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", exception.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
}
也可以在handleException方法上加上@ResponseBody直接返回json數據。
4. 基於Flash屬性的跨重定向請求數據傳遞
我們有兩種方式來跳轉請求,一種是重定向,一種是請求轉發。
- 請求轉發:請求參數不變,瀏覽器url也不變
- 重定向:參數丟失,瀏覽器url變
那麼我們怎麼攜帶參數進行重定向呢?
方法1:拼接url
@RequestMapping("/testRedirect")
public String redirect(String name){
return "redirect:/demo/testName?name="+name;
}
方法2:使用RedirectAttributes
@RequestMapping("/testRedirect")
public String redirect(String name,RedirectAttributes redirectAttributes){
//該屬性會暫存在session中,跳轉頁面後該屬性銷燬
redirectAttributes.addFlashAttribute("name",name);
return "redirect:/demo/testName";
}
@RequestMapping("/testName")
public String testName(HttpSession session,@ModelAttribute("name") String name){
System.out.println(name);
return "success";
}