Chcę wykonać JavaScript w serwlecie. Czy jest możliwe ponowne użycie tego samego silnika skryptowego we wszystkich wywołaniach serwletów? Instancje Serwlety są współużytkowane przez wiele wątków. Czy to wymaga utworzenia nowego aparatu Scripting Engine na żądanie? Byłaby to niedopuszczalna kara za wyniki. Jako przykład, czy jest następujący zapis kodu?Reuse Nashorn ScriptEngine in Servlet
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);
}
}
}
Jeśli to nie jest bezpieczne, co byłoby najlepszym sposobem na uniknięcie tworzenia silnik za zamówienie? Korzystając z puli silników?
Edit: Czy możliwe jest ponowne jeden i ten sam silnik i jeden i ten sam JavaScriptObject, co powoduje, jak przy ocenie JS-funkcja dla wszystkich żądań serwletów, jeśli funkcja nie zmienia wspólne obiekt, ale używa tylko argumentów podanych w wywołaniu? Spójrz na następującą adaptację powyższego przykładu:
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);
}
}
Czy to jest bezpieczne?
dziękuję! to odpowiada na moje pytanie. i dziękuję za podpowiedź, aby używać lokalnych wątków. – Gregor
Proszę zobaczyć: http://stackoverflow.com/questions/30140103/should-i-use-a-separate-scriptengine-and-compiledscript-instances-per-each-threa – igr
Myślę, że powinieneś przekazać 'newContext' do' eval' zamiast 'engineScope' – gamliela