`
zhenjia
  • 浏览: 6770 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

一个基于guice的开发平台

阅读更多
    自GoogleGuice出现以后一直对它好奇,很希望在自己的项目中加入这一块,可惜公司内所有项目都是基于Spring的,所以一直对它半知半解,现在项目完成,有一段空闲时间,于是马上对Guice开始研究,简单的例子很早就跑过,所有目标放在web开发平台这块,想用guice把Spring给替了,经过三个星期的反复修改代码,最终终于完成了目前这个简单的开发平台。现在把部分基于这个平台的代码放出来,大家批评批评。
    首先说一下包含哪些第三方开源框架,在以前公司的项目中,都是本人搭建开发平台。
    两年当中一之使用WebWork.Spring Hibernate这样的组合,现在肯定有人会说,那你用guice代替spring很简单啊,因为guice发布了一个plugin,可以直接应用到struts2中,而我用webwork迁移到struts2基本只需要用半小时就可全部搞定。当然我也试了,一切OK。但是发现一个问题,Guice Injector对象是在当用户访问一个Action之后才进行实例的,所以如果用户没有访问任何Action时候,你又象在Action之前通过Guice inject你需要的对象时候,是无奈的。什么时候会遇到这样的问题呢?HibernateSessionInView时候就会遇到。Spring提供的HibernateSessionInView实现是在Filter里,并且是在启动项目时候就将HibernateSessionFactory创建,所以在Filter里可直接引用SessionFactory,而我现在遇到的问题就是我是先到Filter然后才到Action,而第一次到Filter时Guice无法给我inject SessionFactory,所以,我又有了一个想法,把webwork也抛弃了吧,用了这么长时间的webwork对它的内部实现已经很清楚了,于是,我开始了自己的MVC层+guice+Hibernate的整合。保留webwork的经典Interceptor,自己的MVC也有这个机制,实现了的Interceptor有:1.Action CleanUp Interceptor 清理ActionContext.
    2.Action Exception Interceptor 异常跳转
    3.Action TokenValidator Interceptor Token验证 
    4.Action Params Interceptor httpServletRequest参数绑定
    5.Action Result Interceptor result跳转
    6.Action ReqSet Interceptor httpServletRequest.setAttribute 这6个拦截
而Action也没有定义在xml文件中了,而是以Annotation的方式来实现的
具体代码如下:
@Action(name = "cpny", namespace = "/hr")
public class SysCompanyAction extends ActionSupport<SysCompany> {}

正如大家看见的 这样定义一个Action,就可以用http://localhost/hr/cpny.action来访问默认执行execute方法
而webwork方便大家的也在于只要是Action的属性,并提供getter setter方法 都可以从http参数中自动求值,这点我也是基于Annotation实现的,只是起的名字有点怪,呵呵。
@ReqGet
private Long id;

@ReqGet
private String _cpnyName;
	
@ReqGet
@ModelDriver
@ReqSet
private SysCompany sysCompany;

id将从request参数中获取,并自动进行类型转换 _cpnyName也如此,而sysCompany则使用@ModelDriver 将request参数中的值封装为sysCompany对象。假设request中存在如下请求参数id=1&_cpnyName=javaeye&sysCompany.id=1&sysCompany.cpnyId=google 则会正确匹配并装换成功,sysCompany如果包含其他对象则可以sysCompany.object.id=1这样的形式 如同ognl。还一点需要和大家解释在webwork中使用valueStack的方式将整个Action压入stack中在用ww标签进行求值,而这一步我没有实现,因为如果那样我还需要写一套类似ww的标签,显得有些麻烦,本人比较懒,所以采用JSTL,那当然需要在request里setAttribute所以我用@ReqSet来代表在action执行完毕以后将这些属性自动set进去。这样大家就可在页面上用<c:out value="${sysCompany.id}"/>形式访问了
接下来到执行完成以后的页面跳转了,同样采用Annotation定义
@PageFlow(result = { @Result(name = "input", path = "/view/sys/editCompany.jsp", type = Dispatcher.Forward) })
	public String input() throws Exception {
		if (id != null) {
			this.sysCompany = this.sysCompanyService.getCompanyById(id);
		}
		return "input";
	}

大家一看就明白,也和webwork的xml类似。@Result可定义多个,针对有不同结果返回的方法。
而guice可直接在Action里Inject
@Inject
	private SysCompanyService sysCompanyService;

免去了烦人的setter方法,呵呵 这样整个action无论是inject 还是从request获取参数都不再需要setter getter方法了,清爽了好多。
接着是也许我的一个创新,但是估计会招来骂声,就是DAO与Service的关系。以往的应用都是dao提供基本操作方法,Service调用Dao。Action调用Service.再平常不过了。而我在这里把DAO“省”去了。
大家先看看代码吧
@Singleton
public class SysCompanyService {

	@Inject
	private SysCompanyDao sysCompanyDao;


	
	@Transactional(type=TransactionType.READ_ONLY)
	@FinderByCriteria(value=SysCompany.class,orderBy=@OrderBy(column="id"))
	public Page<SysCompany> getResultPage(
			@FirstResult int start ,
			@MaxResults int limit,
			@LIKE(column="cpnyNameZh") String _cpnyName,
			@By(group="asd") String sort,
			@Order(group="asd") boolean isAsc
			) {
		return null;
	}
	


	@Transactional(type = TransactionType.READ_ONLY)
	@FinderById(SysCompany.class)
	public SysCompany getCompanyById(@PK
	Long id) {
		return null;
	}

	@Transactional(type = TransactionType.READ_WRITE)
	@Persistence(PersistenceType.SAVEORUPDATE)
	public void saveCompany(@PO
	SysCompany sysCompany) {
	}

	@Transactional(type = TransactionType.READ_WRITE)
	@Persistence(PersistenceType.DELETE)
	public void deleteCompany(@PO
	SysCompany sysCompany) {
	};

	@Transactional(type = TransactionType.READ_WRITE)
	public void deleteCompanyById(Long id) {
		this.deleteCompany(this.sysCompanyDao.getById(id));
	}

}

这样写的方式完全来源于基于guice Annotation的持久层框架warp-persistence
我只是做了一些扩展 比如@Persistence 需要指定PersistenceType参数携带@PO就能进行相应持久化操作
@FinderById需要指定PO.class,参数携带@PK 就能通过id查询对象。这样简单的操作
还有一个是@FinderByCriteria 做得过于复杂,不过是一个创新。至于能不能用在项目上不说,但是是我学习Annotation的一个阶段,而且我不再需要写任何dao 只需要声明一下Annotation,并且Service还是
@Singleton的。
现在重点解释一下@FinderByCriteria
@Transactional(type=TransactionType.READ_ONLY)
	@FinderByCriteria(value=SysCompany.class,orderBy=@OrderBy(column="id"))
	public Page<SysCompany> getResultPage(
			@FirstResult int start ,
			@MaxResults int limit,
			@LIKE(column="cpnyNameZh") String _cpnyName,
			@By(group="myOrderBy") String sort,
			@Order(group="myOrderBy") boolean isAsc
			) {
		return null;
	}

@FinderByCriteria(value=SysCompany.class,orderBy=@OrderBy(column="id"))第1个参数为查询的PO.class,而后面可任意追加一些固定的条件和排序方法,以上为追加了固定的按id进行ASC排序的条件
接着@FirstResult int start ,@MaxResults int limit,指名需要进行分页操作,并传入参数,@LIKE(column="cpnyNameZh") String _cpnyName,表示对cpnyNameZh进行模糊查询
@By(group="myOrderBy") String sort,@Order(group="myOrderBy") boolean isAsc,则接收用户需要以哪个字段进行升或降序的排序方式 注意中间一个参数group="myOrderBy" 表示@By ,@Order 是一组 by接收需要排序的字段而isAsc接收升或降序方式
这样在后台生成的SQL语句则是
select
    *
from
    ( select
        this_.id as id0_0_,
        this_.CPNY_ID as CPNY2_0_0_,
        this_.CPNY_NAME_EN as CPNY3_0_0_,
        this_.CPNY_NAME_KO as CPNY4_0_0_,
        this_.CPNY_NAME_ZH as CPNY5_0_0_,
        this_.CREATED as CREATED0_0_,
        this_.CREATEDBY as CREATEDBY0_0_,
        this_.UPDATED as UPDATED0_0_,
        this_.UPDATEDBY as UPDATEDBY0_0_,
        this_.USE_YN as USE10_0_0_
    from
        SYS_COMPANY this_
    where
        this_.CPNY_NAME_ZH like ?
    order by
        this_.CPNY_NAME_ZH asc,
        this_.id asc )
where
    rownum <= ?

说得有些乱,不知道各位理解没理解。发帖只是想让各位高手批评批评。我有哪些没考虑到的或者哪些不应该这样做的。
分享到:
评论
11 楼 beitongmoming 2008-10-16  
不错·不错
guice有一个针对servlet的jar,里面有RequestScoped和SessionScoped 两个annotation专门针对request,session的域注入。
想问一下LZ,关于request和session这2个scope你是怎么处理的呢?
10 楼 javabay 2008-09-26  
不错,先学习了。
9 楼 mornstar 2008-09-24  
楼主很强啊~
8 楼 zhenjia 2008-08-27  
jasongreen 写道
fireflyc 写道
其实guice不太适合做应用,而适合做框架或者内核使用。因为它的依赖注入是以一种侵入的紧耦合的方式进行的~而框架之类的内部是必然紧耦合的。


非常精辟!但guice松耦合也未尝不可,自己定义一种配置文件格式,然后内部用guice,就和spring一样了。

恩,我也提供了一个专门的XML配置文件,配置GUICE的每个module,而用guiceAop实现的Interceptor也是基于interface
可自己实现。
7 楼 jasongreen 2008-08-27  
fireflyc 写道
其实guice不太适合做应用,而适合做框架或者内核使用。因为它的依赖注入是以一种侵入的紧耦合的方式进行的~而框架之类的内部是必然紧耦合的。


非常精辟!但guice松耦合也未尝不可,自己定义一种配置文件格式,然后内部用guice,就和spring一样了。
6 楼 fireflyc 2008-08-27  
侵入~侵入~~侵入~~~

其实guice不太适合做应用,而适合做框架或者内核使用。因为它的依赖注入是以一种侵入的紧耦合的方式进行的~而框架之类的内部是必然紧耦合的。
5 楼 jasongreen 2008-08-27  
的确像T5,但是本质上是webwork。

Annotation使用的稍微有些多了。还是很棒。
4 楼 zhenjia 2008-08-27  
jessdy 写道
有点像T5

T5?今天首页的那个新闻? 。。一直不知道那个是什么东西。。。。有时间去看看
3 楼 jessdy 2008-08-27  
有点像T5
2 楼 zhenjia 2008-08-27  
看得人挺多。就没一个能给我一点意见吖。。。      
1 楼 zhenjia 2008-08-26  
以下帖出Action代码
@Action(name = "cpny", namespace = "/hr")
public class SysCompanyAction extends ActionSupport<SysCompany> {
	@Inject
	private SysCompanyService sysCompanyService;

	@ReqGet
	private Long id;

	@ReqGet
	private String _cpnyName;
	
	@ReqGet
	@ModelDriver
	@ReqSet
	private SysCompany sysCompany;



	/**
	 * 不执行任何操作 跳转至/view/sys/company.jsp
	 */
	@PageFlow(result = { @Result(name = "success", path = "/view/sys/company.jsp", type = Dispatcher.Redirect) })
	public String execute() throws Exception {
		return "success";
	}

	/**
	 * 获取list json输出 ajax不需要配置@PageFlow
	 * @return
	 * @throws Exception
	 */
	public String list() throws Exception {
		page = this.sysCompanyService.getResultPage(start, limit, _cpnyName,sort,isAsc());
		if (page != null) {
			List<SysCompany> companyList = page.getResultList();
			JSONObject root = new JSONObject();
			JSONArray arrayItems = new JSONArray();
			if (companyList != null) {
				for (SysCompany cpny : companyList) {
					JSONObject Item = new JSONObject();
					Item.put("ID", cpny.getId().toString());
					Item.put("cpnyId", StringUtils.defaultIfEmpty(cpny
							.getCpnyId(), ""));
					Item.put("cpnyNameZh", StringUtils.defaultIfEmpty(cpny
							.getCpnyNameZh(), ""));
					Item.put("cpnyNameEn", StringUtils.defaultIfEmpty(cpny
							.getCpnyNameEn(), ""));
					Item.put("cpnyNameKo", StringUtils.defaultIfEmpty(cpny
							.getCpnyNameKo(), ""));
					arrayItems.add(Item);
				}
				root.put("Items", arrayItems);
				root.put("totalCount", Integer.toString(page.getTotalRecord()));
			}
			
			writeTextByAction(root.toString());
		}
		return null;
	}

	/**
	 * 通过id获取对象 至修改 添加页面
	 * @return
	 * @throws Exception
	 */
	@PageFlow(result = { @Result(name = "input", path = "/view/sys/editCompany.jsp", type = Dispatcher.Forward) })
	public String input() throws Exception {
		if (id != null) {
			this.sysCompany = this.sysCompanyService.getCompanyById(id);
		}
		return "input";
	}

	/**
	 * 持久化一个对象
	 * @return
	 * @throws Exception
	 */
	@PageFlow(result = { @Result(name = "saveSuccess", path = "/hr/cpny.dhtml", type = Dispatcher.Redirect) })
	@Token
	public String save() throws Exception {
		if (this.sysCompany != null) {
			bind(this.sysCompany);
			this.sysCompanyService.saveCompany(this.sysCompany);
		}
		return "saveSuccess";
	}

	/**
	 * 通过id删除一个对象
	 * @return
	 * @throws Exception
	 */
	@PageFlow(result = { @Result(name = "deleteSuccess", path = "/hr/cpny.dhtml", type = Dispatcher.Redirect) })
	public String delete() throws Exception {
		if (id != null) {
			this.sysCompanyService.deleteCompanyById(id);
		}
		return "deleteSuccess";
	}
}

以下帖出@LIKE @EQ 代码 @LE @LT @GE @GT @BETWEEN等都是同理
/**
 * <p>
 * 在使用@FinderByCriteria查询时候在方法中使用<br/>
 * 标识需要进行模糊条件查询<br/>
 * column:配置entity里需要进行约束的字段名称<br/>
 * ignoreCase:配置是否忽略大小写 默认为false<br/>
 * not:配置条件是否为反向默认为false<br/>
 * ignoreBank:配置是否忽略空对象或者空字符串 默认为true<br/>
 * reloation:配置当前约束是否存在和其他约束的连接约束关系 默认为Relation.NULL<br/>
 * or:如果当前约束reloation=Relation.OR,则配置or策略配置,须和reloation一起使用<br/>
 * and:如果当前约束reloation=Relation.AND,则配置and策略配置,须和reloation一起使用<br/>
 * matchMode:配置模糊匹配策略 默认为Match.ANYWHERE<br/>
 * </p>
 * @author zhenjia <a href='mailto:zhenjiaWang@gmail.com'>email</a>
 * @since JDK1.5
 * @version 1.0 $Date:200808
 *          
 */

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LIKE {
	/**
	 * 
	 * @return 返回需要进行模糊条件约束字段
	 */
	String column();
	/**
	 * 
	 * @return 返回是否忽略大小写
	 */
	boolean ignoreCase() default false;

	/**
	 * 
	 * @return 返回是否为反向条件
	 */
	boolean not() default false;

	/**
	 * 
	 * @return 返回是否忽略空白字符串
	 */
	boolean ignoreBank() default true;

	/**
	 * @see Relation
	 * @return 返回连接关系
	 */
	Relation relation() default Relation.NULL;

	/**
	 * @see OR
	 * @return 返回OR策略
	 */
	OR or() default @OR(group = "");

	/**
	 * @see AND
	 * @return 返回AND策略
	 */
	AND and() default @AND(group = "");
	
	/**
	 * @see Match
	 * @return 返回模糊匹配方式
	 */
	Match matchMode() default Match.ANYWHERE;
	
}


/**
 * <p>
 * 在使用@FinderByCriteria查询时候在方法中使用<br/>
 * 标识需要进行等于条件查询<br/>
 * column:配置entity里需要进行约束的字段名称<br/>
 * ignoreCase:配置是否忽略大小写 默认为false<br/> 
 * not:配置条件是否为反向默认为false<br/>
 * ignoreBank:配置是否忽略空对象或者空字符串 默认为true<br/>
 * reloation:配置当前约束是否存在和其他约束的连接约束关系 默认为Relation.NULL<br/>
 * or:如果当前约束reloation=Relation.OR,则配置or策略配置,须和reloation一起使用<br/>
 * and:如果当前约束reloation=Relation.AND,则配置and策略配置,须和reloation一起使用<br/>
 * </p>
 * @author zhenjia <a href='mailto:zhenjiaWang@gmail.com'>email</a>
 * @since JDK1.5
 * @version 1.0 $Date:200808
 *          
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface EQ {
	/**
	 * 
	 * @return 返回需要EQ约束的字段
	 */
	String column();

	/**
	 * 
	 * @return 返回是否忽略大小写
	 */
	boolean ignoreCase() default false;

	/**
	 * 
	 * @return 返回是否为反向条件
	 */
	boolean not() default false;

	/**
	 * 
	 * @return 返回是否忽略空白字符串
	 */
	boolean ignoreBank() default true;

	/**
	 * @see Relation
	 * @return 返回连接关系
	 */
	Relation relation() default Relation.NULL;

	/**
	 * @see OR
	 * @return 返回OR策略
	 */
	OR or() default @OR(group = "");

	/**
	 * @see AND
	 * @return 返回AND策略
	 */
	AND and() default @AND(group = "");
}


service代码已经在主帖中给出

相关推荐

    google guice基础例子

    Guice是Google开发的一个轻量级,基于Java5(主要运用泛型与注释特性)的依赖注入框架(IOC)。Guice非常小而且快。Guice是类型安全的,它能够对构造函数,属性,方法(包含任意个参数的任意方法,而不仅仅是setter...

    mojave:一个基于注释的基于POJO的Java Web MVC框架,支持Guice的DI

    Mojave MVC Web框架======================== Mojave(发音为Mo-hav-ee)是一个注释驱动的基于POJO的Java Web应用程序开发框架。 它借鉴了Spring Web MVC和EJB 3.1的思想,并合并了Guice。 它试图: 通过提供IoC功能...

    android roboguice

    RoboGuice是Android平爱上基于Google Guice开发的一个库,可以大大简化Android应用开发的代码及一些繁琐重复的代码,给Android带来了简单、医用的依赖注入,如果你使用Spring或Guice的话,你就会知道这种编程方式是...

    quarantineJ:一个基于netty的实现了ioc、router的reactor模式的server

    目录功能router,支持通用的restful请求(当前版本支持得还不完善,补全中)ioc,支持直接注入,也支持扫描注入(当前版本基于guice,后续可能会替换掉),考虑到实际场景,仅支持singleton的注入aop,基于asm开发,非常...

    基于Java的简单Java内容管理系统设计源码

    该系统使用了jQuery、jqGrid、jsp、servlet、guice、mybatis和thymeleaf等技术,是一个简单的Java内容管理系统。适合用于学习和实践JavaScript、Java、CSS和HTML技术,以及开发基于Java的简单Java内容管理系统相关的...

    使用Spring in Guice和Guice in Spring的工具(高分项目).zip

    1. Spring框架:Spring是一个轻量级的Java开发框架,提供了丰富的功能和模块,用于开发企业级应用。它包括IoC(Inverse of Control,控制反转)容器、AOP(Aspect-Oriented Programming,面向切面编程)等特性,可以...

    warp-persist-2.0-20090214.zip

    warp-persist-2.0是最近刚刚发布的、基于Google Guice的轻量级Web开发框架。 Warp是一个相当棒的Java Web框架,而且前景非常看好。 Warp框架充分利用了JDK5.0的Annotation和泛型机制,并且基于Google Guice这个...

    dropwizard-guice-jpa-seed:一个用 Java 编写的示例 REST 应用程序(dropwizard、guice、jpa、hibernate、cors 等)

    它的目的是创建一个通用项目,该项目可用作新项目的起点,也可用于学习工作(我正在建立一个开放的游戏数据库)。 基于版本 0.7.0 使用依赖注入(没有 Spring 依赖!) / JPA 2.1 作为数据库访问框架 作为数据库...

    Java轻量级IOC框架Guice

    Guice是由Google大牛Bob lee开发的一款轻量级的java IoC容器。其优势在于:  速度快,号称比spring快100倍。  无外部配置(如需要使用外部可以可以选用Guice的扩展包),完全基于annotation特性,支持重构,代码...

    sited-project:基于JAX-RS,Guice风格DI,Bean验证,JPA和React的对开发人员友好的Java CMS

    基于JAX-RS,Guice风格DI,Bean验证,JPA和React的对开发人员友好的Java CMS。 专为启动而设计,提供了精心设计的快速原型代码库。 更多模块即将推出... 特征 构架 内容 笔记 操作系统 视窗Linux 苹果系统 数据库...

    primefaces-6.0.rar

    Optimus提供基于Google Guice IOC容器的注释来代替XML配置和一个XML-less Navigation Handler能够让你减少基于XML配置JSF Navigation的需要。此外Optimus还支持利用JPA实现数据持久化;将DataTable的内容导出成Excel...

    PrimeFacesV6.0.jar

    Optimus提供基于Google Guice IOC容器的注释来代替XML配置和一个XML-less Navigation Handler能够让你减少基于XML配置JSF Navigation的需要。此外Optimus还支持利用JPA实现数据持久化;将DataTable的内容导出成Excel...

    PrimeUI Widgets

    PrimeFaces是一个轻量级的、支持JSF 2.0的开源组件套件,具有100多个丰富的JSF组件,极大地提高了JSF Web应用程序的开发效率。 PrimeFaces是一个用于提高JSF Web应用程序开发效率的开源类库。主要由三个模块组成: ...

    web bean官方手册(简体中文版+繁体中文版+英文原版)

    一个将 interceptors(拦截器)绑定至组件的较佳方式,以及一个称为 decorator(装饰器)的新型拦截器,它适用于解决商业上的相关问题。 依赖注入和 contextual 生命周期管理这两者组合起来可让一个不熟悉的 API ...

    Jboot微服务框架-其他

    她是一个基于jfinal 和 undertow开发的微服务框架。提供了AOP、RPC、分布式缓存、限流、降级、熔断、统一配置中心、swagger api自动生成、Opentracing数据追踪、metrics数据监控、分布式session、代码生成器、shiro...

    myeslib:使用 Camel、Hazelcast、Guice、Gson、JDBI、Lombok 等进行的事件溯源实验

    请参阅语境这个想法是探索在 基本上,代替具有与空隙的方法,该方法将返回一个List&lt;? extends Event&gt; List&lt;? extends Event&gt; 。 这些事件和原始命令将形成一个 。 然后,这个 UnitOfWork 被持久化到一个由...

    平安银行java开发笔试题-qbit-extensions:QBit扩展

    平安银行java开发笔试题| #qbit ...是一个库而不是一个框架。 您可以将 QBit 与 Spring、Guice 等混合搭配。 QBit 很快! 从 maven 使用 &lt; dependency &gt; &lt; groupId &gt;io.advantageous.qbit&lt;

    trinityshell:三一壳。 基于 Java 的窗口管理器和桌面 shell

    它仍然是一个可用但没有用的年轻项目,因为仍然缺少许多非常基本的窗口管理控件。 该项目的目标是成为 Java 开发人员构建自己的成熟桌面的工具和库,包括硬件加速合成、平铺窗口管理等。 ##构建和运行 git clone ...

    better-hibernate-with-scala:在scala中使用Hibernate的更好方法,而无需使用null,java-bean访问器或过多的样板

    该项目是从另一个开发中的项目中提取的。 我这样做是希望对像我这样的人有所帮助。 进行函数式编程时不会认为ORM消失的人。 我已经做了很多研究,以使基于我的scala项目的持久层正确无误。 我得出的结论是,ORM在...

    dddlib:DDD(域驱动设计)库,源于Eric Evans的书

    是一个领域驱动设计(Domain Driven Design,简称DDD)类库,它的目的是: 为基于DDD的开发范式提供基本的接口和抽象,实现一致性。 支持业务代码和技术代码分离。使领域层代码纯粹表达业务概念和业务规则,将具体...

Global site tag (gtag.js) - Google Analytics