要使用Java编写网页监控程序,核心思路是通过定时检测目标网页的状态(如可用性、响应时间、内容变化等),并在异常时触发告警,以下是详细的实现步骤,包括技术选型、代码结构、关键功能实现及部署建议。

技术选型与环境准备
-
核心库选择:
- HTTP请求:使用
HttpURLConnection
(JDK内置)或第三方库如Apache HttpClient
、OkHttp
,后者支持异步请求和更丰富的功能。 - 定时任务:
java.util.Timer
(简单场景)或Spring Scheduler
(Spring框架)、Quartz
(复杂调度)。 - JSON/XML解析:
Jackson
、Gson
(JSON),DOM4J
、JAXB
(XML)。 - 日志记录:
SLF4J
+Logback
,便于调试和问题追踪。 - 数据库存储:
MySQL
/PostgreSQL
(关系型)或MongoDB
(非关系型),用于存储监控历史数据。 - 告警通知:邮件(
JavaMail
)、短信(第三方API如阿里云短信)、企业微信/钉钉机器人(HTTP API调用)。
- HTTP请求:使用
-
开发环境:
- JDK 8+(推荐11+ LTS版本)
- Maven/Gradle(依赖管理)
- IDE(IntelliJ IDEA/Eclipse)
程序核心功能实现
HTTP请求模块
通过HTTP GET/POST请求获取网页内容,并校验响应状态码和响应时间,示例代码(使用HttpURLConnection
):
import java.net.HttpURLConnection; import java.net.URL; import java.io.BufferedReader; import java.io.InputStreamReader; import java.time.Duration; import java.time.Instant; public class WebMonitor { public static MonitorResult checkUrl(String urlString) { Instant start = Instant.now(); try { URL url = new URL(urlString); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); // 5秒连接超时 connection.setReadTimeout(10000); // 10秒读取超时 int statusCode = connection.getResponseCode(); Instant end = Instant.now(); long responseTime = Duration.between(start, end).toMillis(); String content = ""; if (statusCode == 200) { try (BufferedReader reader = new BufferedReader( new InputStreamReader(connection.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { content += line; } } } return new MonitorResult(statusCode, responseTime, content); } catch (Exception e) { return new MonitorResult(-1, Duration.between(start, Instant.now()).toMillis(), e.getMessage()); } } } class MonitorResult { private int statusCode; private long responseTime; private String content; // 构造方法、getter略 }
定时任务调度
使用Spring Scheduler
实现定时监控(需添加@EnableScheduling
注解):

import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component public class MonitorScheduler { @Scheduled(fixedRate = 60000) // 每分钟执行一次 public void monitorWebsites() { List<String> urls = List.of("https://www.example.com", "https://test.com"); urls.forEach(url -> { MonitorResult result = WebMonitor.checkUrl(url); if (result.getStatusCode() != 200) { AlertService.sendAlert(url, result); } // 存储结果到数据库 DatabaseService.saveResult(url, result); }); } }
内容变化检测
通过对比网页内容的哈希值或关键字段判断是否变更:
import java.nio.charset.StandardCharsets; import java.security.MessageDigest; public class ContentChangeDetector { public static boolean hasChanged(String oldContent, String newContent) { try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] oldHash = digest.digest(oldContent.getBytes(StandardCharsets.UTF_8)); byte[] newHash = digest.digest(newContent.getBytes(StandardCharsets.UTF_8)); return !MessageDigest.isEqual(oldHash, newHash); } catch (Exception e) { return false; } } }
告警通知模块
以邮件告警为例(使用JavaMail
):
import javax.mail.*; import javax.mail.internet.*; import java.util.Properties; public class AlertService { public static void sendAlert(String url, MonitorResult result) { String to = "admin@example.com"; String subject = "网页监控告警:" + url; String body = String.format("状态码:%d\n响应时间:%dms\n错误:%s", result.getStatusCode(), result.getResponseTime(), result.getContent()); Properties props = new Properties(); props.put("mail.smtp.host", "smtp.example.com"); props.put("mail.smtp.auth", "true"); Session session = Session.getInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("username", "password"); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress("monitor@example.com")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); message.setSubject(subject); message.setText(body); Transport.send(message); } catch (MessagingException e) { e.printStackTrace(); } } }
数据库存储设计
使用MySQL存储监控记录,表结构示例: | 字段名 | 类型 | 说明 | |----------------|--------------|--------------------| | id | BIGINT | 主键,自增 | | url | VARCHAR(255) | 监控的URL | | status_code | INT | HTTP状态码 | | response_time | BIGINT | 响应时间(毫秒) | | check_time | TIMESTAMP | 检测时间 | | error_message | TEXT | 错误信息(如有) |
高级功能扩展
- 多线程监控:使用
ExecutorService
并发检测多个URL,提高效率。 - SSL证书检查:通过
X509TrustManager
验证目标网站的SSL证书有效性。 - 代理支持:在
HttpURLConnection
中设置代理服务器地址,适用于内网环境。 - 可视化报表:集成
ECharts
或JasperReports
生成响应时间趋势图、可用率统计等。
部署与运维
- 打包为可执行JAR:使用Maven Shade Plugin或Spring Boot Maven Plugin生成包含依赖的JAR文件。
- 系统服务化:通过
systemd
(Linux)或NSSM
(Windows)将程序注册为后台服务。 - 日志管理:配置
Logback
按日期分割日志文件,并设置保留天数。 - 监控自身状态:添加程序健康检查接口(如
/health
),通过Prometheus+Grafana监控。
相关问答FAQs
Q1: 如何处理网页需要登录才能访问的情况?
A: 可以通过以下方式解决:

- Session管理:首次请求时获取登录页面的
Set-Cookie
,后续请求携带该Cookie维持会话。 - 表单提交:解析登录页面的表单结构(如
action
、input
字段),使用HttpClient
模拟POST提交登录数据。 - Headless浏览器:对于复杂验证(如JavaScript渲染),集成
Selenium
或Playwright
控制无头浏览器完成登录。
Q2: 如何优化监控程序的资源占用?
A: 从以下方面优化:
- 连接池复用:使用
HttpClient
的PoolingHttpClientConnectionManager
管理HTTP连接,避免频繁创建/销毁连接。 - 异步非阻塞:采用
CompletableFuture
或Spring WebFlux
(基于Netty)实现异步IO,减少线程阻塞。 - 增量检测:仅检测网页内容的关键部分(如特定
<div>
),而非完整HTML,减少数据传输量。 - 缓存策略:对短期内未变化的URL降低检测频率(如从1分钟/次调整为5分钟/次)。