flexigrid结合SSH常见问题及使用笔记

来源:互联网 发布:端口扫描器怎么用 编辑:程序博客网 时间:2024/05/21 09:31

【注】常见问题和需要重点注意的地方,已用红色高亮标出

一、flexigrid和SSH相关介绍

1.flexigrid for JQuery的官方网站(http://flexigrid.info/)

2.Flexigrid百度给出的词条

Flexigrid是一个类似于Ext Gird,但基于jQuery开发的Grid。它具有的功能包括:可以调整列宽,合并列标题,分页,排序,显示/隐藏表格等。Flexigrid显示的数据能够通过Ajax获取或者从一个普通的表格转换。

3.SSH为Java进行web开发的Struts 2.x spring hibernate 三大框架的简称,这里同时还是用到了JSON数据格式来传递数据。

二、下面言归正传,开始集成flexigrid

1.      我们最终想要实现的效果为下图所示:


图表1

我们可以看到实现的效果中,主要分操作工作区(这里指——增删改)、标题区(即显示数据的标题)、数据区(显示查询的数据)、搜索功能区(开始为隐藏,用来根据条件来搜索)、显示数据的控制功能区(控制每页显示信息条数、上一页、下一页、刷新数据、提示)。

2.      首先我们应该到相关的官网上下载我们需要的所有的包(JQuery、Flexigrid)。

3.      下载完成后,我们就可以开始向着我们需要的方向前进了,我们先编写一个html文档,格式大概为下面的内容:

<body>    <divid="parent"><divalign="center">        </div><tableid="flexme"></table>    </div></body>

flexme就是指的要使用flexigrid的地方,之所以会有#parent,我想朋友们应该理解,因为我们需要控制整体的flexme,所以在外面再包一层。

当然我们不能忽略了引入包的问题,因为刚才我们已经下载JQueryFlexigrid的包,都解压好以后,放到工程目录中。这里注意我们需要先引入JQuery,然后才引入flexigridjavascriptcss包。

4.      做完上面的一步,就代表我们需要在html文件中做的工作,已经做完了,剩下的就是开始在javascript文件中完成了。大家如果有疑惑,可以了解一下flexigrid官方网站上给出的例子,最好用chrome或者firefox看一下例子源码。

我在这里进行了小范围的二次开发,即函数封装,我们只需要按要求传入下面的所有的参数,而不需要关心具体的flexigrid的设置,可以多次调用。所以这里我新建一个util.js文件,文件中的具体内容如下:

//JavaScript Document/* * author: 小森(http://weibo.com/jingmoxiaosen) * 参数解释 * ajaxurl 对应下边的url,即获取初次数据的ajax的url * args 指要显示的列名,即要展示的数据的标头的名字,可组合成colModel的json格式 * title 指显示在表格上面的提示,对应下边的title * searchitems 指要设置可以用来搜索的部分,组合成json后对应下边的searchitems * delurl 对应要进行删除操作的url(SSH对应的一个action) * addurl 对应进行添加和编辑操作的url(对应jsp页面) * */function initflexifrid(ajaxurl,args,title,searchitems,delurl,addurl){    /*根据传入的参数数组,封装成JSON格式,因为flexigrid使用的JSON格式的形式*/    var cols ="[";    cols = cols + "{display:'" + args[0] + "', name: '" + args[0] +"', width: 40, sortable: true, align:'center'},";    for(var i = 1; i < args.length - 1; i++){       cols = cols + "{display:'" + args[i] + "', name: '" + args[i] +"', width: 200, sortable: true, align:'left'},";    }    cols = cols + "{display:'" + args[args.length - 1] + "', name: '" + args[args.length - 1] +"', width:200, sortable: true, align: 'left'}]";    var cols = eval("("+cols+")");//转化成json格式       var items ="[";    for (var i = 0; i < searchitems.length - 1; i++)    {       items = items + "{display:'" + searchitems[i] + "' , name: '"+searchitems[i] +"'},";    }    items = items + "{display:'" + searchitems[searchitems.length - 1] +"' , name: '"+searchitems[searchitems.length - 1] +"', isdefault: true } ]";    var items = eval("("+ items +")");//转化成json格式     //初始化flexigrid插件    $('#flexme').flexigrid({//flexme就是刚才在html文件中创建的table的id       url: ajaxurl,       dataType: 'json',       colModel : cols,       buttons : [//操作功能区,onpress对应他们相应的js操作函数,下面有函数体           {name: '增加', bclass:'add',onpress:button},           {name: '删除', bclass:'delete',onpress:button},           {name: '编辑', bclass:'edit',onpress:button},           {separator: true}           ],       searchitems : items,//搜索功能区       sortname: "id",//默认使用id排序       sortorder: "asc",//默认排序方式为递增       procmsg: "正在加载...",       pagestat: '显示 {total}中 {from} 到 {to} 的元素',       nomsg: '没有数据',       errormsg: '链接失败',       usepager: true,//是否使用分页       title: title,       useRp: true,       rp: 10,//每页显示信息的条数       showTableToggleBtn: true,//是否显示上一页、下一页的按钮       width: 640,       height: 300,    });      //button的事件函数    function button(com,grid)      {       if (com=='删除')             {                   if($('.trSelected',grid).length==0){                    alert("请选择要删除的数据");                }else{                    if(confirm('是否删除这 ' + $('.trSelected',grid).length +' 条记录吗?'))                    {                      var id = "mulid=";                      for(var i=0;i<$('.trSelected',grid).length;i++){                       if(i==$('.trSelected',grid).length-1){                           id += $('.trSelected',grid).find("td:first").eq(i).text();                      } else {                           id += $('.trSelected',grid).find("td:first").eq(i).text()+",";                       }                      }                     window.location.href= delurl +"!delete.action?"+id;                  }                }             }         elseif (com=='增加')             {                window.location.href= addurl;            }         elseif (com=='编辑')         {             if($(".trSelected").length==1){                var getargs ="?";              for(var i = 0; i < args.length - 1; i++){                  getargs = getargs + args[i] +"="+$('.trSelected',grid).find("td").eq(i).text()+"&";              }              getargs = getargs + args[args.length-1] +"=" + $('.trSelected',grid).find("td").eq(args.length-1).text();              window.location.href = addurl + getargs;            }elseif($(".trSelected").length > 1){                alert("请选择一个修改,不能同时修改多个");             }elseif($(".trSelected").length==0){                alert("请选择一个您要修改的内容")             }         }      } }

有几点我们需要注意:【1】将传递过来的数组参数组装成JSON格式时,我们需要在前后加上”[””]”,这是JSON的格式要求,同时,我们组装完成后,需要使用JS的函数eval来完成转换,具体看上面的例子;【2dataType的值为’json’,这是我使用的方式,还可以选择’xml’格式。

5.      这样子以后,我们就已经把使用flexigrid的js操作封装好了,当然我们需要的是在刚才新建的那个html文件加载完成时,就执行现在我们完成的js,所以我们需要新建对应的html的js文件friendlink.js,内容如下:

// JavaScript Document$(document).ready(function() {//在html加载时,自动完成的操作    var ajaxurl ='/****/friendlinkAction!getAllFriendlink.action';    varargs= new Array();    args[0]='id';    args[1]='text';    args[2]='link';    title = '友情链接';    var searchitems =new Array();    searchitems[0] = 'link';    searchitems[1] = 'text';    delurl = '/****/friendlinkAction';    addurl = '/****/manager/friendlink/addfriendlink.jsp';    initflexifrid(ajaxurl,args,title,searchitems,delurl,addurl);//这里就是我们调用的封装的函数});

然后我们引入把这些文件都引入到html中,如何引入不再赘述,但是要注意引入顺序:JQuery->flexigrid->util.js->friendlink.js

6.      至此,我们所有的前台的操作已经基本完成了,我们可以开始做后台的SSH操作了,我们需要做什么呢?

这里关于导入SSH包,hibernate反转sql就不做说明了。在此,我们假设你已经得到了DAO文件和其他相关的配置文件。

编编写编写后台的Action走起,我们新建一个class文件,然后我们需要做的就是理一下我们的思绪。因为我们要弄清楚,我们需要什么后台接受什么参数,前台需要从后台得到什么数据等问题。当我们开始看官方给出的例子时,我们发现,其实后台需要的参数还是蛮多的,因为我们需要分页显示、需要每一页具体显示多少条信息、需要删除那些行、按照什么方式排序、按什么排序、按什么方式搜索、按什么条件搜索等等,前台还需要共有多少数据等,所以我查看了一下官方的例子(因其前台的name都是自动生成),总结出需要的参数为当前页(page)、共有多少条数据(total)、每页显示信息条数(rp)、搜索条件(query)、搜索方式(qtype)、排序方式(sortorder)、排序条件(sortname),还需要返回给前台的JSON数据(List的对象rows)。当然我们需要操作删除操作,就必须要获取已经选中的数据的id,这里我以字符串的形式get方式传递的,以”,”进行分割(mulid),全部生成对应的gettersetter方法。

下面为具体代码:(参数对应上面所述参数传递说明)

@Controller("friendlinkAction")@Namespace("/")@Scope("prototype")public classFriendlinkAction {private List<Map> rows = new ArrayList();private int page;private int total;private int rp;private List<Friendlink> list;private String mulid;private String query;private String qtype;private String sortname;private String sortorder;private Map map=new HashMap(); public Friendlink friendlink = newFriendlink();@Autowiredprivate FriendlinkService flService;@JSON(serialize=false)public String getAllFriendlink(){        if (query == null ||("").equals(query)){               total =GetPagedata.getCount("Friendlink");               if ((Integer)page == null || page< 1)                      page = 1;               else if (page > (total/rp+1)){                      page = total/rp;               }               int start = (page-1)*rp;               list = GetPagedata.getData("Friendlink",start,rp,sortname,sortorder);               for (Friendlink temp : list){                      map = new HashMap();                      map.put("cell",new Object[]{temp.getId(),temp.getText(),temp.getLink()});                      rows.add(map);               }        }else{               total = GetPagedata.getCount("Friendlink",query,qtype);               if ((Integer)page == null || page< 1)                      page = 1;               else if (page > (total/rp+1)){                      page = total/rp;               }               int start = (page-1)*rp;               list =GetPagedata.getData("Friendlink",query,qtype,start,rp,sortname,sortorder);               for (Friendlink temp : list){                      map = new HashMap();                      map.put("cell",new Object[]{temp.getId(),temp.getText(),temp.getLink()});                      rows.add(map);               }        }        return "success";}public String delete(){        flService.delete(mulid);        return "index";}public String addormerge(){        flService.addormerge(friendlink);        return "index";}

我们还需要配置struts.xml文档,因为我们需要返回JSON格式的数据,具体配置如下

<packagename="getjson"extends="json-default"namespace="/">       <actionname="friendlinkAction"class="friendlinkAction">           <resulttype="json"name="success">              <paramname="rows">rows</param>              <paramname="page">page</param>              <paramname="total">total</param>              <paramname="rp">rp</param>           </result>           <resultname="index">/manager/friendlink/friendlink.html</result>       </action></package>

这里为我们需要返回给前台ajaxJSON格式数据和普通数据,当然如果有些数据我们不想要返回,我们需要在action中的get*()方法前面加上@JSON(serialize=false),这样数据就不会传递了,减小网络传输压力,也避免不必要的数据被用户看到。

7.      具体的操作截图和解释如下:


图表2—添加操作

 

图表3—添加成功


图表4—删除一条数据操作


图表5—删除多条数据操作


图表6—不可同时编辑多条数据


图表7—看到我们编辑成功(对比图表3)


图表8—设置每一页显示的信息条数


图表9—按照条件搜索

三、常见问题跟踪(flexigrid使用常见问题)

1.    我们在firefox中的firebug跟踪时,已经看到了传递过来的JSON数据,显示全是undefined。

解决方法:我们需要仔细查看一下firebug下的json数据格式(特别是rows),看看是不是符合格式,将获得数据list需要转化为如下格式的json数据:[{‘cell’:*,*,*}, {‘cell’:*,*,*}, {‘cell’:*,*,*}],代码操作应该为:

list =GetPagedata.getData("Friendlink",start,rp,sortname,sortorder);           for (Friendlink temp :list){              map =newHashMap();              map.put("cell",new Object[]{temp.getId(),temp.getText(),temp.getLink()});              rows.add(map);        }

2.    网上也有朋友写的好像是有些问题,其json格式为[{‘id’:*,’cell’: *,*},{‘id’:*,’cell’: *,*}],测试了一下,这样子好像不行,当然我也不能完全确定,就当给大家提醒一下吧,不妨试试。

3.    获取数据成功后,无法进行分页操作。

这里我们首先,应该查看一下,我们在设置#flexme时 usepager:true(单击链接查看),是否已经设置为了true。如果这里已经设置成功,那我们就要确定一下,是不是已经在后台获取了rp、page等参数,如果没有获取就按照java 的action(单击链接查看)中的设置的方式弄一下。

4.    无法获取数据,表格显示不出来。

这个问题的话,可能就是我上面说的可能没有在后台获取相关的参数,可以按照参数说明(单击链接查看)这里的方法自己捉摸一下。

5.    为什么在添加、删除、编辑的按钮上没有图片

这个问题我也没有弄明白,为什么官方给的例子上有图片,自己的却没有。后来查看了一下他给的css文档,发现根本没有设置。当然了,这里可以理解,毕竟它也不知道你要有哪些按钮,按钮的名字有叫什么,它也不能智能生成css,所以这里需要我们自己来设置,自己在它给的css中设置一下就好了。代码如下:

.flexigrid div.fbutton .add{background:url(images/add.png)no-repeatcenterleft} .flexigrid div.fbutton.delete{background:url(images/close.png)no-repeatcenterleft}.flexigrid div.fbutton .edit{background:url(images/edit.png)no-repeatcenterleft}

6.    这里额外说一些可能在结合使用SSH的过程中,查询数据可能遇到的问题

(1)   hibernate中使用LIKE报错 unexception token: %

这里大致的解决方法,就是这样做:like ? 然后query.setParameter(0,"%"+q+"%");好像是因为hibernate不兼容的问题吧。

(2)   hibernate中使用limit时报错 unexception token:limit

这里是因为hibernate不允许使用limit,但是它也提供了相应的方法:

query.setFirstResult(start);query.setMaxResults(rp);

可以设置第一个数据和最大偏移量,和limit效果一样的。

(3)hibernate我们进行merge操作后,无法立即刷新数据,但是数据库中已经是新的数据,重启服务器发现可以显示出来。

解决方法:因为可能使用的是query.list()的方法获取数据,但是merge之后在一级缓存中的还是旧的数据,但是id是一样的,所以它就不会重新获取数据,这里我们可以在merge之后,这样操作:

Session session =HibernateSessionFactory.getSession();session.clear();session.close();