2.12.4 改进的Servlet API
2.12.4 改进的Servlet API
Servlet3还有一个改变是改进了部分API,这种改进很好地简化了Java Web开发。其中两个较大的改进是
HttpServletRequest增加了对文件上传的支持。ServletContext允许通过编程的方式动态注册Servlet、Filter
HttpServletRequest文件上传方法
HttpServletRequest提供了如下两个方法来处理文件上传。
Part getPart(String name):根据名称来获取文件上传域。Collection<Part> getParms():获取所有的文件上传域
通过Part类对象来访问文件信息 将文件写入服务器
上面两个方法的返回值都涉及一个API:Part,每个Part对象对应于一个文件上传域,该对象提供了大量方法来访问上传文件的文件类型、大小、输入流等,并提供了一个write(String file)方法将上传文件写入服务器磁盘。
HTML文件域
为了向服务器上传文件,需要在表单里使用<input type="file">文件域,这个文件域会在HTML页面上产生一个单行文本框和一个“浏览”按钮,浏览者可通过该按钮选择需要上传的文件。
需要设置HTML form元素的enctype属性
除此之外,上传文件一定要为表单域设置enctype属性。
application/x-www-form-urlencoded:这是默认的编码方式,它只处理表单域里的value属性值,采用这种编码方式的表单会将表单域的值处理成URL编码方式。multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数里。text/plain:这种编码方式当表单的action属性为mailto:URL的形式时比较方便,这种方式主要适用于直接通过表单发送邮件的方式。
如果将enctype设置为application/x-www-form-urlencoded,或不设置enctype属性,提交表单时只会发送文件域的文本框里的字符串,也就是浏览者所选择文件的绝对路径,对服务器获取该文件在客户端上的绝对路径没有任何作用,因为服务器不可能访问客户机的文件系统。
upload.jsp
下面定义了一个文件上传的页面。
1 | <%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %> |
上面的页面中的表单需要设置enctype="multipart/form-data",这表明该表单可用于上传文件。
上面的表单中定义了两个表单域:
- 一个普通的文本框,它将生成普通请求参数;
- 一个文件上传域,它用于上传文件。
对于传统的文件上传需要借助于common-fileupload等工具,处理起来极为复杂,借助于Servlet3的API,处理文件上传将变得十分简单。看下面的Servlet类代码
UploadServlet.java
1 | package lee; |
上面Servlet使用了@MultipartConfig注解修饰,处理文件上传的Servlet应该使用该注解修饰。接下来该Servlet中HttpServletrequest就可通过getPart( String name)方法来获取文件上传域——就像获取普通请求参数一样。
web.xml中配置
与Servlet所有注解相似的是,Servlet为@MultipartConfig提供了相似的配置元素,同样可以通过在<servlet>元素中添加<multipart-config/>子元素来达到相同的效果
获取了上传文件对应的Part之后,可以非常简单地将文件写入服务器磁盘,如上面的①号代码所示。当然也可以通过Part获取所上传文件的文件类型、文件大小等各种详细信息。
例如选择一个*.png图片,然后单击上传将可看到如图2.52所示的页面。
上面的Servlet中将会把上传的文件保存到Web应用的根路径下的uploadFiles目录下,因此读者还应该在Web应用的根路径下创建uploadFiles目录
避免上传的文件同名
上面Servlet上传时保存的文件名直接使用了上传文件的原始文件名,在实际项目中一般不会这么做,因为可能多个用户可能上传同名的文件,这样将导致后面用户上传的文件覆盖前面用户上传的文件。在实际项目中可借助于java.util.UUID工具类生成文件名。
动态注册Servlet Filter
ServletContext则提供了如下方法来动态地注册Servet、Filter,并允许动态设置Web应用的初始化参数。
- 多个重载的
addServlet()方法:动态地注册ServletE - 多个重载的
addFilter()方法:动态地注册Filter - 多个重载的
addListener()方法:动态地注册Listener setInitParameter(String name, String value)方法:为Web应用设置初始化参数。