认识HttpServletRequest和HttpServletResponse

hi,大家好,上一期我们认识了HttpServlet,这一期我们来认识一下HttpServletRequest和HttpServletResponse
认识HttpServletRequest和HttpServletResponse_第1张图片

HttpServletRequest

1.核心方法介绍

2.代码举例展示

HttpServletResponse

1.核心方法展示

2.代码举例展示

1.HttpServletRequest

一个http请求,在Tomcat收到http请求,就会解析成上述的HttpServletRequest对象,HTTP 请求报文里面有啥,这个类里面就有啥
来看它的核心方法

方法 描述
String getProtocol() 返回请求协议的名称和版本
String getMthod() 返回请求的HTTP方法的名称,例如get,post,或者put
String getRequest()URI 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请
求的 URL 的一部分。
String getContextPath() 返回指示请求上下文的请求 URI 部分。
String getQueryString() 返回包含在路径后的请求 URL 中的查询字符串。
EnumerationgetParameterNames() 返回一个 String 对象的枚举,包含在该请求中包含的参数的名称。
String getParameter(Stringname) 以字符串形式返回请求参数的值,或者如果参数不存在则返回null。
String[]getParameterValues(Stringname) 返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null
EnumerationgetHeaderNames() 返回一个枚举,包含在该请求中包含的所有的头名。
String getHeader(Stringname) 以字符串形式返回指定的请求头的值。
StringgetCharacterEncoding() 返回请求主体中使用的字符编码的名称。
String getContentType() 返回请求主体的 MIME 类型,如果不知道类型则返回 null。
int getContentLength() 以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 - 1
InputStreamgetInputStream() 用于读取请求的 body 内容. 返回一个 InputStream 对象.

通过上述的方法可以获取一个请求的各个方面的信息
细心的同学可以发现方法都是get类型的,因为请求是服务器获取到的内容,不应该修改,所以都是get方法,没有set
解释一下这个方法里的URI,URI和URL不是一个东西
URL是唯一资源定位符,URI是唯一资源标识符,也可以认为URI包含于URL中,概念非常相似,很多时候就会混着用

注意一下最后一个方法,通过InputSream,进一步读取body的内容,如果确实需要按照字符处理,手动转换即可

我们都知道InputStream是按照字节流读取,为啥不按照字符流嘞?
字节流比字符流更加通用,当前数据如果是文本,那么用字符流或者字节流都行,如果数据是二进制的,那么就只能用字节流

HTTP是超文本协议,但是其实http的body也可以携带二进制数据
比如请求或者响应的body压缩过的的话,此时的body就是二进制的,当然了,大部分的请求的body都不是二进制

==================================================
下面我们用代码来认识一下这些方法
前五个我们已经在之前学习了,这里就不再赘述了~~~

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;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-09
 * Time: 16:57
 */
@WebServlet("/showRequest")
public class ShowRequest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        StringBuilder result=new StringBuilder();
        result.append(req.getProtocol());
        result.append("
"
); result.append(req.getMethod()); result.append("
"
); result.append(req.getRequestURI()); result.append("
"
); result.append(req.getQueryString()); result.append("
"
); result.append(req.getContextPath()); result.append("
"
); result.append("============================="); /* Enumeration headerNames=req.getHeaderNames(); while(headerNames.hasMoreElements()){ String headerName=headerNames.nextElement(); String headerValue=req.getHeader(headerName); result.append(headerName+":"+headerValue+"
"); }*/
//设置响应格式便于让浏览器解析 resp.setContentType("text/html; charset=utf8"); resp.getWriter().write(result.toString());//转换成字符串的形式 } }

运行代码看看结果
认识HttpServletRequest和HttpServletResponse_第2张图片
在这里我不小心将result.toString()写成了resp.toString(),就出现了另一个结果
认识HttpServletRequest和HttpServletResponse_第3张图片
这一段其实就是resp对象的地址了
getParameter是最常用的API之一
前端给后端传递数据,是非常常见的需求

1.通过querystring 传递
2.通过body(form表单的形式)
3.通过body(json格式)

下面我们分别来说
1.通过query string传递

我们约定前端通过query string传递username和password
看后端代码咋写

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;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-09
 * Time: 18:16
 */
@WebServlet("/getParameter")
public class GetParameter  extends HttpServlet {
    //前端通过query string传递username和password两个属性

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username=req.getParameter("username");
        if(username==null){
            System.out.println("username这个key在query string不存在");

        }
        String password=req.getParameter("password");
        if(password==null){
            System.out.println("password这个key在query string不存在");
        }
        System.out.println("username="+username+",password="+password);
        resp.getWriter().write("ok");

    }


}

打开浏览器

认识HttpServletRequest和HttpServletResponse_第4张图片
认识HttpServletRequest和HttpServletResponse_第5张图片

2.通过body(form表单形式)

相当于body存的格式和query string一样,但是Content-Type是
application/x-www-form-urlencoded,也是通过getParameter来获取键值对

构造post请求(一般来说都是post请求有body)

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;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-09
 * Time: 18:16
 */
@WebServlet("/getParameter")
public class GetParameter  extends HttpServlet {
    //前端通过query string传递username和password两个属性

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username=req.getParameter("username");
        if(username==null){
            System.out.println("username这个key在query string不存在");

        }
        String password=req.getParameter("password");
        if(password==null){
            System.out.println("password这个key在query string不存在");
        }
        System.out.println("username="+username+",password="+password);
        resp.getWriter().write("ok");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //前端通过body,以form表单的格式,将username和password传给服务器
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        if(username==null){
            System.out.println("username这个key在body 不存在");
        }
        if(password==null){
            System.out.println("password这个key在body不存在");
        }

        System.out.println("username"+username+",password"+password);
        resp.getWriter().write("ok");




    }
}

这个请求是一个post请求,我们使用postman构造这个请求
认识HttpServletRequest和HttpServletResponse_第6张图片
认识HttpServletRequest和HttpServletResponse_第7张图片

认识HttpServletRequest和HttpServletResponse_第8张图片

可以看到成功返回结果

有一个问题,键值对的value是否可以是中文呢?
认识HttpServletRequest和HttpServletResponse_第9张图片

在这里插入图片描述
我们看到结果依然返回,但是这其实只是一个巧合

在URL中,如果query string 中包含中文或者特殊字符,必须使用urlencode的方式进行转码.如果直接写中文或者特殊字符,会有风险!
认识HttpServletRequest和HttpServletResponse_第10张图片

在这里插入图片描述

一敲回车
在这里插入图片描述
在这里插入图片描述

结果显示张三

如果不转码,有些浏览器或者http服务器,对中文支持不好的话,出现问题
一搬来说服务器解码(urldecode),Servlet已经处理好了,前端编码(urlencode)

post请求中
用postman来看更加直观
认识HttpServletRequest和HttpServletResponse_第11张图片
在这里插入图片描述
直接乱码了,为什么会出现乱码呢,前端默认是utf8编码方式,但是后端不知道啊,所以要给请求设置编码方式
认识HttpServletRequest和HttpServletResponse_第12张图片

此时
认识HttpServletRequest和HttpServletResponse_第13张图片

在这里插入图片描述
结果就不会乱码了

3.使用body(json格式)
json也是键值对格式的数据,要拿到key和value,但是Servlet自身没有内置json解析功能,我们拿到的就只是字符串,拿不到key和对应的value,咋办捏
我们采用第三方库,用来处理json的第三方库有很多,我们使用jackson
要引入依赖
认识HttpServletRequest和HttpServletResponse_第14张图片

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>servlet</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>


    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.0</version>
        </dependency>


    </dependencies>
    <packaging>war</packaging>
    <build>
        <finalName>hello_servlet</finalName>
    </build>
</project>

认识HttpServletRequest和HttpServletResponse_第15张图片
在这里插入图片描述
下面来解释一下这个代码的执行流程
在这里插入图片描述
认识HttpServletRequest和HttpServletResponse_第16张图片
readvalue的作用(json字符串转换成Java对象)
1.通过readValue解析json字符串转化成若干键值对
2.根据第二个参数User.class找到User里面的public的属性,依次遍历
3.根据属性名字,去准备好的键值对查询是否存在对应的value,然后赋值给该属性

总结:HttpServletRequest,这个类,主要就是用于获取到请求的各个方面的信息,尤其是前端传过来的自定义数据,自定义数据通过query
string,post body (form),post body(json)来体现

2.HttpServletResponse

依旧先来看核心方法

方法 描述
void setStatus(int sc) 为该响应设置状态码
void setHeader(String name,String value) 设置一个带有给定的名称和值的header,如果那么name已经存在,则覆盖旧的值
void addHeader(Stringname, String value) 添加一个带有给定的名称和值的 header. 如果 name 已经存在,不覆盖旧的值, 并列添加新的键值对
void setContentType(Stringtype) 设置被发送到客户端的响应的内容类型。
voidsetCharacterEncoding(Stringcharset) 设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。
void sendRedirect(Stringlocation) 使用指定的重定向位置 URL 发送临时重定向响应到客户端
PrintWriter getWriter() 用于往 body 中写入文本格式数据.
OutputStreamgetOutputStream() 用于往 body 中写入二进制格式数据.

面对空的响应对象就需要设置一些属性了
也依然通过代码来看

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;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-09
 * Time: 20:46
 */
@WebServlet("/status")
public class StatusServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(200);
        resp.setContentType("text/html charset=utf8");
        resp.getWriter().write("返回200响应");
    }
}

这个是设置状态码,根据需要自己设置
结果
在这里插入图片描述
通过header实现自动刷新效果

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;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-09
 * Time: 20:58
 */
@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //每隔一秒自动刷新一次
        resp.setHeader("Refresh","1");
        resp.getWriter().write("time="+System.currentTimeMillis());
    }
}

认识HttpServletRequest和HttpServletResponse_第17张图片
这个结果是一个动态的,时间一直在变
实现重定向

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;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: WHY
 * Date: 2023-06-09
 * Time: 21:03
 */@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //当用户访问这个路径自动重定向到百度
        /*resp.setStatus(302);
        resp.setHeader("Location","https://www.baidu.com");*/
        resp.sendRedirect("https://www.bidu.com");

    }
}

以上就是今天所有的内容,我们下期再见,886~~~
认识HttpServletRequest和HttpServletResponse_第18张图片

你可能感兴趣的:(java,前端,servlet)