Servlet

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.中文问题

为了成功获取中文参数,需要做如下操作

  1. login.html中加上

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

这句话的目的是告诉浏览器,等下发消息给服务器的时候,使用UTF-8编码

  1. login.html

form的method修改为post

  1. 在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);

}

  1. 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 应用自动重启通常发生在以下几种情况:

  1. 修改了 Web 应用的代码或资源:例如,修改了 JSP 文件、Servlet 类、配置文件等。许多 Web 容器(如 Tomcat)会检测到这些变化,并重新加载 Web 应用,这可能会导致容器卸载旧的 Servlet 并加载新的 Servlet。

  2. 容器重启:当 Web 容器本身重启时,所有的 Web 应用都会经历从初始化到销毁的生命周期。

  3. 部署新的版本:当你部署一个新的 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 |

java 复制代码
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");
        }
 
 
    }

}

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: 缓存时限

java 复制代码
import 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>

注意:

  1. 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 即可~

注意:

相关推荐
计算机毕业编程指导师18 分钟前
【Python毕设选题推荐】基于Hadoop+Django的奥斯卡奖获奖数据可视化分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习 深度学习
大数据·hadoop·python·计算机·毕业设计·课程设计·奥斯卡奖
计算机毕业编程指导师25 分钟前
【大数据毕设选题】基于Spark的电信网络诈骗话术语义特征挖掘分析系统源码 毕业设计 选题推荐 数据分析 机器学习 深度学习
大数据·hadoop·python·spark·毕业设计·课程设计·网络诈骗
计算机毕业编程指导师31 分钟前
计算机大数据毕设怎么选?基于Spark的个体肥胖健康风险评估的数据分析与可视化系统带你通关 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·计算机·spark·毕业设计·肥胖风险
shjita37 分钟前
几个hadoop中运行mapreduce的错误记录一下。
大数据·hadoop·eclipse
计算机毕业编程指导师2 小时前
计算机毕设答辩技巧:基于Hadoop+Django的公共交通运营数据分析与可视化系统怎么做 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·spark·毕业设计·课程设计·交通运行
计算机毕业编程指导师2 小时前
【计算机毕设选题推荐】基于Hadoop+Django高频电力消耗大数据分析系统从0到1 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
hadoop·python·数据分析·spark·毕业设计·课程设计·电力
计算机毕业编程指导师2 小时前
【计算机毕设选题推荐】基于Spark的多源影视数据整合质量评估与可视化分析系统全解析 源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·计算机·数据分析·spark·影视
卷毛迷你猪19 小时前
快速实验篇(B07 )Session 会话化与序列
大数据·hive·hadoop
卷毛迷你猪19 小时前
快速实验篇(B08)搜索词分析实战
大数据·hive·hadoop
计算机源码社1 天前
基于Spark的租房数据挖掘与可视化平台构建研究 基于K-Means与PCA的租房价值洞察与可视化分析
大数据·hadoop·数据挖掘·spark·毕业设计·kmeans·课程设计