Gre*_*gor 13 java servlets nashorn
我想在servlet中执行JavaScript.是否可以在所有servlet调用中重用相同的Scripting Engine?Servlet实例由多个线程共享.这是否需要为每个请求创建一个新的Scripting Engine?这将是一个令人无法接受的性能损失.例如,以下代码是否保存?
public class MyServlet extends HttpServlet {
private ScriptEngineManager factory;
private ScriptEngine engine;
@Override
public void init() throws ServletException {
factory = new ScriptEngineManager();
engine = factory.getEngineByName("nashorn");
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
try (PrintWriter writer = res.getWriter()) {
ScriptContext newContext = new SimpleScriptContext();
newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
engineScope.put("writer", writer);
Object value = engine.eval("writer.print('Hello, World!');", engineScope);
writer.close();
} catch (IOException | ScriptException ex) {
Logger.getLogger(AsyncServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
Run Code Online (Sandbox Code Playgroud)
}
如果这不安全,那么避免每个请求创建引擎的最佳方法是什么?使用引擎池?
编辑: 如果函数不更改任何共享对象但仅使用给定的参数,是否可以重用同一个引擎和一个相同的JavaScriptObject(这是对JS函数的评估)对所有servlet请求的结果跟电话?请看以上示例的以下适应性:
public class MyServlet extends HttpServlet {
private ScriptEngineManager factory;
private ScriptEngine engine;
private ScriptObjectMirror script;
@Override
public void init() throws ServletException {
try {
factory = new ScriptEngineManager();
engine = factory.getEngineByName("nashorn");
script = (ScriptObjectMirror)engine.eval("function(writer) {writer.print('Hello, World!');}");
} catch (ScriptException ex) {
Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
try (PrintWriter writer = res.getWriter()) {
script.call(null, writer);
writer.close();
} catch (IOException ex) {
Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
Run Code Online (Sandbox Code Playgroud)
这样安全吗?
van*_*nje 15
在javax.script.ScriptEngineFactory存在一种方法getParameter(String key).
使用特殊键,THREADING您可以获得此特定发动机工厂的线程信息.
这个小程序为每个注册的发动机工厂打印出这些信息:
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
public class ScriptEngineTest {
public static void main(String[] args) {
final ScriptEngineManager mgr = new ScriptEngineManager();
for(ScriptEngineFactory fac: mgr.getEngineFactories()) {
System.out.println(String.format("%s (%s), %s (%s), %s", fac.getEngineName(),
fac.getEngineVersion(), fac.getLanguageName(),
fac.getLanguageVersion(), fac.getParameter("THREADING")));
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于Java 7,它是:
Mozilla Rhino (1.7 release 3 PRERELEASE), ECMAScript (1.8), MULTITHREADED
Run Code Online (Sandbox Code Playgroud)
对于Java 8:
Oracle Nashorn (1.8.0_25), ECMAScript (ECMA - 262 Edition 5.1), null
Run Code Online (Sandbox Code Playgroud)
null 表示引擎实现不是线程安全的.
在您的servlet中,您可以使用a ThreadLocal为每个线程保存一个单独的引擎,允许为同一线程提供的后续请求重用引擎.
public class MyServlet extends HttpServlet {
private ThreadLocal<ScriptEngine> engineHolder;
@Override
public void init() throws ServletException {
engineHolder = new ThreadLocal<ScriptEngine>() {
@Override
protected ScriptEngine initialValue() {
return new ScriptEngineManager().getEngineByName("nashorn");
}
};
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
try (PrintWriter writer = res.getWriter()) {
ScriptContext newContext = new SimpleScriptContext();
newContext.setBindings(engineHolder.get().createBindings(), ScriptContext.ENGINE_SCOPE);
Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
engineScope.put("writer", writer);
Object value = engineHolder.get().eval("writer.print('Hello, World!');", engineScope);
writer.close();
} catch (IOException | ScriptException ex) {
Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4036 次 |
| 最近记录: |