URLConnection.getLastModified()方法仅返回服务器提供的资源最后修改时间戳,其本身无法直接判断资源是否更新。该时间戳可能不准确或缺失,因此单独使用并不可靠。更健壮的方法是配合If-Modified-Since发起条件请求,依据服务器返回的304或200状态码进行判断。结合ETag校验可进一步提升准确性。使用时需注意正确调用时机、缓
URLConnection.getLastModified判断资源更新方法
时间:2026-05-10
浏览:82
文章目录
在开发过程中,我们经常需要判断远程资源(例如图片或API接口)的内容是否已更新,以避免重复下载并节省流量。一个很自然的想法是:能否通过文件的上次修改时间来判断呢?Java的URLConnection.getLastModified()方法似乎就是为此而设计的。但实际情况真的如此简单吗?

直接给出结论:URLConnection.getLastModified()本身并不能直接“判断”资源是否更新。它的角色更像是一个信使,只负责将服务器在HTTP响应头中提供的Last-Modified时间戳(一个毫秒级的Unix时间)传递给你。至于这个时间戳是否有用、如何使用,完全取决于你的后续操作。
理解 getLastModified 的真实含义与局限
该方法的核心是读取服务器响应头中的Last-Modified字段。它返回一个long型数值,理论上代表该资源在服务器端最后一次被修改的时间(GMT时间戳)。然而,这里有三个关键点需要明确:
- 首先,这个时间戳是服务器“告知”你的,它不一定是文件系统中该资源的真实修改时间。服务器可以自由设置这个值。
- 其次,对于动态页面(例如由PHP、JSP或Node.js实时生成的页面),其
Last-Modified值很可能被设置为“当前响应生成的时间”,而不是背后数据真正发生变更的时间。这就失去了判断更新的意义。 - 最后,如果服务器根本没有返回
Last-Modified这个响应头,那么该方法会返回0。这并不意味着资源没有更新,仅仅表示信息缺失。
因此,单纯获取这个时间戳,然后与本地记录的旧时间戳进行比较,只是一种客户端的猜测,并不完全可靠。
如何实现可靠的服务端校验:配合 If-Modified-Since
更健壮的做法是将判断权交给服务器。这需要利用HTTP协议的条件请求机制。具体流程如下:
- 首次请求:正常获取资源,并记录下
connection.getLastModified()返回的值,我们称之为lastTime。 - 后续请求:在发起新的请求之前,通过
connection.setIfModifiedSince(lastTime)方法,将之前记录的lastTime设置到请求头的If-Modified-Since字段中。 - 解读响应:发起这次带条件的请求后,重点观察HTTP状态码:
如果服务器返回304 Not Modified,则说明内容没有变化,可以直接使用本地缓存。
如果服务器返回200 OK,则说明内容已更新,响应体中包含的就是全新的数据。
这套流程才是getLastModified()方法的正确使用方式,它实现了由服务器端进行权威判断的缓存验证。
提升准确性:建议与 ETag 结合使用
尽管Last-Modified机制很有用,但它也存在弱点。例如,有些服务器的文件时间戳只精确到秒,一秒内的多次修改无法区分;或者服务器配置不当,总是返回当前时间。这时,ETag(实体标签)就是一个更精准的补充方案。
你可以将ETag理解为服务器为资源内容生成的一个唯一“指纹”或哈希值。只要内容有一个字节的改变,这个指纹就会变化。使用方法与Last-Modified类似:
- 首次请求时,通过
response.getHeaderField("ETag")获取ETag值并保存。 - 后续请求时,在请求头中设置
request.setHeader("If-None-Match", savedEtagValue)。 - 在HTTP协议中,
If-None-Match(ETag校验)的优先级通常高于If-Modified-Since(时间校验)。只有当两个条件都满足时,服务器才会返回304。只要有一个条件不满足(例如ETag不匹配),就会返回200和新内容。
将两者结合使用,能最大程度确保缓存验证的准确性。
实际编码中的几个注意点
了解了原理后,在编写代码时还有一些细节需要注意,否则可能会遇到问题:
- 调用时机:必须在调用
getLastModified()之前,先执行connect()方法,或者通过调用getInputStream()等触发实际网络请求的方法。在此之前,响应头信息是无法获取的。 - 缓存干扰:如果启用了连接缓存(
setUseCaches(true)),可能会直接拿到本地缓存的响应,导致获取的Last-Modified时间不是最新的。在调试阶段,可以暂时将其设为false来排除干扰。 - 平台限制:在Android平台上进行开发时,切记网络操作不能在主线程中执行,否则会抛出
NetworkOnMainThreadException异常,务必在子线程或使用异步任务进行处理。
总而言之,URLConnection.getLastModified()是一个有用的工具,但它只是一个起点。要构建可靠的资源更新判断逻辑,关键在于理解并正确运用HTTP的条件请求机制,并考虑结合ETag来应对复杂场景。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。