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

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这个...

    Cloudflare WARP Release-x64.msi

    Cloudflare WARP Release-x64 安装包

    Warp Framework-开源

    Warp Framework 是一个用Python编程语言开发的高效应用程序框架,其设计理念在于提供一种简洁而强大的方式来构建各种类型的应用。这个框架的核心特性是它的智能属性和对象管理机制,这些机制基于元数据进行操作,...

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

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

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

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

    rust-web-framework-comparison:比较一些用Rust编写的Web框架和库

    本文将深入探讨"rust-web-framework-comparison"项目,它提供了一个对比不同Rust Web框架和库的资源,帮助开发者选择最适合他们需求的工具。以下是关于Rust Web开发的一些关键知识点: 1. Rust语言基础: Rust是一...

    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: ...

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

    提供的压缩包名为`warp-cli-master`,这可能是一个包含了warp-cli源代码的完整版本,包括所有必要的文件和目录,如源码、测试文件、配置文件等。开发者可以查看源代码以了解其内部工作原理,甚至可以根据自己的需求...

    百度硅谷warp-CTC

    【百度硅谷warp-CTC】是百度公司在其硅谷研发中心推出的一种优化的连续标注计算(Connectionist Temporal Classification, CTC)实现,旨在提升在现代高性能计算硬件上的运行效率。CTC是一种常用的序列到序列模型的...

    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

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

    标题 "Go-warp让您通过一个简单的命令安全地共享您的终端" 涉及到的是一个基于Go语言开发的工具——Warp,它提供了一种便捷且安全的方式,让用户能够通过命令行分享自己的终端会话。这个工具对于远程协作、演示或者...

    Python库 | sol-warp-0.2.4.tar.gz

    标题中的"Python库 | sol-warp-0.2.4.tar.gz"指的是一个特定版本的Python库,名为sol-warp,版本号为0.2.4,并且它被压缩成一个tar.gz文件进行分发。在Python编程环境中,库(Library)是用于扩展其功能的模块集合,...

    Guice+Struts2+warp-persist 简单实例

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

    为Arch_Linux提供可安装的Cloudflare_Warp_ArchLinux-Warp-deb.zip

    为Arch_Linux提供可安装的Cloudflare_Warp_ArchLinux-Warp-deb

    Java_非官方的warp客户端android.zip

    Java_非官方的WARP客户端Android项目是一个针对Android平台的第三方实现,允许用户在移动设备上使用WARP技术。WARP(Wireless Application Protocol)是一种通信协议,旨在提高无线网络上的数据传输效率和安全性。非...

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

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

    meta-warp7-distro:WaRP7的Yocto项目

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

    warp:超级便捷,可组合的Web服务器框架,可提高扭曲速度

    Warp是一款用Rust编程语言编写的高效、轻量级且极其灵活的Web服务器框架。它以其易于使用、高性能和高度可组合性著称,为开发人员提供了一种编写Web服务的新方式。在了解Warp之前,我们先来看看Rust本身——一种系统...

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

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

Global site tag (gtag.js) - Google Analytics