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("" + "ip:" + ip + "");
            }

            @Override
            public JspTag getParent() {
                return null;
            }

            @Override
            public void setJspBody(JspFragment arg0) {  
            }


            @Override
            public void setParent(JspTag arg0) {
            }
        }

 



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

       

        
            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">
            
          JSTL 1.1 core library
          JSTL core
          1.1
          <short-name>skyshort-name>
          http://com.suse/jsp/jstl/sky
          
          
            ip
            class>com.suse.simpletag.Democlass>
            empty 
          
        

 

 



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

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

        

 

 



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

四、案例:
    一】控制标签中的内容是否执行( 标签 )
        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:
             
                  execute
                  class>com.suse.simpletag.ExecuteTagclass>
                  scriptless       
             

 

 


    二】控制标签后的内容是否执行
        方法:抛出 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:
              
                  skip
                  class>com.suse.simpletag.SkipTagclass>
                  scriptless
              

 

 




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

    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:
        
             forskip
             class>com.suse.simpletag.ForSkipclass>
             scriptless
             
                 var
                 true
                 true
             
             
                 begin
                 true
                 true
             
             
                 end
                 true
                 true
             
             
                 step
                 false
                 true
             
        
    jsp:
        
            ${item}   &nbsp;
        

 

 



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

  code:
        //1,  content 
        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, content 
        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,content
        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:
         
             choose
             class>com.suse.simpletag.ChooseTagclass>
             scriptless
         
         
             while
             class>com.suse.simpletag.WhileTagclass>
             scriptless
             
                 test
                 true
                 true
             
         
        
         
             otherwise
             class>com.suse.simpletag.OtherWiseTagclass>
             scriptless
         
    jsp:
        <%
        pageContext.setAttribute("age", 25);
        %>
        
            while test="${age > 16}">
                你成年了
while> 你未成年

 

 



    六】防盗链

  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:
       
               refer
             class>com.suse.simpletag.Referenceclass>
             scriptless
             
                 url
                 true
                 true
             
             
                 error
                 true
                 true
             
         
    jsp:
        
        下载
        

 

 



   七】仿写forEach自定义标签

   code:
        //Foreach自定义标签
        //Connection类族:  ${item}   ${item}
        //Map类族:${en.key} ----- ${en.value}

        public class ForEachTag extends SimpleTagSupport {
            
            /*用一个Collection类来进行转换*/
            private Collection coll;
            
            private Object items;
            private String var;
            public void setItems(Object items) {
                /*设置coll的值:当为Collection类族时直接转换,否则保存Set>形式的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:
         
             forEach
             class>com.suse.simpletag.ForEachTagclass>
             scriptless
             
                 var
                 true
                 true
             
             
                 items
                 true
                 true
             
         

      jsp:
              <%
                List list = new ArrayList();
                list.add("jack");
                list.add("merry");
                list.add("berry");
                list.add("sky");
                
                pageContext.setAttribute("LIST", list);
                
                Map map = new HashMap();
                map.put("id", "121010");
                map.put("username", "jack");
                map.put("age", "15");
                
                pageContext.setAttribute("MAP", map);
            %>
            
                ${item}  &nbsp;
            
            
${en.key}:${en.value}

 

 




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

  code:
        //标签处理类
        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("<");
                        break;
                    case '>':
                        result.append(">");
                        break;
                    case '&':
                        result.append("&");
                        break;
                    case '"':
                        result.append(""");
                        break;
                    default:
                        result.append(content[i]);
                    }
                }
                return (result.toString());
            }
        }

 

 



转载于:https://www.cnblogs.com/SkyGood/p/4064074.html

你可能感兴趣的:(JSP自定义标签)