目录

  • 📋 个人简介
  • 前言
  • Request
  • Request 继承体系
  • Request 获取请求参数
  • 获取请求参数的通用方式
  • Request 请求转发
  • Response
  • Response继承体系
  • Response 设置响应数据功能
  • Respones 请求重定向
  • 请求转发和重定向的区别
  • Response 响应数据
  • 结语


前言

web开发最重要的之一不就是处理请求与响应吗,那么这节就来总结Servlet是如何处理的,在请求与响应这块基本都差不多,浅浅的过一下!

Request

request:获取请求数据

  • 浏览器会发送HTTP请求到后台服务器[Tomcat]
  • HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
  • 后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
  • 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
  • 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务!

Request 继承体系

java响应式编程原理 java请求和响应_System


所以ServletRequest和HttpServletRequest是继承关系,并且两个都是接口,接口是无法创建。

对象,这个时候就引发了下面这个问题:

java响应式编程原理 java请求和响应_System_02


这个时候,我们就需要用到Request继承体系中的RequestFacade :

  • 该类实现了HttpServletRequest接口,也间接实现了ServletRequest接口。
  • Servlet类中的service方法、doGet方法或者是doPost方法最终都是由Web服务器[Tomcat]来调用的,所以Tomcat提供了方法参数接口的具体实现类,并完成了对象的创建。
  • 要想了解RequestFacade中都提供了哪些方法,我们可以直接查看JavaEE的API文档中关于ServletRequest和HttpServletRequest的接口文档,因为RequestFacade实现了其接口就需要重写接口中的方法。

所以,你可以打印这个参数resquest,可以看到这个对象是由RequestFacade创建的!

Request 获取请求参数

1.请求行包含三块内容,分别是请求方式、请求资源路径、HTTP协议及版本

java响应式编程原理 java请求和响应_System_03


对于这三部分内容,request对象都提供了对应的API方法来获取!2.对于请求头的数据,格式为key: value如下:

java响应式编程原理 java请求和响应_System_04


3.获取请求体数据

浏览器在发送GET请求的时候是没有请求体的,所以需要把请求方式变更为POST!

对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是:

获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法:

ServletInputStream getInputStream()

获取字符输入流,如果前端发送的是纯文本数据,则使用该方法:

BufferedReader getReader()

以上java代码如下:

@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);


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


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取post 请求体:请求参数

        //1. 获取字符输入流
        BufferedReader br = req.getReader();
        //2. 读取数据
        String line = br.readLine();
        System.out.println(line);
    }
}

对于post请求,可以写一个html表单测试!

获取请求参数的通用方式

对于请求参数的获取,常用的有以下两种:

GET:

String getQueryString()

POST:

BufferedReader getReader();

但通常情况写,有可能我们get或post处理的业务逻辑是相同的,但请求方式有不同,怎么办呢?

java响应式编程原理 java请求和响应_前端_05


当然,也可以在doGet中调用doPost,在doPost中完成参数的获取和打印,另外需要注意的是,doGet和doPost方法都必须存在,不能删除任意一个。

GET请求和POST请求获取请求参数的方式不一样,在获取请求参数这块该如何实现呢?要想实现,我们就需要思考:

GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样,是否可以提供一种统一获取请求参数的方式,从而统一doGet和doPost方法内的代码?

解决方法一:

java响应式编程原理 java请求和响应_前端_06

这样不就好了,但是以后每个Servlet我们都要这样这样写,还是麻烦!

解决方案二:
request对象已经将上述获取请求参数的方法进行了封装,并且request提供的方法实现的功能更强大,以后只需要调用request提供的方法即可,在request的方法中都实现了哪些操作呢?

java响应式编程原理 java请求和响应_java_07


如图,request将获取到的内容进行分割,然后将分割后的数据存到Map集合中!

java响应式编程原理 java请求和响应_servlet_08


基于此,request提供了以下api,直接上案例代码了哦:

package com.aniu;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Map;

/**
 * request 通用方式获取请求参数
 */
@WebServlet("/demo3")
public class ServletDemo3 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();  //换行
        }

        System.out.println("------------");

        //2. 根据key获取参数值,数组
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {

            System.out.println(hobby);
        }

        //3. 根据key 获取单个参数值
        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 {
        //POST请求逻辑
        System.out.println("post...");

        this.doGet(req,resp);
    }
}

b.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/tomcat-demo/demo3" method="post">
    <input type="text" name="username"><br>
     <input type="password" name="password"><br>
     <input type="checkbox" name="hobby" value="1"> 游泳
     <input type="checkbox" name="hobby" value="2"> 爬山 <br>
    <input type="submit">
 </form>
</body>
</html>

java响应式编程原理 java请求和响应_servlet_09


可以看到出现汉字乱码问题!

解决请看:

Request 请求转发

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

java响应式编程原理 java请求和响应_System_10

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A处理完请求后将请求发给资源B
(3)资源B处理完后将结果响应给浏览器
(4)请求从资源A到资源B的过程就叫请求转发

@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);
	}
}
@WebServlet("/req6")
public class RequestDemo6 extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("demo6...");
		//获取数据
		Object msg = request.getAttribute("msg");
		System.out.println(msg);
	}
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request, response);
	}
}

Response

response:设置响应数据

  • 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
  • 把响应数据封装到response对象中
  • 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
  • 浏览器最终解析结果,把内容展示在浏览器给用户浏览

Response继承体系

java响应式编程原理 java请求和响应_java_11

Response 设置响应数据功能

HTTP响应数据总共分为三部分内容,分别是响应行、响应头、响应体,对于这三部分内容的数据,
respone对象都提供了方法来进行设置。

1.响应行

对于响应头,比较常用的就是设置响应状态码:

void setStatus(int sc);

2.响应头

设置响应头键值对:

void setHeader(String name,String value);

3.响应体

对于响应体,是通过字符、字节输出流的方式往浏览器写,
获取字符输出流:

PrintWriter getWriter();

获取字节输出流

ServletOutputStream getOutputStream();

Respones 请求重定向

Response重定向(redirect):一种资源跳转方式。

java响应式编程原理 java请求和响应_java响应式编程原理_12

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求
(2)资源A现在无法处理该请求,就会给浏览器响应一个302的状态码+location的一个访问资源B的
路径
(3)浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
(4)资源B接收到请求后进行处理并最终给浏览器响应结果,这整个过程就叫重定向

重定向方法一:

resp.setStatus(302);
resp.setHeader("location","资源访问路径");

重定向方法二:

//重定向
resposne.sendRedirect("资源访问路径");

请求转发和重定向的区别

java响应式编程原理 java请求和响应_servlet_13

Response 响应数据

响应字符数据:

//设置响应的数据格式及数据的编码
response.setContentType("text/html;charset=utf-8");
writer.write("你好");

响应字节数据:

1.通过Response对象获取字节输出流:

ServletOutputStream outputStream = resp.getOutputStream();

2.通过字节输出流写数据:

outputStream.write(字节数据);
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	//1. 读取文件
	FileInputStream fis = new FileInputStream("d://a.jpg");
	//2. 获取response字节输出流
	ServletOutputStream os = response.getOutputStream();
	//3. 完成流的copy
	byte[] buff = new byte[1024];
	int len = 0;
	while ((len = fis.read(buff))!= -1){
	os.write(buff,0,len);
	}
	fis.close();
}

结语