职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 730|回复: 8

Douyu 0.6.1发布了,这是一个超乎您想象的Web框架

[复制链接]
话说我当年 发表于 2011-9-3 10:38 | 显示全部楼层 |阅读模式
  
自从2009年11月份发布第一个原型版本后,(见这里)
时间一恍就过去了1年半,
这段时间主要忙于工作了(从事分布式数据访问、存储以及Web容器方面的工作),
所以douyu一直处于停滞状态,直到今年3月份开始才能将1/3的时间投入到上面。


最初的版本抛弃了Servlet/JSP规范,并且自已实现容器,这思路理论上是没有大的错的,
但是太新潮了,原有的技术积累不能充分使用,所以但凡追求稳定第一的产品都不敢贸然尝试。


因此,douyu的设计思路也跟着变了,努力的方向是:
尽量兼容现有技术、寻求一种更简单更有效的办法改进现有技术。

douyu 0.6.1往这个方向迈出了第一步,
第一步主要关注Web层的东西,不涉及持久层,douyu 0.6.1包含了如下亮点:

1. 兼容Servlet/JSP,使用douyu提供的api写出的程序能部署到Servlet容器上(例如Tomcat、Jetty)


2. 基于Javac编译器技术,实现零配置,无需打包、部署,无需重启Servlet容器,直接运行Java源文件。


3. 支持Velocity、FreeMaker,集成其他模板引擎也是非常简单,多种模板引擎可以在同一个应用中同时使用。


4. 学习成本非常低,目前只需要学习5个接口(不超过15个方法)。


5. douyu 0.6.1源代码不超过1500行,所以非常适合初学者入门,如果想达到另一个境界,可以继续看Javac编译器的代码。




Douyu项目主页目前放在:
http://code.google.com/p/douyu/


以下是例子:

(可以从发布包的douyu-examples\WEB-INF\src中找到这些例子)


Hello World


  
@Controller  
public class HelloWorld {   
    public void index(PrintWriter out) {   
        out.println("Hello Douyu World!");   
    }   
}  

@Controller
public class HelloWorld {
        public void index(PrintWriter out) {
                out.println("Hello Douyu World!");
        }
}  


自动提取HTML表单参数:


Html代码  
<FORM METHOD=POST ACTION="FormExample.save">     
    姓名:<INPUT TYPE="text" NAME="name" VALUE="haha">  
    年龄:<INPUT TYPE="text" NAME="age" VALUE="100">     
    <INPUT TYPE="submit">     
</FORM>  

<FORM METHOD=POST ACTION="FormExample.save">  
    姓名:<INPUT TYPE="text" NAME="name" VALUE="haha">
    年龄:<INPUT TYPE="text" NAME="age" VALUE="100">  
    <INPUT TYPE="submit">  
</FORM>  


  
@Controller  
public class FormExample {   
    public void save(String name, int age) {   
        ...   
    }   
}  

@Controller
public class FormExample {
        public void save(String name, int age) {
                ...
        }
}
  

文件上传


Html代码  
   <FORM ENCTYPE="multipart/form-data" METHOD="POST" ACTION="FileUpload.upload">  
   文件1:<INPUT NAME="file1" TYPE="file" size="50"><br>  
文件2:<INPUT NAME="file2" TYPE="file" size="50"><br>  
  
说明 :<TEXTAREA NAME="description" ROWS="5" COLS="50"></TEXTAREA><br>  
  
   <INPUT TYPE="submit" VALUE="上传">  
   </FORM>  

    <FORM ENCTYPE="multipart/form-data" METHOD="POST" ACTION="FileUpload.upload">
    文件1:<INPUT NAME="file1" TYPE="file" size="50"><br>
        文件2:<INPUT NAME="file2" TYPE="file" size="50"><br>

        说明 :<TEXTAREA NAME="description" ROWS="5" COLS="50"></TEXTAREA><br>

    <INPUT TYPE="submit" VALUE="上传">
    </FORM>  


  
@Controller  
public class FileUpload {   
    public void upload(Part[] parts, Part part, String description) {   
        part.write(...);   
    }   
}  

@Controller
public class FileUpload {
        public void upload(Part[] parts, Part part, String description) {
                part.write(...);
        }
}  

嵌套Model自动注入:


  
@Model  
public class Consumer {   
    private String name;   
    private Address address;   
  
    public void set(String name, Address address) {   
        this.name = name;   
        this.address = address;   
    }   
}   
  
@Model  
public class Address {   
    private String country;   
    private String city;   
  
    public void set(String country, String city) {   
        this.country = country;   
        this.city = city;   
    }   
}  

@Model
public class Consumer {
        private String name;
        private Address address;

        public void set(String name, Address address) {
                this.name = name;
                this.address = address;
        }
}

@Model
public class Address {
        private String country;
        private String city;

        public void set(String country, String city) {
                this.country = country;
                this.city = city;
        }
}  


  
@Controller  
public class ModelInjectExample {   
    //通过这个url访问   
    //ModelInjectExample?consumer.name=zhh&consumer.address.country=china&consumer.address.city=hangzhou   
  
    //输出:   
    //consumer=Consumer[name=zhh, address=Address[country=china, city=hangzhou]]   
    public void index(Consumer consumer, PrintWriter out) {   
        out.println("consumer=" + consumer);   
    }   
}  

@Controller
public class ModelInjectExample {
        //通过这个url访问
        //ModelInjectExample?consumer.name=zhh&consumer.address.country=china&consumer.address.city=hangzhou

        //输出:
        //consumer=Consumer[name=zhh, address=Address[country=china, city=hangzhou]]
        public void index(Consumer consumer, PrintWriter out) {
                out.println("consumer=" + consumer);
        }
}  


最炫的功能:

可以在JSP、Velocity、FreeMaker中直接访问控制器Action中的本地变量:


  
@Controller  
public class ViewManagerExample {   
    public void soCool(ViewManager v, String name, int age) {   
        Date date = new Date();   
        v.out("/jsp/ViewTest.jsp");   
        v.out("/ViewTest.vm");   
        v.out("/ViewTest.ftl");   
    }   
}  

@Controller
public class ViewManagerExample {
        public void soCool(ViewManager v, String name, int age) {
                Date date = new Date();
                v.out("/jsp/ViewTest.jsp");
                v.out("/ViewTest.vm");
                v.out("/ViewTest.ftl");
        }
}  

ViewTest.vm


Html代码  
<HTML>  
<HEAD>  
<TITLE>ViewManager Test</TITLE>  
</HEAD>  
  
<BODY BGCOLOR="white">  
name = ${name} <br>  
age = ${age} <br>  
date = ${date} <br>  
</BODY>  
  
</HTML>  

<HTML>
<HEAD>
<TITLE>ViewManager Test</TITLE>
</HEAD>

<BODY BGCOLOR="white">
name = ${name} <br>
age = ${age} <br>
date = ${date} <br>
</BODY>

</HTML>  


异步Action


  
@Controller  
public class AsyncTest {   
    public void asyncAction(HttpServletRequest request) {   
  
        if (request.getAttribute("async-result") != null) {   
            doSomething();   
  
            request.getAsyncContext().complete();   
        } else {   
            AsyncContext actx = request.startAsync();   
            actx.setTimeout(10000);   
  
            invokeLongTimeService(actx);   
  
            ....   
        }   
    }   
}  

@Controller
public class AsyncTest {
        public void asyncAction(HttpServletRequest request) {

                if (request.getAttribute("async-result") != null) {
                        doSomething();

                        request.getAsyncContext().complete();
                } else {
                        AsyncContext actx = request.startAsync();
                        actx.setTimeout(10000);

                        invokeLongTimeService(actx);

                        ....
                }
        }
}  


最后,源代码在这,赶紧凑凑热闹吧:
svn checkout http://douyu.googlecode.com/svn/trunk/ douyu-read-only

google code的svn不太稳定,时好时坏:
源代码压缩包: 点我




郁闷小男人 发表于 2011-9-3 10:38 | 显示全部楼层
看完了,不知道你这个是搞什么的。介绍就不能给力些吗?

醉倚西风 发表于 2011-9-3 10:38 | 显示全部楼层
leibos 写道
看完了,不知道你这个是搞什么的。介绍就不能给力些吗?

标题写着"Web框架",
Struts、Spring MVC也是Web框架,Struts、Spring MVC总该听说过吧?

ksdal 发表于 2011-9-3 10:38 | 显示全部楼层
agapple 写道
LZ,我对你的异步Action挺感兴趣的,能深入多提点内部的一些点不?

这个异步操作,是实现了长链接的吗,反向推送?




这个异步Action是基于servlet3.0的异步api的,
如果不设置超时,不主动关闭,可以认为是长链接,
可以实现Server端主动推数据。


agapple 写道

还有一点,我一直对velocity和javac的整合挺感兴趣的,按照现在velocity的模板语言的特性,是无法明确知道Token对应的class信息。是不是需要在原先的模板信息上增加点东西? 比如建立Token和class的对应关系?



velocity和javac的整合并不是用javac对velocity模板编译的,
只是把action中的变量自动put到velocity的context中,

velocity模板静态编译这件事我另一个同事已做好了,因为还没开源,
所以我没打包到douyu,不过已经开始在内部使用这个经过修改的velocity了。


shmilyyu 发表于 2011-9-3 10:39 | 显示全部楼层
斗鱼重出江湖,先下个源代码研究研究。

爱车车 发表于 2011-9-3 10:39 | 显示全部楼层
    不会吧,这么快就有动作啦,我还以为要等到2012呢

走就走吧 发表于 2011-9-3 10:39 | 显示全部楼层
我认真地看了,觉得有点像 Apache Click的简化版。

已经来了吗 发表于 2011-9-3 10:39 | 显示全部楼层
去看看 play framework 吧  源码量也不是很大
scooter 也不错

月上萧萧 发表于 2011-9-3 10:39 | 显示全部楼层
强力抢占前排,这东西当初确实很抢眼,不过再看就没什么消息了
等了这么就终于有东西放出来了~
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-5-3 20:14 , Processed in 0.157602 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表