Java 中的 HttpServletRequest 和 HttpServletResponse 对象
HttpServletRequest对象详解
javax.servlet.http.HttpServletRequest是SUN制定的Servlet规范,是一个接口。表示请求,“HTTP请求协议”的完整内容都被封装到request对象中,HttpServletRequest接口的父接口是javax.servlet.ServletRequest。
Apache软件基金会开发的“Tomcat容器”对javax.servlet.http.HttpServletRequest接口的实现类完整类名是org.apache.catalina.connector.RequestFacade,但是我们javaweb程序员不需要关心具体的请求对象类型,不需要关心是哪个容器,我们只需要面向HttpServletRequest接口调用方法即可。
一次请求对应一个请求对象,请求开始,请求对象被创建,请求结束,请求对象被回收,下一次请求的时候是一个新的请求对象。如何理解一次请求:浏览器向服务器发送请求到服务器响应结束为一次请求。
HttpServletRequest接口中常用的方法
通过用户提交的参数name获取参数value(最常用的方法)
String value = request.getParameter(String name);
向HttpServletRequest对象中存储数据(绑定)
request.setAttribute(String name,Object obj);
从HttpServletRequest对象中获取数据(读取数据)
Object obj = request.getAttribute(String name);
移除HttpServletRequest对象中的数据
request.removeAttribute(String name);
使用request对象完成转发(转发是一次请求,一次请求跨越多个Servlet)
request.getRequestDispatcher(“资源路径”).forward(request,response);
获取客户端的IP地址
String clientIP = request.getRemoteAddr();
获取URI
String uri = request.getRequestURI();
获取URL
StringBuffer url = request.getRequestURL();
获取Servlet Path
String servletPath = request.getServletPath();
获取应用程序的根路径,获取应用上下文路径
String contextPath = request.getContextPath();
解决请求体中的乱码问题(在从request对象中获取任何数据之前设置有效)
request.setCharacterEncoding(“UTF-8”);
在服务器端获取用户发送的请求中的所有Cookie
Cookie[] cookies = request.getCookies();
获取会话对象session
HttpSession sessoin = request.getSessoin(); 获取session对象,如果获取不到则开启新session
HttpSession sessoin = request.getSession(true); 获取session对象,如果获取不到则开启新session
HttpSession sessoin = request.getSession(false); 获取session对象,如果获取不到则返回null
HttpServletRequest对象是一个请求级别的对象,一次请求一个对象,所以request对象只能完整在同一次请求中进行数据的传递,可以跨越多个Servlet进行数据的传递,但是必须使用转发机制。如果request对象和ServletContext对象都可以完成此功能,我们优先选择request范围。request不能完成跨用户传递数据。只能完成在一次请求中传递数据。
HttpServletResponse对象详解
javax.servlet.ServletResponse是接口,是SUN制定的响应对象,专门完成向浏览器的响应动作。
javax.servlet.http.HttpServletResponse父接口是ServletResponse
获取响应流:PrintWriter out = response.getWriter();
关于PrintWriter中的方法:
1、println方法:输出到浏览器的HTML源码换行
2、print方法:输出到浏览器的HTML源码不换行,如果想在网页中做到换行效果,需要使用HTML识别的 <br>标签。
3、向特定的浏览器客户端发送Cookie:response.addCookie(cookie);
重定向:response.sendRedirect(“/webcontextPath/servletPath”);
关于转发和重定向
转发与重定向的区别(资源跳转),如下图所示
代码上的实现:
转发
request.getRequestDispatcher("/servletPath").forward(request,response);
重定向
response.sendRedirect("/webcontextPath/servletPath");
注意资源路径:在转发中不需要编写web应用的根路径名称。但是在重定向的时候需要编写web应用的根路径名称,假设web应用的根路径名称是StudyServlet,该web应用的根下有a资源,如果是转发则路径写 /a,如果是重定向则 /StudyServlet/a
RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的资源(这个资源可能是Servlet、JSP、HTML等),而HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到另一个WEB应用中的资源
调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;而调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”一共发出了两封信和收到了两次回复, “浏览器”也知道他借到的钱出自李四之手。RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只发 出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。
RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个WEB应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用HttpServletRequest.setAttribute方法传递预处理结果,那就应该使用RequestDispatcher.forward方法。不同WEB应用程序之间的重定向,特别是要重定向到另外一个WEB站点上的资源的情况,都应该使用HttpServletResponse.sendRedirect方法。
无论是转发还是重定向,转发和重定向后面不能再有转发和重定向相关的代码。(转发和重定向在同一个Servlet中只能有一次。)
怎么选择是重定向还是转发呢?
通常情况下转发更快,而且能保持request内的对象,所以它是第一选择。但是由于在转发之后,浏览器中URL仍然指向开始页面,此时如果重载当前页面,开始页面将会被重新调用。如果你不想看到这样的情况,则选择重定向(页面刷新问题)。
重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。
转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。
1、 如果是web应用之间资源的跳转,必须使用重定向。
2、 为了解决页面的刷新问题,必须使用重定向。
3、 如果在Servlet中向request对象中存储了一个数据,希望在下一个Servlet/JSP页面中把request对象中的数据取出来,这个时候必须使用转发,因为重定向是两次请求,request不能跨请求传递数据。其它情况都可以使用重定向。