異常處理思路
系統的dao、service、controller出現異常都通過throws Exception向上拋出,最後由springmvc的前端控制器交由異常處理器進行異常處理
自定義異常類
對不同的異常類型定義不同的異常類,每種異常都要定義異常類
public class CustomException extends Exception {
//異常信息
private String message;
public CustomException(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
全局異常處理器
處理思路:如果該異常是系統自定義異常,直接取出異常信息,在錯誤頁面顯示,如果該異常類型不是系統自定義異常,構造一個系統自定義異常類型(信息爲”未知錯誤”)
springnvc提供了一個HandlerExceptionResolver接口:
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception exception) {
//handler就是處理器適配器要執行的handler對象(只有method)
//exception 系統拋出的異常
//解析異常類型,如果是系統自定義異常,取出錯誤信息在頁面顯示
/*String message = null;
if(exception instanceof CustomException ) {
message = ((CustomException)exception).getMessage();
}
else {
//如果不是系統自定義異常,構建一個自定義的異常類型
message = "未知錯誤";
}*/
CustomException customException = null;
if(exception instanceof CustomException) {
customException = (CustomException)exception;
}
else{
customException = new CustomException("未知錯誤");
}
String message = customException.getMessage();
ModelAndView modelAndView= new ModelAndView();
modelAndView.addObject("message", message);
modelAndView.setViewName("items/error");
return modelAndView;
}
}
全局異常處理器配置:
<!-- 只要實現了HandlerExceptionResolver接口就是全局異常處理器 -->
<bean class="springmvc.exception.CustomExceptionResolver"></bean>
如果與業務處理功能相關的異常建議在service層拋出,與業務功能沒有關係的異常建議在Controller中拋出
pringnvc中對多部件類型的解析
在頁面form中提交enctype=”multipart/form-data”的數據時,需要springmvc對這種類型的數據進行解析。
需要在springmvc.xml中配置multipart解析器:
<!-- 文件上傳 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 設置上傳文件最大尺寸爲5MB -->
<property name="maxUploadSize" value="5242880"></property>
</bean>
Controller類:
@RequestMapping("/pic.action")
public String ediItemsSubmit(Model model, MultipartFile pic) throws IllegalStateException, IOException {
if(pic != null) {
//存儲的物理路徑
String path = "F:\\tomcat\\apache-tomcat-8.0.33\\webapps\\springmvc\\image\\";
//圖片的原始名稱
String fileName = pic.getOriginalFilename();
System.out.println(fileName);
//生成新的圖片名稱,避免文件衝突
String newFileName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."));
File newFile = new File(path + newFileName);
pic.transferTo(newFile);
model.addAttribute("image", newFileName);
}
return "items/images";
}
注意:1.multipart解析器依賴於 commons-fileupload和commons-io這兩個jar包
2.文件上傳頁面中 :
<form id="Items" enctype="multipart/form-data" method="post" action="/springmvc/pic.action">
<input type="file" name="pic" />
<input type="submit" name="提交">
</form>
input標籤文件上傳(type=”file”)的name需要與Controller類形參MutipartFile的名稱一致,即都爲pic,文件才能傳入Controller類
攔截器
處理攔截器類似於Servlet的中的過濾器,用於對處理器進行預處理和後處理
spring攔截器針對HandlerMapping進行攔截設置,如果在某個HandlerMapping中配置攔截,經過該HandlerMapping映射成功的handler最終使用該攔截器。
springmvc配置類似全局的攔截器,springmvc框架將配置的類似全局的攔截器注入到每個handlerMapping中。
HandlerInterceptor類:
public class HandlerInterceptor1 implements HandlerInterceptor {
@Override
//執行handler方法之後
//可以使用同一的異常處理,日誌處理
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("1..afterCompletion");
}
@Override
//進入handler方法之後返回ModelAndView之前
//應用場景從modelAndView出發,將公用的模型數據(如菜單導航)在這裏傳到視圖,也可以在這裏統一指定視圖
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
System.out.println("1..postHandle");
}
@Override
//進入handler方法之前
//可用於身份驗證、身份授權
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
System.out.println("1.。preHandle");
//true表示放行,false表示攔截
return true;
}
}
配置:
<!-- 攔截器 -->
<mvc:interceptors>
<!-- 多個攔截器,順序執行 -->
<mvc:interceptor>
<!-- /**表示所有url包括子路徑
/*表示包含所有的跟路徑 -->
<mvc:mapping path="/**"/>
<bean class="springmvc.interceptor.HandlerInterceptor1"></bean>
</mvc:interceptor>
</mvc:interceptors>
preHandle方法按攔截器的順序執行,postHandle和afterCompletion方法按攔截器的逆序執行,所以日誌處理的攔截器一般放在首位。
攔截器1放行了攔截器2纔會放行,只要有一個攔截器不放行,postHandle方法不會執行。