Board logo

标题: 方便 Ajax 与 Java EE 的集成(2) [打印本页]

作者: look_w    时间: 2018-7-16 12:48     标题: 方便 Ajax 与 Java EE 的集成(2)

与 Web 框架集成试着把 Ajax 开发与所选的 Java EE Web 框架集成,是很自然的。但是有些 Java EE Web 框架对异步通信模型提供直接可以使用的支持。要体会这个事实的意义,需要理解 servlet 处理同步和异步通信的方式。图 4 显示了处理同步请求的传统 servlet 序列:
图 4. 处理同步请求的 Servlet 序列图 4 对于 Java EE Web 开发人员来说应当相当熟悉。来自浏览器的请求先由控制器 servlet 的 service() 处理。servlet 可以从 HttpRequest 检索到需要的任何值(以参数的形式或者以属性的形式)。一旦控制器处理完成,结果就发送回 HttpRequest (或 HttpSession),而 RequestDispatcher 则把控制转发(或包含)回页面。
图 5 显示了处理异步请求的 servlet 序列:
图 5. 处理异步请求的 Servlet 序列图 5 中的序列与同步序列略有不同。来自浏览器的请求先由控制器 servlet 的 service() 处理。servlet 可以从 HttpRequest 检索到需要的任何值(以参数的形式或者以属性的形式)。一旦控制器处理完成,HttpServletResponse 的内容类型必须设置成 XML。而且,控制器逻辑的结果要用 PrintWriter 写入。这时,RequestDispatcher 的使用被越过。
这个(异步序列)恰恰是多数 Java EE Web 框架不支持的,从而造成与 Ajax 的集成非常困难。不支持异步通信模型的 Portlet 和 JavaServer Faces (JSF)框架面临着同样的问题。
克服这个问题也有一些选项:
使用标记库大量使用标记库(taglib)在 Java 的 Web 应用程序开发中是很普遍的。像许多 Java EE Web 框架一样,有些标记库现在也不支持异步通信模型,没有把通过 XMLHttpRequest 提交的数据转换成 HttpServletRequest (以及反过来)的途径。实际上,不支持异步通信的标记库,在 Ajax XMLHttpRequest 调用期间不工作。可用的选项有:
用 IDE 进行开发与调试有许多 JavaScript 调试工具可以帮助开发人员开发 JavaScript 解决方案。但是,传统的 Java 开发环境不允许检查 XMLHTTPRequest 和与 Ajax 相关的其他东西的值。
一个解决方案是利用 AJAX Toolkit Framework(ATF)(请参阅 )。ATF 是个 Eclipse 插件,带有增强的 JavaScript 编辑特性,例如编辑时语法检查,内嵌的 Mozilla Web 浏览器,内嵌的 DOM 浏览器,内嵌的 JavaScript 调试器。ATF 还包含 Personality Builder 功能,这个功能可以帮助任何 Ajax 运行时框架构建 IDE 特性,从而加入到 ATF 支持的运行时环境集中。
线程问题在典型的同步 Web 应用程序中,有些领域对按钮或链接点击要求更长一点的处理时间。没有耐心和没经验的 Web 用户通常会不止一次地点击按钮或链接,以为可以帮助加快处理速度,从而引发多重表单提交。其他时候,用户认为需要双击(就像桌面应用程序那样)。Web 应用程序中的多重表单提交在某些情况下是无害的。而在其他情况下,副作用可能造成严重的线程问题或争用情况(此时多个线程竞争执行一个代码块)。例如,在银行应用程序中多次点击转帐按钮,可能造成不希望的多次转帐。
既支持同步通信模型又支持异步通信模型的 Web 应用程序会发现,如果它的功能没有正确分析和规划,那么自己就处在了相似的困境中。支持两种通信模型的应用程序在某个页面上可能混合了服务器端调用(即,或者同步,或者异步,或者混合了同步和异步)。就像在多重点击场景中一样,异步调用可能处理得慢些。如果应用程序不做预防,用户可能会在异步线程正在处理时又调用了一个同步调用,因为页面没有刷新,所以无法阻止页面上的进一步活动。结果是两个线程并发处理。虽然不是由 Web 页面上的同一按钮或链接引发,这类情况还是会造成服务器端的线程问题(与多重点击问题类似)。
例如,以图 6 所示的银行应用程序的转账页面为例:
图 6. 转帐示例对于这个示例,用红色表示的转账按钮引发一个 Ajax 调用。退出链接(黄色)引发同步调用。如果不耐烦或没有经验的用户点击了红色按钮之后接着又点击黄色链接(假设两个链接在代码中有共同的路径),就会发生争用情况。
一般来说,有两种方式可以避免这类情况发生。第一种方式是客户端解决方案。一旦点击了一个链接或按钮,就用 JavaScript 确保禁止后续的页面提交,直到当前线程执行完成。第二个解决方案是允许多线程提交,但是依赖于服务器端代码中的同步来避免争用情况。如果引入同步来解决这个问题,请记住 Java EE Web 组件(servlet、portlet、JSF 等)是多线程的。要当心大段代码的同步(特别是与请求/响应生命周期处理有关的代码)。在效果上,同步的误用,会把应用程序变成单线程应用程序,从而降低吞吐率。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0