目录
一、HttpServletRequest
1.简介 :
2.常用方法 :
1° getRequestURI() :
2° getRequestURL() :
3° getRemoteHost() :
4° getHeader(String header) :
5° getParameter(name) :
6° getParameterValues(name) :
7° getMethod() :
8° setAttribute(key, value) :
9° getAttribute(key) :
10° getRequestDispatcher() :
3.获取表单数据的演示 :
4.使用细节 :
二、请求转发
1.基本介绍 :
2.应用实例 :
3.请求转发细节 :
三、HttpServletResponse
1.基本介绍 :
2.常用方法 :
3.乱码问题的解决办法 :
四、请求重定向
1.基本介绍 :
2.应用实例 :
3.使用细节 :
五、Servlet(下)总结
一、HttpServletRequest
1.简介 :
HttpServletRequest对象代表客户端的请求,当客户端 / 浏览器通过 HTTP 协议访问服务器时, HTTP请求头中的所有信息都封装在这个对象中;通过HttpServletRequest对象来调用响应的API,即可获取来自客户端的请求信息。HttpServletRequest接口的类图如下 :
2.常用方法 :
1° getRequestURI() :
获取请求的统一资源标识符(资源路径);eg : /Servlet_Demo/countServlet
2° getRequestURL() :
获取请求的统一资源定位符(绝对路径);eg : http://localhost:8080/Servlet_Demo/countServlet
PS:URL是URI的一个子集(更具体)。
3° getRemoteHost() :
获取客户端的主机名;
4° getHeader(String header) :
获取请求头;
5° getParameter(name) :
获取请求的参数;(name可以是text,password,radio,select或textarea的name属性值)
6° getParameterValues(name) :
获取请求的参数(多个值);eg : checkbox返回的数组
7° getMethod() :
获取请求的方式;eg : GET, POST, etc.
8° setAttribute(key, value) :
设置域数据;
9° getAttribute(key) :
获取域数据;
10° getRequestDispatcher() :
获取请求转发对象(实现“请求转发”的核心对象)
3.获取表单数据的演示 :
静态页面registerEX.html如下 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Register</title>
<style>
table,tr,td {
border:2px solid cornflowerblue;
border-collapse: collapse;
margin-left:auto;
margin-right:auto;
/*padding: 10px;*/
}
#tr_1 {
text-align: center;
}
</style>
</head>
<body>
<form action="http://localhost:8080/Servlet_Demo/httpServletRequestMethods" method="post">
<table>
<tr>
<th colspan="2">User Register</th>
</tr>
<tr>
<td>username:</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>password:</td>
<td><input type="password" name="password"/></td>
</tr>
<tr>
<td>Choose your favorite fruit:</td>
<td><input type="checkbox" name="fruit" value="apple"/>Apple<br/>
<input type="checkbox" name="fruit" value="strawberry"/>Strawberry<br/>
<input type="checkbox" name="fruit" value="grape"/>Grape</td>
</tr>
<tr id="tr_1">
<td><input type="submit" value="register"/></td>
<td><input type="reset" value="reset"/></td>
</tr>
</table>
</form>
</body>
</html>
页面效果如下图所示 :
HttpServletRequestMethods类代码如下 :
package down;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
(1)若重写后的doPost方法中没有做任何处理,是默认的super.doPost(req, resp);
这种情况下,浏览器会报405状态码(方法不允许)
(2)HTTP请求的内容主要分为两大类 ———— 请求头和请求体(也叫请求参数)
*/
//通过注解方式配置url
@WebServlet(urlPatterns = {"/httpServletRequestMethods"})
public class HttpServletRequestMethods extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求的统一资源标识符URI
String requestURI = req.getRequestURI();
System.out.println("URI = " + requestURI);
//2.获取请求的统一资源定位符URL
//PS:URL是URI的一个子集(更具体)。
StringBuffer requestURL = req.getRequestURL();
System.out.println(("URL = " + requestURL));
//3.获取客户端的主机地址
String remoteHost = req.getRemoteHost();
System.out.println("Host's IP = " + remoteHost);
//获取客户端的IP地址
String remoteAddr = req.getRemoteAddr();
System.out.println("Addr = " + remoteAddr);
//4.获取请求头
//客户端的主机名(IP + 端口)
String host = req.getHeader("Host");
System.out.println("Host = " + host);
//请求的发起地址
String referer = req.getHeader("Referer");
System.out.println("Referer = " + referer);
//请求的用户信息
String userAgent = req.getHeader("User-Agent");
System.out.println("User-Agent = " + userAgent);
System.out.println("Browser = " + userAgent.split(" ")[userAgent.split(" ").length - 1]);
/*======================================获取表单数据======================================*/
//5.获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("text = " + username);
System.out.println("password = " + password);
//6.获取请求的参数(多个值)
String[] fruits = req.getParameterValues("fruit");
for (String fruit : fruits) {
System.out.println("The checkbox elements you choose:" + fruit);
}
//7.获取请求的方式(GET POST etc)
String method = req.getMethod();
System.out.println("method = " + method);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
运行效果 :(如下GIF图)
4.使用细节 :
1° 为防止“表单提交的数据出现乱码”问题,可以在使用req.getParameter(string)方法前,调用req.setCharacterEncoding("utf-8")方法。
2° 为防止“服务器返回给浏览器的数据出现乱码”问题,可以在获取PrintWriter对象前,调用resp.setContentType("text/html; charset=utf-8")方法。(对应Http响应的响应头Content-Type)
二、请求转发
1.基本介绍 :
当业务比较复杂时,一次请求可能需要多个Servlet来完成(eg : Servlet链的流水作业)。如下图所示 :
请求转发,即指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。
HttpServletRequest对象提供了getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。
HttpServletRequest对象同时也是一个域对象,开发人员通过HttpServletRequest对象可以在实现转发时,把数据通过request对象带给其它web资源来处理。
常用方法如下——
- setAttribute方法
- getAttribute方法
- removeAttribute方法
- getAttributeNames方法
2.应用实例 :
要求定义VerifyServlet和ReplyServlet两个servlet资源,前者用于对表单提交的数据进行校验,并令Tomcat去调用ReplyServlet来处理校验后的数据;后者用于处理数据并反馈给浏览器。
register.html代码如下 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Register</title>
</head>
<body>
<h1>User Register</h1>
<form action="http://localhost:8080/Servlet_Demo/verifyServlet" method="post">
username:<input type="text" name="username"/> <br/><br/>
<input type="submit" value="register"/>
</form>
</body>
</html>
VerifyServlet类代码如下 :
package down.req;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author : Cyan_RA9
* @version : 21.0
*/
@WebServlet(urlPatterns={"/verifyServlet"})
public class VerifyServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("VerifyServlet's doPost is invoked~");
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
if ("Cyan".equals(username)) {
req.setAttribute("status", "Manager");
} else {
req.setAttribute("status", "Employee");
}
/**
(1) /replyServlet是要转发的servlet的url
(2) "/"会被Tomcat解析成"/Servlet_Demo",即当前Web工程路径
如果开头没写/,默认会隐含一个/。
(3) forward(request,response)表示把当前servlet的request对象和response对象,
传递给下一个servlet使用 (相同)
*/
//获取分发器
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/replyServlet");
requestDispatcher.forward(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
ReplyServlet类代码如下 :
package down.req;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author : Cyan_RA9
* @version : 21.0
*/
@WebServlet(urlPatterns = {"/replyServlet"})
public class ReplyServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ReplyServlet's doPost is invoked~");
String username = req.getParameter("username");
String status = (String) req.getAttribute("status");
resp.setContentType("text/html; charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.print("" +
"<table border=\"2px\"; bordercolor=\"pink\" cellspacing=\"0\" cellpadding=\"10px\">" +
"<tr>" +
"<td colspan = 2>The data you submitted : </td>" +
"</tr>" +
"<tr>" +
"<th>username: </th>" +
"<th>" + username + "</th>" +
"</tr>" + "<tr><th>status: </th><th>" + status + "</th>" +
"</tr>" +
"</table>");
writer.flush();
writer.close();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
运行效果 : (如下GIF图)
3.请求转发细节 :
- 浏览器地址栏的URL不会变化 (地址会保留在第1个servlet的url)。因为“请求转发”的整个过程都是在服务器端进行的,与浏览器没有关系;最终仍是Tomcat以HTTP响应的方式回显给浏览器。
- 同一次HTTP请求中可进行多次转发;同一次HTTP请求中,进行多次转发,多个Servlet可以共享request域/对象的数据(因为始终是同一个request对象)。
- “请求转发”也可以转发到WEB-INF目录下(做项目使用)
- “请求转发”不能访问当前WEB工程外的资源。(404)
- 因为浏览器地址栏会停止在第一个servlet,因此,如果刷新页面,会再次发出请求(并且会携带数据),所以在支付页面等情况下,不要使用请求转发,否则会造成重复支付。
三、HttpServletResponse
1.基本介绍 :
每次 HTTP 请求, Tomcat 会创建一个 HttpServletResponse 对象传递给 Servlet 程序去使用。HttpServletRequest表示请求过来的信息,而 HttpServletResponse则 表示所有响应的信息, 如果需要设置返回给客户端的信息,通过 HttpServletResponse 对象来进行设置即可( 最终仍是由Tomcat以HTTP响应的方式将数据返回给客户端 )。HttpServletResponse类图如下 :
2.常用方法 :
1.字节流getOutputStream() :
常用于下载文件(处理二进制数据)
2.字符流getWriter() :(之前举过的例子用过)
常用于回显字符串
Δ细节:两个流只能同时使用一个——使用了字节流,就不能再使用字符流,反之亦然,否则就会报错
3.乱码问题的解决办法 :
方式一 —— 老办法(最好用):
resp.setContentType("text/html; charset = utf-8");
setContentType方法会同时设置服务器端和客户端都使用utf-8字符集编码,并且还设置了响应头,但setContentType必须在获取流对象之前调用。
方式二 —— 新办法(也还行):resp.setCharacterEncoding("utf-8"); //先设置服务器端使用utf-8编码
resp.setHeader("Content-Type", "text/html; charset = utf-8"); /*再通过响应头的方式设置浏览器端的编码 */
四、请求重定向
1.基本介绍 :
请求重定向 指:一个 web 资源收到客户端请求后,通知 客户端 去访问另外一个 web 资源,这称之为请求重定向。请求重定向中,负责重定向功能的servlet会将响应状态码修改为302(表示请求重定向),然后设置一个Location属性,用于告知浏览器下一次请求该访问哪个资源。[sendRedirect("/web工程名/web资源")方法]
2.应用实例 :
有一个超链接的页面,要求该超链接导向一个servlet,而该servlet会通过“请求重定向”通知浏览器端去访问另外一个servlet。(Servlet此处采用注解方式配置)
redirection.html代码如下 :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redirection Demo</title>
</head>
<body>
<h1>⭐408资料分享⭐</h1>
<a href="http://localhost:8080/Servlet_Demo/old" target="_self">
快点我!点我下载数据结构1800题!
</a>
</body>
</html>
OldServlet类代码如下 :
package down.resp;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author : Cyan_RA9
* @version : 21.0
*/
@WebServlet(urlPatterns = {"/old"})
public class OldServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
(1) sendRedirect方法本质上就会返回302(重定向)状态码,并且设置Location响应头;
(2) 与请求转发不同,“请求重定向”的解析不是在服务器端进行的,而是由浏览器解析;
此处的"/"会被浏览器解析为"http://localhost:8080/";
(3) So, “请求重定向”时,sendRedirect方法中的格式必须是“/Web应用名/Web资源”
注意第一个斜杠!(如果开头没有写斜杠,默认会隐含一个斜杠!)
*/
resp.sendRedirect("/Servlet_Demo/new");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
NewServlet类代码如下 :
package down.resp;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author : Cyan_RA9
* @version : 21.0
*/
@WebServlet(urlPatterns={"/new"})
public class NewServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//注意此处MIME类型的使用
resp.setContentType("application/x-tar; charset=utf-8");
//如果想看到浏览器地址栏的变化,可以使用"text/html"MIME类型
PrintWriter writer = resp.getWriter();
writer.print("数据结构1800题pdf!");
writer.flush();
writer.close();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
运行效果 : (如下GIF图)
3.使用细节 :
1° "302" 的最佳应用场景 —— 网站迁移。比如网站的域名变更,原域名是 www.CyanRA9.com 迁移到新域名 www.CyanRA9.cn,但是浏览器抓取的仍然是原来的域名,这时就可以通过一个请求重定向来解决问题。
2° “请求重定向”的使用中,浏览器地址栏会发生变化(最终停留在新的web资源的URL),本质是两次HTTP请求。
3° 不能共享HttpServletRequest域中的数据,因为本质是两次HTTP请求,会生成两个不同的HttpServletRequest对象
4° 不能重定向到 /WEB-INF 下的资源(受保护)
5° 可以重定向到 Web 工程以外的资源, 比如到其他网站(必应之类的)
6° 请求重定向有两种方式——(1) resp.sendRedirect("/web项目名/web资源"); //推荐第一种!
(2) resp.setStatus(302);
resp.setHeader("Location", "/Servlet_Demo/new");
7° 可以使用getServletContext().getContextPath() 方法来获取当前Web项目的工程路径(动态获取工程路径),得到工程路径后,再以字符串拼接的形式(工程路径 + 具体的web资源)传递给sendRedirect方法。
五、Servlet(下)总结
(1) 掌握HttpServletRequest的常用方法(eg : URL和URI的区别;获取请求头的方法;获取表单提交数据的多种方式)
(2) 掌握请求转发的底层原理(同一个域对象),以及如何实现请求转发。
(3) 掌握HttpServletResponse回显数据给浏览器的具体步骤,以及如何解决乱码问题。
(4) 掌握请求重定向的底层原理,以及重定向的具体实现(注意与请求转发格式的区别!)
System.out.println("END---------------------------------------------------------------------------------");