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

注意:

相关推荐
念言-ny12 小时前
springboot远程链接Hadoop
hadoop·spring boot·后端
马丁•路德•王13 小时前
Java测试开发平台搭建(八) Jenkins
java·servlet·jenkins
浩浩kids14 小时前
Hadoop•配置网络&克隆虚拟机
大数据·网络·hadoop
武子康17 小时前
大数据-267 实时数仓 - ODS Lambda架构 Kappa架构 核心思想
大数据·数据仓库·hive·hadoop·sql·架构·kafka
橘猫云计算机设计20 小时前
基于Django的旅游信息管理系统(源码+lw+部署文档+讲解),源码可白嫖!
java·大数据·hadoop·python·django·旅游
罗仲虎20 小时前
CDP集成Hudi实战-Hive
大数据·数据库·数据仓库·hive·hadoop
研究司马懿1 天前
【DevOps】Jenkins项目发布
servlet·jenkins·devops
阿年、嗯啊1 天前
MySQL和Hive中的行转列、列转行
数据库·hive·mysql·侧窗·行专列、列转行·hive侧窗列转行·构造map数据结构
leap_ruo2 天前
pyspark 执行group by操作 - 原始数据非hive
数据仓库·hive·hadoop
B站计算机毕业设计超人2 天前
计算机毕业设计PyHive+Hadoop深圳共享单车预测系统 共享单车数据分析可视化大屏 共享单车爬虫 共享单车数据仓库 机器学习 深度学习
大数据·hadoop·python·深度学习·机器学习·数据分析·数据可视化