Version: 4.3 Update
Signed-off-by: gh0stkey <24655118+gh0stkey@users.noreply.github.com>
This commit is contained in:
@@ -35,7 +35,7 @@ public class Databoard extends JPanel {
|
||||
private JSplitPane splitPane;
|
||||
private MessageTable messageTable;
|
||||
private JProgressBar progressBar;
|
||||
private SwingWorker<Map<String, List<String>>, Void> handleComboBoxWorker;
|
||||
private SwingWorker<Map<String, List<String>>, Integer> handleComboBoxWorker;
|
||||
private SwingWorker<Void, Void> applyHostFilterWorker;
|
||||
|
||||
public Databoard(MontoyaApi api, ConfigLoader configLoader, MessageTableModel messageTableModel) {
|
||||
@@ -125,16 +125,16 @@ public class Databoard extends JPanel {
|
||||
columnModel.getColumn(5).setPreferredWidth((int) (totalWidth * 0.1));
|
||||
}
|
||||
|
||||
private void setProgressBar(boolean status) {
|
||||
progressBar.setIndeterminate(status);
|
||||
if (!status) {
|
||||
progressBar.setMaximum(100);
|
||||
progressBar.setString("OK");
|
||||
progressBar.setStringPainted(true);
|
||||
private void setProgressBar(boolean status, String message, int progress) {
|
||||
progressBar.setIndeterminate(status && progress <= 0);
|
||||
progressBar.setString(message);
|
||||
progressBar.setStringPainted(true);
|
||||
progressBar.setMaximum(100);
|
||||
|
||||
if (progress > 0) {
|
||||
progressBar.setValue(progress);
|
||||
} else if (!status) {
|
||||
progressBar.setValue(progressBar.getMaximum());
|
||||
} else {
|
||||
progressBar.setString("Loading...");
|
||||
progressBar.setStringPainted(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,54 +173,15 @@ public class Databoard extends JPanel {
|
||||
String selectedHost = hostComboBox.getSelectedItem().toString();
|
||||
|
||||
if (getHostByList().contains(selectedHost)) {
|
||||
progressBar.setVisible(true);
|
||||
setProgressBar(true);
|
||||
hostTextField.setText(selectedHost);
|
||||
hostComboBox.setPopupVisible(false);
|
||||
|
||||
if (handleComboBoxWorker != null && !handleComboBoxWorker.isDone()) {
|
||||
progressBar.setVisible(false);
|
||||
handleComboBoxWorker.cancel(true);
|
||||
}
|
||||
|
||||
handleComboBoxWorker = new SwingWorker<>() {
|
||||
@Override
|
||||
protected Map<String, List<String>> doInBackground() {
|
||||
return getSelectedMapByHost(selectedHost);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
if (!isCancelled()) {
|
||||
try {
|
||||
Map<String, List<String>> selectedDataMap = get();
|
||||
if (!selectedDataMap.isEmpty()) {
|
||||
dataTabbedPane.removeAll();
|
||||
|
||||
for (Map.Entry<String, List<String>> entry : selectedDataMap.entrySet()) {
|
||||
String tabTitle = String.format("%s (%s)", entry.getKey(), entry.getValue().size());
|
||||
Datatable datatablePanel = new Datatable(api, configLoader, entry.getKey(), entry.getValue());
|
||||
datatablePanel.setTableListener(messageTableModel);
|
||||
dataTabbedPane.addTab(tabTitle, datatablePanel);
|
||||
}
|
||||
|
||||
JSplitPane messageSplitPane = messageTableModel.getSplitPane();
|
||||
splitPane.setLeftComponent(dataTabbedPane);
|
||||
splitPane.setRightComponent(messageSplitPane);
|
||||
messageTable = messageTableModel.getMessageTable();
|
||||
resizePanel();
|
||||
|
||||
splitPane.setVisible(true);
|
||||
hostTextField.setText(selectedHost);
|
||||
|
||||
hostComboBox.setPopupVisible(false);
|
||||
applyHostFilter(selectedHost);
|
||||
|
||||
setProgressBar(false);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
handleComboBoxWorker = new DataLoadingWorker(selectedHost);
|
||||
|
||||
handleComboBoxWorker.execute();
|
||||
}
|
||||
@@ -251,33 +212,57 @@ public class Databoard extends JPanel {
|
||||
isMatchHost = false;
|
||||
}
|
||||
|
||||
private Map<String, List<String>> getSelectedMapByHost(String selectedHost) {
|
||||
private Map<String, List<String>> getSelectedMapByHost(String selectedHost, DataLoadingWorker worker) {
|
||||
ConcurrentHashMap<String, Map<String, List<String>>> dataMap = Config.globalDataMap;
|
||||
Map<String, List<String>> selectedDataMap;
|
||||
|
||||
if (selectedHost.contains("*")) {
|
||||
selectedDataMap = new HashMap<>();
|
||||
dataMap.keySet().forEach(key -> {
|
||||
List<String> matchingKeys = new ArrayList<>();
|
||||
|
||||
// 第一步:找出所有匹配的键(预处理)
|
||||
for (String key : dataMap.keySet()) {
|
||||
if ((StringProcessor.matchesHostPattern(key, selectedHost) || selectedHost.equals("*")) && !key.contains("*")) {
|
||||
Map<String, List<String>> ruleMap = dataMap.get(key);
|
||||
matchingKeys.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
// 第二步:分批处理数据
|
||||
int totalKeys = matchingKeys.size();
|
||||
for (int i = 0; i < totalKeys; i++) {
|
||||
String key = matchingKeys.get(i);
|
||||
Map<String, List<String>> ruleMap = dataMap.get(key);
|
||||
|
||||
if (ruleMap != null) {
|
||||
for (String ruleKey : ruleMap.keySet()) {
|
||||
List<String> dataList = ruleMap.get(ruleKey);
|
||||
if (selectedDataMap.containsKey(ruleKey)) {
|
||||
List<String> mergedList = new ArrayList<>(selectedDataMap.get(ruleKey));
|
||||
mergedList.addAll(dataList);
|
||||
// 使用HashSet去重
|
||||
HashSet<String> uniqueSet = new HashSet<>(mergedList);
|
||||
selectedDataMap.put(ruleKey, new ArrayList<>(uniqueSet));
|
||||
} else {
|
||||
selectedDataMap.put(ruleKey, dataList);
|
||||
selectedDataMap.put(ruleKey, new ArrayList<>(dataList));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 报告进度
|
||||
if (worker != null && i % 5 == 0) {
|
||||
int progress = (int) ((i + 1) * 90.0 / totalKeys);
|
||||
worker.publishProgress(progress);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selectedDataMap = dataMap.get(selectedHost);
|
||||
// 对于非通配符匹配,直接返回结果
|
||||
if (worker != null) {
|
||||
worker.publishProgress(90);
|
||||
}
|
||||
}
|
||||
|
||||
return selectedDataMap;
|
||||
return selectedDataMap != null ? selectedDataMap : new HashMap<>();
|
||||
}
|
||||
|
||||
private void filterComboBoxList() {
|
||||
@@ -395,4 +380,67 @@ public class Databoard extends JPanel {
|
||||
hostTextField.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
// 定义为内部类
|
||||
private class DataLoadingWorker extends SwingWorker<Map<String, List<String>>, Integer> {
|
||||
private final String selectedHost;
|
||||
|
||||
public DataLoadingWorker(String selectedHost) {
|
||||
this.selectedHost = selectedHost;
|
||||
progressBar.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, List<String>> doInBackground() throws Exception {
|
||||
return getSelectedMapByHost(selectedHost, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(List<Integer> chunks) {
|
||||
if (!chunks.isEmpty()) {
|
||||
int progress = chunks.get(chunks.size() - 1);
|
||||
setProgressBar(true, "Loading... " + progress + "%", progress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
if (!isCancelled()) {
|
||||
try {
|
||||
Map<String, List<String>> selectedDataMap = get();
|
||||
if (selectedDataMap != null && !selectedDataMap.isEmpty()) {
|
||||
dataTabbedPane.removeAll();
|
||||
|
||||
for (Map.Entry<String, List<String>> entry : selectedDataMap.entrySet()) {
|
||||
String tabTitle = String.format("%s (%s)", entry.getKey(), entry.getValue().size());
|
||||
Datatable datatablePanel = new Datatable(api, configLoader, entry.getKey(), entry.getValue());
|
||||
datatablePanel.setTableListener(messageTableModel);
|
||||
dataTabbedPane.addTab(tabTitle, datatablePanel);
|
||||
}
|
||||
|
||||
JSplitPane messageSplitPane = messageTableModel.getSplitPane();
|
||||
splitPane.setLeftComponent(dataTabbedPane);
|
||||
splitPane.setRightComponent(messageSplitPane);
|
||||
messageTable = messageTableModel.getMessageTable();
|
||||
resizePanel();
|
||||
|
||||
splitPane.setVisible(true);
|
||||
|
||||
applyHostFilter(selectedHost);
|
||||
setProgressBar(false, "OK", 100);
|
||||
} else {
|
||||
setProgressBar(false, "Error", 0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
api.logging().logToOutput("DataLoadingWorker: " + e.getMessage());
|
||||
setProgressBar(false, "Error", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 提供一个公共方法来发布进度
|
||||
public void publishProgress(int progress) {
|
||||
publish(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,15 +33,32 @@ public class MessageRenderer extends DefaultTableCellRenderer {
|
||||
boolean hasFocus, int row, int column) {
|
||||
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
|
||||
MessageEntry messageEntry = log.get(table.convertRowIndexToModel(row)); // 使用convertRowIndexToModel方法转换行索引
|
||||
// 添加边界检查以防止IndexOutOfBoundsException
|
||||
int modelRow = table.convertRowIndexToModel(row);
|
||||
if (modelRow < 0 || modelRow >= log.size()) {
|
||||
// 如果索引无效,返回默认渲染组件(使用默认背景色)
|
||||
component.setBackground(Color.WHITE);
|
||||
component.setForeground(Color.BLACK);
|
||||
return component;
|
||||
}
|
||||
|
||||
MessageEntry messageEntry = log.get(modelRow);
|
||||
|
||||
// 设置颜色
|
||||
String colorByLog = messageEntry.getColor();
|
||||
Color color = colorMap.get(colorByLog);
|
||||
|
||||
// 如果颜色映射中没有找到对应颜色,使用默认白色
|
||||
if (color == null) {
|
||||
color = Color.WHITE;
|
||||
}
|
||||
|
||||
if (isSelected) {
|
||||
// 通过更改RGB颜色来达成阴影效果
|
||||
component.setBackground(new Color(color.getRed() - 0x20, color.getGreen() - 0x20, color.getBlue() - 0x20));
|
||||
int red = Math.max(0, color.getRed() - 0x20);
|
||||
int green = Math.max(0, color.getGreen() - 0x20);
|
||||
int blue = Math.max(0, color.getBlue() - 0x20);
|
||||
component.setBackground(new Color(red, green, blue));
|
||||
} else {
|
||||
// 否则使用原始颜色
|
||||
component.setBackground(color);
|
||||
|
||||
@@ -55,7 +55,6 @@ public class MessageTableModel extends AbstractTableModel {
|
||||
messageTable.setDefaultRenderer(Object.class, new MessageRenderer(filteredLog, messageTable));
|
||||
messageTable.setAutoCreateRowSorter(true);
|
||||
|
||||
// Length字段根据大小进行排序
|
||||
TableRowSorter<DefaultTableModel> sorter = getDefaultTableModelTableRowSorter();
|
||||
messageTable.setRowSorter(sorter);
|
||||
messageTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||
@@ -71,6 +70,8 @@ public class MessageTableModel extends AbstractTableModel {
|
||||
|
||||
private TableRowSorter<DefaultTableModel> getDefaultTableModelTableRowSorter() {
|
||||
TableRowSorter<DefaultTableModel> sorter = (TableRowSorter<DefaultTableModel>) messageTable.getRowSorter();
|
||||
|
||||
// Length字段根据大小进行排序
|
||||
sorter.setComparator(4, (Comparator<String>) (s1, s2) -> {
|
||||
Integer age1 = Integer.parseInt(s1);
|
||||
Integer age2 = Integer.parseInt(s2);
|
||||
@@ -104,6 +105,14 @@ public class MessageTableModel extends AbstractTableModel {
|
||||
return;
|
||||
}
|
||||
|
||||
if (comment == null || comment.trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (color == null || color.trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isDuplicate = false;
|
||||
try {
|
||||
if (!log.isEmpty() && flag) {
|
||||
@@ -241,131 +250,163 @@ public class MessageTableModel extends AbstractTableModel {
|
||||
}
|
||||
|
||||
public void applyHostFilter(String filterText) {
|
||||
filteredLog.clear();
|
||||
fireTableDataChanged();
|
||||
// 预分配合适的容量,避免频繁扩容
|
||||
final List<MessageEntry> newFilteredLog = new ArrayList<>(log.size() / 2);
|
||||
|
||||
// 预处理过滤条件,优化性能
|
||||
final boolean isWildcardFilter = "*".equals(filterText) || filterText.contains("*");
|
||||
final String normalizedFilter = filterText.toLowerCase().trim();
|
||||
|
||||
// 创建log的安全副本
|
||||
final List<MessageEntry> logSnapshot;
|
||||
synchronized (log) {
|
||||
logSnapshot = new ArrayList<>(log);
|
||||
}
|
||||
|
||||
int batchSize = 500;
|
||||
|
||||
// 分批处理数据
|
||||
List<MessageEntry> batch = new ArrayList<>(batchSize);
|
||||
int count = 0;
|
||||
|
||||
for (MessageEntry entry : log) {
|
||||
String host = StringProcessor.getHostByUrl(entry.getUrl());
|
||||
if (!host.isEmpty() && (StringProcessor.matchesHostPattern(host, filterText) || filterText.contains("*"))) {
|
||||
batch.add(entry);
|
||||
count++;
|
||||
|
||||
// 当批次达到指定大小时,更新UI
|
||||
if (count % batchSize == 0) {
|
||||
final List<MessageEntry> currentBatch = new ArrayList<>(batch);
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
filteredLog.addAll(currentBatch);
|
||||
fireTableDataChanged();
|
||||
});
|
||||
batch.clear();
|
||||
// 使用并行流高效过滤,但保持有序
|
||||
logSnapshot.parallelStream()
|
||||
.filter(entry -> {
|
||||
// 快速通配符检查
|
||||
if (isWildcardFilter && "*".equals(filterText)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
String host = StringProcessor.getHostByUrl(entry.getUrl());
|
||||
if (host.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 优化后的匹配逻辑
|
||||
return StringProcessor.matchesHostPattern(host, filterText) ||
|
||||
(isWildcardFilter && host.toLowerCase().contains(normalizedFilter.replace("*", "")));
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.forEachOrdered(newFilteredLog::add);
|
||||
|
||||
// 处理最后一批
|
||||
if (!batch.isEmpty()) {
|
||||
final List<MessageEntry> finalBatch = new ArrayList<>(batch);
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
filteredLog.addAll(finalBatch);
|
||||
fireTableDataChanged();
|
||||
});
|
||||
}
|
||||
// 一次性更新UI,避免频繁刷新
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
synchronized (filteredLog) {
|
||||
filteredLog.clear();
|
||||
filteredLog.addAll(newFilteredLog);
|
||||
}
|
||||
fireTableDataChanged();
|
||||
});
|
||||
}
|
||||
|
||||
public void applyMessageFilter(String tableName, String filterText) {
|
||||
filteredLog.clear();
|
||||
for (MessageEntry entry : log) {
|
||||
List<MessageEntry> newFilteredLog = new ArrayList<>();
|
||||
|
||||
// 创建log的安全副本以避免ConcurrentModificationException
|
||||
List<MessageEntry> logSnapshot;
|
||||
synchronized (log) {
|
||||
logSnapshot = new ArrayList<>(log);
|
||||
}
|
||||
|
||||
for (MessageEntry entry : logSnapshot) {
|
||||
// 标志变量,表示是否满足过滤条件
|
||||
AtomicBoolean isMatched = new AtomicBoolean(false);
|
||||
|
||||
HttpRequestResponse requestResponse = entry.getRequestResponse();
|
||||
HttpRequest httpRequest = requestResponse.request();
|
||||
HttpResponse httpResponse = requestResponse.response();
|
||||
try {
|
||||
HttpRequestResponse requestResponse = entry.getRequestResponse();
|
||||
HttpRequest httpRequest = requestResponse.request();
|
||||
HttpResponse httpResponse = requestResponse.response();
|
||||
|
||||
String requestString = new String(httpRequest.toByteArray().getBytes(), StandardCharsets.UTF_8);
|
||||
String requestBody = new String(httpRequest.body().getBytes(), StandardCharsets.UTF_8);
|
||||
String requestHeaders = httpRequest.headers().stream()
|
||||
.map(HttpHeader::toString)
|
||||
.collect(Collectors.joining("\r\n"));
|
||||
String requestString = new String(httpRequest.toByteArray().getBytes(), StandardCharsets.UTF_8);
|
||||
String requestBody = new String(httpRequest.body().getBytes(), StandardCharsets.UTF_8);
|
||||
String requestHeaders = httpRequest.headers().stream()
|
||||
.map(HttpHeader::toString)
|
||||
.collect(Collectors.joining("\r\n"));
|
||||
|
||||
String responseString = new String(httpResponse.toByteArray().getBytes(), StandardCharsets.UTF_8);
|
||||
String responseBody = new String(httpResponse.body().getBytes(), StandardCharsets.UTF_8);
|
||||
String responseHeaders = httpResponse.headers().stream()
|
||||
.map(HttpHeader::toString)
|
||||
.collect(Collectors.joining("\r\n"));
|
||||
String responseString = new String(httpResponse.toByteArray().getBytes(), StandardCharsets.UTF_8);
|
||||
String responseBody = new String(httpResponse.body().getBytes(), StandardCharsets.UTF_8);
|
||||
String responseHeaders = httpResponse.headers().stream()
|
||||
.map(HttpHeader::toString)
|
||||
.collect(Collectors.joining("\r\n"));
|
||||
|
||||
Config.globalRules.keySet().forEach(i -> {
|
||||
for (Object[] objects : Config.globalRules.get(i)) {
|
||||
String name = objects[1].toString();
|
||||
String format = objects[4].toString();
|
||||
String scope = objects[6].toString();
|
||||
Config.globalRules.keySet().forEach(i -> {
|
||||
for (Object[] objects : Config.globalRules.get(i)) {
|
||||
String name = objects[1].toString();
|
||||
String format = objects[4].toString();
|
||||
String scope = objects[6].toString();
|
||||
|
||||
// 从注释中查看是否包含当前规则名,包含的再进行查询,有效减少无意义的检索时间
|
||||
if (entry.getComment().contains(name)) {
|
||||
if (name.equals(tableName)) {
|
||||
// 标志变量,表示当前规则是否匹配
|
||||
boolean isMatch = false;
|
||||
// 从注释中查看是否包含当前规则名,包含的再进行查询,有效减少无意义的检索时间
|
||||
if (entry.getComment().contains(name)) {
|
||||
if (name.equals(tableName)) {
|
||||
// 标志变量,表示当前规则是否匹配
|
||||
boolean isMatch = false;
|
||||
|
||||
switch (scope) {
|
||||
case "any":
|
||||
isMatch = matchingString(format, filterText, requestString) || matchingString(format, filterText, responseString);
|
||||
break;
|
||||
case "request":
|
||||
isMatch = matchingString(format, filterText, requestString);
|
||||
break;
|
||||
case "response":
|
||||
isMatch = matchingString(format, filterText, responseString);
|
||||
break;
|
||||
case "any header":
|
||||
isMatch = matchingString(format, filterText, requestHeaders) || matchingString(format, filterText, responseHeaders);
|
||||
break;
|
||||
case "request header":
|
||||
isMatch = matchingString(format, filterText, requestHeaders);
|
||||
break;
|
||||
case "response header":
|
||||
isMatch = matchingString(format, filterText, responseHeaders);
|
||||
break;
|
||||
case "any body":
|
||||
isMatch = matchingString(format, filterText, requestBody) || matchingString(format, filterText, responseBody);
|
||||
break;
|
||||
case "request body":
|
||||
isMatch = matchingString(format, filterText, requestBody);
|
||||
break;
|
||||
case "response body":
|
||||
isMatch = matchingString(format, filterText, responseBody);
|
||||
break;
|
||||
case "request line":
|
||||
String requestLine = requestString.split("\\r?\\n", 2)[0];
|
||||
isMatch = matchingString(format, filterText, requestLine);
|
||||
break;
|
||||
case "response line":
|
||||
String responseLine = responseString.split("\\r?\\n", 2)[0];
|
||||
isMatch = matchingString(format, filterText, responseLine);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
switch (scope) {
|
||||
case "any":
|
||||
isMatch = matchingString(format, filterText, requestString) || matchingString(format, filterText, responseString);
|
||||
break;
|
||||
case "request":
|
||||
isMatch = matchingString(format, filterText, requestString);
|
||||
break;
|
||||
case "response":
|
||||
isMatch = matchingString(format, filterText, responseString);
|
||||
break;
|
||||
case "any header":
|
||||
isMatch = matchingString(format, filterText, requestHeaders) || matchingString(format, filterText, responseHeaders);
|
||||
break;
|
||||
case "request header":
|
||||
isMatch = matchingString(format, filterText, requestHeaders);
|
||||
break;
|
||||
case "response header":
|
||||
isMatch = matchingString(format, filterText, responseHeaders);
|
||||
break;
|
||||
case "any body":
|
||||
isMatch = matchingString(format, filterText, requestBody) || matchingString(format, filterText, responseBody);
|
||||
break;
|
||||
case "request body":
|
||||
isMatch = matchingString(format, filterText, requestBody);
|
||||
break;
|
||||
case "response body":
|
||||
isMatch = matchingString(format, filterText, responseBody);
|
||||
break;
|
||||
case "request line":
|
||||
String requestLine = requestString.split("\\r?\\n", 2)[0];
|
||||
isMatch = matchingString(format, filterText, requestLine);
|
||||
break;
|
||||
case "response line":
|
||||
String responseLine = responseString.split("\\r?\\n", 2)[0];
|
||||
isMatch = matchingString(format, filterText, responseLine);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
isMatched.set(isMatch);
|
||||
break;
|
||||
}
|
||||
|
||||
isMatched.set(isMatch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 由于每个用户规则不同,如果进行项目文件共享则需要考虑全部匹配一下
|
||||
if (!isMatched.get()) {
|
||||
isMatched.set(matchingString("{0}", filterText, requestString) || matchingString("{0}", filterText, responseString));
|
||||
}
|
||||
|
||||
if (isMatched.get()) {
|
||||
newFilteredLog.add(entry);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
|
||||
if (isMatched.get()) {
|
||||
filteredLog.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
fireTableDataChanged();
|
||||
messageTable.lastSelectedIndex = -1;
|
||||
// 在EDT线程中更新UI
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
synchronized (filteredLog) {
|
||||
filteredLog.clear();
|
||||
filteredLog.addAll(newFilteredLog);
|
||||
}
|
||||
fireTableDataChanged();
|
||||
messageTable.lastSelectedIndex = -1;
|
||||
});
|
||||
}
|
||||
|
||||
private boolean matchingString(String format, String filterText, String target) {
|
||||
@@ -398,7 +439,9 @@ public class MessageTableModel extends AbstractTableModel {
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return filteredLog.size();
|
||||
synchronized (filteredLog) {
|
||||
return filteredLog.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -408,27 +451,31 @@ public class MessageTableModel extends AbstractTableModel {
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
if (!filteredLog.isEmpty()) {
|
||||
synchronized (filteredLog) {
|
||||
if (rowIndex < 0 || rowIndex >= filteredLog.size()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
MessageEntry messageEntry = filteredLog.get(rowIndex);
|
||||
|
||||
if (messageEntry != null) {
|
||||
return switch (columnIndex) {
|
||||
case 0 -> messageEntry.getMethod();
|
||||
case 1 -> messageEntry.getUrl();
|
||||
case 2 -> messageEntry.getComment();
|
||||
case 3 -> messageEntry.getStatus();
|
||||
case 4 -> messageEntry.getLength();
|
||||
case 5 -> messageEntry.getColor();
|
||||
default -> "";
|
||||
};
|
||||
if (messageEntry == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return switch (columnIndex) {
|
||||
case 0 -> messageEntry.getMethod();
|
||||
case 1 -> messageEntry.getUrl();
|
||||
case 2 -> messageEntry.getComment();
|
||||
case 3 -> messageEntry.getStatus();
|
||||
case 4 -> messageEntry.getLength();
|
||||
case 5 -> messageEntry.getColor();
|
||||
default -> "";
|
||||
};
|
||||
} catch (Exception e) {
|
||||
api.logging().logToError("getValueAt: " + e.getMessage());
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user