Support ScriptEngine#eval(String, Bindings) in ScriptTemplateView
Supporting ScriptEngine#eval(String, Bindings) when no render function is specified allows to support use cases where script templates are simply evaluating a script expression with an even more simplified configuration. This improvement also makes it possible to use script engines that do not implement Invocable. Issue: SPR-15115
This commit is contained in:
@@ -17,6 +17,8 @@
|
||||
package org.springframework.web.servlet.view.script;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -63,7 +65,8 @@ public interface ScriptTemplateConfig {
|
||||
String getRenderObject();
|
||||
|
||||
/**
|
||||
* Return the render function name (mandatory).
|
||||
* Return the render function name (optional). If not specified, the script templates
|
||||
* will be evaluated with {@link ScriptEngine#eval(String, Bindings)}.
|
||||
*/
|
||||
@Nullable
|
||||
String getRenderFunction();
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.web.servlet.view.script;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
/**
|
||||
@@ -65,9 +67,23 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
||||
private String resourceLoaderPath;
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public ScriptTemplateConfigurer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ScriptTemplateConfigurer using the given engine name.
|
||||
*/
|
||||
public ScriptTemplateConfigurer(String engineName) {
|
||||
this.engineName = engineName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the {@link ScriptEngine} to use by the view.
|
||||
* The script engine must implement {@code Invocable}.
|
||||
* If {@code renderFunction} is specified, the script engine must implement {@code Invocable}.
|
||||
* You must define {@code engine} or {@code engineName}, not both.
|
||||
* <p>When the {@code sharedEngine} flag is set to {@code false}, you should not specify
|
||||
* the script engine with this setter, but with the {@link #setEngineName(String)}
|
||||
@@ -85,7 +101,7 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
||||
|
||||
/**
|
||||
* Set the engine name that will be used to instantiate the {@link ScriptEngine}.
|
||||
* The script engine must implement {@code Invocable}.
|
||||
* If {@code renderFunction} is specified, the script engine must implement {@code Invocable}.
|
||||
* You must define {@code engine} or {@code engineName}, not both.
|
||||
* @see #setEngine(ScriptEngine)
|
||||
*/
|
||||
@@ -155,13 +171,15 @@ public class ScriptTemplateConfigurer implements ScriptTemplateConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the render function name (mandatory).
|
||||
* Set the render function name (optional). If not specified, the script templates
|
||||
* will be evaluated with {@link ScriptEngine#eval(String, Bindings)}.
|
||||
* <p>This function will be called with the following parameters:
|
||||
* <ol>
|
||||
* <li>{@code String template}: the template content</li>
|
||||
* <li>{@code Map model}: the view model</li>
|
||||
* <li>{@code String url}: the template url (since 4.2.2)</li>
|
||||
* <li>{@code RenderingContext context}: the rendering context (since 5.0)</li>
|
||||
* </ol>
|
||||
* @see RenderingContext
|
||||
*/
|
||||
public void setRenderFunction(String renderFunction) {
|
||||
this.renderFunction = renderFunction;
|
||||
|
||||
@@ -29,6 +29,7 @@ import javax.script.Invocable;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import javax.script.SimpleBindings;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -126,7 +127,6 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
* See {@link ScriptTemplateConfigurer#setEngine(ScriptEngine)} documentation.
|
||||
*/
|
||||
public void setEngine(ScriptEngine engine) {
|
||||
Assert.isInstanceOf(Invocable.class, engine, "ScriptEngine must implement Invocable");
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
@@ -260,7 +260,9 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
setEngine(createEngineFromName());
|
||||
}
|
||||
|
||||
Assert.isTrue(this.renderFunction != null, "The 'renderFunction' property must be defined.");
|
||||
if (this.renderFunction != null && this.engine != null) {
|
||||
Assert.isInstanceOf(Invocable.class, this.engine, "ScriptEngine must implement Invocable when 'renderFunction' is specified.");
|
||||
}
|
||||
}
|
||||
|
||||
protected ScriptEngine getEngine() {
|
||||
@@ -357,7 +359,6 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
|
||||
try {
|
||||
ScriptEngine engine = getEngine();
|
||||
Invocable invocable = (Invocable) engine;
|
||||
String url = getUrl();
|
||||
Assert.state(url != null, "'url' not set");
|
||||
String template = getTemplate(url);
|
||||
@@ -372,12 +373,18 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
RenderingContext context = new RenderingContext(obtainApplicationContext(), this.locale, templateLoader, url);
|
||||
|
||||
Object html;
|
||||
if (this.renderObject != null) {
|
||||
if (this.renderFunction == null) {
|
||||
SimpleBindings bindings = new SimpleBindings();
|
||||
bindings.putAll(model);
|
||||
model.put("renderingContext", context);
|
||||
html = engine.eval(template, bindings);
|
||||
}
|
||||
else if (this.renderObject != null) {
|
||||
Object thiz = engine.eval(this.renderObject);
|
||||
html = invocable.invokeMethod(thiz, this.renderFunction, template, model, context);
|
||||
html = ((Invocable)engine).invokeMethod(thiz, this.renderFunction, template, model, context);
|
||||
}
|
||||
else {
|
||||
html = invocable.invokeFunction(this.renderFunction, template, model, context);
|
||||
html = ((Invocable)engine).invokeFunction(this.renderFunction, template, model, context);
|
||||
}
|
||||
|
||||
response.getWriter().write(String.valueOf(html));
|
||||
|
||||
Reference in New Issue
Block a user