楼主: 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
11#
 楼主| 发表于 2009-4-5 18:27 | 只看该作者
Handling requests

You could simply call the above runScript() method to execute the script that is mapped to the URL of the HTTP request. In a real application, however, you'll probably want to do some initialization before running the script and some finalization after the script's execution.

It is possible to run multiple scripts, sequentially, in the same context. For example, a script could define a set of variables and functions. Then, another script could do some processing, using the variables and functions of the previous script that was executed in the same context.

The servlet's handleRequest() method (shown in Listing 14) sets the HTTP headers, runs the init.jss script, removes the context path from the request's URI, executes the script that has the obtained URI, and then runs another script named finalize.jss.

Listing 14. The handleRequest() method of JSServlet

public class JSServlet extends HttpServlet {
    ...
    protected void handleRequest(
            HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        if (cacheControlHeader != null)
            response.setHeader("Cache-Control", cacheControlHeader);
        if (contentTypeHeader != null)
            response.setContentType(contentTypeHeader);
        ScriptContext scriptContext = createScriptContext(request, response);
        try {
            runScript("/init.jss", scriptContext);
            String uri = request.getRequestURI();
            uri = uri.substring(request.getContextPath().length());
            try {
                runScript(uri, scriptContext);
            } catch (FileNotFoundException x) {
                response.sendError(404, request.getRequestURI());
            }
            runScript("/finalize.jss", scriptContext);
        } catch (ScriptException x) {
            x.printStackTrace(response.getWriter());
            throw new ServletException(x);
        }
    }
    ...
}


The doGet() and doPost() methods (see Listing 15) of JSServlet call handleRequest().

Listing 15. The doGet() and doPost() methods of JSServlet

public class JSServlet extends HttpServlet {
    ...
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        handleRequest(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        handleRequest(request, response);
    }

}

使用道具 举报

回复
论坛徽章:
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
12#
 楼主| 发表于 2009-4-5 18:28 | 只看该作者
Developing server-side scripts

This section contains several examples of server-side scripts, which show how you can get the request parameters, access the properties of your JavaBeans, and generate JSON responses.

Pre-processing and post-processing

In the previous section, you've seen that JSServlet invokes init.jss (shown in Listing 16) before executing the requested script. If you want to measure how long it takes to execute your scripts, you can store the start time into a variable as shown below.

Listing 16. The init.jss script

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


Then, you can calculate the execution time in finalize.jss (see Listing 17). The time is printed as a JavaScript comment so that JSServlet can generate valid JSON responses.

Listing 17. The finalize.jss script

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


More code will be added to init.jss and finalize.jss through this series.

Getting request parameters

Scripts invoked with the help of JSServlet can access request parameters with request.getParameter() and request.getParameterValues(), which return Java objects. You might prefer a shorter syntax and you might want to work with JavaScript objects instead of Java strings and arrays. This can be done very easily by adding the following lines to init.jss (see Listing 18).

Listing 18. Getting request parameters in init.jss

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();


Let's say you request a script named ParamDemo.jss with the URL shown in Listing 19.

Listing 19. URL example for requesting a script

http://localhost:8080/jsee/ParamDemo.jss?firstName=John&lastName=Smith


In ParamDemo.jss (see Listing 20), you can get the two request parameters with param.firstName and param.lastName.

Listing 20. The ParamDemo.jss example

println("Hello " + param.firstName + " " + param.lastName);

使用道具 举报

回复
论坛徽章:
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
13#
 楼主| 发表于 2009-4-5 18:28 | 只看该作者
Accessing JavaBeans

The application, session and request scopes of a Web application store bean instances, which you can obtain and replace with the getAttribute() and setAttribute() methods of ServletContext, HttpSession, and HttpServletRequest, respectively. You can also use the getBean() and setBean() functions (shown in Listing 21), which must be placed into the init.jss file so that any script can call them. The scope parameter should be one of the following strings:

    * "application"
    * "session"
    * "request"


Listing 21. The getBean() and setBean() functions of init.jss

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);
}


Now say you want to keep an instance of DemoBean (see Listing 22) in the session scope.

Listing 22. The DemoBean.java example

package jsee.demo;

public class DemoBean {
    private int counter;

    public int getCounter() {
        return counter;
    }

    public void setCounter(int counter) {
        this.counter = counter;
    }

}


The BeanDemo.jss script (shown in Listing 23) imports the package containing the JavaBean with importPackage(Packages.jsee.demo). Then, the script tries to get the bean instance from the session scope with getBean(). If the bean is not found, BeanDemo.jss creates the object and places it into the session scope with setBean(). At the end, the script increments and prints the bean's counter property.

Listing 23. The BeanDemo.jss example

importPackage(Packages.jsee.demo);
var bean = getBean("session", "demo");
if (!bean) {
    bean = new DemoBean();
    setBean("session", "demo", bean);
}
bean.counter++;
println(bean.counter);


If you import a package that starts with java, javax, org, edu, com, or net, you don't have to use the Packages prefix in importPackage(). You may also import individual classes with importClass().

使用道具 举报

回复
论坛徽章:
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
14#
 楼主| 发表于 2009-4-5 18:28 | 只看该作者
Returning JSON responses

Listing 24 shows an example that generates a JSON response containing some information about the JavaScript engine and the script's URI. The example uses the JavaScript syntax to create the json object whose source code is obtained as a String with the toSource() method.

Listing 24. The JsonDemo.jss example

var json = {
    engine: {
        name: String(factory.engineName),
        version: String(factory.engineVersion),
        threading: String(factory.getParameter("THREADING"))
    },
    language: {
        name: String(factory.languageName),
        version: String(factory.languageVersion)
    },
    script: {
        uri: String(request.requestURI)
    }
};

println(json.toSource());


All Java objects, which are retrieved from the properties of factory and request in this example, must be converted to JavaScript objects so that toSource() can work properly. Listing 25 contains the script's output:

Listing 25. The output of JsonDemo.jss

({language:{name:"ECMAScript", version:"1.6"},
engine:{name:"Mozilla Rhino", threading:"MULTITHREADED",
version:"1.6 release 2"}, script:{uri:"/jsee/JsonDemo.jss"}})

使用道具 举报

回复
论坛徽章:
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
15#
 楼主| 发表于 2009-4-5 18:29 | 只看该作者
The RPC mechanism is very simple. You have a set of JavaScript functions on the server and you want to be able to call them from the Web browser as if you had a single JavaScript engine executing both the client code and the server code. Therefore, you'll need some client-side routines that should have the same names and parameters as their server-side counterparts.

The client-side routines will use Ajax to transmit their parameters to the server where the actual processing takes place. A Java servlet will invoke the server-side functions and will return the results to the client, using the JSON format. The client-side routines will then evaluate the Ajax responses, converting the JSON strings back to JavaScript objects, which are returned to the application.

As an application developer, you can focus on building the user interface and the functions that are executed on the server. You won't have to deal with Ajax or RPC issues because this article provides a JavaScript code generator in the form of a tag file, which you can use in your JSP pages to produce the client-side routines automatically. To understand how this works, let's start with a sample application.

Developing a JVM-monitoring application

The sample application in this article uses the Java Management API to monitor the JVM running the Java EE server that hosts the application. The user interface consists of a single Web page that shows various indicators, such as the number of Java classes, memory consumption, garbage collector's activity, and the number of threads.

This information is retrieved with Ajax and is inserted into an HTML table (see Figure 1; click here for a larger version of Figure 1). To make things more interesting, the Web page contains a form that lets you allocate some memory for a given number of seconds. You can also invoke the JVM's garbage collector (GC).

Figure 1. Sample application
Screen shot showing the interface of the sample application

On the server side, the application uses a JavaScript file whose functions are invoked from the Web browser with the help of Ajax, using the script runner that was presented in Part 1 of this series. This is a simple servlet that handles all requests whose URLs end with the .jss extension. The servlet looks for the corresponding JavaScript file on the server and executes it, using the Java Scripting API.

使用道具 举报

回复
论坛徽章:
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
16#
 楼主| 发表于 2009-4-5 18:29 | 只看该作者
Creating the Web page

Listing 1 shows the table and the form of the MonitorPage.jsp file. Each data cell has an ID so that the table's content can be updated with JavaScript. The onload attribute of the <body> tag is used to call a JavaScript function named init(), which will initialize the client-side portion of the application. Two other functions named allocMem() and gc() are called when the user clicks the buttons.

Listing 1. The HTML code of MonitorPage.jsp

<html>
<head>
    ...
    <style type="text/css">
        th { text-align: left; }
        td { text-align: right; }
        .space { margin: 10px; }
    </style>
</head>
<body onload="init()">
    <table border="1" cellpadding="5">
        <tr>
            <th colspan=2>Classes</th>
            <th colspan=2>Heap Memory</th>
            <th colspan=2>Non-Heap Memory</th>
            <th colspan=2>Garbage Collector</th>
            <th colspan=2>Threads</th>
        </tr>
        <tr>
            <th>Loaded</th>
            <td id="info.classes.loaded"></td>
            <th>Used</th>
            <td id="info.memory.heap.used"></td>
            <th>Used</th>
            <td id="info.memory.nonHeap.used"></td>
            <th>Count</th>
            <td id="info.gc.count"></td>
            <th>Live</th>
            <td id="info.threads.live"></td>
        </tr>
        <tr>
            <th>Unloaded</th>
            <td id="info.classes.unloaded"></td>
            <th>Committed</th>
            <td id="info.memory.heap.committed"></td>
            <th>Committed</th>
            <td id="info.memory.nonHeap.committed"></td>
            <th>Time</th>
            <td id="info.gc.time"></td>
            <th>Peak</th>
            <td id="info.threads.peak"></td>
        </tr>
    </table>
    <br>
    <form name="monitorForm">
        Size: <input name="size" size="10">
        <span class="space"></span>
        Seconds: <input name="seconds" size="4">
        <span class="space"></span>
        <button type="button"
            onclick="allocMem(this.form.size.value, this.form.seconds.value)"
        >Allocate Memory</button>
        <span class="space"></span>
        <button type="button" onclick="gc()">Collect Garbage</button>
    </form>
</body>
</html>


The MonitorPage.jsp file (see Listing 2) uses a custom tag named <js:rpc> to generate the client-side JavaScript functions that call their server-side counterparts. The <js:rpc> tag has the following attributes:
script        the URL of the script that will be executed on the server
function        the signature of the JavaScript function that is called remotely
validator        an optional expression that is evaluated in the Web browser to verify the function's parameters
jsonVar        the name of an optional JavaScript variable that will store the JSON response
method        the HTTP method, which can be GET or POST
async        a boolean attribute indicating whether XMLHttpRequest should be used asynchronously or synchronously

Listing 2. The JavaScript code of MonitorPage.jsp

<%@ taglib prefix="js" tagdir="/WEB-INF/tags/js" %>

<html>
<head>
    <title>Monitor</title>
    <script src="xhr.js" type="text/javascript">
    </script>
    <script type="text/javascript">
        <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>

        function showInfo(obj, id) {
            if (typeof obj == "object") {
                for (var prop in obj)
                    showInfo(obj[prop], id + "." + prop);
            } else {
                var elem = document.getElementById(id);
                if (elem)
                    elem.innerHTML = htmlEncode(String(obj));
            }
        }

        function valid(name, value) {
            if (!value || value == "") {
                alert(name + " is required");
                return false;
            }
            var n = new Number(value);
            if (isNaN(n) || n <= 0 || Math.floor(n) != n) {
                alert(name + " must be a positive integer.");
                return false;
            } else
                return true;
        }

        function init() {
            getInfo();
            setInterval(getInfo, 1000);
        }
    </script>
    ...
</head>
...
</html>


The JavaScript code included between <js:rpc> and </js:rpc> will be used to process the Ajax responses. For example, in the case of the getInfo() function, the json response is passed to another function named showInfo(), which traverses the object tree recursively, inserting the information within the data cells of the HTML table. Because async is true, the generated getInfo() function will return immediately after sending the request, and the showInfo() function will be invoked by the Ajax callback.

使用道具 举报

回复
论坛徽章:
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
17#
 楼主| 发表于 2009-4-5 18:29 | 只看该作者
The allocMem() function uses the validator attribute to verify the user input. If the valid() function returns false for any of the two parameters, the remote call is canceled and an alert message is shown. The gc() function will wait for the response before returning the control because async is false in its case. The init() function calls getInfo() to initialize the UI and passes the same function to setInterval() so that it is called every second to refresh the Web page's information.

Listing 3 contains the code produced with the <js:rpc> custom tag, which is implemented as a tag file named rpc.tag. Each generated function uses an XHR object whose prototype can be found in the xhr.js file that MonitorPage.jsp imports in its header. The source code of both rpc.tag and xhr.js files will be presented later in this article.

Listing 3. Generated JavaScript functions

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);
}


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);
}


var gcXHR = new XHR("POST", "MonitorScript.jss", false);

function gc() {
    var request = gcXHR.newRequest();
    gcXHR.addHeader("Ajax-Call", "gc()");
    function processResponse() {
        if (gcXHR.isCompleted()) {
            alert("Garbage Collected");
        }
    }
    gcXHR.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
18#
 楼主| 发表于 2009-4-5 18:29 | 只看该作者
Coding the server-side script

The MonitorScript.jss file contains three JavaScript functions that are executed on the server. The getInfo() function (shown in Listing 4) uses the Java Management API to obtain JVM information related to classes, memory, and threads. The entire data is packed into an object tree, which will be returned as JSON in response to an Ajax request. The getInfo() function doesn't have to do anything special. You'll see how the RPC mechanism is implemented in the following sections.

Listing 4. The getInfo() function of MonitorScript.jss

importClass(java.lang.management.ManagementFactory);

function getInfo() {
    var classes = ManagementFactory.getClassLoadingMXBean();
    var memory = ManagementFactory.getMemoryMXBean();
    var heap = memory.getHeapMemoryUsage();
    var nonHeap = memory.getNonHeapMemoryUsage();
    var gc = ManagementFactory.getGarbageCollectorMXBeans();
    var threads = ManagementFactory.getThreadMXBean();

    var gcCount = 0;
    var gcTime = 0;
    for (var i = 0; i < gc.size(); i++) {
        gcCount += gc.get(i).collectionCount;
        gcTime += gc.get(i).collectionTime;
    }

    return {
        classes: {
            loaded: classes.loadedClassCount,
            unloaded: classes.unloadedClassCount,
        },
        memory: {
            heap: {
                init: heap.init,
                used: heap.used,
                committed: heap.committed,
                max: heap.max
            },
            nonHeap: {
                init: nonHeap.init,
                used: nonHeap.used,
                committed: nonHeap.committed,
                max: nonHeap.max
            }
        },
        gc: {
            count: gcCount,
            time: gcTime
        },
        threads: {
            live: threads.threadCount,
            peak: threads.peakThreadCount
        }
    };
}


The allocMem() function (see Listing 5) creates a Java thread that executes a run() method implemented in JavaScript. The code creates a byte array, using the newInstance() method of the java.lang.reflect.Array class, and calls java.lang.Thread.sleep(). After that, the array becomes eligible for garbage collection.

Listing 5. The allocMem() function of MonitorScript.jss

function allocMem(size, seconds) {
    var runnable = new java.lang.Runnable() {
        run: function() {
            var array = new java.lang.reflect.Array.newInstance(
                    java.lang.Byte.TYPE, size);
            java.lang.Thread.sleep(seconds * 1000);
        }
    }
    var thread = new java.lang.Thread(runnable);
    thread.start();
}


Listing 6 shows the gc() function, which invokes the JVM's garbage collector.

Listing 6. The gc() function of MonitorScript.jss

function gc() {
    java.lang.System.gc();
}

使用道具 举报

回复
论坛徽章:
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
19#
 楼主| 发表于 2009-4-5 18:29 | 只看该作者
Building the XMLHttpRequest wrapper

You saw the JavaScript code produced by the <js:rpc> tag in the previous section. To minimize and simplify the generated code, all operations related to the XMLHttpRequest API, such as creating a new request object or sending the HTTP request, were placed into a separate JavaScript file named xhr.js. This section presents the methods of the XHR object.

Initializing requests

The XHR() constructor (see Listing 7) takes three parameters (method, url, and async) and stores them as properties. The newRequest() method aborts the previous request if it's still active, frees the memory with the delete operator, and creates a new XMLHttpRequest instance. This behavior is suitable for applications that use Ajax to connect to a data feed or to save the user's input. In a typical case, you are interested in loading or saving only the latest data.

Listing 7. The XHR() and newRequest() functions of xhr.js

function XHR(method, url, async) {
    this.method = method.toUpperCase();
    this.url = url;
    this.async = async;
}

XHR.prototype.newRequest = function() {
    var request = this.request;
    if (request) {
        request.onreadystatechange = function() { };
        if (request.readyState != 4)
            request.abort();
        delete request;
    }
    request = null;
    if (window.ActiveXObject)
        request = new ActiveXObject("Microsoft.XMLHTTP");
    else if (window.XMLHttpRequest)
        request = new XMLHttpRequest();
    this.request = request;
    this.sent = false;
    this.params = new Array();
    this.headers = new Array();
    return request;
}


Listing 8 shows the addParam() and addHeader() methods, which let you add request parameters and headers that are included in the HTTP request when it's sent. You can use these methods as soon as a new request is created. The checkRequest() function will throw an exception if the XMLHttpRequest object has not been created or if the request has already been sent.

Listing 8. The checkRequest(), addParam(), and addHeader() functions of xhr.js

XHR.prototype.checkRequest = function() {
    if (!this.request)
        throw "Request not created";
    if (this.sent)
        throw "Request already sent";
    return true;
}

XHR.prototype.addParam = function(pname, pvalue) {
    this.checkRequest();
    this.params[this.params.length] = { name: pname, value: pvalue };
}

XHR.prototype.addHeader = function(hname, hvalue) {
    this.checkRequest();
    this.headers[this.headers.length] = { name: hname, value: hvalue };
}

使用道具 举报

回复
论坛徽章:
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
20#
 楼主| 发表于 2009-4-5 18:30 | 只看该作者
Sending requests

The sendRequest() function (see Listing 9) encodes the parameters, opens the request, adds the headers, sets the Ajax callback if async is true, and sends the HTTP request. If async is false, the callback is invoked after send().

Listing 9. The sendRequest() function of xhr.js

XHR.prototype.sendRequest = function(callback) {
    this.checkRequest();
    var query = "";
    for (var i = 0; i < this.params.length; i++) {
        if (query.length > 0)
            query += "&";
        query += encodeURIComponent(this.params.name) + "="
            + encodeURIComponent(this.params.value);
    }
    var url = this.url;
    if (this.method == "GET" && query.length > 0) {
        if (url.indexOf("?") == -1)
            url += "?";
        else
            url += "&";
        url += query;
    }
    this.request.open(this.method, url, this.async);
    for (var i = 0; i < this.headers.length; i++)
        this.request.setRequestHeader(
                this.headers.name, this.headers.value);
    if (this.async)
        this.request.onreadystatechange = callback;
    var body = null;
    if (this.method == "POST") {
        body = query;
        this.request.setRequestHeader("Content-Type",
            "application/x-www-form-urlencoded");
    }
    this.sent = true;
    this.request.send(body);
    if (!this.async)
        callback();
}


In your Ajax callback, you may use isCompleted() (shown in Listing 10) to verify the request's status.

Listing 10. The isCompleted() function of xhr.js

XHR.prototype.isCompleted = function() {
    if (this.request && this.sent)
        if (this.request.readyState == 4)
            if (this.request.status == 200)
                return true;
            else
                this.showRequestInfo();
    return false;
}

使用道具 举报

回复

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

本版积分规则 发表回复

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