zoukankan      html  css  js  c++  java
  • 【SSH网上商城项目实战07】Struts2和Json的整合

     上一节我们完成了DataGrid显示jason数据,但是没有和后台联系在一起,只是单纯地显示了我们自己弄的json数据,这一节我们将json和Struts2整合,打通EasyUI和Struts2之间的交互。

    1. json环境的搭建

            json环境搭建很简单,导入json的jar包即可,如下:

            (注:json-lib-2.4的jar包下载地址:http://download.csdn.net/detail/eson_15/9514985 )

    2. 完善Action

            在DataGrid控件中有个属性是url,可以指定请求数据的url地址,在上一节我们将这个地址直接设置成了一个具体的json文件,这里我们将这个url设置成一个action,如url:'category_queryJoinAccount.action',表示会去请求categoryAction的queryJoinAccount方法(文章最后会给出query.jsp的代码)。所以我们需要去完成categoryAction中的queryJoinAccount方法。

            在Struts2和json整合前,我们先看一下之前显示一次json数据都发了哪些请求:

            因为type是Category类的一个属性,我们在BaseAction中已经实现了ModelDriven<Category>接口,所以这个type会被封装到model中,我们不需要管它,可以通过model来获取,但是EasyUI自动发过来的page和rows参数我们需要自己获取了,所以我们可以在BaseModel中增加两个成员变量page和rows并实现get和set方法,最后还要考虑一点,这些参数都获得了后,我们根据这些参数去数据库中查询数据,那么我们查出来的数据放到哪呢?而且还要打包成json格式发到前台才能被DataGrid显示。我们先不考虑将查询到的数据如何打包成json格式,我们先考虑把这些数据放到一个地方,很自然的想到了使用Map,因为json格式的数据就是key-value形式的。想到这里,我们继续完善BaseAction:

    @Controller("baseAction")  
    @Scope("prototype")  
    public class BaseAction<T> extends ActionSupport implements RequestAware,SessionAware,ApplicationAware,ModelDriven<T> {  
      
        //page和rows和分页有关,pageMap存放查询的数据,然后打包成json格式用的  
        //page和rows实现get和set方法,pageMap只需要实现get方法即可,因为pageMap不是接收前台参数的,是让struts获取的  
        protected Integer page;  
        protected Integer rows;  
        protected Map<String, Object> pageMap = null;//让不同的Action自己去实现  
            //省略get和set方法……  
          
        /******************* 下面还是原来BaseAction部分 *************************/  
        //service对象  
        @Resource  
        protected CategoryService categoryService;  
        @Resource  
        protected AccountService accountService;  
      
        //域对象  
        protected Map<String, Object> request;  
        protected Map<String, Object> session;  
        protected Map<String, Object> application;  
              
        @Override  
        public void setApplication(Map<String, Object> application) {  
            this.application = application;  
        }  
        @Override  
        public void setSession(Map<String, Object> session) {  
            this.session = session;  
        }  
        @Override  
        public void setRequest(Map<String, Object> request) {  
            this.request = request;  
        }  
          
        //ModelDriven  
        protected T model;  
        @Override  
        public T getModel() {  
            ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();  
            Class clazz = (Class)type.getActualTypeArguments()[0];  
            try {  
                model = (T)clazz.newInstance();  
            } catch (Exception e) {  
                throw new RuntimeException(e);  
            }     
            return model;  
        }  
    }  

    好,完善了BaseCategory后,我们可以写categoryAction中的queryJoinAccount方法了,我们将categoryAction中原来的方法全删掉,因为那些都是之前搭建环境时候测试用的,都不用了,现在真正开始项目代码了:

    @Controller("categoryAction")  
    @Scope("prototype")  
    public class CategoryAction extends BaseAction<Category> {  
          
        public String queryJoinAccount() {  
      
            //用来存储分页的数据  
            pageMap = new HashMap<String, Object>();  
              
            //根据关键字和分页的参数查询相应的数据。这个方法我们在Service中写过了,当时完成级联查询  
            List<Category> categoryList = categoryService.queryJoinAccount(model.getType(), page, rows);  
            pageMap.put("rows", categoryList); //存储为JSON格式,从上一节的json文件可以看出,一个key是total,一个key是rows,这里先把rows存放好  
            //根据关键字查询总记录数  
            Long total = categoryService.getCount(model.getType()); //这个方法没写,我们等会儿去Service层完善一下  
    //      System.out.println(total);  
            pageMap.put("total", total); //存储为JSON格式,再把total存放好  
      
            return "jsonMap";  
        }  
    }  

       这样Action我们就写好了,现在Action拿到前台传来的参数,然后根据参数查询了指定type的总记录数,以及指定type的所有商品,并且按照json中指定的key(即total和rows)进行存放,放在HashMap中了,之后只要将这个HashMap中的数据打包成json格式发送到前台就可以被DataGrid显示了。我们先把这个HashMap放这,先去完善了Service层的代码后,再来打包这个HashMap中的数据。

    3. 完善categoryService

            从上面的categoryAction中可知,需要在categoryService中增加一个getCount方法,并且要在具体实现类中实现好,实现如下:

    //CategoryService接口  
    public interface CategoryService extends BaseService<Category> {  
        //查询类别信息,级联管理员  
        public List<Category> queryJoinAccount(String type, int page, int size); //使用类别的名称查询  
        //根据关键字查询总记录数  
        public Long getCount(String type);  
    }  
      
    //CategoryServiceImpl实现类  
    @SuppressWarnings("unchecked")  
    @Service("categoryService")  
    public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {  
      
        @Override  
        public List<Category> queryJoinAccount(String type, int page, int size) {  
            String hql = "from Category c left join fetch c.account where c.type like :type";  
            return getSession().createQuery(hql)  
                    .setString("type", "%" + type + "%")  
                    .setFirstResult((page-1) * size) //从第几个开始显示  
                    .setMaxResults(size) //显示几个  
                    .list();  
        }  
      
        @Override  
        public Long getCount(String type) {  
            String hql = "select count(c) from Category c where c.type like :type";  
            return (Long) getSession().createQuery(hql)  
                .setString("type", "%" + type + "%")  
                .uniqueResult(); //返回一条记录:总记录数  
        }  
    }  

     到现在为止,这个数据库中数据的获取这条路就打通了,前面两步完成了从前台-->数据库-->取数据,接下来就开始打包HashMap中存放的数据,然后发给前台了。

    4. 配置struts.xml

            在struts.xml中通过配置就可以完成对指定数据的打包,我们先看一下struts.xml中的配置:

    <struts>  
          
        <constant name="struts.devMode" value="true" />  
          
        <package name="shop" extends="json-default"><!-- jason-default继承了struts-default -->  
          
            <global-results>  
                <result name="aindex">/WEB-INF/main/aindex.jsp</result>  
            </global-results>  
      
            <!-- class对应的是Spring中配置该Action的id值,因为要交给Spring管理 -->  
            <action name="category_*" class="categoryAction" method="{1}">  
                <!-- 必须要先添加json包,然后上面继承json-default -->  
                <result name="jsonMap" type="json">  
                    <!-- 要转换成json对象的数据 -->  
                    <param name="root">pageMap</param>  
                    <!-- 配置黑名单,过滤不需要的选项 ,支持正则表达式  
                    json格式:{total:3,rows:[{account:{id:2,login:"user",name:"客服A",pass:"user"},hot:true,id:3,…}]}  
                    -->  
                    <param name="excludeProperties">  
                        <!-- rows[0].account.pass-->  
                                            <!-- 这里显示不了正则表达式, CSDN的一个bug,我接个图放下面 -->  
                    </param>  
                </result>  
            </action>  
              
            <action name="account_*" class="accountAction" method="{1}">  
                <result name="index">/index.jsp</result>  
            </action>  
              
            <!-- 用来完成系统 请求转发的action,所有的请求都交给execute-->  
            <action name="send_*_*" class="sendAction">  
                <result name="send">/WEB-INF/{1}/{2}.jsp</result>  
            </action>  
        </package>  
      
    </struts>  
     <package name="shop" extends="json-default"><!-- jason-default继承了struts-default -->  要注意已经不是struts-default了

            从上面的配置可以看出,首先package要继承json-default,因为json-default继承了struts-default,因为在json的jar包里有个struts2-json-plugin-2.3.24.1.jar,打开即可看到里面有个struts-plugin.xml,打开即可看到json-default是继承了struts-default:

            接下来我配置<result>,name是刚刚action返回的字符串,type一定要配成json。然后就是result中的参数了,首先必须要配的就是name为root的参数,这个参数要配成刚刚需要转换的HashMap对象,即我们定义的pageMap,有了这个参数的配置,struts才会将pageMap中的数据打包成json格式。然后就是配置黑名单,黑名单的意思就是告诉struts在打包的时候,哪些字段不需要打包,比如管理员密码之类的信息,由上面注释中的jason格式可以看出rows[0].account.pass表示密码字段,但是数据肯定不止一条,所以我们得用正则表达式来表示,这样所有密码都不会被打包到json中。

    5. 修改query.jsp内容

                 到此,我们已经将数据打包成了json格式了,接下来我们完善一下前台query.jsp的内容就可以让DataGrid正确显示了:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
    <html>  
      <head>  
        <%@ include file="/public/head.jspf" %>  
        <script type="text/javascript">  
            $(function(){  
                $('#dg').datagrid({     
                    //url地址改为请求categoryAction  
                    url:'category_queryJoinAccount.action',  
                    loadMsg:'Loading......',  
                    queryParams:{type:''},//type参数,这里不需要传具体的type,因为我们要显示所有的  
                    //300,  
                    fitColumns:true,  
                    striped:true,  
                    nowrap:true,  
                    singleSelect:true,  
                    pagination:true,  
                    rowStyler: function(index,row){  
                        console.info("index" + index + "," + row)  
                        if(index % 2 == 0) {  
                            return 'background-color:#fff;';  
                        } else {  
                            return 'background-color:#ff0;';  
                        }  
                          
                    },        
                    frozenColumns:[[  
                        {field:'checkbox',checkbox:true},  
                        {field:'id',title:'编号',200}    //这里的field字段要和json数据中的一样               
                    ]],  
                    columns:[[                       
                        {field:'type',title:'类别名称',100, //字段type  
                            formatter: function(value,row,index){  
                                return "<span title=" + value + ">" + value + "</span>";  
                            }  
                        },      
                        {field:'hot',title:'热卖',100,  //字段hot  
                            formatter: function(value,row,index){  
                                if(value) { //如果是hot,该值为true,value是boolean型变量  
                                    return "<input type='checkbox' checked='checked' disabled='true'"; //勾选  
                                } else {  
                                    return "<input type='checkbox' disable='true'"; //不勾选  
                                }  
                            }  
                        },  
                        {field:'account.login',title:'所属管理员',200, //account.login管理员登录名  
                            formatter: function(value,row,index){  
                                if(row.account != null && row.account.login != null) {  
                                    return row.account.login; //如果登录名不为空,显示登录名  
                                } else {  
                                    return "此类别没有管理员";  
                                }  
                        }     
                        }  
                    ]]      
                });   
            });  
        </script>  
      </head>  
        
      <body>  
        <table id="dg"></table>  
      </body>  
    </html>

    6.  测试显示结果

            最后我们测试一下DataGrid的显示结果,如下:

            到这里,我们成功整合了Struts2和json,现在可以和前台传输json格式的数据了。

    本篇如果遇到数据显示不出来 前台页面不显示数据。

    查询不报错,而且sql语句也打印出来了,其次我在CategoryAction queryJoinAccount()方法里面debug了
    rows 是10 total 是1.
    model.getType()为空是为了查询出所有数据。 在里面遍历了下categoryList.get(0).getType();
    打印出来为1也没问题 。前台filed名字 数据库一模一样。

    那么他的问题所在就是 是因为BaseAction里面 pageMap 只有set 没有get 然后数据怎么都查不出来。

    set和get 一个是页面往java传参绑定 一个是java往页面传参绑定 

     
  • 相关阅读:
    Maximum Depth of Binary Tree
    Single Number
    Merge Two Sorted Lists
    Remove Nth Node From End of List
    Remove Element
    Remove Duplicates from Sorted List
    Add Two Numbers
    编译视频直播点播平台EasyDSS数据排序使用Go 语言 slice 类型排序的实现介绍
    RTMP协议视频直播点播平台EasyDSS在Linux系统中以服务启动报错can’t evaluate field RootPath in type*struct排查
    【解决方案】5G时代RTMP推流服务器/互联网直播点播平台EasyDSS实现360°全景摄像机VR直播
  • 原文地址:https://www.cnblogs.com/shanheyongmu/p/5805436.html
Copyright © 2011-2022 走看看