Tomcat与JavaWeb 8.2 自定义标签的创建和使用(一)访问标签属性

1.    创建和使用message标签(访问标签属性)

在JSP文件中会包含许多静态文本,例如以下hello0.jsp中的“helloapp”"Nice to meet you:"都是静态文本:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>helloapp</title>
</head>
<body>
<b>Nice to meet you: ${param.username}</b>
</body>
</html>

下面创建一个能够替换JSP文件中的所有静态文本的message标签,它放在mytaglib标签库中,hello.jsp与hello0.jsp能生成同样的网页,区别在于hello.jsp使用了 message标签。在hello.jsp文件中使用message标签的步骤如下。

    1)    在JSP文件中引入这个标签库:

<%@ taglib prefix="mm" uri="/mytaglib" %>
    2)    用<mm:message>标签替换文件中的所有静态文本,以下是hello.jsp的源代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="mm" uri="/mytaglib" %>
<html>
<head>
    <title><mm:message key="hello.title"/></title>
</head>
<body>
<b><mm:message key="hello.hi"/>:${param.username}</b>
</body>
</html>

当客户访问hello.jsp时,message标签的处理类会根据key属性的值从一个特定的资源文件中找到与key匹配的字符串。假定与"hello.hi"字符串匹配的字符串为"Nice to meet you",那么message标签的处理类就将这个字符串输出到网页上。

对开发人员来说,采用message标签可以使JSP网页变得简洁并且易于维护。如果许多JSP网页的静态文本内容发生需求变更,那么无需修改这些JSP文件的代码,而只需要修改一个集中存放了所有网页的静态文本的资源文件即可。

采用message标签,还可以方便地实现同一个JSP文件支持多种语言版本。message标签可以根据客户选择的语言来输出响应的静态文本。使用不同语言的客户访问hello.jsp文件,message标签的处理过程如图所示:

1.1    创建message标签的处理类MessageTag

下面将创建message标签的处理类MessageTag,以及相关的资源文件和Servlet类。

    1)    创建包含JSP网页静态文本的资源文件

首先创建包含JSP网页静态文本的资源文件,这些文本以key/value的形式存放。在messageresource.properties资源文件中存放英文静态文本,在messageresource_ch.properties资源文件中存放中文静态文本,这两个文件都要存放在WEB_INF目录下:
messageresource.properties

hello.title = helloapp
hello.hi = Nice to meet you
login.title = helloapp
login.user = User Name
login.password = Password
login.submit = Submit

messageresource_ch.properties

hello.title = helloapp的hello页面
hello.hi = 你好
login.title = helloapp的登录页面
login.user = 用户名
login.password = 密码
login.submit = 提交

以上资源文件中包含了login.jsp和hello.jsp的静态文本,为了便于管理和区分不同JSP文件的文本,约定login.jsp中的静态文本的key以login开头,而hello.jsp中的静态文本以hello开头。

    2)    在Web应用启动时加载静态文本

尽管加载静态文本的任务可以直接由标签处理类来完成,但是把初始化的操作安排在Web应用启动时完成,更符合Web编程的规范。在本例中,将用LoadServlet类的init()方法来完成加载静态文本的任务。init()方法分别从messageresource.properties文件和messageresource_ch.properties文件中读取英文、中文静态文本,然后把它们加载到各自的Properties对象中,最后再把两个Properties对象作为属性保存到Web应用范围内。下面是其源代码:

LoadServlet.java

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Properties;

public class LoadServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        Properties ps = new Properties();
        Properties ps_ch = new Properties();
        try {
            ServletContext context = getServletContext();
            InputStream in = context.getResourceAsStream("/WEB_INF/messageresource.properties");
            ps.load(in);
            InputStream in_ch = context.getResourceAsStream("/WEB_INF/messageresource_ch.properties");
            ps_ch.load(in);

            in.close();
            in_ch.close();

            //在Web应用范围内存放包含静态文本的Properties对象
            context.setAttribute("ps",ps);
            context.setAttribute("ps_ch",ps_ch);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        init();
        PrintWriter out = resp.getWriter();
        out.println("The resource file is loaded.");
    }
}
为了保证在Web应用启动时就加载LoadServlet,应该在web.xml中配置这个Servlet时设置为<load-on-setup>子元素:
<web-app>
    <servlet>
        <servlet-name>LoadServlet</servlet-name>
        <servlet-class>LoadServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoadServlet</servlet-name>
        <url-pattern>/load</url-pattern>
    </servlet-mapping>
</web-app>

    3)    创建MessageTag类

MessageTag.java

package mypack;

import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.TagSupport;
import java.util.Properties;

public class MessageTag extends TagSupport {
    private String key = null;

    public String getKey() {
        return this.key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    @Override
    public int doEndTag() throws JspException {
        try {
            Properties ps = (Properties) pageContext.getServletContext().getAttribute("ps");
            Properties ps_ch = (Properties) pageContext.getServletContext().getAttribute("ps_ch");

            HttpSession session = pageContext.getSession();
            String language = (String) session.getAttribute("language");

            String message = null;
            if (language != null && language.equals("Chinese")) {
                message = (String) ps_ch.get(key);
            } else {
                message = (String) ps.get(key);
            }
            pageContext.getOut().print(message);
        } catch (Exception e) {
            throw  new JspTagException(e);
        }
        return EVAL_PAGE;
    }
}

MessageTag类包含一个成员变量key,它与<message>标签的属性key对应。在MessageTag中定义了getKey()和setKey()方法。LoadServlet的init()方法吧Properties对象保存在Web应用范围内。在MessageTag的doEndTag()方法中,首先从Web应用范围内读取包含静态文本的Properties对象,接着从会话范围内读取当前客户所使用的语言,然后根据使用的语言来选择相应的Properties对象,从中读取key对应的静态文本。如果用户选择的是中文语言,还要进行字符编码转换处理。Properties对象在通过InputStream流装载文件时,按照ISO-8859-1编码来读取数据,因此应该把葱Properties对象中读取的静态文本转换为中文编码GB2312.

1.2    创建标签库描述文件(TLD)

TLD文件采用XML文件格式,对标签库及库中的标签做了描述。TLD文件中的元素可以分为3类:<taglib>,标签库元素;<tag>,标签元素;<attribute>,标签属性元素。

    1)    标签库元素<taglib>

标签库元素用来设定标签库的相关信息,它的子元素包括:

  • tlib-version:指定标签库的版本
  • jsp-version:指定JSP的版本
  • short-name:指定标签库默认的前缀名(prefix)
  • uri:sh标签库的唯一访问标识符
  • info:设定标签库的说明信息。

    2)    标签元素<tag>

标签元素用来定义一个标签,它的子元素包括:

  • name:设定标签的名字
  • tag-class:设定标签的处理类
  • body-content:设定标签主体的类型
  • info:设定标签的说明信息

以上<tag>元素的<body-content>子元素用于设定标签主体的类型,可选值包括:

  • empty:标签主体为空。
  • scriptless:标签主体不为空,并且包含JSP的EL表达式和动作元素,但不能包含JSP的脚本元素。所谓动作元素是指<jsp:include>和<jsp:forward>等以"jsp"为前缀的JSP内置标签。所谓脚本元素是指以"<%!"、"<%="、"<%!"这三种以"<%"开头的JSP标记。
  • jsp:标签主体不为空,并且包含JSP代码,在JSP代码中可包含EL表达式、动作元素和脚本元素。<body-content>子元素的scriptless可选值与jsp可选值的区别在于前者不能包含JSP的脚本元素。
  • tagdependant:标签主体不为空,并且标签主体内容由标签处理类来解析和处理。标签主体内的所有代码都会原封不动地传给标签处理类,而不是把标签主体的执行结果传给标签处理类。加入用户定义了一个<sql:query>标签,它的<body-content>元素的值为tagdependant。以下JSP代码使用了该标签:
<sql:query>
 select * from MemberDB where ID<10
</sql:query>

    这段代码中的标签主体为一个SQL语句,它将由<sql:query>标签的处理类来处理,该类负责执行这个SQL语句。

    3)    标签属性元素<attribute>

标签属性元素用来描述标签的属性,该元素的子元素包括:

  • name:属性名称
  • required:属性是否是必须的,默认为false
  • rtexprvalue:属性值是否可以为基于"<%"和"%>"形式的Java表达式或EL表达式

对于<rtexprvalue>子元素,如果取值为true,表示标签的属性可以为普通的字符串,或者是Java表达式和EL表达式;如果是false,那么标签的属性只能为普通的字符串。例如对于以下mytag标签,它的num属性就是一个Java表达式,因此当TLD文件中定义mytag标签的num属性时,应该把<rtexprvalue>子元素设置为true。

<% int num = 1;%>
<prefix:mytag num="<%= num %>"/>

下面将创建TLD文件,命名为mytaglib.tld。在这个文件中定义了uri为"/mytaglib"的标签库,本章创建的所有标签都位于这个标签库中。下例程是mytaglib.tld文件的源代码,它定义了一个名为message的标签,这个标签有一个名为"key"的属性。本章后文还会介绍向mytaglib.tld文件中加入其他范例标签的定义代码。

WEB_INF/mytaglib.tld

<?xml version="1.0" encoding="ISO-8859-1"?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
        version="2.1">

    <tlib-version>1.0</tlib-version>
    <short-name>mytaglib</short-name>
    <uri>/mytaglib</uri>

    <tag>
        <description>produce message by key</description>
        <name>message</name>
        <tag-class>mypack.MessageTag</tag-class>
        <body-content>empty</body-content>
        <attribute>
            <name>key</name>
            <required>true</required>
        </attribute>
    </tag>
</taglib>

由于<message>标签的主体为空,因此<body-content>子元素的值为"empty"。当在JSP文件中使用<message>标签时,必须为标签设置key属性,因此<attribute>元素的<required>子元素的值为"true".

1.3    在Web应用中使用标签

如果在Web应用中用到了特定标签库中的自定义标签,则应该在web.xml中加入<taglib>元素,它用于声明所引用的标签库:

    <jsp-config>
        <taglib>
            <taglib-uri>/mytaglib</taglib-uri>
            <taglib-location>/WEB-INF/mytaglib.tld</taglib-location>
        </taglib>
    </jsp-config>
在JSP文件中需要通过<%@ taglib>指令来声明对标签库的引用,例如:
<%@ taglib uri="/mytaglib" prefix="mm" %>
以上指令中的uri属性用来指定标签库的标识符,它和web.xml中的<taglib-uri>元素的值保持一致。prefix属性表示在JSP文件中引用这个标签库中的标签的前缀,例如如下代码表示引用mytaglib标签库中的<message>标签:
<title><mm:message key="hello.title" /></title>

除了按照本章的方式在web.xml文件中声明引入的标签库,还可以直接使用第三方提供的符合特定规范的标签库的JAR打包文件下面在Web应用中加入3个负责产生网页的文件:index.html、login.jsp和hello.jsp,它们之间的链接关系为:index.html -> login.jsp -> hello.jsp,这三个文件组成了一个小小的支持中文和英文两个版本的Web应用。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>helloapp</title>
</head>
<body>
<p>Welcome to helloapp!</p>
<a href="login.jsp?language=English">English Version</a>
<a href="login.jsp?language=Chinese">中文版本</a>
</body>
</html>
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="mm" uri="/mytaglib" %>
<html>
<%
    String language = request.getParameter("language");
    if (language==null) language="English";
    session.setAttribute("language",language);
%>
<head>
    <title><mm:message key="login.title"/></title>
</head>
<body>
<br>
<form name="loginForm" method="post" action="hello.jsp">
    <table>
        <tr>
            <td><div align="right"><mm:message key="login.user"/>:</div> </td>
            <td><input type="text" name="username"> </td>
        </tr>
        <tr>
            <td><div align="right"><mm:message key="login.password"/>:</div> </td>
            <td><input type="password" name="username"> </td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" name="Submit" value=<mm:message key="login.submit"/> > </td>
        </tr>
    </table>
</form>
</body>
</html>
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="mm" uri="/mytaglib" %>
<html>
<head>
    <title><mm:message key="hello.title"/></title>
</head>
<body>
<b><mm:message key="hello.hi"/>:${param.username}</b>
</body>
</html> 

OK,需要的文件都已经写好,下面运行起来应用,进入index.html效果图:

分别点击中英文版本,会出现对应语言的表单。(如果点击中文版本显示Server Internal Error,可能是IDEA编码设置的问题,在IDEA的File ——Settings——Editor——File Encodings,把Global和Project Encoding设为UTF-8,把下方Default encoding for properties files设置为ISO-8859-1,并勾选旁边的Transparent native-to-ascii conversion)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值