我想让用户拖放一个链接到列表,这将进入数据库的网址,允许用户查看所有的链接,文章,或类似的东西在页面的右上角(即使是简单的细节,如标题和链接是什么时候被添加的罚款),然后查看网页视图。我无法让它在右上角正确显示url详细信息,或在右下角正确显示webview。我对javafx和derby非常熟悉,只是对web方面不太熟悉。任何帮助都将不胜感激。到目前为止,url可以拖放到列表中,标题和一些详细信息在右上角显示不正确。webview在大多数情况下也不起作用。超链接也无法在列表中正确显示,但这只是一些需要修复的格式。最终目标只是允许用户在他们输入的url上监视新的帖子、文章或新闻。
DBUtils.java
public class DBUtils {
final static Properties props = new Properties();
static {
props.put("user", "admin");
props.put("password", "letmein");
}
private static String framework = "embedded";
private static String driver = "org.apache.derby.jdbc.EmbeddedDriver";
private static String protocol = "jdbc:derby:";
public static void setupDb() {
loadDriver();
Connection conn = null;
ArrayList statements = new ArrayList();
Statement s = null;
ResultSet rs = null;
try {
String dbName = "UrlDB";
conn = DriverManager.getConnection(protocol + dbName + ";create=true", props);
System.out.println("Creating database " + dbName);
boolean createTable = false;
s = conn.createStatement();
try {
s.executeQuery("SELECT count(*) FROM urlFeed");
} catch (Exception e) {
createTable = true;
}
if (createTable) {
conn.setAutoCommit(false);
s = conn.createStatement();
statements.add(s);
s.execute("CREATE TABLE UrlFeed(ID INT, Title VARCHAR(255), Url VARCHAR(600))");
System.out.println("Created table UrlFeed ");
conn.commit();
}
shutdown();
} catch (SQLException sqle) {
sqle.printStackTrace();
} finally {
close(rs);
int i = 0;
while (!statements.isEmpty()) {
Statement st = (Statement) statements.remove(i);
close(st);
}
close(conn);
}}
public static List<UrlFeed> loadFeeds() {
loadDriver();
Connection conn = null;
ResultSet rs = null;
List<UrlFeed> feeds = new ArrayList<>();
try {
String dbName = "UrlDB";
conn = DriverManager.getConnection(protocol + dbName + ";create=true", props);
rs = conn.createStatement().executeQuery("SELECT ID, Title, Url FROM UrlFeed");
while (rs.next()) {
String title = rs.getString("title");
String url = rs.getString("url");
UrlFeed urlFeed = new UrlFeed(title, url);
urlFeed.id = urlFeed.link.hashCode();
feeds.add(urlFeed);
}
shutdown();
} catch (SQLException sqle) {
sqle.printStackTrace();
} finally {
close(rs);
close(conn);
}
return feeds;
}
private static void shutdown() {
if (framework.equals("embedded")) {
try {
DriverManager.getConnection("jdbc:derby:;shutdown=true");
} catch (SQLException se) {
if (((se.getErrorCode() == 50000)
&& ("XJ015".equals(se.getSQLState())))) {
System.out.println("Derby shut down normally");
} else {
System.err.println("Derby did not shut down normally");
se.printStackTrace();
}}
}}
public static int saveUrlFeed(UrlFeed urlFeed) {
int pk = urlFeed.link.hashCode();
loadDriver();
Connection conn = null;
ArrayList statements = new ArrayList();
PreparedStatement psInsert = null;
Statement s = null;
ResultSet rs = null;
try {
String dbName = "UrlDB";
conn = DriverManager.getConnection(protocol + dbName + ";create=true", props);
rs = conn.createStatement().executeQuery("SELECT COUNT(id) FROM UrlFeed WHERE id = " + urlFeed.link.hashCode());
rs.next();
int count = rs.getInt(1);
if (count == 0) {
conn.setAutoCommit(false);
s = conn.createStatement();
statements.add(s);
psInsert = conn.prepareStatement("INSERT INTO UrlFeed VALUES (?, ?, ?)");
statements.add(psInsert);
psInsert.setInt(1, pk);
String escapeTitle = urlFeed.channelTitle.replaceAll("\'", "''");
psInsert.setString(2, escapeTitle);
psInsert.setString(3, urlFeed.link);
psInsert.executeUpdate();
conn.commit();
System.out.println("Inserted " + urlFeed.channelTitle + " " + urlFeed.link);
System.out.println("Committed the transaction");
}
shutdown();
} catch (SQLException sqle) {
sqle.printStackTrace();
} finally {
close(rs);
int i = 0;
while (!statements.isEmpty()) {
Statement st = (Statement) statements.remove(i);
close(st);
}
close(conn);
}
return pk;
}
private static void close(AutoCloseable closable) {
try {
if (closable != null) {
closable.close();
closable = null;
}
} catch (Exception sqle) {
sqle.printStackTrace();
}
}
private static void loadDriver() {
try {
Class.forName(driver);
System.out.println("Loaded driver");
} catch (Exception e) {
e.printStackTrace();
}
}
}
DisplayContentsFromDatabase.java
public class DisplayContentsFromDatabase extends Application {
@Override public void start(Stage stage) {
Group root = new Group();
Scene scene = new Scene(root, 640, 480, Color.WHITE);
final Map<String, Hyperlink> hyperLinksMap = new TreeMap<>();
final WebView newsBrief = new WebView();
final WebEngine webEngine = new WebEngine();
final WebView websiteView = new WebView();
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue){
if (newValue != State.SUCCEEDED) {
return;
}
UrlFeed urlFeed = parse(webEngine.getDocument(), webEngine.getLocation());
hyperLinksMap.get(webEngine.getLocation()).setText(urlFeed.channelTitle);
StringBuilder urlSource = new StringBuilder();
urlSource.append("<head>\n")
.append("</head>\n")
.append("<body>\n");
urlSource.append("<b>")
.append(urlFeed.channelTitle)
.append(" (")
.append(urlFeed.news.size())
.append(")")
.append("</b><br />\n");
StringBuilder htmlArticleSb = new StringBuilder();
for (NewsArticle article:urlFeed.news) {
htmlArticleSb.append("<hr />\n")
.append("<b>\n")
.append(article.title)
.append("</b><br />")
.append(article.pubDate)
.append("<br />")
.append(article.description)
.append("<br />\n")
.append("<input type=\"button\" onclick=\"alert('")
.append(article.link)
.append("')\" value=\"View\" />\n");
}
String content = urlSource.toString() + "<form>\n" + htmlArticleSb.toString() + "</form></body>\n";
System.out.println(content);
newsBrief.getEngine().loadContent(content);
DBUtils.saveUrlFeed(urlFeed);
}
});
newsBrief.getEngine().setOnAlert(new EventHandler<WebEvent<String>>(){
public void handle(WebEvent<String> evt) {
websiteView.getEngine().load(evt.getData());
}
});
SplitPane splitPane = new SplitPane();
splitPane.prefWidthProperty().bind(scene.widthProperty());
splitPane.prefHeightProperty().bind(scene.heightProperty());
final VBox leftArea = new VBox(10);
final TextField urlField = new TextField();
urlField.setOnAction(new EventHandler<ActionEvent>(){
public void handle(ActionEvent ae){
String url = urlField.getText();
final Hyperlink jfxHyperLink = createHyperLink(url, webEngine);
hyperLinksMap.put(url, jfxHyperLink);
HBox rowBox = new HBox(20);
rowBox.getChildren().add(jfxHyperLink);
leftArea.getChildren().add(rowBox);
webEngine.load(url);
urlField.setText("");
}
});
leftArea.getChildren().add(urlField);
List<UrlFeed> urlFeeds = DBUtils.loadFeeds();
for (UrlFeed feed:urlFeeds) {
HBox rowBox = new HBox(20);
final Hyperlink jfxHyperLink = new Hyperlink(feed.channelTitle);
jfxHyperLink.setUserData(feed);
final String location = feed.link;
hyperLinksMap.put(feed.link, jfxHyperLink);
jfxHyperLink.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent evt) {
webEngine.load(location);
}
}
);
rowBox.getChildren().add(jfxHyperLink);
leftArea.getChildren().add(rowBox);
}
scene.setOnDragOver(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
if (db.hasUrl()) {
event.acceptTransferModes(TransferMode.COPY);
} else {
event.consume();
}
}
});
scene.setOnDragDropped(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
boolean success = false;
HBox rowBox = new HBox(20);
if (db.hasUrl()) {
if (!hyperLinksMap.containsKey(db.getUrl())) {
final Hyperlink jfxHyperLink = createHyperLink(db.getUrl(), webEngine);
hyperLinksMap.put(db.getUrl(), jfxHyperLink);
rowBox.getChildren().add(jfxHyperLink);
leftArea.getChildren().add(rowBox);
}
webEngine.load(db.getUrl());
}
event.setDropCompleted(success);
event.consume();
}
});
leftArea.setAlignment(Pos.TOP_LEFT);
SplitPane splitPane2 = new SplitPane();
splitPane2.setOrientation(Orientation.VERTICAL);
splitPane2.prefWidthProperty().bind(scene.widthProperty());
splitPane2.prefHeightProperty().bind(scene.heightProperty());
HBox centerArea = new HBox();
centerArea.getChildren().add(newsBrief);
HBox rightArea = new HBox();
rightArea.getChildren().add(websiteView);
splitPane2.getItems().add(centerArea);
splitPane2.getItems().add(rightArea);
splitPane.getItems().add(leftArea);
splitPane.getItems().add(splitPane2);
newsBrief.prefWidthProperty().bind(scene.widthProperty());
websiteView.prefWidthProperty().bind(scene.widthProperty());
ObservableList<SplitPane.Divider> dividers = splitPane.getDividers();
for (int i = 0; i < dividers.size(); i++) {
dividers.get(i).setPosition((i + 1.0) / 3);
}
HBox hbox = new HBox();
hbox.getChildren().add(splitPane);
root.getChildren().add(hbox);
stage.setScene(scene);
stage.show();
}
private static UrlFeed parse(Document doc, String location) {
UrlFeed urlFeed = new UrlFeed();
urlFeed.link = location;
urlFeed.channelTitle = doc.getElementsByTagName("title")
.item(0)
.getTextContent();
NodeList items = doc.getElementsByTagName("item");
for (int i=0; i<items.getLength(); i++){
Map<String, String> childElements = new HashMap<>();
NewsArticle article = new NewsArticle();
for (int j=0; j<items.item(i).getChildNodes().getLength(); j++) {
Node node = items.item(i).getChildNodes().item(j);
childElements.put(node.getNodeName().toLowerCase(), node.getTextContent());
}
article.title = childElements.get("title");
article.description = childElements.get("description");
article.link = childElements.get("link");
article.pubDate = childElements.get("pubdate");
urlFeed.news.add(article);
}
return urlFeed;
}
private Hyperlink createHyperLink(String url, final WebEngine webEngine) {
final Hyperlink jfxHyperLink = new Hyperlink("Loading News...");
UrlFeed aFeed = new UrlFeed();
aFeed.link = url;
jfxHyperLink.setUserData(aFeed);
jfxHyperLink.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent evt) {
UrlFeed urlFeed = (UrlFeed)jfxHyperLink.getUserData();
webEngine.load(urlFeed.link);
}
});
return jfxHyperLink;
}
public static void main(String[] args){
DBUtils.setupDb();
Application.launch(args);
}
}
class UrlFeed {
int id;
String channelTitle = "News...";
String link;
List<NewsArticle> news = new ArrayList<>();
public String toString() {
return "urlFeed{" + "id=" + id + ", channelTitle=" + channelTitle + ", link=" + link + ", news=" + news + '}';
}
public UrlFeed() {
}
public UrlFeed(String title, String link) {
this.channelTitle = title;
this.link = link;
}
}
class NewsArticle {
String title;
String description;
String link;
String pubDate;
public String toString() {
return "NewsArticle{" + "title=" + title + ", description=" + description + ", link=" + link + ", pubDate=" + pubDate + ", enclosure=" + '}';
}
}
1条答案
按热度按时间dtcbnfnu1#
我复制了你的代码并重构了它。
捕捉异常并只打印堆栈跟踪意味着程序将继续运行。例如,如果您不能加载jdbc驱动程序,那么继续下去又有什么意义呢?整个程序取决于能否与数据库交互。
无法从中恢复的异常将导致程序终止。异常可能超出您的控制范围,也可能表示程序中存在错误。
但是请注意,可以忽略这一点
SQLException
当你无法关闭Statement
或者ResultSet
因为即使ResultSet
/Statement
没有关闭。您的jdbc代码应该使用try with资源。
可以使用java.sql.databasemetadata类检查表是否存在。
只需加载一次jdbc驱动程序类。
您应该只在程序终止时关闭数据库。
尽管
WebEngine
将成功加载您在urlField
,方法返回的值getLocation()
可能与您输入的内容不同,因此hyperLinksMap
将不包含您搜索的密钥。因此hyperLinksMap.get(webEngine.getLocation())
将返回null,这意味着下面的代码行将抛出NullPointerException
.你还应该处理
WebEngine
无法加载用户输入的url。下面是重构后的代码。注意,所有的课程都是我做的
public
班级。班级
DisplayContentsFromDatabase
```import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.concurrent.Worker;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Hyperlink;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebEvent;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class DisplayContentsFromDatabase extends Application {
}
班级
UrlFeed
```import java.util.ArrayList;
import java.util.List;
public class UrlFeed {
int id;
String channelTitle = "News...";
String link;
List news = new ArrayList<>();
}
目前上述代码只打印到标准输出。您应该更改它,以便通过gui让用户知道程序正在做什么。例如,在加载网页时,可以显示进度指示器。什么时候
WebEngine
无法加载输入的url,您可能会显示警报。编辑
在回复您的评论时,您写道:
webview似乎没有在右下角加载。有什么建议吗?
我相信你指的是局部变量
websiteView
in方法start
班级DisplayContentsFromDatabase
,即。代码中唯一引用该变量的部分如下(也在方法中
start
):这里引用了javadoc的方法
setOnAlert
:设置属性onalert的值。
de属性scription:javascript alert 处理程序属性。当网页上运行的脚本调用alert函数时,将调用此处理程序。
因此,您需要为包含javascript的网页输入一个url,javascript将显示一个警报。只有这样,代码才会尝试加载某些内容并在中显示它
websiteView
. 请原谅,我不打算测试代码。