zoukankan      html  css  js  c++  java
  • JSP自定义标签

    一、为什么需要自定义标签
        1)与JSP页面整体统一
        2)还具有一定的业务逻辑功能,例如:循环、判断等

    二、自定标签开发步骤
        一】第一步:写一个自定义的标签处理类

        public class Demo implements SimpleTag{
                private PageContext pageContext;
                //PageContext是JspContext的子类
                @Override
                public void setJspContext(JspContext jspContext) {
                    System.out.println("Do setJspContext");
                    //得到jsp页面对象
                    pageContext = (PageContext) jspContext;
                }
    
                @Override
                public void doTag() throws JspException, IOException {
                    System.out.println("Do doTag");
                    //取得HttpServletRequest对象
                    HttpServletRequest request= (HttpServletRequest) pageContext.getRequest();
                    //得到ip地址
                    String ip = request.getRemoteAddr();
                    System.out.println(ip);
                    //取得out <---> JspWriter对象
                    JspWriter out = pageContext.getOut();
                    //向浏览器输出IP地址信息
                    out.write("<font size='30px' color='red'>" + "ip:" + ip + "</font>");
                }
    
                @Override
                public JspTag getParent() {
                    return null;
                }
    
                @Override
                public void setJspBody(JspFragment arg0) {  
                }
    
    
                @Override
                public void setParent(JspTag arg0) {
                }
            }



        二】第二步:在/WEB-INF/目录下,写一个.tld文件,目的是让web容器知道自定义标签和标签处理类的对应关系

           <?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>JSTL 1.1 core library</description>
              <display-name>JSTL core</display-name>
              <tlib-version>1.1</tlib-version>
              <short-name>sky</short-name>
              <uri>http://com.suse/jsp/jstl/sky</uri>
              
              <tag>
                <name>ip</name>
                <tag-class>com.suse.simpletag.Demo</tag-class>
                <body-content>empty</body-content> <!--empty:此标签为空标签-->
              </tag>
            </taglib>



        三】第三步:在JSP页面中,通过<%@taglib%>指令引用标签库

          <%@ taglib prefix="sky" uri="http://com.suse/jsp/jstl/sky"%>
    
            <sky:ip />



    三、标签处理过程
        1)SimpleTag接口中有5个方法,这5个方法容器会在适当的时候选择调用,
        2)其中,doTag()方法最为核心,该方法中封装了该标签的处理业务逻辑
        3)项目中通常都会使用SimpleTagSupport类,该类已经对SimpleTag接口实现

    四、案例:
        一】控制标签中的内容是否执行( <sky:execute>标签 )
            1)执行标签体     :调用invoke(null)方法
            2)不执行标签体   :不调用invoke(null)方法

        code:
                public class ExecuteTag extends SimpleTagSupport {
                    @Override
                    public void doTag() throws JspException, IOException {
                        //将此标签内的内容封装成JspFragment对象
                        JspFragment jspFragment = this.getJspBody();
                        //将标签中的内容进行输出,null表示默认输出到浏览器中,否则会输出到相应的流中
                        jspFragment.invoke(null); //若没有这条语句,那么此标签的内容便不会输出到浏览器页面中
                    }
                }
            tag:
                 <tag>
                      <name>execute</name>
                      <tag-class>com.suse.simpletag.ExecuteTag</tag-class>
                      <body-content>scriptless</body-content>       <!-- //scriptless表示不允许有脚本存在此标签内部 -->
                 </tag>


        二】控制标签后的内容是否执行
            方法:抛出 SkipPageException 异常。导致标签体后的内容不执行

        code:
                public class SkipTag extends SimpleTagSupport {
                    @Override
                    public void doTag() throws JspException, IOException {
                        JspFragment jspFragment = this.getJspBody();
                        jspFragment.invoke(null);                    //设置此标签后的内容不再执行。方法:抛出一个 SkipPageException() 异常。
                        throw new SkipPageException();
                    }
                }
          tag:
                  <tag>
                      <name>skip</name>
                      <tag-class>com.suse.simpletag.SkipTag</tag-class>
                      <body-content>scriptless</body-content>
                  </tag>




        三】将标签体中内容转换成大写

        public class UpperTag extends SimpleTagSupport {
            @Override
            public void doTag() throws JspException, IOException {
                JspFragment jspFragment = this.getJspBody();
                
                //创建一个缓冲区,用于存储标签中的内容
                StringWriter writer = new StringWriter();
                jspFragment.invoke(writer);
                
                //将缓冲区中的内容进行处理(小写 --> 大写)
                StringBuffer buffer = writer.getBuffer();
                String upString = buffer.toString().toUpperCase();
                
                //将转换后的内容输出到浏览器中
                JspContext jspContext = this.getJspContext();
                JspWriter out = jspContext.getOut();
                out.write(upString);
            }



        四】开发带属性的标签:
            1)在标签处理器中编写每个属性对应的setter方法
            2)在TLD文件中描述标签属性

       code:
            public class ForSkip extends SimpleTagSupport{
                private String var;
                private int begin;
                private int end;
                private int step = 1; //增量默认为1
                
                public void setVar(String var) {
                    this.var = var;
                }
                public void setBegin(int begin) {
                    this.begin = begin;
                }
                public void setEnd(int end) {
                    this.end = end;
                }
                public void setStep(int step) {
                    this.step = step;
                }
                
                @Override
                public void doTag() throws JspException, IOException {
                    for (int i = this.begin; i <= this.end; i += this.step ) {
                        this.getJspContext().setAttribute(this.var, i);
                        this.getJspBody().invoke(null);
                    }
                }
            }
    
        tld:
            <tag>
                 <name>forskip</name>
                 <tag-class>com.suse.simpletag.ForSkip</tag-class>
                 <body-content>scriptless</body-content>
                 <attribute>
                     <name>var</name>
                     <required>true</required>
                     <rtexprvalue>true</rtexprvalue>
                 </attribute>
                 <attribute>
                     <name>begin</name>
                     <required>true</required>
                     <rtexprvalue>true</rtexprvalue>
                 </attribute>
                 <attribute>
                     <name>end</name>
                     <required>true</required>
                     <rtexprvalue>true</rtexprvalue>
                 </attribute>
                 <attribute>
                     <name>step</name>
                     <required>false</required>
                     <rtexprvalue>true</rtexprvalue>
                 </attribute>
            </tag>
        jsp:
            <sky:forskip var="item" begin="1" end="25" step="3">
                ${item} &nbsp;&nbsp;&nbsp;
            </sky:forskip>



        五】开发带有父标签的自定义标签
            思路:当某些标签是排它执行,此时:
              1) 可以在这些标签外,嵌入一个父标签,
              2) 并在父标签中做一个标志位,判断是否执行过。

      code:
            //1, <sky:choose> content </sky:choose>
            public class ChooseTag extends SimpleTagSupport {
                private boolean done = false;
    
                public boolean isDone() {
                    return done;
                }
                
                public void setDone(boolean done) {
                    this.done = done;
                }
    
    
                @Override
                public void doTag() throws JspException, IOException {
                    JspFragment jspFragment =  this.getJspBody();
                    jspFragment.invoke(null);
                }
                
            }
    
            //2,<sky:while test="${expr}"> content </sky:while>
            public class WhileTag extends SimpleTagSupport {
                
                private boolean test;
                public void setTest(boolean test) {
                    this.test = test;
                }
    
                
                @Override
                public void doTag() throws JspException, IOException {
                    //得到父标签后获取是否已经做过了
                    ChooseTag chooseTag = (ChooseTag) this.getParent();
                    boolean done = chooseTag.isDone();
                    
                    //如果没有做过,并且表达式成立
                    if (!done && test) {
                        this.getJspBody().invoke(null);
                        chooseTag.setDone(true);
                    }
                }
            }
    
            //3,<sky:otherwise>content</sky:otherwise>
            public class OtherWiseTag extends SimpleTagSupport {
                @Override
                public void doTag() throws JspException, IOException {
                    //得到父类标签对象,获取到Done的状态,进行相应的处理
                    ChooseTag chooseTag = (ChooseTag) this.getParent();
                    boolean done = chooseTag.isDone();
                    if (!done) {
                        this.getJspBody().invoke(null);
                        chooseTag.setDone(true);
                    }
                }
            }
    
        tld:
             <tag>
                 <name>choose</name>
                 <tag-class>com.suse.simpletag.ChooseTag</tag-class>
                 <body-content>scriptless</body-content>
             </tag>
             <tag>
                 <name>while</name>
                 <tag-class>com.suse.simpletag.WhileTag</tag-class>
                 <body-content>scriptless</body-content>
                 <attribute>
                     <name>test</name>
                     <required>true</required>
                     <rtexprvalue>true</rtexprvalue>
                 </attribute>
             </tag>
            
             <tag>
                 <name>otherwise</name>
                 <tag-class>com.suse.simpletag.OtherWiseTag</tag-class>
                 <body-content>scriptless</body-content>
             </tag>
        jsp:
            <%
            pageContext.setAttribute("age", 25);
            %>
            <sky:choose>
                <sky:while test="${age > 16}">
                    你成年了<br />
                </sky:while>
                <sky:otherwise>
                    你未成年 <br />
                </sky:otherwise>
            </sky:choose>



        六】防盗链

      code:
             public class Reference extends SimpleTagSupport{
                private String url;
                private String error;
                
                public void setUrl(String url) {
                    this.url = url;
                }
                public void setError(String error) {
                    this.error = error;
                }
    
    
                @Override
                public void doTag() throws JspException, IOException {
                    //得到页面内置对象
                    PageContext pageContext = (PageContext) this.getJspContext();
                    HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
                    HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
                    
                    //获取标签体中的内容并进行处理
                    JspFragment jspFragment = this.getJspBody();
                    String refer = request.getHeader("referer");
                    System.out.println(refer);
                    if (this.url.equals(refer)) { //referer头表明来自于哪里
                        jspFragment.invoke(null);
                    } else {
                        try {
                            request.getRequestDispatcher(this.error).forward(request, response);
                        } catch (ServletException e) {
                            e.printStackTrace();
                        }
                    }
                    
                }
            }
    
        tld:
           <tag>
                   <name>refer</name>
                 <tag-class>com.suse.simpletag.Reference</tag-class>
                 <body-content>scriptless</body-content>
                 <attribute>
                     <name>url</name>
                     <required>true</required>
                     <rtexprvalue>true</rtexprvalue>
                 </attribute>
                 <attribute>
                     <name>error</name>
                     <required>true</required>
                     <rtexprvalue>true</rtexprvalue>
                 </attribute>
             </tag>
        jsp:
            <sky:refer error="/ad.jsp" url="http://localhost:8080/day_16/index.jsp">
            <a href="#">下载</a>
            </sky:refer>



       七】仿写forEach自定义标签

       code:
            //Foreach自定义标签
            //Connection类族:  <sky:forEach var="item" items="${list}">${item}</sky:forEach>   <sky:forEach var="item" items="${set}">${item}</sky:forEach>
            //Map类族:<sky:forEach var="en" items="map">${en.key} ----- ${en.value}</sky:forEach>
    
            public class ForEachTag extends SimpleTagSupport {
                
                /*用一个Collection类来进行转换*/
                private Collection coll;
                
                private Object items;
                private String var;
                public void setItems(Object items) {
                    /*设置coll的值:当为Collection类族时直接转换,否则保存Set<Entry<K,V>>形式的Connection*/
                    if (items instanceof Collection) {
                        coll = (Collection) items;
                    } else if(items instanceof Map) {
                        Map map = (Map) items;
                        coll = map.entrySet();
                    }
                }
                public void setVar(String var) {
                    this.var = var;
                }
                
                
                @Override
                public void doTag() throws JspException, IOException {
                    for (Iterator it = coll.iterator(); it.hasNext(); ) {
                        //得到单个对象
                        Object obj = (Object) it.next();
                        
                        //将单个对象放入域对象中
                        PageContext pageContext = (PageContext) this.getJspContext();
                        pageContext.getRequest().setAttribute(this.var, obj);
                        
                        //将标签封装的表达式输出到页面中
                        this.getJspBody().invoke(null);
                    }
                }
          
    
    
    
          tld:
             <tag>
                 <name>forEach</name>
                 <tag-class>com.suse.simpletag.ForEachTag</tag-class>
                 <body-content>scriptless</body-content>
                 <attribute>
                     <name>var</name>
                     <required>true</required>
                     <rtexprvalue>true</rtexprvalue>
                 </attribute>
                 <attribute>
                     <name>items</name>
                     <required>true</required>
                     <rtexprvalue>true</rtexprvalue>
                 </attribute>
             </tag>
    
          jsp:
                  <%
                    List<String> list = new ArrayList<String>();
                    list.add("jack");
                    list.add("merry");
                    list.add("berry");
                    list.add("sky");
                    
                    pageContext.setAttribute("LIST", list);
                    
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("id", "121010");
                    map.put("username", "jack");
                    map.put("age", "15");
                    
                    pageContext.setAttribute("MAP", map);
                %>
                <sky:forEach items="${LIST}" var="item">
                    ${item} &nbsp;&nbsp;
                </sky:forEach>
                <br />
                <sky:forEach items="${MAP}" var="en">
                    ${en.key}:${en.value} <br />
                </sky:forEach>




        八】过滤器(防止恶意JS代码)

      code:
            //<simple:filter>标签处理类
            public class FilterTag extends SimpleTagSupport {
                public void doTag() throws JspException, IOException {
                    JspFragment jspFragment = this.getJspBody();
                    StringWriter writer = new StringWriter();
                    jspFragment.invoke(writer);
                    String temp = writer.getBuffer().toString();
                    //结果必定是转义后的字符串
                    temp = filter(temp);
                    PageContext pageContext = (PageContext) this.getJspContext();
                    pageContext.getOut().write(temp);
                }
                public String filter(String message) {
                    if (message == null)
                        return (null);
                    char content[] = new char[message.length()];
                    message.getChars(0, message.length(), content, 0);
                    StringBuffer result = new StringBuffer(content.length + 50);
                    for (int i = 0; i < content.length; i++) {
                        switch (content[i]) {
                        case '<':
                            result.append("&lt;");
                            break;
                        case '>':
                            result.append("&gt;");
                            break;
                        case '&':
                            result.append("&amp;");
                            break;
                        case '"':
                            result.append("&quot;");
                            break;
                        default:
                            result.append(content[i]);
                        }
                    }
                    return (result.toString());
                }
            }



  • 相关阅读:
    4.1.7 POD对象
    异常处理
    POJ3167 Cow Patterns [KMP]
    POJ1961 Period [KMP应用]
    POJ2778 DNA Sequence [AC自动机+矩阵]
    HDU2243 考研路茫茫——单词情结 [AC自动机+矩阵]
    POJ2185 Milking Grid [KMP应用]
    POJ2541 Binary Witch [状态压缩]
    ZOJ3430 Detect the Virus [AC自动机]
    POJ2752 Seek the Name, Seek the Fame [KMP]
  • 原文地址:https://www.cnblogs.com/SkyGood/p/4064074.html
Copyright © 2011-2022 走看看