【JavaWeb】Request对象详解
HTTP之Request:接上一篇博文HTTP协议详细.
本文目录
一.Request请求
1.Request对象和Response对象的原理
- request和response对象是由服务器创建的。我们来使用它们
- request对象是来获取请求消息,response对象是来设置响应消息
2.Request对象继承体系结构
ServletRequest – 接口
| 继承
HttpServletRequest – 接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat内部)
3.Request功能
3.1 获取请求消息数据
1.获取请求行数据
//请求行数据
GET /Http_war_exploded/RequestDemo1?name=dong HTTP/1.1
常用获取请求行数据的方法:通过request对象调用方法
-
String getMethod()
:获取请求方式get或post -
String getContextPath()
:**(重点)**获取虚拟目录 -
String getServletPath()
:获取Servlet路径 -
String getQueryString()
:获取get方式所有请求参数 -
String getRequestURI()
:**(重点)**获取请求URI(统一资源标识符)
例如:/Http_war_exploded/RequestDemo1、*,资源范围大 -
StringBuffer getRequestURL()
:获取请求URL(统一资源定位符)
例如:http://localhost:8080/Http_war_exploded/RequestDemo1、*,资源范围小 -
String getProtocol()
:获取协议及版本 -
String getRemoteAddr()
:获取客户机的IP地址
代码演示:
先创建一个form表单用于提交数据
<form action="/Http_war_exploded/RequestDemo1" method="GET">
<input name="username">
<input type="submit" value="提交">
</form>
再创建访问的Servlet,在浏览器*问创建的Servlet
@WebServlet(name = "RequestDemo1", urlPatterns = "/RequestDemo1")
public class RequestDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1. 获取请求方式 :GET
String method = request.getMethod();
System.out.println(method);
//2.(*)获取虚拟目录:/Http_war_exploded
String contextPath = request.getContextPath();
System.out.println(contextPath);
//3. 获取Servlet路径: /RequestDemo1
String servletPath = request.getServletPath();
System.out.println(servletPath);
//4. 获取get方式请求参数:username=dong
String queryString = request.getQueryString();
System.out.println(queryString);
//5.(*)获取请求URI:/Http_war_exploded/RequestDemo1
String requestURI = request.getRequestURI();
StringBuffer requestURL = request.getRequestURL();
System.out.println(requestURI);// /Http_war_exploded/RequestDemo1
System.out.println(requestURL);// http://localhost:8080/Http_war_exploded/RequestDemo1
//6. 获取协议及版本:HTTP/1.1
String protocol = request.getProtocol();
System.out.println(protocol);
//7. 获取客户机的IP地址:0:0:0:0:0:0:0:1
String remoteAddr = request.getRemoteAddr();
System.out.println(remoteAddr);
}
}
3.2 获取请求头数据
方法:
-
String getHeader(String name)
; (重点)通过请求头的名称获取请求头的值 -
Enumeration<String> getHeaderNames()
:获取所有的请求头名称的迭代器(与枚举类似)
代码演示1:获取所有请求头内容
@WebServlet(name = "RequestDemo2", urlPatterns = "/RequestDemo2")
public class RequestDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 演示获取请求头数据
*/
//1.获取所有请求头名称
Enumeration<String> headerNames = request.getHeaderNames();
//2.遍历
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
//根据名称获取请求头的值
String value = request.getHeader(name);
System.out.println(name + "---" + value);
}
}
}
从浏览器访问http://localhost:8080/Http_war_exploded/RequestDemo2,控制台打印:
代码演示2:获取请求头数据中user-agent
的内容,判断agent的浏览器版本
@WebServlet(name = "RequestDemo3", urlPatterns = "/RequestDemo3")
public class RequestDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 演示获取请求头数据中:user-agent
* 如果请求头user-agent的内容中包含了谷歌的浏览器的关键字Chrome,就可以认为使用的是谷歌浏览器
*/
String agent = request.getHeader("user-agent");
//判断agent的浏览器版本
if(agent.contains("Chrome")){
//谷歌
System.out.println("谷歌来了...");
}else if(agent.contains("Firefox")){
//火狐
System.out.println("火狐来了...");
}
}
}
代码演示3:获取请求头数据中referer
的内容,防盗链应用,可以知道访问从哪里URL过来的。
比如我从一个login.html登录页面访问RequestDemo4,那么请求头中的referer
的值就是:http://localhost:8080/Http_war_exploded/login.html,referer
中包含正确的URI的内容/Http_war_exploded,就是正确访问。
如果从其它页面访问RequestDemo4,referer
中不会包含/Http_war_exploded,但是又能访问到RequestDemo4,这就属于盗链。我们要防止这种现象,防止山寨网站嘛。
referer
的值为空的情况:比如直接在浏览器地址栏中直接输入http://localhost:8080/Http_war_exploded/RequestDemo4访问,referer的值就是null,因为它并没有从哪里来,直接访问,所以为null。
@WebServlet(name = "RequestDemo4", urlPatterns = "/RequestDemo4")
public class RequestDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 演示获取请求头数据中:referer
*/
String referer = request.getHeader("referer");
System.out.println(referer);//http://localhost:8080/Http_war_exploded/login.html
//防盗链
if(referer != null ){
//如果referer中包含正确的URI的内容,就是正确访问
if(referer.contains("/Http_war_exploded")){
//正常访问
// System.out.println("播放电影....");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("播放电影....");
}else{
//盗链
//System.out.println("想看电影吗?来优酷吧...");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("想看电影吗?来优酷吧...");
}
}
}
}
3.3 获取请求体数据
请求体:只有POST请求方式,才有请求体,GET方式没有。在请求体中封装了POST请求的请求参数。
获取步骤
1.获取流对象
底层是通过IO流形式传递数据,方法有:
-
BufferedReader getReader()
:获取字符输入流,只能操作字符数据(包括中文) -
ServletInputStream getInputStream()
:获取字节输入流,可以操作所有类型数据(包括一些文件,图音视频),在文件上传知识点详细讲解。
2.再从流对象中拿数据
- 读取数据使用读取相应IO流的方法即可
代码演示:
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/Http_war_exploded/RequestDemo5" method="post">
<input name="username">
<input type="submit" value="提交">
</form>
<hr>
</body>
</html>
访问的Servlet类RequestDemo5
@WebServlet(name = "RequestDemo5", urlPatterns = "/RequestDemo5")
public class RequestDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 获取请求消息体中请求参数
*/
//1.获取字符流
BufferedReader br = request.getReader();
//2.读取流中的数据
String line =null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
启动服务器,访问login.html,点击提交表单:
控制台打印
4.Request其它功能
4.1 获取请求参数通用方式
不论get还是post请求方式都可以使用下列方法来获取请求参数,所以get和post请求处理逻辑可以使用同一套代码:
-
String getParameter(String name)
:(重点)根据参数名称获取参数值,只能获取一个参数值。适合请求参数如:username=zs&password=123 -
String[] getParameterValues(String name)
:根据参数名称获取参数值的数组。 适合请求参数如:hobby=xx&hobby=game -
Enumeration<String> getParameterNames()
:获取所有请求的参数名称 -
Map<String,String[]> getParameterMap()
: (重点)获取所有参数的map集合
代码演示
register.html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/Http_war_exploded/RequestDemo6" method="post">
<input type="text" placeholder="请输入用户名" name="username"><br>
<input type="text" placeholder="请输入密码" name="password"><br>
<input type="checkbox" name="hobby" value="game">游戏
<input type="checkbox" name="hobby" value="study">学习
<br>
<input type="submit" value="注册">
</form>
</body>
</html>
访问的Servlet类
@WebServlet(name = "RequestDemo6", urlPatterns = "/RequestDemo6")
public class RequestDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* post 获取请求参数
*/
//1.根据参数名称获取参数值
String username = request.getParameter("username");//只能获取到一个参数值
System.out.println("post");
System.out.println(username);
System.out.println("========================");
//2.根据参数名称获取参数值的数组
String[] hobbies = request.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
System.out.println("========================");
//3.获取所有请求的参数名称
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()){
String name = parameterNames.nextElement();
String value = request.getParameter(name);
System.out.println(name+"-->"+value);
}
System.out.println("========================");
//4.获取所有参数的map集合
//泛型是参数名称,参数值数组
Map<String, String[]> parameterMap = request.getParameterMap();
//遍历
Set<String> keyset = parameterMap.keySet();
for (String name : keyset) {
//根据键获取值
String[] values = parameterMap.get(name);
System.out.println(name);
for (String value : values) {
System.out.println(value);
}
System.out.println("----------------");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* get获取请求参数
*/
this.doPost(request,response);
}
}
启动服务器,访问register.html,点击注册提交表单:
控制台打印:
4.1.1 中文请求参数乱码问题
get方式:tomcat 8 内部已经将get方式乱码问题解决了,中文数据使用get请求方式不会乱码。
post方式:会乱码
- 解决办法:在获取参数前,设置request的编码request.setCharacterEncoding(“utf-8”);
代码演示
修改上面的register.html中表单,访问RequestDemo7。
@WebServlet(name = "RequestDemo7", urlPatterns = "/RequestDemo7")
public class RequestDemo7 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 设置流的编码
* 需要与页面编码格式一致
*/
//request.setCharacterEncoding("utf-8");//先注释掉,查看乱码问题
//获取请求参数username
String username = request.getParameter("username");
System.out.println(username);
}
}
点击注册,提交表单:
控制台出现乱码:
取消request.setCharacterEncoding("utf-8");
的注释,重写启动服务器再次提交,乱码解决:
4.2 请求转发
请求转发:是一种在服务器内部的资源跳转方式。
请求包含
请求包含指的是使用
include()
方法将Servlet请求转发给其它Web资源进行处理,与请求转发不同的是,在请求包含返回的响应消息中,既包含了当前Servlet的响应消息,也包含了其他Web资源所作出的响应消息。从图中可以看出,当客户端访问Servlet1时,通过调用include()方法将其它Web资源包含了进来,这样,当请求处理完毕后,回送给客户端的响应结果既包含当Servlet的响应结果,也包含其它Web资源的响应结果。
使用步骤:
- 1.通过request对象获取请求转发器对象:
RequestDispatcher getRequestDispatcher(String path)
- 2.使用RequestDispatcher对象来进行转发:
forward(ServletRequest request, ServletResponse response)
请求转发的特点:
- 1.浏览器地址栏路径不发生变化。
- 2.只能转发到当前服务器内部资源中(静态和动态资源)。
- 3.转发是一次请求。
代码演示
创建了两个Servlet类:RequestDemo8和RequestDemo9
现在从浏览器中访问RequestDemo8,服务器内部会请求转发到RequestDemo9。
@WebServlet(name = "RequestDemo8", urlPatterns = "/RequestDemo8")
public class RequestDemo8 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Demo8888被访问了。。。。");
/**
* 请求转发
*/
//RequestDispatcher requestDispatcher = request.getRequestDispatcher("/requestDemo9");
//requestDispatcher.forward(request,response);
//推荐使用链式编程,因为转发对象一般只使用一次
request.getRequestDispatcher("/RequestDemo9").forward(request,response);
}
}
@WebServlet(name = "RequestDem9", urlPatterns = "/RequestDemo9")
public class RequestDemo9 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 请求转发
*/
System.out.println("Demo9也被访问了。。。。");
}
}
启动服务器,访问RequestDemo8:
控制台打印情况:
4.3 共享数据
概念:域对象和request域
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源*享数据
共享数据的方法
-
void setAttribute(String name,Object obj)
:存储数据,参数:
String name:存储对象的名称,用于获取到存储的对象;
Object obj:存储的对象; -
Object getAttitude(String name)
:通过键获取值 -
void removeAttribute(String name)
:通过键移除键值对
代码演示
创建了两个Servlet类:RequestDemo8和RequestDemo9
现在从浏览器中访问RequestDemo8,服务器内部会请求转发到RequestDemo9。
在RequestDemo8中存储了数据到request域中,在RequestDemo9中获取存储的数据。
@WebServlet(name = "RequestDemo8", urlPatterns = "/RequestDemo8")
public class RequestDemo8 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Demo8888被访问了。。。。");
/**
* 共享数据
* 存储数据到request域中
*/
request.setAttribute("msg","Hello");
/**
* 请求转发
*/
//推荐使用链式编程,因为转发对象一般只使用一次
request.getRequestDispatcher("/RequestDemo9").forward(request,response);
}
}
@WebServlet(name = "RequestDem9", urlPatterns = "/RequestDemo9")
public class RequestDemo9 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 请求转发
*/
System.out.println("Demo9也被访问了。。。。");
/**
* 获取共享数据
* 从request域中获取存储的数据
*/
Object msg = request.getAttribute("msg");
System.out.println(msg);
}
}
启动服务器,访问RequestDemo8,控制台打印情况:
4.4 获取ServletContext对象
ServletContext
官方叫servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。
获取方法
-
ServletContext getServletContext()
:获取servlet上下文对象
代码演示
@WebServlet(name = "RequestDemo10", urlPatterns = "/RequestDemo10")
public class RequestDemo10 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 获取ServletContext容器对象
*/
ServletContext servletContext = request.getServletContext();
System.out.println(servletContext);//aaa@qq.com
}
}
到这HTTP之Request对象细节结束,学无止境,每天都要全力以赴!
欢迎点赞评论,指出不足,笔者由衷感谢哦!~
上一篇: 判断字符串是否是数字
下一篇: 设计模式-行为型-备忘录模式