HTTP Status 404 的几种解决办法

本文详细介绍了导致Web应用出现404错误的多种原因,包括目录引用错误、URL输入错误、Web应用未部署、Tomcat服务器配置问题等,并提供了相应的排查与解决方法。
               

1)目录不能被引用。 排错方法:

在 Eclipse的“包资源管理器(Package Explorer)”检查文件存放的位置。由于META-INF

WEB-INF文件夹下的内容无法对外发布,所以,如果你引用了带这两个目录的文件,肯定是不允许。例如: http://localhost:8080/guestbook/WEB-INF/index.html就是错误的

文件位置存放错误

2)URL输入错误。排错方法:

首先,查看URL的IP地址和端口号是否书写正确。

其次,查看上下文路径是否正确 Project--------Properties------MyElipse-----Web-----

Web Context-root检查这个路径名称是否书写正确。

最后,检查一下文件名称是否书写正确。
3)未部署Web应用

4)Tomcat服务器中web.xml中的问题。 排错方法:

      如果你的web应用程序有多个jsp页面的话,当你点击你web应用程序的虚拟根目录时可能会出现404错 误,只是你只需要修改Tomcat服务器中web.xml       

 <init-param>        <param-name>listings</param-name>        <param-value>false(将其该为true)</param-value>  </init-param>

补充说明:在6.0.18 版本error:“ The requested resource () is not available. ”

总是无法访问/myapp/*.jsp文件,可以将 /ROOT 中build.xml 文件copy 一份到myapp,  注意把里面所有的 ROOT 用 myapp 代替. 应该就OK.

5)WEB-INF下面必须要有几个固定的文件夹和文件   

 ±web.xml 该web app的配置文件 ±lib 该web app用到的库文件 ±classes存放编译好的servlet 

 请注意他们的名字,我曾经就由于把classes写成class,查错查了半宿还没解决,所以写这些的时候千万要仔细,要不会浪费更多的精力去查错。

6、如果要运行的不是.jsp文件,而是servlet(.class)文件,要配置web.xml(当然是WEB-INF下面的),加上以下字段: 

 <servlet>      <servlet-name>HelloWorldServlet</servlet-name>      <servlet-class>HelloWorldServlet</servlet-class> </servlet> <servlet-mapping>      <servlet-name>HelloWorldServlet</servlet-name>          <url-pattern>/HelloWorldServlet</url-pattern> </servlet-mapping>

其中的“HelloWorldServlet”改为你要运行的文件名

7)struts.xml配置错误,可能是你的Action值写错或者链接URL写错

下面是我自己的解决办法,很多书都是导入六个文件,我自己的话是多增加了commons-lang3-3.1.jar和javassist-3.11.GA.jar

增加commons-lang3-3.1.jar文件到啊WEB-INF/lib目录下,struts2最新的web开发包如下:

 

下载地址:http://download.csdn.net/detail/ahy1024/4626028

 

持续更ing....

 

           
<think> 我们面对的核心问题是:当后端数据更新后,如何避免从localStorage中读取到过时的旧数据。结合用户提供的引用资料,以下是多种解决方案: ### 解决方案一:版本控制 + 定时刷新(基础方案) 在存储数据时添加版本标识和时间戳,每次加载时进行双重验证: ```javascript // 存储增强数据 const storeData = (key, data, version) => { localStorage.setItem(key, JSON.stringify({ data, version, // 从后端API响应头获取版本号 timestamp: Date.now() })); } // 初始化页面时 async function loadData() { const cacheKey = 'userData'; const cache = JSON.parse(localStorage.getItem(cacheKey)); // 1. 优先展示缓存提升体验 if (cache) render(cache.data); // 2. 发起网络请求获取最新数据 try { const response = await fetch('/api/data'); const freshData = await response.json(); const serverVersion = response.headers.get('X-Data-Version'); // 版本检查(或使用ETag) if (!cache || cache.version !== serverVersion) { render(freshData); // 渲染新数据 storeData(cacheKey, freshData, serverVersion); } } catch (err) { console.error('网络请求失败,使用缓存数据', err); } } ``` **原理**:通过版本号比对检测数据变更[^1]。若版本不匹配则更新缓存。 ### 解决方案二:基于时间的自动失效(TTL) ```javascript // 设置缓存有效期(5分钟) const TTL = 300000; function getWithTTL(key) { const item = localStorage.getItem(key); if (!item) return null; const { data, timestamp } = JSON.parse(item); const isExpired = Date.now() - timestamp > TTL; return isExpired ? null : data; } // 使用示例 const cachedData = getWithTTL('userData') || await fetchFreshData(); ``` 此方案确保缓存不会长期滞留,适合更新频率稳定的数据[^4]。 ### 解决方案三:增量更新(高效同步) 当数据量较大时,可采用增量更新策略: ```javascript // 从后端获取数据变更记录 const changes = await fetch(`/api/changes?since=${lastUpdateTime}`); // 应用变更到本地缓存 changes.forEach(change => { applyChangeToLocalData(change); // 根据操作类型(增删改)更新本地数据 }); // 更新最后同步时间戳 localStorage.setItem('lastUpdate', Date.now()); ``` 适用于列表类数据(如消息流、日志记录),配合WebSocket可实现实时同步。 ### 解决方案四:压缩存储 + 变更检测 当存储空间不足时(引用[2]): ```javascript import LZString from 'lz-string'; // 压缩存储变更标记 function storeChangeFlag(hash) { const compressed = LZString.compress(hash); localStorage.setItem('dataHash', compressed); } // 检查变更 async function checkForUpdates() { const currentHash = LZString.decompress(localStorage.getItem('dataHash')); const serverHash = await fetch('/api/data-hash'); if (currentHash !== serverHash) { // 触发全量数据更新 } } ``` 通过存储数据哈希值(如MD5)检测变更,压缩后仅需几百字节存储空间[^2]。 ### 解决方案五:Service Worker 缓存控制 在Service Worker中拦截请求并实现智能更新: ```javascript // service-worker.js self.addEventListener('fetch', event => { if (event.request.url.includes('/api/data')) { event.respondWith( caches.match(event.request).then(cachedResp => { const fetchPromise = fetch(event.request).then(serverResp => { // 更新localStorage serverResp.clone().json().then(data => { localStorage.setItem('data', JSON.stringify(data)); }); return serverResp; }); return cachedResp || fetchPromise; }) ); } }); ``` 该方案可实现后台静默更新,同时保持离线访问能力。 ### 对比总结 | 方案 | 适用场景 | 优点 | 缺点 | |---------------------|----------------------------|-------------------------------|----------------------| | 版本控制 | 中小型数据 | 实现简单,可靠性高 | 需后端支持版本标识 | | TTL自动失效 | 定期更新数据 | 无需后端配合 | 可能短暂展示旧数据 | | 增量更新 | 大型列表数据 | 传输量小,效率高 | 实现复杂度高 | | 压缩哈希检测 | 存储空间紧张场景 | 节省带宽和存储 | 需计算哈希值 | | Service Worker | PWA应用 | 支持离线,后台更新 | 学习曲线陡峭 | > **特殊场景处理建议**:对于敏感数据(如用户凭证),应避免长期存储在localStorage中,改用sessionStorage[^3]。 §§相关问题§§ 1. 如何实现localStorage数据的跨标签页同步更新? 2. 当使用增量更新策略时,如何处理客户端数据冲突? 3. 如何利用HTTP缓存头(ETag/Last-Modified)优化数据更新流程? </think> ### 解决 localStorage 数据过期的多种方案 #### 方案一:版本控制 + 主动更新(推荐) ```javascript // 存储时添加版本标识 function saveWithVersion(key, data, version) { localStorage.setItem(key, JSON.stringify({ data, version, // 从后端API获取的版本号 timestamp: Date.now() })); } // 读取时校验版本 async function getData(key) { const raw = localStorage.getItem(key); if (!raw) return await fetchFreshData(key); const { data, version, timestamp } = JSON.parse(raw); const freshData = await fetchFreshData(key); // 获取最新数据 // 版本校验 if (freshData.version !== version) { saveWithVersion(key, freshData, freshData.version); return freshData; } return data; } // 后端接口返回数据结构示例 { data: { /* 业务数据 */ }, version: "2024-06-15T08:30:00" // 使用时间戳或hash作为版本标识 } ``` **原理**:通过对比存储版本和API返回版本,确保数据一致性[^1][^4] #### 方案二:基于时间戳的自动刷新 ```javascript // 设置缓存有效期(5分钟) const CACHE_TTL = 300000; function getDataWithTTL(key) { const cached = localStorage.getItem(key); if (!cached) return fetchFreshData(key); const { data, timestamp } = JSON.parse(cached); // 检查缓存有效期 if (Date.now() - timestamp > CACHE_TTL) { return fetchFreshData(key); // 自动获取新数据 } return data; } ``` **优点**:实现简单,适合更新频率固定的数据[^4] #### 方案三:ETag 协商缓存 ```javascript async function getDataWithETag(key) { const cached = localStorage.getItem(key); const cachedETag = localStorage.getItem(`${key}-etag`); // 发起带ETag的请求 const headers = cachedETag ? { 'If-None-Match': cachedETag } : {}; const response = await fetch('/api/data', { headers }); if (response.status === 304) { // 数据未修改 return JSON.parse(cached).data; } // 获取新数据 const data = await response.json(); const etag = response.headers.get('ETag'); // 更新缓存 localStorage.setItem(key, JSON.stringify(data)); localStorage.setItem(`${key}-etag`, etag); return data; } ``` **原理**:利用HTTP缓存机制,减少无效数据传输[^4] #### 方案四:WebSocket 实时同步 ```javascript // 建立WebSocket连接 const ws = new WebSocket('wss://api.example.com/updates'); ws.onmessage = (event) => { const { key, data, version } = JSON.parse(event.data); // 更新本地缓存 const current = JSON.parse(localStorage.getItem(key) || '{}'); if (current.version !== version) { localStorage.setItem(key, JSON.stringify({ data, version })); refreshUI(); // 刷新界面 } }; ``` **适用场景**:需要实时数据同步的系统(如聊天应用、股票行情) #### 方案五:压缩存储 + 定时轮询 ```javascript import LZString from 'lz-string'; // 定时检查更新(每2分钟) setInterval(() => { checkDataUpdates('userData'); }, 120000); async function checkDataUpdates(key) { const compressed = localStorage.getItem(key); if (!compressed) return; // 解压数据获取版本号 const cached = JSON.parse(LZString.decompress(compressed)); const freshData = await fetch('/api/data'); if (freshData.version !== cached.version) { // 更新压缩存储 const newCompressed = LZString.compress(JSON.stringify(freshData)); localStorage.setItem(key, newCompressed); } } ``` **优点**:节省存储空间,适合大型数据集[^2] ### 方案对比 | 方案 | 实时性 | 网络消耗 | 实现复杂度 | 适用场景 | |--------------------|----------|----------|------------|------------------------| | 版本控制 | ★★☆ | ★★★ | ★★☆ | 通用场景 | | 时间戳TTL | ★☆☆ | ★★★ | ★☆☆ | 周期性更新数据 | | ETag协商 | ★★☆ | ★☆☆ | ★★★ | RESTful API | | WebSocket | ★★★ | ★★☆ | ★★★ | 实时系统 | | 压缩存储+轮询 | ★☆☆ | ★★☆ | ★★☆ | 大型数据存储 | > **最佳实践建议**:敏感数据推荐使用 `sessionStorage` 替代,避免隐私数据长期滞留本地[^3]。对于关键业务数据,应组合使用版本控制和时间戳方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值