`
yimeng528
  • 浏览: 188769 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

基于Spring MVC的Web应用开发(4) - FileUpload

阅读更多

上一篇文章介绍了Spring MVC如何处理静态资源文件,本文讲解如何使用Spring MVC做文件上传,附带深入一下Spring MVC的ModelAndView。增加一个Controller,叫FileUploadController:

Java代码 复制代码 收藏代码
  1. package org.springframework.samples.mvc.fileupload;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.RequestMapping;
  4. import org.springframework.web.bind.annotation.RequestMethod;
  5. @Controller
  6. @RequestMapping("/fileupload")
  7. publicclass FileUploadController {
  8. @RequestMapping(method=RequestMethod.GET)
  9. publicvoid fileUploadForm() {
  10. }
  11. }
package org.springframework.samples.mvc.fileupload;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/fileupload")
public class FileUploadController {

	@RequestMapping(method=RequestMethod.GET)
	public void fileUploadForm() {
	}

}

这个类和HelloWorld中的Controller类就有点差别了,首先类名上加入了@RequestMapping注解,这样在做HandlerMapping时,SpringMVC会将类名和方法名的@RequestMapping连接起来,而本例方法名前并没有具体路径(当然也可以写),因此最终映射的URL还是"/fileupload",另外一点就是在方法级@RequestMapping的注解增加了一个RequestMothod.GET,意思是只有以GET方式提交的"/fileupload"URL请求才会进入fileUploadForm()方法,其实根据HTTP协议,HTTP支持一系列提交方法(GET,POST,PUT,DELETE),同一个URL都可以使用这几种提交方式,事实上SpringMVC正是通过将同一个URL的不同提交方法对应到不同的方法上达到RESTful。

访问http://localhost:8080/web/fileupload,后台报错:

Java代码 复制代码 收藏代码
  1. 2012-03-2019:12:44.557:WARN::/web/fileupload
  2. javax.servlet.ServletException: Circular view path [fileupload]: would dispatch back to the current handler URL [/web/fileupload] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
  3. at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:292)
  4. ...
2012-03-20 19:12:44.557:WARN::/web/fileupload
javax.servlet.ServletException: Circular view path [fileupload]: would dispatch back to the current handler URL [/web/fileupload] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
	at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:292)
...

正如Hint中指出的,没有指定一个View,大家可能会有疑问,HelloWorld中不是可以将结果返回到浏览器么?注意HelloWorld中的@ResponseBody跟View没有任何关系,HelloWorld中其实也是返回了一个ModelAndView,但这个View为null,并且在返回前,已经将结果通过HttpServletResponse发送给浏览器了。
那么怎么指定一个View呢?通常我们会想到一个默认的View,即如果没有写特殊的View,所有的结果都将转到这个默认的View上,最后将这个View推到浏览器展示。在servlet-context.xml中增加一个配置:

Xml代码 复制代码 收藏代码
  1. <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
  2. <beans:beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver">
  3. <beans:propertyname="prefix"value="/WEB-INF/views/"/>
  4. <beans:propertyname="suffix"value=".jsp"/>
  5. </beans:bean>
	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>

配置了一个Bean,对应的类为InternalResourceViewResolver,并设置了prefix属性为"/WEB-INF/views",suffix属性为".jsp",这个类为视图解析器(view resolver),支持InternalResourceView(比如Servlet和JSP)及其子类如JstlView,默认的是InternalResourceView,如果有JSTL API存在的话,就是JstlView。

现在有一个默认的View了,这个View将view名字解析到/WEB-INF/views/目录下对应的jsp文件。
哪里有view名字?当带有@RequestMapping的方法返回void时,@RequestMapping映射的URL路径即view名字。

所以当使用GET方式访问http://localhost:8080/web/fileupload时,最终会找WEB-INF/views/目录下有没有fileupload.jsp文件,有则将此jsp文件显示在浏览器上,没有则报如下错误:

Java代码 复制代码 收藏代码
  1. ERROR: PWC6117: File &quot;/Users/stephansun/Documents/workspace/samples/samples-web/src/main/webapp/WEB-INF/views/fileupload.jsp&quot; not found
ERROR: PWC6117: File &quot;/Users/stephansun/Documents/workspace/samples/samples-web/src/main/webapp/WEB-INF/views/fileupload.jsp&quot; not found

fileUploadForm.jsp文件为:

Html代码 复制代码 收藏代码
  1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core"prefix="c" %>
  2. <html>
  3. <head>
  4. <title>fileupload | mvc-showcase</title>
  5. <linkhref="<c:url value="/resources/form.css" />" rel="stylesheet"type="text/css"/>
  6. <scripttype="text/javascript"src="<c:url value="/resources/jquery/1.6/jquery.js" />"></script>
  7. <scripttype="text/javascript"src="<c:url value="/resources/jqueryform/2.8/jquery.form.js" />"></script>
  8. </head>
  9. <body>
  10. <divid="fileuploadContent">
  11. <h2>File Upload</h2>
  12. <p>
  13. See the <code>org.springframework.samples.mvc.fileupload</code> package for the @Controller code
  14. </p>
  15. <formid="fileuploadForm"action="fileupload"method="POST"enctype="multipart/form-data"class="cleanform">
  16. <divclass="header">
  17. <h2>Form</h2>
  18. <c:iftest="${not empty message}">
  19. <divid="message"class="success">${message}</div>
  20. </c:if>
  21. </div>
  22. <labelfor="file">File</label>
  23. <inputid="file"type="file"name="file"/>
  24. <p><buttontype="submit">Upload</button></p>
  25. </form>
  26. </div>
  27. </body>
  28. </html>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
	<title>fileupload | mvc-showcase</title>
	<link href="<c:url value="/resources/form.css" />" rel="stylesheet"  type="text/css" />		
	<script type="text/javascript" src="<c:url value="/resources/jquery/1.6/jquery.js" />"></script>
	<script type="text/javascript" src="<c:url value="/resources/jqueryform/2.8/jquery.form.js" />"></script>	
</head>
<body>
	<div id="fileuploadContent">
		<h2>File Upload</h2>
		<p>
			See the <code>org.springframework.samples.mvc.fileupload</code> package for the @Controller code	
		</p>
		<form id="fileuploadForm" action="fileupload" method="POST" enctype="multipart/form-data" class="cleanform">
			<div class="header">
		  		<h2>Form</h2>
		  		<c:if test="${not empty message}">
					<div id="message" class="success">${message}</div>	  		
		  		</c:if>
			</div>
			<label for="file">File</label>
			<input id="file" type="file" name="file" />
			<p><button type="submit">Upload</button></p>		
		</form>	
	</div>
</body>
</html>

上传页面正确显示后,我们需要一个方法处理上传请求,processUpload,现在FileUploadController看起来是这样的:

Java代码 复制代码 收藏代码
  1. package org.springframework.samples.mvc.fileupload;
  2. import java.io.IOException;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.ui.Model;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. import org.springframework.web.bind.annotation.RequestParam;
  8. import org.springframework.web.multipart.MultipartFile;
  9. @Controller
  10. @RequestMapping("/fileupload")
  11. publicclass FileUploadController {
  12. @RequestMapping(method=RequestMethod.GET)
  13. publicvoid fileUploadForm() {
  14. }
  15. @RequestMapping(method=RequestMethod.POST)
  16. publicvoid processUpload(@RequestParam MultipartFile file, Model model) throws IOException {
  17. model.addAttribute("message", "File '" + file.getOriginalFilename() + "' uploaded successfully");
  18. }
  19. }
package org.springframework.samples.mvc.fileupload;

import java.io.IOException;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@Controller
@RequestMapping("/fileupload")
public class FileUploadController {

	@RequestMapping(method=RequestMethod.GET)
	public void fileUploadForm() {
	}

	@RequestMapping(method=RequestMethod.POST)
	public void processUpload(@RequestParam MultipartFile file, Model model) throws IOException {
		model.addAttribute("message", "File '" + file.getOriginalFilename() + "' uploaded successfully");
	}
	
}

这里出现了一个新注解@RequestParam,先看一下JSP页面的代码片段:

Html代码 复制代码 收藏代码
  1. <inputid="file"type="file"name="file"/>
<input id="file" type="file" name="file" />

input框提交的参数名就是file,@RequestParam注解自动将POST提交的参数中名为file的封装到一个MultipartFile类中,一切都在开发人员眼皮底下做好了,大大减少了开发人员的代码量。现在我们在上传页面选择一个文件上传,后台报错,看报错日志:

Java代码 复制代码 收藏代码
  1. java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
  2. at org.springframework.util.Assert.notNull(Assert.java:112)
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?
	at org.springframework.util.Assert.notNull(Assert.java:112)

说"是不是没配置MultipartResolver?",恩,还没有配,所有在servlet-context.xml中加上这么一段配置:

Xml代码 复制代码 收藏代码
  1. <!-- Only needed because we require fileupload in the org.springframework.samples.mvc.fileupload package -->
  2. <beans:beanid="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<!-- Only needed because we require fileupload in the org.springframework.samples.mvc.fileupload package -->
	<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

这个Bean也是一个视图解析器(view resolver)。

完整的XML:

Xml代码 复制代码 收藏代码
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beans:beansxmlns="http://www.springframework.org/schema/mvc"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:beans="http://www.springframework.org/schema/beans"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xmlns:mvc="http://www.springframework.org/schema/mvc"
  7. xsi:schemaLocation="
  8. http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
  9. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  10. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
  11. <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
  12. <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
  13. <resourcesmapping="/resources/**"location="/resources/"/>
  14. <!-- Imports user-defined @Controller beans that process client requests -->
  15. <beans:importresource="controllers.xml"/>
  16. <!-- You have to add this because you had a <resources/> declare -->
  17. <mvc:annotation-driven/>
  18. <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
  19. <beans:beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver">
  20. <beans:propertyname="prefix"value="/WEB-INF/views/"/>
  21. <beans:propertyname="suffix"value=".jsp"/>
  22. </beans:bean>
  23. <!-- Only needed because we require fileupload in the org.springframework.samples.mvc.fileupload package -->
  24. <beans:beanid="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
  25. </beans:beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
	<resources mapping="/resources/**" location="/resources/" />
	
	<!-- Imports user-defined @Controller beans that process client requests -->
	<beans:import resource="controllers.xml" />
	
	<!-- You have to add this because you had a <resources/> declare -->
	<mvc:annotation-driven/>
	
	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<!-- Only needed because we require fileupload in the org.springframework.samples.mvc.fileupload package -->
	<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
	
</beans:beans>

然后再次上传文件,页面显示:

Xml代码 复制代码 收藏代码
  1. File 'a.js' uploaded successfully
File 'a.js' uploaded successfully

上传成功,最后我们分析一下FileUploadController中的processUpload方法:

Java代码 复制代码 收藏代码
  1. @RequestMapping(method=RequestMethod.POST)
  2. publicvoid processUpload(@RequestParam MultipartFile file, Model model) throws IOException {
  3. model.addAttribute("message", "File '" + file.getOriginalFilename() + "' uploaded successfully");
  4. }
@RequestMapping(method=RequestMethod.POST)
	public void processUpload(@RequestParam MultipartFile file, Model model) throws IOException {
		model.addAttribute("message", "File '" + file.getOriginalFilename() + "' uploaded successfully");
	}

Model就是MVC模式中的M,Model层封装了要传递给View层显示的值。

最后更新一下pom.xml文件,添加两个依赖:

Xml代码 复制代码 收藏代码
  1. <!-- File Upload -->
  2. <dependency>
  3. <groupId>commons-fileupload</groupId>
  4. <artifactId>commons-fileupload</artifactId>
  5. <version>1.2.2</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>commons-io</groupId>
  9. <artifactId>commons-io</artifactId>
  10. <version>2.0.1</version>
  11. </dependency>
	
	<!-- File Upload -->
	<dependency>
		<groupId>commons-fileupload</groupId>
		<artifactId>commons-fileupload</artifactId>
		<version>1.2.2</version>
	</dependency>	
	<dependency>
		<groupId>commons-io</groupId>
		<artifactId>commons-io</artifactId>
		<version>2.0.1</version>
	</dependency>

好像前面写的代码根本没有涉及到这两个jar包啊,为什么要引入?

之前我写道

@RequestParam注解自动将POST提交的参数中名为file的封装到一个MultipartFile类中,一切都在开发人员眼皮底下做好了,大大减少了开发人员的代码量。

底层真正由谁来做的呢?我们加入了multipartResolver这个Bean,它对应的类为

org.springframework.web.multipart.commons.CommonsMultipartResolver,

看看这个类的源代码,import中赫然写着:

Java代码 复制代码 收藏代码
  1. import org.apache.commons.fileupload.FileItem;
  2. import org.apache.commons.fileupload.FileItemFactory;
  3. import org.apache.commons.fileupload.FileUpload;
  4. import org.apache.commons.fileupload.FileUploadBase;
  5. import org.apache.commons.fileupload.FileUploadException;
  6. import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

因此SpringMVC封装了commons-fileupload上传组件,真正起上传作用的还是commons-fileupload-1.2.2.jar这个jar包里面的类。

分享到:
评论

相关推荐

    Spring MVC 文件上传下载 后端 - Java.zip

    在Spring MVC框架中,文件上传和下载是常见的功能需求,特别是在构建Web应用程序时。这个压缩包文件"Spring MVC 文件上传下载 后端 - Java.zip"包含的文档可能详细阐述了如何在Java后端实现这些功能。以下是关于...

    commons-fileupload-1.3.3.jar和commons-io-2.6.jar

    1. **初始化Servlet环境**:首先,确保你的web应用配置了`CommonsMultipartResolver`作为Spring MVC或者Struts2等框架的文件解析器,以便处理multipart请求。 2. **解析请求**:在Servlet或控制器中,调用`...

    commons-fileupload-1.3.2.jar

    - Spring MVC: 在Spring MVC应用中,可以与`CommonsMultipartResolver`结合,自动处理文件上传。 - Struts 2: 对于基于Struts 2的应用,可以通过配置`struts.multipart.parser`属性为`jakarta`来启用Apache ...

    commons-fileupload及源码

    7. **与其他库的集成**:Apache Commons FileUpload可与Servlet API、Spring MVC、Struts等Web框架无缝集成,简化了在这些框架中实现文件上传的复杂性。 源码分析对于理解其内部工作原理非常有帮助。`commons-...

    commons-fileupload-1.3.3.jar commons-io-2.5.jar

    在Java开发中,文件上传是一项常见的任务,尤其是在构建Web应用时。`commons-fileupload-1.3.3.jar` 和 `commons-io-2.5.jar` ...在实际开发中,结合Spring MVC或其他Web框架,可以进一步提高代码的可维护性和灵活性。

    commons-fileupload-1.3.1.jar

    在Web开发中,尤其是基于Java的服务器端应用程序,文件上传是常见的需求,例如用户在表单中提交图片、文档或其他类型的数据。Apache Commons FileUpload库简化了这一过程,提供了高效且灵活的文件上传解决方案。 ...

    commons-fileupload-1.2.2-bin.zip

    7. **与Struts、Spring等框架的整合**:Commons FileUpload库可以轻松与主流的Java Web框架集成,如Struts、Spring MVC等,使得文件上传功能的实现更加便捷。 总的来说,Apache Commons FileUpload库是Java开发人员...

    commons-fileupload-1.2.2.jar和commons-io-2.4.jar包

    总之,`commons-fileupload-1.2.2.jar`和`commons-io-2.4.jar`是Java Web开发中处理文件上传和下载不可或缺的工具。尽管它们的版本可能不是最新的,但依然能提供可靠的功能,并且在很多现有的系统中广泛使用。理解并...

    commons-fileupload-1.2.jar和commons-io-1.3.2.jar

    标题中的"commons-fileupload-1.2.jar"和"commons-io-1.3.2.jar"是两个在Java...不过,随着技术的发展,现代Web应用更多地采用Struts2或其他更先进的框架,如Spring MVC,它们通常内建了更强大且安全的文件上传机制。

    commons-fileupload-1.2.1.jar

    此外,它也能与Spring MVC、Struts等Web框架无缝集成,简化文件上传的实现。 8. **版本更新**:`1.2.1`是该库的一个较旧版本,后续的版本可能添加了更多功能和修复了已知问题。使用时,建议根据项目需求选择合适且...

    最新实现上传下载 commons-fileupload-1.3.1和commons-io-2.4 整套下载

    标签中的`springmvc`表明了这些操作是在Spring MVC框架下进行的,该框架简化了Web应用的开发,提供了模型-视图-控制器的架构模式。 总的来说,`commons-fileupload-1.3.1`和`commons-io-2.4`是Java开发者在处理文件...

    SpringMVCForm-FileUpload-Example.zip_The Web

    【SpringMVCForm-FileUpload-Example.zip_The Web】是一个与Web开发相关的资源包,特别关注Spring MVC框架中的表单文件上传功能。这个压缩包很可能是为了帮助软件开发者理解和实现Spring MVC应用中的文件上传机制。...

    使用commons-fileupload实现的文件上传和下载

    在Java Web开发中,文件上传和下载是常见的功能需求,Apache Commons FileUpload库提供了一种高效、方便的方式来处理这些...在实际开发中,还可以结合Spring MVC或Struts等框架,进一步简化代码和提高代码的可维护性。

    一个简单的使用commons-fileupload包上传文件的例子

    在Java Web开发中,文件上传是一项常见的功能,`commons-fileupload`库是Apache Commons项目提供的一款强大且易于使用的工具,专门用于处理HTTP请求中的多部分数据,即文件上传。本示例将详细介绍如何使用`commons-...

    java中common-fileupload 上传文件demo

    在Java开发中,文件上传是一项常见的任务,尤其是在构建Web应用时。`Commons FileUpload`是Apache Commons项目的一部分,它为处理HTTP请求中的多部分数据(通常用于文件上传)提供了便利。下面,我们将深入探讨如何...

    commons-fileupload-1.2.2.jar

    `commons-fileupload-1.2.2.jar`是Apache Commons FileUpload项目的版本1.2.2的Java档案库,主要用于处理HTTP协议中的多部分表单数据,即在Web应用程序中进行文件上传的功能。这个库是Java EE环境中实现文件上传...

    commons-fileupload-1.2.jar commons-io-1.3.1.jar上传图片jar

    在实际开发中,它们经常与其他Java Web框架(如Spring MVC、Struts等)配合,为用户提供便捷的文件上传体验。在使用过程中,需要注意安全问题,例如防止文件覆盖、处理非法文件名、过滤敏感文件类型等。同时,为了...

    commons-fileupload.jar

    标题中的"commons-fileupload.jar"是一个Java库,它是Apache Commons FileUpload项目的组成部分,主要用于处理HTTP...在实际开发中,它们常常与其他Java Web框架(如Spring MVC或Struts)一起使用,构建强大的Web应用。

    Commons-FileUpLoad(JAR包).zip

    6. **与其他库的集成**:Commons-FileUpload可以很好地与Servlet API和其他Java Web框架(如Spring MVC)集成,使得在各种环境中使用都很方便。 7. **多线程支持**:在高并发环境下,库支持多线程处理上传请求,...

Global site tag (gtag.js) - Google Analytics