论坛首页 Java企业应用论坛

Without SSH/JSP/Servlet,不走寻常路,Java可以更酷

浏览 213671 次
该帖已经被评为精华帖
作者 正文
   发表时间:2009-11-20  
app下不行么?
0 请登录后投票
   发表时间:2009-11-20  
刚才试了一下,在app下建了个util包,里面放了个随便写的DateUtil类,在controller里引用成功。
0 请登录后投票
   发表时间:2009-11-21  
佩服博主的学习能力,把罗列的技术全部看一遍都不是个轻松事,何况深入学习。
对博主提出的解决方案也很欣赏,但如何把你的这个做成标准 或者产品有点担心,希望你能持之以恒的做下去。
0 请登录后投票
   发表时间:2009-11-24  
"以关系数据库为中心的设计思想"
这一节说的相当不错,同感,虽然我不会JAVA
0 请登录后投票
   发表时间:2009-11-25  
充分利用编译器这点很帅。

问个问题:没看出怎么处理多个应用中使用不同版本jar包,是否有意的不考虑部署多个应用?
0 请登录后投票
   发表时间:2009-11-25  
garid 写道
作为技术学习还可以,真正的企业级软件在产品发布后不是随便改源代码,也不怎么需要重启服务器,就算要重启服务器,一般都是集群的,可以一台一台更新部署。个人看法,这个框架应该是华而不实。

不同的设计针对不同目标用户了。不需要集群的场合还是很多的。
我感觉这个设计针对的目标就是快速开发较小规模的系统。

没考虑多应用也没考虑集群确实是个问题,但可以以后再说。
MySQL一开始也不强吧,现在发展得多好。

我觉得斗鱼应该考虑怎么分多个项目放出来。
0 请登录后投票
   发表时间:2009-11-26   最后修改:2009-11-26
miaow 写道
充分利用编译器这点很帅。

问个问题:没看出怎么处理多个应用中使用不同版本jar包,是否有意的不考虑部署多个应用?



是的,是有意这么做的,
不想使用传统的每一个应用一个子目录的方式,
传统方式在处理uri时,应用目录前缀是一件很烦人的事,
比如在webapps下建了个应用子目录examples,那么在html中写uri时就得很小心。
如果要支持多个应用也是简单的,可以采用虚拟主机的方式,
通过请求uri中的hostname部份(或者Host请求头)就可以区分不同的应用了。


刚刚用google搜douyu时,发现了这个:
关于国人项目Douyu的初步分析

 

看来还是有挺多人对实现细节感兴趣的,

不过CSDN的Blog真的不想说什么了,把我在上面的评论也发到这里吧,

最近这三个月Douyu可能没有什么动静,所以下面的话就算是Douyu的一些“八卦”了:

 

 写道
我是Douyu的作者ZHH,
首先很感谢cping1982对Douyu的关注。

有感于网络的强大,
虽然没在CSDN发表任何有关Douyu的文章,
但是通过baidu、google还是很容易找到相关内容。

最近的精力集中在Junit、Freemarker、Ehcache的源码研究上,
希望从这三个流行的开源框架中寻找一些灵感,
以便Douyu能在自动化测试、View、缓存这三方面有一些突破。

我对Http1.0/1.1协议还是有一点研究的,
你所讲的gzip没有实现,这个不难。
目前Douyu只是0.1版,内置的Http服务器也很简单,
像Transfer Codings这些基本的东西都没有完全实现,
0.1版的Douyu就像你说的一样是用来尝试这种新的开发思路是否可行,
而不是马上就要样样去实现,只要思路是对的,完善她只是时间问题。

还要一点,我可能会考虑放弃开发Http服务器了,
Douyu内置的Http服务器只作为开发用途,下一步会考虑给Tomcat加个插件,
然后Douyu把所有的Java源文件、View模板、数据库模型类静态生成class文件,
把生成的class文件和其他静态资源打包后就可以在Tomcat中部署了。

另外,以下包中的代码是面向开发人员的:
com.douyu.config
com.douyu.http
com.douyu.main
com.douyu.security
com.douyu.sql

上面这些包中大多数是接口和一些简单的工具类,
就好比javax.servlet与javax.servlet.http,
如果将来有别的个人或团体或公司对Douyu感兴趣,
那么只要他实现了上面的包中定义的相关接口,
完全可以替换Douyu的默认实现的(就好比现在有不同的JSP/Servlet容器一样)。

com.douyu.engine包中定义的类就是Douyu的默认实现,
比如com.douyu.engine.http包中的很多类就是com.douyu.http的默认实现。
com.douyu.engine包中定义的类是不向开发人员开放的。

(P.S. 你发的那个Eclipse插件生成的关系图太复杂了,连我自己都看得晕)

Douyu的技术实现细节难点不在于http也不在于db,而是要对Javac足够熟悉,
知道Javac编译源代码的所有细节,然后你才知道在哪一步发挥Javac的作用,
整个com.douyu包中的源代码加起来也不过3万行左右。
com.sun这个包中的源代码才是难点。


最后,这三个月内会对Douyu作一些大的改动,
估计下一个版本就会放出源代码了,
所以我建议你别花心思分析反编译后的代码了,呵呵,这样看起来很痛苦的,
如果你对Douyu的实现有兴趣,可以关注我在JavaEye的blog。



 

 

 

0 请登录后投票
   发表时间:2009-11-26  
很佩服楼主的精神,不过这个把所有东西都包含起来的大杂烩会不会过了点?或者说重量大了点?
0 请登录后投票
   发表时间:2009-11-29  
ZHH2009 写道
标题的构思来源于Rod Johnson的那本"Without EJB"以及CCTV5中一句耳熟能详的广告词,
不过此文并不是用来批判SSH(Struts、Spring、Hibernate)/JSP/Servlet的,
也不是为某品牌做广告,而是用来分享这将近一年来的研究心得。

去年圣诞节时曾在JavaEye发过一两篇文章,不过现在找不到了,
文章内容提到要在3个月左右的时间内设计出一个有别于SSH的新型MVC框架,
设计的起点最初是以JSP/Servlet为基础的,虽然在两个多月后有了个雏形,
但是跟Rails这样的框架相比还是没有明显的优势,
比如在不使用反射的情况下,
很难将不同的uri对应到Servlet类中的public方法。
(Servlet类指的是继承自javax.servlet.http.HttpServlet的类)
每次修改Servlet类的源代码时总得经过烦人的手工编译步骤(有时还不得不重启Tomcat),
还有与数据库打交道的模型层也得人工干预,一堆烦人的映射配置。

那三个月内时常有沮丧感,似乎已走近了死胡同!
后来心一狠,决心甩开JSP/Servlet那一堆条条框框,把设计的起点再往下深一个层次。
因为2007年曾详细研究过Java语言的编译器(javac)实现细节,所以从编译器着手,
但是编译器的强项在于分析Java源代码,无法处理Http请求,
接着在网上把Tomcat6的源代码下下来研究了三个月,
期间顺便研究了Sun公司的超轻量级Http服务器"com.sun.net.httpserver"的源代码,
同时详细学习HTTP/1.0(RFC1945)与HTTP/1.1(RFC2616)协议。

但是Tomcat6过于臃肿了,包含的Java文件超过了1300个,
光是解析server.xml与web.xml的代码看完后就让人有烦躁感。
(如org\apache\tomcat\util\digester与org\apache\catalina\startup包中的很多类)

另外最重要一点,Tomcat6采用的是Eclipse JDT编译器,仅仅是用来编译JSP文件,
编译器在控制层没有发挥一点作用。
而Sun公司的超轻量级Http服务器又过于简单了,连HTTP/1.1的大多数功能都没实现,
除了参考一下它的SSL实现外基本上毫无价值。

本想在现有的JSP/Servlet容器上做一下简单扩展就得了,
哪知也是四处碰壁(还下过Jetty的源代码下来看了一会,结果发现比Tomcat6还糟),
后来决定对Tomcat6与Sun的Http服务器进行大刀阔斧的改造,
完成了一个精简版的改良后的基于NIO的Http服务器(目前的版本只有60个左右的Java源文件),
并且能跟Javac编译器完美结合,能直接运行Java源文件。

在模型层这一块,最初是从书上和网络上对Hibernate进行应用层次的研究,
但是并不想深入源代码,因为代码量也实在是太多了,倒是对Ibatis2.0深入研究了一下,
Ibatis2.0代码量比较少,也简单,看了不到一星期就基本上看完了,不过现在并没留下深刻映象,
因为并没发现什么特别出彩的地方,Ibatis2.0还是离不开xml,而我想要完全抛弃xml。

当然,不管Hibernate也好,Ibatis2.0也好,相比Rails的ActiveRecord还是逊色了点,
不过我的目标并不是要造一个Hibernate、Ibatis2.0或ActiveRecord这样的轮子,
我的要求更高,我在想如何才能写更少的代码,如何才能实现自动化?
可不可以在服务器启动时或运行时动态解析数据库的元数据,
让编译器跟据这些元数据动态生成类呢?
接着我转去研究JDBC-1.2/JDBC-2.1/JDBC-3.0/JDBC-4.0规范,研究数据库驱动的开发手册。
我得从零开始,我目前的实现是这样做的:你可以在你自己的Java源文件中直接引用动态生成的类,
就像这些类是你自己写的一样,ORM已基本上实现自动化了,2.9 节专门讲Douyu的ORM。

最后一点值得一提的是,我在Java语言层次引入了权限管理模型,
不过你别担心,我并没有引入新的Java语言语法,
只是借助Annotation扩充了某些特殊的语义。
目前这个权限管理模型的粒度只是划分为功能、字段权限两个等级,
并没有实现与具体业务相关的数据权限,不过在未来的路线图中有打算引入工作流模型,
到时会努力尝试各种实现数据权限的方案。

与权限相关的细节请看2.8节 Douyu的权限模型



折腾了半年后,发现已不再是个MVC框架了,我想称为平台更合适,
一种运行在JVM之上的新型平台,我给她起了个名字: Douyu
(呵呵,名字的由来暂时保密,也许你能猜出来。。。)



虽然孤军奋战将近一年,自我感觉小有成就,但是还有很多不怎么满意的地方,
各位大牛们也许更牛,看见不爽砸砖头便是。



Ok,上干货。




1. 安装配置


(这里只针对Windows平台,特别是XP操作系统,因为我没其他试验环境)



1.1 安装JDK


Douyu是在JDK1.6下开发的,不支持也不打算支持JDK1.4及更早的版本,JDK1.5我没有测试过,
所以我只能推荐你安装JDK1.6了,安装细节我想你都会,
唯一要注意的一点是:最好是建个JAVA_HOME环境变量,然后把%JAVA_HOME%\bin加入到Path中,
因为在Douyu服务器的启动脚本中并没有进行过多的环境检测,
而是直接使用了%JAVA_HOME%\bin目录下的java命令来启动Java HotSpot VM。


1.2 安装Douyu服务器

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

请先下载二进制版的压缩文件:
http://douyu.googlecode.com/files/Douyu_0_1_0.rar

目前的版本是:0.1.0,版本号很小,但大多数功能都包含了,
我并不推荐你用于工业级别的产品开发,
因为还不稳定,目前只适合分享、交流、尝鲜目的。

下下来后直接解压到一个你选定的目录(假定你解压到了D:\Douyu目录)

D:\Douyu目录里头有下面7个目录(跟Tomcat6差不多):
apps  //应用程序的源代码放在这里,里头有一些java源文件是下面的演示中用到的,当然你可以全都删了。
bin   //服务器的启动脚本和运行时类库都在这里
conf  //服务器的配置文件放在这里
lib   //应用程序使用到的第三方类库(比如数据库驱动)都放在这里,初始情况下是个空目录
logs  //存放服务器运行期间的日志(目前日志只是输出到控制台),初始情况下是个空目录
temp  //服务器运行期间用到的临时文件夹(比如上传文件时可能会用到),初始情况下是个空目录
work  //服务器运行期间的工作目录,初始情况下是个空目录

了解了这些就足够了,目前你不需要做任何配置。







2. 体验Douyu



2.1 如何运行Douyu服务器?


点"开始->运行",输入cmd,打开一个控制台,切换到D:\Douyu\bin目录,
然后输入 douyu  启动Douyu服务器 (要关闭Douyu服务器连按两次Ctrl+C既可)
见下图:



如果你是第一次打开操作系统第一次启动JVM运行Java程序
或是隔了一个小时左右重新启动JVM运行Java程序,这时可能要等待几秒钟(5--10秒),
出现这种情况并不是Douyu服务器的问题,而是JVM本身或操作系统的问题,
通常启动Douyu服务器如果不加载数据库的话,一般在一秒钟内就能启动完成了。

Douyu服务器默认情况下监听的主机名是: localhost,端口: 8000

如果你不喜欢这样的默认配置,
或者最常见的情况是端口8000被占用了
(一般抛出异常: java.net.BindException: Address already in use)
你可以打开conf\server.java这个服务器配置文件,
配置文件本身就是一个java源文件,参数的配置使用Java语言的Annotation语法,
所有与服务器配置有关的都是Annotation或是Enum,全都在com.douyu.config包中定义。
import com.douyu.config.*;

@Server(
	port=8000,
	.................



要修改默认主机名和端口,请修改hostName和port的值,
hostName是一个字符串,可以用IP地址来表示,port是一个整型(int)值。


其他很多参数先不罗列了,使用到时再详细说明。


当你修改了conf\server.java后,你也不需要自己去手工编译它,
启动Douyu服务器时,Douyu会自行决定是否要编译它。
如果conf\server.java存在语法错误,那么编译失败,
Douyu服务器的启动也会失败,同时向你显示编译错误信息。



下文中假定Douyu服务器已启动,监听的主机名是: localhost,端口是: 8000
以下所有例子都经过严格测试了,

我的JRE版本:
D:\Douyu\bin>java -version
java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Client VM (build 14.2-b01, mixed mode, sharing)

测试浏览器用了两个:

傲游浏览器(IE6.0),
谷歌浏览器(Chrome 3.0.195.27)





2.2 Hello World!



2.2.1 程序代码


//对应apps\HelloWorld.java文件

import java.io.PrintWriter;
import com.douyu.main.Controller;

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


2.2.2 手工编译已经Out了,你再也不需要这一步了。


2.2.3 运行HelloWorld

打开你心爱的浏览器,输入 http://localhost:8000/HelloWorld
如果你能看到下图中所示内容,恭喜你,你己经进入了Douyu的精彩世界。



(注:这是你第一次直接运行Java源文件,可能会等几秒钟(2--4秒),因为Douyu得初始化编译器)


2.2.4 程序代码说明

com.douyu.main包中的类大多数是Annotation,还包含一些重要的接口和类,
相当于java.lang,是你用Douyu开发程序时最常用到的,也是通往其他模块的快速入口,
本想让com.douyu.main包中的类像java.lang一样让编译器自动导入的,
但是考虑到很多开发人员更偏爱使用IDE,不同IDE内置的编译器不一样,
从而会引起找不到com.douyu.main包中的类的问题,所以最后决定放弃这样的设计了。

@Controller 这个Annotation是用来告诉Douyu这是一个控制器,
当你在浏览器的地址栏中输入http://localhost:8000/HelloWorld 这样的uri时,
浏览器内部通常会生成一个HTTP GET请求消息,消息内容类似这样:
GET /HelloWorld HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,......
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon)
Host: localhost:8000
Connection: Keep-Alive

不过这里并不打算介绍HTTP协议,如果你有兴趣,可以把RFC2616下下来研究。

Douyu服务器收到浏览器发来的请求消息后,
特别留意 "GET /HelloWorld HTTP/1.1" 这一行消息,
其中的"/HelloWorld"表示想要获取Douyu服务器上的哪些资源,
资源有静态的(如html、jpg等文件),也有动态的,在Douyu服务器中动态资源只有一种,
凡是带有@Controller这个Annotation的Java源文件都是可以直接通过uri访问的动态资源。

不过Douyu服务器不能根据uri的表面特征一眼就看出它是动态的还是静态资源,
服务器内部有一个专用的资源装载器,装载器的搜索根目录是从apps这个地方开始的,
资源装载器会尝试将apps目录与uri组合成一个java.io.File对象,
如果File对象存在,那么它就是一个静态资源,
然后由Douyu服务器内部的静态资源处理器给浏览器发送包含有文件内容的响应消息;

如果File对象不存在,资源装载器把请求的uri当成一个类名,
然后尝试采用类装载器的方式装载类,如果找不到那么就直接返回未找到(404)消息;
如果找到了,并且uri是第一次请求的,资源装载器会返回java源文件,
然后把java源文件交给Douyu服务器内置的编译器处理,编译器的处理过程很复杂,
这里就不深入说明了,总之它会为你动态生成HelloWorld的实例,
然后调用它的index这个缺省的public方法,
之后调用out.println()方法把"Hello World!"发送给浏览器。

0 请登录后投票
   发表时间:2009-11-29  
你好厉害呀,由衷地佩服
现在是凌晨1点多,偶很少熬夜的
你的帖子能坚持偶倒现在全部看完(包括80%的回帖)
你的代码,偶会明天带去公司好好研究的

偶会给予你最直接的帮助和支持,例如说帮楼主测试bug之类
而不像好多回帖的人在那里说风凉话打击人
他们那些人就想证明自己厉害,又没有什么实实在在的本事,又没见得对我们有什么贡献,就知道说大道理,对别人做的东西挑三拣四,自己又做不出什么像样的东西来。
javaeye里这种自以为是的人可多了,因为我身边也有这样的人,所以我很清楚他们平时的性格,可烦他们这些人了。所以师兄你有时候大可不必理会

师兄你要记得把尽量详细的文档和例子放到google里去托管啊
偶一定会去好好研究的。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics