Spring 实战-第七章-Spring MVC的高级技术
1.处理multipart形式的数据
对于文件,Spring可以支持multipart形式的数据,但是DispatcherServlet没有实现任何解析multipart请求数据的功能,需要配置一个解析器用来解析multipart。
DispatcherServlet将该任务委托给了Spring中的MultipartResolver策略接口的实现,Spring内置了两个实现可以选择:
- CommonMultipartResolver:使用Jakarta Commons FileUpload解析multipart请求;
- StandardServletMultipartResolver:依赖于Servlet3.0对multipart请求的支持(始于Spring3.1)
声明MultipartResolver的Bean
@Bean public MultipartResolver multipartResolver() throws IOException { return new StandardServletMultipartResolver(); }
使用的时候,必须在web.xml或Servlet初始化类中,将multipart的具体细节(文件路径、大小等)作为DispatcherServlet配置的一部分,否则无法正常使用。
如果采用Servlet初始化类的方式配置DispatcherServlet的话,这个类已经实现了WebApplicationInitializer,那么可以在Servlet registration上调用setMultipartConfig()方法,传入一个MultipartConfigElement。
DispatcherServlet ds=new DispatcherServlet(); Dynamic registration=context.addServlet("appServlet",ds); registration.addMapping("/"); registration.asetMultipartConfig( new MultipartCofigElement("/tmp/spittr/upolads"));
如果配置的Servlet初始化类继承了AbstractAnnotationConfigDispatcherServletInitializer或AbstractDispatcherServletInitializer的话,可以重载customizeRegistration()方法来配置multipart的具体细节。
//设置multipart上传配置,路径,文件不超过2MB,请求不超过4MB @Override protected void customizeRegistration(ServletRegistration.Dynamic registration){ registration.setMultipartConfig( new MultipartConfigElement("C:/test",2097152,4194304,0)); }
页面增加input标签
<input type="file" name="profilePicture" accept="image/jpeg,image/png,image/gif"/>
处理multipart请求,最常用的是在控制器方法参数上添加@RequestPart注解,接收multipart数据可以使用byte[]、MultipartFile、Part等形式,MultipartFile与Part类似,都包含保存到文件系统的方法。
@RequestMapping(value="/register",method = POST) public String processRegistration( @RequestPart("profilePicture") MultipartFile profilePicture, @Valid Spitter spitter, Errors errors, RedirectAttributes model) throws IOException{ if(errors.hasErrors()){ return "registerForm"; } spitterRepository.save(spitter); //如果有上传文件,则保存到指定位置 if(!profilePicture.isEmpty()) { profilePicture.transferTo(new File(profilePicture.getOriginalFilename())); } model.addFlashAttribute("spitter",spitter); return "redirect:/spitter/"+ spitterRepository.findByUsername("").getUsername(); }
7.3处理异常
默认情况下,Spring会将吱声的一些异常自动转为为合适的状态,此外,我们可以对应用抛出的异常进行个性化的处理。
- 将应用异常转为HTTP状态
通过@ResponseStatus注解,可以将异常类转换为特定的HTTP状态,并且增加相关信息
@ResponseStatus(value= HttpStatus.NOT_FOUND,reason = "将异常映射为特定的状态码") public class ErrorOneException extends Exception { }
当代码抛出被包装的异常后,网页会使用异常指定的状态码,并且显示相关信息
//将异常映射为特定的状态码 @RequestMapping(value="/errorone",method = GET) public String errorone(Model model) throws ErrorOneException{ throw new ErrorOneException(); }
-
编写处理异常的方法
在某些情况下,主动抛出异常,不仅会增加无关的逻辑,并且通过异常机制处理可能不能满足需求,需要对于特定异常进行更复杂的操作,比如跳转到其他页面,
这时候在@ExceptionHandler注解,可以处理指定类型的异常
//编写处理异常的方法 @RequestMapping(value="/errortwo",method = GET) public String errortwo(Model model){ int a=1/0;//会抛出ArithmeticException return "test"; } //编写处理异常的方法 @ExceptionHandler(ArithmeticException.class) public String handleErrorTwo(){ return "error";//使用error视图进行渲染 }
7.4 为控制器添加通知
Spring3.2引入的控制器通知(controller advice),是任意带有@ControllerAdvice注解的类,这样控制器类的特定切面能够运用到整个应用程序的所有控制器中。
这个类包含一个或多个如下类型的方法:
- @ExceptionHandler注解标注的方法;
- @InitBinder注解标注的方法;
- @ModelAttribute注解标注的方法。
在带有@ControllerAdvice注解的类中,以上所述的这些方法会运用到整个应用程序所有控制器中带有@RequestMapping注解的方法上。
@ControllerAdvice注解本身已经使用了@Component,因此@ControllerAdvice注解锁标注的类将会自动被主键扫描获取到。
比如7.3中的异常处理,就可以将异常处理统一到一处
@ControllerAdvice public class AppWideExceptionHandler { @ExceptionHandler(ErrorThreeException.class) public String errorThreeExceptionHandler(){ return "error"; } }
7.5跨重定向请求传递数据
当使用“redirect:”前缀进行重定向的时候,由于模型数据已经随着上一个请求的结束而消亡,无法传递到下一个请求中,Spring提供了flash(闪存)属性,用于存储这类模型数据。
相比Session存储,flash的好处在于,其生命周期只延续到下一个请求,请求结束后就会消失。
使用flash存储模型数据
//使用flash存储模型数据 @RequestMapping(value="/flash",method = POST) public String processFlash(Spitter spitter, RedirectAttributes model) { model.addFlashAttribute("spitter",spitter); return "redirect:/spitter/test"; }
读取flash中的模型数据,当model中没有spitter属性时,使用查询数据库,否则就使用属性中的,当返回到页面请求结束,flash中的数据就没有了
//读取flash中的模型数据 @RequestMapping(value = "/{username}",method = GET) public String showSpitterProfile( @PathVariable String username,Model model){ if(!model.containsAttribute("spitter")) { Spitter spitter = spitterRepository.findByUsername(username); model.addAttribute(spitter); } return "profile"; }
sourceCode:https://github.com/ljw8947/SpringInAction/tree/master/Capter7/Spittr
posted on 2017-11-29 18:07 Lv Jianwei 阅读(484) 评论(0) 编辑 收藏 举报