接着上篇文章,我们上篇文章讲到了jsp的基本原理以及和servlet的关系,还介绍了jsp的基本语法部分,本篇文章就继续介绍余下的内容。

  • 编译指令Page和include
  • 基本的动作指令
  • 内置对象

一、两个编译指令

     Page指令顾名思义,操作当前页面的。首先我们要知道使用编译指令的格式:<%@ page 属性名="属性值"%>,关于page的属性有哪些,如下图所示:

     简单说明一下,language指定的是本页面使用的脚本语言,contentType指定了本页面的类型,有text/html,img/png等。import可以引入指定的包,默认情况下已经为我们引入了java.lang.,javax.servlet.jsp.,javax.servlet.http.*。所有在jsp页面引入的包,都会对应到servlet实例中。session指定当前页面是否支持会话(后面详细介绍),errorPage指定了当前页面如果出现异常调用的页面,如果没有为当前页面指定errorPage页面,就会直接抛出异常信息个浏览器(这是我们所不愿意看到的),isErrorPage指定了当前页面是否是错误页面,如果是,当别的页面出错的时候就会跳转到此页面,默认为false。这么多的属性,我们只要稍微有点印象,实际用的时候再过来参考即可。

     我们说jsp页面中是不需要处理任何异常的,甚至是检查类异常都是不需要处理的。我们来看看为什么。从servlet类的源代码中找原因,因为这是本质。

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;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("<html>\n");
out.write(" <head>\n");
out.write(" <title></title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write("\t\t");
for(int a=0;a<10;a++){
out.write("\n");
out.write("\t\t\t<p>Walker</p>\n");
out.write("\t\t");
}
out.write("\n");
out.write(" </body>\n");
out.write("</html>\n");
} 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);
}
}

     我们就看看这个用来响应用户请求的方法,_jspservice(),不知道大家看到没有,整个输出html页面信息的代码块都被try....catch了,而看到catch捕捉的异常时异常机制的源头Throwable ,所有的异常都是继承自它的。而我们看到捕捉到异常之后所进行的操作是,如果当前对象不为空,就调用该对象的处理方法,处理方法就是判断当前页面是否制定的errorPage页面,如果没有抛异常给浏览器,如果有,跳向错误页面。所以无论你jsp页面会抛出什么异常,在被编译到servlet实例中,已经做了处理了,这就是为什么jsp页面不需要处理异常的原因。

第二个指令是include指令,这是一个用来包含指定页面的内容的编译指令,<%@include file="文件路径"%>,我们来看一个例子:

<html>
<head>
<title></title>
</head>
<body>
<h1>这是当前页面</h1>
<%@include file="convert.jsp"%>
</body>
</html> <html>
<head>
<title></title>
</head>
<body>
<h1>这是引入页面</h1>
</body>
</html>

运行结果的图片就不贴了,从servlet实例中可以明显看出,这一切都做了什么。

out.write("\n");
out.write("\n");
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title></title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write("\t\t<h1>这是当前页面</h1>\n");
out.write("\t\t");
out.write("\n");
out.write("\n"); out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title></title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write("\t<h1>这是引入页面</h1>\n");
out.write(" </body>\n");
out.write("</html>\n"); out.write("\n");
out.write(" </body>\n");
out.write("</html>\n");

     不知道大家看出来了没有,一个页面里竟然包含了两个html标签和title和body标签,可见,这个编译指令就是在编译的时候将要引入的页面中的全部信息直接插入在指定位置上。

二、基本的工作指令

     第一个动作指令是,forward指令,这个指令用来向另外的一个页面进行跳转。用法如下:

<html>
<head>
<title>index.jsp</title>
</head>
<body>
<h1>这是当前页面</h1> <jsp:forward page="convert.jsp">
/*这是传入参数,暂时可以不用关心*/
<jsp:param name="key" value="v" />
</jsp:forward> </body>
</html> <html>
<head>
<title>convert.jsp</title>
</head>
<body>
<h1>这是引入页面</h1>
</body>
</html>

     从运行结果上看,至少可以看出两点。第一,地址栏上的地址依然是index页面,也就是说页面并没有跳走,第二,我们看原来index页面的所有信息都被替换成convert页面的内容。由此我们可以推断出,所谓的跳转指令,其实并没有完成跳转的操作,只是将目标页面的所有信息全部替换当前页面,这和我们之前说过的一个编译指令很是类似,他是include,我们应该可以记得,include编译指令是将目标页面中所有内容替换到当前页面的某个位置,也就是替换了当前页面中的部分内容。而可以将跳转指令forward理解为替换了当前页面的所有内容。

	  out.write("\n");
out.write("\n");
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title>1</title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write("\t\t<h1>这是当前页面</h1>\n");
out.write("\t\t");
if (true) {
_jspx_page_context.forward("convert.jsp" + "?" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("key", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("v", request.getCharacterEncoding()));
return;
}
out.write("\n");
out.write(" </body>\n");
out.write("</html>\n");

     从servlet源代码中,我们可以看到,index中前面的代码正常加载,当加载到我们的跳转指令的时候,它实际上构建以个URL:convert.jsp?key=v,默默的请求了此页面然后将返回的结果显示在当前的页面中,其实就是去拿来目标页面中的内容覆盖当前页面,对于index页面的一些请求参数,不会丢失。(关于请求参数的接收,下文介绍)

     第二个动作指令,include指令,用来动态引入外部文件到当前页面,和我们的include编译指令相似,但是也有着显著的区别。先看怎么使用:

<html>
<head>
<title>1</title>
</head>
<body>
<h1>这是当前页面</h1> <jsp:include page="convert.jsp">
<jsp:param name="a" value="c" />
</jsp:include>
</body>
</html> <html>
<head>
<title>2</title>
</head>
<body>
<h1>这是引入页面</h1> </body>
</html>
out.write("\n");
out.write("\n");
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title>1</title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write("\t\t<h1>这是当前页面</h1>\n");
out.write("\t\t\n");
out.write("\t\t");
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "convert.jsp" + "?" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("a", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("c", request.getCharacterEncoding()), out, false);
out.write("\n");
out.write(" </body>\n");
out.write("</html>\n");

     我们可以看到,动作指令include实际上不想编译指令include将目标页面的所有信息全部插入到指定位置,动态include指令调用的是一个include方法,动态的将目标页面的body部分的内容拿过来,并且还允许传入参数。可能结果和编译指令include一样,但是内部的实现确是截然不同的,各自有各自的适用场所。

     第三个动作指令,param,这是我们之前一直在使用的指令,只是一直没有说明。param指令一般都不会单独使用,通常都是结合jsp:include,jsp:forward等使用。使用的格式如下:

<jsp:include page="convert.jsp">
<jsp:param name="a" value="c" />
</jsp:include>

     name指定参数名,value指定参数数值。至于怎么获取,我们在介绍request对象的时候加以说明。request对象就是一个专门用于处理用户请求的对象,所以所有的参数传递都是可以使用这个对象进行接收的。还有一些动作指令牵扯到javabean知识,暂时不说。

三、JSP内置对象

     我们打开任意的servlet源代码,可以看到在用于响应用户请求的方法_jspservice();的头部有一些成员变量的定义和初始化。看:

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response){
.....
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;
.......
}

     接下来我们会详细介绍这些对象的含义及其具体的操作。由于篇幅限制,未完待续。。

Java EE基础之JSP(二)的更多相关文章

  1. Java EE基础之JSP

    从本篇文章开始,我会用文章记录下我在学习Java EE过程中的一些笔记和感悟,至于还没有更新结束的Java SE还是会继续写的,只是我觉得一直写语法很枯燥,自己也没法继续下去,所以带着点web学习,会 ...

  2. Java EE基础之JSP(三)

         原来准备简单点,用一篇文章介绍完JSP的,没想到细节很多.这是第三篇也是最后一篇,这三篇文章介绍了基本的JSP知识,很多名词概念和用法,一定要在实践项目中使用之后才会有更加亲切的体会.第三篇 ...

  3. Java编程基础——数组和二维数组

    Java编程基础——数组和二维数组 摘要:本文主要对数组和二维数组进行简要介绍. 数组 定义 数组可以理解成保存一组数的容器,而变量可以理解为保存一个数的容器. 数组是一种引用类型,用于保存一组相同类 ...

  4. Java 多线程基础(十二)生产者与消费者

    Java 多线程基础(十二)生产者与消费者 一.生产者与消费者模型 生产者与消费者问题是个非常典型的多线程问题,涉及到的对象包括“生产者”.“消费者”.“仓库”和“产品”.他们之间的关系如下: ①.生 ...

  5. Java Web基础:JSP基础概念

    JSP介绍 JSP全称是Java Server Pages,它和Servlet都是Sun公司定义的用于开发动态Web资源的技术,它解决了Servlet输出流排版复杂和难以维护的问题.JSP完美融合了H ...

  6. Eclipse Java EE IDE中jsp页面编码修改

    Eclipse Java EE IDE模板编码是ISO8859,肯定不是我们需要的,修改方法如下图: 依次点击:Window---->Preference---->Web---->J ...

  7. Java多线程基础知识(二)

    一. Java线程具有6种状态  NEW 初始状态,线程被创建,但是还没有调用start方法. RUNNABLE 运行状态,java线程将操作系统中的就绪和运行两种状态笼统的称作进行中. BLOCKE ...

  8. Java零基础教程(二)基础语法

    Java 基础语法 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.下面简要介绍下类.对象.方法和实例变量的概念. 对象:对象是类的一个实例,有状态和行为.例如 ...

  9. Java多线程基础学习(二)

    9. 线程安全/共享变量——同步 当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次.这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”. ...

随机推荐

  1. nodejs笔记2 --关于nodejs最新启动方式

    1,运行应用以前是node app.js或者 supervisor app.js 2, 现在的应用方式是npm start或者supervisor bin/www

  2. ionic-cordova 支付宝支付插件cordova-plugin-alipay-v2使用篇

    支付宝WS_APP_PAY_SDK_BASE_2.0 <APP支付> 支付宝的cordova插件其实在github上已经有很多了,但是都已经是以前的版本了.在2016年11月的时候支付宝进 ...

  3. JavaScript中国象棋程序(4) - 极大极小搜索算法

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第4节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  4. css居中问题

    学习过程中遇到css居中问题 , 也查阅了资料,每个人的方法都不尽相同,而且当时看懂了,过后就记混淆了;so作为一个前端小白,也来写一下俗话说好脑子不如烂笔头,毕竟自己知道的也不多,其实是抱着学习和交 ...

  5. 项目中通过Sorlj获取索引库中的数据

    在开发项目中通过使用Solr所提供的Solrj(java客户端)获取索引库中的数据,这才是真正对项目起实质性作用的功能,提升平台的检索性能及检索结果的精确性 第一步,引入相关依赖的jar包 第二步,根 ...

  6. 使用Bootstrap + Vue.js实现 添加删除数据

    界面首先需要引入bootstrap的css和bootstrap的js文件,还有vue.js和jQuery.js才可以看见效果. 这里提供bootstrap的在线文件给大家引用: <!-- 最新版 ...

  7. Mac环境下.Net开发

    Mono是一个由Novell公司(由Xamarin发起),并由Miguel de lcaza领导的,一个致力于开创.NET在Linux上使用的开源工程.它包含了一个C#语言的编译器,一个CLR的运行时 ...

  8. 配置apache

    1. 修改httpd.conf文件 # vi  /usr/local/apache/conf/httpd.conf 1) 设置根目录的路径 根目录是指Apache存放配置文件和日志文件的目录,配置参数 ...

  9. JDK 安装过程

    1.首先是下载jdk:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 2.下载完 ...

  10. Linux的capability深入分析

    Linux的capability深入分析详见:http://blog.csdn.net/u014338577/article/details/48791953 lxd中对容器能力的限制: 普通用户不能 ...