作为JSP
JSP变成Servlet。这个servlet不用你来创建。容器会查看你的JSP,把它转换成Java源代码,在编译成完整的Java servlet类。
JSP技术模型
6.1 识别或描述以下元素,或为以下元素编写JSP代码:
- 模板文本
- 脚本元素(注释、指令、声明、scriptlet和表达式)
- 标准动作和制定动作
- 表达式语言元素
6.2 编写使用以下指令的JSP代码:
- page(带有属性import、session、contentType和isELIgnored)
- include
- taglib
6.3 编写使用了正确语法的JSP文档(基于XML的文档)
6.4 描述页面生命周期的作用和事件序列:
- JSP页面转换
- JSP页面编译
- 加载类
- 创建实例
- 调用jspInit方法
- 调用_jspService方法
- 调用_jspDestroy方法
6.5 给定一个设计目标,使用适当地隐式对象编写JSP代码:
- request
- response
- out
- session
- config
- application
- page
- pageContext
- exception
6.6 配置部署描述文件来声明一个或多个标记库,禁用计算(表达式)语言,以及禁用脚本语言
6.7 给定一个特定的设计目标,要求将一个JSP片段包含在另一个页面中,编写JSP代码使用最合适的包含机制(include指令或jsp:include标准动作)
JSP变成一个servlet
这一章将解决下面几个问题:
- JSP文件中的各个部分最后会放在servlet源代码中的说明位置?
- 能访问JSP页面的“servlet性”吗?例如,JSP中有ServletConfig或ServletContext的概念吗?
- JSP中可以放哪些类型的元素?
- JSP中的不同元素有什么语法?
- JSP的生命周期是怎样的?能介入到JSP生命周期中吗?
- JSP中的不同元素在最后的servlet中如何交互?
建立一个JSP显示被访问了多少次
开发环境:
BasicCounter.jsp文件代码:
<!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">
</head>
<body>
The page count is:
<%
//JSP不认识Counter类,所以需要foo.Counter
out.println(foo.Counter.getCount());
%>
</body>
</html>
Counter.java文件代码:
package foo;
public class Counter {
private static int count = 0;
public static synchronized int getCount() {
count++;
return count;
}
}
XML文件代码:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<welcome-file-list>
<welcome-file>/BasicCounter.jsp</welcome-file>
</welcome-file-list>
</web-app>
实验结果:
使用page指令导入包
我们发现写foo有点麻烦。所以,使用page指令导入包。将JSP文件代码更改为:
<%@ page import="foo.*" %>
<!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">
</head>
<body>
The page count is:
<%
out.println(Counter.getCount());
%>
</body>
</html>
实验结果:
指令有3种:
- page
- include
- taglib
page允许你导入包。导入多个包<%@ page import="foo.*,java.util.*" %>
记住:<%@ page import = ? %>中的page是指令,import是page的属性,?是属性的值。
表达式
我们在JSP代码里面使用了out.println()
,我们应该尽量的避免这样的做法。所以可以更改JSP代码:
<%@ page import="foo.*" %>
<!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">
</head>
<body>
The page count is:
<%= Counter.getCount() %>
</body>
</html>
实验结果:
我们已经看到3种不同类型的JSP元素:
- Scriptlet:
<% %>
- 指令:
<%@ %>
- 表达式:
<%= %>
容器看到<%= Counter.getCount()%>就会把它转换为out.print(Counter.getCount());。
如果看到的是<%= Counter.getCount();%>
,注意最后一个分号,容器会转换成out.print(Counter.getCount(););
这种样子,明显会报错。
要记住:不要在表达式的最后加分号(还有要注意的地方就是,表达式不能输出一个void的类型,想想如果调用一个返回值为void的方法,就会报错)。
一个炸弹
修改JSP文件代码如下:
<%@ page import="foo.*" %>
<!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">
</head>
<body>
//定义一个变量是count,JSP是一个servlet
<% int count = 0; %>
The page count is:
//count+1
<%= ++count %>
</body>
</html>
我们认为JSP是一个servlet,用scriptlet声明一个变量,然后去使用它。结果刚刚开始的时候还不错,如下:
第二次访问:
发现怎么和结果1等同呢?
于是我们查看jsp最后会变成一个什么样的servlet代码。如下:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/9.0.4
* Generated at: 2018-08-02 12:04:37 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
//与servlet的差别
import javax.servlet.jsp.*;
//导入的包
import foo.*;
//继承也不一样
public final class BasicCounter_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("foo");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
//初始化
public void _jspInit() {
}
//销毁
public void _jspDestroy() {
}
//service方法
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
//下面是隐式对象
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
//我们写的代码,定义一个变量
int count = 0;
out.write("\r\n");
out.write("The page count is:\r\n");
//我们写的代码,然count+1
out.print( ++count );
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
由上面代码的注释就知道了,原来我们定义的count是局部变量。因此我们知道了我们的原因。
另一个JSP元素
我们想要声明一个全局变量。
将JSP代码修改为(<%! %>
设置全局变量):
<%@ page import="foo.*" %>
<!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">
</head>
<body>
//设置全局变量
<%! int count = 0; %>
The page count is:
<%= ++count %>
</body>
</html>
我们在看看JSP.java文件的代码:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/9.0.4
* Generated at: 2018-08-02 12:20:55 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import foo.*;
public final class BasicCounter_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
//count变成了全局变量
int count = 0;
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("foo");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("\r\n");
out.write("The page count is:\r\n");
out.print( ++count );
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
正如上面代码所看见的,count变成了全局变量。实验效果很好,会一直累计访问次数。
方法声明
修改JSP文件代码:
<%@ page import="foo.*" %>
<!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">
</head>
<body>
//JSP中定义方法
<%! int doubleCount(){
count = count*2;
return count;
} %>
<%! int count = 0; %>
The page count is:
<%= ++count %>
</body>
</html>
JSP.java文件在int count的上方增加了下面这样的一段代码:
//方法定义
int doubleCount(){
count = count*2;
return count;
}
//全局变量
int count = 0;
于是乎,我们好像知道了JSP就是一个servlet。
容器如何处理JSP
- 查看指令,得到转换时可能需要的信息。(比如导包)
- 创建一个HttpServlet子类,所生成的servlet会拓展:org.apache.jasper.runtime.HttpJspBase
- 如果有声明,容器会将这些声明写到类文件中,通常放在类声明下面,并在服务方法前面。(正如我们所看到的Tomcat声明了好多静态变量和好多方法)
- 建立服务方法。服务方法的具体方法名是_jspService()。这个方法由servlet超类被覆盖的service()方法调用,要接收HttpServletRequest和HttpServletResponse参数在建立这个方法时,容器会声明并初始化所有隐式对象
- 将普通的HTML(称为模板文本)、scriptlet和表达式放到服务方法中,完成格式化,并写至PrintWriter响应输出。
隐式对象
API | 隐式对象 |
---|---|
JspWriter | out |
HttpServletRequest | request |
HttpServletResponse | response |
HttpSession | session |
ServletContext | application |
ServletConfig | config |
Throwable | exception |
PageContext | pageContext |
Object | page |
我们这里说说第4个作用域:pageContext(页面级作用域)。
其中PageContext封装了其他隐式对象,所以如果向某些辅助对象提供一个PageContext引用,这些辅助对象就可以使用这个PageContext引用得到其他隐式对象的引用以及所有作用域的属性。
再说说exception,只有指定“错误页面”才能用到这个隐式对象。
练习
开发环境:
hobby.html代码:
<%@ page import="java.util.*" %>
<html>
<body>
The friends who share your hobby of
<%= request.getParameter("hobby") %>
are:<br>
<% ArrayList al = (ArrayList)request.getAttribute("names");%>
<% Iterator it = al.iterator(); %>
<% while(it.hasNext()){ %>
<%= it.next() %>
<br>
<% } %>
</body>
</html>
Hobby.java这个servlet代码:
package foo;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Hobby extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void doPost(HttpServletRequest request
, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("html/text");
ArrayList<String> al = new ArrayList<String>();
al.add("Fred");
al.add("Pradeep");
al.add("Philippe");
request.setAttribute("names", al);
request.getRequestDispatcher("/BasicCounter.jsp").forward(request, response);
}
}
BasicCounter.jsp代码:
<%@ page import="java.util.*" %>
<html>
<body>
The friends who share your hobby of
<%= request.getParameter("hobby") %>
are:<br>
<% ArrayList al = (ArrayList)request.getAttribute("names");%>
<% Iterator it = al.iterator(); %>
<% while(it.hasNext()){ %>
<%= it.next() %>
<br>
<% } %>
</body>
</html>
XML代码:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<servlet>
<servlet-name>hobby</servlet-name>
<servlet-class>foo.Hobby</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hobby</servlet-name>
<url-pattern>/HobbyPage.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/hobby.html</welcome-file>
</welcome-file-list>
</web-app>
实验结果:
点击提交后:
所生成servlet的API
JSP的UML图:
3个关键方法:
- jspInit(),这个方法由init()方法调用。可以覆盖这个方法。
- jspDestroy(),这个方法由servlet的destroy()方法调用。可以覆盖这个方法。
- _jspService(),这个方法由servlet的service()方法调用,这说明,对于每个请求,它会在一个单独的线程中运行。容器将Request和Response对象传递给这个方法。不能覆盖这个方法。
JSP生命周期
- 部署.jsp文件,此时不做任何事情
- 客户请求.jsp文件,将.jsp文件转换成一个servlet.java文件
- 容器尝试这把这个.java文件被编译为.class文件
- 容器加载servlet类
- 容器实例化servlet并调用jspInit()方法
- 容器创建一个新线程来处理这个请求,通过调用_jspService()方法
- 调用jspDestroy()方法销毁servlet实例
这里指出:Web应用包含JSP,部署这个应用时,在JSP生命周期中,整个转换和编译步骤只发生一次。
初始化JSP
我们想着既然JSP也是servlet,那么我们能不能能不能像初始化Servlet一样初始化JSP呢?该怎么做呢?
开发环境:
配置servlet初始化参数(DD)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<servlet>
<servlet-name>MyTestInit</servlet-name>
<jsp-file>/TestInit.jsp</jsp-file>
<init-param>
<param-name>email</param-name>
<param-value>ikickedbutt@wickedlysmart.com</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyTestInit</servlet-name>
<!-- 注意这里的url名字,映射而已 -->
<url-pattern>/TestInit.do</url-pattern>
</servlet-mapping>
</web-app>
覆盖jspInit()
<html>
<body>
<%!
public void jspInit(){
ServletConfig sConfig = getServletConfig();
String emailAddr = sConfig.getInitParameter("email");
ServletContext ctx = getServletContext();
ctx.setAttribute("mail", emailAddr);
}
%>
<%= config.getInitParameter("email") %>
<%= application.getAttribute("mail") %>
</body>
</html>
实验结果如下:
JSP中的属性
- | servlet中 | JSP中(隐式对象) |
---|---|---|
应用 | getServletContext() | application |
请求 | request | request |
会话 | request.getSession() | session |
页面 | 不适用 | pageContext |
通常我们不需要关系页面作用域,除非我们在开发定制标记。
PageContext的UML图:
使用pageContext的实例
设置一个页面作用域属性
<%
Float one = new Float(42,5);
pageContext.setAttribute("foo",one);
%>
获取一个页面作用域属性
<%= pageContext.getAttribute("foo")%>
使用pageContext设置一个会话作用域属性
<%
Float two = new Float(22.4);
pageContext.setAttribute("foo",two,PageContext.SESSION_SCOPE);
%>
使用pageContext获得一个会话作用域属性(等价于session.getAttribute(“foo”))
<%= pageContext.getAttribute("foo",PageContext.SESSION_SCOPE)%>
使用pageContext获得一个应用作用域属性(等价于application.getAttribute(“mail”))
<%= pageContext.getAttribute("mail",PageContext.APPLICATION_SCOPE)%>
使用pageContext,即使不知道作用域也可以查找一个属性(查找顺序:先从请求作用域查找,再查找会话作用域,最后查找应用作用域。先找到哪一个就算“赢”)
<%= pageContext.findAttribute("foo")%>
JSP的3个指令
指令 | 格式 | 说明 |
---|---|---|
page指令 | <%@ page import=”foo.*” session=”false”%> | 定义页面特定的属性,如字符编码、页面响应的内容类型,已经这个页面是否要有隐式对象。page指令可以使用至多13个不同属性(如import属性) |
taglib指令 | <%@ taglib tagdir=”/WEB-INF/tags/cool” prefix=”cool”%> | 定义JSP可以使用标记库 |
include指令 | <%@ include file=”wickedHeader.html”%> | 定义在转换时增加到当前页面的文本和代码。从而允许你建立可重用的块,这些可重用的块能增加到各个页面上,而不必在每个JSP中重复写所有这些代码 |
page指令的属性
属性 | 说明 |
---|---|
import | 导包 |
isThreadSafe | 定义生成的servlet是否需要实现SingleThreadModel(最好不要这样做) |
contentType | 定义JSP响应的MIME内容 |
isELIgnored | 定义转换(.jsp到.java)这个页面时是否忽略EL表达式 |
errorPage | 定义一个资源的URL,如果有未捕获到的Throwable,就会发送到这个资源。如果这个属性指定了一个JSP,该JSP的page指令中就会有isErrorPage=”true”属性 |
language | 定义scriptlet、表达式和声明中使用的脚本语言(现在就只有一个值,就是”java”) |
extends | JSP会变成一个servlet类,这个属性则定义了这个类的超类(一般不会使用这个属性) |
session | 定义页面是否有一个隐式的session对象。默认值为”true” |
buffer | 定义隐式out对象如何处理缓存 |
autoFlush | 定义缓存的输出是否自动刷新输出。默认值为”true” |
info | 定义放到转换后页面中的串,这样就能使用所生成servlet继承的getServletInfo()方法来得到这个信息 |
pageEncoding | 定义JSP的字符编码。默认为”ISO-8859-1” |
EL
HTML开发员不懂Java,所以不能再JSP里面写这种Java代码。
于是,EL出现了,它的出现完美的解决下面2个问题:
- 不应该要求Web页面设计人员必须懂Java
- JSP中的Java代码很难修改和维护
EL小试牛刀
EL表达式:${applicationScope.mail}
等价于<%= application.getAttribute("mail")%>
禁用scriptlet
在DD中配置:
<web-app ...>
<jsp-config>
<jsp-property-group>
//作用于所有的.jsp文件
<url-pattern>*.jsp</url-pattern>
//只要配置上这个就行了,记住true是禁用scriptlet
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
</web-app>
禁用EL表达式
两种方式:
(1)在DD中配置:
<web-app ...>
<jsp-config>
<jsp-property-group>
//作用于所有的.jsp文件
<url-pattern>*.jsp</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>
</web-app>
(2)在JSP中用page指令(注意前面还有一个is):
<%@ page isELIgnored="true"%>
初见JSP的“动作”
标准动作:<jsp:include page="wickedFooter.jsp">
其他动作:<c:set var="rate" value="32">
看看动作的语法,把它与其他类型JSP元素的语法做个比较。我们回答下面问题:
(1)动作元素与scriptlet有什么区别?
本质上没有区别,只是代码形式改变了。
(2)看到一个动作时,怎么才能认出来?
不知道= =