注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

和申的个人主页

专注于java开发,1985wanggang

 
 
 

日志

 
 

WEBX2.0学习源码分析(三)初识 WebxControllerServlet 的父类AbstractWebxControllerServlet  

2011-12-26 23:33:00|  分类: WebX |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
AbstractWebxControllerServlet

/**

 * Webx控制器servlet的基本实现。<p>这个类实现了Webx controller servlet的基本框架,并且将初始化、处理请求和错误的接口留给子类实现。</p>

 */

public abstract class AbstractWebxControllerServlet extends HttpServlet {

  /**
     * 处理HTTP get和post请求。
     *
     * @param request HTTP请求
     * @param response HTTP响应
     *
     * @throws ServletException 如果该请求不能被正确处理
     * @throws IOException 如果输入/输出失败
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

。。。}


    /**
     * 处理HTTP post请求。此处调用<code>doGet</code>方法,因为我们不需要区别GET和POST请求。
     *
     * @param request HTTP请求
     * @param response HTTP响应
     *
     * @throws ServletException 如果该请求不能被正确处理
     * @throws IOException 如果输入/输出失败
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }


   /**
     * 处理HTTP head请求。<p>此处覆盖<code>javax.servlet.http.HttpServlet</code>中的实现,为了避免weblogic的一个bug。</p>
     *
     * @param request HTTP请求
     * @param response HTTP响应
     *
     * @throws ServletException 如果该请求不能被正确处理
     * @throws IOException 如果输入/输出失败
     */
    protected void doHead(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        NoBodyResponse noBodyResponse = new NoBodyResponse(response);

        doGet(request, noBodyResponse);

        noBodyResponse.setContentLength();
    }

}

看看WebxControllerServlet 的父类AbstractWebxControllerServlet:

其继承了    javax.servlet.http.HttpServlet

其中实现了doGet,doHead,doPost的几个处理方法。

先看看,‘牛逼’不区分get,post方法,就是现在可以假设说不太好实现spring中的SimpleFormController,因为根本就不区分post提交还是get提交,现在没有看完去代码,所以现在还是猜想一下。

还有一个doHead方法只请求页面的首部。


先看看常用的doGet,doPost方法吧


/**
* 处理HTTP get和post请求。
*
* @param request HTTP请求
* @param response HTTP响应
*
* @throws ServletException 如果该请求不能被正确处理
* @throws IOException 如果输入/输出失败
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RunData rundata = null;
Throwable requestException = null;
boolean beforeRequestCalled = false;

try {
rundata = getRunData(request, response);

if (!rundata.isRedirected()) {
try {
Profiler.enter("before request");

beforeRequest(rundata);
} finally {
Profiler.release();
beforeRequestCalled = true;
}

try {
Profiler.enter("handle request");
handleRequest(rundata);
} finally {
Profiler.release();
}
}
} catch (Throwable e) {
requestException = e;

// 处理异常e的过程:
//
// 1. 首先调用handleException处理异常e,handleException将根据不同的异常,生成友好的错误页面。
// 同时,handleException将根据需要,在日志中记录或不记录这些异常。
// 2. 如果handleException发生异常ee,则尝试生成一个简陋的错误报告页面,报告发生了
// 错误e,同时在日志中记录ee。
// 3. 如果不幸再次遇到异常eee,则将异常e直接抛出给servlet engine。
// 最终e将被记录到servlet log中。同时在日志中记录eee。
try {
try {
rundata.setStatusCode(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (Exception ee) {
// ignore this exception
}

Profiler.enter("handle exception");

// 1. 常规处理
if (!handleException(rundata, request, response, e)) {
try {
// 2. 如果handleException放弃处理,则尝试生成简易的出错页面
handleExceptionException(rundata, response, e, null);
} catch (Throwable eee) {
// 3. 放弃!把异常e交给servlet engine来处理
handleHorribleException(e, eee);
}
}
} catch (Throwable ee) {
try {
if ((ee == e)
|| ((ee instanceof ChainedThrowable)
&& (((ChainedThrowable) ee).getCause() == e))) {
// 确保e和ee不是指同一件事
ee = null;
}

if (ee != null) {
log.error("Another exception occurred while handling exception "
+ e.getClass().getName(), ee);
}

// 2. 尝试生成简易的出错页面
handleExceptionException(rundata, response, e, ee);
} catch (Throwable eee) {
// 3. 放弃!把异常e交给servlet engine来处理
handleHorribleException(e, eee);
}
} finally {
Profiler.release();
}
} finally {
try {
commitRunData(rundata);
} catch (Exception e) {
log.error("Exception occurred while commit rundata", e);
} finally {
if (beforeRequestCalled) {
try {
Profiler.enter("after request");
afterRequest(rundata);
} catch (RuntimeException e) {
log.error("Exception occurred while post-process request", e);

// 确保不会冲掉前面已经发生的异常。
if (requestException == null) {
throw e;
}
} catch (Error e) {
log.error("Exception occurred while post-process request", e);

// 确保不会冲掉前面已经发生的异常。
if (requestException == null) {
throw e;
}
} finally {
Profiler.release();
}
}
}
}
}

这里面首先生成一个RunData   rundata 对象。
   if (!rundata.isRedirected()) { //判断一下是不是重定向,这个是判断如果不是重定向,那就是forward转发了,
之后是这个东西,猜想估计是线程安全的或者是,ThreadLocal的东西,反正是将参数直接转发到了beforeRequest这个处理方法中
 try {
Profiler.enter("before request");

beforeRequest(rundata);
} finally {
Profiler.release();
beforeRequestCalled = true;
}
beforeRequest位于其子类WebxControllerServlet 中,看起来挺靠谱的挺像一个类似ThreadLocal的东东。如果threadContextService  不为空就将其放入到threadContextService ,估计是一个ThreadLocal的神马实现。

  /**
     * 此方法允许controller在处理一个HTTP请求之前,做一些事情。
     *
     * @param rundata 运行时刻数据
     *
     * @throws WebxException 如果该请求不能被正确处理
     */
    protected void beforeRequest(RunData rundata) throws WebxException {
        // 将rundata放到thread context中。
        ThreadContextService threadContextService = getWebxController().getThreadContextService();

        if (threadContextService != null) {
            threadContextService.setObject(rundata);
        }
    }

接下来调用子类中的WebxControllerServlet中的handleRequest,
这里面取得了一个名为
PipelineService这样的一个服务,然后又取得Pipeline这样的一个东西。如果为空时异常,看来这个WEBX是非得有这个Pipeline才能用。属于必需品。

/**
* 处理HTTP get和post请求。
*
* @param rundata 运行时刻数据
*
* @throws WebxException 如果该请求不能被正确处理
*/
protected void handleRequest(RunData rundata) throws WebxException {
// 取得当前component的默认pipeline。
PipelineService pipelineService = (PipelineService) getWebxController().getServiceManager()
.getService(PipelineService.SERVICE_NAME,
rundata.getComponent());
Pipeline pipeline = pipelineService.getPipeline();

if (pipeline == null) {
throw new WebxException("Failed to get pipeline, the PipelineService may be failed to initialize");
}

TryCatchFinallyValve tryCatchFinally = null;

// 取得try-catch-finally valve,特殊处理之。
if ((pipeline.getLength() == 1) && pipeline.getValve(0) instanceof TryCatchFinallyValve) {
tryCatchFinally = (TryCatchFinallyValve) pipeline.getValve(0);
rundata.setAttribute(TRY_CATCH_FINALLY_VALVE_KEY, tryCatchFinally);
}

try {
if (tryCatchFinally == null) {
pipeline.invoke(rundata);
} else {
tryCatchFinally.invokeTryPipeline(rundata);
}
} catch (PipelineException e) {
throw new WebxException(e);
}
}

这个是有点意思,如果pipeline的长度为1(注意是==1 不是>=1,>1的时候程序玩不转了,哈哈),并且,取得的Valve的第一个(里面存储的是List,有序集合),为TryCatchFinallyValve时,需要特殊处理一下。

   // 取得try-catch-finally valve,特殊处理之。
if ((pipeline.getLength() == 1) && pipeline.getValve(0) instanceof TryCatchFinallyValve) {
tryCatchFinally = (TryCatchFinallyValve) pipeline.getValve(0);
rundata.setAttribute(TRY_CATCH_FINALLY_VALVE_KEY, tryCatchFinally);
}
这里面取出TryCatchFinallyValve放入rundata的一个属性中。
接下来判断了一下是否存在tryCatchFinally,如果没有旧直接使用pipeline调用,将rundata参数传入。
如果有tryCatchFinally就使用其来调度。
看来这个tryCatchFinally有点意思,应该是再pineline文件中可能是只可以配置一个try-catch-finally.到目前为止看到的代码,如果多了就没有TryCatchFinallyValve这东西嘛事了。

try {
if (tryCatchFinally == null) {
pipeline.invoke(rundata);
} else {
tryCatchFinally.invokeTryPipeline(rundata);
}
} catch (PipelineException e) {
throw new WebxException(e);
}

  评论这张
 
阅读(1611)| 评论(2)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016