民工心事 发表于 2025-1-4 18:37:40

Servlet

Servlet 本身不能独立运行,需要在一个web应用中运行的
而一个web应用是摆设在服务器中的,比如服务器tomcat。
1.获取参数

创建一个LoginServlet
因为浏览器中的form的method是post,所以LoginServlet需要提供一个doPost方法
在doPost方法中,通过request.getParameter 根据name取出对应的账号和密码
然后用System.out.println() 打印在控制台
本测试例子只是控制台输出,后面例子网页显示。
后台代码:LoginServlet  继承  HttpServlet
https://i-blog.csdnimg.cn/direct/3cbe6a3b8c4641619dce7b0577b6a1cd.png
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 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
<!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 不是中文,下个例子防止浏览器因中文显示乱码。
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编码

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()之前
 
通俗讲:字符串  小明  ,浏览器将其按规则A编码,后台获取后 也要按照规则A解码。
即编码、解码 规则一致就不会乱码【一样平常针对的是中文】。
login.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
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.调用流程

https://i-blog.csdnimg.cn/direct/ae2368bdbb754dfab32220fc140b964f.png
https://i-blog.csdnimg.cn/direct/e0a6a695f53b4e44b75a9816eae55977.png
还原一下颠末:
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);
    }
6. 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.htmlfail.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.htmlpublic 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");
      }


    }

}https://i-blog.csdnimg.cn/direct/c1550941f7f041ca9a62972f942780ec.png
7.自启动

有的时候会有如许的业务需求:
tomcat一启动,就需要实行一些初始化的代码,比如校验数据库的完备性等。
但是Servlet的生命周期是在用户访问浏览器对应的路径开始的。如果没有用户的第一次访问,就无法实行相关代码。怎么办?Servlet实现自启动
很简单:web.xml中添加     <load-on-startup>10</load-on-startup>
取值范围是1-99   数字越小,启动的优先级越高

即表明该Servlet会随着Tomcat的启动而初始化。

同时,为HelloServlet提供一个init(ServletConfig) 方法,验证自启动
<?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> 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
<!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类型。
前台
<!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>

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

 
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();
                }
        }
       
}
https://i-blog.csdnimg.cn/direct/4343dacf9a8f40ef8a9be87a0df16ac6.png
10.服务端传参

setAttribute和getAttribute可以用来在进行服务端跳转的时候,在不同的Servlet之间进行数据共享。
在 Servlet 中,可以通过多种方式将数据传递给客户端或在不同的请求间共享数据:


[*]请求参数(URL 参数、表单提交)可以通过 HttpServletRequest 获取。
[*]会话数据可以通过 HttpSession 进行传递。
[*]全局数据可以通过 ServletContext 共享。
[*]请求转发可以通过 RequestDispatcher 来传递数据并转发请求。
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");//
  response.getWriter().println("<h1>Hello Servlet!</h1>");
  response.getWriter().println(new Date().toLocaleString());
12.上传文件

前台:
<!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下
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;
                  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>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")
https://i-blog.csdnimg.cn/direct/f845191851cb41509fc50f76ad6ddeef.png
在遍历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
https://i-blog.csdnimg.cn/direct/a4dcddd1d9c44a51bd66fa2e221da3c0.png删除后重启即可。
14.无法启动Tomcat

办理办法粗暴一点:菜单-Window->Show View->Other->Server->Servers 此时会出现如图所示的Tomcat v7.0 Server....
右键点击,选择Delete
然后再重新配置 通过Eclipse启动Tomcat-Run On Server 即可~
留意:

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Servlet