@cxm-2016
2016-12-26T10:06:19.000000Z
字数 7903
阅读 3206
Web
版本:2
作者:陈小默
声明:禁止商业,禁止转载
JSP全名为Java Server Pages,其根本是一个简化的Servlet设计。也就是说,看起来像是一个HTML网页的JSP在Tomcat中是以Servlet对象的形式存在的。JSP与Servlet一样,是在服务器端执行的。通常JSP页面很少进行数据处理,只是用来实现网页的静态化页面,只是用来提取数据,不会进行业务处理。
一个JSP会在第一次被访问时翻译成一个Servlet对象,此后所有的响应都由这个对象输出。
每个JSP页面在第一次被访问时,WEB容器都会把请求交给JSP引擎去处理。JSP引擎先将JSP翻译成Servlet,然后以Servlet的调用方式调用。以后再访问时不再翻译而是直接使用当前Servlet对象。
JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供其使用。
用于向客户端发送文本数据。
out对象通过调用pageContext对象的getOut方法返回,其作用和用法与ServletResponse.getWriter对象相似。
out对象的类型为JSPWriter,是一个实现了缓存功能的PrintWriter对象。可以通过设置page指令的buffer属性设置缓冲区的大小,也可以关闭缓冲区。
当满足以下任意一个条件后,out对象会去调用ServletResponse的getWriter方法,并将当前out缓冲区的内容写到Servlet的缓冲区中。
当前页面的上下文对象。
该对象代表了JSP页面的运行环境。其中封装了其他八个隐式对象的引用,并且其自身还是一个域对象。并且,这个对象还封装了web开发中经常使用的一些操作,例如跳转等。
我们可以通过pageContext对象获取其他对象的引用。
<%Object page1 = pageContext.getPage();ServletRequest request1 = pageContext.getRequest();ServletResponse response1 = pageContext.getResponse();HttpSession session1 = pageContext.getSession();ServletConfig config1 = pageContext.getServletConfig();JspWriter out1 = pageContext.getOut();ServletContext application1 = pageContext.getServletContext();Exception exception = pageContext.getException();%>
<%//保存到PageContext域pageContext.setAttribute("key", 1);//保存到Application域pageContext.setAttribute("key", 2, PageContext.APPLICATION_SCOPE);//保存到Session域pageContext.setAttribute("key", 3, PageContext.SESSION_SCOPE);//保存到Request域pageContext.setAttribute("key", 4, PageContext.REQUEST_SCOPE);%>
JSP页面中的HTML内容都可以被称之为模板元素。
接下来我们在webapp目录下创建一个JSP index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>index</title></head><body>Welcome to Smart JSP !!!</body></html>
由于webapp的可访问性,其中所有的文件,除WEB-INF目录外,都可以被浏览器通过地址直接访问。而文件名为index的文件又具有默认访问的特性。所以我们既可以通过
http://127.0.0.1:8080/smart/index.jsp
形式访问,也可以省略index.jsp,直接通过
http://127.0.0.1:8080/smart
访问。
<%=System.currentTimeMillis() %>
JSP引擎在翻译表达式时会使用out.print输出表达式中的内容。
JSP脚本也叫作JSP脚本片段
<%for (int i = 0; i < 10; i++) {out.print(i);out.print("<br>");}%>
JSP脚本允许不完整的脚本片段,但是多个片段组合后的脚本片段必须是完整的,比如上面的示例还可以改成这个样子:
<%for (int i = 0; i < 10; i++) {out.print(i);%><br><%}%>
JSP脚本片段会被原封不动的放在生成的Servlet代码中。
JSP页面中编写的代码会被翻译到Servlet的service中,而JSP声明中的java代码会被翻译到_jspService方法的外面。
通常JSP声明被用于
<%!private int base = 10;%><%for (int i = 0; i < 10; i++) {out.println(base++);}%>
<%!{System.out.println("init");}%>
<%!private String getCurrent() {SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");return format.format(new Date());}%><%=getCurrent() %>
<%!private class DateUtil {String getCurrent() {SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");return format.format(new Date());}}%><%DateUtil util = new DateUtil();out.print(util.getCurrent());%>
在JSP中注释有三种方式,第一种为JSP注释,该注释不会被保存到Servlet中。
<%-- JSP注释 --%>
第二种是Java注释,这种注释只能在JSP脚本中使用,并且会被写入到Servlet中。
<%// 单行注释/*多行注释*//*** 文档注释*/%>
第三种是HTML注释,该注释会被当做模板元素输出。
<!-- HTML -->
对于HTML注释,有一点需要注意:
<% int i = 0; %><!--<% i+=10; %> --><%=i %>
上述网页会输出数字10。
这是因为在JSP翻译为Servlet时,对于模板元素采取的是直接输出:
int i = 0;out.print("<!--");i+=10;out.print("-->");out.print(i)
JSP指令用于指挥JSP引擎如何处理JSP页面。其中包含三个主要部分
page、include、taglib
用于定义JSP页面中各种属性,无论指令在何处,都作用域整个JSP页面。
常用属性有:
java.lang.*包和javax.servlet.*)text/html;charset=utf-8language
<%@ pagelanguage="java"%>
目前仅支持Java语言。
import
<%@ pagelanguage="java"import="java.util.Date,java.util.ArrayList"%>
session
<%@ pagelanguage="java"import="java.util.Date,java.util.ArrayList"session="false"%>
当我们将session设置为false之后,我们就无法在JSP脚本中使用session隐式对象了。
我们可以通过errorPage标签指定当前页面发生后跳转到的页面。
首先创建一个JSP页面用来显示错误:
<%@ pagecontentType="text/html;charset=UTF-8"language="java"isErrorPage="true"%><html><head><title>错误页面</title></head><body>发生了一个错误,错误原因是:<%=exception.getMessage()%></body></html>
然后在需要的JSP页面中指定错误页面。
<%@ pagelanguage="java"errorPage="ErrorPage.jsp"%><html><head><title>Hello</title></head><body><%throw new RuntimeException("用户未登录");%></body></html>
最后也是最重要的就是在web.xml文件中指定错误类型与访问路径的关系。
我们可以使用相应代码:
<error-page><error-code>500</error-code><location>/ErrorPage.jsp</location></error-page>
或者使用错误类型:
<error-page><exception-type>java.lang.RuntimeException</exception-type><location>/ErrorPage.jsp</location></error-page>
通知JSP将两个JSP文件翻译成一个Servlet
比如:
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Hello</title></head><body>---------a----------<%@include file="index.jsp" %>---------b----------</body></html>
我们可以从浏览器看到翻译过后的Servlet的输出内容是:
<html><head><title>Hello</title></head><body>---------a----------<html><head><title>index</title></head><body>Welcome to Smart JSP !!!</body></html>---------b----------</body></html>
include指令属于静态引入,也就是源文件级别的合并,并最终生成一个Servlet。
需要注意的是:
.jspf作为静态引入文件的扩展名。用于在JSP页面中导入标签库
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
我们将
<servlet><servlet-name>helloJsp</servlet-name><jsp-file>/WEB-INF/view/HelloJsp.jsp</jsp-file></servlet><servlet-mapping><servlet-name>helloJsp</servlet-name><url-pattern>/view/hello</url-pattern></servlet-mapping>
JSP最终是以Servlet的方式运行的。那么一个JSP最终转换成的Servlet结构是什么样子的?
首先我们创建一个最简单的JSP页面:
<%@ page import="java.text.SimpleDateFormat" %><%@ page import="java.util.Date" %><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Hello</title></head><body><%!private String getDate() {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");return format.format(new Date());}%><%-- 注释1 --%><%=getDate()%><%//注释2for (int i = 0; i < 10; i++) {out.print(i);%><br><!--<%}%>--></body></html>
那么生成的Servlet页面源码如下(已精简)
package org.apache.jsp;...import java.text.SimpleDateFormat;import java.util.Date;public final class HelloJsp_jsp extends org.apache.jasper.runtime.HttpJspBaseimplements org.apache.jasper.runtime.JspSourceDependent,org.apache.jasper.runtime.JspSourceImports {/*** 使用JSP声明定义的方法*/private String getDate() {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");return format.format(new Date());}.../*** JSP生命周期的初始化方法,在第一次被访问时调用*/public void _jspInit() {}/*** JSP生命周期的销毁,在JSP被移除出容器时调用*/public void _jspDestroy() {}/*** 模板元素在这里被输出,JSP脚本在这里被运行*/public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)throws java.io.IOException, javax.servlet.ServletException {...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;charset=UTF-8");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("\n");out.write("\n");out.write("\n");out.write("<html>\n");out.write("<head>\n");out.write(" <title>Hello</title>\n");out.write("</head>\n");out.write("<body>\n");out.write('\n');out.write('\n');out.print(getDate());out.write('\n');//注释2for (int i = 0; i < 10; i++) {out.print(i);out.write("\n");out.write("<br>\n");out.write("<!--");}out.write("-->\n");out.write("</body>\n");out.write("</html>\n");} catch (java.lang.Throwable t) {...} finally {...}}}