深入体验JavaWeb开发内幕——关于HttpServletRequestRequest对象
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的相关方法,即可以获得客户的这些信息。
一、通过request常用方法获得相关信息:
1、通过request常用方法获得客户机信息
- getRequestURL方法返回客户端发出请求时的完整URL。
- getRequestURI方法返回请求行中的资源名部分。
- getQueryString 方法返回请求行中的参数部分。
- getRemoteAddr方法返回发出请求的客户机的IP地址
- getRemoteHost方法返回发出请求的客户机的完整主机名
- getRemotePort方法返回客户机所使用的网络端口号
- getLocalAddr方法返回WEB服务器的IP地址。
- getLocalName方法返回WEB服务器的主机名
- getMethod得到客户机请求方式
例如在Request.java中加入如下代码:
- //返回相关请求的信息
- String uri=request.getRequestURI();
- Stringrad = request.getRemoteAddr();
- Stringrh = request.getRemoteHost();
- Stringru = request.getRemoteUser();
- intrp = request.getRemotePort();
- Stringcp = request.getContextPath();
- Stringla = request.getLocalAddr();
- Stringce = request.getCharacterEncoding();
- Stringgm = request.getMethod();
- Stringqs = request.getQueryString();
- System.out.println(uri);
- System.out.println(rad);
- System.out.println(rh);
- System.out.println(ru);
- System.out.println(rp);
- System.out.println(cp);
- System.out.println(la);
- System.out.println(ce);
- System.out.println(gm);
- System.out.println(qs);
即可获取相关信息。
2、通过request常用方法获得客户机请求头信息
- getHead(name)方法
- getHeaders(String name)方法
- getHeaderNames方法
如:
- private void getRequestValue(HttpServletRequest request) {
- //获得客户机请求头及请求头的值
- System.out.println(request.getHeader("method"));
- Enumeration e = request.getHeaderNames();
- 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类型的值数组。
二、request的常见应用
1、 各种表单输入项数据的获取
如可以获取form表单中的text、password、radio、checkbox、 file、select、textarea、 hidden、image、button等组件的值进行数据库操作或其他处理操作。
来看一个具体应用:
界面代码主体部分如下:
- Register.html
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN">
- <html>
- <head>
- <title>Register.html</title>
- <metahttp-equivmetahttp-equiv="keywords"content="keyword1,keyword2,keyword3">
- <metahttp-equivmetahttp-equiv="description" content="this is my page">
- <meta http-equiv="content-type" content="text/html;charset=UTF-8">
- <!--<link rel="stylesheet" type="text/css"href="./styles.css">-->
- </head>
- <body>
- <form action ="RequestLogin" method ="post">
- 用户名:<input type="text"name = "username" ><br/>
- 密码: <inputtypeinputtype="password" name = "password"><br/>
- 性别:<input type="radio"name = "sex" value ="male">男
- <input type="radio" name = "sex" value="female">女<br/>
- 籍贯: <select name="city">
- <option value ="HeBei">河北</option>
- <opton value ="HuBei">湖北</opton>
- <option value ="ShanXi">山西</option>
- </select><br/>
- 简历:<br/>
- &nsp;<textarea rows="5" cols="20" name="intro"></textarea>
- <br/>
- 爱好:<br/>
- <input type="checkbox" name="hobbies" value ="sing"/>唱歌
- <input type="checkbox" name="hobbies" value ="dance"/>跳舞
- <input type="checkbox" name="hobbies" value ="readbook"/>读书
- <input type="checkbox" name="hobbies" value ="readnewspaper"/>看报<br/>
- 上传头像:<br/>
- <input type="file" value="image" name ="browser"><br/>
- <input type="submit" value="提交"/>
- </form>
- </body>
- </html>
然后,定义一个RequestLogin.java类通过request对象获取表单中组件的值:
如调用自定义方法:
- private void getInformation(HttpServletRequest request)
- throws UnsupportedEncodingException {
- //取出参数值
- 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");
- String hobby ="";
- //hobbies!=null对所取值为空时进行设置
- for(int i=0;hobbies!=null&&i<hobbies.length;i++)
- { String hovalue = hobbies[i]; hobby += hovalue; }
- //获取头像信息 // 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); System.out.println("hobby:"+hobby);}
即可获取表单中组件的值。
2、请求参数的中文乱码问题
前面我们提到了Response对象中出现乱码问题及相应的解决措施,那么在Request中如何解决编码问题呢?
下面来看具体的例子:
例如我想将一个form表单中的信息提取到并在控制台输出如图:
假设在服务端并未Request对象给指定编码时即服务器端接收请求的字符编码为ISO8859-1,这时你在客户端添加信息如:
当填入的信息有中文时,假设设置表单的提交方式为post方式提交
则在服务端输出如下:
此时输出结果出现乱码。
客户端主体代码同上:
- Register.html
- <body>
- <form action ="RequestLogin" method ="post">
- 用户名:<input type="text" name = "username" ><br/>
- 密码: <input type="password" name = "password"><br/>
- 性别:<input type="radio" name = "sex" value ="male">男
- <input type="radio" name = "sex" value ="female">女<br/>
- 籍贯: <select name ="city">
- <option value ="HeBei">河北</option>
- <opton value ="HuBei">湖北</opton>
- <option value ="ShanXi">山西</option>
- </select><br/>
- 简历:<br/>
- &nsp;<textarea rows="5" cols="20" name ="intro"></textarea>
- <br/>
- 爱好:<br/>
- <input type="checkbox" name ="hobbies" value ="sing"/>唱歌
- <input type="checkbox" name ="hobbies" value ="dance"/>跳舞
- <input type="checkbox" name ="hobbies" value ="readbook"/>读书
- <input type="checkbox" name ="hobbies" value ="readnewspaper"/>看报<br/>
- 上传头像:<br/>
- <input type="file" value ="image" name ="browser"><br/>
- <input type="submit" value ="提交"/>
- </form>
- </body>
服务端主体代码如下:
- RequestLogin.java
- package net.csdn.request;
- import java.io.IOException;
- import java.io.PrintWriter;
- importjava.io.UnsupportedEncodingException;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- importjavax.servlet.http.HttpServletRequest;
- importjavax.servlet.http.HttpServletResponse;
- public class RequestLogin extendsHttpServlet
- {
- public void doGet(HttpServletRequest request,HttpServletResponse response)
- throws ServletException, IOException
- {
- getInformation(request);
- }
- private voidgetParameter(HttpServletRequest request)
- throws UnsupportedEncodingException
- {
- private voidgetInformation(HttpServletRequest request)
- throws UnsupportedEncodingException {
- //取出参数值
- 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");
- String hobby ="";
- //hobbies!=null对所取值为空时进行设置
- for(inti=0;hobbies!=null&&i<hobbies.length;i++)
- { String hovalue = hobbies[i]; hobby +=hovalue; }
- //获取头像信息 // 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);System.out.println("hobby:"+hobby);}
- public void doPost(HttpServletRequestrequest, HttpServletResponse response)
- throws ServletException, IOException{doGet(request, response);}}
这里会出现乱码问题,是因为你在RegisterLogin.java中并没有给Request对象设置编码集,而Request对象的默认编码集是ISO8859-1是不支持汉字的,所以你只需要在此类中为其指明相应的编码即可:
改正:在doGet方法中加入如下代码指明接收请求的编码方式:
request.setCharacterEncoding("utf-8");
即可输出:
但是这种修改方式只在提交方式为post时才有效。当提交方式为get时是不起作用的。
即;
<form action ="RequestLogin" method ="get">
时即便在
RequestLogin.java
中再设置
request.setCharacterEncoding("utf-8");
也不会起任何作用了程序还会输出如图所示信息:
这时就需要在
RequestLogin.java
中含有中文的地方进行如下设置了即在doGet方法中加入如下代码:
- String username = new String(name.getBytes("iso8859-1"),"utf-8");
- String introduction = new String(intro.getBytes("iso8859-1"),"utf-8");
- System.out.println("username:"+username);
- System.out.println("password:"+introduction);
此时再度测试时就OK了!如图
好了到这里,你大概已经知道该如何对Response和Request对象中的乱码问题进行操作了吧!
3、防盗链
所谓的防盗链就是当你以一个非正常渠道去访问某一个Web资源的时候,服务器会将你的请求忽略并且将你的当前请求变为按正常渠道访问时的请求并返回到相应的页面,用户只有通过该页面中的相关操作去访问想要请求的最终资源。
例如,你有一个访问某资源的网址,但是你事先不知道这个网址是有防盗链的,那么当你输入该网址时你可能会发现,并没有马上跳转到你想要的资源页面而是一些无关的信息页面,但是就是在这些信息页面中你发现有一个超链接或是其他操作可以跳转到你所访问的最终资源页面。
这就是防盗链技术了,好了来看一个具体应用:
Rquest.java
- public class Request extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {getDoorChain(request, response);}
- private void getDoorChain(HttpServletRequest request,
- HttpServletResponse response) throws IOException {
- //通过request获取请求头参数
- String referer = request.getHeader("referer");
- if(referer==null || !referer.endsWith("http://localhost:8080/Request/index.jsp")){
- response.sendRedirect("http://localhost:8080/Request/index.jsp");
- return;
- }
- response.setCharacterEncoding("utf-8");
- response.setContentType("text/html;charset =utf-8");
- PrintWriter pw = response.getWriter();
- pw.write("喜剧片《东成西就》");
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }
index.jsp部分的主体代码:
- <body>
- 这里是防盗链技术的应用检测! <br>
- <a href ="/Request/Request" >喜剧片 </a>
- </body>
- </html>
效果如图:
例如我最终想要通过http://lcoalhost:8080/Request/Request这个网址获取到我想要的《东成西就》
的资源可是当我真正的输入这个网址时,却转到了:
http://localhost:8080/Request/index.jsp这个页面
只有当你点击“喜剧片”这个超链接时才会真正的得到你想要的资源页面即:
好了赶快自己动手试一试吧!
4、request对象实现请求转发:
Servlet API中定义了一个RequestDispatcher接口,俗称请求分派器。它定义了如下两个方法: public void forward(ServletRequest request, ServletResponseresponse) 、public void include(ServletRequest request,ServletResponse response) ,
获取RequestDispatcher实例的方式主要有两种:
- 调用ServletContext接口提供的getRequestDispatcher(Stringurl)方法。
- 调用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方法;
三、关于请求转发的一些细节
- forward方法用于将请求转发到RequestDispatcher对象封装的资源。
- 如果在调用forward方法之前,在Servlet程序中写入的部分内容已经被真正地传送到了客户端,forward方法将抛出IllegalStateException异常。
- 如果在调用forward方法之前向Servlet引擎的缓冲区 (response)中写入了内容,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区中的 内容将被清空,但是,已写入到HttpServletResponse对象中的响应头字段信息保持有效。
四、请求重定向和请求转发的区别
一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理,称之为请求转发。
一个web资源收到客户端请求后,通知浏览器去访问另外一个web资源,称之为请求重定向。
注意:
- RequestDispatcher.forward方法只能将请求 转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。 如果传递HttpServletResponse.sendRedirect方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。
- 调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL 地址变成重定向的目标URL;调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
- HttpServletResponse.sendRedirect 方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。
- RequestDispatcher.forward方法的调用者与 被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而 HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于 两个独立的访问请求和响应过程。
关于请求消息头我们在以后的学习中还会经常用到request对象是我们目前在JavaWeb开发中学到的三个作用域即ServletContext、Request和Session域之一,是非常重要的一个请求对象,希望以上的相关介绍对能你有所帮助!