Java初学者项目实战:开发一个简单的新闻聚合系统

可行:用HttpURLConnection+DocumentBuilder可实现简易新闻聚合,需设User-Agent、启用重定向、校验响应码、强制UTF-8解析、先取channel再查item、用ZonedDateTime安全解析pubDate。

用 Java 标准库就能跑起来的新闻聚合系统,完全可行——不需要 Spring、不用 Maven、不配 Tomcat,HttpURLConnection + DocumentBuilder 就能抓 RSS、解析标题链接、打印到控制台。关键不是“多完整”,而是“哪几行代码真正卡住新手”。

怎么用 HttpURLConnection 安全取 RSS 内容?

RSS 是 XML,但很多源(比如 BBC、Reuters 的公开 feed)默认返回 301 重定向或要求 User-Agent,直接 openConnection 会抛 IOException: Server returned HTTP response code: 403

  • 必须手动设置 conn.setRequestProperty("User-Agent", "JavaNewsAggregator/1.0")
  • 要启用自动重定向:conn.setInstanceFollowRedirects(true)
  • 别漏掉 conn.connect() 前的 conn.setReadTimeout(5000),否则 DNS 卡住就干等
  • 响应码非 200 时,别硬读 getInputStream(),先检查 conn.ge

    tResponseCode()

为什么 DocumentBuilder.parse() 总报 org.xml.sax.SAXParseException

不是 XML 写错了,大概率是 RSS 源带了 BOM 或编码声明不一致。例如 feed 返回 UTF-8 但声明为 ,Java 解析器就会乱码后报错。

  • 绕过声明,强制用 UTF-8 解析:把 new StringReader(rssContent) 换成 new InputSource(new ByteArrayInputStream(rssContent.getBytes(StandardCharsets.UTF_8)))
  • 提前 strip BOM:rssContent = rssContent.replace("\uFEFF", "")
  • 别依赖 getElementsByTagName("item") 返回顺序——RSS 2.0 规范不保证 item 一定在 channel 下,有些 feed 直接平级放,得先 getElementsByTagName("channel").item(0) 再查子节点

NewsItem 类要不要加 pubDate 字段?

要,但别直接存字符串。几乎所有主流 RSS feed 的 pubDate 是 RFC 822 格式(如 Wed, 01 Jan 2025 12:00:00 GMT),用 SimpleDateFormat 解析极易抛 ParseException——因为时区缩写(GMT/UTC/EST)和线程不安全。

  • 推荐用 java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME(Java 8+)
  • 字段类型定义为 ZonedDateTime,不是 StringDate
  • 解析失败时 fallback 到 Instant.now(),避免整个条目丢弃
public static ZonedDateTime parsePubDate(String dateStr) {
    try {
        return ZonedDateTime.parse(dateStr, DateTimeFormatter.RFC_1123_DATE_TIME);
    } catch (DateTimeParseException e) {
        return Instant.now().atZone(ZoneOffset.UTC);
    }
}

真正卡住初学者的,从来不是“怎么写完”,而是“为什么一换 feed 地址就崩”——每个 RSS 源都是独立小宇宙,有的没 description,有的 link 是相对路径,有的 title 里藏 HTML 实体。先写死一个已知稳定的测试源(比如 https://rss.cnn.com/rss/edition.rss),跑通再换,比对着报错堆栈猜强十倍。