如何移除已弃用的ScriptObjectMirror并替换Nashorn API实现消息解码?
Got it, let's tackle this problem step by step. You're looking to ditch the Nashorn-specific ScriptObjectMirror (deprecated since JDK 11) and use standard JSR 223 scripting API features instead—here's exactly how to refactor your code to remove all Nashorn dependencies:
Key Concepts to Switch To
Instead of relying on Nashorn's ScriptObjectMirror, we'll use standard Java collections (like Map<String, Object>) or custom POJOs to handle the JavaScript object returned by your decode function. This works because modern JS engines (like GraalVM JavaScript, the default in JDK 11+) automatically map plain JavaScript objects to Java Maps (or custom classes if you prefer type safety).
Refactored Code
First, remove the Nashorn import entirely, then adjust the return type and logic:
import java.io.File; import java.nio.file.Files; import java.util.Map; import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import org.springframework.core.io.ClassPathResource; // Renamed method to follow Java camelCase conventions public Map<String, Object> decodeString(String decodeString) { try { File resource = new ClassPathResource("script/decode.js").getFile(); ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript"); // Evaluate the script (uses standard API, no Nashorn ties) engine.eval(new String(Files.readAllBytes(resource.toPath()))); Invocable inv = (Invocable) engine; // Call your helper function and decode payload byte[] bytes = (byte[]) inv.invokeFunction("hexToBytes", decodeString); // Cast directly to Map<String, Object> instead of ScriptObjectMirror Map<String, Object> data = (Map<String, Object>) inv.invokeFunction("DecodeElsysPayload", bytes); // Access values exactly like you did before System.out.println(data.entrySet().toString()); System.out.println("temperature:" + data.get("temperature")); System.out.println("humidity:" + data.get("humidity")); return data; } catch (Exception e) { // Replace with specific exception handling (IOException, ScriptException, etc.) for production e.printStackTrace(); throw new RuntimeException("Failed to decode payload", e); } }
Optional: Type-Safe POJO Alternative
If you want stronger type safety instead of using a Map, define a custom Java class that matches the structure of your decoded payload:
// Create a POJO to represent your decoded data public class ElsysPayload { private double temperature; private double humidity; // Add other fields your script returns, plus getters/setters // Getters and Setters public double getTemperature() { return temperature; } public void setTemperature(double temperature) { this.temperature = temperature; } public double getHumidity() { return humidity; } public void setHumidity(double humidity) { this.humidity = humidity; } }
Then update the method to cast directly to this class:
ElsysPayload data = (ElsysPayload) inv.invokeFunction("DecodeElsysPayload", bytes); // Now you can use type-safe getters System.out.println("temperature:" + data.getTemperature());
Important Notes
- Engine Compatibility: This works with GraalVM JavaScript (default in JDK 11+) and any JSR 223-compliant JS engine—no extra dependencies needed.
- Script Requirements: Ensure your
DecodeElsysPayloadfunction returns a plain JavaScript object (not a Nashorn-specific object) for the auto-mapping to work. - Exception Handling: Replace the generic
Exceptioncatch with specific exceptions (likeIOException,ScriptException,NoSuchMethodException) for better error clarity in production.
内容的提问来源于stack exchange,提问作者JustAnotherNoob

