Servlet 本身不能独立运行,需要在一个web应用中运行的
而一个web应用是部署在服务器中的,比如服务器tomcat。
1.获取参数
创建一个LoginServlet
因为浏览器中的form的method是post,所以LoginServlet需要提供一个doPost方法
在doPost方法中,通过request.getParameter 根据name取出对应的账号和密码
然后用System.out.println() 打印在控制台
本测试例子只是控制台输出,后面例子网页显示。
后台代码:LoginServlet 继承 HttpServlet
java
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 {
String name = request.getParameter("name");
String password = request.getParameter("password");
System.out.println("name:" + name);
System.out.println("password:" + password);
}
}
后台配置文件: web.xml
XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet> # 定义了一个名为 LoginServlet 的 Servle
<servlet-name>LoginServlet</servlet-name>
<servlet-class>LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
# Servlet 与 URL /login 进行绑定。用户访问 http://xx/login 时,LoginServlet 会处理该请求
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
前台文件login.html
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<form action="login" method="post">
账号: <input type="text" name="name"> <br>
密码: <input type="password" name="password"> <br>
<input type="submit" value="登录">
</form>
</body>
</html>
启动项目后,访问页面http://127.0.0.1/login.html 控制台会输出 账户、密码.
注意:前台action=login ,后台web配置中 <url-pattern>/login</url-pattern> ,再到对应的LoginServlet
2.返回响应
本次将数据返回给前台页面展示
要求:
判断账号、密码是否为 admin 、123,如果是就打印successful 否则就打印 fail
根据账号密码,创建对应的html字符串。
然后通过response.getWriter().println() 发送到浏览器。
注意:显示successful 不是中文,下个例子防止浏览器因中文显示乱码。
java
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 doPost(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'> Login Successful</div>";
else
html = "<div style='color:red'>Login Fail</div>";
PrintWriter pw = response.getWriter();
pw.println(html);
// 或者显示==========
out.println("<html><body>");
out.println("<h1>Login Successful</h1>");
out.println("</body></html>");
// ===========================
}
}
3.中文问题
为了成功获取中文参数,需要做如下操作
- login.html中加上
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
这句话的目的是告诉浏览器,等下发消息给服务器的时候,使用UTF-8编码
- login.html
form的method修改为post
- 在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()之前
通俗讲:字符串 小明 ,浏览器将其按规则A编码,后台获取后 也要按照规则A解码。
即编码、解码 规则一致就不会乱码【一般针对的是中文】。
login.html
html
<!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<form action="login" method="post">
账号 : <input type="text" name="name"> <br> 密码: <input
type="password" name="password"> <br> <input
type="submit" value="登录">
</form>
LoginServlet.java
java
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 该方法中统一设置解码
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
// byte[] bytes = name.getBytes("ISO-8859-1");
// name = new String(bytes, "UTF-8");
// 浏览器和网页编码的发展经历了几个阶段,ISO-8859-1、GBK 和 UTF-8 是其中非常关键的几个编码方式,它们代表了不同的历史阶段和全球化需求
String password = request.getParameter("password");
System.out.println("name:" + name);
// 返回中文的响应 ,也要设置
response.setContentType("text/html; charset=UTF-8");
PrintWriter pw = response.getWriter();
pw.println("登陆成功!");
}
}
response.setContentType("text/html; charset=UTF-8");
作用是设置 HTTP 响应的内容类型和字符编码。【告诉客户端(如浏览器)响应内容的类型以及它的字符编码】
text/html
:这是响应的 MIME 类型,表示响应内容是 HTML 文档。这意味着服务器将发送一个 HTML 页面,浏览器会将其渲染为网页。charset=UTF-8
:这部分指定了响应内容的字符编码为 UTF-8。UTF-8 是一种常见的字符编码,支持世界上几乎所有语言的字符。通过设置为 UTF-8,可以确保浏览器正确地解码和显示网页中的多语言内容,尤其是对于中文或其他非 ASCII 字符集的支持。
4.调用流程
还原一下经过:
1.客户发送http://127.0.0.1/login.html,打开静态页面,里面填写账户、密码 ,以POST方式提交到 /login 路径。
2.tomcat接收请求,http://127.0.0.1/login 与web配置文件匹配,找到对应的类LoginServlet。
3.tomcat发现没有LoginServlet存在,就调用无参构造方法实例化一个LoginServlet对象
4.tomcat拿到LoginServlet实例之后,根据方法类型 POST找到对应的doPost方法
5.通过request 获取参数,response 设置响应。
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 该方法中统一设置解码
request.setCharacterEncoding("UTF-8");
// 获取 姓名 密码
String name = request.getParameter("name");
String password = request.getParameter("password");
System.out.println("name:" + name);
PrintWriter pw = response.getWriter();
// 返回中文的响应 ,也要设置
response.setContentType("text/html; charset=UTF-8");
String result ="登陆成功!";
pw.println(result);
}
- tomcat 将 响应内容传递给浏览器。
在Servlet完成工作之后,tomcat拿到被Servlet修改过的response,根据这个response生成result字符串,然后再通过HTTP协议,把result字符串,回复给浏览器,浏览器再根据HTTP协议获取这个result字符串,并渲染在界面上。
5.生命周期
一个 Servlet 的生命周期由 Web 容器管理,主要包括 加载\实例化 、初始化 、请求处理\提供服务 和 销毁 四个阶段。
1.实例化-加载 反射
首次接收到请求时,Web 容器会根据配置文件(如 web.xml
)或注解(如 @WebServlet
)加载 Servlet 类,此时Servlet会被实例化。【只执行一次!Servlet是单例的!】可以无参构造中打印一条语句查看验证。
2.初始化 init()方法
LoginServlet 继承了HttpServlet,HttpServlet继承了GenericServlet。所以LoginServlet也继承了init(ServletConfig) 方法。
init 方法是一个实例方法,所以会在构造方法执行后执行。无论访问了多少次LoginSerlvet
init初始化 只会执行一次
3.请求处理\提供服务 service()方法
接下来就是执行service()方法,然后通过浏览器传递过来的信息进行判断,是调用doGet()还是doPost()方法来响应请求。
4.销毁 destroy()方法
当容器关闭或卸载 Servlet 时 ,调用 destroy()
方法。该方法用于释放 Servlet 使用的资源,如关闭数据库连接、释放文件句柄等
1.Servlet所在的web应用重启
<Context path="/" docBase="e:\\project\\j2ee\\web" debug="0" reloadable="false" />
如果把 reloadable="false" 改为reloadable="true" 就表示有任何类发生的更新,web应用会自动重启
当web应用自动重启的时候,destroy()方法就会被调用。【重启前先卸载容器内的servlet】
Web 应用自动重启通常发生在以下几种情况:
修改了 Web 应用的代码或资源:例如,修改了 JSP 文件、Servlet 类、配置文件等。许多 Web 容器(如 Tomcat)会检测到这些变化,并重新加载 Web 应用,这可能会导致容器卸载旧的 Servlet 并加载新的 Servlet。
容器重启:当 Web 容器本身重启时,所有的 Web 应用都会经历从初始化到销毁的生命周期。
部署新的版本:当你部署一个新的 Web 应用或更新现有的 Web 应用时,容器通常会先销毁旧的应用,再加载新的版本。
2.关闭tomcat的时候 destroy()方法会被调用,但是这个一般都发生的很快,不易被发现
6.跳转
页面跳转是开发一个web应用经常会发生的事情。比如登录成功或是失败后,分别会跳转到不同的页面。
跳转的方式有两种,服务端跳转和客户端跳转
首先在web目录下准备两个页面 success.html,fail.html
分别用于显示登录成功 或者登录失败
如果登录成功了,服务端跳转到success.html
如果登录失败了,客户端跳转到fail.html
|--------------------------------------------------------------------------|---------------------------------------------------------|
| success.html | fail.html |
|<``div
style``=``"color:green"``>login success</``div``>
|<``div
style``=``"color:red"``>login fail</``div``>
|
| request.getRequestDispatcher("success.html").forward(request, response); | response.sendRedirect("fail.html"); |
| 服务端跳转可以看到浏览器的地址依然是/login 路径,并不会变成success.html 仍是xx/login | 客户端跳转,浏览器地址发生了变化 原先地址xx/login变为了xx/fail.html |
javapublic 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"); } } }
7.自启动
有的时候会有这样的业务需求:
tomcat一启动,就需要执行一些初始化的代码,比如校验数据库的完整性等。
但是Servlet的生命周期是在用户访问浏览器对应的路径开始的。如果没有用户的第一次访问,就无法执行相关代码。怎么办?Servlet实现自启动
很简单:web.xml中添加 <load-on-startup>10</load-on-startup>
取值范围是1-99 数字越小,启动的优先级越高
即表明该Servlet会随着Tomcat的启动而初始化。
同时,为HelloServlet提供一个init(ServletConfig) 方法,验证自启动
html
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>LoginServlet</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
java
public class HelloServlet extends HttpServlet{
public void init(ServletConfig config){
System.out.println("init of Hello Servlet");
}
public void doGet(HttpServletRequest request, HttpServletResponse response){
try {
response.getWriter().println("<h1>Hello Servlet!</h1>");
response.getWriter().println(new Date().toLocaleString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
8.request常见方法
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
html<!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>
获取参数
request.getParameter(): 是常见的方法,用于获取单值的参数
request.getParameterValues(): 用于获取具有多值的参数,比如注册时候提交的 "hobits",可以是多选的。
request.getParameterMap(): 用于遍历所有的参数,并返回Map类型。
前台
html
<!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>
后台
java
public class RegisterServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("获取单值参数name:" + request.getParameter("name"));
// 前台type=checkbox 可多选,后台得到数组
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));
}
}
}
web.xml
html
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>LoginServlet</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>
</web-app>
9.获取头信息
request.getHeader() 获取浏览器传递过来的头信息。
比如getHeader("user-agent") 可以获取浏览器的基本资料,这样就能判断是firefox、IE、chrome、或者是safari浏览器
request.getHeaderNames() 获取浏览器所有的头信息名称,根据头信息名称就能遍历出所有的头信息
host: 主机地址
user-agent: 浏览器基本资料
accept: 表示浏览器接受的数据类型
accept-language: 表示浏览器接受的语言
accept-encoding: 表示浏览器接受的压缩方式,是压缩方式,并非编码
connection: 是否保持连接
cache-control: 缓存时限
javaimport java.io.IOException; import java.util.Date; import java.util.Enumeration; 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){ 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(); } } }
10.服务端传参
setAttribute和getAttribute可以用来在进行服务端跳转的时候,在不同的Servlet之间进行数据共享。
在 Servlet 中,可以通过多种方式将数据传递给客户端或在不同的请求间共享数据:
- 请求参数 (URL 参数、表单提交)可以通过
HttpServletRequest
获取。 - 会话数据 可以通过
HttpSession
进行传递。 - 全局数据 可以通过
ServletContext
共享。 - 请求转发 可以通过
RequestDispatcher
来传递数据并转发请求。
java
1. 通过 URL 参数传递数据 (GET 请求)
当客户端发送一个 GET 请求时,服务端可以通过 URL 参数传递数据。这些参数会附加在 URL 后面。
客户端请求:
<a href="myServlet?name=John&age=30">Click me</a>
服务端接收:
@WebServlet("/myServlet") 省去配置web.xml
public class MyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name"); // 获取 "name" 参数
String age = request.getParameter("age"); // 获取 "age" 参数
response.getWriter().write("Name: " + name + ", Age: " + age);
}
}
2. 通过表单提交数据 (POST 请求)
客户端也可以通过 HTML 表单提交数据到服务端。表单数据通常通过 POST 请求发送到指定的 URL。
客户端 HTML 表单:
<form action="myServlet" method="post">
<input type="text" name="username" />
<input type="password" name="password" />
<input type="submit" value="Submit" />
</form>
服务端接收:
@WebServlet("/myServlet")
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
response.getWriter().write("Username: " + username + ", Password: " + password);
}
}
3. 通过 HttpSession 传递数据
HttpSession 对象允许在多个请求之间存储数据,从而实现跨请求的数据传递。它通常用于在一个用户会话中保存数据。
设置 Session 数据:
@WebServlet("/setSession")
public class SetSessionServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("username", "John"); // 保存数据到 Session
response.getWriter().write("Session data set.");
}
}
获取 Session 数据:
@WebServlet("/getSession")
public class GetSessionServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username"); // 获取 Session 数据
response.getWriter().write("Session data: " + username);
}
}
4. 通过 ServletContext 传递数据
ServletContext 是一个全局对象,它可以在同一 Web 应用中的所有 Servlet 和 JSP 页面之间共享数据。不同的 Servlet 可以通过 ServletContext 存取全局范围的数据。
设置 ServletContext 数据:
@WebServlet("/setContext")
public class SetContextServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = getServletContext();
context.setAttribute("company", "TechCorp"); // 保存数据到 ServletContext
response.getWriter().write("ServletContext data set.");
}
}
获取 ServletContext 数据:
@WebServlet("/getContext")
public class GetContextServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = getServletContext();
String company = (String) context.getAttribute("company"); // 获取 ServletContext 数据
response.getWriter().write("ServletContext data: " + company);
}
}
5. 通过 RequestDispatcher 转发请求并传递数据
RequestDispatcher 用于请求转发,服务端可以通过 RequestDispatcher 将请求转发给另一个 Servlet,并传递请求数据。
请求转发并传递数据:
@WebServlet("/forwardRequest")
public class ForwardRequestServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("message", "Hello from the first servlet!");
RequestDispatcher dispatcher = request.getRequestDispatcher("/receiveRequest");
dispatcher.forward(request, response);
}
}
接收转发的请求:
@WebServlet("/receiveRequest")
public class ReceiveRequestServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String message = (String) request.getAttribute("message");
response.getWriter().write("Received message: " + message);
}
}
11.response 用法
response是HttpServletResponse的实例,用于提供给浏览器的响应信息
1.设置响应内容
PrintWriter pw= response.getWriter();
通过response.getWriter(); 获取一个PrintWriter 对象
可以使用println(),append(),write(),format()等等方法设置返回给浏览器的html内容。
pw.println(``"<h1>Hello Servlet</h1>"``);
2.
设置响应格式
response.setContentType("text/html");
"text/html" 是即格式 ,在request获取头信息 request获取头信息 中对应的request.getHeader("accept").
"text/html" 是存在的,表示浏览器可以识别这种格式,如果换一个其他的格式, 比如 "text/lol" ,浏览器不能识别,那么打开此servlet就会弹出一个下载的对话框。
3.设置响应编码
设置响应编码有两种方式
1. response.setContentType("text/html; charset=UTF-8");
设置字符编码,还设置了响应内容的类型 。浏览器在接收到该响应时,会根据
Content-Type
来判断该如何处理数据。**2. response.setCharacterEncoding("UTF-8");**只设置字符编码,不指定内容类型
这两种方式都需要在response.getWriter调用之前执行才能生效。
最佳实践:通常情况下,为了确保响应体在不同浏览器中都能正确显示,建议同时设置这两者。
4.设置不使用缓存
使用缓存可以加快页面的加载,降低服务端的负担。但是也可能看到过时的信息,可以通过如下手段通知浏览器不要使用缓存
``response.setDateHeader(``"Expires"``, ``0``);
// [
告诉浏览器响应内容已过期。]
``response.setHeader(``"Cache-Control"``, ``"no-cache"``);
//[
确保每次请求都验证缓存的有效性]
response.setHeader(``"pragma"``, ``"no-cache");
// [Pragma 头是 HTTP/1.0 中用于禁用缓存的头,它在较新的 HTTP/1.1 中被 Cache-Control 头取代,但为了兼容旧版浏览器,通常仍会一起使用。]
response.getWriter().println(``"<h1>Hello Servlet!</h1>"``);
``response.getWriter().println(``new
Date().toLocaleString());
12.上传文件
前台:
html
<!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<form action="uploadFile" method="post" enctype="multipart/form-data">
名称:<input type="text" name="name" /> <br>
上传 : <input type="file" name="filepath" /> <br>
<input type="submit" value="上传">
</form>
注意:
- form 的method必须是post的 ,get不能上传文件。 还需要加上enctype="multipart/form-data" 表示提交的数据是二进制文件
后台:
需要用到两个第三方的jar包,commons-io-1.4.jar和commons-fileupload-1.2.2.jar。 在右侧下载,并放在WEB-INF/lib下
java
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 和 ServletFileUpload 来解析上传的请求:
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 对象代表请求中的一个字段(可能是文件或表单数据)。
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
XML
<servlet>
<servlet-name>UploadFileServlet</servlet-name>
<servlet-class>UploadPhotoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadFileServlet</servlet-name>
<url-pattern>/uploadFile</url-pattern>
</servlet-mapping>
上传测试:
重启tomcat, 打开页面进行上传 http://127.0.0.1/upload.html
如何处理其他非File字段?
因为浏览器指定了以二进制的形式提交数据,那么就不能通过常规的手段获取非File字段:
request.getParameter("name")
在遍历Item时(Item即对应浏览器提交的字段),可以通过
item.isFormField true 是常规表单字段。
通过item.getFieldName()和item.getString()就知道分别是哪个字段,以及字段的值了。
13.Servlet无法配置Tomcat
主要针对Eclipse,idea自带内置服务器方便调试。
解决办法:定位到你自身安转的 盘:\project\.metadata\.plugins\org.eclipse.core.runtime\.settings
删除:
org.eclipse.wst.server.core.prefs
org.eclipse.jst.server.tomcat.core.prefs
删除后重启即可。
14.无法启动Tomcat
解决办法粗暴一点:菜单-Window->Show View->Other->Server->Servers 此时会出现如图所示的Tomcat v7.0 Server....
右键点击,选择Delete
然后再重新配置 通过Eclipse启动Tomcat-Run On Server 即可~
注意: