Spring学习之旅(九)--SpringMVC高级技术
文件上传
在 Web 应用中,允许用户上传文件是很常见的需求。文件上传通常是采用 multipart 格式,而 DispatcherServlet 并没有任何解析 multipart 请求数据的功能,它将这个解析的任务委托给了 Spring 中的 MultipartResolver 策略接口的实现,通过这个实现类来解析 multipart 请求中的内容。
从 Spring 3.1 开始, Spring 内置了两个 MultipartResolver 实现供我们选择:
- CommonsMultipartResolver: 使用 Jakarta Commons FileUpload 解析 multipart 请求
- StandardServletMultipartResolver: 依赖于 Servlet 3.0 对 multipart 请求的支持
使用 CommonsMultipartResolver
@Bean
public MultipartResolver multipartResolver() throws IOException {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
// 配置存放路径,默认存放在 Servlet 容器临时目录
multipartResolver.setUploadTempDir(new FileSystemResource("/tmp/spring/uploads"));
// 配置最大文件容量为 2MB
multipartResolver.setMaxUploadSize(2097152);
// 配置最大内存容量为0,即直接写入到硬盘中
multipartResolver.setMaxInMemorySize(0);
return multipartResolver;
}
使用 StandardServletMultipartResolver
相比于CommonsMultipartResolver 来说 StandardServletMultipartResolver 没有构造器和属性,所以它的申明会很简单:
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
那么我们要如何取设置文件保存路径和大小呢?
我们可以在 Serlvet 中指定 multipart 的配置,我们之前通过继承 AbstractAnnotationConfigDispatcherServletInitializer 来实现了配置 DispatcherServlet,那么可以重载 customizeRegistration() 方法来配置 multipart:
@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
super.customizeRegistration(registration);
// 设置文件存放路径、文件最大文件容量为 2MB
// 整个请求不超过 4MB 并且直接写入到硬盘
registration.setMultipartConfig(
new MultipartConfigElement("/tmp/spring/uploads",2097152,
4194304,0));
}
可以看到 StandardServletMultipartResolver 相比于 CommonsMultipartResolver 多了一个设置整个请求大小的属性。
处理 multipart 请求
处理 multipart 请求有三种方式:
- 原始的 byte[]
- Spring 提供的 MultipartFile 接口
- Servlet3 支持的 Part
**原始的 byte[] **
@RequestMapping("/register")
public String processRegistration(@RequestPart("profilePicture") byte[] profilePicture){
......
}
byte 数组形式不能提供给我们文件类型、文件原始名称等信息。
Spring 提供的 MultipartFile 接口
接口定义
public interface MultipartFile extends InputStreamSource {
String getName();
String getOriginalFilename();
String getContentType();
boolean isEmpty();
long getSize();
byte[] getBytes() throws IOException;
InputStream getInputStream() throws IOException;
void transferTo(File var1) throws IOException, IllegalStateException;
}
MultipartFile 提供了获取原始文件名称、大小、内容类型等信息,还提供了一个 transferTo 方法,帮助我们将上传的文件写入到文件系统中。
** Servlet3 支持的 Part**
接口定义:
public interface Part {
InputStream getInputStream() throws IOException;
String getContentType();
String getName();
String getSubmittedFileName();
long getSize();
void write(String fileName) throws IOException;
void delete() throws IOException;
String getHeader(String name);
Collection<String> getHeaders(String name);
Collection<String> getHeaderNames();
}
Part 和 MultipartFile 基本差别不大,要注意的是如果使用了 *Part 那么就不需要配置 MultipartResolver 了。
异常处理
Spring 提供了多种方式将异常转为响应:
- 特定的 Spring 异常将会自动映射为指定的 HTTP 状态码
- 异常上可以添加 @ResponseStatus 注解,从而将其映射为某一个 HTTP 状态码
- 在方法上添加 @ExceptionHandler 注解,使其用来处理异常
将异常映射为 HTTP 状态码
| Spring 异常 | 状态码 |
|---|---|
| BindException | 400-Bad Request |
| ConversionNotSupportedException | 500-Intemal Server Error |
| HttpMediaTypeNotAcceptableException | 406-Not Acceptable |
| HttpMediaTypeNotSupportedException | 415-Unsupported Media Type |
| HttpMessageNotReadableException | 400-Bad Request |
| HttpMessageNotWritableException | 500-Intemal Server Error |
| HttpRequestMethodNotSupportedException | 405-Method NOt Allowed |
| MethodArgumentNotValidException | 400-Bad Request |
| MissingServletRequestParameterException | 400-Bad Request |
| MissingServletRequestPartException | 400-Bad Request |
| NoSuchRequestHandlingMethodException | 404-Not Found |
| TypeMismatchException | 400-Bad Request |
上面表中列出的异常一般会由 Spring 自身抛出,如果是应用自身抛出的异常它们就无能为力了,我们可以通过 @ResponseStatus 注解,将异常映射为特定的状态码。
@ResponseStatus(value=HttpStatus.NOT_FOUND,reason="not found")
public class SpringNotFoundException extends RuntimeException{
}
如果控制器抛出 SpringNotFoundException 异常后,响应状态将会变为 404。
异常处理方法
除了返回状态之外,我们还想返回异常包含的信息,我们可以通过 @ExceptionHandler 注解来处理异常信息。
@ExceptionHandler(SpringNotFoundException.class)
public String handleExceptionHandler(){
......
}
@ExceptionHandler 可以处理同一个 Controller 中的异常,但是如果是其他 Controller 的话就无能为力了。Spring 也考虑到了这个问题,为我们提供了 @ControllerAdvice 注解,它会捕获到所有的 Controller 异常。
@ControllerAdvice
public class AppWideExceptionHandler{
@ExceptionHandler(SpringNotFoundException.class)
public String handleExceptionHandler(){
......
}
}
Spring学习之旅(九)--SpringMVC高级技术的更多相关文章
- Spring学习之旅(六)--SpringMVC集成
对大多数 Java 开发来说,基于 web 的应用程序是我们主要的关注点. Spring 也提供了对于 web 的支持,基于 MVC 模式的 Spring MVC 能够帮助我们灵活和松耦合的完成 we ...
- Spring学习之旅(八)--SpringMVC请求参数
现在我们已经完成了一个无参的接口了,但是应用中有很多需要携带参数的场景,我们来看看 ** SpringMVC** 对它的支持. 参数绑定 SpringMVC 提供了一种绑定机制,通过这个机制可以从请求 ...
- Spring学习之旅(七)--SpringMVC视图
在之前的实例中我们只是在 Controller 中返回了 home 字符类型的值,而没有直接生成可以在浏览器中直接渲染的 HTML,这是因为 SpringMVC 将请求处理的逻辑和视图渲染的实现进行了 ...
- Spring学习之旅(十)--MockMvc
在之前的 Spring学习之旅(八)--SpringMVC请求参数 我们是通过在控制台输出来验证参数是否正确,但是这样做实在是太耗时间了,我们今天来学习下 MockMvc,它可以让我们不需要启动项目就 ...
- Spring学习之旅(八)Spring 基于AspectJ注解配置的AOP编程工作原理初探
由小编的上篇博文可以一窥基于AspectJ注解配置的AOP编程实现. 本文一下未贴出的相关代码示例请关注小编的上篇博文<Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AO ...
- 【Spring学习笔记-MVC-9】SpringMVC数据格式化之日期转换@DateTimeFormat
作者:ssslinppp 1. 摘要 本文主要讲解Spring mvc数据格式化的具体步骤: 并讲解前台日期格式如何转换为java对象: 在之前的文章<[Spring学习笔记-MVC ...
- 【Spring学习笔记-MVC-4】SpringMVC返回Json数据-方式2
<Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...
- 【Spring学习笔记-MVC-3】SpringMVC返回Json数据-方式1
<Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...
- spring-mvc高级技术
Spring MVC高级技术包括但不限于web.xml配置.异常处理.跨重定向请求传递数据 1.web.xml文件的配置 <!DOCTYPE web-app PUBLIC "-//Su ...
随机推荐
- 记一次愚蠢的经历--String不可变性
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 记录一次在写代码时愚蠢的操作,本文涉及到的知识点:S ...
- 将个人网站主页设置为Tomcat默认打开页面
步骤: 1.打开server.xml,在</Host>的上一行添加内容格式如下 <Context path="" reloadable="true&qu ...
- C# ORM简单原理
对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技术,用来把对象模型表示的对象映射到基于SQL的关系模型数据结构中去. 在今日的企业环境中,把面向对象 ...
- mysql8.0忘记密码如何操作?
很不幸,刚安装了MYSQL8,由于密码验证方式的不同,自己折腾了一小会,不小心退出来了,进不去了.从网上面查了一下资料,好多都不是特别好使,最后摸索出来可以进行如下操作: 1. 在配置文件中设置将密码 ...
- 入门训练-4. Fibonacci数列
问题描述 Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1. 当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少. 输入格式 输入包含一个整数n ...
- JavaScript基础学习第六天
目标: 能够使用对象的方式处理数据 ☞ 代码预解析: 1. 变量提升 :当程序中遇到定义变量后,就会将该变量的定义提升到当前作用域的开始位置,不包括变量的赋值 2. 函数提升:当程序中遇到函数的声明时 ...
- PageHelper分页实战(SSM整合)
步骤一:引入SSM相关的jar包,包列表如下: 步骤二:创建或修改配置文件,配置文件清单如下: applicationContext.xml <?xml version="1.0&qu ...
- 【iOS】CocoaPods 使用问题
这两天使用 CocoaPods 安装时遇到了这个问题,之前从没遇到过需要用户名和密码的情况.刚开始都是强退了重新在终端进入,后来不行…… [!] /usr/local/bin/git clone ht ...
- 蓝桥杯 2n皇后问题 深搜
默认大家会了n皇后问题 基础练习 2n皇后问题 时间限制:1.0s 内存限制:512.0MB 问题描述 给定一个n*n的棋盘,棋盘中有一些位置不能放皇后.现在要向棋盘中放入n个黑皇后和 ...
- 【Python-Django】浏览器同源策略
1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这个政策. 同源策略是浏览器的一个安全功能,不同源的客户端脚本(js文件)在没有明确授权的情况下,不能读写对方资源.只有 ...