`
robbin
  • 浏览: 4799176 次
  • 性别: Icon_minigender_1
  • 来自: 上海
博客专栏
377a9ecd-1ea1-34ac-9530-9daa53bb2a7b
robbin谈管理
浏览量:135741
社区版块
存档分类
最新评论

Warp framework - 一个相当有前途的Java轻量级Web开发框架

    博客分类:
  • Java
阅读更多
Warp framework 是最近刚刚发布的、基于Google Guice的轻量级Web开发框架,我也是在JavaEye网站的新闻频道看到的这条新闻: warp-persist 1.0: 为Google Guice专门提供持久层与事务处理的框架,通过这个新闻仔细阅读了Warp网站上面的文档,感觉到很振奋,Warp是一个相当棒的Java Web框架,而且前景非常看好。

Warp框架充分利用了JDK5.0的Annotation和泛型机制,并且基于Google Guice这个IoC框架,提供了full-stack的Web开发设施,他主要包含了四个部分:

warp-persist框架:封装Hibernate和JPA,提供事务管理和持久化资源管理
warp-dynamic-finder:提供了基于Annotation的动态查询功能,让数据库查询变得异常简单,不再需要DAO层
warp-mvc:借鉴了Tapestry5,提供了一个基于事件机制和组件化的Web层,并且组件注入方式高度IoC化
warp-servlet: 提供了一些Servlet的封装和附加的高级功能,例如URL过滤,和其他web框架集成等等

这几年来,Java在Web开发框架方面的进步显得很有限,Spring/Hibernate组合对撼JBoss Seam形成两大竞争的主流态势,但是这两个Web框架在Web快速开发方面的创新还显得不够好:Spring是越来越臃肿了,配置文件也是越来越复杂难懂了;JBoss Seam门槛又过高,而且集成的JSF一向受人垢病,并非完美的解决方案,特别是在Ruby on Rails横空出世之后,Java社区对于简洁易用的快速web开发框架的企盼也是一直很高的。

Warp在我看来是这方面做的最好的,它有以下几个鲜明的特点:

一、充分利用JDK5的annotation,简化编程和配置文件

Warp基于Google Guice并且发扬光大,自身无配置文件,所有功能完成均通过annotation,所以编程相当简洁

二、大量使用JDK5的泛型编程,提供强类型安全保证

虽说脚本语言的Duck Typing理念很流行,不过Java的优势也就是类型安全,Spring大量运用反射和XML配置等于是放弃了Java的优势。Warp在泛型方面做的很好,我相信在IDE的帮助下,Warp编程会更轻松

三、Warp-persist提供了声明式的事务管理,终于可以取代Spring了

Google Guice很好很强大,但是它没有事务管理能力和资源管理能力,所以无法取代spring,但是Warp-persist填补了这一缺憾,注入和管理Hibernate很容易:

Injector injector = Guice.createInjector(..., PersistenceService
			.usingHibernate()
			.across(UnitOfWork.TRANSACTION)
			.buildModule());


要声明事务比spring可简单多了:

public class MyService {
    @Inject Provider<Session> session; 

    @Transactional 
    public void createNewPerson() {
        session.get().saveOrUpdate(new Person(...)); 
    } 
}


Warp支持Hibernate/JPA的所有事务管理策略,不但注入方式简单,而且声明事务方式更简单,代码看着简洁,写着更省心。

四、Dynamic Finder实在很酷!

还是直接看代码吧:

@Finder(query="from Person")
public List<Person> listAll() { return null; }

用annotation声明一下,一行查询代码都没有,你还要DAO干啥呢?

@Finder(query="from Person where firstName = :firstName")
Person find(@Named("firstName") String name);

带参数的绑定变量查询,还是一行代码不用写,DAO是啥?

@Finder(query="from Person")
List<Person> listAll(@FirstResult int first, @MaxResults int max);

带分页的查询,还是一行代码不用写,谁用DAO我跟谁急 !


五、Web层也极其简单

Warp-MVC模仿了Tapestry 5的架构,但是作者做了大量的改良和简化,作者解释了一下为什么不直接使用Tapestry,而是自己开发的理由。

Warp-MVC看起来像一个Tapestry的简化版,有组件的概念,事件响应的方式,但是非常易用,非常简洁,URL映射也通过annotation方式声明,作者在自己的博客上面提供了相关的简单示例,可以参考:

http://www.jroller.com/dhanji/

Warp框架是最近几年来,我看到的第一个走在正确发展方向上的Java Web框架:结构简单、易用使用、但充分发挥了Java自身的语法优势,非常值得期待!

目前Warp框架还不是特别成熟,但是Warp-persistent已经相当稳定了,如果你是使用Hibernate/Spring/Struts来开发项目的话,不妨试试Warp,把spring换掉改成Hibernate/Warp/Struts2.0,也是一个不错的解决方案,全部运用annotation,让你的项目Zero Configuration。

友情提醒:Warp官方网站无法直接访问,建议在FireFox浏览器上面安装gladder插件,跨越GFW。

Warp Framework - 官方网站








分享到:
评论
80 楼 ajoo 2008-03-14  
ozzzzzz 写道
我觉得ajoo现在有些跟自己较劲的意思。其实就这个事情来说,本无所谓对错,都有道理。关键是自己的权衡和选择。
而之所以我最近很少发表对java社区的看法,原因当然是我自己对java就不太通,水平不够。但是我还以为,java社区的框架看似不少,但是真正的说起来,又没多少。这些框架之间的哲学思路其实分析起来,仅仅是细节层面的不同,而无本质上的区别。而现在构架师满天飞,又看不出哪个出来设计一个自己的框架来。要说grails哲学稍微有所不同,但是又是外来户,不能算本土球员。
而本身java社区的框架层出不穷,就说明java这里需要框架这样的开发套路。而同时又可以说明,这些套路又都不是令人满意。因此我看,与其发明更多的套路,不如发明组织套路的法子出来,叫大家学会这个法子,自己整自己的套路出来来得彻底。

死胖子是说springside这类的东西么?
79 楼 quaff 2008-03-14  
sorphi 写道
看来ajoo大哥很喜欢immutable,所以尤其喜欢Constructor injection

引用
Guice best practices
Field vs. method vs. constructor injection

Field injection

    * + Most compact syntax (good for a trivial custom provider, e.g.)
    * - Can't take any special action upon injection
    * - Your class is not testable!

Method injection

    * + Isn't field injection
    * + Only thing that works for some strange edge cases

Constructor injection

    * + Fields can be final!
    * + Injection cannot possibly have been skipped, even if Guice is not in the picture
    * + Easy to see dependencies at a glance
    * + It's what the idea of construction is all about
    * - No optional injections
    * - Useless when Guice can't do instantiation itself, e.g. a servlet
    * - Subclasses need to "know about" the injections needed by their superclasses
    * - Less convenient for tests that only "care about" one of the parameters


不过上面有些概念还是没有很多经验来体会差别,劳烦ajoo大哥您给讲讲?比如
    * - Your class is not testable!
    * + Only thing that works for some strange edge cases
    * - Useless when Guice can't do instantiation itself, e.g. a servlet

你举的那个代码,每个请求都要对应一个action的构造函数,那怎么用url/actionmethod mapping?根据struts2.1的rest plugin,我臆想了一段伪码如下:

public final class BlogsController {

  private final Blogs blogs;

  @Inject
  public BlogsController(Blogs blogs){
    this.blogs = blogs;
  }

  /** GET /blogs/?page={page} */
  @Resource("/blogs/") @RestMethod("GET") @RestAccept("text/html")
  public Renderer index(@RestParam("page") int page) {
    return new Renderer("index.html")
       .put("blogs", blogs.list(page));
  }

  /** GET /blogs/1 */
  @Resource("/blogs/{id}") @RestMethod("GET") @RestAccept("text/json")
  public Renderer show(@RestParam("id") String id) {
    Blog blog = blogs.get(id);
    return new Renderer("show.json")
       .withEtag(...)
       .lastModified(blog.getLastModified())
       .put("blog", blog);
  }

  /** PUT /blogs/1 */
  @Resource("/blogs/{id}") @RestMethod("PUT") @RestAccept("text/html")
  public Renderer update(???) {
    // how to do when we need to store some values from request into pojo but can't change pojo's 
    //state for protecting ajoo's faith? varargs in method scope?

    //prepare , parameter/property binder, then save

    return index(0);
  }

  ...
}

public class Renderer {

  private Map context;

	public Render(String result);
	@Inject	public void setResponse(HttpResponse res);
	@Inject	public void setResponse(HttpRequest req);

	public put(String key, Object value);
	public void render();

  ...
}


action pojo想要immutable,就得需要写mutable的Renderer和Binder之类的设施来存放中间状态。只不过是换了个地方而已。


Guice推荐ctor injection,我来点评一下他说的优点

    * + Fields can be final! 
      这个有什么实际意义?
    * + Injection cannot possibly have been skipped, even if Guice is not in the picture
      如果用方法注入,可以加一个比如@Required来强制必须注入
    * + Easy to see dependencies at a glance
      这个是鸡肋
    * + It's what the idea of construction is all about
      这个没明白说什么

再来加一个缺点,和getter/setter注入相比没办法在运行期改变,拿acegi举例
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
\A/backend/switchuser\Z=ROLE_SUPERVISOR
\A/backend/switch\Z=ROLE_SUPERVISOR
\A/backend/exit\Z=ROLE_PREVIOUS_ADMINISTRATOR
\A/backend/.*\Z=ROLE_SUPERVISOR
这个是控制url访问权限的配置,在容器启动的时候就注入到bean里面了,也可以在webapp运行期间,修改它然后再set进去
78 楼 quaff 2008-03-14  
robbin 写道
melin 写道
rainlife 写道
使用struts2(CoC)+JPA+spring(注解),会是怎么样呢?


在java中这样的组合应该成经典,如果一味的最求zero 配置,也不是很完美,应该是注解和xml相结合,基本不会变动用注解,如果那些可变动的还是需要xml的,特别是spring2.5。提供的新特性(@Component,@Repository,@Service),大大简化了典型的三层结构的配置。

Spring在静态的配置文件当中描述bean的依赖关系(或者静态的Annotation),在某些情况下这是一个非常讨厌的限制,导致你很难在程序运行期修改或者创建bean的依赖关系。

比方说,你的程序根据某用户的操作,创建了quartz bean执行后台任务,这玩意你没办法事先在配置文件里面写死的,那你就麻烦大了,只能想办法自己写FactoryBean,在程序里面调用这个FactoryBean自己手工创建依赖。再例如你一个prototype的bean,在程序运行期创建的时候需要从程序里面传入一个构造器参数,这个参数可能来自你的业务逻辑,那你马上傻眼了,写FactoryBean吧,在程序里面自己create吧。类似这种情况还挺多的,Spring也就是管理Singleton的bean很好用,一旦涉及到prototype bean啥的,处处受限制。

所以这个IoC的玩意,你要在程序运行期玩花样,灵活起来,动态起来,Google Guice就比Spring好用不是一点半点。这就是为啥我推崇基于Google Guice的warp的原因,当然warp自己也有一些很不错的地方。


1.spring要更改bean的依赖关系可以手动的去get和set,也可以采用spring-dm,这是osgi的强项,不知道guice有什么更好的方法?
2.你说的quartz bean还是在自己的带面里面传入构造参数new出来比较好,然后获取spring里面org.quartz.Scheduler的实例,然后按照quartz的方式去处理,既然这个bean的构造参数是依赖业务逻辑不断的变,难道guice可以检测到然后得到不同的实例?

个人认为采用guice比采用spring好的只是代码上的优雅,对于设计并没有什么新意,因为IoC最近也没什么新概念,guice只是采用jdk5的annotation方式.
77 楼 nazar 2008-03-14  
花这么多时间讨论guice?没有看看tapestry-ioc吗?
吸收了很多guice的东东,而且可以独立的使用在应用程序中,而不是和tapestry web framework 绑定的。
76 楼 icewubin 2008-03-14  
<div class='quote_title'>ozzzzzz 写道</div><div class='quote_div'>我觉得ajoo现在有些跟自己较劲的意思。其实就这个事情来说,本无所谓对错,都有道理。关键是自己的权衡和选择。 <br/>而之所以我最近很少发表对java社区的看法,原因当然是我自己对java就不太通,水平不够。但是我还以为,java社区的框架看似不少,但是真正的说起来,又没多少。这些框架之间的哲学思路其实分析起来,仅仅是细节层面的不同,而无本质上的区别。而现在构架师满天飞,又看不出哪个出来设计一个自己的框架来。要说grails哲学稍微有所不同,但是又是外来户,不能算本土球员。 <br/>而本身java社区的框架层出不穷,就说明java这里需要框架这样的开发套路。而同时又可以说明,这些套路又都不是令人满意。因此我看,与其发明更多的套路,不如发明组织套路的法子出来,叫大家学会这个法子,自己整自己的套路出来来得彻底。</div><br/><p>你这样说未免也太大了吧,从宣传上来讲,各个框架都有各自的宣传渠道或者是相当数量的布道者,每年都有相当数量的框架和自己号称是框架的东西出现,暂且认为都是框架吧,这些框架有些是特定条件下的产物,如早期的struts和webwok都是某些人基于在公司中的需要衍生出来的,有些是挂羊头卖狗肉如IBM在幕后操纵的,还有些一开始就为了商业目的启动的。还有些是为了解决特定领域的问题,你说的好像仅仅局限在web框架中啊。我认为即使是在web框架中,根据不同的系统特性,本来就有很多种业务特点和系统特点,有多种适合不同情况的框架的选择权本身就很好,难道一定要像微软那样大家都用一套,听起来不错,能减少重复劳动,实际呢,垄断带来死气沉沉和不思进取,从这个角度上来说新的框架出现对老框架地推动和鞭策也是很有效果的。</p><p> </p><p>组织套路也算是个领域,也有类似框架和方法论的。“java这里需要框架这样的开发套路”不等于“我们需要把所有的框架集成起来”。</p>
75 楼 sorphi 2008-03-14  
谢谢ajoo。资源定位器这个概念我理解了。不过我对REST的理解很肤浅,可能太局限于现有这些框架的路子。某个框架,或者某个想法出来了,首先用熟悉框架的经验去考察它。
74 楼 ozzzzzz 2008-03-13  
我觉得ajoo现在有些跟自己较劲的意思。其实就这个事情来说,本无所谓对错,都有道理。关键是自己的权衡和选择。
而之所以我最近很少发表对java社区的看法,原因当然是我自己对java就不太通,水平不够。但是我还以为,java社区的框架看似不少,但是真正的说起来,又没多少。这些框架之间的哲学思路其实分析起来,仅仅是细节层面的不同,而无本质上的区别。而现在构架师满天飞,又看不出哪个出来设计一个自己的框架来。要说grails哲学稍微有所不同,但是又是外来户,不能算本土球员。
而本身java社区的框架层出不穷,就说明java这里需要框架这样的开发套路。而同时又可以说明,这些套路又都不是令人满意。因此我看,与其发明更多的套路,不如发明组织套路的法子出来,叫大家学会这个法子,自己整自己的套路出来来得彻底。
73 楼 ajoo 2008-03-13  
* - Your class is not testable!

field基本上都是private的。你没法在test case里面给它设一个mock值。Guice不象Spring,它老老实实告诉你,写单元测试不要靠容器,而是用JUnit/TestNG。

* + Only thing that works for some strange edge cases

不清楚。可能是说lifecycle的情况或者你需要做除了赋值以外的其它特殊动作。

* - Useless when Guice can't do instantiation itself, e.g. a servlet

servlet是由servlet容器直接调用无参构造函数创建的,Guice插不进去。

至于说这个rest的例子。我觉得warp和我的理想用法的共同点都是:直接的domain模型,一个对象代表一个资源。所以对rest method的响应不在这个pojo里面。分歧只在于我希望更直接的构造函数完成一切,而不是一些人为定义的特殊事件。

一个假想的用法是:
interface ResourceLocator {
  <T> T getResource(String path, Class<T> resourceType);
}

class FooServlet extends HttpServlet {
  private ResourceLocator locator;
  public void doGet(HttpServletRequest request, HttpServletResponse response) {
    Foo foo = locator.getResource(request.getServletPath(), Foo.class);
    // foo对象就是一个完全注射好的,对象当前请求的资源的实例。
    response.getWriter().write(foo.getName());
  }
}
72 楼 瞬间爱情 2008-03-13  
   呵...
           很不错额...'
71 楼 sorphi 2008-03-13  
看来ajoo大哥很喜欢immutable,所以尤其喜欢Constructor injection

引用
Guice best practices
Field vs. method vs. constructor injection

Field injection

    * + Most compact syntax (good for a trivial custom provider, e.g.)
    * - Can't take any special action upon injection
    * - Your class is not testable!

Method injection

    * + Isn't field injection
    * + Only thing that works for some strange edge cases

Constructor injection

    * + Fields can be final!
    * + Injection cannot possibly have been skipped, even if Guice is not in the picture
    * + Easy to see dependencies at a glance
    * + It's what the idea of construction is all about
    * - No optional injections
    * - Useless when Guice can't do instantiation itself, e.g. a servlet
    * - Subclasses need to "know about" the injections needed by their superclasses
    * - Less convenient for tests that only "care about" one of the parameters


不过上面有些概念还是没有很多经验来体会差别,劳烦ajoo大哥您给讲讲?比如
    * - Your class is not testable!
    * + Only thing that works for some strange edge cases
    * - Useless when Guice can't do instantiation itself, e.g. a servlet

你举的那个代码,每个请求都要对应一个action的构造函数,那怎么用url/actionmethod mapping?根据struts2.1的rest plugin,我臆想了一段伪码如下:

public final class BlogsController {

  private final Blogs blogs;

  @Inject
  public BlogsController(Blogs blogs){
    this.blogs = blogs;
  }

  /** GET /blogs/?page={page} */
  @Resource("/blogs/") @RestMethod("GET") @RestAccept("text/html")
  public Renderer index(@RestParam("page") int page) {
    return new Renderer("index.html")
       .put("blogs", blogs.list(page));
  }

  /** GET /blogs/1 */
  @Resource("/blogs/{id}") @RestMethod("GET") @RestAccept("text/json")
  public Renderer show(@RestParam("id") String id) {
    Blog blog = blogs.get(id);
    return new Renderer("show.json")
       .withEtag(...)
       .lastModified(blog.getLastModified())
       .put("blog", blog);
  }

  /** PUT /blogs/1 */
  @Resource("/blogs/{id}") @RestMethod("PUT") @RestAccept("text/html")
  public Renderer update(???) {
    // how to do when we need to store some values from request into pojo but can't change pojo's 
    //state for protecting ajoo's faith? varargs in method scope?

    //prepare , parameter/property binder, then save

    return index(0);
  }

  ...
}

public class Renderer {

  private Map context;

	public Render(String result);
	@Inject	public void setResponse(HttpResponse res);
	@Inject	public void setResponse(HttpRequest req);

	public put(String key, Object value);
	public void render();

  ...
}


action pojo想要immutable,就得需要写mutable的Renderer和Binder之类的设施来存放中间状态。只不过是换了个地方而已。
70 楼 ajoo 2008-03-13  
robbin 写道
ajoo 写道
robbin 写道

我不这么看。这个ViewBlog类似Webwork的Action,本身是prototype的,每次请求创建,为啥就不能有状态呢?就是RoR的controller也是一样,每次请求创建controller实例。

再说@Event,这个就是Webwork里面的Interceptor的东西,起到AOP作用的,在RoR里面也有类似的Filter概念,没觉得加一个@Event怎么会复杂。

不过话说回来,在ViewBlog这个具体的例子当中,使用@Event的方式来初始化数据,的确没有必要,例子举的不恰当。

状态不可怕,可怕的是状态变迁。这个例子里面,就涉及了before initialized和initialized两个状态。而且优先使用immutable也是基本的best practice吧?Guice也是强调constructor injection的。

interceptor不会有状态变化,所以无所谓。要说这个,更象servlet的init(),老掉牙很丑陋的东西。

你说的固然有道理,但更像是一种编程味道的好恶,特别是这个例子的确举的不好。但它这样用,也不会导致代码出啥问题吧?


一个框架的评判很多时候是不能不去闻味道的。象这种给pojo强加一个特殊的中间状态并且不允许immutable的,我觉得不是很轻量,而且也和Guice的一贯精神不符。
69 楼 icewubin 2008-03-13  
<div class='quote_title'>robbin 写道</div><div class='quote_div'><div class='quote_title'>xpf7622 写道</div><div class='quote_div'>问一下Robbin: <br/>感觉你以前极力推荐Rails,现在又推荐warp,不知在实际项目中你会选择那个. <br/>JavaEye3.0还是用Rails做,能不能用Warp做呢? <br/>能否分析一下这两个框架各自优势么? Warp和Rails比,谁的效率高?</div><br/><br/>好的工匠精通各种工具的使用,他知道在什么情况下用什么工具适合做什么家具; <br/><br/>差的工匠永远只会手里拿着一把锤子,用这把锤子去锤所有的东西,你今天告诉他Java这把锤子做书柜好,他就拿Java这把锤子锤所有的家具,明天你告诉他Rails这把锤子做桌子好,他就把Java这把锤子扔掉,用Rails这把锤子锤所有的家具,后天你告诉他Java这把锤子做大衣柜很合适,他又把Rails锤子扔掉,一边用Java锤子锤桌子,一边疑惑的问你?你不是说要用Rails锤子的吗?怎么现在又用Java这把锤子了?然后他又不依不饶的问你,你给我比较比较究竟是Java锤子好用,还是Rails锤子好用?谁有前途,谁做家具的效率高?我究竟该用哪把锤子锤所有的家具呢,究竟该扔掉哪把锤子呢? <br/><br/>所以这种问题根本就是错误的问题,好的程序员要具备很强的快速学习能力,深入了解常用编程语言和框架优势劣势和适用的场景,然后根据实际情况去灵活的选择。而不是企图孤注一掷的寻找一种所谓的万金油编程语言,然后死抱着不放,企图用它干任何事情,眼睛里面容不下任何其他技术。 <br/><br/><br/><br/><br/></div><br/><p>选择权往往不在程序员手里的,一般一个项目是一个团队的事,作为技术架构师或者技术经理一般作这个选择,选择的过程并不是你所说的“企图孤注一掷的寻找一种所谓的万金油编程语言,然后死抱着不放,企图用它干任何事情,眼睛里面容不下任何其他技术。”,初期一定是想听听各种人的意见,仅仅是听意见而已,实际作选择的时候要考虑很多方面,选择的过程是找平衡点的过程。当然对我来说,你的意见是比较重要的,或者说你的意见中的理念是很值得参考的。</p><p> </p><p>话说回来,这个世界从来不是最好的技术成为最流行的技术,虽然我们朝这个方向努力,当初Hibernate的成功也算是努力的结果,但是市场格局出现很多意想不到的结果,个人以为即使是技术架构师必须要考虑很多非技术的因素,我记得有一个回英文贴的一个观点非常好,要重视这个框架背后操作的团队是谁。</p>
68 楼 manmoon 2008-03-13  
java体系发展到现在,我感觉应该是浓缩的时候了,这样才能到达另外一个高度。我估计很多开发者都在期盼sun出来一整江湖。
67 楼 manmoon 2008-03-13  
零配置是没了,都转向硬编码了,我看不出annotation 比配置文件好到哪里。
66 楼 robbin 2008-03-13  
ajoo 写道
robbin 写道

我不这么看。这个ViewBlog类似Webwork的Action,本身是prototype的,每次请求创建,为啥就不能有状态呢?就是RoR的controller也是一样,每次请求创建controller实例。

再说@Event,这个就是Webwork里面的Interceptor的东西,起到AOP作用的,在RoR里面也有类似的Filter概念,没觉得加一个@Event怎么会复杂。

不过话说回来,在ViewBlog这个具体的例子当中,使用@Event的方式来初始化数据,的确没有必要,例子举的不恰当。

状态不可怕,可怕的是状态变迁。这个例子里面,就涉及了before initialized和initialized两个状态。而且优先使用immutable也是基本的best practice吧?Guice也是强调constructor injection的。

interceptor不会有状态变化,所以无所谓。要说这个,更象servlet的init(),老掉牙很丑陋的东西。

你说的固然有道理,但更像是一种编程味道的好恶,特别是这个例子的确举的不好。但它这样用,也不会导致代码出啥问题吧?
65 楼 ajoo 2008-03-13  
robbin 写道

我不这么看。这个ViewBlog类似Webwork的Action,本身是prototype的,每次请求创建,为啥就不能有状态呢?就是RoR的controller也是一样,每次请求创建controller实例。

再说@Event,这个就是Webwork里面的Interceptor的东西,起到AOP作用的,在RoR里面也有类似的Filter概念,没觉得加一个@Event怎么会复杂。

不过话说回来,在ViewBlog这个具体的例子当中,使用@Event的方式来初始化数据,的确没有必要,例子举的不恰当。

状态不可怕,可怕的是状态变迁。这个例子里面,就涉及了before initialized和initialized两个状态。而且优先使用immutable也是基本的best practice吧?Guice也是强调constructor injection的。

interceptor不会有状态变化,所以无所谓。要说这个,更象servlet的init(),老掉牙很丑陋的东西。
64 楼 robbin 2008-03-13  

我不这么看。这个ViewBlog类似Webwork的Action,本身是prototype的,每次请求创建,为啥就不能有状态呢?就是RoR的controller也是一样,每次请求创建controller实例。

再说@Event,这个就是Webwork里面的Interceptor的东西,起到AOP作用的,在RoR里面也有类似的Filter概念,没觉得加一个@Event怎么会复杂。

不过话说回来,在ViewBlog这个具体的例子当中,使用@Event的方式来初始化数据,的确没有必要,例子举的不恰当。
63 楼 dboylx 2008-03-13  
ajoo 写道
2。什么东西一旦有生命期,有状态变化,有事件,利马这复杂度就上去了。这个什么@OnEvent @PreRender用的着么?还明显强迫对象不能immutable。



楼上说的深有体会, 像SEAM里的会话上下文, 工作区管理

再加上几个新概念,学习曲线也水涨船高。
62 楼 ajoo 2008-03-13  
正好工作中需要用一个非常轻量的rest框架。看了restlet,感觉作者受servlet毒害太甚,什么Request, Response,这么一层一层的包装不累么?

然后看warp,看到这个示例,觉得不是很清楚,拿出来讨论一下:
@URIMapping("/blog/{subject}")
public class ViewBlog {
  private Blog blog;

  @OnEvent @PreRender
  public void init(String subject) {
    this.log = listBlogs.getBlog(subject);
  }
}


不满意的地方:
1。从rest的角度,我总觉得@URIMapping不如叫@Resource合适。这是命名问题。
2。什么东西一旦有生命期,有状态变化,有事件,利马这复杂度就上去了。这个什么@OnEvent @PreRender用的着么?还明显强迫对象不能immutable。


我希望的理想状况应该是:

@Resource("/blog/{subject}")
public final class ViewBlog {
  private final Blog blog;

  @Inject public ViewBlog(@RestParam("subject") String subject) {
    this.log = listBlogs.getBlog(subject);
  }
}


这样,对象还是完全遵守immutable对象规范,单一状态,线程安全,完全pojo。

从domain设计上说,每个pojo实例完全代表一个独立的资源,而不是service handler或者说transaction script模式。不明白为什么warp不这样做。

61 楼 xyz20003 2008-03-12  
return null在他的blog例子里出现了,是写在类里的,不是接口。

@Named是guice的那个,需不需要绑定,还真不晓得。

相关推荐

    warp-persist-2.0-20090214.zip

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

    Themes-Warp-Framework-7:一款快速和简洁的主题框架,它提供了丰富的工具集,用于开发跨平台的主题。这里是中文文档

    Themes-Warp-Framework-7 一款快速和简洁的主题框架,它提供了丰富的工具集,用于开发跨平台的主题。 适用于YOOtheme出品的基于 Warp 7 框架的所有 Wordpress 主题和 Joomla 模板。 中文语言包:

    Warp Framework-开源

    Warp框架是使用Python构建的应用程序框架。 它具有仅基于元数据的智能属性和对象管理功能。 当前支持Zope,并具有将其扩展到基于GTK / SQL / etc。的应用程序的空间。

    Cloudflare_WARP_Release-x64.msi

    Cloudflare_WARP_Release-x64.msi

    Python库 | warp10-jupyter-0.1.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:warp10-jupyter-0.1.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    ovh-warp10-datasource:用于Warp10平台的Grafana数据源

    Grafana Warp 10:trade_mark:数据源插件 安装插件 使用grafana-cli sudo grafana-cli plugins install ovh-warp10-datasource installing ovh-warp10-datasource @ 2.2.0 from: ...

    Cloudflare_WARP_Release-x64.msi.cab

    Cloudflare_WARP_Release-x64.msi.cab

    Guice+Struts2+warp-persist 简单实例

    借助Guice+Struts2+Warp-persist来构建一个比较轻盈的web开发框架,目的是想抛砖引玉。随后还会将Scala部分整合进来,目的就是唯恐框架不烂!(*^__^*)。 对于代码的不妥之处欢迎各路高手斧正。 mail to : meconsea@...

    warp-proxy:生成代理或模拟服务器的命令行工具

    一个简单的命令行,用于快速启动Web服务器,该服务器将您的请求代理到外部服务器或本地文件(JSON)。 对于测试和开发非常有帮助。 不用于生产。 使用风险自负。 入门 使用安装warp-proxy: npm install warp-...

    Python库 | warp_rnnt-0.0.3.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:warp_rnnt-0.0.3.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    百度开源的人工智能软件 WARP-CTC.zip

    2016年新年伊始,百度硅谷实验室向 GitHub上传了 Warp-CTC C 代码库,并在一篇博客文章中鼓励开发者使用这些代码。据悉,CTC 代码结合了多个不同的神经网络设计,以处理不完美的数据集,并采用更复杂的数据模式,...

    warp-cli:使用祝福构建的CLI工具集原型

    经线 基于Blessed库的CLI工具集原型 概述 安装 $ npm install warp-cli --save 用法 $ npm start

    meta-warp7-distro:WaRP7的Yocto项目

    meta-warp7-distro 该自述文件包含有关构建meta-warp7-distro DISTRO层的信息。 有关详细信息,请参见下面的相应部分。 快速开始 要获取BSP,您需要安装回购协议并将其用作: 安装回购实用程序: $: mkdir ~/bin...

    warp-rnnt:CUDA-Warp RNN-换能器

    一个GPU实现RNN换能器(格雷夫斯 , )。 该代码是从移植的(由Awni Hannun编写),并且充分利用了CUDA warp机制。 损失的主要瓶颈是基于动态规划算法的前进/后退。 特别是,存在一个嵌套循环,用于填充形状为(T,...

    warp-plus-cloudflare:在Warp +上获取无限GB的脚本(https

    一个在Warp +上获得无限GB的项目( ) [?!]更新日志 修复gui版本(v 2.0)。 修复gui版本(v 2.1)ssl错误。 下载适用于Windows OS的App 测试在线版本 [?]如何在Windows,Mac,Linux上使用此脚本 首先下载...

    Go-warp让您通过一个简单的命令安全地共享您的终端

    warp 让您通过一个简单的命令安全地共享您的终端

    百度硅谷warp-CTC

    Warp-CTC是百度前期为了在最新的计算机芯片上更快速运行而专门研发的一种改良版深度学习算法。

    Cloudflare-WARP优选IP,解决使用限制

    为了解决这个烦恼,大佬们推出了很多好用的工具来解决这个麻烦,这里上传的就是其中一个,相当好用的,通过精选一些可用的ip,实现Cloudflare原始功能,亲测选择延迟最低的那一个ip就好了,有很多可以选择的ip,网速...

    Guice2.0+Hibernate3.2+warp-persist-2.0+Struts2+JPA

    轻量级的Guice2.0代替了Spring,速度更快,项目体积更小,Hibernate3.2与JPA的结合使用代替了传统的配置文件,使Hibernate的开发更简单,本项目基本上是零配置开发,由于我只能上传小于15M的文件,故JAR被我删除了,...

Global site tag (gtag.js) - Google Analytics