JavaWeb之Request请求和Response响应

admin 2024年9月25日23:28:56评论7 views字数 8938阅读29分47秒阅读模式
声明:请勿利用本公众号文章内的相关技术、工具从事非法测试,如因此造成一切不良后果与文章作者及本公众号无关!

前一篇分享了JavaWeb的基础知识包括HTTP协议、Tomcat容器和Servlet组件,其中Servlet是JavaWeb三大核心组件之一,另外两个核心组件Filter和Listener后续会介绍。想看JavaWeb基础内容的请参考下面链接:

JavaWeb之HTTP、Tomcat、Servlet

0xNvyao,公众号:安全随笔JavaWeb之HTTP、Tomcat、Servlet

本篇来学习下JavaWeb的两个重要的对象-Request和Response。

目录:
0x01,Request对象
    -- Request 继承体系
    -- Request 获取请求数据
    -- Request 通用方式获取请求参数(统一doGet和doPost)
0x02,Response对象
    -- Response 继承体系
    -- Response 响应数据
0x03,请求转发和响应重定向的区别

0x01,Request对象

上一篇介绍了Javaweb的Servlet最后留一个思考?编写Servlet类有两种方式,一种是通过实现Servlet接口,另一种是通过继承HttpServlet抽象类,注意观察这两种方式接收的请求、响应的参数类型是有区别的,前者是ServletRequest类型,后者是HttpServletRequest类型。本节详细说说他们之间的继承关系和常规用法。下面是两者的官方描述:

ServletRequest:

定义一个对象来向 servlet 提供客户端请求信息(说白了就是提供一个对象来封装请求信息)。servlet 容器创建一个 ServletRequest 对象并将其作为参数传递给 servlet 的service()方法。ServletRequest 对象提供数据,包括参数名称和值、属性和输入流。通过继承ServletRequest 接口可以提供其他特定于协议的数据(如:javax.servlet.http.HttpServletRequest 提供 HTTP 数据

HttpServletRequest:

继承自 ServletRequest 接口以提供 HTTP servlet 的请求信息。servlet 容器创建一个 HttpServletRequest 对象并将其作为参数传递给 servlet 的服务方法(doGet、doPost 等)

Request 继承体系

ServletRequest       //Java提供的请求对象根接口-->继承关系HttpServletRequest   //Java提供的对Http协议封装的请求对象接口-->实现关系RequestFacade        //Tomcat定义的实现类

可以通过IDEA看一下:

JavaWeb之Request请求和Response响应

上面两个接口都是java提供好理解,为啥是Tomcat提供实现类?

在前一篇我们分析过,知道了Servlet类对象是由Tomcat创建的,Servlet对象的service()是由Tomcat调用的,因此service(request,response)方法的的requestresponse对象也应该是Tomcat来实现(用于封装请求、响应数据)。

JavaWeb之Request请求和Response响应

我们通过打印一下request、response对象证实一下:

@Override  public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException    System.out.println(servletRequest);    System.out.println(servletResponse);}

JavaWeb之Request请求和Response响应

  • Request对象:org.apache.catalina.connector.RequestFacade

  • Response对象:org.apache.catalina.connector.ResponseFacade

Request 获取请求数据

Request请求数据其实就是HTTP请求的数据,可以通过F12抓包看到,学习Request对象就是学习如何获取HTTP请求数据,请求数据包含请求行、请求头和请求体

JavaWeb之Request请求和Response响应

1)获取请求行

//获取请求行常用方法String method = req.getMethod();System.out.println(method);String contextPath = req.getContextPath();System.out.println(contextPath);StringBuffer requestURL = req.getRequestURL(); //类型是StringBufferSystem.out.println(requestURL);String requestURI = req.getRequestURI();System.out.println(requestURI);

2)获取请求头

//获取请求头String header = req.getHeader("user-agent");System.out.println(header);Cookie[] cookies = req.getCookies();System.out.println(cookies);System.out.println(req.getContentLength());System.out.println(req.getContentType());System.out.println(req.getLocalPort());

3)获取请求体

@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {    //获取post请求体    //1.获取字符输入流    BufferedReader bufferedReader = req.getReader();    //2.读取数据:按行    //String line = bufferedReader.readLine();    //System.out.println(line);    //3.读取数据:按字符    int read = 1;    while(read >0) {        read = bufferedReader.read();        System.out.print((char)read);    }}

当然如果是非字符输入流数据,而是字节输入流,需要通过创建字节输入流来接收请求体数据,举个例子:

@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {    // 获取字节输入流    Part filePart = req.getPart("file"); // 获取上传的文件部分    String fileName = filePart.getSubmittedFileName(); // 获取文件名    // 获取当前日期和时间    LocalDateTime currentDateTime = LocalDateTime.now();    // 定义日期时间格式    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");    // 格式化日期时间    String formattedDateTime = currentDateTime.format(formatter);    System.out.println(formattedDateTime);    InputStream fileContent = filePart.getInputStream();    // 保存文件到服务器    OutputStream outputStream = new FileOutputStream("/Users/liujianping/Downloads/" + fileName.substring(0, fileName.lastIndexOf('.')) + formattedDateTime + ".png");    byte[] buffer = new byte[4096];    int bytesRead = -1;    while ((bytesRead = fileContent.read(buffer)) != -1) {        outputStream.write(buffer, 0, bytesRead);    }    outputStream.close();    fileContent.close();    resp.getWriter().println("File " + fileName + " uploaded successfully");}

JavaWeb之Request请求和Response响应

Request 通用方式获取请求参数(统一doGet和doPost)

根据前面介绍,请求方式(Get或者Post)的不同,导致获取请求参数的方式也不一样,如下。除此之外其他的数据获取都是一样的。

  • GET参数:req.getQueryString();

  • POST参数:req.getReader();

因此如果因为参数获取方式不同导致写两遍一样的代码,显然不合理的,因此HttpServletRequest接口正好提供了这样的一些方法可以用于统一GET和POST不同方式的请求参数获取方式,分为以下三种场景:

  • Map<String, String[]>getParameterMap(): 获取所有参数Map集合

  • String[]getParameterValues(String name): 根据名称获取参数值(数组)

  • StringgetParameter(String name): 根据名称获取参数值(单个值)

package com.nvyao.web;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.util.Map;@WebServlet("/req2")public class RequestDemo2 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//        System.out.println("get...");        System.out.println(req.getMethod() + "...");        //1.获取所有的参数的Map集合        Map<String, String[]> map = req.getParameterMap();        for(String key : map.keySet()) {            //获取键            System.out.print(key + ":");            //获取值            String[] values = map.get(key);            for (String value : values) {                System.out.print(value + " ");            }            System.out.println();        }        System.out.println("-------------");        //2.根据key获取参数值:数组        String[] hobbies = req.getParameterValues("hobby");        for (String hobby : hobbies) {            System.out.println(hobby);        }        System.out.println("-------------");        //3.根据key 获取单个参数值        String username = req.getParameter("username");        String password = req.getParameter("password");        System.out.println("username:" +username +",password:" + password);    }    @Override    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletExceptionIOException {        this.doGet(req, resp);    }}

JavaWeb之Request请求和Response响应

可以看到不管是GET还是POST都可以通用地获取请求参数 

0x02,Response对象

Response 继承体系

和Request 继承体系一样,Response的继承体系如下:

ServletResponse       //Java提供的响应对象根接口-->继承关系HttpServletResponse   //Java提供的对Http协议封装的响应对象接口-->实现关系ReponseFacade        //Tomcat定义的实现类

JavaWeb之Request请求和Response响应

Response 响应数据

Response 响应数据分为响应字符数据和响应字节数据,具体是:

  • Response响应字符数据:PrintWriter writer = response.getWriter();

  • Response响应字节数据:ServletOutputStream os = resp.getOutputStream();

以下是响应字符数据的代码示例:

/** * 响应字符数据:设置字符数据的响应体 */@WebServlet("/resp3")public class ResponseDemo3 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        response.setContentType("text/html;charset=utf-8");//设置响应的数据格式和字符集        System.out.println("resp3...");        //1、获取字符输出流        PrintWriter responseWriter = response.getWriter();//        response.setHeader("content-type","text/html");        responseWriter.write("你好");        responseWriter.write("<h1>bbbb</h1>");    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

JavaWeb之Request请求和Response响应

以下是响应字节数据的代码示例:

package com.nvyao.web.response;import org.apache.commons.io.IOUtils;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.FileInputStream;import java.io.IOException;import java.io.PrintWriter;/** * 响应字节数据:设置字节数据的响应体 */@WebServlet("/resp4")public class ResponseDemo4 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        //1、读取文件        FileInputStream fis = new FileInputStream("/Users/liujianping/Downloads/baidu.png");        //2、获取response字节输出流        ServletOutputStream os = response.getOutputStream();        //3、完成流的copy        /*byte[] buffer = new byte[1024];        int len = 0;        while((len = fis.read(buffer)) != -1){            os.write(buffer, 0, len);        }*/        int copy = IOUtils.copy(fis, os);//返回总字节大小        System.out.println(copy);        fis.close();    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

JavaWeb之Request请求和Response响应

0x03,请求转发和响应重定向的区别

再来介绍下请求转发和响应重定向的区别:

请求转发(forward):一种在服务器内部的资源跳转方式,特点是:

  • 浏览器地址栏路径不发生变化

  • 只能转发到当前服务器的内部资源

  • 发生一次请求,可以在转发的资源间使用request共享数据

重定向(Redirect):一种资源跳转方式,特点是:

  • 浏览器地址栏路径发生变化

  • 可以重定向到任意资源,包括外部资源

  • 发生两次请求,不能在多个资源间使用request共享数据

以下是请求转发的代码示例:

@WebServlet("/req5")public class RequestDemo5 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        System.out.println("demo5...");        //存储数据        request.setAttribute("msg", "hello~");        // 请求转发        request.getRequestDispatcher("/req6").forward(request, response);    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

以下是响应重定向代码示例:

package com.nvyao.web.response;import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.annotation.*;import java.io.IOException;@WebServlet("/resp1")public class ResponseDemo1 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        System.out.println("resp1...");        //重定向//        //1.设置响应码302//        response.setStatus(302);//        //2.设置响应头Location//        response.setHeader("location","/request-demo/resp2");        //简化完成重定向        String contextPath = request.getContextPath();//        System.out.println(contextPath);        response.sendRedirect( contextPath + "/resp2");    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

原文始发于微信公众号(安全随笔):JavaWeb之Request请求和Response响应

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月25日23:28:56
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JavaWeb之Request请求和Response响应http://cn-sec.com/archives/3125240.html

发表评论

匿名网友 填写信息