关于XOA的架构,结合项目经验作以下陈述:
1、分层
renren-wap-fuxi-model:对外提供的实体对象
renren-wap-fuxi-service:内部接口和实现及数据库表单的实体对象,主要的开发
及DAO的编写在此处
renren-wap-fuxi-xoa-api:对外提供的接口
renren-wap-fuxi-xoa-server:具体业务映射的Controller类,主要用于api和 service层的交互。
2、依赖
<name>renren-wap-wqo-model</name>
<dependencies>
<dependency>
<groupId>net.paoding</groupId>
<artifactId>paoding-rose</artifactId>
</dependency>
<dependency>
<groupId>com.renren</groupId>
<artifactId>xoa-commons-interceptors</artifactId>
</dependency>
<dependency>
<groupId>com.xiaonei</groupId>
<artifactId>renren-wap-wqo-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<name>renren-wap-fuxi-service</name>
<dependency>
<groupId>net.paoding</groupId>
<artifactId>paoding-rose-jade</artifactId>
</dependency>
<dependency>
<groupId>com.xiaonei</groupId>
<artifactId>xiaonei-datasource4jade</artifactId>
</dependency>
<dependency>
<groupId>com.xiaonei</groupId>
<artifactId>renren-wap-framework-logic</artifactId>
</dependency>
<dependency>
<groupId>com.xiaonei</groupId>
<artifactId>renren-wap-fuxi-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.xiaonei</groupId>
<artifactId>xiaonei-xcache</artifactId>
</dependency>
<name>renren-wap-fuxi-xoa-api</name>
<dependency>
<groupId>com.renren</groupId>
<artifactId>xoa-api</artifactId>
</dependency>
<dependency>
<groupId>com.xiaonei</groupId>
<artifactId>renren-wap-wqo-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>net.paoding</groupId>
<artifactId>paoding-rose</artifactId>
</dependency>
<dependency>
<groupId>com.renren</groupId>
<artifactId>xoa-commons-interceptors</artifactId>
</dependency>
<name>renren-wap-fuxi-xoa-server Maven Webapp</name>
<dependency>
<groupId>net.paoding</groupId>
<artifactId>paoding-rose</artifactId>
</dependency>
<dependency>
<groupId>com.renren</groupId>
<artifactId>xoa-commons-interceptors</artifactId>
</dependency>
<dependency>
<groupId>com.xiaonei</groupId>
<artifactId>renren-wap-fuxi-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.xiaonei</groupId>
<artifactId>renren-wap-fuxi-service</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>xiaonei-commons-interceptors</artifactId>
<groupId>com.xiaonei</groupId>
</exclusion>
</exclusions>
</dependency>
3、sevice层的接口开发
wap.fuxi目录下
dao
--IAppPageDAO 编写基本的与数据库交互的sql语句,规则如下:
@DAO(catalog = "user_fuxi")
public interface IAppPageDAO {
/**
* 插入游戏信息表、返回自增主键id
* @param appPage
*/
@ReturnGeneratedKeys
@SQL("insert into app_page(page_name,company,introduction,web_logo_url,wap_logo_url,web_snapshot,wap_snapshot,keyword,display_order,status,source,source_url,add_time) "
+ "values( "
+ ":appPage.pageName,:appPage.company, "
+ ":appPage.introduction, "
+ ":appPage.webLogoUrl,:appPage.wapLogoUrl,:appPage.webSnapshot, "
+ ":appPage.wapSnapshot,:appPage.keyword,:appPage.displayOrder, "
+ ":appPage.status,:appPage.source,:appPage.sourceUrl, "
+ ":appPage.releaseTime "
+ ")")
public int save(@SQLParam("appPage") AppPageEntity appPage);
/**
* 根据id更新游戏记录
* @param appPage
*/
@SQL("UPDATE app_page " + " set page_name = :appPage.pageName, "
+ " company = :appPage.company, "
+ " introduction = :appPage.introduction, "
+ " web_logo_url = :appPage.webLogoUrl, "
+ " wap_logo_url = :appPage.wapLogoUrl, "
+ " web_snapshot = :appPage.webSnapshot, "
+ " wap_snapshot = :appPage.wapSnapshot, "
+ " keyword = :appPage.keyword, "
+ " status = :appPage.status, "
+ " source = :appPage.source, "
+ " source_url = :appPage.sourceUrl, "
+ " add_time = :appPage.addTime "
+ " where id = :appPage.id ")
public int update(@SQLParam("appPage") AppPageEntity appPage);
/**
* 根据id查询游戏记录
* @param id
*/
@SQL("select id,page_name,company,introduction,web_logo_url,wap_logo_url,web_snapshot,wap_snapshot,keyword,display_order,status,source,source_url,add_time "
+ "from app_page where id = :id")
public AppPageEntity select(@SQLParam("id") int id);
entity
--AppPageEntity 数据库表单实体的属性及set、get方法
service
--IAppPageService 定义内部接口
/**
* 前台根据id获取前台游戏信息
* @param id
* @return
*/
public AppPage getAppPageById(int id);
--impl
--AppPageServiceImpl 内部接口的实现,程序的主要业务逻辑在此实现并将结果加入缓存
@Override
public AppPage getAppPageById(int id) {
XCache<AppPage> cache = XCache.getCache(CACHE_TYPE_APPPAGE,
AppPage.class);
String key = String.valueOf(id);
AppPage appPageResult = cache.get(key);
if (appPageResult == null) {
AppPageEntity appPage = appPageDAO.select(id);
if (appPage != null) {
AppCategoryRelationEntity appCategoryRelation = appCategoryRelationDAO
.selectCategoryRelationByPageId(id);
List<AppPageSupport> appList = appPageSupportDAO
.selectAppListByPageId(id);
appPageResult = buildAppPage(appCategoryRelation, appList,
appPage);
cache.set(key, appPageResult, cacheTime);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("getAppPageById from cache:" + id);
}
}
return appPageResult;
}
4、api层和server层的url关系映射
一个url请求过来,通过请求api的接口,通过xoa规则映射到具体的controller里的方法,在方法中调用service层的内部接口,完成一次调用过程
api层GameCenterService
@XoaService(serviceId = "fuxi.xoa.renren.com") 唯一标识的serviceId
final static String _PREFIX_PAGE_TOPAPPPAGE_LIST = "/gamecenter/page/toppagelist";
/**
* 获取推荐page的列表
* @param pageNum
* @param pageSize
* @return
*/
@XoaGet(_PREFIX_PAGE_TOPAPPPAGE_LIST)
public List<AppPage> getAppPageListByStatus(@XoaParam("pageNum") int pageNum,
@XoaParam("pageSize") int pageSize);
以上代码标识 /gamecenter/page/toppagelist这里url请求 会走getAppPageListByStatus 这个get方法
5、server层的GameCenterController中完成对内部接口的调用
@Path("/gamecenter") 表示接受路径为"/gamecenter"的api请求
private final static String _PREFIX_PAGE_TOPAPPPAGE_LIST = "/page/toppagelist";
@Get(_PREFIX_PAGE_TOPAPPPAGE_LIST)
public List<AppPage> getAppPageListByStatus(@XoaParam("pageNum") int pageNum,
@XoaParam("pageSize") int pageSize) {
return appPageService.getAppPageListByStatus(pageNum, pageSize);
}
通过@Path和@Get等和api层的@XoaGet构成一个完整的映射关系,
在Controller中调用内部接口appPageService中的具体方法,完成一个具体调用过程。
在这里api相当位于客户端,controller相当位于服务端
编程接口中,XOA服务的开发者也应该同时提供一个API包,其中是XOA接口的定义文件,即Java接口类,接口中定义的XOA服务的serviceId、URI、入口参数以及返回值等信息,这非常类似Jade的DAO接口,不需要实现,放在容器中运行的时候,容器会将其用动态代理封装,自动提供那些可复用的调用逻辑。
* example: UserController下有一个方法xyz<br>
* 1、在没有配置任何注解的情况下,xyz方法代表的资源是/user/xyz,支持GET和POST两种访问<br>
* 2、如果对xyz标注了@Get()注解,xyz代表的资源是/user,并且仅支持GET访问<br>
* 3、如果对xyz标注了@Get("abc"),xyz代表的是资源/user/abc,并且仅支持GET访问<br>
* example: UserController下有一个方法xyz<br>
* 1、在没有配置任何注解的情况下,xyz方法代表的资源是/user/xyz,支持GET和POST两种访问<br>
* 2、如果对xyz标注了@Put()注解,xyz代表的资源是/user,并且仅支持PUT访问<br>
* 3、如果对xyz标注了@Put("abc"),xyz代表的是资源/user/abc,并且仅支持PUT访问<br>
时间的处理
if (userAccessFlow.getAddTime() != null) {
userAccessFlowResult.setAddTime(userAccessFlow.getAddTime().getTime());
}