简单的HTTP服务器

静态资源服务器

功能:
1、控制后台应用程序;最常用的就是后台定时程序完成定时任务;
2、静态资源web服务器功能;

创作冲动

因为前段时间我来调整彩信包月发送模块、还有与上海全程公司得数据同步问题。这两个都是后台应用程序,里面都有一个定时任务得概念。
原来做的是用Resin来控制的(没有用系统任务控制),把实现ServletContextListener的类在web.xml里面注册了一下,当容器启动了,就激活这个事件.
容器关闭就停止了这个事件。
后来觉得就这么简单的功能如果还用resin来做有些大才小用了。
于是就觉得自己写个应用程序吧,如果是带有界面的应用程序,我们开始应用和结束应用用界面可以控制。而且实现起来比较简单。
但是没有界面的情况下,我本次启动java应用程序会把程序装载到jvm里面去,如果我再次开一个命令行想试图通过xxx stop来结束命令,是不可能的。
因为两次开的命令行装载的程序跟本不是同一个实例,因为他们根本就不再同一个jvm中。
经过仔细研究tomcat的启动框架,觉得用打开端口的方式来控制。。。。。

然后,后来扩展出来了web功能。。。。。。。
主要学习了NIO,Socket方面的知识,熟悉了HTTP协议…..

配置

设置系统环境变量

STATIC_SERVER_HOME:该服务的跟目录比如:D:/work/static-server/

否则系统无法启动!

系统描述:

%STATIC_SERVER_HOME%/conf 是配置文件目录
web.properties是留给用户添加属性的文件,这个属性文件的值可以通过接口IServerContext中的方法获得
log4j.properties是系统日志配置文件
app-server.properties 是系统配置文件
如下解释:

#listener.port
listener.port=7474
是服务启动时候监听的端口号
http.port=80
HTTP服务器端口
web.root=httpdocs
web服务器跟目录,如果修改请制定具体的物理目录如:D:/www/html/否则不需修改。
max.thread=50
web服务器最大链接数
#index file
welcome.file=index.html
web服务器默认首页页面,暂时只支持一个
#listener.class
#exa: class1;class2;class3
listener.class=com.zhanglihai.app.server.test.MyListener
后台监听的应用程序
每一个类都是接口com.zhanglihai.app.server.ISessionListener的实现类
多个类之间用;分割开。系统会自动装载这些类,然后来调用里面的start|stop方法。
##1.0 Beta 版本增加以下标记
default.content-type=text/plain
//系统保留
dir.list=true
//是否可以浏览目录true:如果没有默认页面就浏览目录;false禁止浏览目录
http.encoding=GBK
//request请求中的编码
http.404=/404.html

//当请求发生404时候所制定的文件,要求从系统跟目录算起。
auth.class=需要对请求访问做限制的类全名,并且必须是继承com.zhanglihai.app.server.Authorization类并且覆盖了里面的authorization方法
如果不需要访问验证,此处不需要填写。

%STATIC_SERVER_HOME%/lib : 是系统所需的jar包,其中static-server.1.0.jar里面有两个接口,
static-server.1.0.jar 在1.0 Beta版本中增加两个接口Request,Response,和一个对于访问验证的类
一个是用户要实现的com.zhanglihai.app.server.ISessionListener接口,一个是系统环境变量接口。用户使用的时候要加入这个包
startup.jar是系统启动时候的应用程序入口jar;test.jar是测试ISessionListener,和请求控制验证,接口的程序实际中可以把这个包删除,同时去掉app-server.properties中相关的注册信息 %STATIC_SERVER_HOME%/logs :系统日志输出目录
%STATIC_SERVER_HOME%/httpdocs:系统默认的web跟目录

系统启动|停止:

从dos窗口到%STATIC_SERVER_HOME%/bin/目录

然后执行app-server.bat start来启动服务

同样执行app-server.bat stop来停止服务
Linux用户请用相关的app-server.sh文件来执行同样的命令。 在Linux下需要用户用root权限启动该文件。
下载

STATIC-SERVER 1.0(JDK1.4)

系统 JDK 版本 最后更新时间 备注
Windows JDK1.4或以上 1.0 5M 2005-05-18 15:07
Linux JDK1.4或以上 1.0 5M 2005-05-18 15:07
Windows JDK1.4或以上 1.0 6M 2005-05-23 20:39 完全用NIO、多线程实现数据的读写操作,效率提高很多,
有兴趣可以测试,我测试的结果和Resin的处理能力接近,远远高于Tomcat,手头没有Apache,所以没有测试
Linux JDK1.4或以上 1.0 6M 2005-05-23 20:39
Windows JDK1.4或以上 1.0 Beta 2005-05-24 20:10 1、添加对HEAD请求的处理;
2、添加浏览目录的处理;
3、修改浏览目录时候的Bug;
4、添加对请求的编码处理;
5、添加对文件类型的处理;
6、增加对404状态的处理;
7、增加配置文件%STATIC_SERVER_HOME%/conf/mime.properties文件,增加对文件类型的处理;
8、实现对请求资源的控制;
9、增加app-server.properties标记如下:
default.content-type=text/plain //系统暂时保留
dir.list=true//是否显示目录
http.encoding=GBK//系统默认请求编码
http.404=/404.html //发生404时候所指定的文件,必须从系统跟目录起。
auth.class=需要对请求访问做限制的类全名,并且必须是继承com.zhanglihai.app.server.Authorization类并且覆盖了里面的authorization方法
10、static-server.1.0.jar中新增加两个接口Request/Response ,和一个访问权限验证的类Authorization,如果需要访问限制,请参看test中AuthTest类的实现,所有的权限验证的类都
应该继承Authorization
11、增加对中文目录以及中文文件名的处理;
12、增加对Request里面中文参数、值的处理;
13、增加web.properties提供给用户更多配置。
Linux JDK1.4或以上 1.0 Beta 2005-05-24 20:10
Windows/Linux JDK1.4或以上 1.0 Beta 2005-05-27 10:08 1、修改读取大文件(超过10M)时候的一个bug,
2、写文件时候一个bug,就是用户下载文件时候突然停止或者终端的bug.
请下载文件包刀到本地后解压出里面的 startup.jar,覆盖到%STATIC_SERVER_HOME%/lib 里面去.
另外由于系统文件类型有限,如果系统不识别的文件类型就默认是text/html;请自动更新mime.properties文件.关于类型设置以后会不断升级..
Windows/Linux JDK1.4或以上 cr 1.0 2005-05-29 10:08 1、修改浏览中文目录以及文件时候的一个bug(对于M$.IE和Mozilla.Firefox有些区别);
2、添加对请求日志的记录;
3、扩展Authorization类的方法,扩展Response里面的方法,对于Authorization可以理解为”全局的过滤器”请参考例子中提供的简单方法扩展适合自己的过滤器。
4、增加了app-server.peroperties里面的日志属性

用户使用须知:

首先机器安装有JDK1.4或以上;
下载最新版本的程序到本地解压后,设置系统环境变量名STATIC_SERVER_HOME值为刚才解压的目录如:D:/work/static-server/
如果需要修改端口可以通过修改app-server.properites中相关设置来修改
这是启动系统,系统开始工作。

A:定时任务或后台任务

如果需要定时或者后台任务方面的工作,可以自己写一个类来实现接口com.zhanglihai.app.server.ISessionListener里面的两个方法,同时在app-server.properties里面
listener.class=添加上去,多个类请用英文状态的”;”分割开来。类名请用全路径,例如com.zhanglihai.app.server.test.MyListener
接口中的start方法时系统启动时候会调用,stop方法在系统停止时候调用,其中里面的参数IServerContext可以方便获得系统相关信息以及用户配置的web.properties里面的信息。

B:WEB请求控制

如果需要对某些资源或者某个IP过来的用户做限制,用户可以自己写一个类来继承com.zhanglihai.app.server.Authorization,同时实现里面的authorization方法,该方法里面有两个参数:Request:IServerContext,用户可以从中获得相关信息以便来实现对某些资源的控制。把该类注册到app-server.properties里面的auth.class=类的全路径名。如果没有找到该类或者类型错误系统认为不需要控制。

测试中提供的一个简单控制,该控制禁止用户访问/auth开头的所有目录及文件,如果系统中不存在这个目录系统仍然提示授权失败,而不提示404错误
还测试了,以配置文件中配置的扩展名结尾的文件都给予浏览器下载提示,比如 aa.mp3。

/**
* @see com.zhanglihai.app.server.Authorization#authorization(com.zhanglihai.app.server.IServerContext, com.zhanglihai.app.server.Response, com.zhanglihai.app.server.Request)
*/
public boolean authorization(IServerContext context, Response response, Request request) {
String uri = request.getUri();
if (isDown(uri, context)) {
response.setContentType("application/x-msdownload");
response.addHeader("Content-Disposition", "attachment;filename=" + getFileName(uri));
}
String ip = request.getRemoteAddr();
String authIPs = context.getInitParameter("auth.ip");
String authPath = context.getInitParameter("auth.path");
if (authIPs == null) return false;
log.debug("Uri : " + uri);
log.debug("IP : " + ip);
log.debug("homePath : " + context.getHomePath());
log.debug("webRoot : " + context.getWebRoot());
String[] ips = authIPs.split(",");
return isContiant(ips, ip);
}
 
/**
* 判断字符串是否在数组中
* 
* @param array
* @param s
* @return
*/
private boolean isContiant(String[] array, String s) {
if (array == null) return false;
if (s == null) return true;
for (int i = 0; i < array.length; i++) {
if (s.trim().equalsIgnoreCase(array[i].trim())) { return false; }
}
return true;
}
 
/**
* 判断是否为下载类型
* 
* @param uri
* @param context
* @return
*/
private boolean isDown(String uri, IServerContext context) {
String extstr = context.getInitParameter("ext.download");
if (extstr == null) return false;
String[] exts = extstr.split(",");
if (exts == null) return false;
String temps = uri;
int p = temps.lastIndexOf(".");
if (p == -1) return false;
String ext = temps.substring(p + 1);
for (int i = 0; i < exts.length; i++) {
if (exts[i].equalsIgnoreCase(ext)) { return true; }
}
return false;
}
 
private String getFileName(String uri) {
int p = uri.lastIndexOf("/");
if (p == -1) return uri;
return uri.substring(p + 1);
}

系统截图:


Blog In China

blog在中国的确创造了很多奇迹,2003年的《木子美》就是从blogChina火起来的,到2004年初的时候,我们看到各个网站都有blog,04年末,google忍不住寂寞终于推出了自己的blog,,但是我们对blog的理解程度还不一样,IT圈内的人有自己的理解,IT圈外的人也有自己的理解。


比如我可能会写一些关于技术啊,IT方面的文章,而那些文学方面的人或者专业的写手他们根本不关心什么是blog,只要给他们一个能写能输入文字的地方就可以了,你给他们开一个私有论坛也是完全可以的,然后他们改个名字叫“XX论坛”。这些对于IT圈内的人从技术角度考虑其实是一样的。
在blog满街横飞的同时,我们也注意到一种和blog一直纠缠在一起的东西RSS。目前对于“rss”这三个字母没有准确的中文意思,当然有人叫做“聚集”。 blog提供可以定制自己制定栏目blog的rss,这样你就不用经常跑我到我的网站上看东西。随后就推出了各种rss阅读器。
然后rss还是有很多局限的,目前只限于新闻/Blog的传递,能否适应WEB2.0的扩展还很难说,起初有人曾说过rss将有可能取代webnews,但是到目前看来还有很大差距,尤其是google推出news以后,有人更看好google的新闻,到目前google还没有在他的新闻,搜索里面加入rss,这说明google还在考虑是否可行。

国内很多新闻网站都有rss订阅的,比如 新华网 ,百度,DoNews等等都有的,现在觉得虽然rss起源于国外,但是我们给他推广到了高点。虽然rss功能还不多,我们不能完全否认,rss,blog的出现毕竟给沉闷以久的网络带来了亮点。

在客户端rss的推出后,不甘寂寞的网络又出现了rss书签,比如Lilina .只要输入正确的rss订阅地址,可以输入多个,系统会把每个rss上的相关新闻都给你显示出来,并且利用Google提供的API,从google搜索相关的信息,都保存下来。。。。

每个网站都提供一个rss,再和其他网站的rss交换链接,如果你交换的rss越多,你的信息内容就越多。可见其信息的传播速度。

“盛大收购新浪股票”事件起初最早就是从blog传出去的,然后各大新闻网站才发布新闻。可见其速度之快,然而我们也意识到blog/RSS上的垃圾信息、虚假信息也日益增多,,,这个是不好的方面。

如果这样下去,blog/RSS将成为下一个垃圾信息,就像我们对待垃圾邮件那样对待blog/RSS.