黑马程序员技术交流社区

标题: 【西安校区】关于Servlet的三个域对象的介绍 [打印本页]

作者: 西安Java组    时间: 2018-4-18 15:19
标题: 【西安校区】关于Servlet的三个域对象的介绍

## 1、概述
### 1.1、什么是域对象?
在Web开发中,所有的组件(JSP/Servlet/Filter/Listener)在开发的过程中都是相互独立,彼此没有任何交互的。但是我们往往在完成一个任务的时候是需要多个组件之间协同来完成,就必须在各个组件之间对数据进行共享。
例如:我们要在页面呈现所有的商品信息时,需要先访问Servlet,由Servlet调用业务层查询数据,并且将这组数据存入request域中,然后跳转到JSP,在JSP中将request域中的数据呈现,流程如下
![0](images/0.png)

在这个案例中我们就使用Servlet组件来获取数据,使用JSP组件来显示数据。那么JSP显示的数据就应该是Servlet中获取的数据。那么要实现数据的共享,我们就需要使用域对象。
简单说来,域对象就是用来在各个组件之间进行数据共享的一种方式。即:
  Servlet1 ------------>作用域对象(数据)-----------> jsp


### 1.2、Servlet中的作用域有哪些

在Servlet中,提供了三个作用域来实现数据共享。根据范围的大小,分为三类:
![0](images/1.png)
   
作用域对象如何来共享数据(把数据存放到作用域,从作用域取出数据,修改/删除数据):
  - 设置共享数据: 作用域对象.setAttribute(String name,Object value)
  - 获取共享数据: Object val = 作用域对象.getAttribute(String name);
  - 删除共享数据: 作用域对象.removeAttribute(String name);

注意:
  - 所有作用域对象的操作方法都是相同的
  - 那个域中设置了共享数据,就只能从该域中获取这个数据。如果是需要获取request域中的共享数据,则页面的跳转只能是请求转发。
![0](images/2.png)




## 2、代码演示

### 2.1、准备两个Servlet,一个Servlet用来给域中存储数据,另一个Servlet用来获取域中的数据
#### 存储数据的Servlet:
    public class SaveDateServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
   request.setAttribute("rname", "rvalue");
   request.getSession().setAttribute("sname", "svalue");
   getServletContext().setAttribute("aname", "avlue");
   //使用请求转发
   request.getRequestDispatcher("/ServletDemo10").forward(request,response);
   //重定向
   //response.sendRedirect(request.getContextPath() + "/ServletDemo10");
  }

  protected void doPost(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
  }
}

#### 获取数据的Servlet:
`public class ServletDemo10 extends HttpServlet {
  private static final long serialVersionUID = 1L;

  protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
   //获取request域中的数据
   String rname  = (String) request.getAttribute("rname");
   String sname  = (String) request.getSession().getAttribute("sname");
   String aname  = (String) getServletContext().getAttribute("aname");
   System.out.println("rname : " + rname);
   System.out.println("sname : " + sname);
   System.out.println("aname : " + aname);
  }

  protected void doPost(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
   doPost(request, response);
  }

}`

### 2.2、 运行结果
- 如果是请求转发到 ServletDemo10(一次请求内),运行结果如下:
![0](images/3.png)
<font color=red>三个域中的数据都是可以获取的!!!</font>

- 如果是重定向到 ServlrtDemo10(两次请求,一次会话),运行结果如下:
![0](images/4.png)

<font color=red>因为是两次请求,所以request域的数据过期了!!!</font>

- 如果是使用另外一个浏览器,直接访问ServletDemo10(两次请求,两次会话,一个应用),运行结果如下:
![0](images/5.png)
<font color=red>因为是两次请求,两次会话,所以request域和session域的数据过期了!!!</font>

## 总结:在使用域对象进行数据传输的一些注意事项:
### 域对象在选择的时候,能使用小的就不要使用大的。一般情况下,可以这么选择:
- 如果需要存储全局的数据,这个时候可以使用ServletContext域对象。比如
  - 网站在线人数统计: 所有用户看到的都应该是这一个数据
  
- 如果数据是在多次请求中使用,并且在会话结束了后就无效了,那么就可以使用HttpSession域对象。
  - 用户登录:在访问其他页面时,用户的数据也是需要显示的。
  - 购物车:购物信息可以随时向购物车添加商品,也可以随时查看购物车信息。
- 只在这次请求中使用,请求结束了就没有了,可以使用HttpServletRequest域对象。
  - 访问一个列表页面:数据只要显示到页面就可以了,下一次访问再重新查询。
- 对于使用session域还是request域,还可以这么选择:
  - 如果想用请求转发,那么就一定使用request域来进行数据传递。





作者: hmhm123    时间: 2018-4-23 22:27
总结的很好,就是帖子中的图片上传后没引用,导致帖子图片没显示,如果能排版一下更好。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2