Java --- JSP2新特性

     自从03年发布了jsp2.0之后,新增了一些额外的特性,这些特性使得动态网页设计变得更加容易。jsp2.0以后的版本统称jsp2。主要的新增特性有如下几个:

  • 直接配置jsp属性
  • 表达式语言(EL)
  • 标签文件(Tag File)

一、直接配置jsp属性      原先我们对于jsp页面的一些属性的配置需要使用编译指令page在页面的头部指定,这就会导致在多个jsp页面中都做了同样的事情。jsp2为我们提供了一种方式,可以在web.xml中统一指定某个或者某些jsp页面的一些属性配置。主要的可配置的jsp属性有:

<el-ignored></el-ignored>   ---指定该jsp页面是否支持表达式语言

<page-encoding></page-encoding>     ---指定该jsp页面的编码方式

<scripting-invalid></scripting-invalid>    --指定该页面是否允许jsp脚本

<include-prelude></include-prelude>    --向指定的页面隐式的包含外部文件(引入的位置在指定页面的头部)

<include-coda></include-coda>       --向指定的页面隐式的包含外部文件(引入的位置在指定页面的底部)

在web.xml中我们使用元素jsp-config来直接配置jsp属性,每个jsp-config元素下,可以由多个jsp-property-group元素,它就是用来具体配置某个或者某些jsp属性的,具体看下面的演示:

    <jsp-config>
        <jsp-property-group>
            <url-pattern>/index.jsp</url-pattern>
            <el-ignored>false</el-ignored>
            <page-encoding>UTF-8</page-encoding>
            <scripting-invalid>false</scripting-invalid>
            <include-prelude>/top.jsp</include-prelude>
            <include-coda>/bottom.jsp</include-coda>
        </jsp-property-group>

        <jsp-property-group>
            <url-pattern>/index2.jsp</url-pattern>
            <el-ignored>true</el-ignored>
            <page-encoding>UTF-8</page-encoding>
            <scripting-invalid>true</scripting-invalid>
            <include-prelude>/top.jsp</include-prelude>
            <include-coda>/bottom.jsp</include-coda>
        </jsp-property-group>
    </jsp-config>

其中url-pattern元素用来指定哪些jsp页面将被应用以下配置,可以是单个jsp页面,也可以是一组jsp页面。el-ignored元素指定该页面是否支持表达式语言(接下来会说),默认是false表示支持EL。page-encoding元素指定了页面的编码方式,等效于jsp页面page编译指令中contentType属性中charset部分。scripting-invalid元素指定了页面是否支持jsp脚本,默认为false表示支持。include-prelude和include-coda元素我们分别隐式引用了外部文件,一个放在原页面的头部,另一个则是放在尾部。我们看看这两个页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" %>
<html>
  <head>
    <title>top.jsp</title>
  </head>
  <body>
      <p>这是头部的内容</p>
  </body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" %>
<html>
  <head>
    <title>bottom.jsp</title>
  </head>
  <body>
      <p>这是底部的内容</p>
  </body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" %>
<html>
  <head>
    <title>index.jsp</title>
  </head>
  <body>
      <p>这是index页面的内容</p>
      <p>这是index页面的内容</p>
      <p>这是index页面的内容</p>
      <p>这是index页面的内容</p>
      <p>这是index页面的内容</p>
  </body>
</html>

结果如下:

查看网页源码可以看到:

可以看到这两个元素的作用和我们jsp中的编译指令include十分相似,只是我们的include编译指令可以自己选择引入的外部文件放在被引入的jsp页面中的位置,而这两个元素则一个是引入到当前jsp页面头部,一个则是引入到当前jsp页面的底部。

二、表达式语言(EL)      表达式语言是一种简化了的数据访问方式,使用它我们可以用简单的语法来实现对数据的访问。在jsp2中,建议使用表达式语言使得jsp页面格式一致,而避免使用jsp脚本。EL的使用语法是:${expression}。在了解如何使用之前,我们先了解一下他的内置对象,这些对象也是我们使用EL的关键。

pageContext: 获取当前页面的context对象,如jspcontext,servletcontext

pageScope:用于获取page范围内的属性的值

requestScope:用于获取request范围内的属性的值

sessionScopt:用于获取session范围内的属性的值

applicationScope:用于获取application范围内的属性的值

param:用于获取请求参数的值

paramValues:用于获取请求参数的集合(数组形式)

initParam:用于获取请求web应用的初始化参数(web.xml中的)

cookie:用于获取指定的cookie

从EL的内置对象看,基本上前台需要的数据都是可以获取到的。下面演示如何使用EL获取数据。

<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" %>
<html>
  <head>
    <title>index</title>
  </head>
  <body>
      <%
          request.setAttribute("a","aaaaa");
          session.setAttribute("b","bbbbb");
      %>
      ${requestScope.a}    <!--或者${requestScope["a"]}-->
      ${sessionScope.b}
  </body>
</html>

以上的演示是EL的很简单的使用方法,也是利用了它的内置对象来完成对数据的访问获取。下面我们看看如何通过EL语法调用自定义函数,可以说扩充了调用自定义函数的功能使得EL更加灵活。但是允许EL调用的函数都必须是静态的(因为如果非静态的就需要创建对象来调用,违背了EL设计的初衷)。自定义函数主要有以下三个步骤:

  • 定义一个具有静态方法的类,并定义一些静态方法
  • 在标签库中配置可供调用的方法
  • 在jsp页面中使用自定义方法

第一步比较简单,就是定义一个具有静态方法的类,第二步有点像我们的自定义标签的过程,创建一个标签库,在taglib元素下,定义一个function子元素表示一个方法。

<?xml version="1.0" encoding="UTF-8"?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
    <description>A tag library exercising SimpleTag handlers.</description>
    <tlib-version>1.0</tlib-version>
    <short-name>SimpleTagLibrary</short-name>

    <uri>mytid</uri>
//定义了一个EL可调用的静态方法
    <function>
        <name>sayHello</name>  //指明方法名
        <function-class>Test_packge.SayHello</function-class>  //指明类名
        <function-signature>java.long.String sayHello(java.lang.String)</function-signature>  //指明方法的返回值,参数情况
    </function>
</taglib>
public class SayHello {

    public static String sayHello(String s){
        return "hello " + s;
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" %>
<%@ taglib prefix="fun" uri="mytid" %>
<html>
  <head>
    <title>index</title>
  </head>
  <body>
    <p>${fun:sayHello("walker")}</p>
  </body>
</html>

我们可以看到在EL中调用自定义方法和使用自定义标签的语法很是类似,之上我们演示了一个EL调用自定义方法的完整流程,并由此可以看出,基本上EL可以调用一切所需资源,可以调用Javabean中方法获取数据库中的数据,也可以自定义类实现具体方法供EL调用。功能很是强大。

三、标签文件(Tag File)      我们之前介绍过了自定标签的定义和使用,需要三个步骤。首先需要写一个标签处理类继承SimpleTag,然后实现doTag方法就就可以用来处理标签了,然后我们需要创建一个tld文件,在跟元素taglib中定义一个一个的tag元素,最后在jsp页面中使用。过程还是很麻烦的。jsp2.0之后,引入了标签文件,这是一个简化了的自定义标签的过程,实际上计算机内部还是将它转换成了我们自定义的三个步骤,在本节的结尾,我们会一起看看源码了解下编译器做了哪些操作。      在Tag File文件中有5个编译指令,他们是:

  • taglib:用于导入其他的标签库
  • include:用于导入静态页面
  • tag:类似jsp页面中的page编译指令,用于指定页面的基本属性
  • attribute:用于设定自定义标签的属性,值是从jsp页面传入的
  • variable:可以提供jsp页面调用的变量

下面定义了一个简单的Tag file:

//在WEB-INF/tags 文件下创建一个myTag.tag标签文件
<%@ tag pageEncoding="UTF-8" import="java.util.*"%>

<%@ attribute name="bgColor"%>
<%@ attribute name="cellColor"%>
<%@ attribute name="title"%>
<%@ attribute name="bean"%>
<%@ variable name-given="time" variable-class="java.lang.String" scope="AT_BEGIN" %>

<% jspContext.setAttribute("time","now");%>
<table>
    <tr><td>${title}</td></tr>
    <%
        List<String> list = (List<String>)request.getAttribute("a");
        for(Object ele : list){%>
    <tr>
        <td bgColor="${cellColor}"><%=ele%></td>
    </tr>
    <%}%>
</table>
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" %>
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>

<html>
  <head>
    <title>index</title>
  </head>
  <body>
      <%
          List<String> list = new ArrayList<String>();
          list.add("walker");
          list.add("yam");
          request.setAttribute("a",list);
      %>
      <tags:myTag bgColor="red" cellColor="blue" bean="a" title="测试" />
      <p><%=time%></p>

  </body>
</html>

我们需要始终知道的是,我们使用所有的标签,他们返回的结果都是页面片段,所以如果tag文件页面全是jsp语法就完全没有意义了。我们先从index页面看,前面引入标签库不用介绍了,只是这里需要知道我们引入的tagdir并不是这个标签文件(.tag),而是他的父目录。(这样做也是为了页面简洁,不用每个标签文件都引入一次),接着我们看,使用jsp脚本定义了一个list集合,并设置共享范围。

然后我们使用标签文件,和使用标签一样,这里的bgColor等属性是对应于我们myTag.tag文件中的attribute编译指令的,这样我们这边传入的属性的值就可以自动赋值到标签文件中了。

接下来我们看看标签文件,首先使用了tag 编译指令指定了页面片段的基本属性,如编码方式等。然后就是attribute 编译指令,用于接受jsp页面传入的属性值。至于这个variable变量的定义,我们先过(后面说)。紧接着是jsp脚本输出一个表格,不再赘述。我们看看结果:

     我们之前说过,标签文件是简化了的自定义标签,最终还是会被编译成Java类,和我们之前自定义标签时候写的标签处理类差不多。我们打开Tomcat/work....一直找到你的项目的tag文件夹,在里面会发现

我们打开这个标签文件,看到一坨代码。我们注意到:

  private java.lang.String bgColor;
  private java.lang.String cellColor;
  private java.lang.String title;
  private java.lang.String bean;
  public java.lang.String getBgColor() {
    return this.bgColor;
  }

  public void setBgColor(java.lang.String bgColor) {
    this.bgColor = bgColor;
    jspContext.setAttribute("bgColor", bgColor);
  }
....

我们看到这些代码是我们用编译指令attribute定义了的变量,经过编译之后,他们被创建成私有变量并配上set/get方法。这和我们在自定义标签处理类的时候是一样的,我们说这样可以保证jsp页面传入的属性的值可以自动的赋值给这些私有属性。(web容器干的)。我们还注意到:

这里也是一样的重写了doTag方法,同时还看到了标签文件中内置的对象有:

  • request
  • response
  • session
  • application
  • config
  • out
  • jspContext

绕了这么一圈,我们发现所谓的标签文件本质上还是我们那一套的自定义标签的流程,只是很大一部分内容交给了编译器。简化了我们程序员的工作。

     最后我们看看刚才跳过的编译指令variable,从上面的内容中我们知道,jsp页面可以通过属性传值给我们的标签文件,但是如果标签文件想要返回对象给jsp页面就需要使用到我们的variable编译指令。这个指令有几个属性需要注意下:

  • name-given ---指定了该变量的名称
  • variable-clas - ---指定了该变量的数据类型
  • scope ---指定该变量作用范围,这里有三个值

scope的第一个值可以是AT_BEGIN,该值表示此变量可以在标签体或者向下的代码中生效,第二值可以是NESTED,该值表示此变量只能出现在标签体中,第三个可以是AT_END,该值表示此变量只能从标签结束位置以后的代码中生效。可以看到第一个值的范围最大,包含了下面两个值的范围。定义完成之后,我们可以使用jspContext.setAttribute("time","now")方法为其赋值,这样我们的jsp页面就可以使用该变量了。

本篇文章至此结束,内容很简单,深入的内容还有待作者继续学习,希望能有大神指点纠正。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏行者常至

(09)Struts2 请求的扩展名问题

501
来自专栏MoeLove

理解Redis的RESP协议

Redis 的客户端和服务端之间采取了一种独立的名为 RESP(REdis Serialization Protocol) 的协议,作者主要考虑了以下几个点:

521
来自专栏数据结构笔记

scrapy爬虫框架(四):scrapy中 yield使用详解

MySQL下载:点我 python MySQL驱动下载:pymysql(pyMySql,直接用pip方式安装)

962
来自专栏Python小屋

Python使用模块中对象的几种方法

Python默认安装仅包含部分基本或核心模块,启动时也仅加载了基本模块,在需要时再显式地加载(有些模块可能需要先安装)其他模块,这样可以减小程序运行的压力,且具...

3336
来自专栏闪电gogogo的专栏

Python初学——pickle & set

pickle 存放数据 将数据保存为文件是永久保存的唯一方式,而文档内部是以字符串形式进行存放的,如果我们需要保存的是一个包含很多数据甚至是类的实例化的复杂的列...

1855
来自专栏数据库

存储过程和触发器的应用

实验案例三:创建视图 方法一:在图形界面下创建视图(以Myschool数据库为例) 创建一个视图,分别来自三个的表的三个列,并重命名列,生成的视图名为stude...

19410
来自专栏我的博客

CI基础知识笔记

1.知识点 $config[‘url_suffix’] = ”;//url后缀 $config[‘enable_query_strings’] = FALS...

2663
来自专栏海天一树

小朋友学Python(7):输入与输出

一、print与input print "a =", a = input() print "b =" b = input() print "c =", c = ...

26610
来自专栏Python攻城狮

常见编码问题UnicodeEncodeError

python 里面的编码和解码也就是 unicode 和 str 这两种形式的相互转化。编码是 unicode -> str,相反的,解码就是 str -> u...

562
来自专栏用户2442861的专栏

cmake 学习笔记(一)

http://blog.csdn.net/dbzhang800/article/details/6314073

411

扫码关注云+社区