Ringo.js嵌入集成(二):使用Listener Filter替换官方的JsgiServlet实现
来源:互联网 发布:数据库编辑器有哪些 编辑:程序博客网 时间:2024/05/16 04:54
就像上回所讲,官方提供了一个样例JsgiServlet。虽然已经在其上stick矿建,但是就个人看来,这个东西确实类似一个样例。
如果使用serlvet作为js容器(ringo-engine)的载体,那么势必一个webapp可以配置多个servlet,也就是多个js容器。这种方式会导致开发人员在不熟悉环境的情况错误的开发判断。其实,如果要方便开发,那么就应该至少提供一个较为但单纯的环境。降低入门曲线。即,提供一个webapp默认对应的js容器。
另一方面,我后续的需要完成的仿制wordpress plugin的机制也需要用到直接获取默认引擎。
参考spring:
spring在这块做的比较好,其WebApplicationContext在开发时对于业务开发者来看其实就是被绑定在ServletContext(application)对象上的“单例”。虽然springContext并没有那么简单,其context可以有树形结构的。但至少提供一个默认入口。
ok,那我现在其实可以参考spring的context绑定方式对Jsgi的进行改造。另外,一方面其实有经验的开发者完全可以自己构造ringo的web-connector接口不一定要符合标准jsgi。完全可以构造一个类似nodejs-express的web框架。我这里是想尽量利用ringo自带的stick框架才这么干的。
架构:
下面是一个粗鲁(是“鲁”)的框线图:
整体结构大致由RingoListener,JsgiFilter,JsgiUtils,RingoEngineHolder(附加),RingoSpringBindingListener(附加)等若干类组成。
RingoListener:
其功能就是读取web.xml中的配置初始化ringo engine。然后将engine绑定到对servletContext。
主要代码是实现一个createRingoEngine方法,初始化engine。
protected RhinoEngine createRingoEngine(ServletContext servletContext){ if (engine == null) { String ringoHome = getStringParameter(servletContext, "ringo-home", "/WEB-INF"); String modulePath = getStringParameter(servletContext, "ringo-module-path", "WEB-INF/usrmod"); //原来默认WEB-INF/app,可以多个逗号分割。 logger.info("modulePath:"+modulePath); String bootScripts = getStringParameter(servletContext, "ringo-bootscript", null); //这个似乎不是基于module路径寻找的。 int optlevel = getIntParameter(servletContext, "ringo-optlevel", 0); boolean debug = getBooleanParameter(servletContext, "ringo-debug", false); boolean production = getBooleanParameter(servletContext, "ringo-production", false); boolean verbose = getBooleanParameter(servletContext, "ringo-verbose", false); boolean legacyMode = getBooleanParameter(servletContext, "ringo-legacy-mode", false);// ServletContext context = servletContext; Repository base = new WebappRepository(servletContext, "/"); Repository home = new WebappRepository(servletContext, ringoHome); try { if (!home.exists()) { home = new FileRepository(ringoHome); System.err.println("Resource \"" + ringoHome + "\" not found, " + "reverting to file repository " + home); } // Use ',' as platform agnostic path separator String[] paths = StringUtils.split(modulePath, ","); String[] systemPaths = {"modules", "packages"}; //如果ringo-home下有则ringo会直接用该目录作为系统模块,而取消从jar包中读取。所以如果没有必要不要建立。 RingoConfig ringoConfig = new RingoConfig(home, base, paths, systemPaths); ringoConfig.setDebug(debug); ringoConfig.setVerbose(verbose); ringoConfig.setParentProtoProperties(legacyMode); ringoConfig.setStrictVars(!legacyMode && !production); ringoConfig.setReloading(!production); ringoConfig.setOptLevel(optlevel); if (bootScripts != null) { ringoConfig.setBootstrapScripts(Arrays.asList( StringUtils.split(bootScripts, ","))); } engine = new RhinoEngine(ringoConfig, null); return engine; } catch (RuntimeException ex) { logger.error("Ringo-engine initialization failed", ex); servletContext.setAttribute(RINGO_ENGINE_ATTRIBUTE, ex); throw ex; } catch (Exception e) { logger.error("Ringo-engine initialization failed", e); servletContext.setAttribute(RINGO_ENGINE_ATTRIBUTE, e); throw new java.lang.RuntimeException("Ringo-engine initialization failed",e); } catch (Error err) { logger.error("Ringo-engine initialization failed", err); servletContext.setAttribute(RINGO_ENGINE_ATTRIBUTE, err); throw err; } } else{ return this.engine; }}
JsgiUtils:
这个类其实是一个工具类,通过它可以直接从servletContext中获取engine,非常简单。
这个类其实是一个工具类,通过它可以直接从servletContext中获取engine,非常简单。
JsgiFilter:
这个就是处理请求的filter。之所以用Filter主要是可以忽略一些处理。如果js无法处理,还能回到java版本的serlvet来完成。当然,一旦使用filter,js部分如果需要提供filterChain.doFilter()功能则需要二外提供扩展。
这个就是处理请求的filter。之所以用Filter主要是可以忽略一些处理。如果js无法处理,还能回到java版本的serlvet来完成。当然,一旦使用filter,js部分如果需要提供filterChain.doFilter()功能则需要二外提供扩展。
其主要部分当然是doFilter的实现。
/** * 当前没有调用,基本只要filter-mapping url-pattern正确就会执行,并不会执行后续操作。? * chain.doFilter(req, resp); */@Overridepublic void doFilter(ServletRequest prequest, ServletResponse presponse,FilterChain filterChain) throws IOException, ServletException {//httpHttpServletRequest request = (HttpServletRequest) prequest;HttpServletResponse response = (HttpServletResponse) presponse; JsgiRequest req = new FilterJsgiRequest(request, response, requestProto, engine.getScope(),this.servletContext ,this,this.filterConfig,filterChain); //如果底层不进行修改需要生成一个模拟的servlet RingoWorker worker = engine.getWorker(); try { //filterChain.doFilter也可以由js内部完成。帮助过滤真正需要的内容。 //区别于jsgiservlet一旦符合pattern(比如/XXX/*)必须进行处理。无法要求释放该请求过滤某个后缀。 //servlet无法取消某个特定url的拦截。二filter可以doFilter。 worker.invoke("ringo/jsgi/connector", "handleRequest", module, function, req); // } catch (Exception x) { List<ScriptError> errors = worker.getErrors(); boolean verbose = engine.getConfig().isVerbose(); try { renderError(x, response, errors); RingoRunner.reportError(x, System.err, errors, verbose); } catch (Exception failed) { // custom error reporting failed, rethrow original exception // for default handling RingoRunner.reportError(x, System.err, errors, false); throw new ServletException(x); } } finally { worker.release(); } }
需要注意的是,其实传递到js中时存在一个request的封装(按照jsgi要求)。
在其env属性下取消原有的servlet,添加filter相关内容。
/** * 用来适配request对象原型类 * @author wfeng007 * @date 2013-10-1 下午08:43:49 */static class FilterJsgiRequest extends JsgiRequest{..........public FilterJsgiRequest(HttpServletRequest request,HttpServletResponse response, JsgiRequest prototype,Scriptable scope,ServletContext servletContext,Filter filter,FilterConfig filterConfig,FilterChain filterChain) {super(request, response, prototype, scope, new JsgiServlet()); //一个空的jsgiservlet之后需要删除。deleteProperty((Scriptable)this.getProperty(this, "env"),"servlet"); //删除该对象引用,与servlet互相排斥?//env-extdefineProperty((Scriptable)this.getProperty(this, "env"),"servletContext", //filter.filterConfig可以得到config? new NativeJavaObject(scope, servletContext, null), PERMANENT);defineProperty((Scriptable)this.getProperty(this, "env"),"filter", //filter.filterConfig可以得到config? new NativeJavaObject(scope, filter, null), PERMANENT);defineProperty((Scriptable)this.getProperty(this, "env"),"filterConfig", //filterConfig new NativeJavaObject(scope, filterConfig, null), PERMANENT);defineProperty((Scriptable)this.getProperty(this, "env"),"filterChain", new NativeJavaObject(scope, filterChain, null), PERMANENT);}}
RingoEngineHolder与RingoSpringBindingListener
这两个附加内容都是与engine绑定。通过这两个类可以讲engine绑定到一个静态区域,同时也可以绑定到默认的spring Context上。实现原理与参考Spring的listener即可。
- Ringo.js嵌入集成(二):使用Listener Filter替换官方的JsgiServlet实现
- Ringo.js嵌入集成:java-web应用嵌入JsgiServlet
- Ringo.js嵌入集成(三):利用RingoJs仿制wordpress的plugin机制
- 基于JVM的服务端javascript平台Ringo.js入门(二)
- 基于JVM的服务端javascript平台Ringo.js入门(三):模块以及包实现
- 基于JVM的服务端javascript平台Ringo.js入门(四):stick-web框架使用
- Filter+Listener的简单使用
- --Listener (二)Listener使用
- springboot 使用Servlet,Filter,Listener的方法
- 基于JVM的服务端javascript平台Ringo.js入门(一)
- Ringo.js字符集问题解决
- js filter的使用
- Filter二(利用Filter实现简单的登录验证)
- servlet的filter使用替换流
- Filter与Listener使用案例
- 在servlet(或者filter或者listener)中使用spring的IOC容器
- js的filter()使用及查询方法实现
- 使用oracle10g官方文档找到监听文件(listener.ora)的模板
- c++有关编译期和运行期的访问
- JBoss 系列三:使用4种方式部署应用到JBoss7/WildFly
- 十七道海量数据面试题
- 使用GNU 编译OBjectC
- hibernate之HQL之参数绑定
- Ringo.js嵌入集成(二):使用Listener Filter替换官方的JsgiServlet实现
- OpenCL 和 CUDA 之间的区别
- Windows下的Objective-C集成开发环境(IDE)的搭建
- Crazy Tea Party
- CF204 Div 1 题解
- 徐海蛟:svm理论与实验之1
- hibernate之HQL之引用查询
- Linux下多任务间通信和同步-System V共享内存
- 头文件与cpp文件为什么要分开写