每篇一句:观察的本质是:不赞美,不责难,甚至也不惋惜,但求了解认识而已。 ——《看见》
看一下维基百科的定义:
JSP(全称JavaServer Pages)是由Sun Microsystems公司主导创建的一种动态网页技术标准。JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成HTML、XML或其他格式文档的Web网页,然后返回给请求者。
JSP 最终会变成一个完整的 servlet 在 Web 应用中运行。首先,容器拿到在 JSP 中写的代码,把这些代码转换为一个 servlet 类源文件 ( .java ),然后在把这个源文件编译为 Java servlet 类。然后和 servlet 运行一样了。
在 JSP 中可以使用 scriptlet 放入常规的 Java 代码。所谓 scriptlet 就是 放在 <% ··· %>
标记中的 Java 代码。例如:
<% out.println(foo.Counter.getCount()); %>
在 JSP 中使用 Java,要么导入包,要么在代码中使用完全限定名。
指令有 3 种:page. include. taglib。
定义页面特定的属性,如字符编码,页面响应的内容类型,以及这个页面是否有隐式的会话对象
导入单个包
<%@ page import="foo.*" %>
<html><body>
The page count is:
<%
out.println(Counter.getCount());
%>
body>html>
导入多个包
使用逗号来分隔多个包。
<%@ page import="foo.*, java.util.*" %>
page 指令的属性
属性 | 作用 |
---|---|
import | 定义 Java,所定义的 import 语句会增加到生成的 servlet 类中 |
isThreadSafe | 定义生成的 servlet 是否需要实现 SingleThreadModel。默认值为 “true”,表示不需要实现 SingleThreadModel |
contentType | 定义 JSP 响应的 MIME 内容 |
isELIgnored | 定义转换这个页面时是否忽略 EL 表达式 |
isErrorPage | 定义当期页面是否是另一个 JSP 的错误页面。默认是 “false” |
errorPage | 定义一个资源的 URL,如果有未捕获的 Throwable,就会发送到这个资源 |
定义 JSP 可以使用的标记库
<%@ taglib tagdir="/WEB-INF/tags/cool" prefix="cool" %>
定义在转换时增加到当前页面的文本和代码,以建立可重用的块
<%@ include file="wickedHeader.html" %>
表达式元素会自动打印放在标记之间的内容
<%= Counter.getCount() %>
表达式会成为 out.print()
的参数。也就是说,容器拿到 <%=
和 %>
之间的所有内容,把它作为参数传递给打印语句,打印到隐式响应 PrinWriter out。如上式会转换为
out.println(Counter.getCount());
注意:不要把一个返回类型为 void 的方法用作表达式
JSP 转换为 servlet 代码时,所有 scriptlet 和表达式代码都放在服务方法中。所以 scriptlet 中声明的变量都是局部变量
声明的 JSP 元素
<@! int count = 0; %>
JSP 声明用于声明所生成 servlet 类的成员,包括变量和方法。而 <%!
和 %>
标记之间的 所有内容都会增加到类中,且置于服务方法之外。
例如,这个 JSP
<html><body>
<%! int doubleCount(){
count = count * 2;
return count;
}
%>
<%! int count = 0; %>
The page count is now:
<%= doubleCount() %>
body>html>
会转换为这个 servlet
public class basicCounter_jsp extends SomeSepecialHttpServlet{
int doubleCount(){
count = count * 2;
return count;
}
int count = 0;
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
PrintWriter out = response.getWriter();
response.setContentType("text/html");
response.write("");
response.write("The page count is now:");
response.print( doubleCount() );
response.write("");
}
}
容器把 JSP 转换为 servlet 时,服务方法最前面会有一些隐式对象声明和赋值。所有的隐式对象都会映射到 Servlet/JSP 中的某个东西。
API | 隐式对象 |
---|---|
JspWriter | out |
HttpServletRequest | request |
HttpServletResponse | response |
HttpSession | session |
ServletContext | application |
Throwable | exception |
PageContext | pageContext |
Object | page |
其中 PageContext 封装了其他隐式对象,可以使用提供的 PageContext 的引用得到其他隐式对象的引用以及所有作用域的属性
在 JSP 中可以有两种不同的注释:
容器把它直接传递给客户,在客户端,浏览器会把它解释为注释
<%-- JSP 注释 -->
JSP 注释会在转换页面时将其去掉
容器根据 JSP 生成的类会实现 HttpJspPage 接口。其中三个关键方法:
- jspInit()
这个方法由 init() 方法调用,可以覆盖
这个方法由 servlet 的 destroy() 方法调用,也可以覆盖
这个方法由 servlet 的 service() 方法调用,不过不能覆盖
JSP 完整的生命周期如下:
在整个生命周期中,转换和编译步骤只发生了一次。一旦servlet 得到加载和初始化,请求时只会创建或分配一个线程来运行服务方法
与为 servlet 配置初始化参数基本一样,只是在 标记中增加一个 元素
<web-app ···>
<servlet>
<servlet-name>MyTestInitservlet-name>
<jsp-file>/TestInit.jspjsp-file>
<init-param>
<param-name>emailparam-name>
<param-value>[email protected]param-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>MyTestInitservlet-name>
<url-pattern>/TestInit.jspurl-pattern>
servlet-mapping>
web-app>
jspInit() 方法由 servlet 的 init() 方法调用,在 JSP 页面成为 servlet 的最开始,容器会调用它。所以在 jspInit() 方法中调用 getServletConfig() 和 getServletContext()。
<%!
public void jspInit(){
ServletConfig sConfig = getServletConfig();
String emailAddr = sConfig.getInitParameter("email");
ServletContext ctx = getServletContext();
ctx.setAttribute("email", emailAddr);
}
%>
一般使用隐式对象来得到和设置对应 JSP 中 4 个属性作用域的属性,即标准的 servlet 请求,会话,应用(上下文) 和 页面作用域
servlet | JSP(使用隐式对象) | |
---|---|---|
应用 | getServletContext().setAttribute("foo", barObj); |
application.setAttribute("foo", barObj); |
请求 | request.setAttribute("foo", barObj); |
request.setAttribute("foo", barObj); |
会话 | request.getSession.setAttribute("foo", barObj); |
session.setAttribute("foo", barObj); |
页面 | 不适用 | pageContext.setAttribute("foo", barObj); |
使用 PageContext 可以得到任意作用域的属性
1.设置和获取页面作用域属性
<% Float one = new Float(42.5); %>
<% pageContext.setAttribute("foo", one); %>
<%= pageContext.getAttribute("foo") %>
2.使用 pageContext 设置和获取会话作用域属性
<% Float two = new Float(42.5); %>
<% pageContext.setAttribute("foo", two, PageContext.SESSION_SCOPE); %>
<%= pageContext.getAttribute("foo", PageContext.SESSION_SCOPE); %>
等价于
<%= session.getAttribute("foo", PageContext.SESSION_SCOPE); %>
3.使用 PageContext 获得一个应用作用域属性
<%= pageContext.getAttribute("email", PageContext.APPLICATION_SCOPE) %>
等价于
<%= application.getAttribute("email") %>
4.使用 pageContext,不知道作用域也可以查找一个属性
<%= pageContext.findAttribute("foo") %>
查找时,首先在页面上下文中查找,如果页面作用域中没有这样的 “foo” 属性,会在其他作用域查找,即先在请求作用域查找,再查找会话作用域,最后查找应用作用域
EL 代表 “表达式语言” ,它的用途是提供一种简单的方法来调用 Java 代码,但是代码放在别的地方。它的表达式形式是:(后面会详细介绍)
${something}
例如:
Please contact: ${applicationScope.email}
禁用脚本元素
在 DD 中放一个 标记,可以让 JSP 禁用脚本元素
<web-app ···>
···
<jsp-config>
<jsp-property-group>
<url-pattern>*.jspurl-pattern>
<scripting-invalid>truescripting-invalid>
jsp-property-group>
jsp-config>
<web-app>
忽略 EL
当你想把 EL 作为不处理的文本对待时,可以禁用 EL。可以通过 page 指令,或通过一个 DD 元素指定
在 DD 元素中放置
:
<web-app>
···
<jsp-config>
<jsp-property-group>
<url-pattern>&.jsp</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>
</web-app>
通过 page 指令
<%@ page isElIgnored="true" %>
JSP 元素:动作
标准动作:
<jsp:include page="wickedFooter.jsp" />
其他动作:
set var="rate" value="32" />
如果有任何问题,欢迎交流学习。