HTTPServletRequest对象
HTTPServletRequest对象:主要作用是用来接受客户端送过来的请求信息.
例如:请求的参数,发送的头信息
servic()形参接收的是HttpAServletRequest接口的实例化对象,
表示该对象主要应用在HTTP协议上,该对象是由Tomcat封装好传递过来的
(- 当客户端发送 HTTP 请求时,Tomcat 会解析原始请求数据(如 TCP 报文),并生成一个实现了 HttpServletRequest
接口的对象(例如 Tomcat 中的 org.apache.catalina.connector.RequestFacade
类)。)
HTTPServletrequest 是ServeletRequest的子接口,(专门为 HTTP 协议设计,因此比父接口多了 HTTP 相关的方法(如 getHeader()
、getCookies()
))
HttpServletRequest
中定义了 HTTP 协议特有的方法,例如:String getMethod(); // 获取 HTTP 方法(GET/POST) String getHeader(String name); // 获取请求头 Cookie[] getCookies(); // 获取 Cookie
ServeletRequest只有一个子接口,就是HttpServletRequest 既然只有一个子接口为何不将两个接口合并为一个接口呢
从长远来看,现在主要用的是HTTP协议,但以后可能会出现 更多的新的协议.若以后要支持这种新协议,只需要直接继承 SERvletRequest接口就好了
接收请求
1.方法
package com.xxx.servlet;
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;
@WebServlet("/ser01")
public class Servlet01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
// 统一设置请求和响应编码为 UTF-8 req.setCharacterEncoding("UTF-8");
res.setCharacterEncoding("UTF-8");
// 设置响应内容类型(可选但建议)
res.setContentType("text/html; charset=UTF-8");
/*常用方法*/
System.out.println("hell0 你好");
//获取请求是的完整路径 (从Http开始,到"?"前面结束)
String url = req.getRequestURL()+" ";
System.out.println("获取请求时的完整路径"+url);
//获取请求时的部分路径 (从项目的部分路径开始,到"?"前面结束
String uri = req.getRequestURI();
System.out.println("获取请求的部分路径"+uri);
//获取请求时的参数字符串 (从"?"后面开始,到最后的字符串)
String queryString = req.getQueryString();
System.out.println("获取请求时的参数字符串"+queryString);
//获取请求方式(GET或POST)
String method = req.getMethod();
System.out .println("获取方式"+method);
//获取当前的协议版本(HTTP/1.1)
String prototol=req.getProtocol();
System.out.println("获取当前协议版本"+prototol);
//获取项目的站点名 (项目对外访问路径)
String webapp=req.getContextPath();
System.out.println("获取项目的站点名"+webapp);
/*获取请求的参数*/
//获取指定名称的参数值,返回字符串(重点!!!)
String uname=req.getParameter("uname");
String upwd=req.getParameter("upwd");
System.out.println("uname: "+uname+",upwd: "+upwd);
//获取指定名称的参数的所有参数值,返回字符串数组(用于复选框传值)
String[]hobbys=req.getParameterValues("hobby");
if(hobbys!=null&&hobbys.length>0){
for(String hobby:hobbys){
System.out.println("爱好"+hobby);
}
}
}
}
乱码
![[Pasted image 20250302165232.png]]
-Dfile.encoding=UTF-8
- 原因:Tomcat 控制台未正确处理 GBK 编码的中文输出。
- 解决:
- 进入
Run → Edit Configurations → Tomcat
。 - 在
VM options
中添加:
- 进入
- -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
请求乱码
post 会乱码
通过设置服务器解析编码时的格式
request.setCharacterEncoding("UTF-8);
映射
web.xml 配置(可选)
如果未使用注解 @WebServlet
,需在 web.xml
中添加:
xml
<servlet>
<servlet-name>Servlet02</servlet-name>
<servlet-class>com.example.Servlet02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet02</servlet-name>
<url-pattern>/Servlet02</url-pattern>
</servlet-mapping>
请求转发
“请求转发” 通常指将接收到的请求(如网络请求、API调用等)从一个服务或节点传递到另一个服务或节点的过程
请求转发的核心函数
request.getRequestDispatcher("目标资源路径").forward(request, response);
作用:将当前请求和响应对象转发到服务器内部的其他资源(如 JSP、Servlet 等)。
/**
请求转发
* 可以让请求从服务端跳转到客户端(或者跳到指定的Servlet)
* 特点
1.服务端行为
2.地址栏不发生改变
3.从始至终只有一个请求
4.数据可以共享
*/
ser04共享了ser03的数据
![[Paste
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uname=req.getParameter("uname");
System.out.println("Servelt03 uname : "+uname);
//请求跳转到Servlet04
// req.getRequestDispatcher("ser04").forward(req,resp);
//请求跳转到jsp页面
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uname=req.getParameter("uname");
System.out.println("Servelt03 uname : "+uname);
//请求跳转到Servlet04
// req.getRequestDispatcher("ser04").forward(req,resp);
//请求跳转到jsp页面
// req.getRequestDispatcher("login.jsp").forward(req, resp);
//请求跳转到html页面
req.getRequestDispatcher("login.html").forward(req, resp);
}
request作用域
此时05和06不是一个请求,若让05和06是一个请求,使用请求转发
package com.xxx.servlet;
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.util.ArrayList;
import java.util.List;
/**request作用域
* 通过该对象在一个请求中传递数据,作用域范围:在一次请求中有效,及服务器条装有效(请求和转发跳转有效)
* //设置域对象内容
* request.setAttribute(String name,Object value)
* //获取域对象内容
* request.getAttribute(String name);
* //删除域对象内容
* request.removeAttribute(String name);
*/@WebServlet("/ser05")
public class Servlet05 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servelt05 service");
//设置域对象内容
req.setAttribute( "name","admin");
req.setAttribute( "age",19);
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
req.setAttribute( "list", list);
//req.getRequestDispatcher("ser06").forward(req, resp);
req.getRequestDispatcher("index.jsp").forward(req, resp);
}
}
package com.xxx.servlet;
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.util.List;
@WebServlet("/ser06")
public class Servlet06 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet06 service");
String name =(String) req.getAttribute("name");
System.out.println("name: "+name);
// 或者获取请求作用域中的属性(如果有其他代码设置)
Integer age = (Integer) req.getAttribute("age");
System.out.println("age : " + age);
List<String> list =(List<String>) req.getAttribute("list");
System.out.println(list.get(0));
}
}
![[Pasted image 20250302223731.png]]
<%@ page import="java.util.List" %>
<%@ page contentType="text/html; charset=UTF-8" language="java"%>
<!DOCTYPE html>
<html>
<head>
<title>JSP - Hello World</title>
</head>
<body>
<h1><%= "Hello World!" %>
</h1>
<br/>
<a href="/ser01">Hello Servlet</a>
<%--如果在jsp中写Java代码,需要写在此段--%>
<%
//获取域对象
//获取域对象内容
System.out.println("Servlet06 service");
String name =(String) request.getAttribute("name");
System.out.println("name: "+name);
// 或者获取请求作用域中的属性(如果有其他代码设置)
Integer age = (Integer) request.getAttribute("age");
System.out.println("age : " + age);
List<String> list =(List<String>) request.getAttribute("list");
System.out.println(list.get(0));
%>
</body>
</html>
![[Pasted image 20250302223617.png]]
HttpServletResponse对象
响应数据
接受客户端请求后,可以通过HttpServletResponse对象直接进行响应,响应时获取输出流
两种形式:
getWrite() 获取字符流 (只能响应回字符)
getOutputStream() 获取字节流(能响应一切数据)
getWrite()
getOutputStream()
二者不能同时使用
响应乱码
由于浏览器默认打开的时候采用的字符集编码是ISO-8895-1格式的编码,该编码不支持中文
设置浏览器默认打开的时候采用的字符集编码
resp.setCharacterEncoding("UTF-8");
还需要客户端指定的解码方式
resp.setHeader("content-type","text/html;charset=UTF-8");
保证发送端和接受端的编码一致且都支持中文,可以解决乱码
同时设置客户端和服务端的编码模式
resp.setContentType("text/html;charset=UTF-8");
重定向
重定向(Redirection)是一种将用户从一个URL(统一资源定位符)自动引导到另一个URL的技术
通过浏览器可以看到第一次请求获得的响应码位302,并且含有一个location头信息
实现机制
- 重定向:
- 是服务器向客户端发送一个特殊的响应(通常是状态码为302的响应),告诉客户端需要请求另一个新的URL 。客户端收到这个响应后,会自动发起一个新的请求到指定的新URL。
- 涉及两次HTTP请求和响应过程。例如,用户访问
http://example.com/page1
,服务器返回302状态码并告知客户端去访问http://example.com/page2
,客户端接着向http://example.com/page2
发起新的请求。
- 请求转发:
- 是服务器内部的一种操作,由服务器直接将当前请求转发到另一个资源(如另一个Servlet、JSP页面等)进行处理,客户端并不知道请求已经被转发。
- 整个过程只有一次HTTP请求,客户端只发送了一次请求,服务器内部完成了请求的处理和转发。
区别
数据不共享
请求转发是根据当前路径找地址的
package com.xxx.servlet;
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. 请求转发的地址栏不会发生改变,重定向的地址栏会发生改变
* 2. 请求转发只有一次请求,重定向有两次请求
* 3. 请求转发的request对象可共享,重定向时request对象不共享
* 4. 请求转发是服务端行为,重定向是客户端行为
* 5. 请求转发时的地址只能时当前(当下项目)的资源,重定向时地址可以是任何地址
*/
@WebServlet("/ser06")
public class Servlet06 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet06...");
//请求参数
String uname = req.getParameter("uname");
System.out.println(uname);
//设置request参数
req.setAttribute("upwd", "123456");
//请求转发
//req.getRequestDispatcher("index.jsp").forward(req, resp);
//重定向
// resp.sendRedirect("index.jsp");
//重定位到百度
resp.sendRedirect("http://www.baidu.com");
//请求转发到百度
// req.getRequestDispatcher("http://www.baidu.com").forward(req, resp);
}
}
请求转发在以下场景中具有显著优势:
1. 效率更高(单次请求)
- 请求转发:由服务器内部完成资源跳转,客户端仅发起一次请求,服务器直接转发到目标资源,减少网络开销。
- 重定向:服务器返回
302/307
状态码,客户端需发起第二次请求,增加网络延迟和带宽消耗。
适用场景:对性能要求高的内部跳转(如登录后跳转首页)。
2. 数据共享更方便(保留原始请求信息)
- 请求转发:通过
request
对象共享数据(如request.setAttribute()
),目标资源可直接获取原始请求的参数和属性。 - 重定向:两次请求完全独立,需通过
URL 参数
、Session
或数据库
间接传递数据,可能引发安全风险(如 URL 参数暴露敏感信息)。
适用场景:需要在多个页面间传递复杂数据(如表单处理结果)。
3. 路径更灵活(支持相对路径)
- 请求转发:使用服务器端路径(如
/page.jsp
),无需包含应用上下文(Context Path)。 - 重定向:必须指定完整路径(如
http://domain/app/page.jsp
),若应用部署路径变更,需修改所有重定向代码。
适用场景:动态生成跳转路径时更易维护(如跨模块跳转)。
4. 用户体验更连贯(地址栏不变)
- 请求转发:客户端地址栏显示原始请求 URL,用户感知不到跳转过程。
- 重定向:地址栏变为目标 URL,可能暴露内部逻辑或导致用户困惑。
适用场景:隐藏后端处理流程(如 RESTful API 的分步操作)。
5. 避免重复提交问题(保留请求方法)
- 请求转发:保持原始请求方法(如 POST),适合表单提交后的结果页面跳转。
- 重定向:默认使用 GET 方法,可能导致表单重复提交(需配合
PRG 模式
解决)。
适用场景:防止用户刷新页面时重复提交表单数据。
6. 对 SEO 更友好(保留原始 URL)
- 请求转发:最终内容与原始 URL 关联,搜索引擎权重集中在同一页面。
- 重定向:尤其是临时重定向(302),可能导致搜索引擎分散权重。
以下情况仍需使用重定向:
- 跳转到外部站点(如第三方支付页面)。
- 需要客户端更新地址栏(如登录后跳转到用户主页)。
- 避免浏览器缓存原始请求结果(如强制刷新资源)。
如果想共享request对象的话 ,可以使用请求转发
如果想跳转到不是本站的地址,可以重定向