Browse Source

健壮性工程

main
ZhangYuhan 3 weeks ago
parent
commit
aa4a2f90e8
  1. 39
      w11/AnalyzeCommand11.java
  2. 27
      w11/Article11.java
  3. 48
      w11/ArticleRepository11.java
  4. 6
      w11/Command11.java
  5. 14
      w11/CommandRegistry11.java
  6. 4
      w11/CrawlStrategy11.java
  7. 6
      w11/CrawlerException11.java
  8. 18
      w11/ExitCommand11.java
  9. 21
      w11/HelpCommand11.java
  10. 31
      w11/HistoryCommand11.java
  11. 81
      w11/Main11.java
  12. 6
      w11/NetworkException11.java
  13. 6
      w11/ParseException11.java
  14. 19
      w11/StrategyFactory11.java

39
w11/AnalyzeCommand11.java

@ -0,0 +1,39 @@
import java.util.List;
import java.util.logging.Logger;
public class AnalyzeCommand11 implements Command11 {
private static final Logger logger = Logger.getLogger(AnalyzeCommand11.class.getName());
private final StrategyFactory11 factory;
public AnalyzeCommand11(StrategyFactory11 factory) {
this.factory = factory;
}
@Override
public String getName() {
return "analyze";
}
@Override
public void execute(String[] args, List<Article11> articles) {
if (args == null || args.length == 0) {
logger.warning("analyze 命令未传入URL参数");
System.out.println("用法:analyze 网址");
return;
}
String url = args[0];
logger.info("开始分析链接:" + url);
CrawlStrategy11 strategy = factory.getMatchStrategy(url);
System.out.println("===== 链接分析结果 =====");
if (strategy != null) {
logger.info("链接 " + url + " 匹配到对应爬取策略");
System.out.println("链接:" + url);
System.out.println("状态:支持解析 ✅");
} else {
logger.warning("链接 " + url + " 未匹配到任何策略");
System.out.println("链接:" + url);
System.out.println("状态:不支持解析 ❌");
}
}
}

27
w11/Article11.java

@ -0,0 +1,27 @@
public class Article11 {
private String title;
private String url;
private String content;
private String author;
private String publishDate;
public Article11(String title, String url, String content) {
this.title = title;
this.url = url;
this.content = content;
}
public Article11(String title, String url, String content, String author, String publishDate) {
this.title = title;
this.url = url;
this.content = content;
this.author = author;
this.publishDate = publishDate;
}
public String getTitle() { return title; }
public String getUrl() { return url; }
public String getContent() { return content; }
public String getAuthor() { return author; }
public String getPublishDate() { return publishDate; }
}

48
w11/ArticleRepository11.java

@ -0,0 +1,48 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
public class ArticleRepository11 {
private static final Logger logger = Logger.getLogger(ArticleRepository11.class.getName());
private final List<Article11> articles = new ArrayList<>();
public void add(Article11 article) {
if (article == null) {
logger.severe("添加失败:文章对象为 null");
throw new IllegalArgumentException("文章对象不能为空");
}
articles.add(article);
logger.info("成功添加文章:" + article.getTitle());
}
public void addAll(List<Article11> newArticles) {
if (newArticles == null) {
logger.severe("批量添加失败:传入列表为 null");
throw new IllegalArgumentException("文章列表不能为空");
}
int successCount = 0;
for (Article11 article : newArticles) {
if (article == null) {
logger.warning("列表中存在空对象,已跳过");
continue;
}
articles.add(article);
successCount++;
}
logger.info("批量添加完成,共成功添加 " + successCount + " 篇文章");
}
public List<Article11> getAll() {
return Collections.unmodifiableList(articles);
}
public int size() {
return articles.size();
}
public void clear() {
logger.info("清空文章集合,原有数量:" + articles.size());
articles.clear();
}
}

6
w11/Command11.java

@ -0,0 +1,6 @@
import java.util.List;
public interface Command11 {
String getName();
void execute(String[] args, List<Article11> articles);
}

14
w11/CommandRegistry11.java

@ -0,0 +1,14 @@
import java.util.HashMap;
import java.util.Map;
public class CommandRegistry11 {
private final Map<String, Command11> commandMap = new HashMap<>();
public void registerCommand(Command11 command) {
commandMap.put(command.getName(), command);
}
public Command11 getCommand(String name) {
return commandMap.get(name);
}
}

4
w11/CrawlStrategy11.java

@ -0,0 +1,4 @@
public interface CrawlStrategy11 {
boolean supports(String url);
Article11 crawl(String url) throws ParseException11, NetworkException11;
}

6
w11/CrawlerException11.java

@ -0,0 +1,6 @@
public class CrawlerException11 extends Exception {
public CrawlerException11() { super(); }
public CrawlerException11(String message) { super(message); }
public CrawlerException11(String message, Throwable cause) { super(message, cause); }
public CrawlerException11(Throwable cause) { super(cause); }
}

18
w11/ExitCommand11.java

@ -0,0 +1,18 @@
import java.util.List;
import java.util.logging.Logger;
public class ExitCommand11 implements Command11 {
private static final Logger logger = Logger.getLogger(ExitCommand11.class.getName());
@Override
public String getName() {
return "exit";
}
@Override
public void execute(String[] args, List<Article11> articles) {
logger.info("用户执行 exit 命令,程序即将退出");
System.out.println("程序已安全退出!");
System.exit(0);
}
}

21
w11/HelpCommand11.java

@ -0,0 +1,21 @@
import java.util.List;
import java.util.logging.Logger;
public class HelpCommand11 implements Command11 {
private static final Logger logger = Logger.getLogger(HelpCommand11.class.getName());
@Override
public String getName() {
return "help";
}
@Override
public void execute(String[] args, List<Article11> articles) {
logger.info("用户执行 help 命令");
System.out.println("===== W11 帮助菜单 =====");
System.out.println("help 查看帮助");
System.out.println("history 查看命令历史");
System.out.println("analyze 分析URL链接");
System.out.println("exit 退出程序");
}
}

31
w11/HistoryCommand11.java

@ -0,0 +1,31 @@
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
public class HistoryCommand11 implements Command11 {
private static final Logger logger = Logger.getLogger(HistoryCommand11.class.getName());
private final List<String> commandHistory = new ArrayList<>();
@Override
public String getName() {
return "history";
}
@Override
public void execute(String[] args, List<Article11> articles) {
if (commandHistory.isEmpty()) {
logger.info("暂无命令历史记录");
System.out.println("暂无命令历史记录");
return;
}
logger.info("用户查看命令历史");
System.out.println("===== 命令历史 =====");
for (int i = 0; i < commandHistory.size(); i++) {
System.out.println((i + 1) + ". " + commandHistory.get(i));
}
}
public void addCommand(String cmd) {
commandHistory.add(cmd);
}
}

81
w11/Main11.java

@ -0,0 +1,81 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Logger;
public class Main11 {
private static final Logger logger = Logger.getLogger(Main11.class.getName());
private static final int MAX_RETRY_TIMES = 3;
public static void main(String[] args) {
StrategyFactory11 strategyFactory = new StrategyFactory11();
CommandRegistry11 cmdRegistry = new CommandRegistry11();
HistoryCommand11 historyCmd = new HistoryCommand11();
ArticleRepository11 repository = new ArticleRepository11();
// 模拟爬取策略 + 失败重试逻辑
CrawlStrategy11 blogStrategy = new CrawlStrategy11() {
@Override
public boolean supports(String url) {
return url != null && url.contains("blog");
}
@Override
public Article11 crawl(String url) throws ParseException11, NetworkException11 {
for (int i = 1; i <= MAX_RETRY_TIMES; i++) {
try {
double random = Math.random();
if (random < 0.3) {
throw new NetworkException11("网络连接超时");
}
if (random < 0.2) {
throw new ParseException11("页面内容解析失败");
}
return new Article11("博客文章", url, "正文内容", "博主", "2026-05-30");
} catch (NetworkException11 e) {
logger.warning("第 " + i + " 次爬取异常:" + e.getMessage());
if (i == MAX_RETRY_TIMES) {
throw new NetworkException11("已重试" + MAX_RETRY_TIMES + "次,任务终止", e);
}
}
}
return null;
}
};
strategyFactory.registerStrategy(blogStrategy);
cmdRegistry.registerCommand(new HelpCommand11());
cmdRegistry.registerCommand(historyCmd);
cmdRegistry.registerCommand(new AnalyzeCommand11(strategyFactory));
cmdRegistry.registerCommand(new ExitCommand11());
List<Article11> articleData = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
logger.info("W11 爬虫程序启动成功");
System.out.println("===== W11 爬虫程序启动 =====");
while (true) {
System.out.print("请输入命令:");
String input = scanner.nextLine().trim();
historyCmd.addCommand(input);
logger.info("用户输入命令:" + input);
String[] splitArr = input.split(" ", 2);
String cmdName = splitArr[0];
Command11 command = cmdRegistry.getCommand(cmdName);
if (command != null) {
String[] params = splitArr.length > 1 ? new String[]{splitArr[1]} : new String[0];
try {
command.execute(params, articleData);
} catch (Exception e) {
logger.severe("命令执行发生异常:" + e.getMessage());
System.out.println("命令执行出错,请查看日志!");
}
} else {
logger.warning("未知命令:" + cmdName);
System.out.println("未知命令,请输入 help 查看帮助");
}
}
}
}

6
w11/NetworkException11.java

@ -0,0 +1,6 @@
public class NetworkException11 extends CrawlerException11 {
public NetworkException11() { super(); }
public NetworkException11(String message) { super(message); }
public NetworkException11(String message, Throwable cause) { super(message, cause); }
public NetworkException11(Throwable cause) { super(cause); }
}

6
w11/ParseException11.java

@ -0,0 +1,6 @@
public class ParseException11 extends CrawlerException11 {
public ParseException11() { super(); }
public ParseException11(String message) { super(message); }
public ParseException11(String message, Throwable cause) { super(message, cause); }
public ParseException11(Throwable cause) { super(cause); }
}

19
w11/StrategyFactory11.java

@ -0,0 +1,19 @@
import java.util.ArrayList;
import java.util.List;
public class StrategyFactory11 {
private final List<CrawlStrategy11> strategyList = new ArrayList<>();
public void registerStrategy(CrawlStrategy11 strategy) {
strategyList.add(strategy);
}
public CrawlStrategy11 getMatchStrategy(String url) {
for (CrawlStrategy11 s : strategyList) {
if (s.supports(url)) {
return s;
}
}
return null;
}
}
Loading…
Cancel
Save