一、jsp中嵌入java代码的三种方法
1. <%! 声明; %> :
此方式可以声明变量或方法。
将jsp编译为class文件再反编译后查看可知,此方法声明的变量位于任何方法之外。对应于servlet就是声明成员变量,因此可以声明变量也可以声明方法。而声明的变量因其为成员变量,所以在不断刷新页面时会累加。由于它并不位于service()方法中,而jsp内置对象是在该方法中初始化的,因此不能直接使用jsp内置对象。
2.<% java代码; %>
此方法仅仅可以声明变量,不可声明方法。
将jsp编译为class文件再反编译后查看可知,此方法声明的变量位于_jspService()方法之内,对应于servlet就是声明位于service()方法中的变量。所以在刷新页面时该变量不会累加。
3.<%=表达式 %>
此方法用于表达式,等价于<% out.print(); %>。因此此处只能写入表达式并输出其值到页面,不能声明变量或方法。在表达式中不能加分号。
二、jsp四个作用域
jsp中存在四个作用域:application、session、request、page。
application
application作用域就是服务器启动到关闭的整段时间,在这个作用域内设置的信息可以被所有应用程序使用。application作用域上的信息传递是通过ServletContext实现的,对应于在servlet中获取方式是: ServletContext application=this.getServletContext(); 此对象提供的主要方法如下所示:
Object getAttribute(String name) //从application中获取信息;
void setAttribute(String name, Object value) //向application作用域中设置信息。
session
session作用域比较容易理解,同一浏览器对服务器进行多次访问,在这多次访问之间传递信息,就是session作用域的体现。session是通过HttpSession接口实现的,它提供的主要方法如下所示。Object HttpSession.getAttribute(String name) //从session中获取信息。
void HttpSession.setAttribute(String name, Object value) //向session中保存信息。
HttpSession HttpServletRequest.getSessio() //获取当前请求所在的session的对象。
session的开始时刻比较容易判断,它从浏览器发出第一个HTTP请求即可认为会话开始。但结束时刻就不好判断了,因为浏览器关闭时并不会通知服务器,所以只能通过如下这种方法判断:如果一定的时间内客户端没有反应,则认为会话结束。Tomcat的默认值为120分钟,但这个值也可以通过HttpSession的setMaxInactiveInterval()方法来设置:
void setMaxInactiveInterval(int interval)
如果想主动让会话结束,例如用户单击“注销”按钮的时候,可以使用 HttpSession 的 invalidate()方法,用于强制结束当前session:
void invalidate()
精神病人思路广:初次请求且请求的sevlet中包含session引用时,响应头中将包含set-Cookie这个响应头信息,浏览器将sessionId保存于cookie中,之后每次请求将会带上这一ID,服务器将会根据ID来找到Session对象。当会话结束时(关掉所有该站点网页)此cookie值将会过期,因此关闭浏览器session作用域变量就表现为过期了。
request作用域
一个HTTP请求的处理可能需要多个Servlet合作,而这几个Servlet之间可以通过某种方式传递信息,但这个信息在请求结束后就无效了。Servlet之间的信息共享是通过HttpServletRequest接口的两个方法来实现的。void setAttribute(String name, Object value) //将对象value以name为名称保存到request作用域中。
Object getAttribute(String name) //从request作用域中取得指定名字的信息。
转发
JSP中的doGet()、doPost()方法(使用get或post方法提交数据是自动调用)的第一个参数就是HttpServletRequest对象,使用这个对象的 setAttribute()方法即可传递信息。那么在设置好信息之后,要通过何种方式将信息传给其他的Servlet呢?这就要用到RequestDispatcher接口的forward()方法,通过它将请求转发给其他Servlet。page作用域
page对象的作用范围仅限于用户请求的当前页面,对于page对象的引用将在响应返回给客户端之后被释放,或者在请求被转发到其他地方后被释放。对page对象的引用通常存储在pageContext对象中。request和page的生命周期都是短暂的,它们之间的区别:一个request可以包含多个page页(include,forward及filter)。
在jsp中使用jsp:userBean来创建实例并指定作用域
<jsp:useBean id="pagevar" scope="page" class="java.lang.StringBuffer"/>
<jsp:useBean id="requestvar" scope="request" class="java.lang.StringBuffer"/>
<jsp:useBean id="sessionvar" scope="session" class="java.lang.StringBuffer"/>
<jsp:useBean id="applicationvar" scope="application"/>
三、转发与重定向
重定向和转发有一个重要的不同:当使用转发时,JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程。 与之相反,重定向方式的含义是第一个页面通知浏览器发送一个新的页面请求。因为,当你使用重定向时,浏览器中所显示的URL会变成新页面的URL, 而当使用转发时,该URL会保持不变。重定向的速度比转发慢,因为浏览器还得发出一个新的请求。同时,由于重定向方式产生了一个新的请求,所以经过一次重定向后,request内的对象将无法使用。怎么选择是重定向还是转发呢?通常情况下转发更快,而且能保持request内的对象,所以他是第一选择。但是由于在转发之后,浏览器中URL仍然指向开始页面,此时如果重载当前页面,开始页面将会被重新调用。如果你不想看到这样的情况,则选择转发。
在sevlet中,调用response. forward()将会进行转发,调用 sendRedirect则会重定向。
而在struts中,
<action name="deptAction" class="com.syaccp.erp.action.DeptAction">
<result name="success">/WEB-INF/jsp/basic/dept_list.jsp</result>
<result name="editView">/WEB-INF/jsp/basic/dept_edit.jsp</result>
</action>
不指定时默认使用的是转发方式;
上例action中,success对应的视图是通过默认的转发(dispatch)跳转的。editView作为增删改的一部分,应该通过重定向来跳转页面,这样必须显式声明type=redirect,来达到重定向的效果。这时editView的内容改为action中一个方法更合适。如:
<action name="deptAction" class="com.syaccp.erp.action.DeptAction">
<result name="success">/WEB-INF/jsp/basic/dept_list.jsp</result>
<result name="editView" type="redirect">deptAction!select.action</result>
</action>
这里在执行edit方法后返回editView字符串,将会再执行select方法,跟DeptEditServlet里response.sendRedirect("DeptListServlet")类似
上例只是重定向同一个Action类中的其他方法,开发中可能还需要重定向到其他Action类中,这时就需要用到type属性的另一个值:redirectAction:
<action name="deptAction" class="com.syaccp.erp.action.DeptAction">
<result name="success">/WEB-INF/jsp/basic/dept_list.jsp</result>
<result name="editView" type="redirect">deptAction!select.action</result>
<result name="index" type="redirectAction">indexAction.action</result>
</action>
上例中,如果deptAction中某个方法返回字符串为index,则将跳转到indexAction去,执行indexAction的execute方法。
如果indexAction在其他包里面,则前面应加上包名,例:index/indexAction
四、内置对象
jsp有如下九种内置对象
内置对象 | 代表内容 | 范围 |
request | 触发服务调用的请求 | request |
response | 对请求的应答 | page |
session | 为请求的客户创建的session对象 | session |
application | 从 servlet 配置对象获得的 servlet 上下文(如在getServletConfig() ,getContext()的调用中) | application |
out | 向输出流写入内容的对象 | page |
pageContext | 本 JSP 的页面上下文 | page |
page | 实现处理本页当前请求的类的实例 | page |
config | 本 JSP 的 ServletConfig | page |
exception | 表示JSP页面运行时产生的异常 | Page |
request 对象代表的是来自客户端的请求,例如我们在FORM表单中填写的信息等,是最常用的对象
常用的方法有:getParameter、getParameterNames 和getParameterValues 通过调用这几个方法来获取请求对象中所包含的参数的值。
response 对象代表的是对客户端的响应,也就是说可以通过response 对象来组织发送到客户端的数据。但是由于组织方式比较底层,所以不建议普通读者使用,需要向客户端发送文字时直接使用
pageContext 对象直译时可以称作“页面上下文”对象,代表的是当前页面运行的一些属性
常用的方法有 :findAttribute、getAttribute、getAttributesScope 和getAttributeNamesInScope
一般情况下pageContext对象用到得也不是很多,只有在项目所面临的情况比较复杂的情况下,才会利用到页面属性来辅助处理。
session 对象代表服务器与客户端所建立的会话,当需要在不同的JSP页面中保留客户信息的情况下使用,比如在线购物、客户轨迹跟踪等。“session” 对象建立在cookie的基础上,所以使用时应注意判断一下客户端是否打开了cookie。常用的方法包括getId、 getValue、 getValueNames和putValue等。
application 对象负责提供应用程序在服务器中运行时的一些全局信息,常用的方法有getAttribute、setAttribute、getMimeType和getRealPath等。
out 对象代表了向客户端发送数据的对象,与“response” 对象不同,通过“out” 对象发送的内容将是浏览器需要显示的内容,是文本一级的,可以通过“out” 对象直接向客户端写一个由程序动态生成HTML文件。常用的方法除了pirnt和println之外,还包括clear、clearBuffer、flush、getBufferSize和getRemaining,这是因为“out” 对象内部包含了一个缓冲区,所以需要一些对缓冲区进行操作的方法
config 对象提供一些配置信息,常用的方法有getInitParameter和getInitParameterNames,以获得Servlet初始化时的参数。
page对象代表了正在运行的由JSP文件产生的类对象,不建议一般读者使用。
exception 对象则代表了JSP文件运行时所产生的例外对象,此对象不能在一般JSP文件中直接使用,而只能在使用了“<%@ page isErrorPage="true "%>”的JSP文件中使用
反编译jsp编译产生的class文件可以看到在_jspService方法中前八个变量的初始化与
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
response.setContentType("text/html; charset=gb2312");
pageContext = _jspxFactory.getPageContext(this, request, response,
"", true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
// 省略输出语句<span> out.write("/r/n"); </span>等
} catch (Throwable t) {
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try { out.clearBuffer(); } catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}