Request请求:
- Request请求,就是客户端希望从服务器端获取资源,向服务器发出询问。在B/S架构中,就是客户浏览器向服务器发出询问。在我们的JavaEE工程中,客户浏览器发出询问,要遵循HTTP协议所规定的。
- 请求对象,就是在JavaEE工程中,用于发送请求的对象。我们常用的对象就是ServletRequest和HttpServletRequest,它们的区别就是是否和HTTP协议有关。是Servlet四大域之一
请求对象方法:
返回值 | 方法名 | 说明 |
---|---|---|
String | getContextPath() | 获取虚拟目录名称 |
String | getServletPath() | 获取Servlet映射路径 |
String | getRemoteAdd() | 获取访问者ip地址 |
String | getQueryString() | 获取请求的消息数据 |
String | getRequestURI() | 获取统一资源标识符 |
StringBuffer | getRequestURL() | 获取统一资源定位符 |
演示:
@WebServlet("/requestMethod")
public class RequestMethod extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 访问地址http://localhost:8081/demo/requestMethod
// getContextPath() 获取虚拟目录名称 /demo
System.out.println(req.getContextPath());
// getServletPath() 获取Servlet映射路径 /requestMethod
System.out.println(req.getServletPath());
// getRemoteAdd() 获取访问者ip地址 0:0:0:0:0:0:0:1
System.out.println(req.getRemoteAddr());
// getQueryString() 获取请求的消息数据 null
System.out.println(req.getQueryString());
// getRequestURI() 获取统一资源标识符 /demo/requestMethod
System.out.println(req.getRequestURI());
// getRequestURL() 获取统一资源定位符 http://localhost:8081/demo/requestMethod
System.out.println(req.getRequestURL());
// URI的范围更大(共和国),URL更具体(中华人民共和国)
}
}
获取请求头方法:
返回值 | 方法名 | 说明 |
---|---|---|
String | getHeader(String name) | 根据请求头名称获取一个值 |
Enumeration | getHeaders(String name) | 根据请求头名称获取多个值 |
Enumeration | getHeaderNames() | 获取所有请求头 |
演示:
@WebServlet("/requestHeaderDemo")
public class RequestHeaderDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// getHeader(String name) 根据请求头名称获取一个值
System.out.println(req.getHeader("connection"));
System.out.println("------------------------");
// getHeaders(String name) 根据请求头名称获取多个值
Enumeration<String> values = req.getHeaders("accept-encoding");
while (values.hasMoreElements()) {
String value = values.nextElement();
System.out.println(value);
}
System.out.println("------------------------");
// getHeaderNames() 获取所有请求头
Enumeration<String> names = req.getHeaderNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
String value = req.getHeader(name);
System.out.println(name + " : " + value);
}
}
获取请求参数信息:
返回值 | 方法名 | 说明 |
---|---|---|
String | getParameter(String name) | 根据名称获取数据 |
String[] | getPaeameterValues(String name) | 根据名称获取所有数据 |
Enumeration | getParameterNames() | 获取所有名称 |
Map<String,String[]> | getParameterMap() | 获取所有参数的键值对 |
演示:
注册页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<form action="/servletDemo08" method="get" autocomplete="off">
姓名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
爱好:<input type="checkbox" name="hobby" value="game">游戏
<input type="checkbox" name="hobby" value="study">学习<br/>
<button type="submit">提交</button>
</form>
</body>
</html>
获取请求参数:
@WebServlet("/servletDemo08")
public class ServletDemo08 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// String getParameter(String name) 根据名称获取数据
System.out.println(req.getParameter("username"));
System.out.println(req.getParameter("password"));
System.out.println("——————————————————————");
// String[] getParameterValues(String name) 根据名称获取所有数据
String[] hobbies = req.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
System.out.println("——————————————————————");
// Enumeration<String> getParameterNames() 获取所有名称
Enumeration<String> names = req.getParameterNames();
while (names.hasMoreElements()) {
System.out.println(names.nextElement());
}
System.out.println("——————————————————————");
// Map<String,String[]> getParameterMap() 获取所有参数的键值对
Map<String, String[]> map = req.getParameterMap();
for (String key : map.keySet()) {
String[] values = map.get(key);
System.out.print(key + ":");
for (String value : values) {
System.out.print(value + " ");
}
System.out.println();
}
}
}
获取参数手动封装到对象:
学生类:
public class Student {
private String username;
private String password;
private String[] hobby;
}
注册页面不变,改一下提交路径即可
@WebServlet("/servletDemo09")
public class ServletDemo09 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.获取所有的数据
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
// 2.封装学生对象
Student student = new Student(username, password, hobby);
// 3.打印学生对象
System.out.println(student);
}
}
反射封装对象:
@WebServlet("/servletDemo10")
public class ServletDemo10 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
// 1. 获取所有的数据
Map<String, String[]> map = req.getParameterMap();
// 2. 封装学生对象
Student student = new Student();
// 3. 遍历集合
for (String name : map.keySet()) {
String[] value = map.get(name);
try {
// 获取Student对象的属性描述器,就是获取get/set,然后把get/set封装到pd里
// 拿到User对象中的属性描述器。是谁的属性描述器:是由构造函数的第一个参数决定的。第二个参数是指定javabean的字节码
PropertyDescriptor pd = new PropertyDescriptor(name, student.getClass());//参数指的就是拿哪个类的哪个属性的描述器
// 设置javabean属性的值
Method writeMethod = pd.getWriteMethod();
if (value.length > 1) {
writeMethod.invoke(student, (Object) value);
} else {
writeMethod.invoke(student, value);//第一个参数是指的给哪个对象,第二个参数指的是赋什么值
}
} catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
// 4. 输出对象
System.out.println(student);
}
}
BeanUtils封装对象:
使用apache的commons-beanutils实现封装
如果遇到报500可能是没有将jar包要导入到项目中
@WebServlet("/servletDemo11")
public class ServletDemo11 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
//1.获取所有的数据
Map<String, String[]> map = req.getParameterMap();
//2.封装学生对象
Student stu = new Student();
try {
// 通过该方法将map中的数据映射/封装到javabean的get和set方法中
BeanUtils.populate(stu, map);
} catch (Exception e) {
e.printStackTrace();
}
//4.输出对象
System.out.println(stu);
}
}
流对象获取请求信息:
方法:
返回值 | 方法名 | 说明 |
---|---|---|
BufferedReader | getReader() | 获取字符输入流 |
ServletInputStream | getInputStream() | 获取字节输入流 |
演示:
@WebServlet("/servletDemo04")
public class ServletDemo04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 字符流获取必须使用post,字符流不是new出来的不需要关闭
/* BufferedReader reader = req.getReader();
String len;
while ((len = reader.readLine()) != null) {
System.out.println(len);
}*/
// 如果用post出现乱码就在代码前加个编码格式就可以了
// setCharacterEncoding:设置编码格式
req.setCharacterEncoding("UTF-8");
// 字节流
ServletInputStream inputStream = req.getInputStream();
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
中文乱码问题:
GET方式请求:
- GET方式请求的正文是在地址栏中,在Tomcat8.5版本及以后,Tomcat服务器已经帮我们解决了,所以不会有乱码问题了。
POST方式请求
- 在POST方式请求中,我们的乱码问题可以用如下代码解决:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* GET方式:正文在地址栏
* username=%D5%C5%C8%FD
* %D5%C5%C8%FD是已经被编过一次码了
*
* 解决办法:
* 使用正确的码表对已经编过码的数据进行解码。
*/
// setCharacterEncoding:设置编码格式
req.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
System.out.println(username);
}
请求域:
- 请求域(request域):可以在一次请求范围内进行共享数据
- 一般用于请求转发 的多个资源中共享数据
请求对象操作共享数据方法:
返回值 | 方法名 | 说明 |
---|---|---|
void | setAttribute(String name,Object value) | 向请求域对象中存储数据 |
object | setAttribute(String name) | 通过名称获取请求域对象中的数据 |
void | removeAttribute(String name) | 通过名称移除请求域对象中的数据 |
请求转发:
客户端的一次请求到达以后,发现借助其他的Servlet来实现功能
特点:
- 浏览器地址不变
- 域对象中的数据不丢失
- 负责转发的Servlet转发前后的显示正文会丢失
- 由转发的目的地来响应客户端
请求转发的方法:
返回值 | 方法名 | 说明 |
---|---|---|
RequestDispatcher | getRequestDispatcher(String name) | 获取请求调度对象 |
void | forward(ServletRequest req,ServletResponse resp) | 实现转发 |
@WebServlet("/servletDemo12")
public class ServletDemo12 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置共享数据
req.setAttribute("itzhuzhu", "正在学习");
// 获取请求调度对象
RequestDispatcher rd = req.getRequestDispatcher("servletDemo13");
// 实现转发功能
rd.forward(req, resp);
}
}
@WebServlet("/servletDemo13")
public class ServletDemo13 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取共享数据
System.out.println(req.getAttribute("itzhuzhu"));
System.out.println("ServletDemo13执行");
}
}
请求包含:
可以合并其它Servlet中的功能一起响应给客户端
特点:
- 浏览器地址不变
- 域对象数据不丢失
- 被包含的Servlet响应头会丢失
请求包含方法:
返回值 | 方法名 | 说明 |
---|---|---|
RequestDispatcher | getRequestDispatcher(String name) | 获取请求调度对象 |
void | include(ServletRequest req,ServletResponse resp) | 实现包含 |
@WebServlet("/servletDemo14")
public class ServletDemo14 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置共享数据
req.setAttribute("itzhuzhu", "正在学习");
// 获取请求调度对象
RequestDispatcher rd = req.getRequestDispatcher("/servletDemo13");
// 实现包含功能
rd.include(req, resp);
}
}
重定向和请求转发 :
- 重定向:通过各种方法将各种网络请求重新定个方向转到其它位置,地址会变
- 请求转发:客户端发起请求后,在服务器之间的跳转,然后服务器返回页面给客户端进行显示,地址不变