如何嵌入角度2+;是否仅将应用程序作为GUI导入JavaFX WebView?
我正在开发一个简单的Java客户机应用程序,我希望在GUI中使用HTML和web应用程序框架,而不是使用Swing或JavaFX 因此,我正在使用Angular 6(使用Angular cli生成)设计、构建和测试我的整个应用程序,我想使用JavaFX WebView和WebEngine组件来指向我的Angular UI 有没有什么简单的/现成的/最佳实践的方法来连接所有东西 我希望用户只是启动应用程序,甚至没有意识到他正在浏览webby。如果可能的话,我甚至不会启动任何web服务器。我只需要一个自包含的应用程序,并使用angular框架仅用于GUI目的 如果我必须启动一个web服务器,我希望在幕后这样做,而不希望用户意识到这一点 问题如何嵌入角度2+;是否仅将应用程序作为GUI导入JavaFX WebView?,java,angular,javafx,webview,angular-cli,Java,Angular,Javafx,Webview,Angular Cli,我正在开发一个简单的Java客户机应用程序,我希望在GUI中使用HTML和web应用程序框架,而不是使用Swing或JavaFX 因此,我正在使用Angular 6(使用Angular cli生成)设计、构建和测试我的整个应用程序,我想使用JavaFX WebView和WebEngine组件来指向我的Angular UI 有没有什么简单的/现成的/最佳实践的方法来连接所有东西 我希望用户只是启动应用程序,甚至没有意识到他正在浏览webby。如果可能的话,我甚至不会启动任何web服务器。我只需要一
- 我试图让WebEngine指向内置的angular应用程序,但angular cli是现成的李>
- 我试图使用com.sun.net.httpserver,但web上的所有解释都只说明如何实现自己的虚拟HttpHandler,因此我无法理解如何将服务器绑定到实际构建的web应用程序(位于项目路径中的文件夹中)或如何将web应用程序部署到httpserver中,以正确的为准
文件://
协议,创建自己的Web服务器是过分的。您只需要定义自己的protocl并在java层中声明它
例如:
以下是我的自定义协议实现:
/**
* Register a protocol handler for URLs like this: <code>myapp:///pics/sland.gif</code><br>
*/
public class MyURLConnection extends URLConnection
{
protected MyURLConnection(URL url) {
super(url);
}
private byte[] data;
@Override
public void connect() throws IOException
{
if (connected)
{
return;
}
loadImage();
connected = true;
}
public String getHeaderField(String name)
{
if ("Content-Type".equalsIgnoreCase(name))
{
return getContentType();
}
else if ("Content-Length".equalsIgnoreCase(name))
{
return "" + getContentLength();
}
return null;
}
public String getContentType()
{
String fileName = getURL().getFile();
String ext = fileName.substring(fileName.lastIndexOf('.')+1);
switch(ext){
case "html":return "text/html";
case "jpg":
case "png":return "image/"+ext;
case "js": return "application/javascript";
}
return "text/"+ext;
// TODO: switch based on file-type "image/" + ext
}
public int getContentLength()
{
return data.length;
}
public long getContentLengthLong()
{
return data.length;
}
public boolean getDoInput()
{
return true;
}
public InputStream getInputStream() throws IOException
{
connect();
return new ByteArrayInputStream(data);
}
/**
* Reads all bytes from an input stream and writes them to an output stream.
*/
private static long copy(InputStream source, OutputStream sink)
throws IOException
{
long nread = 0L;
byte[] buf = new byte[8192];
int n;
while ((n = source.read(buf)) > 0) {
sink.write(buf, 0, n);
nread += n;
}
return nread;
}
private void loadImage() throws IOException
{
if (data != null)
{
return;
}
String fileName = getURL().getFile();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
copy(this.getClass().getResourceAsStream(fileName),byteArrayOutputStream);
data = byteArrayOutputStream.toByteArray();
}
public OutputStream getOutputStream() throws IOException
{
// this might be unnecessary - the whole method can probably be omitted for our purposes
return new ByteArrayOutputStream();
}
public java.security.Permission getPermission() throws IOException
{
return null; // we need no permissions to access this URL
}
}
public class MyURLHandler extends URLStreamHandler
{
@Override
protected URLConnection openConnection(URL url) throws IOException
{
return new MyURLConnection(url);
}
}
public class MyURLStreamHandlerFactory implements URLStreamHandlerFactory
{
public URLStreamHandler createURLStreamHandler(String protocol)
{
if (protocol.equals("myapp"))
{
return new MyURLHandler();
}
return null;
}
}
然后只需在javafx启动中注册协议:
public void start(Stage stage) {
URL.setURLStreamHandlerFactory(new MyURLStreamHandlerFactory());
// etc.
并使用urlmyapp://anyhost/yourfile.html
在您的webkit中(不使用任何主机,请使用您想要的任何东西或修改协议)
编辑:
我在github上的项目(正在进行中)中完成了这项工作:您只需启动WebDesktop
main类。它使用src/main/resources的资源
最终,我通过使用嵌入式Jetty服务于我的角度应用程序,成功地解决了这个问题
@Slf4j
public class MyEmbeddedAngularApp extends Application {
private static final String APPLICATION_TITLE = "My Embedded Angular Application";
/**
* The service executing the server.
*/
private ExecutorService executor = Executors.newSingleThreadExecutor();
@Override
public void start(Stage stage) throws Exception {
startServer();
//Create the root AnchorPane
AnchorPane root = new AnchorPane();
//Initialize the Web UI
WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
webEngine.load("http://localhost:2342");
//add WebView to root
root.getChildren().add(browser);
//Setting up the scene
Scene scene = new Scene(root);
stage.setTitle(APPLICATION_TITLE);
stage.setScene(scene);
//Let the show begin!
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private void startServer() throws Exception {
Server server = new Server(2342);
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
File warFile = new File("./src/main/resources/my-app/dist/my-app");
webapp.setWar(warFile.getAbsolutePath());
server.setHandler(webapp);
server.setStopAtShutdown(true);
server.start();
server.dumpStdErr();
executor.submit(() -> {
try {
server.join();
} catch (InterruptedException e) {
log.error("Could not start the server");
}
});
}
}
我不明白为什么会有反对票,也许我遗漏了什么?我能够用一个虚拟的myfile.html使这个解决方案工作。但它不能与Angular应用程序一起工作,也就是说,当我让WebEngine加载由Angular-cli创建的src文件夹或dist/my-app文件夹的index.html时,它不能工作。你真的使用了文件以外的协议吗?它与javascript、内容类型和同源策略有关:您必须使用application/javascript内容类型为js提供服务,并使用同源策略。我的github示例使用javascript项目,angular项目的编译JS版本也应该以同样的方式工作。@DanieleRepici您是否尝试过不使用文件协议?是的,我尝试过,但不幸的是它没有工作。可能有关联?编辑:我不认为是这样,因为它仍然提到了文件协议。。。你有没有用编译过的angular应用程序尝试过你的解决方案?对不起,我现在让它工作了,不知道发生了什么。谢谢你的支持。