模拟comet的实现

本文没有使用任何comet服务器, 只是利用tomcat模拟实现了一下comet, 不是真正的comet哦,因为不会有这样的应用场景, 只是模拟实现, 仅供参考.

一. 需求.

实现将服务端的时间推送到客户端, 客户端在得到服务端相应后将时间显示在页面上.

二.实现.

1开发框架: 用jsp+servlet的方法, 用了一个webframework框架, 自己写的, 类似于struts2, 可以的话就把它当作struts2来看吧.

2. jsp代码如下

php的if语句

为了搞个404页面, 自己编辑sidebar.php, 由于sidebar.php展示的东西太多了, 我想要在404的时候不显示太多的东西, 只要一404图片和一个微博秀就行了,所以在sidebar加if语句就可以了, 呀的, 没想到一直语法错误, 看到有一个if语句是加了个冒号的, 有点疑惑, 搜索了一下, 才知道 if后面加个冒号可以跟endif;配合, 相当于{}, 所以一下子就解决了.


<?php if(condition){

//do something

}

?>

或者


<?php if(condition): ?>

do what you like

<html>tag supported

<?php endif; ?>

对comet的一些思考

哎, 天朝这么大, 对comet的研究的文章却少之又少. 所以目前我除了知道一些可以实现comet的框架之外, 不知道他们是如何实现的, 可以不可以在现有的app 服务器上做一些框架就可以实现, 而不需要实现什么协议.
comet是基于ajax之上的, 或者说基于httpxmlrequest之上的, 实现原理如下:
客户端:发送XHR请求, 一有数据返回就进行处理并继续发起下一个XHR请求, 如此反复.
服务器端:接到来自客户端的请求后, 不是马上返回数据, 而是阻塞着, 等到有需要返回数据的时候(如数据的更新)才返回给客户端.
客户端的技术很容易做到的, 就一个递归的调用, 但服务器端如何做到等到数据的更新, 我想这里其实可以引入事件模型, 就是服务器端注册一系列的事件, 使用线程侦听事件, 当事件触发的时候设置返回值, 并促发服务器返回数据.
目前在我脑钟有点想法, 画了个草图, 准备找一天把他实现一下, 也不知道这种想法是不是正确的. google comet信息会比较多, 可惜英文比较难读懂呐.汗.

加油!

struts2的action的执行过程解析

阅读了struts2的部分源码, 才知道, 原来struts2是不用servlet的, 只用了filter就可以实现所有的功能, 包括action和interceptor.

首先, 一个请求过来, filter会拦截到, 通过解析请求URL, 得到请求的target(哪个类的哪个方法), 放在actionMapping里边, 这个通过actionMapping可以得到要执行的类的方法, 然后作为对象放到DefaultActionInvocation这个类中, 这个类是实现了ActionInvocation的类, 没错, 就是在struts2的拦截器方法intercept(ActionInvocation invocation)的参数类型.把代码罗列出来比较容易看.

先看看FilterDispatcher这个filter的doFilter方法

 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        ServletContext servletContext = getServletContext();

        String timerKey = "FilterDispatcher_doFilter: ";
        try {

            // FIXME: this should be refactored better to not duplicate work with the action invocation
            ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
           //这里就是为什么我们可以在action中直接使用ActionContext.getContext().getRequest()
           //来得到当前的request等对象了. 用的是ThreadLocal的存储.
            ActionContext ctx = new ActionContext(stack.getContext());
            ActionContext.setContext(ctx);

            UtilTimerStack.push(timerKey);
            request = prepareDispatcherAndWrapRequest(request, response);
            ActionMapping mapping;
            try {
                mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
            } catch (Exception ex) {
                log.error("error getting ActionMapping", ex);
                dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
                return;
            }

            if (mapping == null) {
                // there is no action in this request, should we look for a static resource?
                String resourcePath = RequestUtils.getServletPath(request);

                if ("".equals(resourcePath) && null != request.getPathInfo()) {
                    resourcePath = request.getPathInfo();
                }

                if (staticResourceLoader.canHandle(resourcePath)) {
                    staticResourceLoader.findStaticResource(resourcePath, request, response);
                } else {
                    // this is a normal request, let it pass through
                    chain.doFilter(request, response);
                }
                // The framework did its job here
                return;
            }

            dispatcher.serviceAction(request, response, servletContext, mapping);

        } finally {
            try {
                ActionContextCleanUp.cleanUp(req);
            } finally {
                UtilTimerStack.pop(timerKey);
            }
        }
    }