扩展SiteMesh支持WML

SiteMesh 是opensymphony开源组织下一款优秀的Java组件,一般用于页面模板装饰,以减少重复的视图代码为目的。

SiteMesh目前最新版本2.4.1,对HTML页面支持良好,不支持WML页面的装饰。

 

集成SiteMesh到web application较为简单,在这里假设读者熟悉SiteMesh用于HTML的装饰,如果读者不太了解SiteMesh的用法,请查阅官方相关文档。下面简单列出SiteMesh的使用步骤:

 

一、SiteMesh用法

1.1 web.xml文件配置过滤器

	<!--sitemesh filter-->

	<filter>
		<filter-name>sitemesh</filter-name>
		<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>sitemesh</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>REQUEST</dispatcher>
	</filter-mapping>

 

1.2 配置sitemesh.xml文件

<sitemesh>
    <property name="decorators-file" value="/WEB-INF/decorators.xml"/>

    <excludes file="${decorators-file}"/>

    <page-parsers>
        <parser default="true" class="com.opensymphony.module.sitemesh.parser.HTMLPageParser"/>

        <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.HTMLPageParser"/>

        <parser content-type="text/html;charset=UTF-8" class="com.opensymphony.module.sitemesh.parser.HTMLPageParser"/>
    </page-parsers>

    <decorator-mappers>

        <mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">
		<param name="property.1" value="meta.decorator" />
		<param name="property.2" value="decorator" />
	</mapper>

        <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
            <param name="config" value="${decorators-file}"/>
        </mapper>

    </decorator-mappers>

</sitemesh>

 

1.3 decorators.xml 文件

 

<decorators defaultdir="/view/decorators">
    <excludes>
        <pattern>/resources/*</pattern>
    </excludes>
   
    <decorator name="system" page="system.jsp"/>
   
    <decorator name="background" page="background.jsp"/>

    <decorator name="wml" page="wml.jsp"/>

</decorators>

 

1.4 具体装饰模板

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator"%>
<%@ page pageEncoding="utf-8" %>

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

    <head>
        <link rel="stylesheet" type="text/css" media="all" href="styles/default/theme.css" />
	<script language="javascript" src="scripts/jquery/jquery-min.js"></script>

        <decorator:head/>
        <title><decorator:title/>|title test</title>
    </head>
    
	<body
		<decorator:getProperty property="body.id" writeEntireProperty="true"/>
		<decorator:getProperty property="body.class" writeEntireProperty="true"/>>
		
		<jsp:include page="/view/common/messages.jsp"/>
		        	
		<decorator:body/>
				
                 <jsp:include page="/view/html/common/footer.jsp"/>				
	</body>
	
</html>
 

1.5 视图页面

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    
<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8" %>
<%@ include file="/view/common/taglibs.jsp" %>
<%@ page import="org.apache.shiro.SecurityUtils" %>

<html>
	<head>
		<meta name="decorator" content="system"/>
		<title>bye!</title>
	</head>	
	
	<body>
		XXXXXXXXXXXXXXXX
	</body>
</html>
 

 

以上是SiteMesh针对HTML页面的用法,下面扩展SiteMesh以实现对WML页面的支持

 

2扩展SiteMesh以实现对WML页面的支持

 

2.1 实现com.opensymphony.module.sitemesh.PageParser

 

package com.wearereading.frameworks.sitemesh.wml;

import java.io.IOException;

import com.opensymphony.module.sitemesh.Page;
import com.opensymphony.module.sitemesh.PageParser;
import com.opensymphony.module.sitemesh.html.HTMLProcessor;
import com.opensymphony.module.sitemesh.html.State;
import com.opensymphony.module.sitemesh.html.rules.HeadExtractingRule;
import com.opensymphony.module.sitemesh.html.rules.MetaTagRule;
import com.opensymphony.module.sitemesh.html.rules.TitleExtractingRule;
import com.opensymphony.module.sitemesh.html.util.CharArray;

/**
 * WML页面解析
 * @author Aspen
 *
 */
public class WMLPageParser implements PageParser {
	
    public Page parse(char[] data) throws IOException {
        CharArray head = new CharArray(64);
        CharArray card = new CharArray(4096); //cards TODO 暂只支持一个CARD
        TokenizedWMLPage page = new TokenizedWMLPage(data, card, head);
        
        HTMLProcessor processor = new HTMLProcessor(data, card);
        State wml = processor.defaultState();

        // Core rules for SiteMesh to be functional.
        wml.addRule(new HeadExtractingRule(head)); // contents of <head>
        wml.addRule(new CardTagRule(page, card)); // contents of <card>
        wml.addRule(new TitleExtractingRule(page)); // the <title>
        wml.addRule(new MetaTagRule(page));   // all <meta> tags

        processor.process();
        return page;
    }

}

 

package com.wearereading.frameworks.sitemesh.wml;

import com.opensymphony.module.sitemesh.html.BasicRule;
import com.opensymphony.module.sitemesh.html.Tag;
import com.opensymphony.module.sitemesh.html.rules.PageBuilder;
import com.opensymphony.module.sitemesh.html.util.CharArray;

/**
 * 
 * @author Aspen
 *
 */
public class CardTagRule extends BasicRule{
	
    private final PageBuilder page;
    private final CharArray card;

    public CardTagRule(PageBuilder page, CharArray card) {
        super("card");
        this.page = page;
        this.card = card;
    }

    public void process(Tag tag) {
        if (tag.getType() == Tag.OPEN || tag.getType() == Tag.EMPTY) {
            for (int i = 0; i < tag.getAttributeCount(); i++) {
                page.addProperty("card." + tag.getAttributeName(i), tag.getAttributeValue(i));
            }
            card.clear();
        } else {
            context.pushBuffer(new CharArray(64)); 
        }
    }

}

 

2.2 扩展com.opensymphony.module.sitemesh.Page

 

package com.wearereading.frameworks.sitemesh.wml;

import java.io.IOException;
import java.io.Writer;

import com.opensymphony.module.sitemesh.Page;

/**
 * WML page
 * @author Aspen
 *
 */
public interface WMLPage extends Page{
	
    /**
     * Write the contents of the <code>&lt;head&gt;</code> tag.
     */
    void writeHead(Writer out) throws IOException;

    /**
     * Convenience method to return the contents of the <code>&lt;head&gt;</code> tag as a String.
     */
    String getHead();
	
}
 
package com.wearereading.frameworks.sitemesh.wml;

import java.io.IOException;
import java.io.Writer;

import com.opensymphony.module.sitemesh.parser.AbstractPage;

/**
 * 
 * @author Aspen
 *
 */
public abstract class AbstractWMLPage extends AbstractPage implements WMLPage {

    public abstract void writeHead(Writer out) throws IOException;

}
 
package com.wearereading.frameworks.sitemesh.wml;

import java.io.IOException;
import java.io.Writer;

import com.opensymphony.module.sitemesh.html.rules.PageBuilder;
import com.opensymphony.module.sitemesh.html.util.CharArray;

/**
 * 
 * @author Aspen
 *
 */
public class TokenizedWMLPage extends AbstractWMLPage implements PageBuilder {
	
	private CharArray[] cards;
	
    private CharArray head;
    
    public TokenizedWMLPage(char[] original, CharArray[] cards, CharArray head) {
        this.pageData = original;
        this.cards = cards;
        this.head = head;
        addProperty("title", "");
    }
    
    public TokenizedWMLPage(char[] original, CharArray card, CharArray head){
    	this(original,new CharArray[]{card},head );
    }
    
    public void writeHead(Writer out) throws IOException {
        out.write(head.toString());
    }

    public void writeBody(Writer out) throws IOException {
    	for( int i=0;i<cards.length;i++)
    		out.write(cards[i].toString());
    }

    public String getHead() {
        return head.toString();
    }

    public String getBody() {
    	StringBuffer body = new StringBuffer();
    	for( int i=0;i<cards.length;i++)
    		body.append(cards[i].toString());
    	
        return body.toString();
    }

    public String getPage() {
        return new String(pageData);
    }

}

 

2.3 CARD标签

 

package com.wearereading.frameworks.sitemesh.wml;

import com.opensymphony.module.sitemesh.taglib.AbstractTag;

/**
 * 
 * @author Aspen
 *
 */
public class CardTag extends AbstractTag {
    
	private static final long serialVersionUID = 1L;

	public final int doEndTag() {
        try {
        	getPage().writeBody(getOut());
        }
        catch (Exception e) {
            trace(e);
        }
        return EVAL_PAGE;
    }

}

 

  2.4 扩展SiteMesh 过滤器

 

package com.wearereading.frameworks.sitemesh.wml;

import javax.servlet.FilterConfig;

import com.opensymphony.module.sitemesh.Config;
import com.opensymphony.module.sitemesh.Factory;
import com.opensymphony.sitemesh.ContentProcessor;
import com.opensymphony.sitemesh.webapp.SiteMeshFilter;
import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext;

/**
 * 扩展支持WML
 * @author Aspen
 *
 */
public class WMLSupportedSiteMeshFilter extends SiteMeshFilter{
	
	private FilterConfig filterConfig;
	
    public void init(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
        super.init(filterConfig);
    }

    public void destroy() {
        filterConfig = null;
        super.destroy();
    }
	
    protected ContentProcessor initContentProcessor(SiteMeshWebAppContext webAppContext) {
        Factory factory = Factory.getInstance(new Config(filterConfig));
        factory.refresh();
        return new WMLPageParser2ContentProcessor(factory);
    }
	
} 
package com.wearereading.frameworks.sitemesh.wml;

import java.io.IOException;

import com.opensymphony.module.sitemesh.Factory;
import com.opensymphony.module.sitemesh.HTMLPage;
import com.opensymphony.module.sitemesh.Page;
import com.opensymphony.module.sitemesh.PageParser;
import com.opensymphony.module.sitemesh.filter.HttpContentType;
import com.opensymphony.sitemesh.Content;
import com.opensymphony.sitemesh.SiteMeshContext;
import com.opensymphony.sitemesh.compatability.HTMLPage2Content;
import com.opensymphony.sitemesh.compatability.PageParser2ContentProcessor;

/**
 * 
 * @author Aspen
 *
 */
public class WMLPageParser2ContentProcessor extends PageParser2ContentProcessor {

	private final Factory factory;
	
	public WMLPageParser2ContentProcessor(Factory factory) {
		super(factory);
		this.factory=factory;
	}

    public Content build(char[] data, SiteMeshContext context) throws IOException {
        HttpContentType httpContentType = new HttpContentType(context.getContentType());
        PageParser pageParser = factory.getPageParser(httpContentType.getType());
        Page page = pageParser.parse(data);
        if( page instanceof WMLPage)
        	return new WMLPage2Content((WMLPage) page);
        
        return new HTMLPage2Content((HTMLPage) page);        
    }
    
}
 
package com.wearereading.frameworks.sitemesh.wml;

import java.io.IOException;
import java.io.Writer;

import com.opensymphony.sitemesh.Content;

/**
 * 
 * @author Aspen
 *
 */
public class WMLPage2Content implements Content {
	
	private final WMLPage page;
	
	public WMLPage2Content( WMLPage page ){
		this.page = page;
	}

   public void writeOriginal(Writer out) throws IOException {
        page.writePage(out);
    }

    public int originalLength() {
        return page.getContentLength();
    }

    public void writeBody(Writer out) throws IOException {
        page.writeBody(out);
    }

    public void writeHead(Writer out) throws IOException {
        page.writeHead(out);
    }

    public String getTitle() {
        return page.getTitle();
    }

    public String getProperty(String name) {
        return page.getProperty(name);
    }

    public String[] getPropertyKeys() {
        return page.getPropertyKeys();
    }

    public void addProperty(String name, String value) {
        page.addProperty(name, value);
    }

}

 

SiteMesh支持装饰HTML和WML的用法

需要上传的附件(sitemesh-2.4.1-wml-0.9.jar),你也可以使用上述源代码。

 

3.1 web.xml

 

	<!--sitemesh filter-->
	<filter>
		<filter-name>sitemesh</filter-name>
		<filter-class>com.wearereading.frameworks.sitemesh.wml.WMLSupportedSiteMeshFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>sitemesh</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>REQUEST</dispatcher>
	</filter-mapping>


3.2 sitemesh.xml

 

<sitemesh>
    <property name="decorators-file" value="/WEB-INF/decorators.xml"/>
    <excludes file="${decorators-file}"/>
    <page-parsers>
        <parser default="true" class="com.opensymphony.module.sitemesh.parser.HTMLPageParser"/>
        <
parser content-type="text/vnd.wap.wml" class="com.wearereading.frameworks.sitemesh.wml.WMLPageParser"/>
        <parser content-type="text/vnd.wap.wml;charset=UTF-8" class="com.wearereading.frameworks.sitemesh.wml.WMLPageParser"/>
        <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.HTMLPageParser"/>
        <parser content-type="text/html;charset=UTF-8" class="com.opensymphony.module.sitemesh.parser.HTMLPageParser"/>
    </page-parsers>

    <decorator-mappers>
        <mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">
		<param name="property.1" value="meta.decorator" />
		<param name="property.2" value="decorator" />
	</mapper>

        <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
            <param name="config" value="${decorators-file}"/>
        </mapper>
    </decorator-mappers>
</sitemesh>
 

3.3 装饰模板

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">

<%@ page contentType="text/vnd.wap.wml;charset=UTF-8"%>
<%@ taglib uri="http://www.wearereading.com/frameworks/sitemesh/wml/decorator" prefix="wml-decorator"%>

<wml>
	<head>	
		<decorator:head/>
		<meta name="keyword" content="WAP"/>
	</head>
	
	<card <decorator:getProperty property="card.id" writeEntireProperty="true" /> <decorator:getProperty property="card.title" writeEntireProperty="true"/>>
		<jsp:include page="/view/wml/common/header.jsp" />
		
		<wml-decorator:card/>
		
		<jsp:include page="/view/wml/common/footer.jsp" />
	</card>
</wml>

 

 

你可能感兴趣的:(html,jquery,xml,jsp,WAP)