博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
javaWeb学习总结(5)- HttpServletRequest应用
阅读量:6830 次
发布时间:2019-06-26

本文共 18676 字,大约阅读时间需要 62 分钟。

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的相关方法,即可以获得客户的这些信息

 

 

工程

 

 

 

 

一、通过request常用方法获得相关信息:

 

 

  • getContextPath//项目根目录
  • getServletPath//是哪一个servlet
  • getSession().getServletContext().getRealPath("")
  • getSession().getServletContext().getRealPath("/abc");//得到工程目录,参数可具体到包名。
  • XXX.class.getResource("/").getPath();//访问servlet的具体绝对路径
  • getRequestURL方法返回客户端发出请求时的完整URL。
  • getRequestURI方法返回请求行中的资源名部分。
  • getQueryString 方法返回请求行中的参数部分。
  • getRemoteAddr方法返回发出请求的客户机的IP地址
  • getRemoteHost方法返回发出请求的客户机的完整主机名
  • getRemotePort方法返回客户机所使用的网络端口号
  • getLocalAddr方法返回WEB服务器的IP地址。
  • getLocalName方法返回WEB服务器的主机名
  • getMethod得到客户机请求方式

 

package lqy;import java.io.IOException;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;public class requestTest extends GenericServlet {    @Override    public void service(ServletRequest arg0, ServletResponse arg1)            throws ServletException, IOException {        //这样获取HttpServletRequest类        HttpServletRequest request=(HttpServletRequest)arg0;        String ContextPath=request.getContextPath();//项目根目录        String ServletPath=request.getServletPath();//是哪一个servlet                   String RealPath=request.getSession().getServletContext().getRealPath("");//工程根目录绝对路径        String RealPath2=request.getSession().getServletContext().getRealPath("/abc");//得到工程目录,参数可具体到包名。                String RequestController=requestTest.class.getResource("/").getPath();//访问servlet的具体绝对路径                StringBuffer RequestURL=request.getRequestURL();//返回客户端发出请求时的完整URL        String QueryString=request.getQueryString();//方法返回请求行中的参数部分。        String RemoteAddr=request.getRemoteAddr();//方法返回发出请求的客户机的IP地址        String RemoteHost=request.getRemoteHost();//方法返回发出请求的客户机的完整主机名        int RemotePort=request.getRemotePort();//方法返回客户机所使用的网络端口号        String LocalAddr=request.getLocalAddr();//方法返回WEB服务器的IP地址。        String LocalName=request.getLocalName();//方法返回WEB服务器的主机名        String Method=request.getMethod();//得到客户机请求方式                System.out.println("调用ContextPath:"+ContextPath);                System.out.println("调用Servlet的部分:"+ServletPath);        System.out.println("调用RealPath:"+RealPath);        System.out.println("调用RealPath2:"+RealPath2);                    System.out.println("调用RequestController:"+RequestController);                  System.out.println("客户端发出请求时的完整URL:"+RequestURL);                System.out.println("方法返回请求行中的参数部分:"+QueryString);        System.out.println("方法返回发出请求的客户机的IP地址:"+RemoteAddr);        System.out.println("方法返回发出请求的客户机的完整主机名:"+RemoteHost);        System.out.println("方法返回客户机所使用的网络端口号:"+RemotePort);         System.out.println("方法返回WEB服务器的IP地址:"+LocalAddr);        System.out.println("方法返回WEB服务器的主机名:"+LocalName);        System.out.println("得到客户机请求方式:"+Method);     }    public requestTest() {        super();    }    public void destroy() {        super.destroy();     }    public void init() throws ServletException {    }}

 

输入url:http://localhost:8080/servlet_1/servlet/requestTest?id=2&name=luo

 

二、通过request常用方法获得客户机请求头信息

 

  •   getHead(name)方法
  •   getHeaders(String name)方法
  •   getHeaderNames方法

url发出请求:http://localhost:8080/servlet_1/servlet/requestTest?id=2&name=luo

 

HttpServletRequest request=(HttpServletRequest)arg0;	//获得客户机请求头及请求头的值          String method=request.getHeader("method");        System.out.println("method:"+method);//key不存在就返回null        String Connection=request.getHeader("Connection");        System.out.println("Connection:"+Connection);        System.out.println("-----------------------");                //System.out.println(request.getHeader("getHeader:"+getHeader));          Enumeration e = request.getHeaderNames();  //该方法返回一个String对象的列表,该列表反映请求的所有头域名。        while(e.hasMoreElements()){              String name = (String)e.nextElement();              String value = request.getHeader(name);              System.out.println(name+":"+value);          }

 

结果是如下,可以和上图的做对比

 

3.获得客户机请求参数(客户端提交的数据)

  •   getParameter(name):获取指定名称的参数值。这是最为常用的方法之一。
  •   getParameterValues(String name):获取指定名称参数的所有值数组。它适用于一个参数名对应多个值的情况。如页面表单中的复选框,多选列表提交的值。
  •   getParameterNames():返回一个包含请求消息中的所有参数名的Enumeration对象。通过遍历这个Enumeration对象,就可以获取请求消息中所有的参数名
  •   getParameterMap():返回一个保存了请求消息中的所有参数名和值的Map对象。Map对象的key是字符串类型的参数名,value是这个参数所对应的Object类型的值数组。

 

页面jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%>              demo      
用户名:
密码:
性别:
籍贯:
简历:
爱好:
唱歌
跳舞
读书
看报
上传头像:

 

java

package lqy;import java.io.IOException;import java.util.Enumeration;import java.util.Iterator;import java.util.Map;import java.util.Set;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;public class requestTest extends GenericServlet {    @Override    public void service(ServletRequest arg0, ServletResponse arg1)            throws ServletException, IOException {                HttpServletRequest request=(HttpServletRequest)arg0;//      表单输入中文会发生乱码//      这里会出现乱码问题,是因为你在service并没有给Request对象设置编码集,//      而Request对象的默认编码集是ISO8859-1是不支持汉字的,所以你只需要在此类中为其指明相应的编码即可:       //      但是这种修改方式只在提交方式为post时才有效。当提交方式为get时是不起作用的。        request.setCharacterEncoding("utf-8");                //那么如果是get提交则      String username = new String(request.getParameter("username").getBytes("iso8859-1"),"utf-8");        System.out.println("处理后的"+username);      //那么如果是get提交则      String usernameWithout = request.getParameter("username");        System.out.println("未处理后的"+usernameWithout);                      System.out.println("---------------------getParameter-------getParameterValues-----------------");           //post取出参数值             String name = request.getParameter("username");             String pass = request.getParameter("password");             String sex = request.getParameter("sex");             String city = request.getParameter("city");             String intro = request.getParameter("intro");             String [] hobbies = request.getParameterValues("hobbies");//getParameterValues            //获取头像信息    ,只能获得文件名,不能获得绝对路径,现在很多浏览器从安全角度考虑,已经不能获取完整路径了(解决方法前端js获得绝对路径或者先上传到服务器再操作)          String image = request.getParameter("image");                    System.out.println("username:"+name);             System.out.println("password:"+pass);             System.out.println("sex:"+sex);           System.out.println("city:"+city);             System.out.println("intro:"+intro);           for(String hobbie:hobbies){              System.out.println("hobbies:"+hobbie);          }          System.out.println("image:"+image);                                          System.out.println("---------------------getParameterNames------------------------");                                //getParameterNames          Enumeration e=request.getParameterNames();          while(e.hasMoreElements()){              String temp = (String)e.nextElement();              System.out.println("getParameterNames:"+temp);                                      }                                        System.out.println("--------------------getParameterMap-------------------------");                       Map map=request.getParameterMap();          Set set=map.keySet();          for(Object o: set){              String key=(String)o;              System.out.print("key:"+key+"-----value1:");                  // String[] value=(String[])map.get(key);  //不能这样取              String[] valueArray=(String[])map.get(key);  //第一种 :要转换成String[]估计是为了getParameterValues的时候吧              for(String value1:valueArray){                  System.out.print(value1);                }              System.out.print("-----");              System.out.println("value2:"+request.getParameter(key)); //第二种              }                              System.out.println("--------------------getParameterMap2-------------------------");                       Map map2=request.getParameterMap();          Set set2=map.keySet();          for (Iterator iter = map2.entrySet().iterator(); iter.hasNext();)          {               Map.Entry entry = ( Map.Entry ) iter.next();              String key=entry.getKey().toString();              System.out.print("key:"+key+"-----value1:");                  String[] valueArray = ( String[] ) entry.getValue();              for(String value1:valueArray){                  System.out.print(value1);                }              System.out.print("-----");              System.out.println("value2:"+request.getParameter(key)); //第二种      }                       }    public requestTest() {        super();    }    public void destroy() {        super.destroy();     }    public void init() throws ServletException {    }}

结果

 

 

4、防盗链

      所谓的防盗链就是当你以一个非正常渠道去访问某一个Web资源的时候,服务器会将你的请求忽略并且将你的当前请求变为按正常渠道访问时的请求并返回到相应的页面,用户只有通过该页面中的相关操作去访问想要请求的最终资源。

        例如,你有一个访问某资源的网址,但是你事先不知道这个网址是有防盗链的,那么当你输入该网址时你可能会发现,并没有马上跳转到你想要的资源页面而是一些 无关的信息页面,但是就是在这些信息页面中你发现有一个超链接或是其他操作可以跳转到你所访问的最终资源页面。

      这就是防盗链技术了,好了来看一个具体应用:(String referer = request.getHeader("referer");)根据请求头判断

 

两个页面

点击相同的url:<a href ="<%=basePath%>servlet/requestTest" >DoorChain1</a> 

java

package lqy;import java.io.IOException;import java.util.Enumeration;import java.util.Iterator;import java.util.Map;import java.util.Set;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;public class requestTest extends GenericServlet {    @Override    public void service(ServletRequest arg0, ServletResponse arg1)            throws ServletException, IOException {                HttpServletRequest request=(HttpServletRequest)arg0;        //通过request获取请求头参数                  String referer = request.getHeader("referer");              if(referer==null){
//可能直接在空白窗口输入进来 System.out.println("referer==null,may be open new"); } else if(referer.endsWith("http://localhost:8080/servlet_1/DoorChain1.jsp")){ System.out.println("come from DoorChain1.jsp"); //该请求是页面DoorChain1.jsp进来的 } else if(referer.endsWith("http://localhost:8080/servlet_1/DoorChain2.jsp")){ System.out.println("come from DoorChain2.jsp"); //该请求是页面DoorChain2.jsp进来的 } } public requestTest() { super(); } public void destroy() { super.destroy(); } public void init() throws ServletException { }}

 

1.DoorChain1.jsp从进来抓包发现

控制台输出come from DoorChain1.jsp

 

2.同样道理DoorChain2.jsp从进来,输出come from DoorChain2.jsp

3.假如打开新窗口直接输入url

抓包

请求头没有referer参数,request.getHeader("referer")==null,所以输出

referer==null,may be open new

 5、请求转发与重定向

5.1请求转发:

request.getRequestDispatcher(URL地址).forward(request, response)

原理:

  1. 客户端发送请求,Servlet1做出处理。
  2. Servlet1调用sendReadirect()方法,将请求转发给Servlet2来处理请求,为客户端服务。 
  3. Servlet2对客户端浏览器做出响应。

请求转发允许把请求转发给同一应用程序中的其他Web组件。这种技术通常用于Web应用控制层的Servlet流程控制器,它检查HTTP请求数据,并将请求转发到合适的目标组件,目标组件执行具体的请求处理具体的请求处理操作,并生成响应结果。

Servlet类使用javax.servlet.RequestDispatcher.forward()方法来转发它所收到的HTTP请求。转 发目标组件将处理该请求并生成响应结果,或者将请求继续转发到另一个组件。最初请求的ServletRequest和ServletResponse对象 被传递给转发目标组件,这使得目标组件可以访问整个请求上下文。值得注意的是,只能把请求转发给同一Web应用中的组件,而不能转发给其他Web应用的组 件。

在JSP页面中,可以使用<jsp:forward>标签来转发请求。例如: <jsp:forward page="hello.jsp">

对于请求转发,转发的源组件和目标组件共享request范围内的共享数据。

 

request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其它web资源处理。

可通过如下方法对request中的数据对象进行操作:

  • setAttribute方法 ;
  • getAttribute方法  ;
  • removeAttribute方法;
  • getAttributeNames方法;

 

例子

浏览器输入

java

package lqy;import java.io.IOException;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class requestTest extends GenericServlet {    @Override    public void service(ServletRequest arg0, ServletResponse arg1)            throws ServletException, IOException {                HttpServletRequest request=(HttpServletRequest)arg0;        HttpServletResponse response=(HttpServletResponse)arg1;        request.setAttribute("a", 1); //请求转发,转发是在服务器端转发的,客户端是不知道的,请求转发只能请求当前WEB应用程序

          //如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它 是相对于当前WEB应用程序的根目录。

 

         //如果 传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;

//request.getRequestDispatcher("/index.jsp").forward(request, response);//跳去jsp                //可通过setAttribute和getAttribute传输数        request.getRequestDispatcher("/servlet/Dispatcher").forward(request, response);//跳去servlet    }        public requestTest() {        super();    }    public void destroy() {        super.destroy();     }    public void init() throws ServletException {    }}

 

1.跳转去jsp(其实jsp也是servlet。。),输入setAttribute的值

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%>              demo          <%=request.getAttribute("a") %> 

 

请求转发前后url是没变的(),所以客户端是并不知道的(所以叫服务器转发)

 

 

2.跳转去Dispatcher的servlet

package lqy;import java.io.IOException;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;public class Dispatcher extends GenericServlet {    @Override    public void service(ServletRequest arg0, ServletResponse arg1)            throws ServletException, IOException {        //这样获取HttpServletRequest类        HttpServletRequest request=(HttpServletRequest)arg0;        System.out.println(request.getAttribute("a"));    }}

控制台输出1

 

 

 

 

5.2重定向

:response.sendRedirect(URL地址)

原理:

  1. 客户端发送请求,Servlet1做出处理。  
  2. Servlet1调用sendReadirect()方法,将客户端的请求重新定位到Servlet2。  
  3. 客户端浏览器访问Servlet2。
  4. Servlet2对客户端浏览器做出响应。

 

Web组件可以将请求重定向到任一URL,而不仅仅是同一应用中的URL。

重定向的源组件和目标组件之间不共用同一个HttpServletRequest对象,因此不能共享request范围内的共享数据。

HttpServletResponse的sendRedirect()方法向浏览器返回包含重定向的信息,浏览器根据这一信息迅速发出一个新HTTP请求,请求访问重定向目标组件。

(原来就是返回HttpServletResponse对象告诉浏览器重定向去新的链接,所以叫客户端跳转)

 

 

例子

浏览器输入

 

java

package lqy;import java.io.IOException;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;public class requestTest extends GenericServlet {    @Override    public void service(ServletRequest arg0, ServletResponse arg1)            throws ServletException, IOException {                HttpServletRequest request=(HttpServletRequest)arg0;        HttpServletResponse response=(HttpServletResponse)arg1;                HttpSession session = request.getSession();        //重定向不会共享request的数据,所以只能通过session        request.setAttribute("a", 1);        session.setAttribute("b", 2);                //这样写浏览器会跳转http://localhost:8080/servlet/Dispatcher,少了项目根servlet_1         //说明重定向还可以请求其他站点的资源,然而请求转发只能同一站点,因为服务器转发嘛        //response.sendRedirect("/index.jsp");        //response.sendRedirect("/servlet/Dispatcher");                //应该这样        response.sendRedirect(request.getContextPath()+"/index.jsp");        //response.sendRedirect(request.getContextPath()+"servlet/Dispatcher");    }}

 

第一种返回jsp时候

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%>              demo          a=<%=request.getAttribute("a") %> 
b=<%=request.getSession().getAttribute("b")%>

 

输出,注意浏览器地址变了,

 

通过抓包发现重定向其实发出了两次请求

 

 

第一种跳去其他servlet处理

package lqy;import java.io.IOException;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;public class Dispatcher extends GenericServlet {    @Override    public void service(ServletRequest arg0, ServletResponse arg1)            throws ServletException, IOException {        //这样获取HttpServletRequest类        HttpServletRequest request=(HttpServletRequest)arg0;        System.out.println(request.getAttribute("a"));            System.out.println(request.getSession().getAttribute("b"));    }}

控制台输出

 

 

 

 

 

 

 

转发、重定向的区别:

  1. Request Dispatcher.forward()是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;服务器内部转发,请求转发,整个过程处于同一个请求当中。
  2. response.sendRedirect()则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。不在同一个请求。重定向,实际上客户端会向服务器端发送两个请求。
  3. forward()更加高效,在可以满足需要时,尽量使用RequestDispatcher.forward()方法。
  4. RequestDispatcher是通过调用HttpServletRequest对象的getRequestDispatcher()方法得到的,是属于请求对象的方法。
  5. sendRedirect()是HttpServletResponse对象的方法,即响应对象的方法,既然调用了响应对象的方法,那就表明整个请求过程已经结束了,服务器开始向客户端返回执行的结果。

 

(1)RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而 HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。

 

如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它 是相对于当前WEB应用程序的根目录。

如果 传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;

 

 

(2)调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改 变,由初始的URL地址变成重定向的目标URL;而调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。

 

(3)HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对 另外一个URL的 访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览 器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”一共发出了两封信和收到了两次回复, “浏览器”也知道他借到的钱出自李四之手。RequestDispatcher.forward方 法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏 览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只发 出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。

 

 

(4)RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们 属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect()方法调用者与被调用者使用各自的request 对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个WEB应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前 期预处理,并要使用HttpServletRequest.setAttribute方法传递预处理结果,那就应该使用 RequestDispatcher.forward方法。不同WEB应用程序之间的重定向,特别是要重定向到另外一个WEB站点上的资源的情况,都应该 使用HttpServletResponse.sendRedirect方法。

 

(5)无论是RequestDispatcher.forward方法,还是HttpServletResponse.sendRedirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。

 

转载地址:http://kpjkl.baihongyu.com/

你可能感兴趣的文章