请求对象和响应对象

目录

一、Tomcat 请求与响应

定义

二、HttpServletRequest基本功能

1.重要性

2.功能分类

3.获取请求头数据

方法

示例

结果:

4.其他请求相关方法

e.g

示例

结果:

三、HttpServletRequest获取参数

1.传递参数的方式

示例1

示例2(功能极为类似示例1)

 2.获取参数的方法

单值参数接收

多值参数接收

3.中文乱码处理

四、请求转发重定向示例

1.向客户端响应数据(基础)

2.请求转发

3.利用重定向实现向客户端相应数据(两种方式:临时重定向&重定向)

 五、高频面试题

转发和重定向的区别

1. 定义

请求转发(Forward)

重定向(Redirect)

2. 处理流程

3. 路径使用

相对路径

绝对路径

4. 其他区别


先前已经对请求转发和重定向(参见博客:请求转发和重定向_请求转发和重定向的代码-优快云博客)有了核心基础的理解,而无论是请求转发还是重定向,它们都是基于请求响应模型的,所以这篇文章着重于请求对象和响应对象来做系统的梳理和示例演示。

一、Tomcat 请求与响应

定义

Web服务器收到客户端的HTTP请求后,会为每次请求创建一个request对象和一个response对象。

request对象用于获取客户端提交的数据,response对象用于向客户端输出数据。

二、HttpServletRequest基本功能

1.重要性

HttpServletRequest是JavaWeb中非常重要的类,是Servlet的service()方法的参数之一。

2.功能分类

封装请求头数据(如获取请求头名称和值)。

封装请求正文数据(GET请求无正文)。

作为域对象,可以存储和获取数据。

支持请求转发和重定向。

3.获取请求头数据

方法

getHeader(String name):获取指定名称的请求头。

getHeaderNames():获取所有请求头名称。

示例

通过getHeaderNames()getHeader()遍历并输出所有请求头。

【注意:这里的项目用的是普通JavaWeb项目(不含maven的基础款),在这里我用的idea版本是2021版本,配置普通版本的JavaWeb项目需要创建普通Java项目后配置成JavaWeb项目(具体操作可以搜索相关文章),如果是用的2017版本的idea,那么配置JavaWeb基础项目有相关的选项,相较更为简单,但是2017版本的idea并没有自动导包的功能。】

package com.qcby.test;

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.Enumeration;
/**
 * request对象的相关方法
 */
@WebServlet(name = "Demo1Servlet",urlPatterns ="/demo1Servlet")
public class Demo1Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doget.....");
        //获得请求头信息
        String  accept = request.getHeader("Accept");
        System.out.println("Accept:"+accept );

        String ua = request.getHeader("User-Agent");
        System.out.println("User-Agent:"+ua);

        System.out.println("=====================================");
        //获取所有头信息
        Enumeration<String> names = request.getHeaderNames();
        while(names.hasMoreElements()){
            String name = names.nextElement();
            String value = request.getHeader(name);
            System.out.println(name+":"+value);
        }
    }
}
结果:

 其实这里的结果就是请求标头里的内容:

4.其他请求相关方法

方法描述返回类型
getContentLength()获取请求正文的字节数(GET请求无正文,返回-1)。int
getContentType()获取请求的类型(如application/x-www-form-urlencoded)。String
getMethod()获取请求方法(如GETPOSTPUTDELETE等)。String
getLocale()获取客户端浏览器支持的语言环境(java.util.Locale对象)。Locale
getCharacterEncoding()获取请求的编码(默认为ISO-8859-1,未设置时返回null)。String
setCharacterEncoding(String code)设置请求的编码(仅对POST请求的正文有效)。void
getContextPath()获取上下文路径(如/项目名称)。String
getQueryString()获取请求URL中的参数部分(如name=zhangSan)。String
getRequestURI()获取请求的URI路径(如/hello/oneServlet)。String
getRequestURL()获取完整的请求URL路径(不包括参数部分)。StringBuffer
getServletPath()获取Servlet的路径(如/oneServlet)。String
getRemoteAddr()获取客户端的IP地址。String
getRemoteHost()获取客户端的主机名(通常返回IP地址)。String
getRemotePort()获取客户端的端口号。int
getScheme()获取请求协议(如httphttps)。String
getServerName()获取服务器的主机名(如localhost)。String
getServerPort()获取服务器的端口号(如808080)。int

e.g

示例

获取HTTP请求的各种信息

package com.qcby.test;

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;

@WebServlet(name = "Demo2Servlet",urlPatterns = "/demo2Servlet")
public class Demo2Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("request.getContentLength(): " + request.getContentLength());
        response.getWriter().write("request.getContentType(): " + request.getContentType());
        response.getWriter().write("request.getContextPath(): " + request.getContextPath());
        response.getWriter().write("request.getMethod(): " + request.getMethod());
        response.getWriter().write("request.getLocale(): " + request.getLocale());
        response.getWriter().write("request.getQueryString(): " + request.getQueryString());
        response.getWriter().write("request.getRequestURI(): " + request.getRequestURI());
        response.getWriter().write("request.getRequestURL(): " + request.getRequestURL());
        response.getWriter().write("request.getServletPath(): " + request.getServletPath());
        response.getWriter().write("request.getRemoteAddr(): " + request.getRemoteAddr());
        response.getWriter().write("request.getRemoteHost(): " + request.getRemoteHost());
        response.getWriter().write("request.getRemotePort(): " + request.getRemotePort());
        response.getWriter().write("request.getScheme(): " + request.getScheme());
        response.getWriter().write("request.getServerName(): " + request.getServerName());
        response.getWriter().write("request.getServerPort(): " + request.getServerPort());
    }
}

结果:

三、HttpServletRequest获取参数

1.传递参数的方式

GET请求:

  • 地址栏传递参数。

  • 超链接传递参数。

  • 表单传递参数。

POST请求:

  • 表单传递参数。

示例1

获取和打印通过GET和POST方法发送的HTTP请求参数

package com.qcby.test;

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.Arrays;
import java.util.Enumeration;
import java.util.Map;

/**
 * request对象获取请求参数
 */
@WebServlet(name = "Demo3Servlet",urlPatterns = "/demo3Servlet")
public class Demo3Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取get请求的参数
        String username = request.getParameter("username");
        String passsword = request.getParameter("password");
        System.out.println(username+" : "+passsword);

        Enumeration<String> names = request.getParameterNames();
        while(names.hasMoreElements()){
            String name = names.nextElement();
            String value = request.getParameter(name);
            System.out.println(name+":"+value);
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        //前端传过来的都是String类型0
        String password = request.getParameter("password");
        System.out.println(username+" : "+password);

        String[] happy = request.getParameterValues("happy");
        System.out.println("happy:"+ Arrays.toString(happy));

        //第二种方式  获得到请求参数k和v
        Map<String, String[]> map = request.getParameterMap();
        //遍历所有键值对的键key
        for (String key : map.keySet()) {
            String[] values = map.get(key);
            System.out.println(key+":"+Arrays.toString(values));
        }
    }
}

假设有一个表单(可以将它写在JavaWeb项目运行后默认打开的index.jsp文件的<body>部分):

<form action="/项目名/demo3Servlet" method="post">
    <input type="text" name="username" value="user1">
    <input type="password" name="password" value="pass123">
    <input type="checkbox" name="happy" value="yes">Happy
    <input type="checkbox" name="happy" value="no">No Happy
    <input type="submit" value="Submit">
</form>

即:

当用户填写表单并提交时,

doPost方法会被触发,打印出以下内容:

但是普通情况下输入“localhost:8080/requestDemo/demo3Servlet?username=user1&password=pass123”(即走doGet()方法实现)

得到结果:

示例2(功能极为类似示例1)

package com.qcby.test;

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.Arrays;
import java.util.Enumeration;
import java.util.Map;

/**
 * request对象获取请求参数
 */
@WebServlet(name = "Demo4Servlet",urlPatterns = "/demo4Servlet")
public class Demo4Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //post请求解决乱码
        request.setCharacterEncoding("UTF-8");
        String username = request.getParameter("username");
        //传统解决乱码问题
        //username=new String(username.getBytes("ISO-8859-1"),"UTF-8");
        System.out.println(username);
        System.out.println("================================================");
        //第二种方式  获得到请求参数k和v
        Map<String, String[]> map = request.getParameterMap();
        //遍历所有键值对的键key
        for (String key : map.keySet()) {
            String[] values = map.get(key);
            System.out.println(key+":"+Arrays.toString(values));
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //获取get请求的参数
        //get请求在tomcat8.5以上不会乱码,7.0以下需要使用传统方式解码
        String username = request.getParameter("username");
        System.out.println(username);
        System.out.println("=====================================");
        Enumeration<String> names = request.getParameterNames();
        while(names.hasMoreElements()){
            String name = names.nextElement();
            String value = request.getParameter(name);
            System.out.println(name+":"+value);
        }
    }
}

结果:

 2.获取参数的方法

getParameter(String name):获取单个参数值。

getParameterValues(String name):获取多个参数值。

getParameterNames():获取所有参数名称。

getParameterMap():获取所有参数的Map。

单值参数接收

通过getParameter()获取表单提交的单值参数。

多值参数接收

通过getParameterValues()获取表单提交的多值参数(如复选框)。

3.中文乱码处理

POST请求:

  • 手动转码:先使用ISO-8859-1获取字节数组,再用UTF-8解码。

  • 设置编码:调用setCharacterEncoding("UTF-8")

GET请求:

  • 手动转码:与POST请求类似。

  • 服务器配置:在Tomcat的server.xml中设置URIEncoding="UTF-8"

  • 注意:Tomcat 8.5及以上版本默认支持URL传递中文。

四、请求转发重定向示例

1.向客户端响应数据(基础)

package com.qcby.test;

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;

//简单的向客户端响应例子
@WebServlet(name = "RedpondrServlet1",urlPatterns = "/redpondrServlet1")
public class RedpondrServlet1 extends HttpServlet {
    //父类HttpServlet是抽象类并且包含抽象方法,那么继承该抽象类的子类必须实现父类中的所有抽象方法,否则子类也必须被声明为抽象类。
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        //用字符的方式响应数据   字符流  中文出现乱码
        response.getWriter().write("<h3>你好,世界!!</h3>"); //响应附带格式
        response.getWriter().write("你好,世界!!");
    }
}

得到结果:

2.请求转发

package com.qcby.test;

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;

/**
 * request对象获取请求参数
 */
@WebServlet(name = "Demo5Servlet",urlPatterns = "/demo5Servlet")
public class Demo5Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        System.out.println(username);

        request.setAttribute("username","haha");

        request.getRequestDispatcher("/index.jsp").forward(request,response);
        System.out.println("========================================");
    }
}

 请求转发可以转发到任意的内部类(具体转发到哪里可以自行更改选择一个内部界面或其他)。

3.利用重定向实现向客户端相应数据(两种方式:临时重定向&重定向)

package com.qcby.test;

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;

/**
 * 向客户端相应数据
 */
@WebServlet(name = "RedpondrServlet2",urlPatterns = "/redpondrServlet2")
public class RedpondrServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /**
         * 第一种原理方式
         * 1,设置状态码  setStatus(302);
         * 2,设置响应头,重定向的请求地址  setHeader(location,/success.html)
         * 注意:地址的写法与请求转发不同因为重定向可以跨项目  地址两种写法1,绝对路径2,相对路径
         * 第二种方法
         * 重定向方式第二种自动设置状态码和头
         * response.sendRedirect("/success.html");
         */
        response.setStatus(302);  //状态码 302:告诉客户端这是一个临时重定向。
        response.setHeader("location","http://www.chaoxing.com"); //响应头 Location:告诉客户端跳转到 http://www.chaoxing.com。
        
        //重定向方式第二种自动设置状态码和头
        //response.sendRedirect("/success.html");
//        response.sendRedirect("http://www.chaoxing.com");  //普通重定向
    }
}

结果(跳转超星平台):

 五、高频面试题

转发和重定向的区别

1. 定义

请求转发(Forward)
  • 在服务器内部将请求从一个Servlet转发到另一个Servlet或JSP页面。

  • 是服务器端的跳转,客户端浏览器地址栏不会发生变化。

重定向(Redirect)
  • 服务器通知客户端浏览器访问另一个地址,客户端浏览器重新发起请求。

  • 是客户端的跳转,地址栏会显示新的地址。

2. 处理流程

流程请求转发重定向
客户端发送请求客户端发送请求到Servlet A客户端发送请求到Servlet A
Servlet处理Servlet A 调用request.getRequestDispatcher().forward(request, response)Servlet A 调用response.sendRedirect("目标地址")
服务器操作服务器内部将请求转发到目标资源(Servlet B或JSP页面)服务器返回一个302状态码和目标地址给客户端
客户端操作客户端浏览器地址栏不变,显示目标资源内容客户端浏览器根据目标地址重新发起请求,地址栏更新为新地址

3. 路径使用

相对路径
  • 转发和重定向中,相对路径的使用没有区别。

绝对路径

重定向

  • /表示服务器的根目录(如Tomcat的根目录)。

  • 示例:response.sendRedirect("/WebModule/login.jsp"),表示访问http://[hostname]:[port]/WebModule/login.jsp

请求转发

  • /表示当前Web应用程序的根目录。

  • 示例:request.getRequestDispatcher("/login.jsp").forward(request, response),表示访问当前应用下的/login.jsp

4. 其他区别

区别点请求转发重定向
地址栏变化地址栏不变地址栏更新为新地址
请求次数整个过程属于同一个请求客户端会向服务器发送两个请求
数据共享可以通过request作用域传递数据(request.setAttribute()无法使用request作用域,只能通过sessioncookie传递数据
效率更高效,因为只涉及一次请求相对低效,因为需要两次请求
跨域访问不能跨域,仅限于当前Web服务器内部可以跨域访问,客户端可以访问其他服务器
方法调用使用RequestDispatcher.forward(),属于HttpServletRequest使用response.sendRedirect(),属于HttpServletResponse
同源策略不涉及同源策略问题可能涉及同源策略问题(如跨域访问)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值