出家如初,成佛有余

jmesa 使用指南

Posted in Uncategorized by chuanliang on 2008/03/09

1、关于jmesa

  开始搭建新的基于struts2+spring+hibernate的技术架构,基于以前对eXtremeTable的好感,决定继续采用extremetable,而不选用displaytag和valuelist。用google搜索发现eXtremeTable的作者己不再更新eXtremeTable,其把精力转移到了新的项目-JMesa。

  However, now that JMesa is up to release 2.1 I am only focusing my efforts on that library. The JMesa API has really turned into the library I have always wanted to create. With the introduction of the tags and facade in release 2.1 building tables is now easier than ever. I would encourage developers that are able to run in a JDK1.5 and JSP2.0 container to start using JMesa. If you are interested in a full explanation about how JMesa came about you can read more on the JMesa site. If you are more interested in what JMesa offers over the eXtremeTable read the features list.

 

2、基于struts2+spring+hibernate+jquery的jmesa分页实现样例

2.1、需求场景

  基于Jmesa,从数据库表Person中查询出记录,能够实现分页、排序、导出功能。同时结合Jquery,利用ajax实现对数据的删除操作。

2.2、环境说明

Jmesa: 2.3

Struts2 :2.0.11

Spring:2.5

Hibernate:3.2.5

Jquery:jquery-1.2.1.pack,jquery.bgiframe.pack

Tomcat:5.5

Mysql :5.0

数据库、页面、JVM编码统一为GBK

2.3、数据库表结构

CREATE TABLE `person` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `firstName` varchar(45) NOT NULL,
  `lastName` varchar(45) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=76 DEFAULT CHARSET=latin1; 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

2.4、页面list.jsp

<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ page language="java" errorPage="/error.jsp" pageEncoding="GBK" contentType="text/html;charset=GBK" %>
<html>
<head>
<link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/css/web.css"></link>
<link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/css/jmesa.css"></link>
<!--
对jmesa.js脚本的应用必须放到头部,而不能放到尾部
-->
<script type="text/javascript" src="<%= request.getContextPath() %>/js/jmesa.js"></script>
</head>
<body>
<p>Jmesa表单组件使用演示样例</p>

<form name="personForm" action="<%= request.getContextPath() %>/list.action" method="post">
<div id="persons">
<%
    out.println(request.getAttribute("myhtml"));
%>
</div>
</form>

<script type="text/javascript">
function onInvokeAction(id) {
    setExportToLimit(id, '');
    createHiddenInputFieldsForLimitAndSubmit(id);
}
function onInvokeExportAction(id) {
    var parameterString = createParameterStringForLimit(id);
    location.href = '<%= request.getContextPath() %>/list.action?' + parameterString;
}


function delUser(tableId,rowId) {
    var parameterString = createParameterStringForLimit(tableId);
    $.get("<%= request.getContextPath() %>/ajax.action?id="+rowId+"&"+parameterString, function(data) {
        $("#persons").html(data)
    });

}
</script>
<script type="text/javascript" src="<%= request.getContextPath() %>/js/jquery-1.2.1.pack.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/js/jquery.bgiframe.pack.js"></script>

</body>
</html>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

2.4、Action代码

package com.mobilesoft.esales.webapp.action;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import jxl.demo.CSV;

import org.apache.commons.beanutils.BeanUtils;
import org.jmesa.facade.TableFacade;
import org.jmesa.facade.TableFacadeImpl;
import org.jmesa.limit.Limit;

import com.mobilesoft.esales.dao.hibernate.Person;
import com.mobilesoft.esales.service.PersonService;
import com.octo.captcha.service.CaptchaServiceException;
import com.opensymphony.xwork2.Action;
import static org.jmesa.limit.ExportType.CSV;
import static org.jmesa.limit.ExportType.JEXCEL;
import static org.jmesa.limit.ExportType.PDF;
import org.jmesa.core.filter.DateFilterMatcher;
import org.jmesa.core.filter.MatcherKey;
import org.jmesa.facade.TableFacade;
import org.jmesa.facade.TableFacadeImpl;
import org.jmesa.limit.Limit;
import org.jmesa.util.ItemUtils;
import org.jmesa.view.component.Column;
import org.jmesa.view.component.Row;
import org.jmesa.view.component.Table;
import org.jmesa.view.editor.BasicCellEditor;
import org.jmesa.view.editor.CellEditor;
import org.jmesa.view.editor.DateCellEditor;
import org.jmesa.view.html.HtmlBuilder;
import org.jmesa.view.html.component.HtmlColumn;
import org.jmesa.view.html.component.HtmlRow;
import org.jmesa.view.html.component.HtmlTable;
import org.jmesa.view.html.editor.DroplistFilterEditor;

import sun.text.CompactShortArray.Iterator;

/**
 * 用于演示基于jmesa(http://code.google.com/p/jmesa/)的分页、排序组件的使用方法,
 * 在src/java/com/mobilesoft/esales/dao/hibernate/person.sql有Person表的测试数据
 * @author <a href="mailto:liangchuan@mobile-soft.cn">liangchuan</a> 
 * @since 2008-03
 */
public class PersonAction extends BaseAction {
    private PersonService personService;
    private List<Person> persons;
    private Person person;
    private Integer id;
    private String tableId;



    public String execute() {
        this.persons = personService.findAll();
        //创建id为tableId为表单
        //<table id="tableId"  border="0"  cellpadding="0"  cellspacing="0"  class="table"  width="600px" >
        TableFacade tableFacade = new TableFacadeImpl("tableId", getRequest());
        //设定页面分页数据
        tableFacade.setItems(persons);
        //设定支持的查询结果导出格式为csv,excel,pdf格式
        tableFacade.setExportTypes(getResponse(), CSV, JEXCEL, PDF);
        tableFacade.setStateAttr("restore");
        Limit limit = tableFacade.getLimit();
        if (limit.isExported()) {
            export(tableFacade);
            return null;
        } else {
            String html = html(tableFacade);
            getRequest().setAttribute("myhtml", html);
        }
        return Action.SUCCESS;
    }

    private String html(TableFacade tableFacade) {
        // 设定表格属性,注意此处的url用于诸如增加、删除、修改、查询操作,并不是实际的数据库表属性,
        //但表单需要有对应的po对新,因此需要在Person中增加此属性
        tableFacade.setColumnProperties("id", "firstName", "lastName", "url");

        HtmlTable table = (HtmlTable) tableFacade.getTable();
        table.setCaption("测试用户信息列表");
        table.getTableRenderer().setWidth("600px");

        HtmlRow row = table.getRow();

        HtmlColumn id = row.getColumn("id");
        id.setTitle("id");

        HtmlColumn firstName = row.getColumn("firstName");
        firstName.setTitle("属性1");

        HtmlColumn lastName = row.getColumn("lastName");
        lastName.setTitle("属性2");

        HtmlColumn deleteAction = row.getColumn("url");
        deleteAction.setTitle("操作");

        // Using an anonymous class to implement a custom editor.
        // 用于演示在表格中增加超链接
        firstName.getCellRenderer().setCellEditor(new CellEditor() {
            public Object getValue(Object item, String property, int rowcount) {
                Object value = new BasicCellEditor().getValue(item, property,
                        rowcount);
                HtmlBuilder html = new HtmlBuilder();
                html.a().href().quote().append("http://www.mobile-soft.cn")
                        .quote().close();
                html.append(value);
                html.aEnd();
                return html.toString();
            }
        });

        // Using an anonymous class to implement a custom editor.
        //用于演示在表格中增加javascript操作,通过jquery来实现ajax式的删除操作
        deleteAction.getCellRenderer().setCellEditor(new CellEditor() {
            public Object getValue(Object item, String property, int rowcount) {
                Object value = new BasicCellEditor().getValue(item, property,
                        rowcount);
                HtmlBuilder html = new HtmlBuilder();
                //取得每一行的id号
                Object id = ItemUtils.getItemValue(item, "id");
                String js=" onclick='javascript:del("tableId","+id+") '";
                html.a().append(js).href().quote().append(getRequest().getContextPath()+"/remove.action?id="+id).quote().close();
                html.append("删除");
                html.aEnd();
                return html.toString();
            }
        });

        return tableFacade.render(); // Return the Html.
    }

    private void export(TableFacade tableFacade) {
        tableFacade.setColumnProperties("id", "firstName", "lastName");

        Table table = tableFacade.getTable();
        table.setCaption("Persons Test");

        Row row = table.getRow();

        Column id = row.getColumn("id");
        id.setTitle("id");

        Column firstName = row.getColumn("firstName");
        firstName.setTitle("First Name");

        Column lastName = row.getColumn("lastName");
        lastName.setTitle("Last Name");

        tableFacade.render();
    }

    public String login() {
        Boolean isResponseCorrect = Boolean.FALSE;
        // remenber that we need an id to validate!
        String captchaId = getSession().getId();
        // retrieve the response
        String response = getRequest().getParameter("j_captcha_response");
        // Call the Service method
        try {
            isResponseCorrect = CaptchaServiceSingleton.getInstance()
                    .validateResponseForID(captchaId, response);
        } catch (CaptchaServiceException e) {
            // should not happen, may be thrown if the id is not valid
        }
        if (!isResponseCorrect) {
            return Action.LOGIN;
        }
        return execute();
    }

    public String save() {
        this.personService.save(person);
        this.person = new Person();
        return execute();
    }
    /**
     * 用于演示ajax方式删除操作,参看pages/list.jsp
     * @return
     */
    public String remove() {
        String deleteId = getRequest().getParameter("id");

        if (deleteId != null) {
            personService.remove(Integer.parseInt(deleteId));
        }
        this.persons = personService.findAll();
        TableFacade tableFacade = new TableFacadeImpl("tableId", getRequest());
        tableFacade.setItems(persons); // set the items
        tableFacade.setExportTypes(getResponse(), CSV, JEXCEL, PDF);
        tableFacade.setStateAttr("restore");
        Limit limit = tableFacade.getLimit();
        if (limit.isExported()) {
            export(tableFacade);
            return null;
        } else {
            String html = html(tableFacade);
            getRequest().setAttribute("myhtml", html);
        }
        return Action.SUCCESS;

    }

    public List<Person> getPersons() {
        return persons;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void prepare() throws Exception {
        if (id != null)
            person = personService.find(id);
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    /**
     * @return the personService
     */
    public PersonService getPersonService() {
        return personService;
    }

    /**
     * @param personService
     *            the personService to set
     */
    public void setPersonService(PersonService personService) {
        this.personService = personService;
    }

    /**
     * @return the tableId
     */
    public String getTableId() {
        return tableId;
    }

    /**
     * @param tableId
     *            the tableId to set
     */
    public void setTableId(String tableId) {
        this.tableId = tableId;
    }

}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

2.5、Service、DAO层代码

  无特别的,省略

2.6、Model代码

 

package com.mobilesoft.esales.dao.hibernate;

/**
 * Person entity.
 * 
 * @author <a href="mailto:liangchuan@mobile-soft.cn">liangchuan</a>
 */

public class Person implements java.io.Serializable {

    // Fields

    private Integer id;
    private String firstName;
    private String lastName;
    private String url="";

    // Constructors

    /** default constructor */
    public Person() {
    }

    /** full constructor */
    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    // Property accessors

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    /**
     * @return the url
     */
    public String getUrl() {
        return url;
    }

    /**
     * @param url the url to set
     */
    public void setUrl(String url) {
        this.url = url;
    }

}

2.7、Struts.xml

 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <constant name="struts.objectFactory" value="spring"/>
    <constant name="struts.devMode" value="true"/>
    <constant name="struts.i18n.encoding" value="GBK"/>
    <constant name="struts.action.extension" value="action"/>
    <constant name="struts.custom.i18n.resources" value="ApplicationResources,errors"/>
    <constant name="struts.multipart.maxSize" value="2097152"/>
    <constant name="struts.multipart.saveDir" value="/resources"/>
    <constant name="struts.ui.theme" value="css_xhtml"/>
    <constant name="struts.enable.SlashesInActionNames" value="true"/>

    <package name="person" extends="struts-default">
     <interceptors>
            <!-- Copied from struts-default.xml and changed validation exclude methods -->
            <interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servlet-config"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="debugging"/>
                <interceptor-ref name="profiling"/>
                <interceptor-ref name="scoped-model-driven"/>
                <interceptor-ref name="model-driven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="static-params"/>
                <interceptor-ref name="params">
                    <param name="excludeParams">dojo..*</param>
                </interceptor-ref>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">cancel,execute,delete,edit,list</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
            </interceptor-stack>
            <interceptor-stack name="fileUploadStack">
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
        </interceptors>
        <global-results>
            <result name="mainMenu" type="redirect">mainMenu.html</result>
            <result name="dataAccessFailure">pages/dataAccessFailure.jsp</result>
        </global-results>

        <global-exception-mappings>
            <exception-mapping exception="org.springframework.dao.DataAccessException" result="dataAccessFailure"/>
        </global-exception-mappings>

        <action name="list" method="execute" class="personAction">
            <result name="success">pages/list.jsp</result>
            <result name="input">pages/list.jsp</result>
        </action>

        <action name="remove" class="personAction" method="remove">
            <result name="success">pages/list.jsp</result>
            <result name="input">pages/list.jsp</result>
        </action>

        <action name="save" class="personAction" method="save">
            <result name="success">pages/list.jsp</result>
            <result name="input">pages/list.jsp</result>
        </action>

        <action name="login" class="personAction" method="execute">
            <result name="success">pages/list.jsp</result>
            <result name="login">/index.jsp</result>
        </action>

        <action name="uploadFile"
            class="com.mobilesoft.esales.webapp.action.FileUploadAction">
            <interceptor-ref name="fileUploadStack"/>
            <result name="input">pages/uploadForm.jsp</result>
            <result name="success">pages/uploadDisplay.jsp</result>
            <result name="cancel" type="redirect">/index.jsp</result>
        </action>

    </package>

</struts>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

3、jmesa研究

<TBC>

 

4、参考资料

http://code.google.com/p/jmesa/w/list

http://blog.csdn.net/jockCreate/archive/2008/02/20/2110310.aspx

http://blog.csdn.net/czg18596/archive/2007/09/06/1774827.aspx

http://www.javaeye.com/post/362673

No Responses Yet

Subscribe to comments with RSS.

  1. hoho said, on 2008/03/09 at 13:03

    一个感想

    好长啊

  2. gonggt said, on 2008/03/10 at 16:04

    你好。 我也在练习使用jmesa,
    你可以给我发送一份你的源代码吗? 谢谢
    E_Mail : ggt87125@163.com

  3. pysky said, on 2008/05/05 at 17:20

    我也在学习jmesa,可以发送一份比较完整的Demo版本吗?
    在线等,急切盼望中.

  4. tyz said, on 2008/06/05 at 09:01

    刚刚接触jmesa,看了官方网站上的用例,不过太多,看的不是太明白,能不能把你的源码发给我一份呢!!!谢谢啊,我的邮箱是:310628570@163.com

  5. xianhui said, on 2008/06/05 at 14:45

    对Jmesa很有兴趣,根据您的文档做了例子运行报错,是否可以给份源码,谢谢!small_knight@hotmail.com

  6. jamcson said, on 2008/06/06 at 15:58

    这份代码楼主自己都没跑过

  7. zz said, on 2008/06/24 at 17:25

    我也在做jmesa基本都行就是让tbody部分滚动起来有点不行,ie不支持,谁能解决?

  8. Red84 said, on 2009/10/22 at 23:18

    Muslim speech just before the elections and after that the BJP gave him a ticket to contest. ,


发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: