HttpServletRequest 类有什么作用:
每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。 然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的 信息。
HttpServletRequest 类的常用方法:
i. getRequestURI() 获取请求的资源路径
ii. getRequestURL() 获取请求的统一资源定位符(绝对路径)
iii. getRemoteHost() 获取客户端的 ip 地址
iv. getHeader() 获取请求头
v. getParameter() 获取请求的参数
vi. getParameterValues() 获取请求的参数(多个值的时候使用)
vii. getMethod() 获取请求的方式 GET 或 POST
viii. setAttribute(key, value); 设置域数据
ix. getAttribute(key); 获取域数据
x. getRequestDispatcher() 获取请求转发对象
常用 API 示例代码:
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RequestAPIServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// i. getRequestURI() 获取请求的资源路径
System.out.println("URI ==> " + req.getRequestURI());
// ii. getRequestURL() 获取请求的统一资源定位符(绝对路径)
System.out.println("URL ==> " + req.getRequestURL());
/* 正常情况下,idea中
使用localhost访问时,得到的客户端ip地址是 ===> 127.0.0.1
使用127.0.0.1访问时,得到的客户端ip地址是 ===> 127.0.0.1
使用真实的电脑ip访问时,得到的客户端ip地址是 ===> 真实的客户端ip地址
*/
// iii. getRemoteHost() 获取客户端的 ip 地址
System.out.println("客户端ip ==> " + req.getRemoteHost());
// iv. getHeader() 获取请求头
System.out.println("请求头User-Agent ===> " + req.getHeader("User-Agent"));
// vii. getMethod() 获取请求的方式 GET 或 POST
System.out.println("请求的方式:" + req.getMethod());
}
}
运行结果:
如何获取请求参数:
创建一个form.html
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/07_servlet/parameterServlet" method="get">
用户名:<input type="text" name="username" ><br/>
密码:<input type="password" name="password" ><br/>
兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++
<input type="checkbox" name="hobby" value="java">java
<input type="checkbox" name="hobby" value="js">JavaScript
<input type="submit">
</form>
</body>
</html>
创建一个ParameterServlet.java
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名:" + username);
System.out.println("密码:" + password);
System.out.println("兴趣爱好:" + Arrays.asList(hobby));
}
}
当然,别忘了配置xml。
运行结果:
解决post请求中文乱码问题:
在用户名框内输入中文,get请求正常,post请求出现乱码问题:
用一个api就可以了(在获取参数请求之前才有用)
//设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题
req.setCharacterEncoding("UTF-8");
这样,问题就可以得到解决
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题
req.setCharacterEncoding("UTF-8");
System.out.println("---------doPost-----------");
//获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名:" + username);
System.out.println("密码:" + password);
System.out.println("兴趣爱好:" + Arrays.asList(hobby));
}
请求的转发:
什么是请求转发?
请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。
Servlet1:
package com.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求参数(办事的材料)
String username = req.getParameter("username");
System.out.println("在Servlet1(柜台1)中查看的参数(材料):" + username);
//给材料盖一个章,并传递到Servlet2(柜台2)查看
req.setAttribute("key1","柜台1的章");
//问路:Servlet2(柜台2)怎么走
/**
* 请求转发必须要以 / 打头,斜杠表示地址为: http://ip:port/工程名/ ,映射到 idea 代码的 web 目录
*/
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
//走向Servlet2
requestDispatcher.forward(req,resp);
}
}
Servlet2:
package com.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求参数(办事的材料)
String username = req.getParameter("username");
System.out.println("在Servlet2(柜台2)中查看的参数(材料):" + username);
//查看柜台1改的章
Object key1 = req.getAttribute("key1");
System.out.println("柜台1是否有章:" + key1);
//处理自己的业务
System.out.println("Servlet2处理自己的业务");
}
}
请求转发的特点:
- 浏览器地址栏没有变化
- 他们是一次请求
- 他们共享Request域中的数据
- 可以转发到WEB-INF目录下(form.html不可以部署到WEB-INF目录下,但是可以通过请求转发访问进来)
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/WEB-INF/form.html");
base 标签的作用:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
这是web下的index.html<br/>
<a href="a/b/c.html">a/b/c.html</a>
<br/>
<a href="http://localhost:8080/07_servlet/forwardC">请求转发:a/b/c.html</a>
</body>
</html>
c.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
这是web/a/b下的c.html<br/>
<a href="../../index.html">跳回首页</a>
</body>
</html>
ForwardC.java
public class ForwardC extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("经过了ForwardC程序");
req.getRequestDispatcher("/a/b/c.html").forward(req,resp);
}
}
当我们点击index.html中的a标签进行跳转的时候,浏览器的地址栏中的地址是:
http://localhost:8080/07_servlet/a/b/c.html
跳转回去的a标签路径是:
../../index.html
所有相对路径在工作的时候都会参照当前浏览器地址栏中的地址来进行跳转
那么参照后得到的地址是:
http://localhost:8080/07_servlet/index.html
正确的跳转路径
当我们使用请求转发进行跳转的时候,浏览器地址栏中的地址是:
http://localhost:8080/07_servlet/forwardC
跳转回去的a标签路径是:
../../index.html
所有相对路径在工作的时候都会参照当前浏览器地址栏中的地址来进行跳转。
那么参照后得到的地址是:
http://localhost:8080/index.html
这是错误的路径!
base标签可以设置当前页面中所有相对路径工作时,参照哪个路径进行跳转。
修改后的代码:
c.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<!-- base标签设置页面相对路径工作时参照的地址
href属性就是参数的地址值-->
<base href="http://localhost:8080/07_servlet/a/b/c.html">
</head>
<body>
这是web/a/b下的c.html<br/>
<a href="../../index.html">跳回首页</a>
</body>
</html>
说明:
- 首先,会查看有无base标签,要是有base标签,他就会忽略掉浏览器当前地址栏中的地址,而是参考base的值。相当于把地址放到
../../index.html
前面去了:
http://localhost:8080/07_servlet/a/b/c.html../../index.html
一个../
抵消一个文件夹,也就是等于
http://localhost:8080/07_servlet/index.html
- base标签中最后的资源名(c.html)是可以省略的(记住: / 不能省略!)
<base href="http://localhost:8080/07_servlet/a/b/">
Web中的相对路径和绝对路径:
在 JavaWeb 中,路径分为相对路径和绝对路径两种:
相对路径是:
. 表示当前目录
… 表示上一级目录
资源名 表示当前目录/资源名
绝对路径:
http://ip:port/工程路径/资源路径
在实际开发中,路径都使用绝对路径,而不简单的使用相对路径。
1、绝对路径
2、base+相对路径
web 中 / 斜杠的不同意义:
在 web 中 / 斜杠 是一种绝对路径。
/ 斜杠 如果被浏览器解析,得到的地址是:http://ip:port/ http://localhost:8080/
<a href="/">斜杠</a>
/ 斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径 http://localhost:8080/07_servlet/
<url-pattern>/servlet1</url-pattern>
servletContext.getRealPath(“/”);
request.getRequestDispatcher(“/”);
特殊情况: response.sendRediect(“/”); 把斜杠发送给浏览器解析。得到 http://ip:port/