`
ZHH2009
  • 浏览: 123283 次
  • 性别: Icon_minigender_1
  • 来自: 天堂
文章分类
社区版块
存档分类
最新评论

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

阅读更多
标题的构思来源于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!"发送给浏览器。
  • 大小: 27.3 KB
  • 大小: 8.7 KB
  • 大小: 14.8 KB
  • 大小: 13.2 KB
  • 大小: 13.4 KB
  • 大小: 11.1 KB
  • 大小: 20.4 KB
  • 大小: 27.3 KB
  • 大小: 63.7 KB
  • 大小: 75.4 KB
  • 大小: 14.7 KB
  • 大小: 22.6 KB
  • 大小: 22.4 KB
  • 大小: 22.8 KB
  • 大小: 24.4 KB
  • 大小: 23.9 KB
  • 大小: 28.5 KB
  • 大小: 36.9 KB
  • 大小: 24.1 KB
  • 大小: 52.6 KB
  • 大小: 77.3 KB
  • 大小: 101.3 KB
  • 大小: 54.2 KB
  • 大小: 122 KB
分享到:
评论
402 楼 doinsist 2010-11-10  
楼主,真厉害,我为了回复一下回答了好多问题。。。
401 楼 大海lb 2010-11-05  
楼主太强大了,我敬佩你
400 楼 大海lb 2010-11-05  
牛人啊,羡慕,高技术的就是不一样,好喜欢你哦。。。
399 楼 borland 2010-11-01  
楼主可否给个源代码学习下,或者关键代码也行
398 楼 yjshengshe 2010-10-31  
楼主,强人,期待楼主最新的研究成果。
397 楼 allcan 2010-10-29  
中国的大牛啊~
偶像,我还有很远的路要走啊,敬佩~搂住再接再厉~
396 楼 mdsp25xhm 2010-10-29  
哗~~骄傲,牛人也!
395 楼 sylarHong 2010-10-26  
强,有很多值得学习的地方。
394 楼 DOCDOC 2010-10-26  
rebornsteven 写道
想不到俺们广西还有这么牛的大神,不知道douyu现在是否有源码  可供我们这些小辈学习学习

大多数哭着喊着求源代码的主儿,是没这个水平看源代码的。
393 楼 掏掏潇雨 2010-10-26  
。。。LZ爆强,tomcat的代码我就没看懂
392 楼 ideniece 2010-10-25  
原来牛人是这样炼成的
391 楼 1sun1 2010-08-25  
LZ让我明白了,当初我为什么想成为一个JAVA程序员
你是我的偶像,也是我继续努力学习的动力
390 楼 kingsli 2010-08-17  
楼主疯了,过不到好久可能要出更疯狂的人物了
389 楼 herozk 2010-08-15  
asdasd
388 楼 rebornsteven 2010-08-13  
想不到俺们广西还有这么牛的大神,不知道douyu现在是否有源码  可供我们这些小辈学习学习
387 楼 yonlist 2010-08-13  
非常佩服LZ,我一直都在思考比Servlet更轻量级的方式
386 楼 ZHH2009 2010-08-13  

最近工作上的事情太多,好久没写点东西了,
不过我是建议大家不要顶这个帖了吧,特别是一些显得有些夸张的赞美,
听得多了,我都差不多快吐了 ,估计其他人看了也烦,如果实在想说,就发到我博客上吧,
那里发再多的水帖也不会污染大家的视线。 


385 楼 mmBlue 2010-08-12  
原来听项目经理提过douyu。。。今天膜拜一下,楼主真乃神人也。。。
384 楼 jh108020 2010-08-12  
lz真是神人,佩服
383 楼 sbfeeq 2010-08-12  
回复个话,要回答N个问题,烦啊

相关推荐

    《Java Servlet编程(第二版)》英文版 chm (含源码)

    The Java 2, Enterprise Edition (J2EE), specification has included servlets as a core component, and application server vendors wouldn't be caught dead without a scalable servlet implementation....

    Servlet查询数据库案例--Query(java源码)

    * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose. * You may distribute it non-commercially as long as you...

    openssh-server -Ubuntu18.04远程服务离线安装包

    依次运行下面命令进行安装: sudo dpkg -i openssh-client_1%3a7.6p1-4ubuntu0.6_amd64.deb sudo dpkg -i ncurses-term_6.1-1ubuntu1.18.04_all.deb ... 删除permitRootLogin后面的without-password后改为yes

    test-servlet3-without-webxml.rar

    servlet3 without webxml servlet3 without webxml

    servlet2.4doc

    Overrides the standard java.lang.Object.clone method to return a copy of this cookie. containsHeader(String) - Method in class javax.servlet.http.HttpServletResponseWrapper The default behavior of ...

    Redis-desktop redis管理工具 支持SSH 无bug版

    Redis-desktop redis管理工具 支持SSH,SSL,Advanced sessting 无bug版

    eclipse 反编译插件 java工具JadClipse

    eclipse 反编译插件 java工具JadClipse 将JadClipse插件(net.sf.jadclipse_3.3.0.jar)拷贝到{EclipseHome}/plugins文件夹下(如C:\Program F\eclipse-jee-kepler-R-win32-x86_64\eclipse\plugins)。JAD 解压到...

    DJ Java Decompiler 3.12.12.96 老朽痴拙汉化版(JAVA反编译)

    JAVA工具精品新译<5>DJ Java Decompiler 3.12.12.96 32位老朽痴拙...你不需要安装有Java虚拟机或者其它任何Java SDK环境,但是你安装了以上环境之后,DJ就可以创建、编译、运行JAR文件,在浏览器中运行applet小程序。

    OpenSSH 9.3 CentOS7 RPM安装包

    基于centos7编译的openssh9.3的安装包,使用x11-ssh-askpass让openssh不在依赖openssl1.1.1。 更新前:注意备份好/etc/ssh和/etc/pam.d/ ,一般建议开启telnet增加一条备用登陆通道 更新操作:rpm -Uvh openssh-*....

    smali2java.jar

    Smali2java is an utility for converting .smali to .java files without bytecode compiling/decompiling. Why not to use dex2jar? I have never told about it. Dex2jar is a good utility and smali2java is ...

    java反编工具java反编工具

    The decompiled Java code is provided "as is", for your information only, without warranty of any kind, either expressed or implied. You assume all risks concerning the suitability and accuracy of the ...

    配置Docker容器ssh服务端实现远程ssh登录

    #此步骤主要目的是修改sshd_config配置文件,把配置文件中的”PermitRootLogin without-password”加一个”#”号,把它注释掉,再增加一句”PermitRootLogin yes”,参考:https://www.jianshu.com/p/adda91b7c1d2 ...

    毕业设计-jsp-servlet-javabean网上订餐系统.doc

    jsp_servlet_javabean网上订餐系统 摘 要 二十一世纪是一个集数字化,网络化,信息化的,以网络为核心的社会。中国的网民 充分领略到"畅游天地间,网络无极限" 所带来的畅快。随着Internet的飞速发展,使得网络的...

    chart java applet

    - RChartServlet.java: source code of the servlet - servlet_examples directory: examples for the servlet - run*.bat: batchs file to run sample application with different Java VM. - version.txt: ...

    Java Language Specification, Third Edition

    The printed version of this draft book may not be photocopied without the express written permission of Sun. For the complete copyright notice, see Copyright. The online version differs from the ...

    java7帮助文档

    Java Platform Standard Edition 7 Documentation What's New Documentation Release Notes Tutorials and Training The Java Tutorials Java Training More Information Java SE 7 Names and ...

    Print Preview without the Doc/View Architecture

    Print Preview without the Doc/View Architecture

    gokku:Gogs commit hook -> dokku deploy

    悟空 Gogs commit hook -> dokku deploy 用法 从这个 repo 构建一个 docker 镜像。 接下来为您的配置创建一个新的存储库。... ENV BOT_CHANNEL commits # An IRC channel name without the leading hash ENV BOT_PA

    expect4j.jar 1.0

    The goal is to be able to port existing Tcl code bases that use Expect directly to Java without changes. The current version has successfully run a 10,000 line Tcl script which heavily depends on ...

    简单的Java照相机源码

    简单的Java照相机源码 可以获取USB摄像头的视频 /* * jmfcam05s.java 01.01a 07.11.2006 * * Copyright (c) 2006 Andy Dyble. All Rights Reserved. * * Permission is hereby granted, free of charge, to ...

Global site tag (gtag.js) - Google Analytics