Я хочу выполнить JavaScript внутри сервлета. Можно ли повторно использовать один и тот же механизм сценариев во всех вызовах сервлета? Экземпляры сервлета разделяются несколькими потоками. Требуется ли для создания нового сценария для каждого запроса? Это было бы неприемлемым для исполнения. Например, сохраняется ли следующий код?Повторное использование Nashorn ScriptEngine в сервлет
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);
}
}
}
Если это не безопасно, что было бы лучшим способом, чтобы избежать создания двигателя для каждого запроса? Используя пул двигателей?
Edit: Можно ли повторно использовать один и тот же двигатель и один и тот же JavaScriptObject, что приводит в качестве оценки в JS-функции, для всех запросов сервлет, если функция не изменяет любой общей объект, но использует только аргументы, данные с вызовом? Посмотрите на следующую адаптацию приведенного выше примера:
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);
}
}
Это безопасно?
спасибо! что отвечает на мой вопрос. и спасибо за подсказку использовать локаторы потоков. – Gregor
Пожалуйста, смотрите: http://stackoverflow.com/questions/30140103/should-i-use-a-separate-scriptengine-and-compiledscript-instances-per-each-threa – igr
Я думаю, вы должны передать 'newContext' в' eval' вместо 'engineScope' – gamliela