Web基础之自定义JSP标签

Web基础之自定义JSP标签

一、什么是JSP标签
JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写
java代码,造成jsp页面难以维护。
JSP标签是用来替换代码的,那么了解JSP标签,只需要了解JSP标签对应的代码即可。

二、常用的JSP标签


静态包含和静态包含的详细区别见上篇博客;

三、开发自定义标签步骤






四、标签执行流程




五、JSTL

使用JSTL时,需要导入jar包,并在jsp页面中使用taglib指令 
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

JSTL核心标签库

六、自定义标签实例

项目整体架构:


该项目自定义了三个标签,分别是日期转换标签(对应上面的问题)、自定义的if标签、自定义格式化金额标签;

项目源代码:
思路:参照上面的自定义标签开发的步骤

自定义标签类继承SimpleTagSupport类

自定义日期标签类
package com.hx.servlet.tag;

import java.io.IOException;
import java.text.SimpleDateFormat;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class DateFormatTag extends SimpleTagSupport {

    // 格式化的格式
    private String pattern = "yyyy-MM-dd HH:mm:ss";

    private Object date;

    @Override
    public void doTag() throws JspException, IOException {
        // 获取标签体中的文本内容
        // StringWriter sw = new StringWriter();
        // this.getJspBody().invoke(sw);
        // String content = sw.toString();

        // 将给定的时间,按指定的格式转化为字符串
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String str = sdf.format(date);

        // 获取JSPContext对象
        JspContext jc = this.getJspContext();
        // 获取输出对象out
        JspWriter out = jc.getOut();
        // 使用out向外输出
        // out.write(content);
        out.write(str);
    }

    public String getPattern() {
        return pattern;
    }

    public void setPattern(String pattern) {
        this.pattern = pattern;
    }

    public Object getDate() {
        return date;
    }

    public void setDate(Object date) {
        this.date = date;
    }
}

自定义If标签类:
package com.hx.servlet.tag;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class IfTag extends SimpleTagSupport {

    // if 控制语句的条件表达式
    private boolean test;

    @Override
    public void doTag() throws JspException, IOException {
        if (test) {
            // 获取标签体中的文本内容
            StringWriter sw = new StringWriter();
            this.getJspBody().invoke(sw);
            String content = sw.toString();
            // 获取JSPContext对象
            JspContext jc = this.getJspContext();
            // 获取输出对象out
            JspWriter out = jc.getOut();
            // 使用out向外输出
            out.write(content);
        }
    }

    public boolean getTest() {
        return test;
    }

    public void setTest(boolean test) {
        this.test = test;
    }
}


自定义格式化金额类:
package com.hx.servlet.tag;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;

import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class MoneyFormatTag extends SimpleTagSupport {

    private String prefix = ""; // 前缀

    private BigDecimal amount; // 要格式化的金额

    private int scale = 2; // 小数点位数

    @Override
    public void doTag() throws JspException, IOException {
        // 首先设置小数点位数,采用四舍五入
        amount = amount.setScale(scale, RoundingMode.HALF_UP);

        // 格式化金额
        String amt = format(amount);

        // 获取JSPContext对象
        JspContext jc = this.getJspContext();
        // 获取输出对象out
        JspWriter out = jc.getOut();
        // 使用out向外输出
        String content = null;
        if (!"".equals(prefix = prefix.trim())) {
            content = prefix + " " + amt;
        } else {
            content = amt;
        }
        out.write(content);
    }

    /**
     * 格式化金额. <br/>
     * 如:1000.00 格式化为: 1, 000.00
     * 
     * @version 1.0
     *
     * @param amount
     * @return
     */
    private String format(BigDecimal amount) {
        if (amount == null) {
            return "";
        }

        // 1. 设置为两位小数点
        amount.setScale(2);

        // 2. 将金额转化为字符串
        String amt = amount.toPlainString();

        // 3. 格式化
        return formt(amt);
    }

    private String formt(String amount) {
        // 找到小数点
        int index = amount.indexOf(".");
        // 获取整数部分
        String zs = null;
        if (index > 0) {
            zs = amount.substring(0, index);
        } else {
            zs = amount;
        }
        StringBuilder sbuilder = new StringBuilder();
        int length = zs.length();
        int count = 0;
        for (int i = length - 1; i >= 0; i--) {
            count = count + 1;
            sbuilder.append(zs.charAt(i));
            if (count % 3 == 0 && count < length) {
                sbuilder.append(",");
            }
        }

        // 逆序
        sbuilder.reverse();

        // 获取格式化之后的整数部分
        zs = sbuilder.toString();
        if (index > 0) {
            return zs + amount.substring(index);
        }
        return zs;
    }

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    public int getScale() {
        return scale;
    }

    public void setScale(int scale) {
        this.scale = scale;
    }
}


编写tld文件:hx-taglib.tld

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

<!DOCTYPE taglib
        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
        "http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>

  <tlib-version>1.0</tlib-version>
  <jsp-version>1.2</jsp-version>
  <!-- 标签的名称 -->
  <short-name>huaxin</short-name>
  <!-- 标签库的URL,
  	        如果当前工程下没有该描述文件,
  	   @taglib 指令会去它的 uri 路径下查找对应的tld文件
  -->
  <uri>http://www.huaxin.com/tag-lib</uri>
  <!-- JSP标签库的描述信息 -->
  <description>
  	a simple for JSP tag  
  </description>

  <tag>
  	<!-- 标签名称 -->
    <name>formatdate</name>
    <!-- 标签类的全限定名 -->
    <tag-class>com.hx.servlet.tag.DateFormatTag</tag-class>
    <!-- 标签体的类型 -->
    <body-content>empty</body-content>
    <description>format the given date to the specified pattern</description>
    <attribute>
       <!-- 标签的属性名称 -->
       <name>pattern</name>
       <!-- 该属性是否必填 -->
       <required>false</required>
       <!-- 该属性的值是否允许为表达式 -->
       <rtexprvalue>false</rtexprvalue>
    </attribute>
      <attribute>
       <name>date</name>
       <required>true</required>
       <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
  
  <tag>
    <name>if</name>
    <tag-class>com.hx.servlet.tag.IfTag</tag-class>
    <!-- 标签体的类型 -->
    <body-content>scriptless</body-content>
    <description>If control</description>
    <attribute>
       <name>test</name>
       <required>true</required>
       <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
  
  <tag>
    <name>fomartmoney</name>
    <tag-class>com.hx.servlet.tag.MoneyFormatTag</tag-class>
    <!-- 标签体的类型 -->
    <body-content>empty</body-content>
    <description>format money, i.e € 2,000.00 OR 2,000</description>
    <attribute>
       <name>prefix</name>
       <required>false</required>
       <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
       <name>amount</name>
       <required>true</required>
       <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
       <name>scale</name>
       <required>false</required>
       <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
</taglib>


简单的登录(login.jsp)和主页(index.jsp)JSP以及逻辑处理的Servlet(LoginServlet.java)

主页JSP中使用了我们自定义的标签

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" errorPage="error.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<%
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
	request.setAttribute("bathPath", basePath);
%>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>登录</title>
</head>
<body style="text-align:center;">
	<form action="${bathPath }/login" method="POST">
		<table style="margin-top:50px; margin-left:auto; margin-right:auto;width:80%;">
			<tr>
				<td style="text-align:right;">用户名:</td>
				<td style="text-align:left;"><input id="userName" type="text" name="userName"></td>
			</tr>
			<tr>
				<td style="text-align:right;">密 码:</td>
				<td style="text-align:left;"><input type="password" name="userPwd"></td>
			</tr>
			<tr>
				<td colspan="2">
				          
				<input type="submit" value="登录">
				          
				          
				<input type="reset" value="重置"></td>
			</tr>
		</table>
	</form>
</body>
</html>


index.jsp(注意其中的taglib指令)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.huaxin.com/tag-lib" prefix="hx" %>  <%--prefix:前缀 --%>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>主页</title>
</head>
<body>
	欢迎你,${currentUser }。  最近一次登录时间:
	<%--JAVA代码处理时间格式化 --%> 
	<%
		Date lastLoginTime = (Date)pageContext.findAttribute("lastLoginTime");
		if(lastLoginTime != null) {
		    //时间格式化
		    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
		    out.write(sdf.format(lastLoginTime));
		}
	%><br/>
	
	
	<%--自定义JSP标签处理时间格式化 --%>
	最后一次登录时间:<hx:formatdate date="${lastLoginTime }" pattern="yyyy年MM月dd日 HH:mm:ss"/>
	<br/>
	
	
	<%--if分支控制 --%>
	<hx:if test="${currentUser == '张三' }">
		<a href="">查看全体成员</a>
	</hx:if>
	<br/>
	
	账户余额:<hx:fomartmoney prefix="€" amount="${amount }"/>
</body>
</html>

Servlet逻辑处理

package com.hx.servlet;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String userName = req.getParameter("userName");
        String userPwd = req.getParameter("userPwd");
        // 2.登录校验成功,将登录信息保存到 Session
        req.getSession().setAttribute("lastLoginTime", new Date());
        req.getSession().setAttribute("currentUser", userName);
        req.getSession().setAttribute("amount", new BigDecimal("999999999999999999999"));
        // 应该重定向到主页
        resp.sendRedirect("index.jsp");
    }
}

当然,我们的配置文件也是不能少的(只需要配置我们自己写的Servlet,去处理对应的路径就好了)
web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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-app_2_5.xsd"
  version="2.5">
  <display-name>jsptag</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
  	<servlet-name>login</servlet-name>
  	<servlet-class>com.hx.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>login</servlet-name>
  	<url-pattern>/login</url-pattern>
  </servlet-mapping>
</web-app>


七、项目运行效果:

用张三登录








用李四登录




八、总结
主要学习了标签的意义,标签的运行原理以及如何开发我们自己的标签;通过自己开发标签来加深对JSTL标签库的理解;我们以后主要用的是JSTL标签库;但是,我们更要明白其中的原理;
学无止境!共勉!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值