目录
SpringMVC文件上传_原生方式上传
SpringMVC文件上传_SpringMVC方式上传
SpringMVC文件上传_上传多文件
SpringMVC文件上传_异步上传
SpringMVC文件上传_跨服务器上传
SpringMVC文件上传_原生方式上传
上传是Web工程中很常见的功能,SpringMVC框架简化了文件上传 的代码,我们首先使用JAVAEE原生方式上传文件:
1、创建新的SpringMVC项目,在web.xml中将项目从2.3改为3.1, 即可默认开启el表达式
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/webapp_3_1.xsd" id="WebApp_ID" version="3.1">
2、编写上传表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>上传</title> </head> <body> <h3>文件上传</h3> <%-- 上传表单的提交方式必须是post --%> <%-- enctype属性为multipart/formdata,意思是不对表单数据进行编码 --%> <form action="/fileUpload" method="post" enctype="multipart/formdata"> <%-- 文件选择控件,类型是file,必须要有name属性--%> 选择文件:<input type="file"name="upload"/> <input type="submit" value="上传"/> </form> </body> </html>
3、接收请求体数据:
@RequestMapping("/fileUpload") public String upload(HttpServletRequest request) throws Exception { // 获取输入流 ServletInputStream is = request.getInputStream(); // 从输入流获取请求体数据 int i = 0; while ((i=is.read())!=-1){ System.out.println((char)i); } return "index"; }
接下来需要分析请求体中的文件项,并将数据写入磁盘,此时需要 借助文件上传工具
1、引入文件上传依赖:
<!-- 文件上传 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commonsfileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
2、编写控制器接收上传请求,控制器进行三步操作:
2.1 创建文件夹,存放上传文件。
2.2 分析请求体,找到上传文件数据。
2.3 将文件数据写入文件夹。
@RequestMapping("/fileUpload") public String upload(HttpServletRequest request) throws Exception { // 创建文件夹,存放上传文件 // 1.设置上传文件夹的真实路径 String realPath = request.getSession().getServletContext().getRealPath("/upload"); // 2.判断该目录是否存在,如果不存在,创建该目录 File file = new File(realPath); if(!file.exists()){ file.mkdirs(); } // 分析请求体,找到上传文件数据 // 1.创建磁盘文件工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); // 2.创建上传数据分析器对象 ServletFileUpload servletFileUpload = new ServletFileUpload(factory); // 3.利用分析器对象解析请求体,返回所有数据项 List<FileItem> fileItems = servletFileUpload.parseRequest(request); // 4.遍历所有数据,找到文件项(非表单项) for (FileItem fileItem:fileItems){ if(!fileItem.isFormField()){ // 将文件数据写入文件夹 // 1.获取文件名 String name = fileItem.getName(); // 2.将文件写入磁盘 fileItem.write(new File(file,name)); // 3.删除内存中的临时文件 fileItem.delete(); } } return "index"; }
SpringMVC文件上传_SpringMVC方式上传
SpringMVC使用框架提供的文件解析器对象,可以直接将请求体中 的文件数据转为MultipartFile对象,从而省略原生上传中分析请求体的步骤。
1、在SpringMVC核心配置文件配置文件解析器
<!-- 文件解析器对象,id名称必须是 multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 支持一次上传文件的总容量。单位:字节 100M = 100*1024*1024--> <property name="maxUploadSize" value="104857600"/> <!-- 文件名的编码方式--> <property name="defaultEncoding" value="utf-8"/> </bean>
2、创建JSP表单
<form action="/fileUpload2" method="post" enctype="multipart/form-data"> <input type="file" name="file"/> <input type="submit" value="上传"/> </form>
3、编写控制器接收上传请求
// MultipartFile参数名必须和JSP文件空间的name 属性一致 @RequestMapping("/fileUpload2") public String upload2(MultipartFile file,HttpServletRequest request) throws IOException { // 创建文件夹,存放上传文件 String realPath = request.getSession().getServletContext().getRealPath("/upload"); File dir = new File(realPath); if(!dir.exists()){ dir.mkdirs(); } // 将上传的数据写到文件夹的文件中 // 1.拿到上传的文件名 String filename = file.getOriginalFilename(); filename = UUID.randomUUID()+"_"+filename; // 2.创建空文件 File newFile = new File(dir,filename); // 3.将数据写入空文件中 file.transferTo(newFile); return "index"; }
SpringMVC文件上传_上传多文件
SpringMVC支持一次性上传多个文件,写法如下:
1、创建JSP表单
<form action="/fileUpload3" method="post" enctype="multipart/form-data"> 用户名:<input name="username"/> 文件1:<input type="file" name="files"/> 文件2:<input type="file" name="files"/> <input type="submit" value="上传"/> </form>
2、编写控制器接收上传请求
// 处理多文件上传,参数类型为MultipartFile数组,参数名和JSP文件控件的name属性一致 @RequestMapping("/fileUpload3") public String upload3(MultipartFile files[],String username,HttpServletRequest request) throws Exception { System.out.println(username); //1.设置上传文件保存的文件夹 String realPath =request.getSession().getServletContext().getRealPath("/upload"); File dir = new File(realPath); if (!dir.exists()){ dir.mkdirs(); } //2.遍历数组,将上传文件保存到文件夹 for(MultipartFile file:files){ String filename =file.getOriginalFilename(); filename =UUID.randomUUID()+"_"+filename; File newFile = new File(dir,filename); file.transferTo(newFile); } return "index"; }
SpringMVC文件上传_异步上传
之前的上传方案,在上传成功后都会跳转页面。而在实际开发中, 很多情况下上传后不进行跳转,而是进行页面的局部刷新,比如: 上传头像成功后将头像显示在网页中。这时候就需要使用异步文件上传。
1、编写JSP页面,引入jQuery和jQuery表单上传工具
jquery.form.js
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>上传</title> <script src="/js/jquery-2.1.1.min.js"></script> <script src="/js/jquery.form.js"> </script> </head> <body> <h3>文件上传</h3> <form id="ajaxForm" enctype="multipart/form-data" > <input type="file" name="file"/> <%-- 按钮类型不能是submit,否则会刷新页面 --%> <input type="button" value="上传头像"id="btn"/> </form> <%-- 上传头像后展示的位置 --%> <img src="/" width="100" id="img"> <script> $(function () { $("#btn").click(function () { // 异步提交表单 $("#ajaxForm").ajaxSubmit({ url:"/fileUpload4", type:"post", success:function (data) { $("#img").attr("src",data); } }) }) }) </script> </body> </html>
2、编写控制器接收异步上传请求
@RequestMapping("/fileUpload4") //不进行页面跳转 @ResponseBody public String upload3(HttpServletRequest request, MultipartFile file) throws Exception { // 创建文件夹,存放上传文件。 String realPath = request.getSession().getServletContext().getRealPath("/upload"); File dir = new File(realPath); if (!dir.exists()){ dir.mkdirs(); } // 拿到上传文件名 String filename = file.getOriginalFilename(); filename = UUID.randomUUID()+"_"+filename; // 创建空文件 File newFile = new File(dir, filename); // 将上传的文件写到空文件中 file.transferTo(newFile); // 返回文件的路径 return "/upload/"+filename; }
SpringMVC文件上传_跨服务器上传
由于文件占据磁盘空间较大,在实际开发中往往会将文件上传到其 他服务器中,此时需要使用跨服务器上传文件。
1、解压tomcat作为图片服务器,在tomcat的webapps下创建 upload目录作为文件上传目录。
2、修改tomcat的 conf/web.xml 文件,支持跨服上传。
<servlet> <init-param> <param-name>readonly</param-name> <param-value>false</param-value> </init-param> </servlet>
3、修改tomcat的 conf/server.xml 文件,修改tomcat端口,修改完开启 tomcat服务器
<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
4、编写JSP上传表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>上传</title> <script src="/js/jquery2.1.1.min.js"></script> <script src="/js/jquery.form.js"></script> </head> <body> <h3>文件上传</h3> <form id="ajaxForm" enctype="multipart/form-data" > <input type="file" name="file"/> <input type="button" value="上传头像" id="btn"/> </form> <img src="/" width="100" id="img"> <script> $(function () { $("#btn").click(function() { $("#ajaxForm").ajaxSubmit({url:"/fileUpload5", type:"post",success:function(data) { $("#img").attr("src",data); } }) }) }) </script> </body> </html>
5、添加跨服上传依赖
<!-- 跨服上传 --> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> <version>1.18.1</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.18.1</version> </dependency>
6、创建控制器方法,该方法在接受到上传请求后将文件保存到其他服务器上。
@RequestMapping("/fileUpload5") @ResponseBody public String upload4(HttpServletRequest request, MultipartFile file) throws Exception { // 设置跨服上传的服务器路径 String path = "http://localhost:8081/upload/"; // 获取上传的文件名 String filename = file.getOriginalFilename(); filename = UUID.randomUUID()+"_"+filename; // 跨服上传: // 1.创建客户端对象 Client client = Client.create(); // 2.使用客户端对象连接图片服务器 WebResource resource = client.resource(path + filename); //3.传输数据 resource.put(file.getBytes()); return path+filename; }
复习
SpringMVC参数获取_使用Servlet原生对象获取参数
SpringMVC也支持使用Servlet原生对象,在方法参数中定义 HttpServletRequest 、 HttpServletResponse 、 HttpSession 等类型的参数即可直接在 方法中使用。
// 使用Servlet原生对象 @RequestMapping("/c1/param8") public void servletParam(HttpServletRequest request, HttpServletResponse response, HttpSession session){ // 原生对象获取参数 System.out.println(request.getParameter("name")); System.out.println(response.getCharacterEncoding()); System.out.println(session.getId()); }
访问该方法即可:http://localhost:8080/c1/param8?name=bjwan
一般情况下,在SpringMVC中都有对Servlet原生对象的方法的 替代,推荐使用SpringMVC的方式代替Servlet原生对象。
SpringMVC参数获取_自定义参数类型转换器
前端传来的参数全部为字符串类型,SpringMVC使用自带的转换器 将字符串参数转为需要的类型。如:
// 获取简单类型参数
@RequestMapping("/c1/param1")
public void simpleParam(String username,int age){
System.out.println(username);
System.out.println(age);
}
请求路径:http://localhost:8080/c1/param1?username=bz&age =10
但在某些情况下,无法将字符串转为需要的类型,如:
@RequestMapping("/c1/param9")
public void dateParam(Date birthday){
System.out.println(birthday);
}
由于日期数据有很多种格式,SpringMVC没办法把所有格式的字符 串转换成日期类型。比如参数格式为 birthday=2025-01-01 时,SpringMVC 就无法解析参数。此时需要自定义参数类型转换器。
1、定义类型转换器类,实现Converter接口
// 类型转换器必须实现Converter接口,两个泛型代表转换前的类型,转换后的类型 public class DateConverter implements Converter<String, Date> { /** * 转换方法 * @param source 转换前的数据 * @return 转换后的数据 */ @Override public Date convert(String source) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = null; try { date = sdf.parse(source); } catch (ParseException e) { e.printStackTrace(); } return date; } }
2、注册类型转换器对象
<!-- 配置转换器工厂 --> <bean id="dateConverter" class="org.springframework.context.support.ConversionServiceFactoryBean"> <!-- 转换器集合 --> <property name="converters"> <set> <!-- 自定义转换器 --> <bean class="com.tong.converter.DateConverter"></bean> </set> </property> </bean <!-- 使用转换器工厂 --> <mvc:annotation-driven conversionservice="converterFactory"> </mvc:annotation-driven>
3、此时再访问http://localhost:8080/c1/param9?birthday=2025- 01-01时,SpringMVC即可将请求参数封装为Date类型的参数。
SpringMVC参数获取_编码过滤器
在传递参数时,tomcat8以上能处理get请求的中文乱码,但不能处 理post请求的中文乱码
1、编写jsp表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>编码过滤器</title> </head> <body> <form action="/cn/code" method="post"> 姓名:<input name="username"> <input type="submit"> </form> </body> </html>
2、编写控制器方法
@RequestMapping("/cn/code") public void code(String username){ System.out.println(username); }
SpringMVC提供了处理中文乱码的过滤器,在web.xml中配置该过 滤器即可解决中文乱码问题:
<!--SpringMVC中提供的字符编码过滤器,放在所有过滤器的最上方-->
<filter>
<filter-name>encFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
SpringMVC处理响应_配置视图解析器
SpringMVC默认情况下会在控制器执行完成后跳转到视图页面,视 图解析器能找到相应的视图,之前的404异常就是由于没有配置视 图解析器导致找不到视图。
在SpringMVC中提供了13个视图解析器,用于支持不同的视图技术。InternalResourceViewResolver是SpringMVC的默认视图解析 器,用来解析JSP视图。
<!-- 视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/" />
<!-- 视图后缀 -->
<property name="suffix" value=".jsp" />
</bean>
SpringMVC处理响应_控制器方法的返回值
我们可以通过控制器方法的返回值设置跳转的视图,控制器方法支 持以下返回值类型:
返回值为void
此时会跳转到名字是 前缀+方法路径名+后缀 的jsp页面
1、编写控制器方法
// 路径是helloMVC,方法执行完后会跳转到/helloMVC.jsp @RequestMapping("/helloMVC") public void helloMVC(){ System.out.println("hello SpringMVC!"); }
2、编写helloMVC.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>MVC</title> </head> <body> <h1>欢迎来到SpringMVC</h1> </body> </html>
返回值为String
此时会跳转到名字是 前缀+返回值+后缀 的jsp页面
编写控制器方法
// 返回值为String
@RequestMapping("/c2/hello1")
public String helloMVC1(){
System.out.println("hello SpringMVC!");
// 方法执行完后会跳转到/helloMVC.jsp
return "helloMVC";
}
返回值为ModelAndView
这是SpringMVC提供的对象,该对象可以向request域设置数据并 指定跳转的页面。该对象中包含Model对象和View对象。
1、Model:向request域中设置数据。
2、View:指定跳转的页面。
1、编写控制器方法
// 返回值为ModelAndView @RequestMapping("/c2/hello2") public ModelAndView useMAV(){ System.out.println("返回值类型为ModelAndView"); // 1.创建ModelAndView对象 ModelAndView modelAndView = new ModelAndView(); // 2.获取Model对象,本质是一个Map Map<String, Object> model = modelAndView.getModel(); // 3.使用Model对象向request域设置数据 model.put("name","程序员"); // 4.使用View对象设置跳转的路径为/tong.jsp modelAndView.setViewName("baizhan"); return modelAndView; }
2、编写jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java"%> <html> <head> <title>百千万</title> </head> <body> <h1>你好!${requestScope.name}</h1> </body> </html>
3、修改web.xml命名空间,让jsp页面默认支持el表达式
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/webapp_3_1.xsd" version="3.1"> </web-app>