【SSH网上商城项目实战07】Struts2和Json的整合

    xiaoxiao2021-03-25  88

    转自:http://blog.csdn.net/eson_15/article/details/51332758

           上一节我们完成了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:

    [java] view plain copy print ? @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;      }  }   @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中原来的方法全删掉,因为那些都是之前搭建环境时候测试用的,都不用了,现在真正开始项目代码了:

    [java] view plain copy print ? @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";      }  }   @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方法,并且要在具体实现类中实现好,实现如下:

    [java] view plain copy print ? //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(); //返回一条记录:总记录数      }  }   //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中的配置:

    [html] view plain copy print ? <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-->                                          <!-- 这里显示不了正则表达式, 的一个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>   <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-->  <!-- 这里显示不了正则表达式, 的一个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要继承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正确显示了:

    [javascript] view plain copy print ? <%@ 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,因为我们要显示所有的                  //width: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:'编号',width:200}    //这里的field字段要和json数据中的一样                               ]],                  columns:[[                                           {field:'type',title:'类别名称',width:100, //字段type                          formatter: function(value,row,index){                              return "<span title=" + value + ">" + value + "</span>";                          }                      },                          {field:'hot',title:'热卖',width: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:'所属管理员',width: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>   <%@ 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,因为我们要显示所有的 //width: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:'编号',width:200} //这里的field字段要和json数据中的一样 ]], columns:[[ {field:'type',title:'类别名称',width:100, //字段type formatter: function(value,row,index){ return "<span title=" + value + ">" + value + "</span>"; } }, {field:'hot',title:'热卖',width: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:'所属管理员',width: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格式的数据了。

           相关阅读:http://blog.csdn.net/column/details/str2hiberspring.html

            整个项目的源码下载地址:http://blog.csdn.net/eson_15/article/details/51479994

    转载请注明原文地址: https://ju.6miu.com/read-15951.html

    最新回复(0)