Faceye基础版下载:http://code.google.com/p/faceye/downloads/list

Faceye基础版中,对JSON数据进行了统一的处理,使得用户在操作时可以不用关注数据的细节问题,直接使用JSON格式的数据.

比如在Action中,当要输出JSON数据时,只需要:

/**
	 * 博客点击排行榜
	 */
	
	public ActionForward blogClickOrderList(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response){
		String timePeriod=this.get("timePeriod", request);
		PaginationSupport ps=this.getBlogService().getPageOfBlogClickHistoryOrderList(timePeriod, this.getHttp().getCurrentIndex(request), this.getHttp().getCurrentPageSize(request));
		String json=ps.json();
		this.jsonPrint(response, json);
		return null;
	}


在这里面,我们只使用了一句:
ps.json();

就完成了json格式数据的转化,其中,PaginationSupport 使用的Robin早期写的一个Hibernate分页对像,对于JSON数据的输出,我们只需要使用:
this.jsonPrint(response, json);


对于json数据的转化,我们完全在后台完成.
以下是取得分页对像的代码:
public PaginationSupport getPageOfBlogClickHistoryOrderList(
			String periodTime, int startIndex, int pageSize) {
		// TODO Auto-generated method stub
		return this.getBlogClickHistoryDao().getBlogClickOrderList(periodTime, pageSize, startIndex);
	}

在这里,调用DAO进行简单的数据查询.
/**
	 * 点击量包括访问博客首页的量,访问单篇文章的量,其中,访问者包括FaceYe网友(既未注册用户) 同时,包括已注册用户.
	 */
	public PaginationSupport getBlogClickOrderList(String timePeriod,
			int pageSize, int startIndex) {
		if (StringUtils.isEmpty(timePeriod)) {
			timePeriod = StringPool.BLOG_PERIOD_LIST_ORDER_ALL;
		}
		Date[] date = this.getDate(timePeriod);
		String sql = "";
		if (null != date) {
			String start = DateUtil.parseDate(date[0], null);
			String end = DateUtil.parseDate(date[1], null);
			sql = "select * from (select  sum(xx.blog_click_count) as 'blog_click_count',xx.portal_id as 'portal_id', xx.user_id as 'user_id', xx.username as 'username' from ("
					+ "select  sum(x.article_click_count) as 'blog_click_count' ,x.portal_id as 'portal_id',x.user_id as 'user_id',x.username as 'username'"
					+ " from "
					+ "(select p.id as 'portal_id',"
					+ "uba.name as 'article_name',"
					+ "count(ubac.article_id) as 'article_click_count',"
					+ "ubac.article_id   as 'article_id' ,u.id as 'user_id',u.name as 'username'"
					+ " from "
					+ "user_blog_article_click_count ubac,"
					+ "user_blog_article uba,"
					+ "user_blog_article_category ubc,"
					+ "sys_portal_container p,"
					+ "sys_user u"
					+ " where "
					+ "ubc.portalContainer_id=p.id "
					+ "and "
					+ "uba.id=ubac.article_id"
					+ " and "
					+ "uba.articleCategory_id=ubc.id "
					+ "and "
					+ "p.user_id=u.id"
					+ " and ubac.createTime between '"
					+ start
					+ "' and '"
					+ end
					+ "' group by ubac.article_id "
					+ " order by count(ubac.article_id) desc) x "
					+ " group by x.portal_id "
					+

					"union "
					+

					"select  count(ubch.id) as 'blog_click_count',p.id as 'portal_id',u.id as 'user_id',u.name as 'username' from "
					+ "user_blog_click_history ubch,"
					+ "sys_portal_container p,"
					+ "sys_user u"
					+ " where ubch.portalContainer_id =p.id and p.user_id=u.id "
					+ " and ubch.createTime between '"
					+ start
					+ "' and '"
					+ end + "' group by portal_id " +

					") xx group by xx.portal_id order by blog_click_count desc) xxx";

		} else {
			sql = "select * from (select  sum(xx.blog_click_count) as 'blog_click_count',xx.portal_id as 'portal_id', xx.user_id as 'user_id', xx.username as 'username' from ("
					+ "select  sum(x.article_click_count) as 'blog_click_count' ,x.portal_id as 'portal_id',x.user_id as 'user_id',x.username as 'username'"
					+ " from "
					+ "(select p.id as 'portal_id',"
					+ "uba.name as 'article_name',"
					+ "count(ubac.article_id) as 'article_click_count',"
					+ "ubac.article_id   as 'article_id' ,u.id as 'user_id',u.name as 'username'"
					+ " from "
					+ "user_blog_article_click_count ubac,"
					+ "user_blog_article uba,"
					+ "user_blog_article_category ubc,"
					+ "sys_portal_container p,"
					+ "sys_user u"
					+ " where "
					+ "ubc.portalContainer_id=p.id "
					+ "and "
					+ "uba.id=ubac.article_id"
					+ " and "
					+ "uba.articleCategory_id=ubc.id "
					+ "and "
					+ "p.user_id=u.id"
					+ " group by ubac.article_id "
					+ " order by count(ubac.article_id) desc) x "
					+ " group by x.portal_id "
					+

					"union "
					+

					"select  count(ubch.id) as 'blog_click_count',p.id as 'portal_id',u.id as 'user_id',u.name as 'username' from "
					+ "user_blog_click_history ubch,"
					+ "sys_portal_container p,"
					+ "sys_user u"
					+ " where ubch.portalContainer_id =p.id and p.user_id=u.id group by portal_id"
					+

					") xx group by xx.portal_id order by blog_click_count desc) xxx";
		}
		return this.getBaseJdbcDao().getPage(sql, pageSize, startIndex);
	}


至此,返回完整的数据分页对像.

分页对像代码如下:
package com.faceye.core.util.helper;

import java.util.List;

import org.apache.commons.collections.CollectionUtils;

public class PaginationSupport {
	public final static int PAGESIZE = 15;

	private int pageSize = PAGESIZE;

	private List items;

	private int totalCount;

	private int[] indexes = new int[0];

	private int startIndex = 0;

	public PaginationSupport(List items) {
		setItems(items);
		setPageSize(items.size());
		setTotalCount(items.size());
		setStartIndex(0);
	}

	public PaginationSupport(List items, int totalCount) {
		setPageSize(PAGESIZE);
		setTotalCount(totalCount);
		setItems(items);
		setStartIndex(0);
	}

	public PaginationSupport(List items, int totalCount, int startIndex) {
		setPageSize(PAGESIZE);
		setTotalCount(totalCount);
		setItems(items);
		setStartIndex(startIndex);
	}

	public PaginationSupport(List items, int totalCount, int pageSize,
			int startIndex) {
		setPageSize(pageSize);
		setTotalCount(totalCount);
		setItems(items);
		setStartIndex(startIndex);
	}

	public List getItems() {
		return items;
	}

	public void setItems(List items) {
		this.items = items;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public int getTotalCount() {
		return totalCount;
	}

	public void setTotalCount(int totalCount) {
		if (totalCount > 0) {
			this.totalCount = totalCount;
			int count = totalCount / pageSize;
			if (totalCount % pageSize > 0) {
				count++;
			}
			indexes = new int[count];
			for (int i = 0; i < count; i++) {
				indexes[i] = pageSize * i;
			}
		} else {
			this.totalCount = 0;
		}
	}

	public int[] getIndexes() {
		return indexes;
	}

	public void setIndexes(int[] indexes) {
		this.indexes = indexes;
	}

	public int getStartIndex() {
		return startIndex;
	}

	public void setStartIndex(int startIndex) {
		if (totalCount <= 0) {
			this.startIndex = 0;
		} else if (startIndex >= totalCount) {
			this.startIndex = indexes[indexes.length - 1];
		} else if (startIndex < 0) {
			this.startIndex = 0;
		} else {
			this.startIndex = indexes[startIndex / pageSize];
		}
	}

	public int getNextIndex() {
		int nextIndex = getStartIndex() + pageSize;
		if (nextIndex >= totalCount) {
			return getStartIndex();
		} else {
			return nextIndex;
		}
	}

	public int getPreviousIndex() {
		int previousIndex = getStartIndex() - pageSize;
		if (previousIndex < 0) {
			return 0;
		} else {
			return previousIndex;
		}
	}

	public List transItems() {
		return CollectionUtil.getCollectionUtil().transList(this.getItems());
	}

	/**
	 * 将分页像中的数据转化为标准的JSON分页结构
	 * 
	 * @return
	 */
	public String json() {
		if (CollectionUtils.isNotEmpty(this.getItems())) {
			return JSONUtil.pageJson(this.getTotalCount(), CollectionUtil
					.getCollectionUtil().list2Json(this.transItems()));
		} else {
			return null;
		}
	}

}



在分页对像的json()方法中,我们完成了从各式各样数据到json数据的转化工作.
在这里,我们主要使用了一个list2json()方法.如下:

/**
	 * 将一个结果集转化为json数据结构
	 * 
	 * @param source
	 * @return
	 */
	public String list2Json(List source) {
		try {
			if (null == source || source.isEmpty()) {
				return null;
			}
			StringBuffer json = null;
			if (source.get(0) instanceof Map) {
				json = new StringBuffer(JSONArray.fromObject(source).toString());
			} else {
				json = new StringBuffer(StringPool.CHARACTER_MIDDLE_LEFT);
				for (int i = 0; i < source.size(); i++) {
					Object item = source.get(i);
					if (item instanceof BaseObject) {
						Class clazz = item.getClass();
						if (ClassUtils.hasMethod(clazz,
								StringPool.REFLECTION_METHOD_JSON, null)) {
							String temp=ReflectionUtils.invokeMethod(
									ClassUtils.getMethodIfAvailable(clazz,
											StringPool.REFLECTION_METHOD_JSON,
											null), item).toString();
							json.append(temp);
						} else {
							json.append(JSONArray.fromObject(item).toString());
						}
					} else if (item instanceof Map) {
						json.append(JSONArray.fromObject(item).toString());
					}
					json.append(StringPool.CHARACTER_COMMA);
				}
				json.deleteCharAt(json.lastIndexOf(StringPool.CHARACTER_COMMA));
				json.append(StringPool.CHARACTER_MIDDLE_RIGHT);
			}
			return json.toString();
		} catch (Exception e) {
			return null;
		}
	}


在这里,如果我们使用的是Hiberante的实体查询,那么要求我们的实体中有
public Stirng json(){...}


public Map map(){...}

方法
这样
如果不是使用Hiberante的实体查询,那我们不使用这两个方法,直接使用JSONArray对对像进行转化.
以上两个方法的示例为:
public Map map(){
		Map map=new HashMap();
		map.put("id", this.getId());
		map.put("name", this.getName());
		map.put("content", this.getContent());
		SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		map.put("createTime", dateFormat.format(this.getCreateTime()));
		map.put("categoryId", this.getArticleCategory().getId());
		map.put("categoryName", this.getArticleCategory().getName());
		map.put("discusCount", this.getDiscusCount());
		map.put("clickCount", this.getClickCount());
		return map;
	}
	public String json(){
		StringBuffer sb=new StringBuffer("{");
		sb.append("\"id\":");
		sb.append("\"");
		sb.append(this.getId());
		sb.append("\"");
		sb.append(",");
		sb.append("\"name\":");
		sb.append("\"");
		sb.append(this.getName());
		sb.append("\"");
		sb.append(",");
		sb.append("\"content\":");
		sb.append("\"");
		sb.append(this.getContent());
		sb.append("\"");
		sb.append(",");
		sb.append("\"createTime\":");
		sb.append("\"");
		sb.append(this.getCreateTime());
		sb.append("\"");
		sb.append(",");
		sb.append("\"categoryId\":");
		sb.append("\"");
		sb.append(this.getArticleCategory().getId());
		sb.append("\"");
		sb.append(",");
		sb.append("\"categoryName\":");
		sb.append("\"");
		sb.append(this.getArticleCategory().getName());
		sb.append("\"");
		sb.append("}");
		return sb.toString();
	}


至此,便是系统内对json 完整处理.而在系统的其它地方,不会存在对JSON数据的处理

******************************************************************
关于FaceYe开源portal的其它更多内容包括:

FaceYe用户及开发人员提供文档(以下内容为FaceYe开发人员或用户提供,请尊重原著):

******************************************************************
评论
ecsun 2008-06-26
楼上怎么封装的呢~
xfan1982 2008-06-24
封装的不好
tubinee 2008-06-20
kimmking 写道
1 json序列化的时候,hibernate导致的级联怎么处理。
2 大数据量的json序列化如果优化。10M级别。


我想如果是这么大级别的json对象,应该考虑从业务逻辑这块来优化一下需求叻,10M级别的json传输过来,估计页面上的大小远远大于10M叻,IE对Html文件的处理的限制是10M叻,所以可以考虑和客户谈谈需求,看看有没有更好的use case可以来解决用户的要求的。
ecsun 2008-06-20
kimmking 写道
1 json序列化的时候,hibernate导致的级联怎么处理。

对于Hibernate的级联数据,由于考虑到性能,级联的数据并不会马上加载,所以我们在每个实体中加了一个
public String json(){...}

或是
public Map map(){...}

方法
在这两个方法中,对数据进行统一的转化.对于级联数据,提前加载到map或String中,这样解决了在使用JSONArray中出现在级联数据加载出现异常的情况.

对于我们里面提供的JDBC查询,我们向外提供了统一的数据结构,json的转化,非常 方便.
kimmking 写道
2 大数据量的json序列化如果优化。10M级别。

我们并不会这样去处理json
在Faceye基础版(开源)中,对json的处理,具体到每一个实体,每一个分页对像的操作中,不会出现这种大批量的json处理,也就是说,我们将任务进行了分散.有10M级别的JSON,不明白在什么地方有
如果你真有这么大的json结构需要处理,建议可以考虑定时任务.
kimmking 2008-06-19
1 json序列化的时候,hibernate导致的级联怎么处理。
2 大数据量的json序列化如果优化。10M级别。
发表评论

您还没有登录,请登录后发表评论