Java Request和Response对象 - Request篇

Request

Request: 使用 request对象来获取请求数据

Response: 使用 response对象来设置响应数据

Request继承体系

Request的继承体系如下

Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中; 因此Tomcat需要实现HttpServletRequest接口

学习实现类RequestFacade的使用,可以查阅JavaEE API文档的HttpServletRequest接口

在这里插入图片描述

Request获取请求数据

获取请求数据基本使用

请求数据分为三部分:

请求头

请求行

请求体

获取请求头的方法如下:

方法名 描述
String getHeader(String name) 根据请求头名称,获取值
@WebServlet("/req")
public class RequestDemo extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // user-agent: 获取浏览器的版本信息
        String agent = req.getHeader("user-agent");
        System.out.println(agent);
    }
}

获取请求行的方法如下:

方法名 描述
String getMethod() 获取的请求方式
String getContextPath() 获取虚拟目录(项目访问路径)
StringBuffer getRequestURL() 获取URL(统一资源定位符)
String getRequestURI() 获取URI(统一资源标识符)
String getQueryString() 获取请求参数(GET方式)

演示代码: 启动服务器后通过查询字符串传递参数, 访问URL: http://localhost:8080/request-demo/req?name=chenyq&age=18

@WebServlet("/req")
public class RequestDemo extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 获取请求的方式
        String method = req.getMethod();
        System.out.println(method); // GET

        // 获取虚拟目录(项目访问路径)
        String contextPath = req.getContextPath();
        System.out.println(contextPath); // /request-demo

        // 获取URL统一资源定位符
        StringBuffer requestURL = req.getRequestURL();
        System.out.println(requestURL.toString()); // http://localhost:8080/request-demo/req

        // 获取URI统一资源标识符
        String requestURI = req.getRequestURI();
        System.out.println(requestURI); // /request-demo/req

        // 获取请求参数
        String queryString = req.getQueryString();
        System.out.println(queryString); // name=chenyq&age=18
    }
}

获取请求体(post请求才有请求体)的方法如下:

方法名 描述
ServletInputStream getInputStream() 获取字节输入流
BufferedReader getReader() 获取字符输入流

我们编写一个html文件, 在文件中使用表单模拟post请求

<form method="post" action="http://localhost:8080/request-demo/req">
  <div>
    <span>请输入账号: </span>
    <input type="text" name="username">
  </div>
  <div>
    <span>请输入密码: </span>
    <input type="password" name="password">
  </div>
  <input type="submit" value="提交">
</form>

通过post获取到请求体

@WebServlet("/req")
public class RequestDemo extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 获取post请求体(post的请求的参数)
        // 1. 获取字符输入流
        BufferedReader br = req.getReader();
        // 2. 读取数据
        String line = br.readLine();
        System.out.println(line); // username=admin&password=1234
    }
}

通用方式获取请求参数

上面我们说了请求参数获取方式:

GET 方式:String getQueryString()

POST 方式: BufferedReader getReader()

思考:

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

Request 通用获取请求参数的方法如下:

通用指的是: 获取参数的方法既可以被用于Get, 又可以被用于Post请求;

既然有了统一获取参数的方法, 那么我们doPost方法中直接调用doGet即可, 无需再编写重复逻辑的代码

方法名 描述
Map<String, String[ ]> getParameterMap() 获取所有参数Map集合, 如果key相同, 会将值放入一个数组中
String[ ] getParameterValues(String name) 根据名称获取一个参数值的数组
String getParameter(String name) 根据名称获取一个单个参数值

示例代码:

获取所有参数Map集合

@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
      	// 获取所有参数Map集合
        Map<String, String[]> map = req.getParameterMap();
        // 遍历展示
        for (String key : map.keySet()) {
    
    
            String[] values = map.get(key);
            System.out.print(key + ":");
            for (String value : values) {
    
    
                System.out.print(value + " ");
            }
            System.out.println();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
      	// 调用doGet方法, 避免编写重复逻辑
        this.doGet(req, resp);
    }
}

根据名称获取一个参数值的数组

@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 根据名称获取一个参数值的数组
        String[] hobbies = req.getParameterValues("hobby");
        // 遍历展示
        for (String hobby : hobbies) {
    
    
            System.out.println(hobby);
        }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
      	// 调用doGet方法, 避免编写重复逻辑
        this.doGet(req, resp);
    }
}

根据名称获取一个单个参数值

@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 根据名称获取一个单个参数值
        String username = req.getParameter("username");
        System.out.println(username);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
      	// 调用doGet方法, 避免编写重复逻辑
        this.doGet(req, resp);
    }
}

Request请求参数中文乱码处理

请求参数如果存在中文数据,是会出现乱码问题的

POST请求解决方案:

设置输入流的编码为"UTF-8"

request.setCharacterEncoding("UTF-8");

演示代码

@WebServlet("/req3")
public class RequestDemo3 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        // 1. 解决Post乱码
        request.setCharacterEncoding("UTF-8"); // 设置字符输入流的编码为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);
    }
}

GET和POST的通用方式

浏览器进行URL编码默认使用的是UTF-8, 而Tomcat进行URL解码默认的是ISO-8859-1;

所以我们需要拿到Tomcat解码的结果, 对其先编码,再解码;

Tomcat 8.0 之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8

new String(username.getBytes("ISO-8859-1"),"UTF-8");

演示代码

@WebServlet("/req3")
public class RequestDemo3 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        // 1. 获取username参数
        String username = request.getParameter("username");

        // 2. 对获取到的username先通过ISO-8859-1编码再通过UTF-8解码
        username = new String(username.getBytes("ISO-8859-1"), "UTF-8");

        System.out.println(username);
    }

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

请求转发

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

例如下图, 浏览器向Tomcat请求资源A; 资源A又将请求转发给资源B

在这里插入图片描述

实现方式

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

示例代码如下:

分别创建一个RequestDemo4, 访问路径为/req4和一个RequestDemo5, 访问路径为/req5

@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("demo4...");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}
@WebServlet("/req5")
public class RequestDemo5 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("demo5...");
    }

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

再在demo4中将请求转发发哦demo5中

@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("demo4...");

        // 请求转发, 将请求转发到/req5
        request.getRequestDispatcher("/req5").forward(request, response);
    }

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

访问/req4的打印结果

demo4...
demo5...

在很多时候, 我们通常是在资源A中处理一部分数据, 然后再转发给资源B继续处理; 那么就需要请求转发资源间数据共享: 转发资源间数据共享使用的是request对象, request对象提供了如下数据共享常用的方法:

方法名 描述
void setAttribute(String name, Object o) 存储数据到 request域中
Object getAttribute(String name) 根据 key,获取值
void removeAttribute(String name) 根据 key,删除该键值对

示例代码:

@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("demo4...");

        // 向request域中存储数据
        request.setAttribute("name", "chenyq");

        // 请求转发, 将请求转发到/req5
        request.getRequestDispatcher("/req5").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}
@WebServlet("/req5")
public class RequestDemo5 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("demo5...");

        // 从request中获取数据
        Object message = request.getAttribute("name");
        System.out.println(message); // chenyq
    }

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

请求转发的特点:

请求转发后, 浏览器地址栏路径不发生变化

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

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

猜你喜欢

转载自blog.csdn.net/m0_71485750/article/details/127871825