mirror of
https://github.com/Febbweiss/springboot-react-webpack.git
synced 2026-03-04 22:25:34 +00:00
Optim: more generic server side JS engine
This commit is contained in:
@@ -0,0 +1,76 @@
|
|||||||
|
package com.opengroupe.cloud.saas.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import javax.script.Invocable;
|
||||||
|
import javax.script.ScriptEngine;
|
||||||
|
import javax.script.ScriptEngineManager;
|
||||||
|
import javax.script.ScriptException;
|
||||||
|
|
||||||
|
public class JavaScriptEngine {
|
||||||
|
|
||||||
|
private final ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");
|
||||||
|
|
||||||
|
public JavaScriptEngine polyfillToNashorn() {
|
||||||
|
this.loadFromClassPath("static/js/nashorn-polyfill.js");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaScriptEngine eval(String script) {
|
||||||
|
try {
|
||||||
|
this.scriptEngine.eval(script);
|
||||||
|
} catch (ScriptException e) {
|
||||||
|
throw new IllegalStateException("Failed to eval " + script + "!", e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaScriptEngine loadFromClassPath(String file) {
|
||||||
|
try {
|
||||||
|
this.scriptEngine.eval(readFromClassPath(file));
|
||||||
|
} catch (ScriptException e) {
|
||||||
|
throw new IllegalStateException("Failed to loadFromClassPath " + file + "!", e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object invokeFunction(String functionName, Object... args) {
|
||||||
|
try {
|
||||||
|
return ((Invocable) this.scriptEngine).invokeFunction(functionName, args);
|
||||||
|
} catch (ScriptException | NoSuchMethodException e) {
|
||||||
|
throw new IllegalArgumentException("Failed to invoke " + functionName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T invokeFunction(String functionName, Function<Object, T> converter, Object... args) {
|
||||||
|
return converter.apply(invokeFunction(functionName, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readFromClassPath(String path) {
|
||||||
|
try (InputStream in = getClass().getClassLoader().getResourceAsStream(path)) {
|
||||||
|
if (in == null) {
|
||||||
|
throw new IllegalArgumentException(path + " is not found!");
|
||||||
|
}
|
||||||
|
return copyToString(in, StandardCharsets.UTF_8);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException("Failed to read " + path, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String copyToString(InputStream in, Charset charset) throws IOException {
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(in, charset);) {
|
||||||
|
char[] buffer = new char[4096];
|
||||||
|
int bytesRead = -1;
|
||||||
|
while ((bytesRead = reader.read(buffer)) != -1) {
|
||||||
|
out.append(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.opengroupe.cloud.saas.web;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -12,33 +13,42 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.opengroupe.cloud.saas.domain.Comment;
|
import com.opengroupe.cloud.saas.domain.Comment;
|
||||||
import com.opengroupe.cloud.saas.service.CommentService;
|
import com.opengroupe.cloud.saas.service.CommentService;
|
||||||
import com.opengroupe.cloud.saas.util.React;
|
import com.opengroupe.cloud.saas.util.JavaScriptEngine;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class ViewController {
|
public class ViewController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private CommentService service;
|
private CommentService service;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JavaScriptEngine nashornEngine() {
|
||||||
|
return new JavaScriptEngine().polyfillToNashorn()
|
||||||
|
.loadFromClassPath("META-INF/resources/webjars/react/0.14.7/react.min.js")
|
||||||
|
.loadFromClassPath("META-INF/resources/webjars/marked/0.3.2/marked.js")
|
||||||
|
.loadFromClassPath("static/js/app.js")
|
||||||
|
.loadFromClassPath("static/js/app.render.js");
|
||||||
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ObjectMapper objectMapper;
|
ObjectMapper objectMapper;
|
||||||
|
@Autowired
|
||||||
|
JavaScriptEngine nashorn;
|
||||||
|
|
||||||
private React react = new React();
|
|
||||||
|
|
||||||
@RequestMapping("/greeting")
|
@RequestMapping("/greeting")
|
||||||
public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model) {
|
public String greeting(@RequestParam(value = "name", required = false, defaultValue = "World") String name,
|
||||||
|
Model model) {
|
||||||
model.addAttribute("name", name);
|
model.addAttribute("name", name);
|
||||||
return "greeting";
|
return "greeting";
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping("/index")
|
@RequestMapping("/index")
|
||||||
public String index(Model model) throws JsonProcessingException {
|
public String index(Model model) throws JsonProcessingException {
|
||||||
List<Comment> comments = service.getAll();
|
List<Comment> comments = service.getAll();
|
||||||
String commentBox = react.renderCommentBox(comments);
|
String markup = nashorn.invokeFunction("renderServer", String::valueOf, comments);
|
||||||
String data = objectMapper.writeValueAsString(comments);
|
String data = objectMapper.writeValueAsString(comments);
|
||||||
model.addAttribute("markup", commentBox);
|
model.addAttribute("markup", markup);
|
||||||
model.addAttribute("data", data);
|
model.addAttribute("data", data);
|
||||||
return "index";
|
return "index";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user