Head First JSP---随笔五
作为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.Counterout.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.HttpJspBaseimplements 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+1out.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.HttpJspBaseimplements 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;@Overrideprotected 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)看到一个动作时,怎么才能认出来?
不知道= =
本章完
Head First JSP---随笔五相关推荐
- JSP(五):属性范围
定义:设置一个属性后,可以经过多少个其他页面后仍然可以保存的范围. 所有存在JSP里面的属性都有四种范围:page.request.session.pageContext 转载于:https://ww ...
- 随笔 | 五楼西区17架b面1列3层
昨晚跟某人聊起图书馆,一下子勾起了好多回忆. 悠悠北洋,书海无疆,理一理身旁旧事,别往我来时模样.每天晚上闭馆音乐响起的时候,都会自己碎碎念一句,男生版本的似乎更好听一点hhh,然后收拾好自己的书包下 ...
- jsp随笔-工作使用-直播功能
1.状态功能 <div class="form-group"> <label for="" class="col-md-3 cont ...
- 3D数学基础:图形与游戏开发---随笔五
向量运算 5.1 线性代数与几何 数学中专门研究向量的分支称作线性代数. 5.2 符号约定 变量是代表未知量的占位符.本书用不同的字体来区分不同的变量: 标量,用斜体的小谢罗马或者希腊字母表示,如a. ...
- 阅读javascript高级程序设计随笔(五)
2.5 操作符 操作符包括算术操作符.位操作符.关系操作符合相等操作符.ECMAScript操作符与众不同的是,它们能够适用很多值,例如字符串.数字值.布尔值甚至对象.在应用于对象时,相应的操作符通常 ...
- 实验三 JSP应用开发进阶
全部:https://download.csdn.net/download/weixin_42859280/11218260 实验三 JSP应用开发进阶:PDF版本[已经完成所有代码] 想看文档上面有 ...
- JSP基本语法、3个编译指令、7个动作指令、9个内置对象
一.jsp概述 JSP是java server page的缩写,其本质是一个简化的servlet,是一种动态网页技术标准.jsp页面是在HTML页面中嵌入java程序段,使用jsp开发的应用程序可以跨 ...
- Spring+SpringMvc+Hibernate(SSH)+bootstrap/Jsp整合
文章目录 前言: 准备工作: 最终项目的目录结构: 源码 一.使用idea创建web app项目 二.导包 三.SpringMVC配置 第一步:配置spring-mvc.xml 第二步:配置 web. ...
- java基础学习之JSP动态web开发技术
一 JSP是什么? jsp 页面允许在标准的HTML 页面中包含Java代码 目标:是支持表现和业务逻辑的分离. 表现:由前端人员实现. 业务逻辑: 有后台程序员处理 二JSP页面的运行原理 第一步 ...
- jsp页面跳转的几种方式
一, 使用href超链接标记 (客户端跳转) 二, 提交表单 (客户端跳转) <form name="form" method="post" action ...
最新文章
- windows远程ssh与scp操作linux
- shell中的条件语句
- jq的ajax和模块引擎
- 基于Java的RDMA高性能通信库(六):SDP - Java Socket Direct Protocol
- Springboot+Docker+RabbitMQ教程来了。
- abap--REUSE_ALV_GRID_DISPLAY事件子过程和cl_gui_grid类的事件对应关系
- mysql索引失效_MySQL索引失效的底层原理
- 文档 笔记 我全都要
- Workaround for Search for my account in MyAppointment
- 实习生解雇_我们解雇了我们的顶尖人才。 我们做出的最佳决定。
- 2021年看得见的粉丝价值——五大平台KOL粉丝分析研究报告
- WCF服务编程 学习笔记(1)
- js实现一键复制到剪切板上_js实现各种复制到剪贴板的方法(分享)
- 编译原理实验-用FLEX自动构造词法分析程序
- ZPL指令打印标签时出现白色窄条的坑
- 大数据平台架构包含哪些功能
- 医疗管理系统软件 linux系统,MyPatients 4.0.2 发布,医疗信息管理系统
- Cannot run program jad
- synchronized同步机制——如果你愿意一层一层剥开我的心
- WPF 中Combox的使用
热门文章
- NYOJ 301 递推求值(矩阵快速幂)
- Android开发 - 设置DialogFragment全屏显示
- C# Linq to SQL — Group by
- sql server 提示无法彻底删除_复制-而无法删除数据库或重新配置发布订阅
- Eclipse 3.7 3.x SWT/Jface 开发环境搭建
- 在asp.net中控制回车键
- 关于CheckBoxList和RadioButtonList的几个问题
- 软件如何控制硬件、编译器和操作系统是否需要编译
- SCons命令 之 从入门到精通
- jdbc获取结果行数_如何获取JDBC中的行数?