Servlet(1)Request 请求对象

1、接收请求数据的流程

  1. 浏览器发送HTTP请求到Tomcat服务器
  2. HTTP的请求中会包含很多请求数据(请求行+请求头+请求体)
  3. Tomcat服务器会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
  4. 所封装的对象即为Request对象,所以可以从Request对象中获取请求的的所有信息,如请求头、请求参数、请求路径、会话信息等
  5. 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作

2、Request对象

Request对象是一个包含客户端发送给服务器端的所有信息的对象。它是Servlet的一个核心组件,用于收集客户端发送的表单数据、Cookies、超链接等信息,以及获取与客户端请求相关的其他数据,如请求方式、请求头信息、请求参数等。

作用是与客户端进行交互,它允许Servlet获取并处理来自客户端的请求数据。通过Request对象,Servlet可以了解客户端的请求细节,并根据这些请求数据生成相应的响应。

作用域是一次请求。在一次请求中,Servlet可以使用Request对象来获取和处理请求数据,并根据需要构建响应对象(Response对象)来发送回客户端。

3、方法

当客户端发送一个HTTP请求到Servlet时,Servlet容器(Tomcat)会自动创建一个实现了HTTPServletRequest接口的对象,这个对象包含了请求的所有信息(如请求头、请求参数、请求路径等),并将这个对象传递给Servlet的doGet()、doPost()等方法,让Servlet能够处理这个请求。Servlet容器负责管理和调用Servlet处理请求。由于不需要直接实现这个接口,而是使用Servlet容器提供的实例,所以只需要关注怎样使用接口提供的方法处理请求。

HTTP请求数据中包含了请求行、请求头、请求体,分别用各自的API方法获取对应的值:

1)请求行

请求行包括三块内容:请求方式、请求资源路径、HTTP协议及版本。

  • getMethod():获取请求方式
  • getRequestURL():获取客户端发出请求时的完整URL
  • getRequestURI():获取请求行中的资源名称部分(项目名称开始)
  • getQueryString():获取请求行中的参数部分(GET请求)
  • getProtocol():获取HTTP版本号
  • getContextPath():获取请求的上下文路径

应用举例:

@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // String getMethod():获取请求方式: GET
        String method = req.getMethod();
        System.out.println(method);//GET
        // String getContextPath():获取虚拟目录(项目访问路径):/request-demo
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        // StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
        StringBuffer url = req.getRequestURL();
        System.out.println(url.toString());
        // String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
        String uri = req.getRequestURI();
        System.out.println(uri);
        // String getQueryString():获取请求参数(GET方式): username=zhangsan
        String queryString = req.getQueryString();
        System.out.println(queryString);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}

启动服务器,访问http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123,获取的结果如下:

2)请求头

请求头的数据格式是 key: value的键值对。

  •   getHeader(String name)根据请求头名称获取其对应的值

应用举例:

//获取请求头: user-agent: 浏览器的版本信息
        String agent = req.getHeader("user-agent");

3)请求体(POST请求)

对于POST请求,特别是当内容类型是application/json、application/xml或text/plain等时,请求体可能包含重要的数据,如JSON对象或XML文档。在这种情况下,获取请求体是非常常见的。

先获取流对象,再从流对象中拿数据。

  • BufferedReader getReader():获取字符输入流(纯文本)
BufferedReader reader = request.getReader();  
String line;  
StringBuilder requestBody = new StringBuilder();  
while ((line = reader.readLine()) != null) {  
    requestBody.append(line);  
}  
String body = requestBody.toString();
  • ServletInputStream getInputStream():获取字节输入流
InputStream inputStream = request.getInputStream();  
byte[] buffer = new byte[1024];  
int bytesRead;  
StringBuilder requestBody = new StringBuilder();  
while ((bytesRead = inputStream.read(buffer)) != -1) {  
    requestBody.append(new String(buffer, 0, bytesRead));  
}  
String body = requestBody.toString();
  • 对于JSON请求体,还可以使用JSON处理库(如Jackson或Gson)解析请求体为Java对象:
import com.fasterxml.jackson.databind.ObjectMapper;  

ObjectMapper objectMapper = new ObjectMapper();  
MyObject myObject = objectMapper.readValue(request.getInputStream(), MyObject.class);

//注:ObjectMapper类是Jackson库中的一个核心类,它用于在Java对象和JSON数据之间进行转换。
//Jackson 是一个流行的Java库,用于处理JSON(JavaScript Object Notation)数据格式。 //ObjectMapper提供了丰富的方法来进行序列化和反序列化操作。

对于大型请求体,应该考虑使用流式处理来避免内存溢出。此外,在处理完请求体后,应该关闭Reader或InputStream以释放资源。

在现代Web框架(如Spring MVC)中,框架通常会自动处理请求体的解析,并将请求体映射到方法参数上,这使得手动处理请求体变得不那么常见。然而,了解如何在Servlet中手动处理请求体仍然是有价值的,因为它提供了对底层HTTP交互的更深入理解。

4)获取请求参数

请求参数:如登录时的用户名、密码

请求数据:包含请求行、请求头和请求体的所有数据

关系:请求参数是请求数据中的部分内容(GET请求的请求参数在请求行中;POST请求的请求参数一般在请求体中)

  • getParameter(String name)获取指定名称的请求参数的值

应用举例:获取username=zs&password=123 :

@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        System.out.println(password);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}
  • getParameterValues(String name):获取指定名称的请求参数的所有值(当参数有多个值时)

应用举例:获取hobby=xx&hobby=game

@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      
        System.out.println("------------");
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}
  • getParameterMap():获取所有参数的map集合

应用举例:

@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //GET请求逻辑
        System.out.println("get....");
        //1. 获取所有参数的Map集合
        Map<String, String[]> map = req.getParameterMap();
        for (String key : map.keySet()) {
            // username:zhangsan lisi
            System.out.print(key+":");

            //获取值
            String[] values = map.get(key);
            for (String value : values) {
                System.out.print(value + " ");
            }

            System.out.println();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}

5)设置编码

解决POST请求方式的乱码:

  • request.setCharacterEncoding("UTF-8");

GET请求方式在Tomcat 8.0版本后不会出现乱码

应用举例:

@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 解决乱码: POST getReader()
        //设置字符输入流的编码,设置的字符集要和页面保持一致
        request.setCharacterEncoding("UTF-8");
       //2. 获取username
       String username = request.getParameter("username");
       System.out.println(username);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

4、请求转发(forward)

一种在服务器内部的资源跳转方式。

浏览器发送请求给服务器,服务器中的资源A接收到请求并将请求发给资源B,资源B处理完后将结果响应给浏览器。其中,请求从资源A到资源B的过程就叫请求转发。可以转发到Servlet或JSP。

请求转发是一种服务器的行为,当客户端请求到达后,服务器进行转发,此时会将请求对象进行保 存,地址栏中的 URL 地址不会改变,得到响应后,服务器端再将响应发送给客户端,从始至终只有一个请求发出。只能转发到当前服务器的内部资源,不能从一个服务器通过转发访问另一台服务器,因此不能请求转发到服务器外部资源。

实现方式:

  • req.getRequestDispatcher("资源B路径").forward(req,resp);

应用举例:

步骤一:需要创建2个servlet

@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("这是demo1");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}
@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("这是demo2");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

步骤二:请求转发:在RequestDemo1的doGet方法中进行

@WebServlet("/req")
public class RequestDemo5 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("这是demo1");
        //请求转发
        request.getRequestDispatcher("/req2").forward(request,response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

启动访问:http://localhost:8080/request-demo/req1 

看到控制台打印:

这是demo1

这是demo2   

说明请求已经转发到了 /req2

5、共享数据

把请求从/req1 转发到/req2的时候,怎样传递数据给/req2 ?

使用Request对象进行请求转发资源间的共享数据。

Request对象是一个域(范围)对象,具有特定的作用范围,即在一次请求及其转发的过程中。它提供了一组方法—setAttribute、getAttribute和removeAttribute,用于存储、获取和移除数据。

应用举例:

步骤一:在源Servlet中设置数据到Request对象:

@WebServlet("/sourceServlet")  
public class SourceServlet extends HttpServlet {  
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
        // 设置数据到Request对象  
        request.setAttribute("sharedData", "data");  
  
        // 请求转发到目标Servlet  
        RequestDispatcher dispatcher = request.getRequestDispatcher("/targetServlet");  
        dispatcher.forward(request, response);  
    }  
}

步骤二:在目标Servlet中获取数据:

@WebServlet("/targetServlet")  
public class TargetServlet extends HttpServlet {  
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
        // 获取共享数据  
        String sharedData = (String) request.getAttribute("sharedData");  
  
        // 使用共享数据
        System.out.println("收到分享的数据: " + sharedData);  
}

这里面有两个Servlet,当访问SourceServlet时,它会将数据"data"添加到Request对象中,并通过RequestDispatcher将请求转发到TargetServlet。

在TargetServlet中,通过调用request.getAttribute("sharedData")得到之前设置的数据,并可以在该Servlet的业务逻辑中使用这些数据。

客户端的请求URL应该指向源Servlet(在这个例子中是/sourceServlet),然后由源Servlet负责转发请求并共享数据。如http://localhost:8080/request-demo/sourceServlet。

使用请求转发时,客户端访问的URL是源Servlet的URL。请求转发是一种在服务器内部将请求从一个Servlet或JSP转发到另一个Servlet或JSP的技术,客户端并不知道这个过程。

  • 22
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值