请求

HttpServletRequest

public interface HttpServletRequest extends ServletRequest {
    String BASIC_AUTH = "BASIC";
    String FORM_AUTH = "FORM";
    String CLIENT_CERT_AUTH = "CLIENT_CERT";
    String DIGEST_AUTH = "DIGEST";

    String getAuthType();

    Cookie[] getCookies();

    long getDateHeader(String var1);

    String getHeader(String var1);

    Enumeration<String> getHeaders(String var1);

    Enumeration<String> getHeaderNames();

    int getIntHeader(String var1);

    String getMethod();

    String getPathInfo();

    String getPathTranslated();

    String getContextPath();

    String getQueryString();

    String getRemoteUser();

    boolean isUserInRole(String var1);

    Principal getUserPrincipal();

    String getRequestedSessionId();

    String getRequestURI();

    StringBuffer getRequestURL();

    String getServletPath();

    HttpSession getSession(boolean var1);

    HttpSession getSession();

    String changeSessionId();

    boolean isRequestedSessionIdValid();

    boolean isRequestedSessionIdFromCookie();

    boolean isRequestedSessionIdFromURL();

    /** @deprecated */
    boolean isRequestedSessionIdFromUrl();

    boolean authenticate(HttpServletResponse var1) throws IOException, ServletException;

    void login(String var1, String var2) throws ServletException;

    void logout() throws ServletException;

    Collection<Part> getParts() throws IOException, ServletException;

    Part getPart(String var1) throws IOException, ServletException;

    <T extends HttpUpgradeHandler> T upgrade(Class<T> var1) throws IOException, ServletException;
}
当HTTP请求由Web容器处理时,Web容器会对其进行数据采集并封装在HttpServletRequest对象中,所以我们可以通过HttpServletRequest来获取HTTP中的信息,示例代码如下:
/**
 * 该Serlvet主要是为了获取Http请求中的数据
 */
public class HttpRequestContextServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // URL:http://localhost:8080/learnServlet/getHttpRequestContext?name=niezhic&age=23

        // 获取特定的请求参数值
        System.out.println(request.getParameter("name"));// niezhic

        // 这个方法原来是为了获取,像复选框checkbox这类同一个请求参数名对应多个值的情况,这样就是一个数组了
        request.getParameterValues("");

        // 获取所有请求参数名称
        Enumeration<String> params = request.getParameterNames();// name、age
        while (params.hasMoreElements()){
            String param = params.nextElement();
            System.out.println(param);
        }

        // 获取请求头中的信息
        Enumeration<String> headers = request.getHeaderNames();// accept、accept-language、user-agent、accept-encoding、host、connection、cookie
        while (headers.hasMoreElements()){
            String head = headers.nextElement();
            System.out.println(head + ":" + request.getHeader(head));// 获取请求头名称和请求头值
        }
    }
}
如果请求头的值是个整数或日期则可以用getIntHeader()或getDateHeader()分别转换为int和Date
请求编码的处理
/**
 * 对于请求参数处理的Servlet,GET和POST处理的方式不同
 */
public class EncodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 该方法只对请求体中的请求参数有效,所以只用于POST,不过要在获取请求之前声明
        request.setCharacterEncoding("utf-8");
        String name = request.getParameter("username");

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getParameter("username");
        // GET中采用这种方法来处理请求参数的编码
        String name = new String(request.getParameter("username").getBytes("iso-8859-1"), "utf-8");
    }
}
当然,在实际的项目中比如SpringMVC项目,只需要在web.xml配置一个过滤器就搞定请求编码的处理
读取请求体的中内容
先看提交的form表单:
<form action="/learnServlet/requestBodyServlet" method="post">
  用户名:<input name="username" value="聂置纯"/>
  <br/>
  密码:<input type="password" name="password" value="niezhicisgod"/>
  <br/>
  <input type="submit" />
</form>
再看处理的Servlet:
/**
 * 获取请求体中内容的Servlet
 */
public class RequestBodyServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // getReader()获取请求体中的内容
        BufferedReader read = request.getReader();
        String in = "";
        String requestBody = "";
        while ((in = read.readLine()) != null) {
            requestBody += in + "<br/>";
        }
        PrintWriter out = response.getWriter();
        out.print(requestBody);// username=%E8%81%82%E7%BD%AE%E7%BA%AF&password=niezhicisgod
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}
当上传文件的时候,先处理form表单如下:
<form action="/learnServlet/uploadServlet" method="post" enctype="multipart/form-data">
  选择文件:<input type="file" name="filename" />
  <input type="submit" name="upload" />
</form>
此时的Servlet如下:
/**
 * 用于上传文件的Servlet
 */
public class UpLoadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1、获取请求体
        byte[] body = readBody(request);

        // 2、将请求体内容以字符串表示
        String txtBody = new String(body, "utf-8");

        // 3、取得上传文件的名称
        String fileName = getFileName(txtBody);

        // 4、取得文件开始与结束位置
        Position position = getFilePosition(request, txtBody);

        // 5、输出至文件
        writeTo(fileName, body, position);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    /**
     * 定义文件开始与结束的位置的内部类
     */
    class Position {
        int begin;
        int end;

        public Position(int begin, int end) {
            this.begin = begin;
            this.end = end;
        }
    }

    private void writeTo(String fileName, byte[] body, Position position) throws IOException {
        FileOutputStream out = new FileOutputStream("d:" + fileName);
        out.write(body, position.begin, (position.end - position.begin));
        out.flush();
        out.close();

    }

    private Position getFilePosition(HttpServletRequest request, String txtBody) throws UnsupportedEncodingException {
        String contentType = request.getContentType();
        String boundaryTxt = contentType.substring(contentType.lastIndexOf("=") + 1, contentType.length());

        int pos = txtBody.indexOf("fileName=\"");
        pos = txtBody.indexOf("\n", pos) + 1;
        pos = txtBody.indexOf("\n", pos) + 1;
        pos = txtBody.indexOf("\n", pos) + 1;

        int boundaryLoc = txtBody.indexOf(boundaryTxt, pos) - 4;
        int begin = ((txtBody.substring(0, pos)).getBytes("utf-8")).length;
        int end = ((txtBody.substring(0, boundaryLoc)).getBytes("utf-8")).length;
        return new Position(begin, end);

    }

    private String getFileName(String txtBody) {
        String fileName = txtBody.substring(txtBody.indexOf("filename=\"") + 10);

        fileName = fileName.substring(0, fileName.indexOf("\n"));
        fileName = fileName.substring(fileName.lastIndexOf("\\") + 1, fileName.indexOf("\""));

        return fileName;
   }

    private byte[] readBody(HttpServletRequest request) throws IOException {
        int fileSize = request.getContentLength();
        DataInputStream in = new DataInputStream(request.getInputStream());// 上传文件时,文件是以流的形式存在request中的

        byte[] body = new byte[fileSize];
        int totalByte = 0;
        while (totalByte < fileSize) {
            int bytes = in.read(body, totalByte, fileSize);
            totalByte += bytes;
        }

        return body;
    }
}

Servlet3.0中上传文件

在Servlet3.0中,新增了Part接口,可以方便的对文件进行上传操作,进行上传操作时,可以使用request.getPart()取得上传文件数据
public interface Part {
    InputStream getInputStream() throws IOException;

    String getContentType();

    String getName();

    String getSubmittedFileName();

    long getSize();

    void write(String var1) throws IOException;

    void delete() throws IOException;

    String getHeader(String var1);

    Collection<String> getHeaders(String var1);

    Collection<String> getHeaderNames();
}
此时的上传文件Servlet示例代码如下:
/**
 * Servlet3.0中用于上传文件的Servlet
 */
@MultipartConfig // 必须设置该注解才能使用getPart()等相关方法,该注解还有一些非常好用的属性
public class UpLoadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 0、上传的文件名称可能包含中文
        request.setCharacterEncoding("utf-8");

        // 1、获取Part对象
        Part part = request.getPart("upFile");

        // 2、取得上传文件的名称
        String fileName = getFileName(part);

        // 5、输出至文件
        writeTo(fileName, part);
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    /**
     * 当在 @MultipartConfig 注解中设置了location 输出文件目录,
     * 就可以直接使用part.write(filename)方法,无需自定义writeTo()方法了
     */
    private void writeTo(String fileName, Part part) throws IOException {
        InputStream in = part.getInputStream();
        OutputStream out = new FileOutputStream(fileName + "TEMP");
        byte[] buffer = new byte[1024];
        int length = -1;
        while((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length);
        }
        in.close();
        out.close();
    }

    private String getFileName(Part part) {
        String head = part.getHeader("Content-Disposition");
        String fileName = head.substring(head.indexOf("filename=\"") + 10, head.lastIndexOf("\""));
        return  fileName;
    }

}
@MultipartConfig注解,有一些属性如下:

1. location:设置写入文件时的目录,默认为空字符串;当设置了该属性,就可以使用Part中默认的write()方法输出文件了
2. maxFileSize:限制上传文件的大小,默认值为-1L,表示不限制大小
3. maxRequestSize:限制multipart/form-data请求个数,默认值为-1L,表示不限制个数
4. ....
同时上传多个文件时,此时的form表单:
<form action="/learnServlet/upLoadServlet" method="post" enctype="multipart/form-data">
  选择文件1:<input type="file" name="upFile1" />
  选择文件2:<input type="file" name="upFile2" />
  选择文件3:<input type="file" name="upFile3" />
  <input type="submit" name="upload" />
</form>
可以使用request.getParts()方法,此时的Servlet:
/**
 * Servlet3.0中用于上传多个文件的Servlet
 */
@MultipartConfig // 必须设置该注解才能使用getPart()等相关方法,该注解还有一些非常好用的属性
public class UpLoadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 0、上传的文件名称可能包含中文
        request.setCharacterEncoding("utf-8");

        // 1、多个上传文件时,使用request.getParts方法
        for (Part part:request.getParts()) {
            String fileName = getFileName(part);
            if(StringUtils.isNotBlank(fileName)) {
                writeTo(fileName, part);
            }
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    /**
     * 当在 @MultipartConfig 注解中设置了location 输出文件目录,
     * 就可以直接使用part.write(filename)方法,无需自定义writeTo()方法了
     */
    private void writeTo(String fileName, Part part) throws IOException {
        InputStream in = part.getInputStream();
        OutputStream out = new FileOutputStream(fileName + "TEMP");
        byte[] buffer = new byte[1024];
        int length = -1;
        while((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length);
        }
        in.close();
        out.close();
    }

    private String getFileName(Part part) {
        String head = part.getHeader("Content-Disposition");
        String fileName = head.substring(head.indexOf("filename=\"") + 10, head.lastIndexOf("\""));
        return  fileName;
    }

}
@MultipartConfig注解当然也可以在web.xml中进行配置
<servlet>
    <servlet-name>UpLoadServlet</servlet-name>
    <servlet-class>isgod.niezhic.servlet.UpLoadServlet</servlet-class>
    <multipart-config>
        进行相关属性配置,如location
    </multipart-config>
</servlet>
<servlet-mapping>
    <servlet-name>UpLoadServlet</servlet-name>
    <url-pattern>/upLoadServlet</url-pattern>
</servlet-mapping>
使用RequestDispatcher调派请求
在web应用中,经常需要多个Servlet来完成请求。例如,将另一个Servlet的请求处理使用include()包含进来,或将请求通过forward()转发给别的Servlet处理。这两个方法都在RequestDispathcer接口中,可以通过request.getRequestDispatcher()方法来获取到这个接口的实例。
public interface RequestDispatcher {
    String FORWARD_REQUEST_URI = "javax.servlet.forward.request_uri";
    String FORWARD_CONTEXT_PATH = "javax.servlet.forward.context_path";
    String FORWARD_PATH_INFO = "javax.servlet.forward.path_info";
    String FORWARD_SERVLET_PATH = "javax.servlet.forward.servlet_path";
    String FORWARD_QUERY_STRING = "javax.servlet.forward.query_string";
    String INCLUDE_REQUEST_URI = "javax.servlet.include.request_uri";
    String INCLUDE_CONTEXT_PATH = "javax.servlet.include.context_path";
    String INCLUDE_PATH_INFO = "javax.servlet.include.path_info";
    String INCLUDE_SERVLET_PATH = "javax.servlet.include.servlet_path";
    String INCLUDE_QUERY_STRING = "javax.servlet.include.query_string";
    String ERROR_EXCEPTION = "javax.servlet.error.exception";
    String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type";
    String ERROR_MESSAGE = "javax.servlet.error.message";
    String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";
    String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";
    String ERROR_STATUS_CODE = "javax.servlet.error.status_code";

    void forward(ServletRequest req, ServletResponse resp) throws ServletException, IOException;

    void include(ServletRequest req, ServletResponse resp) throws ServletException, IOException;
}

使用include()方法示例代码,如下:

public class OutServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 解决中文字符以 锛氱幇鍦 的乱码格式
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        // 解决中文字符以 ???? 的乱码格式
        response.setCharacterEncoding("utf-8");

        PrintWriter out = response.getWriter();
        out.print("outServlet:现在将要演示包含其他请求处理的方法include(),当然我还会给他一个惊喜");

        // 当要传递对象给inServlet时,可以使用request.setAttribute()方法,通过setAttribute()方法设置的属性被称为请求范围属性,因为只适用于当前请求,当要删除每个属性时,可以通过removeAttribute()方法删除指定属性        request.setAttribute("user",new User("我是一个妹纸", 23));

        // 将inServlet的请求处理流程包含进来,
        // 还可以包含inServlet请求参数,如request.getRequestDispatcher("inServlet?username=niezhicisgod")
        RequestDispatcher disp = request.getRequestDispatcher("inServlet");
        disp.include(request,response);

        out.close();
    }
}
public class InServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 解决中文字符以 锛氱幇鍦 的乱码格式
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        // 解决中文字符以 ???? 的乱码格式
        response.setCharacterEncoding("utf-8");

        PrintWriter out = response.getWriter();
        out.print("inServlet:咦...大家好,没想到以这种方式和大家见面了。额,没想到outServlet还送了妹纸给我,我好喜欢");

        // 获取同一个请求对象生命周期中的设置的对象
        User user = (User) request.getAttribute("user");
        out.print(user);

        // RequestDispatcher该接口中还定义了和include()相关的常量:
        // INCLUDE_REQUEST_URI = "javax.servlet.include.request_uri"; 表示上一个Servlet的请求URL,不过在include中没有上一个Servlet这种说法
        // INCLUDE_CONTEXT_PATH = "javax.servlet.include.context_path"; 表示上一个Servlet的上下文路径,不过在include中没有上一个Servlet这种说法
        // INCLUDE_PATH_INFO = "javax.servlet.include.path_info"; 表示上一个Servlet的路径信息,不过在include中没有上一个Servlet这种说法
        // INCLUDE_SERVLET_PATH = "javax.servlet.include.servlet_path"; 表示上一个Servlet的路径,不过在include中没有上一个Servlet这种说法
        // INCLUDE_QUERY_STRING = "javax.servlet.include.query_string"; 表示上一个Servlet的请求参数,不过在include中没有上一个Servlet这种说法
        String url = (String) request.getAttribute("javax.servlet.include.request_uri");
        out.print(url);

        out.close();
    }
}

使用forward()方法示例代码,如下:

public class FrontServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 解决中文字符以 锛氱幇鍦 的乱码格式
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        // 解决中文字符以 ???? 的乱码格式
        response.setCharacterEncoding("utf-8");

        request.setAttribute("user",new User("一个妹纸", 23));

        // 请求转发操作时,当前Servlet不能进行响应确认否则报错
        RequestDispatcher disp = request.getRequestDispatcher("backServlet");
        disp.forward(request,response);

    }
}
public class BackServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        PrintWriter out = response.getWriter();
        out.print("backServlet:frontServlet说要介绍一个妹纸给我,他自己也还是单身,却为我着想,我好感动");

        // 获取同一个请求对象生命周期中的设置的对象
        User user = (User) request.getAttribute("user");
        out.print(user);

        // RequestDispatcher该接口中还定义了和forward()相关的常量:
        // FORWARD_REQUEST_URI = "javax.servlet.forward.request_uri"; 表示上一个Servlet的请求URL
        // FORWARD_CONTEXT_PATH = "javax.servlet.forward.context_path";
        // FORWARD_PATH_INFO = "javax.servlet.forward.path_info";
        // FORWARD_SERVLET_PATH = "javax.servlet.forward.servlet_path";
        // FORWARD_QUERY_STRING = "javax.servlet.forward.query_string";
        // url = (String) request.getAttribute("javax.servlet.include.request_uri");
        String url = (String) request.getAttribute("javax.servlet.forward.request_uri");
        out.print(url);// learnServlet/frontServlet


    }
}
在使用转发请求操作时,当前的Servlet不能有任何响应确认,否则会抛出IllegalStateException;这里的响应确认是指客户端接收到响应的内容了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容