Strvlet_Request
什么是HttpServletRequest对象
这是一个接口,有Tomcat去实现,由Tomcat去实例化,并且通过doGet方法或doPost方法传入,就代表请求对象
请求的方法:与请求行有关的方法
需求:
创建一个RequestLineServlet,用于获取请求行中相关信息的方法,并且输出到网页上。
代码
package com.itheima.demo1;
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;
import java.io.PrintWriter;
//@WebServlet可以直接指定Servlet的访问地址
@WebServlet("/demo2")
public class Demo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// out.print("<h1>你好,我是注解Servlet</h1>");
//获取是GET请求还是POST请求
String method = request.getMethod();
out.print("请求方式:"+method+"<br/>");
//获取访问地址URI
String requestURI = request.getRequestURI();
out.print("URI的地址:"+requestURI+"<br/>");
//获取URL的地址
StringBuffer requestURL = request.getRequestURL();
out.print("URL地址"+requestURL+"<br/>");
//获取协议和版本
String protocol = request.getProtocol();
out.print("协议和版本"+protocol+"<br/>");
//获取地址栏?后面的内容
String queryString = request.getQueryString();
out.print("地址栏后面的参数"+queryString+"<br/>");
//获取当前服务器项目的访问地址 (重点掌握)
String contextPath = request.getContextPath();
out.print("服务访问地址:"+contextPath+"<br/>");
//回去当前项目的访问地址 (重点掌握)
String servletPath = request.getServletPath();
out.print("当前servlet的访问地址:"+servletPath);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fueoNArQ-1593331102887)(img\Snipaste_2020-06-24_13-21-55.png)]
小结:
HttpServletRequest对象的方法 | 功能描述 |
---|---|
String getMethod() | 获取请求的方式 |
String getRequestURI() | 得到URI,短 |
StringBuffer getRequestURL() | 得到URL,长 |
String getProtocol() | 得到协议和版本 |
String getQueryString() | 获得查询字符串 |
String getContextPath() | 获取当前服务器真实路径(重点) |
String getServletPath() | 获取当前Servlet的方位地址(重点掌握) |
请求的方法:与请求头有关的方法
请求头是由多个键值对组成:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rsdFTKe7-1593331102888)(C:\Users\wucn\Desktop\每日学习总结\线下\java_web\Servlet\img\Snipaste_2020-06-24_14-35-21.png)]
Enumeration接口的方法
需求
- 得到user-agent请求头的值
- 得到所有的请求头信息,并输出所有的请求值信息
代码
package com.itheima.demo1;
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;
import java.io.PrintWriter;
import java.util.Enumeration;
@WebServlet("/demo03")
public class Demo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
//获取请求头中host的值
String host = request.getHeader("Host");
out.print("host的值是:"+host+"<br/>");
//获取素有请求头中的值
Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()){
String s = headerNames.nextElement();//获取的键
String header = request.getHeader(s);//通过键获取值
out.print("请求头中的键是:"+s+" 值是:"+header+"<br/>");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
效果
请求方法 | 功能 |
---|---|
String getHeader(String headName) | 通过请求头中的键,获取请求头的值 |
Stirng getHeader(“referer”) | 可以获取上一次访问地址 |
Enumeration<String> getHeaderNames() | 获取请求头中所有的键 (类似迭代器) |
Enumeration接口方法 | 说明 |
---|---|
boolean hasMoreElements() | 判断是否还有下一个元素,如果有返回true |
String nextElement | 1.获取当前元素 2.向下移动一个元素 |
请求头案例:防盗链
流程
原理:获取上一个页面的地址,如果是我们自己网站的指定网页,就可以下载,否则不允许下载。
- 如何获取上一个页面的地址,使用请求头:referer
- 判断这个页面是不是我们指定的下载页面,如果是正常下载,否则不允许下载
代码
package com.itheima.servlet;
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;
import java.io.PrintWriter;
/**
* 检查下载前的来源地址
*/
@WebServlet("/demo3")
public class Demo3CheckServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
//1.获取上一个页面地址
String referer = request.getHeader("referer");
//2.判断这个地址是否是指定的页面
if(referer.equals("http://localhost:8080/day09_request_war_exploded/demo01.html")) {
out.print("可以下载");
}
//3.如果是就可以下载,否则就不能下载
else {
out.print("您是非法的用户不能下载");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
效果
请求的方法:得到浏览器提交的参数值
方法名 | 描述 |
---|---|
String getParameter(String name) | 通过参数名获取一个参数值 |
String[] getParameterValues(String name) | 通过参数名得到一组参数值,并且返回字符串数组 |
Map<String,String[]> getParameterMap() | 获取所有的参数名和值,返回Map对象 键是参数名,值是字符串数组 |
案例
需求:
- 通过上面的方法得到注册页面的用户名和性别,输出到浏览器
- 得到所有的爱好,输出到浏览器
- 得到所有表单的名字和值,输出到浏览器
- 得到封装好的表单数据Map对象,输出到浏览器
注:页面上name是给服务器使用的,id是给浏览器使用的,服务器通过name属性获取参数值
代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>这是登录页面</title>
</head>
<body>
<h2>用户注册</h2>
<form action="demo5" method="get">
<!--页面上name是给服务器使用的,id是给浏览器使用的,服务器通过name属性获取参数值 -->
用户名: <input type="text" name="user"><br/>
性别: <input type="radio" name="gender" value="男" checked="checked"/>男
<input type="radio" name="gender" value="女"/>女 <br/>
城市:
<select name="city">
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="珠海">珠海</option>
</select>
<br/>
爱好:
<input type="checkbox" name="hobby" value="上网"/>上网
<input type="checkbox" name="hobby" value="上学"/>上学
<input type="checkbox" name="hobby" value="上车"/>上车
<input type="checkbox" name="hobby" value="上吊"/>上吊
<br/>
<input type="submit" value="注册"/>
</form>
</body>
</html>
Servlet代码
package com.itheima.servlet;
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;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Map;
/**
* 得到POST请求体或GET地址栏上参数
*/
@WebServlet("/demo5")
public class Demo5ParamServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.print("您的注册信息如下:<hr/>");
//获取姓名和性别,参数字符串常量是表单项的name属性值。这个方法只能通过参数名得到一个参数值
String name = request.getParameter("user");
String gender = request.getParameter("gender");
out.print("用户名:" + name + "<br/>");
out.print("性别:" + gender + "<br/>");
//得到所有的爱好,输出到浏览器。如果想通过一个参数名得到一组参数值,使用以下方法。返回字符串数组
String[] hobbies = request.getParameterValues("hobby");
out.print("爱好是:" + Arrays.toString(hobbies) + "<hr/>"); //将数组转成字符串
//一次得到所有的参数名和值(键和值),返回的是map对象,键是参数名,值就是值,值是一个String数组
Map<String, String[]> parameterMap = request.getParameterMap();
//输出map的键和值
parameterMap.forEach((k, v) -> out.print("键:" + k + ",值:" + Arrays.toString(v) + "<br/>"));
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
效果
请求域有关的方法
什么是作用域
用户不同的Servlet之间或不同请求或不同的用户之间共享数据。数据结构是Map结构:键和值组成
键是字符串类型,值是Object类型
作用域分类
作用域 | 范围 |
---|---|
请求域(request) | 范围最小,一次请求结束就丢失 |
会话域(Session) | 一个用户的所有请求都可以使用 |
上下文域(Context) | 所有用户所有的请求都可以使用 |
增删该查的方法
方法 | 作用 |
---|---|
void setAttribute(“key”,value); | 往作用域中添加一个数据 如果数据不存在就是添加,如果数据存在就是修改 |
Object getAttribute(“key”); | 根据key获取value,返回的是Object类型 |
void removeAttribute(“key”); | 根据key删除value |
图解
代码
package com.itheima.demo1;
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;
import java.io.PrintWriter;
@WebServlet("/one")
public class Demo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//往请求域中添加一个user
request.setAttribute("user","张三");
request.setAttribute("age",18);
//修改user的名字为李四
request.setAttribute("user","李四");
//获取出姓名和年龄的数据
String user = (String)request.getAttribute("user");
int age = (int)request.getAttribute("age");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.print("姓名: "+user+" 年龄:"+age);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
效果
页面跳转:转发
疑问
- 能否在OneServlet中保存值到请求域中,在另一个TwoServlet中打印出来?
不能,应为访问oneServlet是一次请求,访问twoServlet又是另外一个请求,不是同一个请求,所以不能访问
可以通过转发的方式,让一次请求同时经过多个Servlet,从而可以在第二个Servlet中获取请求域中的数据
转发与重定向的作用
它们在浏览器端看到功能是相同的,都可以实现页面跳转。
转发:是在服务器内部进行页面的跳转,浏览器地址栏是不会发生改变
重新向:是在浏览器端进行页面跳转的,浏览器地址栏是会发生改变
什么是转发
原理图:
转发的方法
//往请求域中添加一个user
request.setAttribute("user","张三");
request.setAttribute("age",18);
//转发 request.getRequestDispatcher("two")获得转发器,forward(request,response);进行转发将请求对象和响应对象传给two
request.getRequestDispatcher("two").forward(request,response);
案例
需求
实现从OneServlet中转发到TwoServlet
步骤
- OneServlet向请求域中添加了一个键和值,转发给TwoServlet
- TwoServlet就从请求域中取出键和值,打印到浏览器上。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dB1KDqex-1593331102898)(img\Snipaste_2020-06-24_17-04-56.png)]
oneServlet代码
package com.itheima.demo1;
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;
import java.io.PrintWriter;
@WebServlet("/one")
public class Demo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//往请求域中添加一个user
request.setAttribute("user","张三");
request.setAttribute("age",18);
//转发
request.getRequestDispatcher("two").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
twoServlet代码
package com.itheima.demo1;
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;
import java.io.PrintWriter;
@WebServlet("/two")
public class Demo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
//从请求域中获取内容
String user =(String) request.getAttribute("user");
int age = (int) request.getAttribute("age");
//打印到浏览器中
out.print("姓名:"+user+" 年龄:"+age);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
效果
转发特点:
- 地址栏:不会发生变化,显示的还是上一个Servlet的地址
- 请求次数:只有1次请求
- 请求域中数据没有丢失的
转发使用的方法:
request.getRequestDisPacher("要转发到的页面或服务器").forward(request,response)
页面跳转:重定向
什么是重定向
由浏览器进行的页面跳转,称为重定向,功能与js中的location.href相同
原理图
重定向的方法
//重定向
response.sendRedirect(request.getContextPath()+"/two");
重定向案例
需求
从OneServlet重定向到TwoServlet
步骤
- 在OneServlet中向请求域中添加键和值
- 使用重定向到TwoServlet,在TwoServlet中看能否取出请求域的值
oneServlet代码
package com.itheima.demo1;
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;
import java.io.PrintWriter;
@WebServlet("/one")
public class Demo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//往请求域中添加一个user
request.setAttribute("user","张三");
request.setAttribute("age",18);
//转发
// request.getRequestDispatcher("two").forward(request,response);
response.sendRedirect(request.getContextPath()+"/two");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
twoServlet代码
package com.itheima.demo1;
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;
import java.io.PrintWriter;
@WebServlet("/two")
public class Demo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
//从请求域中获取内容
String user =(String) request.getAttribute("user");
//打印到浏览器中
out.print("姓名:"+user);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
效果
重定向的特点:
- 地址栏:发生了变化,显示的是新的地址
- 请求次数:2次请求
- 请求域中的数据:丢失了,因为不是同一次请求
小结:重定向和转发的区别
区别 | 转发forward() | 重定向sendRedirect() |
---|---|---|
哪个对象 | request | response |
地址栏是否发生变化 | 不变 | 变化 |
哪一端进行的跳转 | 服务器端 | 浏览器端 |
请求域中数据是否会丢失 | 不会 | 会 |
几次请求 | 1次 | 2次请求 |
根目录地址 | http://localhost:8080/项目地址/ 包含了项目访问地址 | http://localhost:8080/ 不包含项目访问地址 |
跳转的网站 | 只能跳转到同一个项目的地址 | 可以跳转到其它任意的地址 |
//写成一句,地址:http://localhost:8080/day09_request_war_exploded/two
//request.getRequestDispatcher("/two").forward(request, response);
//使用重定向,地址:http://localhost:8080/two
response.sendRedirect(request.getContextPath() + "/two"); //加上项目访问地址
//写成一句,地址:http://localhost:8080/day09_request_war_exploded/two
//request.getRequestDispatcher("/two").forward(request, response);
//使用重定向,地址:http://localhost:8080/two
response.sendRedirect(request.getContextPath() + "/two"); //加上项目访问地址