文章目录
service
Servlet 需要提供对应的doGet()
与 doPost()
方法,目的是响应表单中的get和Post
doGet()
当浏览器使用get方式提交数据的时候,servlet需要提供doGet()方法
哪些是get方式呢?
- form默认的提交方式
- 如果通过一个超链访问某个地址
- 如果在地址栏直接输入某个地址
- ajax指定使用get方式的时候
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
doPost()
当浏览器使用post方式提交数据的时候,servlet需要提供doPost()方法
哪些是post方式呢?
- 在form上显示设置 method="post"的时候
- ajax指定post方式的时候
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
service()
LoginServlet继承了HttpServlet
,同时也继承了一个方法
service(HttpServletRequest , HttpServletResponse )
实际上,在执行doGet()
或者doPost()
之前,都会先执行service()
。由service()
方法进行判断,到底该调用doGet()
还是doPost()
可以发现,service(), doGet(), doPost()
三种方式的参数列表都是一样的。
所以,有时候也会直接重写service()
方法,在其中提供相应的服务,就不用区分到底是get
还是post
了。
比如把前面的登录的LoginServlet,改为提供service
方法,也可以达到相同的效果
但是不安全
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
String password = request.getParameter("password");
String html = null;
if ("admin".equals(name) && "123".equals(password))
html = "<div style='color:green'>success</div>";
else
html = "<div style='color:red'>fail</div>";
PrintWriter pw = response.getWriter();
pw.println(html);
}
}
中文问题
获取中文的参数(服务器端)
为了成功获取中文参数,需要做如下操作
- login.html中加上
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
这句话的目的是告诉浏览器,等下发消息给服务器的时候,使用UTF-8编码
2. login.html
form的method修改为post
3. 在servlet进行解码和编码
byte[] bytes= name.getBytes("ISO-8859-1");
name = new String(bytes,"UTF-8");
先根据ISO-8859-1
解码,然后用UTF-8
编码
这样就可以得到正确的中文参数了
这样需要对每一个提交的数据都进行编码和解码处理,如果觉得麻烦,也可以使用一句话代替:
request.setCharacterEncoding("UTF-8");
并且把这句话放在request.getParameter()
之前
以上是使用UTF-8的方式获取中文呢。 也可以使用GBK。把所有的UTF-8替换为GBK即可。 GB2312同理。
返回中文的响应
在Servlet中,加上
response.setContentType("text/html; charset=UTF-8");
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
String password = request.getParameter("password");
String html = null;
if ("admin".equals(name) && "123".equals(password))
html = "<div style='color:green'>登录成功</div>";
else
html = "<div style='color:red'>登录失败</div>";
response.setContentType("text/html; charset=UTF-8");
PrintWriter pw = response.getWriter();
pw.println(html);
}
}
生命周期
一个Servlet的生命周期由 实例化,初始化,提供服务,销毁,被回收 几个步骤组成
实例化
当用户通过浏览器输入一个路径,这个路径对应的servlet被调用的时候,该Servlet就会被实例化
为LoginServlet显式提供一个构造方法 LoginServlet()
然后通过浏览器访问,就可以观察到
“LoginServlet 构造方法 被调用”
无论访问了多少次LoginServlet,LoginServlet构造方法 只会执行一次,所以Servlet是单实例的
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
public LoginServlet(){
System.out.println("LoginServlet 构造方法 被调用");
}
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//略
}
}
初始化
LoginServlet 继承了HttpServlet
,同时也继承了init(ServletConfig)
方法
init
方法是一个实例方法,所以会在构造方法执行后执行。
无论访问了多少次LoginSerlvet
init初始化 只会执行一次
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
public LoginServlet() {
System.out.println("LoginServlet 构造方法 被调用");
}
public void init(ServletConfig config) {
System.out.println("init(ServletConfig)");
}
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 略
}
}
提供服务
接下来就是执行service()方法,然后通过浏览器传递过来的信息进行判断,是调用doGet()还是doPost()方法
在service()中就会编写我们的业务代码,在本例中就是判断用户输入的账号和密码是否正确
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
public LoginServlet() {
System.out.println("LoginServlet 构造方法 被调用");
}
public void init(ServletConfig config) {
System.out.println("init(ServletConfig)");
}
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
String password = request.getParameter("password");
String html = null;
if ("admin".equals(name) && "123".equals(password))
html = "<div style='color:green'>success</div>";
else
html = "<div style='color:red'>fail</div>";
PrintWriter pw = response.getWriter();
pw.println(html);
}
}
销毁
接着是销毁destroy()
在如下几种情况下,会调用destroy()
- 该Servlet所在的web应用重新启动
在server.xml中配置该web应用的时候用到了
<Context path="/" docBase="e:\\project\\j2ee\\web" debug="0" reloadable="false" />
如果把 reloadable="false" 改为reloadable="true"
就表示有任何类发生的更新,web应用会自动重启
当web应用自动重启的时候,destroy()
方法就会被调用
2. 关闭tomcat的时候 destroy()
方法会被调用,但是这个一般都发生的很快,不易被发现。
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
public void destroy() {
System.out.println("destroy()");
}
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 略
}
}
被回收
当该Servlet被销毁后,就满足垃圾回收的条件了。 当下一次垃圾回收GC来临的时候,就有可能被回收。
这个。。。也是不容易被观察到的现象。
跳转
页面跳转是开发一个web应用经常会发生的事情。
比如登录成功或是失败后,分别会跳转到不同的页面。
跳转的方式有两种,服务端跳转和客户端跳转
准备success.html fail.html
<div style="color:green">login success</div>
<div style="color:red">login fail</div>
服务器跳转
在Servlet中进行服务端跳转的方式:
'还是请求服务器数据:'
request.getRequestDispatcher("success.html").forward(request, response);
服务端跳转,浏览器的地址依然是/login 路径,并不会变成success.html
(这里我的html界面设置charset=“gbk”,中文才显出来了,设置为UTF-8就是乱码)
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
String password = request.getParameter("password");
if ("admin".equals(name) && "123".equals(password)) { request.getRequestDispatcher("success.html").forward(request, response);
}
}
}
客户端跳转
在Servlet中进行客户端跳转的方式:
response.sendRedirect("fail.html");
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
String password = request.getParameter("password");
if ("admin".equals(name) && "123".equals(password)) {
request.getRequestDispatcher("success.html").forward(request, response);
}
else{
response.sendRedirect("fail.html");
}
}
}
两种方法跳转图示
自启动
有的时候会有这样的业务需求:
tomcat一启动,就需要执行一些初始化的代码,比如校验数据库的完整性等。
但是Servlet的生命周期是在用户访问浏览器对应的路径开始的。如果没有用户的第一次访问,就无法执行相关代码。
这个时候,就需要Servlet实现自启动 即,==伴随着tomcat的启动,自动启动初始化,==在初始化方法init()中,就可以进行一些业务代码的工作了。
load-on-startup
在web.xml
中,配置Hello Servlet的地方,增加一句
<load-on-startup>10</load-on-startup>
取值范围是1-99
即表明该Servlet会随着Tomcat的启动而初始化。
同时,为HelloServlet提供一个init(ServletConfig)
方法,验证自启动
如图所示,在tomcat完全启动之前,就打印了init of HelloServlet
<load-on-startup>10</load-on-startup>
中的10表示启动顺序。如果有多个Servlet都配置了自动启动,数字越小,启动的优先级越高
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
import java.io.IOException;
import java.util.Date;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet{
public void init(ServletConfig config){
System.out.println("init of Hello Servlet");
}
public void doGet(HttpServletRequest request, HttpServletResponse response){.....}
}
request常见方法
request
对象的类是HttpServletRequest
,提供了很多有实用价值的方法
常见方法
request.getRequestURL(): 浏览器发出请求时的完整URL,包括协议 主机名 端口(如果有)"
request.getRequestURI(): 浏览器发出请求的资源名部分,去掉了协议和主机名"
request.getQueryString(): 请求行中的参数部分,只能显示以get方式发出的参数,post方式的看不到
request.getRemoteAddr(): 浏览器所处于的客户机的IP地址
request.getRemoteHost(): 浏览器所处于的客户机的主机名
request.getRemotePort(): 浏览器所处于的客户机使用的网络端口
request.getLocalAddr(): 服务器的IP地址
request.getLocalName(): 服务器的主机名
request.getMethod(): 得到客户机请求方式一般是GET或者POST
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
String password = request.getParameter("password");
System.out.println(request.getRequestURL());
System.out.println(request.getRequestURI());
System.out.println(request.getQueryString());
System.out.println(request.getRemoteAddr());
System.out.println(request.getRemoteHost());
System.out.println(request.getRemotePort());
System.out.println(request.getRemoteUser());
System.out.println(request.getMethod());
System.out.println(request.getLocalName());
if("admin".equals(name) && "123".equals(password))
获取参数
request.getParameter(): 是常见的方法,用于获取单值的参数
request.getParameterValues(): 用于获取具有多值的参数,比如注册时候提交的 "hobits",可以是多选的。
request.getParameterMap(): 用于遍历所有的参数,并返回Map类型。
<!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<form action="register" method="get">
账号 : <input type="text" name="name"> <br>
爱好 : LOL<input type="checkbox" name="hobits" value="lol">
DOTA<input type="checkbox" name="hobits" value="dota"> <br>
<input type="submit" value="注册">
</form>
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RegisterServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("获取单值参数name:" + request.getParameter("name"));
String[] hobits = request.getParameterValues("hobits");
System.out.println("获取具有多值的参数hobits: " + Arrays.asList(hobits));
System.out.println("通过 getParameterMap 遍历所有的参数: ");
Map<String, String[]> parameters = request.getParameterMap();
Set<String> paramNames = parameters.keySet();
for (String param : paramNames) {
String[] value = parameters.get(param);
System.out.println(param + ":" + Arrays.asList(value));
}
}
}
获取头部信息
request.getHeader() 获取浏览器传递过来的头信息。
比如getHeader("user-agent") 可以获取浏览器的基本资料,这样就能判断是firefox、IE、chrome、或者是safari浏览器
request.getHeaderNames() 获取浏览器所有的头信息名称,根据头信息名称就能遍历出所有的头信息
在本例,修改HelloServlet,使其获取头信息
访问HelloServlet获取如下头信息:
host: 主机地址
user-agent: 浏览器基本资料
accept: 表示浏览器接受的数据类型
accept-language: 表示浏览器接受的语言
accept-encoding: 表示浏览器接受的压缩方式,是压缩方式,并非编码
connection: 是否保持连接
cache-control: 缓存时限
public void init(ServletConfig config){
System.out.println("init of Hello Servlet");
}
public void doGet(HttpServletRequest request, HttpServletResponse response){
Enumeration<String> headerNames= request.getHeaderNames();
while(headerNames.hasMoreElements()){
String header = headerNames.nextElement();
String value = request.getHeader(header);
System.out.printf("%s\t%s%n",header,value);
}
try {
response.getWriter().println("<h1>Hello Servlet!</h1>");
response.getWriter().println(new Date().toLocaleString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
服务端传参
setAttribute
和getAttribute
可以用来在进行服务端跳转的时候,在不同的Servlet之间进行数据共享
response的用法
设置响应内容
通过response设置响应已经用得比较多了,在前面的Servlet学习中都是用到
PrintWriter pw= response.getWriter();
pw.println("<h1>Hello Servlet</h1>");
通过response.getWriter();
获取一个PrintWriter 对象
可以使用println(),append(),write(),format()
等等方法设置返回给浏览器的html内容。
设置响应格式
response.setContentType("text/html");
"text/html"
是即格式 ,在request获取头信息 中对应的request.getHeader("accept").
“text/html” 是存在的,表示浏览器可以识别这种格式,如果换一个其他的格式, 比如 “text/lol” ,浏览器不能识别,那么打开此servlet就会弹出一个下载的对话框。
这样的手段也就常常用于实现下载功能
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) {
try {
PrintWriter pw = response.getWriter();
pw.println("<h1>Hello Servlet</h1>");
response.setContentType("text/lol");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
设置响应编码
设置响应编码有两种方式:
1. response.setContentType("text/html; charset=UTF-8");
2. response.setCharacterEncoding("UTF-8");
这两种方式都需要在response.getWriter
调用之前执行才能生效。
他们的区别在于:
-
response.setContentType("text/html; charset=UTF-8");
:不仅发送到浏览器的内容会使用UTF-8编码,而且还通知浏览器使用UTF-8编码方式进行显示。所以总能正常显示中文 -
response.setCharacterEncoding("UTF-8");
:仅仅是发送的浏览器的内容是UTF-8编码的,至于浏览器是用哪种编码方式显示不管。 所以当浏览器的显示编码方式不是UTF-8的时候,就会看到乱码,需要手动再进行一次设置。
301或者302客户端跳转
客户端有两种跳转
302 表示临时跳转
301 表示永久性跳转
302就是前面在客户端跳转用到过的
response.sendRedirect("fail.html");
301要使用另外的手段:
response.setStatus(301);
response.setHeader("Location", "fail.html");
用户感受不出这两种跳转的区别,
301 Moved Permanently。
301和302的区别主要在搜索引擎对页面排名的时候有影响,是属于SEO范畴的概念.
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
String password = request.getParameter("password");
if ("admin".equals(name) && "123".equals(password)) {
request.getRequestDispatcher("success.html").forward(request, response);
} else {
response.setStatus(301);
response.setHeader("Location", "fail.html");
}
}
设置不使用缓存
使用缓存可以加快页面的加载,降低服务端的负担。但是也可能看到过时的信息,可以通过如下手段通知浏览器不要使用缓存
response.setDateHeader("Expires",0 );
response.setHeader("Cache-Control","no-cache");
response.setHeader("pragma","no-cache");
上传文件
首先准备上传页面 upload.html
上传页面有两点需要注意
1.form 的method必须是post的,get不能上传文件。 还需要加上enctype="multipart/form-data"
表示提交的数据是二进制文件
<form action="uploadPhoto" method="post" enctype="multipart/form-data">
2.需要提供type="file"
的字段进行上传
<!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<form action="uploadPhoto" method="post" enctype="multipart/form-data">
英雄名称:<input type="text" name="heroName" /> <br>
上传头像 : <input type="file" name="filepath" /> <br>
<input type="submit" value="上传">
</form>
接着准备 UploadPhotoServlet
在UploadPhotoServlet进行上传的功能开发。
1. 需要用到两个第三方的jar包,commons-io-1.4.jar和commons-fileupload-1.2.2.jar。并放在WEB-INF/lib下
2. 前部分代码是固定写法,用来做一些准备工作。 直到遍历出Item,一个Item就是对应一个浏览器提交的数据,通过item.getInputStream可以打开浏览器上传的文件的输入流。
3. 客户提交的文件名有可能是一样的,所以在服务端保存文件的时候,不能使用客户提交的文件名。这里使用的是一种粗糙的解决文件名重复的办法,即使用时间戳。
4. 读取输入流中的数据,保存在服务端的目录下 e:/project/j2ee/web/uploaded,这个目录是通过getRealPath获取到的。 如果项目部署在其他地方,那么会自动做相应的变化。
'注:' 为什么要放这里? 因为后续网页上显示的时候是通过http://127.0.0.1/uploaded/xxx.jpg 路径来获取图片。
5. 根据临时生成的文件名,创建一个html img元素,然后通过response返回浏览器
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class UploadPhotoServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) {
String filename = null;
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置上传文件的大小限制为1M
factory.setSizeThreshold(1024 * 1024);
List items = null;
try {
items = upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (!item.isFormField()) {
// 根据时间戳创建头像文件
filename = System.currentTimeMillis() + ".jpg";
//通过getRealPath获取上传文件夹,如果项目在e:/project/j2ee/web,那么就会自动获取到 e:/project/j2ee/web/uploaded
String photoFolder =request.getServletContext().getRealPath("uploaded");
File f = new File(photoFolder, filename);
f.getParentFile().mkdirs();
// 通过item.getInputStream()获取浏览器上传的文件的输入流
InputStream is = item.getInputStream();
// 复制文件
FileOutputStream fos = new FileOutputStream(f);
byte b[] = new byte[1024 * 1024];
int length = 0;
while (-1 != (length = is.read(b))) {
fos.write(b, 0, length);
}
fos.close();
} else {
System.out.println(item.getFieldName());
String value = item.getString();
value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
System.out.println(value);
}
}
String html = "<img width='200' height='150' src='uploaded/%s' />";
response.setContentType("text/html");
PrintWriter pw= response.getWriter();
pw.format(html, filename);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
配置web.xml
<servlet>
<servlet-name>UploadPhotoServlet</servlet-name>
<servlet-class>UploadPhotoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadPhotoServlet</servlet-name>
<url-pattern>/uploadPhoto</url-pattern>
</servlet-mapping>
在项目中导入jar包
把jar包导入到项目中,导包办法:右键 project->properties->java build path->libaries->add external jars
上传测试
重启tomcat, 打开页面进行上传
http://127.0.0.1/upload.html
选中某个图片点击上传
如何处理其他非File字段
因为浏览器指定了以二进制的形式提交数据,那么就不能通过常规的手段获取非File字段:
request.getParameter("heroName")
在遍历Item时(Item即对应浏览器提交的字段),可以通过
item.isFormField
来判断是否是常规字段还是提交的文件。 当item.isFormField返回true的时候,就表示是常规字段。
然后通过item.getFieldName()
和item.getString()
就知道分别是哪个字段,以及字段的值了。
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class UploadPhotoServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) {
String filename = null;
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置上传文件的大小限制为1M
factory.setSizeThreshold(1024 * 1024);
List items = null;
try {
items = upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (!item.isFormField()) {
// 根据时间戳创建头像文件
filename = System.currentTimeMillis() + ".jpg";
String photoFolder = "e:\\project\\j2ee\\web\\uploaded";
File f = new File(photoFolder, filename);
f.getParentFile().mkdirs();
// 通过item.getInputStream()获取浏览器上传的文件的输入流
InputStream is = item.getInputStream();
// 复制文件
FileOutputStream fos = new FileOutputStream(f);
byte b[] = new byte[1024 * 1024];
int length = 0;
while (-1 != (length = is.read(b))) {
fos.write(b, 0, length);
}
fos.close();
} else {
System.out.println(item.getFieldName());
String value = item.getString();
value = new String(value.getBytes("ISO-8859-1"), "UTF-8");
System.out.println(value);
}
}
String html = "<img width='200' height='150' src='uploaded/%s' />";
PrintWriter pw= response.getWriter();
pw.format(html, filename);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}