1.jsp隐式对象简介
JSP 架构背后的理念是提供一个 Web 组件,它允许开发人员着重关注 Web 内容的表示,而不用陷入解析、编程和数据操纵等细节。JSP 应用程序本质上是特殊的 Web 组件,在处理用户请求之前,J2EE Web 容器首先将其转换成 servlet。在每个 JSP 应用程序内部有一套完整的隐式对象。
隐式对象使得开发人员可以访问容器提供的服务和资源。这些对象之所以定义为 隐式的,是因为不必显式地声明它们---这个对象己存在,你直接使用它的名字调用即可。它们在每个 JSP 页面当中都进行定义,并且在后台由容器使用。因为隐式对象是自动声明的,所以我们只需要使用与一个给定对象相关的引用变量来调用其方法。
JSP 容器使 9 个隐式对象可用,这些对象可以用在 scriptlet 和表达式中,因为它们是在生成的 servlet 的 _jspService() 方法中定义的。
下表列出了 JSP API 中 9 个隐式对象及其说明:
对象 类 目的
application javax.servlet.ServletContext 引用执行 JSP 所在的 Web 应用程序的环境。
config javax.servlet.ServletConfig 可以从这个对象获取部署描述符中给定的初始化参数。
exception java.lang.Throwable 可用于把 page 指令属性 isErrorPage 设为 true 的页面。它可用于异常处理。
Out javax.servlet.jsp.JspWriter 引用 JSP 页面的输出流。
page java.lang.Object 引用 JSP 页面生成的 servlet 的当前实例。
pageContext javax.servlet.jsp.PageContext 提供了某些便利方法和对隐式对象的存储引用。
request javax.servlet.ServletRequest 的子类型 引用传递给 _jspService() 方法的当前请求。
response javax.servlet.ServletResponse 的子类型 引用发送给客户机的响应。也把它传递给 _jspService() 方法。
session Javax.servlet.http.HttpSession 会话对象
以上对象中,常用的为request、session、application对象,其它对象应尽量避免使用;它们都于Servlet中的同名对象作用相同。
2.作用域范围相关对象
与servlet中同样 (基实jsp就是一种servlet),JSP 定义的四个隐式对象可以用来在一个特定的上下文或者作用域中加入有状态数据。这四个对象是 application 、 session 、 request 和 pageContext 。下表列出了这四个对象和它们定义的状态上下文,同时还给出了对每个对象的简单描述。
隐式对象 作用域 描述
ServletContext Application 与Servlet中ServletContext相同且共享数据
HttpSession Session 代表当前HTTP请求对象,与Servlet中request相同且共享数据
HttpServletRequest Request 代表当前的 HTTP 请求。这个上下文可以跨越多个 Web 组件(servlet 和 JSP 页面),只要这些组件属于同一原子请求的一部分。由客户机提供的特定于请求的数据(请求方法、URI、HTTP 参数等等)都被自动地保存在一个 request 上下文中。servlet 或 JSP 页面还可以程式化地(programmatically)将数据的作用域指定为 request ,以便允许同一 request 作用域中的其他 servlet 或 JSP 页面可以获取该数据
request 作用域非常适合于运行期间在组件间共享数据以处理一个特定的请求。 session 作用域被设计用来为单个用户提供持久的、有状态的体验,它可以跨越多个请求。 application 作用域只有需要在组件之间跨用户会话共享数据时才应该使用。
3.Jsp与Servlet共享数据示例
我们演示在jsp文件中使用java对象和与Servlet通过application、session、request共享数据,这个测试流程如下:
用户在登陆页面(login.jsp)输入帐号,如果帐号正确(本例都为netjava),则转向loginOK.jsp,在这个页面中会输出servlet在这三个范转中的数据对象;如果输入的帐号不正确,则转向login.jsp,并给用户显示出错信息,首选,我们login.jsp页面代码如下:
<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<html> <head>
<title>jsp-->Servlet数据传送 蓝杰信息@www.NetJava.cn</title>
</head> <body>
<form name="testForm" method="get" action="UserLoginServlet">
<br>用户名:<input type="text" name="userName"/>
<br>密 码:<input type="password" name="pwd"/>
<input type="Submit" name="submit" value="登陆"/>
</form>
</body></html>
然后,编写Servlet:UserLoginServlet.java代码如下:
package cn.netjava.servlet;
import java.io.*;
import javax.servlet.* ;
import java.util.*;
//处理用户登陆请求的servlet,演示servlet与jsp交换数据
public class UserLoginServlet extends HttpServlet {
//处理用户请求
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charSet=GBK");
//接收客户端发送上来的参数
String userName=request.getParameter("userName");
String pwd=request.getParameter("pwd");
//如果帐号正确,则转向loginOK.jsp
if(null!=userName&&userName.equals("netjava")
&&null!=pwd&&pwd.equals("netjava")){
UserInfo user=new UserInfo();
user.setUserName(userName);
user.setUserPWD(pwd);
//在全局范围内放入对象
this.getServletContext().setAttribute("onlineCount","一个用户");
//在session范围内放入对象
request.getSession().setAttribute("userObj", user);
//在request范围内放入模执从数据库中取出的用户列表
// 这段代码向列表中放入10个用户对象,
List<UserInfo> userList=new ArrayList();
for(int i=0;i<10;i++){
UserInfo us=new UserInfo();
us.setId(i+1);
us.setUserName("用户名"+i);
us.setUserDesc("这是用户说明");
userList.add(us);
}
request.setAttribute("userList", userList);
request.getRequestDispatcher("/loginOK.jsp").forward(request, response);
}
else{
request.setAttribute("errorMsg", "帐号或密码错误!");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
public void init() throws ServletException {}
}
最后,再编写loginOK.jsp,用以展示UserLoginServlet中放入的数据:
<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%@ page import="cn.netjava.servlet.UserInfo" %>
<html> <head>
<title>jsp-->Servlet数据传送 蓝杰信息@www.NetJava.cn</title>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
</head><body>
<br>从application范围内取出的onlineCount变量值
<%
String s=(String)application.getAttribute("onlineCount");
out.println("<br>application范围内onlineCount的值是: "+s);
%>
<hr>
<br>从Session范围内取出的UserInfo对象,并输出其中数据
<%
//以userObj为名字,servlet在session中放放的是UserInfo对象,所以在此强制转型
UserInfo userObj=(UserInfo)session.getAttribute("userObj");
%>
<br>登陆用户名:<%=userObj.getUserName() %>
<br>登陆密码:<%=userObj.getUserPWD() %>
<hr>
<br>从request范围内取出的UserInfo列表对象,并输出其中数据
<%
List<UserInfo> userList=(List)request.getAttribute("userList");
%>
<%--将userList中的对象数据输出展示为表格 --%>
<table align="auto" border="1" width="50%">
<tr><td>用户ID</td><td>用户名</td><td>用户说明</td></tr>
<%--循环输出每行数据 --%>
<%for(int i=0;i<userList.size();i++){
UserInfo us=userList.get(i);
%>
<%="<tr><td>"+us.getId()
+"</td><td>"+us.getUserName()
+"</td><td>"+us.getUserDesc(
)+"</td></tr>" %>
<%
}
%>
</table></body></html>
在登陆页面中输入netjava做帐号,结果loginOK.jsp输出如图:
但如果我们输入的帐号不是netjava,则返回的页面是login.jsp,且注意,我们在servlet中当用户登陆失败时,在request对象中还放入了一条消息:
request.setAttribute("errorMsg", "帐号或密码错误!");
request.getRequestDispatcher("/login.jsp").forward(request, response);
所以,login.jsp页面还需要更改一下:
<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<html> <head>
<title>jsp-->Servlet数据传送 蓝杰信息@www.NetJava.cn</title>
</head> <body>
<form name="testForm" method="get" action="UserLoginServlet">
<br>用户名:<input type="text" name="userName"/>
<br>密 码:<input type="password" name="pwd"/>
<%
String errorMsg=(String)request.getAttribute("errorMsg");
if(null!=errorMsg){
out.print("<br>"+errorMsg);
}
%>
<input type="Submit" name="submit" value="登陆"/>
</form>
</body></html>
这样,如果有servlet中传送过来的消息,就可以取得到;现在,如果输入错误的帐号,就可以看到:
需要注册的是:如果必须是在用户会话周期中才用到的数据,才有必要放入session中,如果只是有一个请求和响应间交换的数据,放入request对象即可。