Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 115
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-25 10:41
文章分类

全部博文(9)

文章存档

2014年(1)

2013年(8)

我的朋友

分类: Java

2014-01-03 17:32:34

HttpServletRequest

我们先来看他们的祖先ServletRequest和ServletResponse

javax.servlet.ServletRequest - 接口

  1. public interface ServletRequest {}
javax.servlet.ServletResponse - 接口
  1. public interface ServletResponse {}
我们已经知道,servlet由servlet容器管理,当客户请求到来的时候,servlet容器创建一个ServletRequest对象,封装请求数据,同时创建一个ServletResponse对象,用来封装响应数据,然后servlet容器把这两个对象作为形参,传递并调用service()方法,数据就这样到了servlet,servlet通过解析ServletRequest获得客户端的实际请求信息,处理完逻辑,把响应的结果封装到ServletResponse中,向客户发送响应数据

至于HttpServletRequest和HttpServletResponse,它们是继承了祖先的子孙接口,而且提供了与Http协议有关的方法,例如设置HTTP状态吗码,管理cookie,同理,servlet容器会收到Http请求并分别创建HttpServletRequest和HttpServletResponse对象

下篇转载HttpServletRequest应用_李晖晖的个人总结(第五次课)


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

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

1、通过request常用方法获得客户机信息

  • getRequestURL方法返回客户端发出请求时的完整URL
  • getRequestURI方法返回请求行中的资源名部分
  • getQueryString 方法返回请求行中的参数部分
  • getRemoteAddr方法返回发出请求的客户机的IP地址
  • getRemoteHost方法返回发出请求的客户机的完整主机名
  • getRemotePort方法返回客户机所使用的网络端口号
  • getLocalAddr方法返回WEB服务器的IP地址
  • getLocalName方法返回WEB服务器的主机名
  • getMethod得到客户机请求方式

例如在Request.java中加入如下代码

[java] view plaincopy
  1. //返回相关请求的信息  
  2. String uri=request.getRequestURI();  
  3. String rad = request.getRemoteAddr();  
  4. String rh = request.getRemoteHost();  
  5. String ru = request.getRemoteUser();  
  6. int rp = request.getRemotePort();  
  7. String cp = request.getContextPath();  
  8. String la = request.getLocalAddr();  
  9. String ce = request.getCharacterEncoding();  
  10. String gm = request.getMethod();  
  11. String qs = request.getQueryString();  

  12. System.out.println(uri);  
  13. System.out.println(rad);  
  14. System.out.println(rh);  
  15. System.out.println(ru);  
  16. System.out.println(rp);  
  17. System.out.println(cp);  
  18. System.out.println(la);  
  19. System.out.println(ce);  
  20. System.out.println(gm);  
  21. System.out.println(qs);  

  即可获取相关信息

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

  •   getHeader(name)
  •   getHeaders(String name)
  •   getHeaderNames()

[java] view plaincopy
  1. private void getRequestValue(HttpServletRequest request) {  
  2.     //获得客户机请求头及请求头的值  
  3.     System.out.println(request.getHeader("method"));  
  4.     Enumeration e = request.getHeaderNames();  
  5.     while(e.hasMoreElements()) {  
  6.         String name = (String)e.nextElement();  
  7.         String value = request.getHeader(name);  
  8.         System.out.println(name+":"+value);  
  9.     }  
  10. }  

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

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

二、request的常见应用

1、 各种表单输入项数据的获取

如可以获取form表单中的text、password、radio、checkbox、 file、select、textarea、 hidden、image、button等组件的值进行数据库操作或其他处理操作

来看一个具体应用


界面代码主体部分如下

  1. Register.html  
  2. >  
  3. <html>  
  4.   <head>  
  5.     <title>Register.htmltitle>  

  6.     <metahttp-equivmetahttp-equiv="keywords"content="keyword1,keyword2,keyword3">  
  7.     <metahttp-equivmetahttp-equiv="description" content="this is my page">  
  8.     <meta http-equiv="content-type" content="text/html;charset=UTF-8">  
  9.      
  10.       
  11.    
  12.   head>  
  13.    
  14.   <body>  
  15.     <form action ="RequestLogin" method ="post">  
  16.     用户名:<input type="text"name = "username" ><br/>  
  17.     密码:<inputtypeinputtype="password" name = "password"><br/>  
  18.     性别:<input type="radio"name = "sex" value ="male">男  
  19.           <input type="radio" name = "sex" value="female"><br/>  
  20.     籍贯:<select name="city">  
  21.            <option value ="HeBei">河北option>  
  22.            <opton value ="HuBei">湖北opton>  
  23.            <option value ="ShanXi">山西option>  
  24.           select><br/>  
  25.     简历:<br/>
  26.             &nsp;<textarea rows="5" cols="20" name="intro">textarea>  
  27.           <br/>
  28.     爱好:<br/>  
  29.             <input type="checkbox" name="hobbies" value ="sing"/>唱歌  
  30.             <input type="checkbox" name="hobbies" value ="dance"/>跳舞  
  31.             <input type="checkbox" name="hobbies" value ="readbook"/>读书  
  32.             <input type="checkbox" name="hobbies" value ="readnewspaper"/>看报<br/>  
  33.     上传头像:<br/>  
  34.             <input type="file" value="image" name ="browser"><br/>  
  35.             <input type="submit" value="提交"/>  
  36.     form>  
  37.    
  38.   body>  
  39. html>  

定义一个RequestLogin.java类通过request对象,即可获取表单中组件的值

[java] view plaincopy
  1. private void getInformation(HttpServletRequest request) throws UnsupportedEncodingException {

  2.     //取出参数值   
  3.     String name = request.getParameter("username");   
  4.     String pass = request.getParameter("password");   
  5.     String sex = request.getParameter("sex");   
  6.     String city = request.getParameter("city");   
  7.     String intro = request.getParameter("intro");   
  8.     String [] hobbies = request.getParameterValues("hobbies");   
  9.     String hobby ="";   

  10.     //hobbies!=null对所取值为空时进行设置 
      
  11.     for(int i=0;hobbies!=null&&i
  12.         String hovalue = hobbies[i];
            hobby += hovalue;
  13.     }   

  14.     //获取头像信息 // String image = request.getParameter("image"); 
      
  15.     System.out.println("username:"+name);   
  16.     System.out.println("password:"+pass);   
  17.     System.out.println("sex:"+sex); System.out.println("city:"+city);   
  18.     System.out.println("intro:"+intro); System.out.println("hobby:"+hobby);}  

2、请求参数的中文乱码问题

Request中会出现编码问题,如何解决呢?

下面来看具体的例子


例如我想将一个form表单中的信息提取到并在控制台输出如图

 

假设在server端未给Request对象指定编码,即server端接收请求的字符编码为ISO8859-1,你在客户端添加如下信息


当填入的信息有中文时,在post提交方式下,server端输出如下乱码


客户端主体代码同上

[html] view plaincopy
  1. Register.html  
  2.   <body>  
  3.     <form action ="RequestLogin" method ="post">  
  4.     用户名:<input type="text" name = "username" ><br/>  
  5.     密码:<input type="password" name = "password"><br/>  
  6.     性别:<input type="radio" name = "sex" value ="male">男  
  7.           <input type="radio" name = "sex" value ="female"><br/>  
  8.     籍贯:<select name ="city">  
  9.            <option value ="HeBei">河北option>  
  10.            <opton value ="HuBei">湖北opton>  
  11.            <option value ="ShanXi">山西option>  
  12.           select><br/>  
  13.     简历:<br/>  
  14.            &nsp;<textarea rows="5" cols="20" name ="intro">textarea>  
  15.           <br/>  
  16.     爱好:<br/>  
  17.            <input type="checkbox" name ="hobbies" value ="sing"/>唱歌  
  18.            <input type="checkbox" name ="hobbies" value ="dance"/>跳舞  
  19.            <input type="checkbox" name ="hobbies" value ="readbook"/>读书  
  20.            <input type="checkbox" name ="hobbies" value ="readnewspaper"/>看报<br/>  
  21.     上传头像:<br/>  
  22.            <input type="file" value ="image" name ="browser"><br/>  
  23.            <input type="submit" value ="提交"/>  
  24.     form>  
  25.   body>  

服务端主体代码如下

[java] view plaincopy
  1. RequestLogin.java  
  2. package net.csdn.request;  
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5. importjava.io.UnsupportedEncodingException;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServlet;  
  8. importjavax.servlet.http.HttpServletRequest;  
  9. importjavax.servlet.http.HttpServletResponse;  

  10. public
     class RequestLogin extendsHttpServlet {

  11.   public void doGet(HttpServletRequest request,HttpServletResponse response)
  12.         throws ServletException, IOException {
  13.  
  14.         getInformation(request);
  15.     }  

  16.   private
     void getParameter(HttpServletRequest request) 
  17.       throws UnsupportedEncodingException {

  18.   private void getInformation(HttpServletRequest request)  
  19.       throws UnsupportedEncodingException {  

  20.     //取出参数值
      
  21.     String name =request.getParameter("username");  
  22.     String pass =request.getParameter("password");  
  23.     String sex =request.getParameter("sex");  
  24.     String city =request.getParameter("city");  
  25.     String intro = request.getParameter("intro");  
  26.     String [] hobbies =request.getParameterValues("hobbies");  
  27.     String hobby ="";  

  28.     //hobbies!=null对所取值为空时进行设置
      
  29.     for(inti=0;hobbies!=null&&i
  30.         String hovalue = hobbies[i];
            hobby += hovalue;
  31.     }  

  32.     //获取头像信息 // String image = request.getParameter("image");
      
  33.     System.out.println("username:"+name);  
  34.     System.out.println("password:"+pass);  
  35.     System.out.println("sex:"+sex);System.out.println("city:"+city);  
  36.     System.out.println("intro:"+intro);System.out.println("hobby:"+hobby);}  

  37.   public
     void doPost(HttpServletRequestrequest, HttpServletResponse response)  
  38.       throws ServletException, IOException{doGet(request, response);}}  

出现乱码是因为你在RegisterLogin.java中并没有给Request对象设置编码集,而Request对象的默认编码集是ISO8859-1是不支持汉字的,所以你需要在此类中为其指明相应的编码集

改正:在doGet方法中加入如下代码指明接收请求的编码方式
  request.setCharacterEncoding("utf-8");
即可输出:

这种修改方式只在提交方式为post时才有效,当提交方式为get时不起作用



即便在RequestLogin.java中再设置request.setCharacterEncoding("utf-8");
也不会起任何作用,程序还会输出如图所示乱码信息

这时就需要在RequestLogin.java中含有中文的地方进行如下设置了即在doGet方法中加入如下代码
[java] view plaincopy
  1. String username = new String(name.getBytes("iso8859-1"),"utf-8");  
  2. String introduction = new String(intro.getBytes("iso8859-1"),"utf-8");  
  3. System.out.println("username:"+username);  
  4. System.out.println("password:"+introduction);  
此时再度测试时就正常
了!

好了到这里,你大概已经知道该如何对Response和Request对象中的乱码问题进行操作了吧!

3、防盗链

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

    例如,你有一个访问某资源的网址,但是你事先不知道这个网址是有防盗链的,那么当你输入该网址时你可能会发现,并没有马上跳转到你想要的资源页面,而是跳转到一些无关的信息页面,但是就是在这些信息页面中你发现有一个超链接或是其他操作可以跳转到你所访问的最终资源页面
    这里顺便说一下防盗链产生的背景:一般浏览有一个重要的现象就是一个完整的页面并不是一次全部传送到客户端的。如果请求的是一个带有许多图片和其它信息的页面,那么最先的一个Http请求被传送回来的是这个页面的文本,然后通过客户端的浏览器对这段文本的解释执行,发现其中还有图片,那么客户端的浏览器会再发送一条Http请求,当这个请求被处理后那么这个图片文件会被传送到客户端,然后浏览器会将图片安放到页面的正确位置,就这样一个完整的页面也许要经过发送多条Http请求才能够被完整的显示。基于这样的机制,就会产生一个问题,那就是盗链问题:就是一个网站中如果没有起页面中所说的信息,例如图片信息,那么它完全可以将这个图片的连接到别的网站。这样没有任何资源的网站利用了别的网站的资源来展示给浏览者,提高了自己的访问量,而大部分浏览者又不会很容易地发现,这样显然,对于那个被利用了资源的网站是不公平的。一些不良网站为了不增加成本而扩充自己站点内容,经常盗用其他网站的链接。一方面损害了原网站的合法利益,另一方面又加重了服务器的负担    

    如何实现防盗链:要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或文件。换句话说,通过referer,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以跟踪到显示它的网页地址。有了referer跟踪来源就好办了,这时就可以通过技术手段来进行处理,一旦检测到来源不是本站即进行阻止或者返回指定的页面。

如果想对自己的网站进行防盗链保护,则需要针对不同的情况进行区别对待。如果网站服务器用的是apache,那么使用apache自带的Url Rewrite功能可以很轻松地防止各种盗链,其原理是检查refer,如果refer的信息来自其他网站则重定向到指定图片或网页上,

如果服务器使用的是IIS的话,则需要通过第三方插件来实现防盗链功能了,现在比较常用的一款产品叫做ISAPI_Rewrite,可以实现类似于apache的防盗链功能。另外对于论坛来说还可以使用“登录验证”的方法进行防盗链

    这就是防盗链技术了,好了来看一个具体应用Request.java

[java] view plaincopy
  1. public class Request extends HttpServlet {  
  2. public void doGet(HttpServletRequest request, HttpServletResponse response)
  3.     throws ServletException, IOException {
        getDoorChain(request, response);
    }

  4. private
     void getDoorChain(HttpServletRequest request, HttpServletResponse response) 
  5.     throws IOException {

  6.     //通过request获取请求头参数       
      
  7.     String referer = request.getHeader("referer");  
  8.     if(referer==null || !referer.endsWith("")) {  
  9.         response.sendRedirect("");  
  10.         return;  
  11.     }  
  12.     response.setCharacterEncoding("utf-8");  
  13.     response.setContentType("text/html;charset =utf-8");  
  14.     PrintWriter pw = response.getWriter();  
  15.     pw.write("喜剧片《东成西就》");  
  16. }  

  17. public
     void doPost(HttpServletRequest request, HttpServletResponse response)  
  18.     throws ServletException, IOException {  
  19.     doGet(request, response);  
  20.     }  
  21. }  

 index.jsp部分的主体代码

[html] view plaincopy
  1. <body>  
  2.   这里是防盗链技术的应用检测! <br>  
  3.   <a href ="/Request/Request" >喜剧片 a>  
  4.   body>  
  5. html>  

效果如图


例如我最终想要通过这个网址获取到我想要的《东成西就》
的资源可是当我真正的输入这个网址时,却转到了
这个页面

 

只有当你点击“喜剧片”这个超链接时才会真正的得到你想要的资源页面即

 



好了赶快自己动手试一试吧!

4、request对象实现请求转发

    Servlet API中定义了一个RequestDispatcher接口,俗称请求分派器
    它定义了如下两个方法: 
    public void forward(ServletRequest request, ServletResponseresponse)
    public void include(ServletRequest request,ServletResponse response) 

获取RequestDispatcher实例的方式主要有两种

  1. 调用ServletContext接口提供的getRequestDispatcher(Stringurl)方法
  2. 调用ServletRequest接口提供的getRequestDispatcher(Stringurl)方法

RequestDispatcher

    被包含的Servlet程序不能改变响应消息的状态码和响应头,这些语句的执行结果将被忽略如果存在下面的语句

    例:request.getRequestDispatcher("./Welcome.jsp").forward(request,response);
即可从当前应用跳转到相应的"./Welcome.jsp"页面。


    request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发

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

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

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

三、关于请求转发的一些细节

  1. forward方法用于将请求转发到RequestDispatcher对象封装的资源
  2. 如果在调用forward方法之前,在Servlet程序中写入的部分内容已经被真正地传送到了客户端,forward方法将抛出IllegalStateException异常
  3. 如果在调用forward方法之前向Servlet引擎的缓冲区 (response)中写入了内容,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区中的 内容将被清空,但是,已写入到HttpServletResponse对象中的响应头字段信息保持有效

四、请求重定向和请求转发的区别

    一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理,称之为请求转发

   一个web资源收到客户端请求后,通知浏览器去访问另外一个web资源,称之为请求重定向

注意

  1. RequestDispatcher.forward方法只能将请求 转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。 如果传递HttpServletResponse.sendRedirect方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher对象时指定的相对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对象,它们属于 两个独立的访问请求和响应过程

         关于请求消息头我们在以后的学习中还会经常用到request对象是我们目前在JavaWeb开发中学到的三个作用域即ServletContext、Request和Session域之一,是非常重要的一个请求对象,希望以上的相关介绍对能你有所帮助!


阅读(488) | 评论(0) | 转发(0) |
0

上一篇:servlet体系(一)

下一篇:没有了

给主人留下些什么吧!~~