hi,大家好,上一期我们认识了HttpServlet,这一期我们来认识一下HttpServletRequest和HttpServletResponse
一个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());//转换成字符串的形式
}
}
运行代码看看结果
在这里我不小心将result.toString()写成了resp.toString(),就出现了另一个结果
这一段其实就是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");
}
}
打开浏览器
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构造这个请求
可以看到成功返回结果
在URL中,如果query string 中包含中文或者特殊字符,必须使用urlencode的方式进行转码.如果直接写中文或者特殊字符,会有风险!
结果显示张三
如果不转码,有些浏览器或者http服务器,对中文支持不好的话,出现问题
一搬来说服务器解码(urldecode),Servlet已经处理好了,前端编码(urlencode)
post请求中
用postman来看更加直观
直接乱码了,为什么会出现乱码呢,前端默认是utf8编码方式,但是后端不知道啊,所以要给请求设置编码方式
3.使用body(json格式)
json也是键值对格式的数据,要拿到key和value,但是Servlet自身没有内置json解析功能,我们拿到的就只是字符串,拿不到key和对应的value,咋办捏
我们采用第三方库,用来处理json的第三方库有很多,我们使用jackson
要引入依赖
<?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>
下面来解释一下这个代码的执行流程
readvalue的作用(json字符串转换成Java对象)
1.通过readValue解析json字符串转化成若干键值对
2.根据第二个参数User.class找到User里面的public的属性,依次遍历
3.根据属性名字,去准备好的键值对查询是否存在对应的value,然后赋值给该属性
总结:HttpServletRequest,这个类,主要就是用于获取到请求的各个方面的信息,尤其是前端传过来的自定义数据,自定义数据通过query
string,post body (form),post body(json)来体现
依旧先来看核心方法
方法 | 描述 |
---|---|
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());
}
}
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");
}
}