Skip to content

Commit c05d0ed

Browse files
committed
解决排序后数据显示错乱问题,关键在addNewInfoEntry和clear中
1 parent bef42c2 commit c05d0ed

File tree

2 files changed

+82
-39
lines changed

2 files changed

+82
-39
lines changed

src/messageTab/Info/InfoTab.java

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package messageTab.Info;
22

33
import java.awt.Component;
4+
import java.util.ArrayList;
45
import java.util.List;
56

67
import javax.swing.JPanel;
8+
import javax.swing.SwingUtilities;
79
import javax.swing.SwingWorker;
810

911
import org.apache.commons.lang3.StringUtils;
@@ -124,33 +126,62 @@ public void setMessage(byte[] content, boolean isRequest) {
124126
return;
125127
} else {
126128
originContent = content;
127-
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
129+
SwingWorker<List<InfoEntry>, Void> worker = new SwingWorker<List<InfoEntry>, Void>() {
130+
/*
131+
* 一、doInBackground()
132+
运行线程:在 后台线程(worker thread) 执行
133+
作用:执行耗时任务(例如网络请求、IO、分析计算)
134+
线程安全性:
135+
不是线程安全的 对 Swing 组件(UI)而言。
136+
在这里不能直接操作 Swing 组件(如 JTable、JLabel 等)。
137+
如果修改 UI,会有随机的显示错误、空指针、数据错乱等问题。
138+
二、done()
139+
运行线程:在 事件派发线程(EDT, Event Dispatch Thread) 执行
140+
作用:后台任务结束后,更新 UI(比如刷新表格、显示结果、关闭加载动画等)
141+
线程安全性:
142+
是线程安全的 对 Swing 组件操作而言。
143+
因为 EDT 是 Swing 的唯一 UI 线程。
144+
*/
128145
@Override
129-
protected Void doInBackground() throws Exception {
130-
((InfoPanel) panel).getTable().getInfoTableModel().clear();
131-
List<String> urls = FindUrlAction.findUrls(originContent);
132-
133-
//清除JS\scss\vue等非接口URL
134-
urls = FindUrlAction.removeJsUrl(urls);
135-
for (String url : urls) {
136-
InfoEntry aaa = new InfoEntry(url, InfoEntry.Type_URL);
137-
((InfoPanel) panel).getTable().getInfoTableModel().addNewInfoEntry(aaa);
138-
}
139-
140-
List<String> emails = EmailUtils.grepEmail(new String(originContent));
141-
emails = TextUtils.deduplicate(emails);
142-
for (String email : emails) {
143-
InfoEntry aaa = new InfoEntry(email, InfoEntry.Type_Email);
144-
((InfoPanel) panel).getTable().getInfoTableModel().addNewInfoEntry(aaa);
145-
}
146-
147-
if (((InfoPanel) panel).getTable().getInfoTableModel().getRowCount()==0) {
148-
InfoEntry aaa = new InfoEntry("No Info To Display", InfoEntry.Type_URL);
149-
((InfoPanel) panel).getTable().getInfoTableModel().addNewInfoEntry(aaa);
150-
}
151-
152-
return null;
153-
}
146+
protected List<InfoEntry> doInBackground() {
147+
List<InfoEntry> entries = new ArrayList<>();
148+
149+
List<String> urls = FindUrlAction.findUrls(originContent);
150+
urls = FindUrlAction.removeJsUrl(urls);
151+
for (String url : urls) {
152+
entries.add(new InfoEntry(url, InfoEntry.Type_URL));
153+
}
154+
155+
List<String> emails = EmailUtils.grepEmail(new String(originContent));
156+
emails = TextUtils.deduplicate(emails);
157+
for (String email : emails) {
158+
entries.add(new InfoEntry(email, InfoEntry.Type_Email));
159+
}
160+
161+
if (entries.isEmpty()) {
162+
entries.add(new InfoEntry("No Info To Display", InfoEntry.Type_URL));
163+
}
164+
165+
return entries;
166+
}
167+
168+
@Override
169+
protected void done() {
170+
try {
171+
List<InfoEntry> newEntries = get();
172+
InfoTableModel model = ((InfoPanel) panel).getTable().getInfoTableModel();
173+
174+
// ✅ 所有 UI 更新都在 EDT 进行
175+
SwingUtilities.invokeLater(() -> {
176+
model.clear();
177+
for (InfoEntry e : newEntries) {
178+
model.addNewInfoEntry(e);
179+
}
180+
});
181+
} catch (Exception ex) {
182+
ex.printStackTrace();
183+
}
184+
}
154185
};
155186
worker.execute();
156187
}

src/messageTab/Info/InfoTableModel.java

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.Arrays;
66
import java.util.List;
77

8+
import javax.swing.SwingUtilities;
89
import javax.swing.table.AbstractTableModel;
910

1011
import burp.BurpExtender;
@@ -107,17 +108,20 @@ public void setValueAt(Object value, int row, int columnIndex) {
107108
}
108109

109110
//////////////////////extend AbstractTableModel////////////////////////////////
110-
111+
111112
public void addNewInfoEntry(InfoEntry lineEntry) {
112-
synchronized (infoEntries) {
113-
infoEntries.add(lineEntry);
114-
int row = infoEntries.size();
115-
//fireTableRowsInserted(row, row);
116-
//need to use row-1 when add setRowSorter to table. why??
117-
//https://stackoverflow.com/questions/6165060/after-adding-a-tablerowsorter-adding-values-to-model-cause-java-lang-indexoutofb
118-
fireTableRowsInserted(row - 1, row - 1);
119-
//fireTableRowsInserted(row-2, row-2);
120-
}
113+
int row;
114+
synchronized (infoEntries) {
115+
infoEntries.add(lineEntry);
116+
row = infoEntries.size() - 1;
117+
//https://stackoverflow.com/questions/6165060/after-adding-a-tablerowsorter-adding-values-to-model-cause-java-lang-indexoutofb
118+
}
119+
// fire 事件必须在 EDT 执行
120+
if (SwingUtilities.isEventDispatchThread()) {
121+
fireTableRowsInserted(row, row);
122+
} else {
123+
SwingUtilities.invokeLater(() -> fireTableRowsInserted(row, row));
124+
}
121125
}
122126

123127

@@ -147,9 +151,17 @@ public void removeRows(int[] rows) {
147151
}
148152

149153
public void clear() {
150-
synchronized (infoEntries) {
151-
infoEntries = new ArrayList<>();
152-
}
154+
int oldSize;
155+
synchronized (infoEntries) {
156+
oldSize = infoEntries.size();
157+
infoEntries.clear();
158+
}
159+
if (oldSize > 0) {
160+
// 必须通知 JTable & Sorter 数据被清空
161+
fireTableRowsDeleted(0, oldSize - 1);
162+
} else {
163+
fireTableDataChanged();
164+
}
153165
}
154166

155167
public void updateRows(int[] rows) {

0 commit comments

Comments
 (0)