下载文件
下载文件是指把服务器端的文件发送到客户端
具体步骤:
OutputStream out;//输出相应正文的输出流
InputStream in;//取得本地文件的输入流
String filename=request.getParameter("filename");//获得请求参数
in=getServletContext().getResourceAsStream("/store/"+filename);//获得store目录下的相应文件输入流
//设置相应正文的MIME类型
int length=in.available();
response.setContentType("application/force-dowload");
response.setHeader("Content-Length", String.valueOf(length));
response.setHeader("Content-Disposition", "attachment;filename=\""+filename+"\"");
//把本地文件中的数据发送给客户
out=response.getOutputStream();
int byteRead =0;
byte[] buffer=new byte[512];
while ((byteRead=in.read(buffer))!=-1) {
out.write(buffer, 0, byteRead);
in.close();
out.close();
}//读取文件数据,并通过输出流把文件中的数据送到客户端
通过浏览器访问http://localhost:8080/helloapp/download?finame=XXXX.rar
文件上传
具体步骤:
在upload.html文件的代码如下
<form name="uploadForm" method="post" enctype="MULTIPART/FORM-DATA0" action="upload">
<table>
<tr>
<td><div align="right">User name:</div></td>
<td><input type="text" name="username" size="30"/></td>
</tr>
<tr>
<td><div align="right">Upload File1:</div></td>
<td><input type="file" name="file1" size="30"/></td>
</tr>
<tr>
<td><div align="right">Upload File2:</div></td>
<td><input type="file" name="file2" size="30"/></td>
</tr>
<tr>
<td><input type="submit" name="submit" value="upload"></td>
<td><input type="reset" name="reset" value="reset"></td>
</tr>
</table>
</form>
在servlet中可利用Apache开源软件组织提供的两个软件包来实现文件上传
fileupload软件包:
http://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi
io软件包:
http://commons.apache.org/proper/commons-io/download_io.cgi
软件包把请求正文包含的复合表单的每个子部分看作是一个FileItem对象,分为两种类型:formFile(普通表单域类型)非formField(上传文件类型)
FileItemFactory是创建FileItem对象的工厂,DiskFileItemFactory类和DiskFlieItem类分别实现了FileItemFactory接口和FileItem接口。DiskFlieItem能够把客户端上传的文件数据保存到硬盘上,DiskFileItemFactory则是DiskFlieItem对象的工厂。
以下代码创建了一个DiskFileItemFactory对象,然后设置了在向硬盘写数据时所用的缓冲区的大小,以及所使用的临时目录:
//创建一个基于硬盘的FileItem工厂
DiskFileItemFactory factory=new DiskFileItemFactory();
//向硬盘写数据时所用的缓冲区的大小,此处为4K
factory.setSizeThreshold(4*1024);
//设置临时目录
factory.setRepository(new File(tempFilePath));
ServletFileUpload为上传处理器,与FileItemFactory关联:
//创建一个文件上传器
ServletFileUpload upload=new ServletFileUpload(factory);
//设置允许上传的文件的最大尺寸为4M
upload.setSizeMax(4*1024*1024);
//ServletFileUpload类的parseRequest(HttpServletRequest req)方法能够解析HttpServletRequest对象中的复合表单数据,返回一组FileItem对象集合:
List items=upload.parseRequest(request);
//然后遍历集合,判断每个FileItem对象的类型做相应的处理
Iterator iter=items.iterator();
while (iter.hasNext()) {
FileItem item=(FileItem)iter.next();
if (item.isFormField()) {
processFormField(item, outNet);//处理普通表单
}
else {
processUploadedFile(item, outNet);//处理上传文件
}
}
web.xml文件中的UploadServlet的配置代码如下:
<servlet>
<servlet-name>upload</servlet-name>
<servlet-class>mypack.UploadServlet</servlet-class>
<init-param>
<param-name>filePath</param-name>
<parm-value>store</parm-value>
</init-param>
<init-param>
<param-name>tempFilePath</param-name>
<parm-value>temp</parm-value>
</init-param>
<servlet-mapping>
<servlet-name>upload</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
读写Cookie
Cookie是客户端访问Web服务器时,服务器在客户端硬盘上存放的信息,服务器可根据Cookie来跟踪客户状态。当客户端首次请求访问服务器时,服务器现在客户端存放该客户相关信息的Cookie信息,以后客户端每次访问服务器时,都会在Http请求数据中包含Cookie信息,服务器解析Http请求中的Cookie,就能获得关于客户的信息。
Web服务器为了支持Cookie,需具备以下功能:
- 把Cookie添加到HTTP响应中
cookie=new Cookie("username", "Tom");
cookie.setMaxAge(60*60);
response.addCookie(cookie);
- 读取来自客户端的Cookie
Cookie [] cookies=request.getCookies();
- 调用getName()方法获得Cookie名字,调用getValue()方法获得Cookie的值
out.println("Cookies name:"+cookies[i].getName());
out.println("Cookies value"+cookies[i].getValue());
可以通过Cookie类的setMaxAge()方法设置Cookie的有效期
访问Web应用的工作目录
Servlet可通过以下方式获得Web应用的工作目录
File workDir=(File)context.getAttribute("javax.servlet.context.tempdir");
转发和包含
Servlet规范为web组件之间的协作提供了两种途径:(1)请求转发(2)包含
公共的特点:
- 源组件和目标组件处理的都是同一个客户要求,两者共享同一个servletRequest和ServletResponse对象
- 目标组件都可以是Servlet,Jsp,Html文档
- 都依赖javax.servlet.RequestDispatcher接口(请求分发器:forward()方法和include()方法)
可以通过两种途径获得RequestDispatch()对象:
- 调用ServletContext的getRequestDispatch(String path)方法
- 调用ServletRequest的getRequestDispatch(String path)方法
前者必须为绝对路径,即以“/”开头的路径,应用的入口,后者可以为绝对路径,也可以为相对路径,不以“/”开头
请求转发:
ServletContext context=getServletContext();
RequestDispatcher dispatcher=context.getRequestDispatcher("/servlet/OutPutStreamServlet");
dispatcher.forward(request, response);
请求包含:
ServletContext context=getServletContext();
RequestDispatcher headDispatcher=context.getRequestDispatcher("/Header.html");
RequestDispatcher greetDispatcher=context.getRequestDispatcher("/servlet/GreetServlet");
headDispatcher.include(request, response);
greetDispatcher.include(request, response);
请求范围内的共享数据可通过setAttribute()方法和getAttribute()方法进行数据共享
重定向
用户在浏览器输入特定的URL,请求访问服务器的某个组件,服务器的组件返回一个状态代码为302的响应结果,该响应的含义是让服务再次请求访问另一个Web组件,另一个组件有可能在同一个Web服务器上,也有可能不在同一个Web服务器上。
关键代码:
response.setRedirect("/helloapp/output?msg="+message);//msg的值为message
如果以“/”开头的则是相对路径,如果以“Http://”开头的则是绝对路径
访问Servlet容器内的其他Web应用
在一个Servlet容器进程内,可以同时运行多个Web应用,这些Web应用之间可进行通信。每个Web应用都有一个ServletContext大总管,对于web应用A中的Servlet,只要得到了Web应用B的ServletContext对象,就能访问到Web应用的各种资源。
ServletContext接口中的getContext(String uripath)可以得到其他Web应用的Context对象,uripath为其他web应用对象的入口,在tomcat中,元素的crossContext对象属性用于设置该选项:crossContext属性为false,则其他应用访问返回null,如果为true则可以访问
代码示例:
ServletContext context=getServletContext();
ServletContext CrossContext=context.getContext("/helloapp");
RequestDispatcher dispatcher=CrossContext.getRequestDispatcher("/servlet/GreetServlet");
dispatcher.forward(request,response);
在XML文件中配置元素
<context reloadable="true" crossContext="true">
避免并发问题
- 合理决定在Servlet中定义的变量的作用域类型
局部变量作用于方法之中,方法结束,变量的生命周期也就结束,实例变量作用于类之中,如果一个实例结束,那么它的实例变量也就结束。
- 使用java同步机制对多线程同步
synchronized(this)