请求

作者: pilipalaboompow | 来源:发表于2016-05-15 19:36 被阅读0次

    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;这里的响应确认是指客户端接收到响应的内容了

    相关文章

      网友评论

          本文标题:请求

          本文链接:https://www.haomeiwen.com/subject/qqgvrttx.html