6.HttpServletRequest对象

本文深入讲解Servlet如何处理HTTP请求,包括获取请求行信息、请求头、实现防盗链及请求参数的解析,帮助读者理解Servlet的工作机制。

1.获取请求行消息的方法

当访问Servlet时,会在请求消息的请求行中,包含请求方法、请求资源名,请求路径等信息,为了获取这些信息,在HttpServletRequest接口中,定义了一系列用于获取请求行信息的方法,如下表所示
在这里插入图片描述
在这里插入图片描述

response.setContentType("text/html;charset=utf-8");
 PrintWriter out = response.getWriter();
 out.println("getRequestURL : " + request.getRequestURL() + "<br>");
 out.println("getScheme : " + request.getScheme() + "<br>");
 out.println("getServerName : " + request.getServerName() + "<br>");
 out.println("getServerPort : " + request.getServerPort() + "<br>");
 out.println("getContextPath : " + request.getContextPath() + "<br>");
 out.println("getServletPath : " + request.getServletPath() + "<br>");
 out.println("getRequestURI : " + request.getRequestURI()+ "<br>");
 out.println("getQueryString : " + request.getQueryString()+ "<br>");    
 out.println("getRemoteAddr : " + request.getRemoteAddr() + "<br>");
 out.println("getRemoteHost : " + request.getRemoteHost() + "<br>");
 out.println("getRemotePort : " + request.getRemotePort() + "<br>");
 out.println("getLocalAddr : " + request.getLocalAddr() + "<br>");
 out.println("getLocalName : " + request.getLocalName() + "<br>");
 out.println("getLocalPort : " + request.getLocalPort() + "<br>"); 

getRequestURL : http://localhost:8080/s6
运行结果:
getScheme : http

getServerName : localhost

getServerPort : 8080

getContextPath :

getServletPath : /s6

getRequestURI : /s6

getQueryString : null

getRemoteAddr : 0:0:0:0:0:0:0:1

getRemoteHost : 0:0:0:0:0:0:0:1

getRemotePort : 22504

getLocalAddr : 0:0:0:0:0:0:0:1

getLocalName : 0:0:0:0:0:0:0:1

getLocalPort : 8080

注意:getLocalPort 与getServerPort 的区别
如果tomcat服务器端口是80,对外端口是通过防火墙设置后映射出来的,为8050,
用getLocalhost获取到的是80端口,
用getServerPort获取到的是8050端口。

2.获取请求消息头

请求消息头用于向服务器传递附加信息,为了获取这些信息, HttpServletRequest接口定义了一系列用于获取请求消息头的方法
代码:

response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
 Enumeration headerNames =request.getHeaderNames();// 获取请求消息中所有头字段
    // 使用循环遍历所有请求头,并通过getHeader()方法获取一个指定名称的头字段
 while(headerNames.hasMoreElements()) {
    String headerName = (String)headerNames.nextElement();
    out.print(headerName + " : " + request.getHeader(headerName)+ "<br>");
 }

结果:

host : localhost:8080
user-agent : Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101Firefox/40.0
accept : text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
accept-language : zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
accept-encoding : gzip, deflate
connection : keep-alive

3.防盗链

原理:在下载服务器上,来判断一下上一步提交的网址(来源)是不是我要求的,如果是我要求的,那么可以下载,如果不是,不让下载。
sitePath:http://127.0.0.1
Path:http://127.0.0.1:8080/JavaTeachR/index.jsp
HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。

Download.html

<html>
         <head>
                   <title>Insert titlehere</title>
         </head>
         <body>
                   <a href="/chapter05/DownManagerServlet">download</a>
         </body>
</html>

对链接进行处理

response.setContentType("text/html;charset=utf-8");
PrintWriter out =response.getWriter();
String referer =request.getHeader("referer");// 获取referer头的值
String sitePart = "http://"+ request.getServerName();// 获取访问地址
// 判断referer头是否为空,这个头的首地址是否以sitePart开始的
if (referer != null&& referer.startsWith(sitePart)) {
         // 处理正在下载的请求
         out.println("dealingdownload ...");
} else {
//  out.print("您没有权限下载,3秒后跳转到主页进行下载");
response.setHeader("Refresh","3;URL=http://localhost:8080/Download.html");
// 非法下载请求跳转到download.html页面

  RequestDispatcher rd= request.getRequestDispatcher("/download.html");

  rd.forward(request,response);

}

4.获取请求参数

form.html

<form action="/JavaTeach/servlet01"method="POST">

    用户名:<input type="text"name="username"><br>

    密码:<input type="password" name="password"><br>

    爱好

    <input type="checkbox"name="hobby" value="sing">唱歌

    <input type="checkbox"name="hobby" value="dance">跳舞

    <input type="checkbox"name="hobby" value="football">足球<br>

    <input type="submit"value="提交">

</form> 

servlet01

response.setContentType("text/html;charset=utf-8");    
PrintWriter out = response.getWriter();
String name = request.getParameter("username");
String password = request.getParameter("password");
out.println("用户名:" + name);
out.println("密   码:" + password);
String[] hobbys=request.getParameterValues("hobby");
out.print("爱好:");
for (int i = 0; i < hobbys.length; i++) {
   out.print(hobbys[i]+" ");
}

结果出现乱码
原因:浏览器在传递请求参数时,请求编码默认采用的是ISO8859-1 ,但在解码时采用的是utf-8编码,所以乱码。
解决:给请求对象设置编码:request.setCharacterEncoding(“utf-8”)

<think>我们正在解决用户的问题:在ZuluJDK17中,出现了`javax.servlet.http.HttpServletRequest`无法转换为`jakarta.servlet.http.HttpServletRequest`的错误。根据引用[3]的信息,Spring6将基线升级到了JakartaEE9+,而JakartaEE9将包名从`javax.servlet`改为了`jakarta.servlet`。因此,这个问题通常是由于项目中同时存在新旧两种ServletAPI(javax和jakarta)的依赖导致的。###问题分析1.**错误原因**:在同一个项目中,可能同时引入了两个不同版本的ServletAPI:-旧版:使用`javax.servlet`包(例如ServletAPI4.0及以下)-新版:使用`jakarta.servlet`包(例如ServletAPI5.0+,对应JakartaEE9+)2.**具体表现**:当代码中尝试将`javax.servlet.http.HttpServletRequest`对象转换为`jakarta.servlet.http.HttpServletRequest`时,由于两者来自不同的包,属于不同的类加载器加载,因此无法转换。###解决方案####方法1:统一使用JakartaEE9+的ServletAPI(推荐)根据引用[3]的内容,Spring6已经将基线升级到JakartaEE9+,因此如果项目使用的是Spring6,那么应该将所有相关的依赖升级到JakartaEE9+版本。步骤:1.**修改pom.xml中的依赖**:-将旧的`javax.servlet`依赖替换为`jakarta.servlet`依赖。-例如,替换ServletAPI依赖:```xml<!--旧的javax.servlet依赖--><!--删除以下依赖--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><!--新的jakarta.servlet依赖--><dependency><groupId>jakarta.servlet</groupId><artifactId>jakarta.servlet-api</artifactId><version>6.0.0</version><!--或更高版本--><scope>provided</scope></dependency>```-同时,确保其他相关依赖(如JSP、JSTL)也使用Jakarta命名空间:```xml<!--JakartaJSTL--><dependency><groupId>jakarta.servlet.jsp.jstl</groupId><artifactId>jakarta.servlet.jsp.jstl-api</artifactId><version>3.0.0</version></dependency>```2.**修改代码中的导入包**:-将所有`javax.servlet`开头的包名替换为`jakarta.servlet`。-例如:```java//替换前importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;//替换后importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;```-使用IDE的全局替换功能可以快速完成。3.**更新Web服务器**:-根据引用[3],确保使用的Web服务器支持JakartaEE9+,例如:-Tomcat10.1.x(注意:Tomcat10.0.x对应JakartaEE9,Tomcat10.1.x对应JakartaEE10)-Jetty11-Undertow2.34.**检查其他依赖**:-确保项目中其他依赖(如SpringFramework、Hibernate等)也是支持JakartaEE9+的版本。例如,Spring6.x版本完全支持JakartaEE9+。####方法2:降级到使用旧版ServletAPI(不推荐)如果项目暂时无法升级到JakartaEE9+,可以考虑继续使用旧版ServletAPI(javax)。但是,这要求Spring版本为5.x(因为Spring6只支持JakartaEE9+)。步骤:1.**确保使用Spring5.x**:-在pom.xml中,将Spring版本设置为5.x。-例如:```xml<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.29</version><!--使用最新的5.x版本--></dependency>```2.**使用javax.servlet依赖**:-确保ServletAPI使用4.0.x版本:```xml<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency>```3.**检查代码**:-确保所有导入的Servlet相关类都是`javax.servlet`包下的。###验证-清理项目(mvnclean)并重新构建。-确保服务器(如Tomcat)的版本与项目依赖的ServletAPI版本一致。###常见问题-**Tomcat版本问题**:如果使用Tomcat10.x,它默认实现了JakartaEE9+(包名为jakarta.servlet),而Tomcat9.x及以下则使用javax.servlet。因此,如果项目使用javax.servlet,应使用Tomcat9.x;如果使用jakarta.servlet,则使用Tomcat10.x。###总结该错误的根本原因是ServletAPI包名的变更(javax->jakarta)导致类不兼容。解决方法是统一项目中的ServletAPI版本,推荐升级到JakartaEE9+并使用Spring6,或者降级到使用旧版javax.servlet并配合Spring5。根据引用[3]的信息,未来趋势是JakartaEE,因此升级是更推荐的方案[^3]。---§§相关问题§§1.如何将基于Spring5和javax.servlet的项目迁移到Spring6和jakarta.servlet?2.在Tomcat10中部署使用javax.servlet的旧项目会出现什么问题?3.JakartaEE9+与JavaEE8的主要区别是什么?4.如何检查项目中是否存在混合使用javax.servlet和jakarta.servlet的情况?5.升级到JakartaEE9+后,JPA和CDI等组件的包名有哪些变化?</think>### 问题分析 在 Zulu JDK 17 中遇到 `javax.servlet.http.HttpServletRequest 无法转换为 jakarta.servlet.http.HttpServletRequest` 错误,核心原因是 **Servlet API 包名变更**。根据引用[3]的信息,从 Java EE 到 Jakarta EE 的演进中,Servlet 包名从 `javax.servlet` 迁移到了 `jakarta.servlet`。以下是具体原因和解决方案: --- ### 根本原因 1. **Jakarta EE 命名空间变更**(引用[3]): - Spring 6/Jakarta EE 9+ 将包名从 `javax.*` 改为 `jakarta.*` - 当项目同时存在新旧版本依赖时,会导致类型不兼容 ```java // 旧版:javax.servlet import javax.servlet.http.HttpServletRequest; ❌ // 新版:jakarta.servlet import jakarta.servlet.http.HttpServletRequest; ✅ ``` 2. **依赖冲突**: - 项目可能同时引入了: - Servlet 4.0(`javax.servlet`) - Servlet 5.0+(`jakarta.servlet`) - 常见于混合使用 Spring Boot 2.x(Java EE)和 Spring Boot 3.x(Jakarta EE) --- ### 解决方案 #### 方案1:统一使用 Jakarta EE(推荐) 适用于新建项目或可升级的项目: 1. **修改所有导入语句**: ```java // 替换前 import javax.servlet.*; import javax.servlet.http.*; // 替换后 import jakarta.servlet.*; import jakarta.servlet.http.*; ``` 2. **更新 Maven/Gradle 依赖**: ```xml <!-- pom.xml 示例 --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <!-- Jakarta EE 10 --> <scope>provided</scope> </dependency> ``` 3. **升级相关组件**(引用[3]): - Spring Boot 3.0+(要求 JDK 17+) - Tomcat 10.1+ / Jetty 11+ / Undertow 2.3+ - 数据库驱动等配套组件 #### 方案2:兼容模式(旧项目过渡) 适用于无法立即升级的项目: 1. **添加转换适配层**: ```java public class JakartaHttpServletRequestWrapper extends HttpServletRequestWrapper { public JakartaHttpServletRequestWrapper(HttpServletRequest request) { super(request); } // 添加需要的适配方法 } ``` 2. **显式类型转换**(临时方案): ```java public void doGet(HttpServletRequest request) { jakarta.servlet.http.HttpServletRequest jakartaRequest = (jakarta.servlet.http.HttpServletRequest) request; } ``` 3. **排除冲突依赖**(Maven): ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </exclusion> </exclusions> </dependency> ``` #### 方案3:降级 Servlet API(不推荐) 仅用于紧急修复: ```xml <!-- 强制使用旧版 Servlet API --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> ``` --- ### 验证步骤 1. **检查依赖树**: ```bash mvn dependency:tree | grep servlet # 或 gradle dependencies | grep servlet ``` 确保输出中只有 `jakarta.servlet` 或 `javax.servlet`(不能共存) 2. **确认服务器版本**: - Tomcat 10.1+ → Jakarta EE 10 - Tomcat 9.x → Java EE 8(`javax`) 3. **IDE 静态检查**: 使用 IntelliJ/Eclipse 的 "Analyze → Inspect Code" 扫描包导入冲突 --- ### 典型修复案例 参考引用[1][2]中的 Servlet 代码,升级后应改为: ```java @WebServlet("/index") public class HelloServlet extends HttpServlet { @Override protected void doGet( jakarta.servlet.http.HttpServletRequest req, // 使用jakarta包 jakarta.servlet.http.HttpServletResponse resp ) { // 实现逻辑 } } ``` > **关键点**:Jakarta EE 9+ 是 Java EE 的演进标准,Zulu JDK 17 完全兼容 Jakarta EE 10 规范[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上进扣得

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值