<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="s" uri="/struts-tags"%>
<jsp:include page="path" flush="true" />
<jsp:param name="paramName" value="paramValue" />
<jsp:forward page="path" />
<jsp:useBean id="name" scope="page | request | session | application" typeSpec />
<jsp:setProperty name="beanName" prop_expr />
<jsp:getProperty name="name" property="propertyName" />
封装JSP中常用的功能, 如可以封装一些html、js代码、jsp代码块(java代码<% %>
)等,封装的标签可以看成实现一个独立的功能的JSP,引用标签相当于包含include了该jsp,使用封装的标签比单纯的引入jsp页面要更简洁,便于在JSP页面中复用
.tag方式,引用时通过tagdir属性指定.tag文件的位置,例如 <%@ taglib prefix="x" tagdir="/WEB-INF/tags" %>
.tld方式,引用时通过uri属性间接指定.tld文件的位置(需要在web.xml中jsp-config下配置taglib),例如 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
基本知识
第一步: 引入web的基本依赖
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.0.1version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>jsp-apiartifactId>
<version>2.2version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
dependencies>
<build>
<finalName>platform-tagfinalName>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>2.3.2version>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
plugins>
build>
第二步: 在src/main/webapp/WEB-INF/tags目录下创建定义标签
此处定义了3个标签,calc.tag 用于数学运算,page.tag,page2.tag 用于测试,没有什么实际意义
calc.tag
<%@ tag body-content="empty" trimDirectiveWhitespaces="true" pageEncoding="UTF-8"%>
<%@ tag import="java.util.Arrays" %>
<%@ attribute name="x" required="true" rtexprvalue="true" %>
<%@ attribute name="y" required="true" rtexprvalue="true" %>
<%@ attribute name="operator" required="true" rtexprvalue="true" %>
<div>
<%
if("+".equals(operator)){
%>
加法运算 :
<%
}
%>
${x}${operator}${y} =
<script type="text/javascript">
document.write(eval("${x}${operator}${y}"))
script>
div>
page.tag
<%@ tag body-content="scriptless" trimDirectiveWhitespaces="true" pageEncoding="UTF-8"%>
<div style="background-color: gray; width=70px;">
contextPath: ${pageContext.request.contextPath}
<jsp:doBody />
div>
page2.tag
<%@ tag body-content="tagdependent" trimDirectiveWhitespaces="true" pageEncoding="UTF-8"%>
<div style="background-color: red; width=auto">
contextPath: ${pageContext.request.contextPath}
<jsp:doBody />
div>
第三步:使用标签库
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="math" tagdir="/WEB-INF/tags/" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title heretitle>
head>
<body>
<math:calc x="1" operator="+" y="1"/>
<math:calc x="1" operator="-" y="1"/>
<math:calc x="1" operator="*" y="2"/>
<math:calc x="1" operator="/" y="2"/>
<hr/>
<math:page>
<b>标签体内容。。。b>
math:page>
<hr/>
<math:page2>
<b>标签体内容2。。。b>
math:page2>
body>
html>
1、自定义标签时需要为该标签设置一些基本属性,如 body-content、trimDirectiveWhitespaces、pageEncoding 等
<%@ tag body-content="empty" trimDirectiveWhitespaces="true" pageEncoding="UTF-8"%>
body-content :用于指定该自定义标签是否允许有标签体以及标签体中的内容该如何解析(是当做纯文本直接输出,还是当做html来渲染呢)
, 支持EL表达式2、 自定义标签时可以声明属性
<%@ attribute name="x" required="true" rtexprvalue="true" %>
- name : 属性名称
- required:属性是否必须,true/false
- rtexprvalue: 是否解析EL表达式,true:解析EL表达式,false: 当做纯文本
- type :属性的数据类型
3、 可以在.tag文件中使用java代码块,可以使用import属性导入使用到的类
<%@ tag import="java.util.Arrays" %>
ext.tld : 用于描述标签的名字和属性
<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">
<tlib-version>1.0tlib-version>
<jsp-version>1.1jsp-version>
<short-name>extshort-name>
<uri>http://www.mengdee.com/tag/exturi>
<tag>
<name>pagename>
<tag-class>com.mengdee.manager.util.tag.PageHandlertag-class>
<body-content>JSPbody-content>
<attribute>
<name>pagename>
<required>truerequired>
<rtexprvalue>truertexprvalue>
attribute>
<attribute>
<name>actionname>
<required>truerequired>
<rtexprvalue>truertexprvalue>
attribute>
tag>
taglib>
<jsp-config>
<taglib>
<taglib-uri>http://www.mengdee.com/tag/exttaglib-uri>
<taglib-location>/WEB-INF/tld/ext.tldtaglib-location>
taglib>
jsp-config>
需要继承BodyTagSupport,重写doStartTag()和doEndTag()方法
PageHandler
package com.mengdee.manager.util.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class PageHandler extends BodyTagSupport{
private static final long serialVersionUID = 1L;
private String action;
private Page page;
@Override
public int doStartTag() throws JspException {
return EVAL_BODY_BUFFERED;
}
// 该方法只是简单的演示一下分页,实际使用时还需要对该分页的html进行完善
@Override
public int doEndTag() throws JspException {
int currentPage = page.getCurrentPage();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(" ");
stringBuilder.append(" 126条 共7页 ");
stringBuilder.append(" " + currentPage + " ");
stringBuilder.append(" " + (currentPage + 1) + " ");
stringBuilder.append(" " + (currentPage + 2) + " ");
stringBuilder.append(" " + (currentPage + 3) + " ");
stringBuilder.append(" " + (currentPage + 4) + " ");
stringBuilder.append(" ... ");
stringBuilder.append(" 下一页 ");
stringBuilder.append(" 尾页 ");
stringBuilder.append("");
try {
pageContext.getOut().print(stringBuilder.toString());
} catch (IOException e) {
e.printStackTrace();
}
return EVAL_PAGE;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public Page getPage() {
return page;
}
public void setPage(Page page) {
this.page = page;
}
}
Page:分页实体,用于封装分页相关的参数
package com.mengdee.manager.util.tag;
public class Page {
/** 当前页码 */
private int currentPage = 1;
/** 每页显示的条数 */
private int count = 10;
/** 总行数 */
private int totalRowCount;
/** 总页数 */
private int totalPageCount;
public Page() {
this.currentPage = 1;
this.count = 10;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getTotalRowCount() {
return totalRowCount;
}
public void setTotalRowCount(int totalRowCount) {
this.totalRowCount = totalRowCount;
}
public int getTotalPageCount() {
return this.totalPageCount = (int) Math.ceil((double) totalRowCount / count);
}
}
index.jsp: 引入自定义的标签库,引入page.css样式
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.mengdee.com/tag/ext" prefix="ext"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="${pageContext.request.contextPath}/static/css/page.css" />
<title>Insert title heretitle>
head>
<body>
<ext:page action="${pageContext.request.contextPath}/indexServlet" page="${page}">ext:page>
body>
html>
page.css :为了美化分页的样式
@CHARSET "UTF-8";
.page_nav{margin:20px 0; color:#666; text-align:center;}
.page_nav a,.page_nav strong{display:inline-block; height:22px; margin:0 2px; padding:0 8px; border:solid 1px #dbe5ee; -moz-border-radius: 3px;-webkit-border-radius:3px; background:#fff; cursor:pointer; font:normal 12px/22px Arial, Helvetica, sans-serif;}
.page_nav strong {height:24px; margin:0 3px; border:none; background:#07519a; color:#fff; line-height:24px; text-decoration:none;}
.page_nav span{margin:0 10px;}
indexServlet中需要将page参数包装到作用域中,index.jsp中自定义的标签需要使用到
package com.mengdee.manager.util.tag;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class IndexServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public IndexServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Page page = new Page();
String pageIndex = request.getParameter("no");
if (pageIndex == null) {
pageIndex = "1";
}
page.setCurrentPage(Integer.parseInt(pageIndex));
request.setAttribute("page", page);
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
访问: http://localhost:8080/custom-tag/indexServlet
流程分析:
首先访问indexServlet, 执行 doGet()方法,方法内部会将page对象保存到request请求中request.setAttribute(“page”, page);接着跳转到index.jsp, 然后 运行自定义标签,当运行自定义标签时就会执行配置的标签类
该标签类通过pageContext.getOut().print(stringBuilder.toString()); 将分页的html字符串输出到页面
两种方式都可以用来自定义标签,不同的是自定义标签时的逻辑写的位置不同
从以上示例可以看到.tag方式将逻辑写在.tag文件中,.tag可以看成一个.jsp文件,可以使用EL表达式、使用java代码库处理逻辑,.tld 文件将逻辑都写在Java类中了,对应复杂的业务使用.tld在Java类中处理更方便,在.tag中还要多个<% %>
看起来太乱,可读性不太好对于逻辑比较简单的使用.tag方式比较方便,直接在.tag中封装
在jsp页面中在使用jstl表达式中经常会用一些函数,如 fn:length(item)、fn:replace(string, before, after)、fn:startsWith(string, prefix) 等
<%@ taglib prefix="fn" uri="http://Java.sun.com/jsp/jstl/functions" %>
<c:if test="${fn:contains(name, searchString)}">
${fn:length(shoppingCart.products)}
第一步: 创建自己的工具类函数, 如:CommonTagLib
package com.mengdee.manager.web.taglib;
public class CommonTagLib {
public static boolean isEmpty(String string){
System.out.println("run ...");
if (null == string || "".equals(string) ||
"undefined".equals(string) || "null".equals(string)) {
return true;
}
return false;
}
}
方法定义为静态方法,可以注入Spring中的bean
第二步:创建tld文件用于描述标签库函数
一般放在/WEB-INF/tld目录下
common.tld
<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">
<tlib-version>1.0tlib-version>
<short-name>commonshort-name>
<uri>http://www.mengdee.com/tag/commonuri>
<function>
<name>isEmptyname>
<function-class>com.mengdee.manager.web.taglib.CommonTagLibfunction-class>
<function-signature>boolean isEmpty(java.lang.String)function-signature>
<example>{common:isEmpty(string)}example>
function>
taglib>
function-class:指定Java类的全路径
function-signature:指定函数的方法签名
example:如何使用该函数,给出一个示例
第三步:在web.xml中配置.tld文件的位置
<jsp-config>
<taglib>
<taglib-uri>http://www.mengdee.com/tag/commontaglib-uri>
<taglib-location>/WEB-INF/tld/common.tldtaglib-location>
taglib>
jsp-config>
第四步:在jsp页面中引用标签库函数
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://www.mengdee.com/tag/common" prefix="common"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title heretitle>
head>
<body>
<c:choose>
<c:when test="${common:isEmpty('null')}">
空
c:when>
<c:otherwise>
有值
c:otherwise>
c:choose>
<c:choose>
<c:when test="${common:isEmpty('123456')}">
空
c:when>
<c:otherwise>
有值
c:otherwise>
c:choose>
body>
html>
参考文章:http://blog.csdn.net/dfdsggdgg/article/details/51492290
相关文章: http://blog.csdn.net/alan_liuyue/article/details/71129046