Browse Source

上传文件至 'W9'

main
pangyaxuan 1 month ago
parent
commit
2ac3083b2b
  1. 4
      W9/.gitignore
  2. 9
      W9/Command.java
  3. 49
      W9/CrawlCommand.java
  4. 24
      W9/ExitCommand.java
  5. 23
      W9/HelpCommand.java
  6. 27
      W9/History.java
  7. 70
      W9/List共享引用风险分析.md
  8. 25
      W9/Main.java
  9. 17
      W9/README.md
  10. BIN
      W9/W9.zip
  11. BIN
      W9/W9ai协助记录.docx
  12. 51
      W9/pom.xml

4
W9/.gitignore

@ -0,0 +1,4 @@
*.jar
*.jar
*.class
*.log

9
W9/Command.java

@ -0,0 +1,9 @@
package com.example.datacollect.command;
import com.example.datacollect.model.Article;
import java.util.List;
public interface Command {
String getName();
void execute(String[] args, List<Article> articles);
}

49
W9/CrawlCommand.java

@ -0,0 +1,49 @@
package com.example.datacollect.command;
import com.example.datacollect.model.Article;
import com.example.datacollect.util.UrlValidator;
import com.example.datacollect.view.ConsoleView;
import java.util.List;
/**
* 爬取命令 URL 验证
*/
public class CrawlCommand implements Command {
private final ConsoleView view;
public CrawlCommand(ConsoleView view) {
this.view = view;
}
@Override
public String getName() {
return "crawl";
}
/**
* 获取命令别名
*/
public String[] getAliases() {
return new String[]{"c"};
}
@Override
public void execute(String[] args, List<Article> articles) {
if (args.length < 2) {
view.printError("Usage: crawl <url> 或 c <url>");
return;
}
String url = args[1];
// URL 格式验证
if (!UrlValidator.isValid(url)) {
view.printError("URL 格式错误:" + UrlValidator.getValidationError(url));
view.printInfo("示例:crawl https://www.example.com");
return;
}
view.printInfo("正在爬取:" + url);
// TODO: 实现实际爬取逻辑
}
}

24
W9/ExitCommand.java

@ -0,0 +1,24 @@
package com.example.datacollect.command;
import com.example.datacollect.model.Article;
import com.example.datacollect.view.ConsoleView;
import java.util.List;
public class ExitCommand implements Command {
private final ConsoleView view;
public ExitCommand(ConsoleView view) {
this.view = view;
}
@Override
public String getName() {
return "exit";
}
@Override
public void execute(String[] args, List<Article> articles) {
view.printSuccess("Bye!");
System.exit(0);
}
}

23
W9/HelpCommand.java

@ -0,0 +1,23 @@
package com.example.datacollect.command;
import com.example.datacollect.model.Article;
import com.example.datacollect.view.ConsoleView;
import java.util.List;
public class HelpCommand implements Command {
private final ConsoleView view;
public HelpCommand(ConsoleView view) {
this.view = view;
}
@Override
public String getName() {
return "help";
}
@Override
public void execute(String[] args, List<Article> articles) {
view.printInfo("Commands: crawl <url>, list, help, exit");
}
}

27
W9/History.java

@ -0,0 +1,27 @@
package com.example.datacollect.command;
import com.example.datacollect.model.Article;
import com.example.datacollect.view.ConsoleView;
import java.util.List;
/**
* 查看历史命令
*/
public class History implements Command {
private HistoryCommand historyCommand;
public History(HistoryCommand historyCommand) {
this.historyCommand = historyCommand;
}
@Override
public String getName() {
return "history";
}
@Override
public void execute(String[] args, List<Article> articles) {
ConsoleView view = new ConsoleView();
historyCommand.showHistory(view, articles);
}
}

70
W9/List共享引用风险分析.md

@ -0,0 +1,70 @@
# List<Article> 共享引用的风险分析
## 问题描述
在 Main.java 中,`List<Article> articles` 被传递给多个对象(CrawlerController、Command 等),这存在共享引用风险。
## 主要风险
### 1. 数据不一致风险
多个对象持有同一个 List 的引用,任何地方对 List 的修改都会影响其他地方。例如:
- CrawlCommand 添加了新 Article
- ListCommand 在遍历
- 如果同时修改,可能导致 ConcurrentModificationException
### 2. 封装性破坏
List 在多个类之间共享,违反了封装原则:
- 任何持有引用的类都可以随意修改 List
- 无法追踪是谁、在什么时候修改了数据
- 难以进行数据验证和完整性检查
### 3. 线程安全问题
如果未来引入多线程:
- 多个线程同时访问同一个 List
- 没有同步机制会导致数据损坏
- 可能出现脏读、丢失更新等问题
### 4. 测试困难
- 单元测试时难以隔离
- 一个测试可能影响另一个测试的结果
- 需要手动清理共享状态
## 解决方案
### 方案 1:使用不可变集合
```java
// 返回不可变列表
public List<Article> getArticles() {
return Collections.unmodifiableList(articles);
}
```
### 方案 2:防御性拷贝
```java
// 创建副本
public List<Article> getArticlesCopy() {
return new ArrayList<>(articles);
}
```
### 方案 3:使用 Repository 模式
```java
// 通过 Repository 管理,不直接暴露 List
public class ArticleRepository {
private List<Article> articles = new ArrayList<>();
public void add(Article article) { }
public List<Article> findAll() {
return new ArrayList<>(articles); // 返回副本
}
}
```
## 总结
共享引用虽然方便,但会带来数据一致性、封装性、线程安全等问题。
最佳实践是:
1. 最小化共享
2. 必要时使用防御性拷贝
3. 使用不可变集合
4. 通过接口/Repository 封装访问
(字数:约 450 字)

25
W9/Main.java

@ -0,0 +1,25 @@
package com.example.datacollect;
import com.example.datacollect.command.HistoryCommand;
import com.example.datacollect.controller.CrawlerController;
import com.example.datacollect.model.Article;
import com.example.datacollect.view.ConsoleView;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
ConsoleView view = new ConsoleView();
List<Article> articles = new ArrayList<>();
HistoryCommand historyCommand = new HistoryCommand();
CrawlerController controller = new CrawlerController(view, articles, historyCommand);
view.printSuccess("Welcome to CLI Crawler (w9_1)! Type help for commands.");
while (true) {
String input = view.readLine();
historyCommand.record(input); // 记录用户输入的命令
controller.handle(input);
}
}
}

17
W9/README.md

@ -0,0 +1,17 @@
# DataCollect 教学项目 — 最小可运行版本
这是一个最小可用的 Java CLI 演示工程,目标:打印帮助信息以验证运行环境。
构建:
```bash
mvn -q package
```
运行(示例):
```bash
java -jar target/datacollect-cli-0.1.0-jar-with-dependencies.jar --help
```
项目结构(最小):
- `src/main/java/com/example/datacollect/Main.java` — CLI 入口,打印帮助
- `pom.xml` — Maven 构建配置,生成可执行 jar

BIN
W9/W9.zip

Binary file not shown.

BIN
W9/W9ai协助记录.docx

Binary file not shown.

51
W9/pom.xml

@ -0,0 +1,51 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>datacollect-cli</artifactId>
<version>0.1.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.datacollect.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Loading…
Cancel
Save