123
返回列表 发新帖
楼主: Sky-Tiger

JavaScript EE

[复制链接]
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
21#
 楼主| 发表于 2009-4-5 18:30 | 只看该作者
Reporting errors

If an error occurs on the server side, isCompleted() calls showRequestInfo(), whose code is included in Listing 11. This function opens a window and prints the request's information: HTTP method, URL, parameters, headers, and response.

Listing 11. The showRequestInfo() function of xhr.js

var xhrErrorWindow = null;

XHR.prototype.showRequestInfo = function() {
    if (xhrErrorWindow && (xhrErrorWindow.closed || xhrErrorWindow._freeze))
        return;
    xhrErrorWindow = window.open("", "XHRError", "menubar=no, resizable=yes, "
            + "scrollbars=yes, width=600, height=600");
    var doc = xhrErrorWindow.document;
    doc.writeln("<p align='right'>");
    doc.writeln("<button onclick='window._freeze = true'>Freeze</button>")
    doc.writeln("</p>");
    doc.writeln(htmlEncode(this.method + " " + this.url));
    doc.writeln("<pre>" + this.request.status + "</pre>");
    doc.writeln("Parameters:");
    doc.writeln("<pre>");
    for (var i = 0; i < this.params.length; i++) {
        doc.writeln(htmlEncode(this.params.name
                + "=" + this.params.value));
    }
    doc.writeln("</pre>");
    doc.writeln("Headers:");
    doc.writeln("<pre>");
    for (var i = 0; i < this.headers.length; i++) {
        doc.writeln(htmlEncode(this.headers.name
                + "=" + this.headers.value));
    }
    doc.writeln("</pre>");
    doc.writeln("Response:");
    var response = this.request.responseText;
    doc.writeln(response);
    doc.close();
    xhrErrorWindow.focus();
}


       
Enabling window.focus() in Firefox
Select Tools > Options > Content, click the Advanced button next to Enable JavaScript, and make sure Rise or lower windows is checked in Advanced JavaScript Settings.

If a previous HTTP error has already opened the error window, the focus() call makes it the current window, which can cause usability issues if the HTTP error occurs again and again. In this case, it is also difficult to analyze the error because the window's contents would be refreshed every second, making the scrolling impossible.

To fix these usability problems, the showRequestInfo() function adds a button that sets a variable named _freeze when clicked. The request's information is not refreshed if _freeze is true. In addition, the error window is not reopened if the user closes it. After making changes in your code, you can just refresh the application's page to verify whether the error still occurs or is fixed.

The htmlEncode() function (see Listing 12) takes a string parameter and replaces the &, < and > characters with &amp;, &lt;, and &gt;, respectively.

Listing 12. The htmlEncode() function of xhr.js

function htmlEncode(value) {
    return value ? value.replace(/&/g, "&amp;")
        .replace(/</g, "&lt;").replace(/>/g, "&gt;") : "";
}

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
22#
 楼主| 发表于 2009-4-5 18:30 | 只看该作者
Implementing the JavaScript-RPC mechanism

This section presents the JSP tag file that generates the JavaScript functions implementing the client-side portion of the RPC mechanism. You'll also see how their server-side counterparts are invoked and how the results are returned. First of all, though, a few notes on security.

Authorizing function calls

Server-side scripts can be treated like regular resources and you may restrict access to them using the standard security procedures of Java EE. You would typically define one or more roles whose users would have the right the access the scripts depending on the security constraints specified in the web.xml file.

Whether or not you restrict the access to your scripts, Web clients should not be able to invoke any function of a server-side script. A simple way to control which JavaScript functions may be called through the RPC mechanism is to maintain them in a Set collection. The AuthorizedCalls bean (shown in Listing 13) provides thread-safe methods for managing the set of authorized calls.

Listing 13. The AuthorizedCalls class

package jsee.rpc;

import java.util.*;

public class AuthorizedCalls implements java.io.Serializable {
    private Set<String> calls;
   
    public AuthorizedCalls() {
        calls = new HashSet<String>();
    }
   
    protected String encode(String scriptURI, String functionName) {
        return scriptURI + '#' + functionName;
    }
   
    public synchronized void add(String scriptURI, String functionName) {
        calls.add(encode(scriptURI, functionName));
    }

    public synchronized void remove(String scriptURI, String functionName) {
        calls.remove(encode(scriptURI, functionName));
    }

    public synchronized boolean contains(
            String scriptURI, String functionName) {
        return calls.contains(encode(scriptURI, functionName));
    }
   
    public String toString() {
        return calls.toString();
    }
   
}


The sample application of this article needs to authorize the calls from a JSP page. The authorize.tag file (see Listing 14) has two attributes (named function and script) whose values are passed to the add() method of AuthorizedCalls. In addition, any relative script URI is converted to an absolute URI to ensure that each script is uniquely identified by the URI. Because the AuthorizedCalls instance is stored in the session scope, the server-side functions will be executed only on behalf of the authorized users (in case you restrict the access to the script for some of your users).

Listing 14. The authorize.tag file

<%@ attribute name="function" required="true" rtexprvalue="true" %>
<%@ attribute name="script" required="true" rtexprvalue="true" %>

<jsp:useBean id="authorizedCalls"
    class="jsee.rpc.AuthorizedCalls" scope="session"/>
<%
    String functionName = (String) jspContext.getAttribute("function");
    String scriptURI = (String) jspContext.getAttribute("script");
    if (!scriptURI.startsWith("/")) {
        String base = request.getRequestURI();
        base = base.substring(0, base.lastIndexOf("/"));
        scriptURI = base + "/" + scriptURI;
    }
    authorizedCalls.add(scriptURI, functionName);
%>


Another security-related aspect that is very important to analyze is how the parameters of a remotely called function are treated on the server side. It might be tempting to encode JavaScript objects as JSON strings in the Web browser and send them to the server where they could be decoded very easily with eval(). This would be a big mistake; it would allow malicious users to inject code that would be executed on your server.

The sample code in this article allows only primitive types (such as strings and numbers) for the parameters that are submitted with Ajax. On the server side, they are treated as strings, letting the JavaScript engine automatically convert them to numbers when required. If you need more complex types, you should not rely on eval() for decoding the parameters on the server. Use your own encoding/decoding methods.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
23#
 楼主| 发表于 2009-4-5 18:32 | 只看该作者
Using a tag file to produce JavaScript code

The MonitorPage.jsp file, which was presented in the first section of this article, uses the <js:rpc> tag (see Listing 15) to generate the JavaScript routines that call the server-side functions.

Listing 15. Using <js:rpc> in MonitorPage.jsp

<js:rpc function="getInfo()" script="MonitorScript.jss"
        method="GET" async="true" jsonVar="json">
    showInfo(json, "info");
</js:rpc>

<js:rpc function="allocMem(size, seconds)" script="MonitorScript.jss"
        validator="valid('Size', size) && valid('Seconds', seconds)"
        method="POST" async="true"/>

<js:rpc function="gc()" script="MonitorScript.jss"
        method="POST" async="false">
    alert("Garbage Collected");
</js:rpc>


Listing 16 contains the rpc.tag file, which implements the custom tag. The tag file declares its attributes and the used JSP libraries, invokes the authorize.tag file with <js:authorize>, sets two JSP variables named xhrVar and paramList, and generates the client-side JavaScript function with the given name and parameters.

The xhrVar variable is used on the server side to maintain the name of a JavaScript variable that is used throughout the generated JavaScript code, which will be executed in the Web browser. The value of the xhrVar variable is composed of the function's name and the XHR string. For example, if function is getInfo(), the value of the JSP variable (and the name of the JavaScript variable) will be getInfoXHR.

The other JSP variable named paramList will keep the list of parameters that are provided through the function attribute between ( and ). For example, if function is allocMem(size, seconds), the paramList variable will store the size, seconds list.

Listing 16. The rpc.tag file

<%@ attribute name="function" required="true" rtexprvalue="true" %>
<%@ attribute name="script" required="true" rtexprvalue="true" %>
<%@ attribute name="validator" required="false" rtexprvalue="true" %>
<%@ attribute name="jsonVar" required="false" rtexprvalue="true" %>
<%@ attribute name="method" required="false" rtexprvalue="true" %>
<%@ attribute name="async" required="true" rtexprvalue="true"
    type="java.lang.Boolean" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="js" tagdir="/WEB-INF/tags/js" %>

<js:authorize script="${script}" function="${function}"/>

<c:set var="xhrVar" value="${fn:trim(fn:substringBefore(function, '('))}XHR"/>
<c:set var="paramList"
    value="${fn:substringBefore(fn:substringAfter(function, '('), ')')}"/>

var ${xhrVar} = new XHR("${method}", "${script}", ${async});

function ${function} {
    <c:if test="${!empty validator}">
        if (!(${validator}))
            return;
    </c:if>
    var request = ${xhrVar}.newRequest();
    ${xhrVar}.addHeader("Ajax-Call", "${function}");
    <c:forEach var="paramName" items="${paramList}">
        <c:set var="paramName" value="${fn:trim(paramName)}"/>
        ${xhrVar}.addParam("${paramName}", ${paramName});
    </c:forEach>

    function processResponse() {
        if (${xhrVar}.isCompleted()) {
            <c:if test="${!empty jsonVar}">
                var ${jsonVar} = eval(request.responseText);
            </c:if>
            <jsp:doBody/>
        }
    }

    ${xhrVar}.sendRequest(processResponse);
}


The first line of JavaScript code generated by rpc.tag creates the XHR object. Then, the tag file produces the JavaScript function that can be used in the Web browser to invoke its server-side counterpart. If the validator attribute has a non-empty value, the JavaScript expression is included in the generated code to decide whether the remote call can be made or not.

Next, the newRequest() function is used to initialize a new XMLHttpRequest object, which is stored in a local JavaScript variable named request. The generated code will add the Ajax-Call header, whose value is the function's signature. Then, the parameters are added to the XHR object. Listing 17 contains the code generated for the allocMem() function.

Listing 17. The allocMem() generated function

var allocMemXHR = new XHR("POST", "MonitorScript.jss", true);

function allocMem(size, seconds) {
    if (!(valid('Size', size) && valid('Seconds', seconds)))
        return;
    var request = allocMemXHR.newRequest();
    allocMemXHR.addHeader("Ajax-Call", "allocMem(size, seconds)");
    allocMemXHR.addParam("size", size);
    allocMemXHR.addParam("seconds", seconds);
    function processResponse() {
        if (allocMemXHR.isCompleted()) {
        }
    }
    allocMemXHR.sendRequest(processResponse);
}


After the initialization of the XHR object, the rpc.tag file generates an Ajax callback named processResponse(). This function verifies if the Ajax request is completed and evaluates the response if the jsonVar attribute is present.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
24#
 楼主| 发表于 2009-4-5 18:32 | 只看该作者
The content placed between <js:rpc> and </js:rpc> in the JSP page, is included within the Ajax callback, using <jsp:doBody/>. For example, the <js:rpc function="getInfo()" ...> element of MonitorPage.jsp contains showInfo(json, "info"); to process the JSON response. Listing 18 shows where this code is placed within the getInfo() function, which is generated by rpc.tag.

Listing 18. The getInfo() generated function

var getInfoXHR = new XHR("GET", "MonitorScript.jss", true);

function getInfo() {
    var request = getInfoXHR.newRequest();
    getInfoXHR.addHeader("Ajax-Call", "getInfo()");
    function processResponse() {
        if (getInfoXHR.isCompleted()) {
            var json = eval(request.responseText);
            showInfo(json, "info");
        }
    }
    getInfoXHR.sendRequest(processResponse);
}

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
25#
 楼主| 发表于 2009-4-5 18:33 | 只看该作者
Invoking the script's function

Every time you call a generated function in the Web browser, the XHR object is used to send an Ajax request whose URL ends with .jss. In addition, the signature of the function that must be invoked on the server side is provided as an HTTP header named Ajax-Call. The .jss requests are handled by a servlet named JSServlet, which was presented in the first part of this series.

When MonitorScript.jss of the sample application is requested, JSServlet actually executes three scripts: init.jss, MonitorScript.jss, and finalize.jss. The init.jss script (see Listing 19) gets the request parameters, which are Java strings, converting them to JavaScript strings and storing the parameters as the properties of the param object. The init.jss script also provides functions for getting and setting beans.

Listing 19. The init.jss file

var debug = true;
var debugStartTime = java.lang.System.nanoTime();

var param = new Object();
var paramValues = new Object();

function initParams() {
    var paramNames = request.getParameterNames();
    while (paramNames.hasMoreElements()) {
        var name = paramNames.nextElement();
        param[name] = String(request.getParameter(name));
        paramValues[name] = new Array();
        var values = request.getParameterValues(name);
        for (var i = 0; i < values.length; i++)
            paramValues[name] = String(values);
    }
}

initParams();

function getBean(scope, id) {
    return eval(scope).getAttribute(id);
}

function setBean(scope, id, bean) {
    if (!bean)
        bean = eval(id);
    return eval(scope).setAttribute(id, bean);
}


Because all three scripts are executed within the same context, finalize.jss (shown in Listing 20) can use the variables and functions of init.jss and MonitorScript.jss. The finalize.jss script gets the Ajax-Call header, verifies if the call is authorized, uses eval() to invoke the script's function, and converts the returned object to a JSON string, using toSource(). Because the function parameters are transmitted as request parameters, their values are obtained from the param object.

Listing 20. The finalize.jss file

var ajaxCall = request.getHeader("Ajax-Call");
if (ajaxCall != null) {
    var authorizedCalls = getBean("session", "authorizedCalls");
    if (authorizedCalls.contains(request.requestURI, ajaxCall)) {
        var ajaxResponse = eval("with(param) " + ajaxCall);
        if (ajaxResponse)
            print(ajaxResponse.toSource());
    }
}

var debugEndTime = java.lang.System.nanoTime();
if (debug)
    println("// Time: " + (debugEndTime - debugStartTime) + " ns");


It is safe to use eval() for executing the function because the Ajax-Call header is verified with authorizedCalls.contains().

Conclusion

In this article, you learned how to use RPC in Ajax and Java applications that rely on JavaScript code on both servers and clients. You've also seen how to implement Java interfaces with JavaScript, how to create Java arrays and start threads in your JavaScript code, and how to manage the life cycle of the Ajax requests when connecting to data feeds.

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
26#
发表于 2009-4-6 22:33 | 只看该作者
头晕啊

使用道具 举报

回复
论坛徽章:
2
开发板块每日发贴之星
日期:2009-04-11 01:01:03设计板块每日发贴之星
日期:2009-04-11 01:01:04
27#
发表于 2009-4-10 19:40 | 只看该作者
我是上海猎头chris,专门从事IT业的职位推荐,目前为上海一中美合资企业招募5年以上资深Java开发/测试,要就该人能和公司CTO face to face 的沟通,公司在美国有接近10 年的技术积累,如果你是java方面的精英,可将简历发给我,我会和你取得联系,具体介绍该职位的情况,联系人chris,联系方式:chris@genhr.com ,021-65090386

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表