一、 HttpServletRequest概述
我们在创建Servlet时会覆盖service()
方法,或doGet()/doPost()
,这些方法都有两个参数,一个为代表请求的request和代表响应response。
service方法中的request的类型是ServletRequest,而doGet/doPost方法的request的类型是HttpServletRequest,HttpServletRequest是ServletRequest的子接口,功能和方法更加强大,今天我们学习HttpServletRequest。
二、 通过抓包工具抓取Http请求
因为request代表请求,所以我们可以通过该对象分别获得Http请求的请求行,请求头和请求体
三、 通过request获得请求行
获得客户端的请求方式:String getMethod()
获得请求的资源:
String getRequestURL()
StringBuffer getRequestURL()
String getContextPath()
----web应用的名称String getQueryString()
---- get提交url地址后的参数字符串username=zhangsan&password=123
案例:
String method = request.getMethod();
System.out.println("method:"+method);
//2、获得请求的资源相关的内容
String requestURI = request.getRequestURI();
StringBuffer requestURL = request.getRequestURL();
System.out.println("uri:"+requestURI);
System.out.println("url:"+requestURL);
//获得web应用的名称
String contextPath = request.getContextPath();
System.out.println("web应用:"+contextPath);
//地址后的参数的字符串
String queryString = request.getQueryString();
System.out.println(queryString);
//3、获得客户机的信息---获得访问者IP地址
String remoteAddr = request.getRemoteAddr();
System.out.println("IP:"+remoteAddr);
效果如下:
此地址为IPV6地址,如果想要变成127.0.0.1,需要修改电脑配置。表示本地IP。
四、 通过request获取请求头
long getDateHeader(String name)
String getHeader(String name)
——获得指定的头Enumeration getHeaderNames()
——获得所有的头的名称Enumeration getHeaders(String name)
int getIntHeader(String name)
案例一:
新建一个HeaderServlet,书写以下内容
//1.获得指定的头,这里是获取USER-Agent也就是用户使用的浏览器
String header = request.getHeader("User-Agent");
System.out.println(header);
//2.获得所有的头的名称
Enumeration<String> headerNames =request.getHeaderNames();
while (headerNames.hasMoreElements()){
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
System.out.println(headerName+":"+headerValue);
效果如下:
案例二:
如果我们在form.html中添加a标签,访问的地址是案例一书写的HeadServlet。
<a href="/HeaderServlet">访问HeaderServlet资源</a>
此时我们获取所有请求头的信息,通过控制台可以查看
TIPS:referer头的作用:执行该此访问的的来源.作用:做防盗链,就是可以表明,该链接是通过我写的html进行访问,可以阻止别人对我的链接网页进行盗用
案例三:
为熟练掌握防盗链,做一个小的demo
第一步新建一个news.html并且访问Servlet
body>
<a href="/RefererServlet">纯手工山楂球</a>
</body>
第二步检测访问链
public class RefererServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//对该新闻的来源进行判断
String Header = request.getHeader("RefererServlet");
if(Header !=null&&Header.startsWith("http://localhost")){
//从本人网站跳转过去,可以看新闻
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("纯手中山楂球安全可食用");
}
else{
response.getWriter().write("盗网站者,可耻");
}
}
五、 通过request获得请求体
请求体中的内容如果是通过post提交的请求参数,格式是:
username=zhangsan&password=123&hobby=football&hobby=basketball
key ---------------------- value
username [zhangsan]
password [123]
hobby [football,basketball]
以上面参数为例,通过一下方法获得请求参数:
String getParameter(String name)
String[] getParameterValues(String name)
案例一:
第一步:新建一个表单
<form action="/ContentServlet" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
爱好:<input type="checkbox" name="hobby" value="zq">足球
<input type="checkbox" name="hobby" value="pq">排球
<input type="checkbox" name="hobby" value="ppq">乒乒球
<input type="submit" value="提交">
</form>
第二步:分别获取文本框中的单个值和多个值
public class ContentServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获得单个表单值
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username+" "+password);
//2.获得多个表单的值
String[]hobbys = request.getParameterValues("hobby");
for (String hobby:hobbys){
System.out.println(hobby);
}
}
}
效果如下:
Enumeration getParameterNames()
(不常用)Map<String,String[]> getParameterMap()
(常用)
注意:客户端发送的参数 到服务器端都是字符串
案例二:
此时我们紧接着上面的Servlet继续书写
//3.获取所有的请求参数的名称
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()){
System.out.println(parameterNames.nextElement());
}
System.out.println("+++++++++++++++++++++++++++++++++++");
//4.获得所有的参数 参数封装到一个Map<String,String[]>
Map<String,String[]> parameterMap = request.getParameterMap();
for (Map.Entry<String,String[]> entry:parameterMap.entrySet()){
System.out.println(entry.getKey());
for(String str:entry.getValue()){
System.out.println(str);
}
System.out.println("+++++++++++++++++++++++++++++++++++");
}
效果如下:
六、解决提交乱码的方案
- 解决post提交方式的乱码:
request.setCharacterEncoding("UTF-8");
- 解决get提交的方式的乱码:
parameter = new String(parameter.getbytes("iso8859-1"),"utf-8")
;
七、 request的其他功能
- request是一个域对象
setAttribute(String name, Object o)
getAttribute(String name)
removeAttribute(String name)
注意:request域的作用范围:一次请求中
案例一:
目的熟练request的域,我们通过在Servlet1的内容存储信息,在Servlet2中进行获取。
第一步新建一个Servlet1
@WebServlet(name = "Servlet1",urlPatterns
="/Servlet1")
public class Servlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//向request域中存储数据
request.setAttribute("name","tom");
RequestDispatcher dispatcher = request.getRequestDispatcher("/Servlet2");
//执行转发的方法
dispatcher.forward(request,response);
}
}
第二步:写一个Servlet2
@WebServlet(name = "Servlet2",urlPatterns
="/Servlet2")
public class Servlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//从request域中取出数据
Object attribute = request.getAttribute("name");
response.getWriter().write("123w45"+attribute);
}
}
效果如下:
注意:我们此时在网站上输入Servlet1的时候,他会进行转发,内容会跳转到Servlet2的内容,这就是Request的下一个内容,转发。其次,注意理解Servlet中的请求一次,即可获取到所有的资源
- request完成请求转发
获得请求转发器----path是转发的地址
RequestDispatcher getRequestDispatcher(String path)
通过转发器对象转发requestDispathcer.forward(ServletRequest request, ServletResponse response)
案例二:
目的:熟练掌握request的请求转发的内容,和案例一几乎类似,我们做一个Servlet1和Servlet2,从Servlet1往Servlet2中转发内容即可。
第一步:写一个Servlet1:
@WebServlet(name = "Servlet1",urlPatterns ="/Servlet1")
public class Servlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Servlet1将请求转发给Servlet2 此处新建一个转发器
RequestDispatcher dispatcher = request.getRequestDispatcher("/Servlet2");
//执行转发的方法
dispatcher.forward(request,response);
}
}
第二步:书写一个Servlet
@WebServlet(name = "Servlet2",urlPatterns ="/Servlet2")
public class Servlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("123w45");
}
}
效果如下:
此时我们访问Servlet1的时候显示的是Servlet2的内容:
八、Request一些注意事项
1.ServletContext域与Request域的生命周期比较?
ServletContext:
- 创建:服务器启动
- 销毁:服务器关闭
- 域的作用范围:整个web应用
request:
- 创建:访问时创建request
- 销毁:响应结束request销毁
- 域的作用范围:一次请求中
2.客户端地址与服务器端地址的写法?
- 客户端地址:
- 是客户端去访问服务器的地址,服务器外部的地址,
- 特点:写上web应用名称
- 访问方式:重定向
- 服务器端地址:
- 服务器内部资源的跳转的地址,
- 特点:不需要写web应用的名称
- 访问方式:转发
3.转发与重定向的区别?
- 重定向两次请求,转发一次请求
- 重定向地址栏的地址变化,转发地址不变
- 重新定向可以访问外部网站 转发只能访问内部资源
- 转发的性能要优于重定向