diff options
| author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
|---|---|---|
| committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
| commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
| tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html | |
| parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
| download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip | |
initial commit
Diffstat (limited to 'files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html')
| -rw-r--r-- | files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html b/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html new file mode 100644 index 0000000000..b7cf0168f5 --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html @@ -0,0 +1,221 @@ +--- +title: 'Tutorial: Embedding Rhino' +slug: Mozilla/Projects/Rhino/Embedding_tutorial +translation_of: Mozilla/Projects/Rhino/Embedding_tutorial +--- +<p>Embedding Rhino can be done simply with good results. With more effort on the part of the embedder, the objects exposed to scripts can be customized further.</p> +<p>This tutorial leads you through the steps from a simple embedding to more customized, complex embeddings. Fully compilable examples are provided along the way.</p> +<p>The examples live in the <code>rhino/examples</code> directory in the distribution and in <code>mozilla/js/rhino/examples</code> in cvs. This document will link to them using <a href="http://lxr.mozilla.org/">lxr</a>.</p> +<p>In this document, JavaScript code will be in <span class="java_js_code">green</span>, Java code will be in <span class="java_js_code">green,</span> and shell logs will be in <span class="shell_logs_code">purple</span>.</p> +<h2 id="In_this_document">In this document:</h2> +<ul class="toc"> + <li><a href="#runScript">RunScript: A simple embedding</a> + <ul> + <li><a href="#enteringContext">Entering a Context</a></li> + <li><a href="#initializing">Initializing standard objects</a></li> + <li><a href="#collecting">Collecting the arguments</a></li> + <li><a href="#evaluating">Evaluating a script</a></li> + <li><a href="#print">Printing the result</a></li> + <li><a href="#exit">Exiting the Context</a></li> + </ul> + </li> + <li><a href="#expose">Expose Java APIs</a> + <ul> + <li><a href="#useJava">Using Java APIs</a></li> + <li><a href="#implementingInterfaces">Implementing interfaces</a></li> + <li><a href="#addJava">Adding Java objects</a></li> + </ul> + </li> + <li><a href="#usingJSObjs">Using JavaScript objects from Java</a> + <ul> + <li><a href="#usingJSvars">Using JavaScript variables</a></li> + <li><a href="#callingJSfuns">Calling JavaScript functions</a></li> + </ul> + </li> + <li><a href="#javaScriptHostObjects">JavaScript host objects</a> + <ul> + <li><a href="#definingHostObjects">Defining Host Objects</a></li> + <li><a href="#counter">Counter example</a> + <ul> + <li><a href="#counterCtors">Counter's constructors</a></li> + <li><a href="#classname">Class name</a></li> + <li><a href="#dynamic">Dynamic properties</a></li> + <li><a href="#definingMethods">Defining JavaScript "methods"</a></li> + <li><a href="#addingCounter">Adding Counter to RunScript</a></li> + </ul> + </li> + </ul> + </li> +</ul> +<h2 id="RunScript_A_simple_embedding"><a id="runScript" name="runScript">RunScript: A simple embedding</a></h2> +<p>About the simplest embedding of Rhino possible is the <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript.java">RunScript example</a>. All it does it read a script from the command line, execute it, and print a result.</p> +<p>Here's an example use of RunScript from a shell command line:</p> +<pre class="code shell_logs_code">$ java RunScript "Math.cos(Math.PI)" +-1 +$ java RunScript "function f(x){return x+1} f(7)" +8 +</pre> +<p>Note that you'll have to have both the Rhino classes and the RunScript example class file in the classpath. Let's step through the body of <code>main</code> one line at time.</p> +<h3 id="Entering_a_Context"><a id="enteringContext" name="enteringContext">Entering a Context</a></h3> +<p>The code</p> +<pre class="code java_js_code">Context cx = Context.enter(); +</pre> +<p>Creates and enters a <code>Context</code>. A <code>Context</code> stores information about the execution environment of a script.</p> +<h3 id="Initializing_standard_objects"><a name="initializing">Initializing standard objects</a></h3> +<p>The code</p> +<pre class="code java_js_code">Scriptable scope = cx.initStandardObjects(); +</pre> +<p>Initializes the standard objects (<code>Object</code>, <code>Function</code>, etc.) This must be done before scripts can be executed. The <var>null</var> parameter tells <code>initStandardObjects</code> to create and return a scope object that we use in later calls.</p> +<h3 id="Collecting_the_arguments"><a id="collecting" name="collecting">Collecting the arguments</a></h3> +<p>This code is standard Java and not specific to Rhino. It just collects all the arguments and concatenates them together.</p> +<pre class="code java_js_code">String s = ""; +for (int i=0; i < args.length; i++) { + s += args[i]; +} +</pre> +<h3 id="Evaluating_a_script"><a id="evaluating" name="evaluating">Evaluating a script</a></h3> +<p>The code</p> +<pre class="code java_js_code">Object result = cx.evaluateString(scope, s, "<cmd>", 1, null); +</pre> +<p>uses the Context <code>cx</code> to evaluate a string. Evaluation of the script looks up variables in <var>scope</var>, and errors will be reported with the filename <code><cmd></code> and line number 1.</p> +<h3 id="Printing_the_result"><a id="print" name="print">Printing the result</a></h3> +<p>The code</p> +<pre class="code java_js_code">System.out.println(cx.toString(result)); +</pre> +<p>prints the result of evaluating the script (contained in the variable <var>result</var>). <var>result</var> could be a string, JavaScript object, or other values. The <code>toString</code> method converts any JavaScript value to a string.</p> +<h3 id="Exiting_the_Context"><a id="exit" name="exit">Exiting the Context</a></h3> +<p>The code</p> +<pre class="code java_js_code">} finally { + Context.exit(); +} +</pre> +<p>exits the Context. This removes the association between the Context and the current thread and is an essential cleanup action. There should be a call to <code>exit</code> for every call to <code>enter</code>. To make sure that it is called even if an exception is thrown, it is put into the finally block corresponding to the try block starting after <code>Context.enter()</code>.</p> +<h2 id="Expose_Java_APIs"><a id="expose" name="expose">Expose Java APIs</a></h2> +<h3 id="Using_Java_APIs"><a id="useJava" name="useJava">Using Java APIs</a></h3> +<p>No additional code in the embedding needed! The JavaScript feature called + <i> + LiveConnect</i> + allows JavaScript programs to interact with Java objects:</p> +<pre class="code shell_logs_code">$ java RunScript "java.lang.System.out.println(3)" +3.0 +undefined +</pre> +<h3 id="Implementing_interfaces"><a id="implementingInterfaces" name="implementingInterfaces">Implementing interfaces</a></h3> +<p>Using Rhino, JavaScript objects can implement arbitrary Java interfaces. There's no Java code to write -- it's part of Rhino's LiveConnect implementation. For example, we can see how to implement java.lang.Runnable in a Rhino shell session:</p> +<pre class="code shell_logs_code">js> obj = { run: function() { print("hi"); } } +[object Object] +js> obj.run() +hi +js> r = new java.lang.Runnable(obj); +[object Object] +js> t = new java.lang.Thread(r) +Thread[Thread-0,5,main] +js> t.start() +hi +</pre> +<h3 id="Adding_Java_objects"><a id="addJava" name="addJava">Adding Java objects</a></h3> +<p>The next example is <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript2.java">RunScript2</a>. This is the same as RunScript, but with the addition of two extra lines of code:</p> +<pre class="code java_js_code">Object wrappedOut = Context.javaToJS(System.out, scope); +ScriptableObject.putProperty(scope, "out", wrappedOut); +</pre> +<p>These lines add a global variable <code>out</code> that is a JavaScript reflection of the <code>System.out</code> variable:</p> +<pre class="code shell_logs_code">$ java RunScript2 "out.println(42)" +42.0 +undefined +</pre> +<h2 id="Using_JavaScript_objects_from_Java"><a id="usingJSObjs" name="usingJSObjs">Using JavaScript objects from Java</a></h2> +<p>After evaluating a script it's possible to query the scope for variables and functions, extracting values and calling JavaScript functions. This is illustrated in the <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript3.java">RunScript3</a> example. This example adds the ability to print the value of variable <var>x</var> and the result of calling function <code>f</code>. Both <var>x</var> and <var>f</var> are expected to be defined by the evaluated script. For example,</p> +<pre class="code shell_logs_code">$ java RunScript3 "x = 7" +x = 7 +f is undefined or not a function. +$ java RunScript3 "function f(a) { return a; }" +x is not defined. +f("my args") = my arg +</pre> +<h3 id="Using_JavaScript_variables"><a id="usingJSvars" name="usingJSvars">Using JavaScript variables</a></h3> +<p>To print out the value of <var>x</var>, we add the following code:</p> +<pre class="code java_js_code">Object x = scope.get("x", scope); +if (x == Scriptable.NOT_FOUND) { + System.out.println("x is not defined."); +} else { + System.out.println("x = " + Context.toString(x)); +} +</pre> +<h3 id="Calling_JavaScript_functions"><a id="callingJSfuns" name="callingJSfuns">Calling JavaScript functions</a></h3> +<p>To get the function <var>f</var>, call it, and print the result, we add this code:</p> +<pre class="code java_js_code">Object fObj = scope.get("f", scope); +if (!(fObj instanceof Function)) { + System.out.println("f is undefined or not a function."); +} else { + Object functionArgs[] = { "my arg" }; + Function f = (Function)fObj; + Object result = f.call(cx, scope, scope, functionArgs); + String report = "f('my args') = " + Context.toString(result); + System.out.println(report); +} +</pre> +<h2 id="JavaScript_host_objects"><a id="javaScriptHostObjects" name="javaScriptHostObjects">JavaScript host objects</a></h2> +<h3 id="Defining_Host_Objects"><a id="definingHostObjects" name="definingHostObjects">Defining Host Objects</a></h3> +<p>Custom host objects can implement special JavaScript features like dynamic properties.</p> +<h3 id="Counter_example"><a id="counter" name="counter">Counter example</a></h3> +<p>The <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/Counter.java">Counter example</a> is a simple host object. We'll go through it method by method below.</p> +<p>It's easy to try out new host object classes in the shell using its built-in <code>defineClass</code> function. We'll see how to add it to RunScript later. (Note that because the <code>java -jar</code> option preempts the rest of the classpath, we can't use that and access the <code>Counter</code> class.)</p> +<pre class="code shell_logs_code">$ java -cp "js.jar;examples" org.mozilla.javascript.tools.shell.Main +js> defineClass("Counter") +js> c = new Counter(7) +[object Counter] +js> c.count +7 +js> c.count +8 +js> c.count +9 +js> c.resetCount() +js> c.count +0 +</pre> +<h3 id="Counter's_constructors"><a id="counterCtors" name="counterCtors">Counter's constructors</a></h3> +<p>The zero-argument constructor is used by Rhino runtime to create instances. For the counter example, no initialization work is needed, so the implementation is empty.</p> +<pre class="code java_js_code">public Counter () { } +</pre> +<p>The method <code>jsConstructor</code> defines the JavaScript constructor that was called with the expression <code>new Counter(7)</code> in the JavaScript code above.</p> +<pre class="code java_js_code">public void jsConstructor(int a) { count += a; } +</pre> +<h3 id="Class_name"><a id="classname" name="classname">Class name</a></h3> +<p>The class name is defined by the <code>getClassName</code> method. This is used to determine the name of the constructor.</p> +<pre class="code java_js_code">public String getClassName() { return "Counter"; +} +</pre> +<h3 id="Dynamic_properties"><a id="dynamic" name="dynamic">Dynamic properties</a></h3> +<p>Dynamic properties are defined by methods beginning with <code>jsGet_</code> or <code>jsSet_</code>. The method <code>jsGet_count</code> defines the + <i> + count</i> + property.</p> +<pre class="code java_js_code">public int jsGet_count() { return count++; +} +</pre> +<p>The expression <code>c.count</code> in the JavaScript code above results in a call to this method.</p> +<h3 id="Defining_JavaScript_methods"><a id="definingMethods" name="definingMethods">Defining JavaScript "methods"</a></h3> +<p>Methods can be defined using the <code>jsFunction_ prefix</code>. Here we define <code>resetCount</code> for JavaScript.</p> +<pre class="code java_js_code">public void jsFunction_resetCount() { count += 0; } +</pre> +<p>The call <code>c.resetCount()</code> above calls this method.</p> +<h3 id="Adding_Counter_to_RunScript"><a id="addingCounter" name="addingCounter">Adding Counter to RunScript</a></h3> +<p>Now take a look at the <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript4.java">RunScript4 example</a>. It's the same as RunScript except for two additions. The method <code>ScriptableObject.defineClass</code> uses a Java class to define the Counter "class" in the top-level scope:</p> +<pre class="code java_js_code">ScriptableObject.defineClass(scope, Counter.class); +</pre> +<p>Now we can reference the <code>Counter</code> object from our script:</p> +<pre class="code shell_logs_code">$ java RunScript4 "c = new Counter(3); c.count; +c.count;" +</pre> +<p>It also creates a new instance of the <code>Counter</code> object from within our Java code, constructing it with the value 7, and assigning it to the top-level variable <code>myCounter</code>:</p> +<pre class="code java_js_code">Object[] arg = { new Integer(7) }; +Scriptable myCounter = cx.newObject(scope, "Counter", arg); +scope.put("myCounter", scope, myCounter); +</pre> +<p>Now we can reference the <code>myCounter</code> object from our script:</p> +<pre class="code shell_logs_code">$ java RunScript3 'RunScript4 'myCounter.count; myCounter.count' +8 +</pre> |
