异常处理思路
系统的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方法不会执行。