Request&Response

作者: 北冥有鱼_很好吃 | 来源:发表于2018-07-06 17:36 被阅读2次

    第一节 http请求协议

    浏览器访问服务器几种方式:(常用get/post)
    请求方式 请求说明
    OPTIONS 返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。
    HEAD 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息
    GET 向特定的资源发出请求(a href="servlet"标签/js location.href="servlet")
    POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改
    PUT 向指定资源位置上传其最新内容
    DELETE 请求服务器删除Request-URI所标识的资源
    TRACE 回显服务器收到的请求,主要用于测试或诊断
    CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
    HTTP请求的数据详解

    浏览器通过请求的协议,将数据发送给服务器.
    请求协议三部分: 请求行,请求头,请求体。
    请求行: 请求地址信息
    请求头: 浏览器信息以请求头形式发送给服务器 : key:value (key固定)
    请求体:用户数据

    get请求:只有请求行和请求头 数据以请求资源地址?拼接形式传递给服务器的  没有请求体!
    例如: http://192.168.21.100:8080/demo/aa?username=jack&password=1234
       <!-- get请求 -->
    <a href='http://localhost:8080/demo/a.html?name=lisi'>
     <img src='http://localhost:8080/demo/img/a.jpg'>
    <form action="a.html" method="get">
    

    post请求,由请求行和请求头和请求体组成, 数据以请求体形式提交!
    例如: http://192.168.21.100:8080/demo/aa
     <!-- post请求 -->
    <form action="bb" method="post">
    

    常见请求头汇总

    请求头key 请求头value
    referer 浏览器通知服务器,当前请求来自何处,如果是直接访问,则不会有这个头。常用于:防盗链
    If-modified-Since 浏览器通知服务器,本地缓存的最后变更时间。与另一个响应头组合控制浏览器页面的缓存。
    cookie 与会话有关技术,用于存放浏览器缓存的cookie信息。
    user-agent 浏览器通知服务器,客户端浏览器与操作系统相关信息
    connection 保持连接状态。Keep-Alive 连接中,close 已关闭
    host 请求的服务器主机名
    content-length 请求体的长度
    content-type 如果是POST请求,会有这个头,默认值为application/x-www-form-urlencoded,表示请求体内容使用url编码
    accept 浏览器可支持的MIME类型。文件类型的一种描述方式。
    mime格式 浏览器请求数据的类型,例如: text/html ,html文件 text/css,css文件 text/javascript,js文件 image/*,所有图片文件
    accept-encoding 浏览器通知服务器,浏览器支持的数据压缩格式。如:GZIP压缩
    accept-language 浏览器通知服务器,浏览器支持的语言。各国语言(国际化i18n)

    第二节 HttpServletRequest对象request学习

    • 通过request的api我们可以获取浏览器发送的请求行的数据

    1. String getMethod() 获取请求方式的类型
    2. String getRequestURI() 获取请求行中的资源名部分
    3. StringBuffer getRequestURL() 获取客户端发出请求完整URL
      说明: uri: 统一资源标识符,用来标识一个资源,资源路径。(相当于身份证) url: 统一资源定位符,是一种具体的URI,可以用来标识一个资源.并且指明了如何定位一个资源.(相当于身份证中的地址)
    4. String getProtocol() 获取当前协议的名称和版本
    5. String getRemoteAddr() 获取IP地址6. int getLocalPort() 获取端口
    • 请求头的组成元素(通过request获取请求头信息)

    @WebServlet(name = "DemoServlet2",urlPatterns = "/demo2")
    public class DemoServlet2 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 {
            /**
            * 1. String getHeader(String name)
            以 String 的形式返回指定请求头的值
            * */
            String header = request.getHeader("User‐Agent");
            System.out.println("getHeader:"+header);
            System.out.println();
            /**
            * 2. Enumeration getHeaderNames()
            返回此请求包含的所有头名称的枚举
            * */
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()){
            System.out.println("getHeaderNames:"+headerNames.nextElement());
         }
        }
    } 
    测试结果: 
    getHeader:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
    Chrome/63.0.3239.132 Safari/537.36    
    getHeaderNames:host
    getHeaderNames:connection
    getHeaderNames:cache‐control
    getHeaderNames:user‐agent
    getHeaderNames:upgrade‐insecure‐requests
    getHeaderNames:accept
    getHeaderNames:accept‐encoding
    getHeaderNames:accept‐language
    getHeaderNames:cookie
    
    • Request接收请求数据(***)

    方法名 描述
    String getParameter(String name) getParameter获得指定参数名对应的值。如果没有返回null,如果只有多个获得第一个。 例如:username=jack
    String[] getParameterValues(name) getParameterValues[] 获取请求数据key相同的多个数据
    /**
     *   方法封装  类封装  原子性   单一 原则
     */
    @WebServlet("/requestServlet")
    public class RequestServlet 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 {
            String username = request.getParameter("username");//  获取用户提交用户名信息
            String[] hobbies = request.getParameterValues("hobby");//
            System.out.println("用户名 = "+username);
            System.out.println("兴趣爱好:"+ Arrays.toString(hobbies));
    
        }
    }
    
    • Request的其他作用 (*)

    String getContextPath() 获取应用程序名称
    通常情况,工程名称=发布的应用程序名称。
    如果应用程序名称发生改变,那么我们如何获取呢? 通过getContextPath()可以获取发布的应用程序名称。

    第三节 HttpServletResponse对象response学习

    状态码:服务器与浏览器用于确定状态的固定数字号码,数字用来表示服务器针对请求做出的响应的状态,常见的响应状态码:

        302 Move temporarily 重定向,请求的资源临时从不同的 URI响应请求。
    
        304 Not Modified 从缓存中读取数据,不从服务器重新获取数据
    
        404 :请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。
        
        403 Forbidden 服务器已经理解请求,但是拒绝执行它
        
        405 Method Not Allowed 请求行中指定的请求方法不能被用于请求相应的资源
    
        500 :服务器内部错误。通常程序抛异常。
    
    • 响应头 (key:value形式)

    响应头Key 响应头value
    location 指定响应的路径,需要与状态码302配合使用,完成跳转。
    content-Type 响应正文的类型(MIME类型)例如:text/html;charset=UTF-8
    content-disposition 通过浏览器以附件形式解析正文,例如:attachment;filename=xx.zip
    set-cookie 与会话相关技术。服务器向浏览器写入cookie
    content-encoding 服务器使用的压缩格式,例如:gzip
    content-length 响应正文的长度
    refresh 页面刷新,例如:3;url=www.itcast.cn //三秒刷新页面到www.itcast.cn
    server 指的是服务器名称,默认值:Apache-Coyote/1.1
    last-modified 服务器通知浏览器,文件的最后修改时间。与If-Modified-Since一起使用。

    Response常见方法:

    addCookie(Cookie cookie):这个方法是向Response容器中添加一个Cookie,然后服务器容器会自动的将这个Cookie回写给客户机的,至于Cookie的相关知识我们会在后面的文章中进行详解,这篇文章中这个方法暂时用不到。
    
    addDateHeader(String name ,long date):这个是向客户机添加一个时间值属性的响应头信息,比如那个缓存的响应头expires
    
    addHeader(String name,String value):这个是向客户机添加一个字符串值属性的响应头信息,比如重定向的响应头location
    
    addIntHeader(String name ,int value):这个是向客户机添加一个字符串属性的响应头信息
    
    containsHeader(String name):这个方法是判断是否含有这个响应头信息字段
    
    encodeURL(String name):这个方法是用于url改写的功能的,这个和session有关,等到说session那篇文章的时候在详细说明
    
    sendRedirect(String name):这个方法是用于请求重定向的,和响应头中的location字段的作用相同
    
    setHeader(String name,String value)/setIntHeader(String name,int value)/setDateHeader(String name,long date):这些方法和addHeader方法是相对应的,唯一和addHeader不同的是,addHeader是向Response中添加一个响应头信息,而setHeader是修改一个响应头信息的。
    
    setStatus(int value):通过这个方法是设置响应码的,比如:200,304,404等。
    
    getOutputStream():通过这个方法可以拿到一个字节流,然后可以向Response容器中写入字节数据,最后客户机向Response容器中拿去数据进行显示
    
    getWriter():通过这个方法可以拿到一个字符流(PrintWriter),然后可以向Response容器中写入字符数据,最后客户机向Response容器中拿去数据进行显示
    
    setContentLength():通过这个方法设置服务器向用户返回的数据长度,我们在HTTP协议详解这篇blog中的那个压缩数据的返回的例子中有说到
    
    setContentType():方法可以直接设置响应头content-type的内容
    
    • 转发和重定向的区别

    1. 转发在一次请求中完成,重定向是两次请求
    2. 转发操作发生在服务器内部,重定向是浏览器执行操作
    3. 转发地址栏不变(只有一次请求,一个地址),重定向,地址栏变化(两次请求,两个地址)
    4. 转发可以在一次请求中共享数据,重定向不行(重定向两次请求)
    
    1530781134215.png
    @WebServlet("/loginServlet")
    public class LoginServlet 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 {
    
            request.setCharacterEncoding("utf-8");
            //  1. 只对post提交数据有效 请求体数据有效 2.必须要request.getParameter之前执行
    
            //  1.获取用户名和密码
            response.setContentType("text/html;charset=utf-8");//  text/plain  .txt  text/xml  xml   text/html   text/json  ajax
            //  获取输出流 向浏览器发送数据
            PrintWriter out = response.getWriter();
            String name = request.getParameter("name");
            String password = request.getParameter("password");
            System.out.println("用户名 = " + name);
            //  2.访问数据库
            String sql = "select * from users where name = ? and password = ?";
            JdbcTemplate template = new JdbcTemplate(C3p0Utils.getDataSource());
            User existUser = null;
            try {
                //  单一原则  查不到对象template报运行错误
                existUser = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), name, password);
            } catch (DataAccessException e) {
                e.printStackTrace();
            }
            //  3. 查询结果   转发和重定向处理
            if (existUser == null) {
               //  response.sendRedirect("login.html");
                //  转发完成登录错误 信息提示    request绑定一个错误信息  key  login_error
                request.setAttribute("login_error","账号或密码错误");
                //  跳转到显示登录错误信息的servlet
            request.getRequestDispatcher("/loginErrorServlet").forward(request,response);
            } else {
    //        response.setStatus(302);
    //  服务器发送给浏览器状态码 302  浏览器接受302  向location地址发送新的请求
    //        response.setHeader("Location","index.html");
    // 这行代码相当于上面两行
                response.sendRedirect("index.html");
            }
        }
    }
    
    @WebServlet("/loginErrorServlet")
    public class LoginErrorServlet 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 {
            //  登录错误显示处理
            PrintWriter out = response.getWriter();
            out.print("<html>");
            String errorinfo = (String)request.getAttribute("login_error");
            //  request绑定错误信息获取
            out.print("<font color='red'>"+errorinfo+"</font>");
            out.print("<form action='loginServlet' method='post'>");
            out.print("用户名<input type='text' name='name'><br>");
            out.print("密码<input type='password' name='password'><br>");
            out.print("<input type='submit' value='登录'>");
            out.print("</form>");
            out.print("<html>");
        }
    }
    

    案例-Response对象完成下载服务器资源

    • 关于工程目录结构的说明


      工程目录结构.PNG
    @WebServlet(name = "loadServlet", urlPatterns = "/loadServlet")
    public class LoadServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            //获取浏览器提交过来的文件名
            String filename = request.getParameter("filename");
            //获取服务器资源位置 : 通过ServletContext对象    一个流两个头:附件弹窗头/文件类型头
            ServletContext servletContext = getServletContext();
            //获取资源的绝对路径
            String realPath = servletContext.getRealPath("/WEB-INF/"+filename);
            //创建文件对象,如果对象存在,那么则输出
            File file = new File(realPath);
            if(file.exists()){
                //设置响应头"下载附件弹窗"
               //  attachment 附件形式   inline 浏览器直接打开的资源
                response.setHeader("content-disposition","attachment;filename="+filename);
                // 根据文件名扩展名 获取文件对应的Mime类型  然后将文件类型告诉response
                String mime = servletContext.getMimeType(filename);
                response.setContentType(mime);
                //创建一个response的输出流
                ServletOutputStream os = response.getOutputStream();
                //创建文件的输入流 内存->程序
                InputStream in = new FileInputStream(file);
                int len = -1;
                byte[] bytes = new byte[1024*4];
                while((len=in.read(bytes))!=-1){
                    os.write(bytes,0,len);
                }
                in.close();
            }
        }
    
    关于下载时文件名乱码的处理
     response.setHeader("Content-Disposition","attachment;filename="+new String(filename.getBytes("gbk"), "ISO8859-1"));
    

    相关文章

      网友评论

        本文标题:Request&Response

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