问题:使用Spring MVC上传大文件,发现从页面提交,到进入后台controller,时间很长。怀疑是文件上传完成后,才进入。由于在HTTP首部自定义了“Token”字段用于权限校验,Token的有效时间很短,因此上传大文件时,就会验证Token失败。

示例代码:

前端:

<form action="upload" enctype="multipart/form-data" method="post"><table><tr><td>文件描述:</td><td><input type="text" name="description"></td></tr><tr><td>请选择文件:</td><td><input type="file" name="file"></td></tr><tr><td><input type="submit" value="上传"></td></tr></table>
</form>

controller:

@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(HttpServletRequest request, @RequestParam("description") String description, @RequestParam("file") MultipartFile file) throws Exception {System.out.println("enter controller."); // 文件上传完才打印}

springmvc-config.xml配置:

  <bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  <property name="maxUploadSize">  <value>524288000</value>  </property>  <property name="defaultEncoding"><value>UTF-8</value></property></bean>

Spring MVC上传文件使用了Commons FileUpload类库,即CommonsMultipartResolver使用commons Fileupload来处理 multipart请求,将Commons FileUpload的对象转换成了Spring MVC的对象。

那如果直接使用Commons FileUpload来进行文件上传下载呢?

示例代码:

protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {System.out.println("enter servlet"); // 页面提交后,立马打印              // 省略获取上传文件的逻辑              // ...}

发现从页面提交,很快就进入了servlet。

既然Spring也是使用了Commons FileUpload类库,但为什么差别这么大呢?Spring在转换过程中做了什么其他操作呢?

查看源码,或者直接看([Java] SpringMVC工作原理之四:MultipartResolver)

发现有个resolveLazily参数是判断是否要延迟解析文件(通过XML可以设置)。当 resolveLazily为false(默认)时,会立即调用 parseRequest() 方法对请求数据进行解析,然后将解析结果封装到 DefaultMultipartHttpServletRequest中;而当resolveLazily为 true时,会在DefaultMultipartHttpServletRequest的initializeMultipart()方法调用parseRequest()方法对请求数据进行解析,而initializeMultipart()方法又是被getMultipartFiles()方法调用,即当需要获取文件信息时才会去解析请求数据,这种方式用了懒加载的思想。

再次修改代码:

1、在springmvc-config.xml增加一个配置resolveLazily,设置true(如何配置见文末);

2、将controller方法中将@RequestParam("file") MultipartFile file注释

再次测试,发现还是不对。。增加打印日志后发现:

@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(HttpServletRequest request, @RequestParam("description") String description /*@RequestParam("file") MultipartFile file*/) throws Exception {System.out.println("enter controller.");   // 还是文件上传完后,才打印System.out.println(request.getHeader("Accept"));System.out.println(request.getParam("description"));// 省略获取上传文件的逻辑}

再注释@RequestParam("description") String description

@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(HttpServletRequest request/*@RequestParam("description") String description, *//*@RequestParam("file") MultipartFile file*/) throws Exception {System.out.println("enter controller.");   // 页面提交后,立刻打印System.out.println(request.getHeader("Accept")); // 几乎也是立刻打印System.out.println(request.getParam("description")); // 文件上传完,才打印    // 省略获取上传文件的逻辑}

这次,第1,2条日志很快打印,第3条日志仍是文件上传完后才打印。简单分析下,应该是后台一直在接收数据,HTTP首部很快就能获取到并解析出来(首部和正文之间有一个空行),但请求正文部分必须在请求数据完全接收后才能解析,因此线程一直阻塞直到数据接收完成才打印第3条日志。因此解决方案是,把controller函数中的@RequestParam("description") String description也注释掉,这样页面提交后,会立即进入controller中。

总结下最终的解决方案:

1、springmvc-config.xml增加一项配置:

<property name="resolveLazily "><value>true</value>
</property>

2、在controller的方法参数中,不能附加请求参数,应在函数中自己解析参数。

转载于:https://www.cnblogs.com/cyh706510441/p/8855320.html

Spring MVC上传文件原理和resolveLazily说明相关推荐

  1. Spring MVC上传文件后重命名读取不显示,报错已解决(The origin server did not find a current representation for the targe)

    上传文件后,重命名保存在本地,再读取时报错:The origin server did not find a current representation for the target resourc ...

  2. java中上传文件有哪些框架,Spring MVC系列教材 (八)- SPRING MVC 上传文件

    HTTP Status 500 – Internal Server Error Type 异常报告 消息 Servlet.init() for servlet [springmvc] threw ex ...

  3. 利用 Spring MVC 上传多文件到指定目录 spring upload files

    本篇文章,我们会教你通过eclipse构建一个创建一个Java web项目并转为maven工程,实现用spring mvc将所选文件上传到指定目录 开发环境: 1.JDK 1.7 2.Maven 3. ...

  4. java spring mvc 上传_Java Spring MVC 上传下载文件配置及controller方法详解

    下载: 1.在spring-mvc中配置(用于100M以下的文件下载) 下载文件代码 @RequestMapping("/file/{name.rp}") public Respo ...

  5. Spring Boot 上传文件(spring boot upload file)

    本篇文章将说明在Spring Boot web程序中如何上传文件. 开发环境: 1. eclipse Oxygen Release (4.7.0) 2. Spring Boot 1.4.3 RELEA ...

  6. Spring CommonsMultipartResolver 上传文件

    http://yanglei008.iteye.com/blog/246920 Spring CommonsMultipartResolver 上传文件 博客分类: spring SpringMVCJ ...

  7. Spring Boot(十七):使用Spring Boot上传文件

    Spring Boot(十七):使用Spring Boot上传文件 环境:Spring Boot最新版本1.5.9.jdk使用1.8.tomcat8.0 一.pom包配置 <parent> ...

  8. (转)Spring Boot(十七):使用 Spring Boot 上传文件

    http://www.ityouknow.com/springboot/2018/01/12/spring-boot-upload-file.html 上传文件是互联网中常常应用的场景之一,最典型的情 ...

  9. springboot上传文件同时传参数_Spring Boot 系列:使用 Spring Boot 上传文件

    上传文件是互联网中常常应用的场景之一,最典型的情况就是上传头像等,今天就带着带着大家做一个 Spring Boot 上传文件的小案例. 1.pom 包配置 我们使用 Spring Boot 版本 2. ...

最新文章

  1. 智能音箱玩出新花样?这家公司推出2699元的智能虚拟机器人
  2. 毛永胜计算机教师,中国文化中心笛子教师与毛国立音乐学院师生交流
  3. 通过WebRTC实现实时视频通信(三)
  4. Android 滑动显示下一层界面
  5. SPringBoot+mybatis 框架搭建例子
  6. Mixing ASP.NET MVC and Webforms
  7. net core 获取网站目录
  8. nodejs missing script: dev_nodejs深入学习系列之v8基础篇
  9. 【抽象代数】类方程和有限群
  10. 电子学会Python(二至五级)
  11. django-模板变量
  12. 绿联扩展坞拆解_拆解报告:UGREEN绿联3A1C四口多功能扩展坞(带SD卡槽版)
  13. 深入理解基本包装类型
  14. 打印工资条怎么做到每个人都有表头明细_使用工资条生成器,“智”作工资条...
  15. 关于taocp的MIX[水上原创]
  16. 原生js实现图片验证码
  17. oracle数据库用户状态失效Expired
  18. 智能可穿戴设备继续火 接入大数据帮你“管”身体
  19. mac 好玩的软件推荐
  20. 国家认证--软件评测师考试要求

热门文章

  1. 【mysq 5.7.31】远程访问权限(允许远程连接)
  2. mysql 树表删除无效节点
  3. ASM ClassReader failed to parse class file
  4. 【Error】Provider com.sun.xml.stream.ZephyrParserFactory not found
  5. php的session怎么用,php $_session怎么用
  6. SecurityContextPersistenceFilter和SecurityContextHolder的作用
  7. MySQL深入(一)
  8. 安装mysql error 1045_安装MySQL出现1045错误
  9. CentOS6.7安装mysql5.7
  10. CentOs安装ssh服务