2017-03-05 116 views
2

我目前正在尝试使用javafx,并且正在尝试使用它来制作Web浏览器。到目前为止,它的发展非常好,但是让我感到厌烦的是我不断登录每一个页面。所以我决定使用cookies并将它们存储在一个文件中,所以我不必每次都登录。 我一直试图让这个工作在过去的5个小时,但我仍然必须每次登录。这是我到目前为止有:存储永久性Cookie

public class Main extends Application { 

public static void main(String[] args) { 
    if (!Values.SRCFILE.exists()) { 
     Installation.launch(Installation.class, args); 
     return; 
    } 

    launch(args); 
} 

private Stage stage; 
private GridPane pane; 

private List<BrowserTab> tabs; 

@FXML 
private TabPane tabPane; 

@FXML 
public void initialize() { 
    tabs = new ArrayList<>(); 

    CookieManager manager = new CookieManager(); 
    manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); 
    CookieHandler.setDefault(manager); 

    Map<String, List<String>> map = new HashMap<>(); 
    URI uri = null; 

    try { 
     for (String line : Files.readAllLines(Values.COOKIESFILE.toPath())) { 
      String[] values = line.split("\\|"); 
      URI newUri = new URI(values[0]); 

      if (uri == null) 
       uri = newUri; 

      if (!uri.equals(newUri)) { 
       CookieHandler.getDefault().put(uri, map); 
       uri = newUri; 
       System.out.println(map); 
       map = new HashMap<>(); 
      } 

      String[] actualValues = values[1].split(":"); 

      map.put(actualValues[0], Arrays.asList(actualValues[1].split(";"))); 
     } 

     if (uri != null) 
      CookieHandler.getDefault().put(uri, map); 
    } catch (IOException | URISyntaxException e) { 
     e.printStackTrace(); 
    } 

    System.out.println(map); 

    stage.setOnCloseRequest(new EventHandler<WindowEvent>() { 
     @Override 
     public void handle(WindowEvent event) { 
      if (tabs.size() > 1) { 
       Alert alert = new Alert(Alert.AlertType.CONFIRMATION); 
       alert.setTitle("Closing window"); 
       alert.setHeaderText(""); 
       alert.setContentText("Are you sure you want to close this window? Doing so will close all open tabs"); 
       alert.showAndWait(); 
      } 

      //save cookies 
      CookieStore store = ((CookieManager) CookieHandler.getDefault()).getCookieStore(); 
      try { 
       Files.write(Values.COOKIESFILE.toPath(), ("").getBytes(), StandardOpenOption.TRUNCATE_EXISTING); 

       for (URI uri : store.getURIs()) { 
        Map<String, List<String>> map = CookieHandler.getDefault().get(uri, new HashMap<>()); 

        Files.write(Values.COOKIESFILE.toPath(), (uri + "|").getBytes(), StandardOpenOption.APPEND); 

        for (String value : map.keySet()) { 
         Files.write(Values.COOKIESFILE.toPath(), (value + ":").getBytes(), StandardOpenOption.APPEND); 

         for (String line : map.get(value)) 
          Files.write(Values.COOKIESFILE.toPath(), (line + ";").getBytes(), StandardOpenOption.APPEND); 

         Files.write(Values.COOKIESFILE.toPath(), ("\n").getBytes(), StandardOpenOption.APPEND); 
        } 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 

    addTab(); 
} 

@Override 
public void start(Stage primaryStage) { 
    this.stage = primaryStage; 
    stage.setTitle("Browser"); 

    try { 
     // Load person overview. 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setController(this); 
     loader.setLocation(Main.class.getResource("/browser.fxml")); 
     pane = loader.load(); 

     Scene scene = new Scene(pane); 
     stage.setScene(scene); 
     stage.show(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

public void setURL(String url) { 
    tabs.get(tabPane.getSelectionModel().getSelectedIndex()).setURL(url); 
} 

public void search(String text) { 
    tabs.get(tabPane.getSelectionModel().getSelectedIndex()).search(text); 
} 

void addTab() { 
    BrowserTab browserTab = new BrowserTab(this); 
    browserTab.setText("Loading..."); 
    browserTab.setURL("https://google.com/"); 

    tabs.add(browserTab); 

    browserTab.setOnClosed(new EventHandler<Event>() { 
     @Override 
     public void handle(Event event) { 
      tabs.remove(browserTab); 

      if (tabPane.getTabs().isEmpty()) 
       Platform.exit(); 
     } 
    }); 
    tabPane.getTabs().add(browserTab); 
} 

而且我BrowserTab类

public class BrowserTab extends Tab { 

private Main main; 

private GridPane pane; 

@FXML 
private WebView webView; 
@FXML 
private TextField urlField; 
@FXML 
private Button backButton; 
@FXML 
private Button forwardButton; 
@FXML 
private Button goButton; 
@FXML 
private Button addTabButton; 

public BrowserTab(Main main) { 
    this.main = main; 

    try { 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setController(this); 
     loader.setLocation(getClass().getResource("/tab-template.fxml")); 

     setContent(loader.load()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    initialize(); 
} 

@FXML 
public void initialize() { 
    webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() { 
     @Override 
     public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) { 
      if (newState == Worker.State.SUCCEEDED) { 
       String title = webView.getEngine().titleProperty().getValue(); 

       if (title == null || title.trim().isEmpty()) 
        title = webView.getEngine().getLocation(); 

       setText(title); 
       urlField.setText(webView.getEngine().getLocation()); 
      } 
     } 
    }); 

    backButton.setOnAction(new EventHandler<ActionEvent>() { 
     @Override 
     public void handle(ActionEvent event) { 
      WebHistory history = webView.getEngine().getHistory(); 

      history.go(-1); 

      int index = history.getCurrentIndex(); 

      if (index + 1 > history.getEntries().size() - 1) 
       forwardButton.setDisable(true); 
      else 
       forwardButton.setDisable(false); 

      if (index - 1 < 0) 
       backButton.setDisable(true); 
      else 
       backButton.setDisable(false); 
     } 
    }); 

    forwardButton.setOnAction(new EventHandler<ActionEvent>() { 
     @Override 
     public void handle(ActionEvent event) { 
      WebHistory history = webView.getEngine().getHistory(); 

      history.go(1); 

      int index = history.getCurrentIndex(); 

      if (index + 1 > history.getEntries().size() - 1) 
       forwardButton.setDisable(true); 
      else 
       forwardButton.setDisable(false); 

      if (index - 1 < 0) 
       backButton.setDisable(true); 
      else 
       backButton.setDisable(false); 
     } 
    }); 

    urlField.setOnKeyPressed(new EventHandler<KeyEvent>() { 
     @Override 
     public void handle(KeyEvent event) { 
      if (event.getCode() == KeyCode.ENTER) 
       goButton.fire(); 
     } 
    }); 

    goButton.setOnAction(new EventHandler<ActionEvent>() { 
     @Override 
     public void handle(ActionEvent event) { 
      String url = urlField.getText(); 

      if (!url.contains(".")) { 
       search(url); 
       return; 
      } 

      if (!(url.startsWith("http://") || url.startsWith("https://"))) 
       url = "http://" + url; 

      setURL(url); 
     } 
    }); 

    webView.getEngine().getHistory().getEntries().addListener(new ListChangeListener<WebHistory.Entry>() { 
     @Override 
     public void onChanged(Change<? extends WebHistory.Entry> c) { 
      Platform.runLater(new Runnable() { 
       @Override 
       public void run() { 
        int index = webView.getEngine().getHistory().getCurrentIndex(); 

        System.out.println(index); 

        if (index + 1 > c.getList().size() - 1) 
         forwardButton.setDisable(true); 
        else 
         forwardButton.setDisable(false); 

        if (index - 1 < 0) 
         backButton.setDisable(true); 
        else 
         backButton.setDisable(false); 
       } 
      }); 
     } 
    }); 

    addTabButton.setOnAction(new EventHandler<ActionEvent>() { 
     @Override 
     public void handle(ActionEvent event) { 
      addTab(); 
     } 
    }); 
} 

public void setURL(String url) { 
    webView.getEngine().load(url); 
} 

public void search(String text) { 
    webView.getEngine().load("https://google.com/search?q=" + text); 
} 

private void addTab() { 
    main.addTab(); 
} 

文件格式是这样的:

uri1|value:string1;string2;string3; 
uri2|value:string1;string2;string3; 

任何帮助将真正理解。

+0

参见:[设定使用JavaFX的WebEngine /的WebView一个cookie(http://stackoverflow.com/questions/14385233 /设定-A-cookie的使用-javafxs-webengine-web视图)。 – jewelsea

+0

@jewelsea这解释了如何使用CookieManager,我的主要问题是,一旦我的Cookie从文件加载,并将它们放入CookieManager中,我的WebView似乎完全忽略它们。我确信我的Cookie在没有从文件加载时正确保存,因为我在我的应用程序中打开新选项卡时仍然登录。 – stefvanschie

+0

实际上,答案中的引用是“不要浪费时间来尝试使用java.net.CookieManager和java.net.CookieStore,它们很可能会导致许多网站出现问题,因为它们实施了错误的标准。”无论如何,我没有详细看你的问题或相关问题,所以也许这对你没有用处。祝你的问题好运。 – jewelsea

回答

2

经过多次挖掘后,我发现了解决方案。 问题在于地图(关键元素)中的默认字符串始终是“Cookie:”。但是,在创建地图以将其实际添加到CookieHandler时,它应该是“Set-Cookie”或“Set-Cookie2”。如果它不是其中之一,它会简单地跳过该值,并且根本没有cookie。另外,我最终使用CookieManager和一些方法将cookie转换为字符串,反之亦然。在创建CookieManager时,必须小心选择带有两个参数(cookiestore和cookiepolicy)的构造函数,而不是具有零参数的构造函数。选择一个零参数不会创建一个cookiestore并导致错误。使用带有两个参数的参数时,只需将商店保留为空,它将为您创建一个。这是我最终使用:

节能:

CookieStore store = ((CookieManager) CookieHandler.getDefault()).getCookieStore(); 
try { 
    Files.write(Values.COOKIESFILE.toPath(), ("").getBytes(), StandardOpenOption.TRUNCATE_EXISTING); 

    for (URI uri : store.getURIs()) { 
    Map<String, List<String>> map = CookieHandler.getDefault().get(uri, new HashMap<>()); 

    Files.write(Values.COOKIESFILE.toPath(), (uri + "|Cookie:").getBytes(), StandardOpenOption.APPEND); 

    for (HttpCookie cookie : store.get(uri)) { 
     if (cookie.hasExpired()) 
     continue; 

     Files.write(Values.COOKIESFILE.toPath(), (CookieUtil.toString(cookie) + "~").getBytes(), StandardOpenOption.APPEND); 
    } 

    Files.write(Values.COOKIESFILE.toPath(), "\n".getBytes(), StandardOpenOption.APPEND); 
    } 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

加载:

CookieManager manager = new CookieManager(null, CookiePolicy.ACCEPT_ALL); 

try { 
    for (String line : Files.readAllLines(Values.COOKIESFILE.toPath())) { 
    String[] values = line.split("\\|"); 
    URI uri = new URI(values[0]); 

    String[] actualValues = values[1].split(":"); 

    if (actualValues.length < 2) 
     continue; 

    for (String header : actualValues[1].split("~")) 
     manager.getCookieStore().add(uri, CookieUtil.fromString(header)); 
    } 
    } catch (IOException | URISyntaxException e) { 
    e.printStackTrace(); 
    } 

CookieHandler.setDefault(manager);