一.JSP运行原理
每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ,然后按照servlet的调用方式进行调用。
由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。
JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。
这9个对象分别是哪些,以及作用也是笔试经常考察的知识点。
二.九大隐式对象
1.哪九大隐式对象??
如下图所示:
Request
Response
Session
Application servletContext
Config servletConfig
Page this
Exception
Out jspWriter
pageContext
为什么叫隐式对象?个人感觉是因为在jsp中内置了,隐藏包含了,所以定义了专有名词,隐式对象.
除了out和pageContext这两个,其余7个都是servlet中已经有的,这里主要介绍jsp独有的out和pageContext.
2.out隐式对象
out隐式对象用于向客户端发送文本数据。
out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
>>设置page指令的buffer属性关闭了out对象的缓存功能
>>out对象的缓冲区已满
>>整个JSP页面结束
如下所示:
<%
out.write("11111");
response.getWriter().write("222222");
%>
结果:
为什么会这样? 上面明明先输出的11..,但显示时却显示为222..111?
主要是因为,首先Jspwriter会将数据先写入缓冲区内,当jsp页面结束时才会将缓冲区的内容显示出来.
同时,整个jsp页面中关于html页面内容的部分也是通过jspwriter对象(即out的方式输出),所以如下,
<body>
00000
<%
//out.write("11111");
response.getWriter().write("222222");
%>
</body>
会有如下输出:
所以,jsp中尽量全部用out对象进行输出,另外jsp页面中尽量不要写任何java代码.
3.pageContext隐式对象
pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象,可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。
通过pageContext获得其他对象 :
getException方法返回exception隐式对象
getPage方法返回page隐式对象
getRequest方法返回request隐式对象
getResponse方法返回response隐式对象
getServletConfig方法返回config隐式对象
getServletContext方法返回application隐式对象
getSession方法返回session隐式对象
getOut方法返回out隐式对象
pageContext封装其它8大内置对象的意义,这个主要用于自定义标签.
pageContext对象的方法:
public void setAttribute(java.lang.String name,java.lang.Object value)
public java.lang.Object getAttribute(java.lang.String name)
public void removeAttribute(java.lang.String name)
pageContext对象中还封装了访问其它域的方法
public java.lang.Object getAttribute(java.lang.String name,int scope)
public void setAttribute(java.lang.String name, java.lang.Object value,int scope)
public void removeAttribute(java.lang.String name,int scope)
代表各个域的常量
PageContext.APPLICATION_SCOPE
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE
findAttribute方法 (*重点,查找各个域中的属性) EL表达式
JavaWeb中有四个域对象,按作用范围从小到大进行排序为pageContext(作用范围为:page)--->request域(请求时)--->session(整个会话都有頝)--->application/servletContext(应用上下文都有頝)
例:
<body>
<%
request.setAttribute("data", "abc");
String data = pageContext.getAttribute("data",PageContext.REQUEST_SCOPE).toString();
out.write(data);
out.write("<br>");
out.write(pageContext.findAttribute("data").toString());//依次从page request session application四个域中找对应的值
%>
</body>
注:EL表达式中取值就是依靠pageContext.findAttribute()方法的.
三.JSP常用标签
1.<jsp:include>标签
<jsp:include>标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。
语法:
<jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。
<jsp:include>标签是动态引入, <jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。
而include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。
不管是<jsp:include>标签,还是include指令,它们都会把两个JSP页面内容合并输出,所以这两个页面不要出现重复的HTML全局架构标签,否则输出给客户端的内容将会是一个格式混乱的HTML文档。
2.<jsp:forward>标签
<jsp:forward>标签用于把请求转发给另外一个资源。
语法:
<jsp:forward page="relativeURL | <%=expression%>" />
page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得。
3.<jsp:param>标签
当使用<jsp:include>和<jsp:forward>标签引入或将请求转发给其它资源时,可以使用<jsp:param>标签向这个资源传递参数。
语法1:
<jsp:include page="relativeURL | <%=expression%>">
<jsp:param name="parameterName" value="parameterValue|<%= expression %>" />
</jsp:include>
语法2:
<jsp:forward page="relativeURL | <%=expression%>">
<jsp:param name="parameterName" value="parameterValue|<%= expression %>" />
</jsp:include>
<jsp:param>标签的name属性用于指定参数名,value属性用于指定参数值。在<jsp:include>和<jsp:forward>标签中可以使用多个<jsp:param>标签来传递多个参数。
例:
home.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>jsp tags</title>
</head>
<body>
<%-- <jsp:include page="public/head.jsp"></jsp:include> --%>
<jsp:forward page="/HomeServlet">
<jsp:param value="amosli" name="username"/>
</jsp:forward> </body>
</html>
web.xml:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app>
<welcome-file-list>
<welcome-file>/home.jsp</welcome-file>
</welcome-file-list>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>HomeServlet</servlet-name>
<display-name>HomeServlet</display-name>
<description></description>
<servlet-class>com.amos.HomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HomeServlet</servlet-name>
<url-pattern>/HomeServlet</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/error/error.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
</web-app>
HomeServlet.java
package com.amos; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HomeServlet extends HttpServlet {
private static final long serialVersionUID = 1L; public HomeServlet() {
super();
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
response.getWriter().write(username+",欢迎您!");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
流程:web.xml中配置欢迎界面为home.jsp,然后home.jsp转向那个HomeServlet,然后将值显示到网页中.
效果如下图所示:
或者将home.jsp页面改为:
<body>
<%-- <jsp:include page="public/head.jsp"></jsp:include> --%>
<%String name="amosli"; %>
<jsp:forward page="/HomeServlet">
<jsp:param value="<%= name %>" name="username"/>
</jsp:forward>
</body>
使用jsp语法表达式设置参数.