上一节中, 我们是处理了文件上传的格式不对时,错误提示。但是这一节我们要处理的是,一旦文件上传的在写出流或写出流出现问题,或是线程上出了问题的话,那么我们应该如何处理。
查看我们自己的代码,我们可以看出,在文件上传时,很可能报出下面的错误:
1) IOException:如果我们文件写入磁盘时发生了错误,那么将会报这个异常栈。
2) MultipartException:这个异常栈应该是在我们正在上传文件时会出现,如,我们上传的文件太大。
很幸运,运用Spring的框架,我们可以很容易处理这些问题,我们处理的方法有下面的两个:
1) 在控制层的方法上注解@ExceptionHandker。
2) 在Servlet的容器内,使用全局的异常操作。
下面让我们用@ExceptionHandler的注解来处理IOException的异常栈。
@ExceptionHandler(IOException.class) public ModelAndView handleIOException(IOException exception) { ModelAndView modelAndView = new ModelAndView("profile/ uploadPage"); modelAndView.addObject("error", exception.getMessage()); return modelAndView; }
为了测试这个方法,我们先将onUpload的方法改变下面的。
@RequestMapping(value = "/upload", method = RequestMethod.POST) public String onUpload(MultipartFile file, RedirectAttributes redirectAttrs, Model model) throws IOException { throw new IOException("Some message"); }
之后,我们上传文件时,就可以看到下面的页面。
现在我们将要来处理MultipartException的异常栈,这个一般是发生服务上的,例如Tomcat服务器。这样的异常栈是我们所不能控制的。
我们需要有WebConfiguration的类中,添加EmbeddedServletContainerCustomizer的bean.
@Bean public EmbeddedServletContainerCustomizer containerCustomizer() { EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer = new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.addErrorPages(new ErrorPage(MultipartException. class, "/uploadError")); } }; return embeddedServletContainerCustomizer; }
我们使用的JDK8所以我们可以将上面的代码简化为下面的形式。(如果出现错误,操作:shift+Alt+S 选择8)
@Bean public EmbeddedServletContainerCustomizer containerCustomizer() { EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer = container -> container.addErrorPages(new ErrorPage(MultipartException.class, "/uploadError")); return embeddedServletContainerCustomizer; }
最后,我们还可以进一步简化我们的代码,如下的形式。
@Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return container -> container.addErrorPages(new ErrorPage(MultipartException.class, "/uploadError")); }
现在,我们需要在PictureUploadController中添加错误映射的路径。
@RequestMapping("uploadError") public ModelAndView onUploadError(HttpServletRequest request) { ModelAndView modelAndView = new ModelAndView("uploadPage"); modelAndView.addObject("error", request.getAttribute(WebUtils. ERROR_MESSAGE_ATTRIBUTE)); return modelAndView; }
错误的页面包含了许多有趣的服务容器中的错误参数属性,有助于我们定位问题。
最后,我们上传一个大于 1MB的文件,将会看到下面的报错信息。
上面的提示信息对于开发者来说是非常有用的,可以让我们快速定位问题,但对于用户来说是没有任何作用的,而且提示的信息也不够简洁。所以我们需要对这样的结果作处理。这就要修改PictureUploadController类,下面是笔者修改好的代码。
private final MessageSource messageSource; @Autowired public PictureUploadController(PictureUploadProperties uploadProperties, MessageSource messageSource) { picturesDir = uploadProperties.getUploadPath(); anonymousPicture = uploadProperties.getAnonymousPicture(); this.messageSource = messageSource; }同时我们相应的方法也要进行修改。
@ExceptionHandler(IOException.class) public ModelAndView handleIOException(Locale locale) { ModelAndView modelAndView = new ModelAndView("profile/ uploadPage"); modelAndView.addObject("error", messageSource.getMessage("upload. io.exception", null, locale)); return modelAndView; } @RequestMapping("uploadError") public ModelAndView onUploadError(Locale locale) { ModelAndView modelAndView = new ModelAndView("profile/ uploadPage"); modelAndView.addObject("error", messageSource.getMessage("upload. file.too.big", null, locale)); return modelAndView; }
这里的英文信息配置已经在前面的学习中配置了,法语是:
upload.io.exception=Une erreur est survenue lors de l'envoi du fichier. Veuillez réessayer. upload.file.too.big=Votre fichier est trop gros.
这一节中,我们已经学习了如何去处理IOException和MultipartException的异常栈。代码都是很简单,只是我们要考虑到用户界面的美观,所以不能直接将错误信息给视图层,需要我们作相应的处理。既然,我们的文件是可以上传了,那么,对于文件的显示又该如何实现呢?在下一节中,我们将会学习。
源码下载:git@github.com:owenwilliam/masterSpringMVC_4.git