- 浏览: 264993 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
DragonKiiiiiiiing:
支持楼主,中国互联网太缺这种无私奉献的人了。您的这本书我已拜读 ...
JAVA NIO 全书 译稿 -
sp42:
非常感谢!热部署帮助很大!
Pure JS (2): 热部署 (利用 JDK 7 NIO 监控文件变化) -
sp42:
其实在我的架构中,我更倾向于 JSP 作为前端模板系统~还是写 ...
Pure JS (5.3):pure.render 的实现(构造window对象,实现服务器端 JQuery Template) -
sp42:
非常不错,楼主做的正是鄙人想做的做的,而且比鄙人的来的成熟、健 ...
OMToolkit介绍(5): 总结 -
cfanllm:
楼主辛苦了,,,谢谢分享啊
JAVA NIO 全书 译稿
Pure JS (1): 在 jetty 上运行 JavaScript
所谓 Pure JS ,就是客户端和服务器端程序都用 JavaScript 编写。
实现思路是:
1. 客户端发起 Ajax 请求,请求的数据格式为 JSON ,方法为 POST
2. 服务器端用 Jetty 接收请求
3. 用 Java 6 ScriptEngine 执行 JavaScript 脚本
4. 结果以 JSON 格式返回
另外,在系统启动时需要对所有脚本进行初始加载。
接下来就按照这个思路逐步进行。
客户端 Ajax 请求
在 Eclipse 中建立 Java 工程,新建 webapp 目录和 webapp/js 目录。
这里需要用到 jQuery 1.6 和一个 $.toJSON 插件 (json.js),可以在附件中找到。
webapp 下的 index.html 的代码如下:
<script src='js/jquery.js'></script> <script src='js/json.js'></script> <script src='js/proxy.js'></script> <script src='js/app.js'></script>实际上只是依次引用了多个js文件。
proxy.js 的作用是利用 jQuery 发起 Ajax 请求。
实现如下:
function proxy(request, success, failure) { request = $.toJSON(request); $.post('api', { request : request }, function(result){ if (result.success) { success && success(result.data); } else if (failure) { failure(result.error); } else { alert('Operation Failed!'); } }, 'json'); }
参数解释如下:
【requset】 请求对象,包含两个属性:
【action】 需要服务器端执行的动作,如 'sayHello' 等
【params】 请求参数,是一个 JavaScript Object, 如 { name: 'Pei Xiaoxing' } ,也可以是更复杂的对象
【success】 执行成功是需要执行的函数 (服务器端返回的 result.success 为 false )
【failure】 执行失败时需要执行的函数 (服务器端返回的 result.success 为 true )
首先将 requset 转为字符串,
然后调用 jQuery 的 post() 函数,url 指定为 'api' ,这是服务器端处理 AJAX 请求的 Servlet 的路径;
最后根据返回的 result.success 分别执行回调函数 success 和 failure。
app.js 的实现如下:
$(function(){ var request = { action: 'sayHello', params: { name: 'Pei Xiaoxing' } }; proxy(request, function(data) { $('body').html(data); }); });
构造一个requset对象作为 proxy 的第一个参数,调用刚刚实现的 proxy 函数;
服务器端返回成功信息时,就将数据填充到 body 。
服务器端 Jetty 接收请求
利用 Jetty 接收服务请求,分为两类:
1. 资源请求,如 html , js 之类的文件,映射到路径 “/”。
2. API请求,如客户端提交的 “ sayHello ” 动作,映射到路径 “/api”。
同时,在启动 Server 前,先执行所有服务器端脚本,以获得所有动作的定义。
JSServer 实现如下:
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; public class JSServer { public static void main(String[] args) throws Exception { JSEngine.excuteFiles("scripts"); startServer(); } private static void startServer() throws Exception, InterruptedException { Server server = new Server(8080); configContext(server); server.start(); server.join(); } private static void configContext(Server server) { ServletContextHandler context = new ServletContextHandler( ServletContextHandler.SESSIONS); context.setContextPath("/"); context.setResourceBase("webapp"); server.setHandler(context); context.addServlet(new ServletHolder(new DefaultServlet()), "/"); context.addServlet(new ServletHolder(new JSServlet()), "/api"); } }
main 函数中做了两件事:
1. 执行 “scripts” 文件夹下的所有 js 脚本。
2. 启动 jetty server
startServer() 函数新建一个监听 8080 端口的 Server ,配置 Context 并启动。
configContext() 函数设置请求路径为 "/",以及资源路径为“webapp”,并添加两个 Servlet 的映射。
JSEngine : Java 6 ScriptEngine 封装
JSEngine 对 Java 6 ScriptEngine 进行简单封装,这纯粹是个人习惯了,
因为使用 ScriptEngine 的时候总是要进行各种强制转换,干脆封装在一个类中了。
实现如下:
import java.io.File; import java.io.FileReader; import java.io.IOException; import javax.script.Compilable; import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class JSEngine { private static ScriptEngine engine; private static Compilable compliable; private static Invocable invocable; static { ScriptEngineManager manager = new ScriptEngineManager(); engine = manager.getEngineByName("javascript"); compliable = (Compilable) engine; invocable = (Invocable) engine; } public static void excuteFiles(String dir) throws ScriptException, IOException { for (File file : new File(dir).listFiles()) { FileReader reader = new FileReader(file); compliable.compile(reader).eval(); reader.close(); } } public static String invoke(String func, Object... args) throws NoSuchMethodException, ScriptException { return (String) invocable.invokeFunction(func, args); } }
excuteFiles 的作用是编译并执行所指定的目录下的所有 js 脚本,invoke 的作用是调用特定函数。
JSServlet :处理 Ajax 请求
JSServlet 用于接收 Ajax ,并执行相应的 js 脚本,实现如下:
import java.io.IOException; import javax.script.ScriptException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class JSServlet extends HttpServlet { private static final long serialVersionUID = -7419703636280795226L; private static final String ERROR = "{\"error\": \"Server internal error.\", \"success\": flase}"; @Override protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String result; try { result = JSEngine.invoke("run", req); } catch (NoSuchMethodException e) { e.printStackTrace(); result = ERROR; } catch (ScriptException e) { e.printStackTrace(); result = ERROR; } res.getWriter().write(result); } }
service() 函数将 HttpServletRequest req 直接作为参数传入,调用 js 脚本 run() 函数,
取得返回结果,并写入到 response 中。
出错则返回 “ Server internal error. ”。
run() 函数是 js 脚本的入口,完成路径映射,JSON 解析和序列化等工作。
编写服务器端脚本
服务器端脚本有两个:
1. api.js 包含所请求的动作的逻辑;
2. run.js 脚本的执行入口,接收 req 参数,并执行指定脚本。
api.js 的实现如下:
api = { sayHello: function(params) { return 'Hello, ' + params.name + '!'; } };
返回类似 “ Hello, xxx! ” 的信息
run.js 的实现如下:
function run(req) { var ret; try { var request = JSON.parse(req.getParameter('request')); var action = request.action; var params = request.params; ret = { data : api[action](params), success : true } } catch (e) { println(e); ret = { error : e.toString(), success : false } } return JSON.stringify(ret); }
首先将 JSON 字符串请求转换为 JavaScript 对象,并提取 action 和 params 。
然后调用 “api” 对象的 “ action ” 方法, 参数为“ params ”,并获得返回数据。返回数据也可以是复杂对象。
最后将返回结果序列化为字符串;出错则将出错信息输出并返回给客户端。
其中 JSON.parse ,JSON.stringify , println 都是内置函数。(JDK 6 中 JSON 对象还不是内置的,请查看下面红字部分。)
运行并查看结果
选择 JSServer 类 ,右键选择 “ Run as Java Application ” , 打开浏览器,输入 “ http://localhost:8080 ” 并回车,可以看到浏览器输出结果如下:
Hello, Pei Xiaoxing!
加入Controller?
如果 api 的形式是 api.controller.action ,那么可以将 app.js 中的 request 对象改为:
var request = { controller: 'hello' action: 'say', params: { name: 'Pei Xiaoxing' } };
并修改 run.js 中参数提取的方式:
var controller = requset.controller; var action = request.action; var params = request.params; ret = { data : api[controller][action](params), success : true }
api 对象的定义可以分开写,比如 api.hello.js 定义一个 controller :
var api = api || {}; api.hello = { say: function(){ ... } }
api.anotherHello.js 定义另一个 controller :
var api = api || {}; api.anotherHello = { anotherSay: function(){ ... } }
REST 风格 URL ? Session, Cookie ?
对于 REST 风格 URL,可以在 run 函数中通过 req.getRequestURI() 获取请求路径,然后直接对路径进行解析。
同样,也可以通过 req.getSession() 和 req.getCookies() 获取 session 和 cookie 。
以上就是我们的第一个 Server 端 JS 程序了。
当然,只是运行这种简单的脚本没有多少意义,但 ScriptEngine 的优势是可以直接导入 Java API。
因此 Java 中能做的,在我们的服务器端也都能做。
关于 Server 端 JavaScript 程序的后续研究的列表如下:
热部署 (已完成)
http://xxing22657-yahoo-com-cn.iteye.com/blog/1054496
文件上传与下载(已完成)
http://xxing22657-yahoo-com-cn.iteye.com/blog/1068055
http://xxing22657-yahoo-com-cn.iteye.com/blog/1070383
利用 MongoDB 进行数据存储(已完成)
http://xxing22657-yahoo-com-cn.iteye.com/blog/1071205
http://xxing22657-yahoo-com-cn.iteye.com/blog/1076016
http://xxing22657-yahoo-com-cn.iteye.com/blog/1097596
仿 Jquery Template 的服务器端模板引擎(已完成)
http://xxing22657-yahoo-com-cn.iteye.com/blog/1112920
http://xxing22657-yahoo-com-cn.iteye.com/blog/1113665
http://xxing22657-yahoo-com-cn.iteye.com/blog/1114521
完善框架功能(已完成 1/6)
http://xxing22657-yahoo-com-cn.iteye.com/blog/1121314
其他模板引擎 (FreeMarker,Velocity,仿 JSP)
数据库操作(SQLite Driver, MySQL JDBC)
ORM(ibatis 等)
其他NoSQL数据库(CouchDB等)
分布式缓存 (Memcached 等)
有朋友指出运行时会出现 "JSON" is not defined 的错误,这是因为 JDK 6 ScriptEngine 中确实没有定义 JSON 对象。因为我自己运行时使用了 JRE 7 预览版,所以没有发现这个问题。
请解压附件中的 json.rar ,并将解压后得到的 json.js 放到“ scripts ”目录下。
- PureJS.rar (966.4 KB)
- 下载次数: 54
- json.rar (1.1 KB)
- 下载次数: 43
评论
7 楼
xuhang1128
2011-06-08
xuhang1128 写道
裴小星 写道
yangwen13 写道
运行会报异常:
ReferenceError: "JSON" is not defined.
run.js需要在哪里引入?
ReferenceError: "JSON" is not defined.
run.js需要在哪里引入?
谢谢指出。
增加了一个附件,请查看。
6 楼
裴小星
2011-05-22
key232323 写道
有更轻巧高效的 Java Web Server ?
这个play! framework里有servlet形式,也有就是基于mina的一个非web container的http server,
ZHH2009(douyu的作者)最近好像也在搞这个,打算把netty nio弄出来,我很期待他的进展。
我的mvc中的逻辑处理单元也屏蔽了servlet api,但相当粗糙,你肯定会失望的很。我给你个链接,如果感兴趣请看下。(只看org.dy.web.core就行)
http://wx.cisee.net/Increx/index.php/Index/download
这个play! framework里有servlet形式,也有就是基于mina的一个非web container的http server,
ZHH2009(douyu的作者)最近好像也在搞这个,打算把netty nio弄出来,我很期待他的进展。
我的mvc中的逻辑处理单元也屏蔽了servlet api,但相当粗糙,你肯定会失望的很。我给你个链接,如果感兴趣请看下。(只看org.dy.web.core就行)
http://wx.cisee.net/Increx/index.php/Index/download
好,我研究研究。谢谢。
5 楼
key232323
2011-05-22
有更轻巧高效的 Java Web Server ?
这个play! framework里有servlet形式,也有就是基于mina的一个非web container的http server,
ZHH2009(douyu的作者)最近好像也在搞这个,打算把netty nio弄出来,我很期待他的进展。
我的mvc中的逻辑处理单元也屏蔽了servlet api,但相当粗糙,你肯定会失望的很。我给你个链接,如果感兴趣请看下。(只看org.dy.web.core就行)
http://wx.cisee.net/Increx/index.php/Index/download
这个play! framework里有servlet形式,也有就是基于mina的一个非web container的http server,
ZHH2009(douyu的作者)最近好像也在搞这个,打算把netty nio弄出来,我很期待他的进展。
我的mvc中的逻辑处理单元也屏蔽了servlet api,但相当粗糙,你肯定会失望的很。我给你个链接,如果感兴趣请看下。(只看org.dy.web.core就行)
http://wx.cisee.net/Increx/index.php/Index/download
4 楼
裴小星
2011-05-22
to key232323:
我觉得没什么关系,语言偏好不同。
估计将来的 Java ,会跟现在的 C/C++ 差不多,成为基础性的语言;
而开发应用的语言将会是继承 Java 优点又更加灵活方便的语言,就像 Java 对 C++ 的继承一样。
Groovy 、 JavaScript 、 Scala 等都是候选。
不过 Oracle 收购了 Sun ,Java 的发展多少有点令人担忧。
我看到你的Blog提到 Java 小型应用的性能问题。其实我们都做到这个地步了,完全可以不用servlet container,但是不知道有没有更轻巧高效的 Java Web Server ?
你那个 groovy mvc 在哪里?能给个链接吗?
我觉得没什么关系,语言偏好不同。
估计将来的 Java ,会跟现在的 C/C++ 差不多,成为基础性的语言;
而开发应用的语言将会是继承 Java 优点又更加灵活方便的语言,就像 Java 对 C++ 的继承一样。
Groovy 、 JavaScript 、 Scala 等都是候选。
不过 Oracle 收购了 Sun ,Java 的发展多少有点令人担忧。
我看到你的Blog提到 Java 小型应用的性能问题。其实我们都做到这个地步了,完全可以不用servlet container,但是不知道有没有更轻巧高效的 Java Web Server ?
你那个 groovy mvc 在哪里?能给个链接吗?
3 楼
key232323
2011-05-22
哎——我用groovy搞了一个mvc,跟你这个思路一摸一样,而且
热部署
文件上传与下载
利用 JDBC 连接 MySQL
模板引擎 (FreeMarker,Velocity)
ORM(ibatis 等)
NoSQL数据库(MongoDB,CouchDB)
几乎都考虑了。。悲剧
热部署
文件上传与下载
利用 JDBC 连接 MySQL
模板引擎 (FreeMarker,Velocity)
ORM(ibatis 等)
NoSQL数据库(MongoDB,CouchDB)
几乎都考虑了。。悲剧
2 楼
裴小星
2011-05-21
yangwen13 写道
运行会报异常:
ReferenceError: "JSON" is not defined.
run.js需要在哪里引入?
ReferenceError: "JSON" is not defined.
run.js需要在哪里引入?
谢谢指出。
增加了一个附件,请查看。
1 楼
yangwen13
2011-05-21
运行会报异常:
ReferenceError: "JSON" is not defined.
run.js需要在哪里引入?
ReferenceError: "JSON" is not defined.
run.js需要在哪里引入?
发表评论
-
Pure JS (7):小结
2011-08-09 08:15 1657Pure JS (7):小结 Pure ... -
Pure (6.7):部署
2011-08-07 09:08 1513Pure (6.7):部署 我们可以按照以下步骤部署 Pu ... -
PureJS (6.6):配置 Spket 智能感知
2011-08-05 07:45 1692PureJS (6.6):配置 Spket 智能感知 本文 ... -
PureJS (6.5):配置文件
2011-08-02 07:40 1477PureJS (6.5):配置文件 配置文件的目的是把经 ... -
PureJS (6.4):利用 proxy 对象实现权限控制和数据校验
2011-08-01 07:52 1743PureJS (6.4):利用 proxy 对象实现权限控制和 ... -
PureJS (6.3):Rhino 中的日志与 proxy 对象
2011-07-30 09:23 1982PureJS (6.3):Rhino 中的日志与 proxy ... -
Pure JS (6.2):结合 Rhino 和 Junit GUI 测试 JS
2011-07-24 11:17 2457Pure JS (6.2):结合 Rhino 和 Junit ... -
Pure JS (6.1):使用 Rhino Shell 和 Debugger 运行和调试 JS
2011-07-11 07:10 3996Pure JS (6.1):使用 Rhino Shell 和 ... -
Pure JS (5.3):pure.render 的实现(构造window对象,实现服务器端 JQuery Template)
2011-07-05 06:36 4163Pure JS (5.3):pure.render 的 ... -
Pure JS (5.2):服务器端与客户端共用页面渲染代码
2011-07-04 08:08 2711Pure JS (5.2):服务器端与客户端共用页面渲染代码 ... -
Pure JS (5.1):在服务器端使用 JQuery DOM 和 JQuery Template
2011-07-02 09:10 2994Pure JS (5.1):在服务器端使用 JQuery DO ... -
Pure JS (4.3): pure.db.js 的实现(基于 MongoDB Rhino Driver)
2011-06-18 23:26 2188Pure JS (4.3): pure.db.js 的实现(基 ... -
Pure JS (4.2): Web 应用中服务器端 JS 调用 MongoDB 的简单示例
2011-06-11 10:50 3063Pure JS (4.2): Web 应用中 ... -
Pure JS (4.1): 使用 MongoDB 进行数据存储和管理
2011-06-07 07:40 3781Pure JS (4.1): 使用 MongoDB ... -
Pure JS (3.2): 上传下载 (HTML5 与 Flash 上传实现,配置项说明)
2011-06-04 21:10 2472Pure JS (3.2): 上传下载 (HTML5 与 Fl ... -
Pure JS (3.1):上传下载(利用 HTML5 与 Flash)
2011-06-02 09:11 3559Pure JS (3.1):上传下载( ... -
Pure JS (2): 热部署 (利用 JDK 7 NIO 监控文件变化)
2011-05-22 17:17 6299Pure JS (2): 热部署 (利用 JDK 7 NIO ...
相关推荐
赠送jar包:jetty-server-8.1.8.v20121106.jar; 赠送原API文档:jetty-server-8.1.8.v20121106-javadoc.jar; 赠送源代码:jetty-server-8.1.8.v20121106-sources.jar; 赠送Maven依赖信息文件:jetty-server-8.1.8...
1. **Servlet 3.1支持**:Jetty 9.x系列支持Servlet 3.1规范,这意味着可以使用异步处理、WebSocket、微容器等高级特性。 2. **嵌入式使用**:Jetty的一大优势是可以轻松地嵌入到Java应用程序中,只需几行代码就...
赠送jar包:jetty-http-9.4.11.v20180605.jar; 赠送原API文档:jetty-http-9.4.11.v20180605-javadoc.jar; 赠送源代码:jetty-http-9.4.11.v20180605-sources.jar; 赠送Maven依赖信息文件:jetty-...
在Java Web开发中,Jetty因其小巧、快速且易于集成的特点而受到开发者的青睐。本资料汇总旨在帮助你深入理解和掌握Jetty的相关知识,通过以下几大主题展开: 一、Jetty基础 1. **什么是Servlet容器**:Servlet容器...
赠送jar包:jetty-util-6.1.26.jar; 赠送原API文档:jetty-util-6.1.26-javadoc.jar; 赠送源代码:jetty-util-6.1.26-sources.jar; 赠送Maven依赖信息文件:jetty-util-6.1.26.pom; 包含翻译后的API文档:jetty-...
- Jetty可以直接运行在类路径下,无需打包成WAR文件,简化了开发和测试流程。 - 它与其他Java框架如Spring、Struts、Hibernate等有良好的集成,方便构建复杂的应用程序。 7. **模块化设计**: - Jetty采用模块化...
1. **配置Jetty**:首先,你需要在项目中引入Jetty服务器,配置监听端口,并设置支持长连接。 2. **集成DWR**:然后添加DWR库,配置DWR的`dwr.xml`文件,声明暴露给JavaScript的Java类和方法。 3. **创建Java后端**...
赠送jar包:jetty-io-9.4.43.v20210629.jar; 赠送原API文档:jetty-io-9.4.43.v20210629-javadoc.jar; 赠送源代码:jetty-io-9.4.43.v20210629-sources.jar; 赠送Maven依赖信息文件:jetty-io-9.4.43.v20210629....
赠送jar包:jetty-security-9.3.19.v20170502.jar; 赠送原API文档:jetty-security-9.3.19.v20170502-javadoc.jar; 赠送源代码:jetty-security-9.3.19.v20170502-sources.jar; 赠送Maven依赖信息文件:jetty-...
赠送jar包:jetty-client-9.4.11.v20180605.jar; 赠送原API文档:jetty-client-9.4.11.v20180605-javadoc.jar; 赠送源代码:jetty-client-9.4.11.v20180605-sources.jar; 赠送Maven依赖信息文件:jetty-client-...
在嵌入式Jetty环境下运行Struts2 Annotation项目是一个常见的任务,特别是在开发和测试阶段,因为这种方式能够快速启动服务,而无需依赖大型服务器容器。本文将深入探讨如何配置和执行这个过程,以及涉及的关键技术...
jetty-maven-springMVC-mybitas-eclipse集成demo 数据库配置:/jetty-maven/src/main/resources/applicationContext.xml 数据库导入到test数据库:/jetty-maven/src/main/resources/hms_user.sql 配置好maven环境,...
本文将详细介绍如何在Jetty环境中配置,使得修改js文件时无需重启项目即可生效。 1. **查找Jetty Maven包**: 首先,你需要找到Jetty的Maven包,这个通常位于用户的`.m2`仓库目录下。例如,在Windows系统中,路径...
- **动态热部署**:如何在运行时更新应用而无需重启Jetty。 - **Servlet2.5新特性**:讨论Jetty对Servlet 2.5规范的支持。 6. **Handler详解**:涵盖不同类型的Handler,如Request Handler、Session Handler等,...
3. **Servlet与JSP**:Jetty支持Servlet和JSP,因此学习如何在Jetty上部署Servlet应用和JSP页面至关重要。掌握Servlet生命周期、过滤器和监听器的使用,以及JSP的EL表达式、JSTL标签库等。 4. **Jetty嵌入式使用**...
赠送jar包:jetty-6.1.26.jar; 赠送原API文档:jetty-6.1.26-javadoc.jar; 赠送源代码:jetty-6.1.26-sources.jar; 赠送Maven依赖信息文件:jetty-6.1.26.pom; 包含翻译后的API文档:jetty-6.1.26-javadoc-API...
赠送jar包:jetty-util-9.4.43.v20210629.jar; 赠送原API文档:jetty-util-9.4.43.v20210629-javadoc.jar; 赠送源代码:jetty-util-9.4.43.v20210629-sources.jar; 赠送Maven依赖信息文件:jetty-util-9.4.43.v...
赠送jar包:jetty-http-9.4.43.v20210629.jar; 赠送原API文档:jetty-http-9.4.43.v20210629-javadoc.jar; 赠送源代码:jetty-http-9.4.43.v20210629-sources.jar; 赠送Maven依赖信息文件:jetty-...