ExtJS5 整合Spring4之二

为ExtJS的grid panel提供restful服务

ExtJS的grid panel集成了负责前端交互的分页、检索、排序。

用浏览器开发者工具查看,可以看到它提交给后台的restful形式:

page:1
start:0
limit:27
sort:[{"property":"id","direction":"DESC"}]
filter:[{"operator":"like","value":"111","property":"title"}]

 而它期待获得的返回结果格式如下:

{
  "data" : [ {
    "id" : 1,
    "dtCreate" : null,
    "href" : null,
    "author" : null,
    "btop" : 0,
    "content" : "内容第1行<div>内容第2行</div>",
    "pid" : 0,
    "plain" : null,
    "postto" : "政策法规;用户中心#办理流程",
    "stitle" : "rrrr",
    "stype" : null,
    "tag" : null,
    "title" : "题名11111",
    "uid" : 0,
    "status" : 2,
    "primaryKey" : 1
  } ],
  "total" : 1
}

其中total是分页的依据。

 我们以下图所示的思路为grid panel提供restful数据服务:



 

 请求传到后台,先由controller对参数进行一次拆分,page、start、limit这样的简单参数直接就拿到了。

	@RequestMapping(value = "/list/{entity}", method = RequestMethod.GET)
	@ResponseBody
	public ResultDTO getEntities(@PathVariable String entity,
			@RequestParam(value = "page", required = false) Integer page,
			@RequestParam(value = "start", required = false) Integer start,
			@RequestParam(value = "limit", required = false) Integer limit,
			@RequestParam(value = "filter", required = false) String filter,
			@RequestParam(value = "sort", required = false) String sort) throws Exception {
		return restService.getEntities(page, start, limit, filter, sort, entity);
	}

 然后对filter和sort进行进一步分析,这两个参数是json格式的复杂请求,分析的策略是:在java中定义与前台对应的请求对象,

通过com.fasterxml.jackson.databind.ObjectMapper 直接读入json内容,获得java请求对象。

package net.bat.filter;

public class ExtJSFilter {

	private String operator;
	private Object value;
	private String property;
	private Boolean exactMatch;

	public Boolean getExactMatch() {
		return exactMatch;
	}

	public void setExactMatch(Boolean exactMatch) {
		this.exactMatch = exactMatch;
	}

	/**
	 * @return the operator
	 */
	public String getOperator() {
		return this.operator;
	}

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

	/**
	 * @return the value
	 */
	public Object getValue() {
		return this.value;
	}

	/**
	 * @param value the value to set
	 */
	public void setValue(Object value) {
		this.value = value;
	}

	/**
	 * @return the property
	 */
	public String getProperty() {
		return property;
	}

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

}

 

package net.bat.filter;

public class ExtJSSort {
	
	private String property;
	private String direction;
	
	/**
	 * @return the property
	 */
	public String getProperty() {
		return property;
	}
	/**
	 * @param property the property to set
	 */
	public void setProperty(String property) {
		this.property = property;
	}
	/**
	 * @return the direction
	 */
	public String getDirection() {
		return direction;
	}
	/**
	 * @param direction the direction to set
	 */
	public void setDirection(String direction) {
		this.direction = direction;
	}

}
ExtJSFilter[] fliters = mapper.readValue(filter, ExtJSFilter[].class);
...
ExtJSSort[] sorts = mapper.readValue(sort, ExtJSSort[].class);

 接下来,需要将请求转化为JPA检索能接受的请求形式:

	public <T> JPAReq parse(String filter, String sort, Class<T> cls) throws Exception {
		JPAReq req = new JPAReq();
		if (filter != null) {
			StringBuffer sbuf = new StringBuffer();
			int pos = 0;
			ExtJSFilter[] fliters = mapper.readValue(filter, ExtJSFilter[].class);
			Object[] queryParams = new Object[fliters.length];
			for (ExtJSFilter ef : fliters) {
				String filedName = ef.getProperty();
				// 处理外键 many-to-many
				if ((ef.getExactMatch() != null) && ef.getExactMatch()) {
					// TODO add ename filter
					if (cls == Attach.class) {
						filedName = "eid";
						ef.setOperator("eq");
					} else {
						filedName = "pid";
						ef.setOperator("eq");
					}
				}
				if (pos == 0) {
					sbuf.append(" " + filedName);
				} else {
					sbuf.append(" and " + filedName);
				}
				Oper oper = Oper.valueOf(ef.getOperator().toUpperCase());
				Object val = ef.getValue();
				// EQ, LIKE, GT, LT, GTE, LTE
				String paraPos = "(?" + (pos + 1) + ")";
				switch (oper) {
				case EQ:
					sbuf.append(" =" + paraPos);
					break;
				case LIKE:
					sbuf.append(" like " + paraPos);
					val = "%" + val + "%";
					break;
				case GT:
					sbuf.append(" >" + paraPos);
					break;
				case LT:
					sbuf.append(" <" + paraPos);
					break;
				case GE:
					sbuf.append(" >=" + paraPos);
					break;
				case LE:
					sbuf.append(" <=" + paraPos);
					break;
				case IN:
					sbuf.append(" in " + paraPos);
					queryParams[pos++] = val;
					continue;
				}
				// 如果参数值与目标属性不匹配,需要特殊处理,例如:日期
				Field f = null;
				try {
					f = cls.getDeclaredField(filedName);
				} catch (Exception e) {
					// getDeclaredField 无法获得 extend的父类field
					f = cls.getSuperclass().getDeclaredField(filedName);
				}
				Class<?> fcl = f.getType();
				if ((val != null) && !fcl.isAssignableFrom(val.getClass())) {
					if (fcl.isAssignableFrom(Date.class)) {
						// val = fmt_date.parse(val.toString());
						// dateformat: time
						val = new Date(Long.parseLong(val.toString()));
					} else if (fcl.isAssignableFrom(Long.class)) {
						// 检索传值integer与期待值long不匹配
						val = Long.parseLong(val.toString());
					}
				}
				queryParams[pos++] = val;
			}
			req.setWhereql(sbuf.toString());
			req.setQueryParams(queryParams);
		}
		if (sort != null) {
			LinkedHashMap<String, String> orderby = new LinkedHashMap<String, String>();
			ExtJSSort[] sorts = mapper.readValue(sort, ExtJSSort[].class);
			for (ExtJSSort es : sorts) {
				orderby.put(es.getProperty(), es.getDirection());
			}
			req.setOrderby(orderby);
		}
		return req;
	}
}

调用JPA分页检索,返回结果:

	private <T extends IdEntity> QueryResult<T> getEntity(Integer page, Integer start, Integer limit, String filter,
			String sort, String entity_name) throws Exception {
		Class<T> cls = UserDAO.classForName(entity_name);

		JPAReq req = parser.parse(filter, sort, cls);
		if (start == null) {
			start = 0;
		}
		if (limit == null) {
			limit = -1;
		}
		QueryResult<T> result = dao.getScrollData(cls, start, limit, req.getWhereql(), req.getQueryParams(),
				req.getOrderby());
		return result;
	}

 通用的dao实现借用了网友的工作。

猜你喜欢

转载自chen4w.iteye.com/blog/2284725