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
应用设置初始化参数。