request 其他功能
# 32.request 其他功能
上一篇博客讲述的方法,都是比较底层的,下面讲一些更方便的方法
- 获取请求参数通用方式,不管是 get 还是 post
- 请求转发
- 共享数据
- 获取 ServletContext
# 获取请求参数通用方式
获取请求参数通用方式:不论 get 还是 post 请求方式,都可以使用下列方法来获取请求参数
String getParameter(String name)
:根据参数名称获取参数值String[] getParameterValues(String name)
:获取相同名称的所有值。假设请求参数是 hobby = xx&hobby = game,则可以获取所有 hobby 的参数。复选框可能会出现这样情况Enumeration<String> getParameterNames()
: 获取所有请求的参数名称Map<String,String[]> getParameterMap()
: 获取所有参数的 map 集合
第 1 个和第 4 个方法比较常用。
# getParameter
写个代码来演示下:
package com.peterjxl.request;
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.BufferedReader;
import java.io.IOException;
@WebServlet("/requestDemo4")
public class RequestDemo4 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
System.out.println("username: " + username);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
System.out.println("username: " + username);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
新建 requestDemo4.html
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<title>requestDemo4</title>
</head>
<body>
<form action="/hello/requestDemo4" method="post">
<input type="text" placeholder="请输入用户名" name="username"><br>
<input type="text" placeholder="请输入密码" name="password"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
重启 Tomcat,访问 requestDemo4.html,并输入用户名和密码
然后提交,观察控制台输出:
username: peterjxl
# 简化 doGet
既然 doGet 和 doPost 方法做的事情是一样的,为了简化代码,我们可以这样简化:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
2
3
4
# getParameterValues
我们修改下 HTML 页面,增加复选框:
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<title>requestDemo4</title>
</head>
<body>
<form action="/hello/requestDemo4" method="post">
<input type="text" placeholder="请输入用户名" name="username"><br>
<input type="text" placeholder="请输入密码" name="password"><br>
<input type="checkbox" name="hobby" value="sing"> 唱歌 <br>
<input type="checkbox" name="hobby" value="dance"> 跳舞 <br>
<input type="checkbox" name="hobby" value="rap"> rap <br>
<input type="checkbox" name="hobby" value="basketball"> 篮球 <br>
<input type="submit" value="注册">
</form>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
然后获取:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
System.out.println("username: " + username);
String[] hobbies = req.getParameterValues("hobby");
for (String hobby: hobbies) {
System.out.println(hobby);
}
}
2
3
4
5
6
7
8
9
10
重启 Tomcat,访问 http://localhost: 8080/hello/requestDemo4.html,勾选后提交
查看控制台输出:
username:
sing
dance
rap
basketball
2
3
4
5
# getParameterNames()
Enumeration<String> getParameterNames()
: 获取所有请求的参数名称
// 获取所有请求的参数名称
Enumeration<String> parameterNames = req.getParameterNames();
while(parameterNames.hasMoreElements()){
String name = parameterNames.nextElement();
String value = req.getParameter(name);
System.out.printf("name: %s, value: %s\n", name, value);
}
2
3
4
5
6
7
访问页面,随便勾选几个数据,提交
输出如下:
name: username, value: peterjxl
name: password, value: 1233445
name: hobby, value: sing
2
3
注意,hobby 只打印了一个,因为 getParameter
只获取一个。
# getParameterMap()
获取所有参数的 map 集合
Map<String, String[]> parameterMap = req.getParameterMap();
Set<String> keyset = parameterMap.keySet();
for (String name : keyset){
System.out.print("name: " + name);
// 根据键获取值
String[] values = parameterMap.get(name);
for (String value : values){
System.out.print(" value: " + value);
}
System.out.println();
}
2
3
4
5
6
7
8
9
10
11
可以看到返回的 map 集合中,value 是 String[]
数组类型的,这样就可以获取所有参数。
重启 Tomcat,访问 http://localhost: 8080/hello/requestDemo4.html,随便勾选几个提交
输出:
name: username value: peterjxl
name: password value: 123456
name: hobby value: sing value: dance value: rap
2
3
# 中文乱码问题
有时候我们会遇到乱码问题,我们来演示下。
新建 requestDemo5.html
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<title>requestDemo5</title>
</head>
<body>
<form action="/hello/requestDemo5" method="post">
<input type="text" placeholder="请输入用户名" name="username"><br>
<input type="text" placeholder="请输入密码" name="password"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
新建 Servlet
package com.peterjxl.request;
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;
@WebServlet("/requestDemo5")
public class RequestDemo5 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
System.out.println("username: " + username);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
重启 Tomcat,访问 http://localhost: 8080/hello/requestDemo5.html,并在表单里填入中文 ,提交:
可以看到乱码了!
这是因为 getParameter 内部还是用流来获取参数的值。
解决方法:获取参数前设置 request 的编码 request.setCharacterEncoding("utf-8");
。为什么是 UTF8 的编码?因为前端用设置了编码:<meta charset="UTF-8">
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");
System.out.println("username: " + username);
}
2
3
4
5
6
如果你使用 get 方式:Tomcat8 已经将 get 方式乱码问题解决了,所以不用担心
# 请求转发
请求转发:一种在服务器内部的资源跳转方式。
为什么需要请求转发:为了避免一个 Servlet 干太多事情,完成所有功能,不合理,难以维护。我们可以拆分 Servlet,将一些公用的方法写成单独的 Servlet。此时我们就需要在一个 Servlet 中,转发请求到另一个 Servlet 的路径上,让另一个 Servlet 执行
转发的方式:
- 通过 request 对象获取请求转发器对象:
request.getRequestDispatcher("http://www.itcast.cn")
- 然后使用 RequestDispatcher 对象来进行转发:
forward(ServletRequest request, ServletResponse response)
方法特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中。即不能访问其他网站,访问会报错 404
- 转发时,浏览器只发送了一次请求,多个资源使用的是同一个请求
我们新建 2 个 Servlet 演示下:RequestDemo6 是被转发处理请求的类:
package com.peterjxl.request;
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;
@WebServlet("/requestDemo6")
public class RequestDemo6 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("requestDemo6被访问了.....");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
RequestDemo7 是转发请求给 RequestDemo6 的类:
package com.peterjxl.request;
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;
@WebServlet("/requestDemo7")
public class RequestDemo7 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("requestDemo7被访问了.....");
req.getRequestDispatcher("/requestDemo6").forward(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
重启 Tomcat,访问 http://localhost: 8080/hello/requestDemo7。可以看到 IDEA 控制台的输出:
requestDemo7被访问了.....
requestDemo6被访问了.....
2
# 数据共享
为什么需要共享数据:比如转发请求后,需要告诉另一个 Servlet 一些数据(例如用户名),然后让另一个 Servlet 处理,此时就需要共享数据了,也就是 Servlet 之间的通信。此时就涉及到域。
域对象:一个有作用范围的对象,可以在范围内共享数据
request 域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据,也就是可以通过 request 存储数据
方法:
void setAttribute(String name, Object obj)
:存储数据Object getAttitude(String name)
:通过键获取值void removeAttribute(String name)
:通过键移除键值对
也就是说,我们可以在 ServletA 中用 setAttribute
存储数据,转发给 ServletB,然后 ServletB 可以用 getAttitude
获取数据。
我们来演示下:
在 RequestDemo7
中设置一个属性:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("requestDemo7被访问了.....");
req.setAttribute("name", "peterjxl");
req.getRequestDispatcher("/requestDemo6").forward(req,resp);
}
2
3
4
5
6
在 RequestDemo6
中获取属性
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("requestDemo6被访问了.....");
String name = (String) req.getAttribute("name");
System.out.println(name);
}
2
3
4
5
6
重启 Tomcat,访问 http://localhost: 8080/hello/requestDemo7,可以看到控制台确实打印了数据 peterjxl。
# 获取 ServletContext
ServletContext 是一个比较重要的对象,可以通过 request.getServletContext()
获取
@WebServlet("/requestDemo10")
public class RequestDemo10 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("requestDemo10被访问了.....");
ServletContext servletContext = req.getServletContext();
System.out.println(servletContext);
}
}
2
3
4
5
6
7
8
9
重启 Tomcat,访问 http://localhost: 8080/hello/requestDemo10,可以看到控制台有打印对象,
org.apache.catalina.core.ApplicationContextFacade@9af79e
后续我们再讲解 servletContext 的功能。