WKwebview 白屏问题——(WebApp/HybirdApp)

本文深入探讨了H5应用在iOS设备上使用WKWebView时出现的白屏问题,分析了两种常见白屏现象的原因,并提供了四种解决方案,包括定时刷新、判断webView.title、监听进程终止及检查WKCompositingView的存在,以减少白屏发生的概率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们app从ReactNative转H5app,在开发过程中发现一个顽固性问题。点击H5的tabbar或者页面之间点击跳转会偶现白屏问题。或者app退到后台一段时间唤醒app会出现白屏。

白屏原因:

WKWebView是一个多进程组件,Network Loading以及UI Rendering在其它进程中执行。所以UIWebView上当内存占用太大的时候,App Process会crash;而在WKWebView上当总体的内存占用比较大的时候,WebContent Process会crash,从而出现白屏现象。这种一般是操作中交互点击内存过大可能会突然白屏,然后这种你查看图层还会看到界面UI,但是页面就是白屏。后台放置一段时间唤醒会白屏,这种感觉也是程序在内存中被销毁,打开白屏。查看图层会发现白屏的WebView的中缺少一个WKCompositingView视图(WKWebView的渲染单元,属于渲染进程)。目前白屏现象发现有这两种表象。

我们处理白屏方案:

方案一:后台放置一段时间唤醒会白屏

解决方式:退到后台再唤醒,我们native 超过10分钟会刷新,一是页面数据定时更新需要刷新,二是防止内存杀死白屏。但是仍然存在偶现白屏。

方案二:判断webView.titile

在白屏的时候,有些时候页面 webView.titile 会被置空,所有会在viewWillAppear判断标题为空的重新reload页面。

- (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    self.navigationController.navigationBar.hidden = true;

    if (!self.isFirstLoad && StrIsEmpty(self.wkWebView.title)) {

        [self.wkWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:Active_Path]]];

    }

方案三:内层过大会执行webViewWebContentProcessDidTerminate进程终止方法

有些情况当日在web一直操作时会突然白屏,有的时候是因为内容过大导致程序终止。所以采用如下方法处理

    // 此方法适用iOS9.0以上     iOS8用监听另行处理

- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0){

    NSLog(@"进程被终止");

    [self loadActiveRequestWithUrl:Active_Path];

    

}

    // 防止白屏,单web应用,后面路由切换不会加载

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    if (object == self.wkWebView && [keyPath isEqualToString:@"URL"])

    {

        NSURL *newUrl = [change objectForKey:NSKeyValueChangeNewKey];

        NSURL *oldUrl = [change objectForKey:NSKeyValueChangeOldKey];

        

        if (ObjIsNilOrNull(newUrl) && !ObjIsNilOrNull(oldUrl)) {

            [self loadActiveRequestWithUrl:Active_Path];

        }

    }

}

这三种方案基本解决了我项目里99%的白屏,复现几率很少。但是最近还遇到过2回白屏。最近逛简书发现还有一种方案。

补充方案:待验证

可以遍历WKWebView的subviews,通过是否包含WKCompositingView来判断是否白屏。按照网络方案,清缓存、reload和setNeedsLayout都不能解决白屏,所以只能回收旧webview(webview = nil 后记得清除代理,移除监听,要不然会crash)创建新的 webview, 然后重新request。

// 判断是否白屏

- (BOOL)isBlankView:(UIView*)view { // YES:blank

    ClasswkCompositingView =NSClassFromString(@"WKCompositingView");

    if ([viewisKindOfClass:[wkCompositingView class]]) {

        returnNO;

    }

    for(UIView*subViewinview.subviews) {

        if (![selfisBlankView:subView]) {

            returnNO;

        }

    }

returnYES;

}

补充方案来源简书作者如下:
作者:zhoutq
链接:https://www.jianshu.com/p/de67f5a752b6
 

<think>好的,我需要回答用户关于JSP文件放在webapp目录和webapp/WEB-INF目录的区别及访问权限影响的问题。首先,用户提到参考了之前的引用,我需要结合这些引用中的信息,同时回顾用户之前的问题和我的回答。 首先,用户之前的问题是关于拦截器的代码位置,现在转向JSP文件的存放位置和访问权限。我需要先理解这两个目录在Java EE和Spring MVC中的作用。 根据引用[1],用户提到JSP页面在webapp和WEB-INF目录下的不同处理方式。这里可能需要解释这两个目录的结构和安全性。WEB-INF目录下的内容通常不能被直接访问,需要通过控制器转发,而webapp下的文件可以直接通过URL访问。这可能是核心区别。 引用[2]提到Spring Boot中JSP无法引用静态文件的问题,解决方案涉及资源处理器的配置。这说明WEB-INF下的资源访问可能需要额外的配置,比如通过ResourceHandler来指定路径。这可能影响到JSP中引用CSS或JS的方式,需要绝对路径或正确配置资源映射。 引用[3]中的警告信息显示,直接访问WEB-INF下的资源会导致警告,说明Spring MVC默认不允许直接访问这些路径。这进一步支持WEB-INF目录的保护性,必须通过控制器才能访问其中的JSP。 引用[4]提到WEB-INF下的CSS无法访问,需要配置HttpModule来排除静态文件处理。这可能涉及到服务器配置,比如Tomcat或IIS,需要特别处理才能访问这些资源。但通常,最佳实践是不将静态资源放在WEB-INF下,而是放在webapp的公共目录中。 接下来,用户的问题需要明确两个目录的区别,以及访问权限的影响。我需要结构化为几点: 1. **目录结构与默认访问权限**:直接放在webapp下的JSP可以通过URL直接访问,而WEB-INF下的需要控制器转发。 2. **安全性差异**:WEB-INF受保护,防止直接访问,增加安全性。 3. **Spring MVC配置影响**:需要配置视图解析器指向WEB-INF下的JSP,而webapp下的可能不需要。 4. **静态资源引用问题**:放在WEB-INF下的JSP若引用CSS/JS,需正确配置资源处理器,否则路径可能出错。 5. **实际应用场景**:公开页面放webapp,需保护的页面放WEB-INF。 同时,结合之前的回答,用户可能对Spring配置比较熟悉,需要提到如何在Spring MVC中配置视图解析器,以及如何处理静态资源路径的问题。例如,在Spring Boot中,可能需要使用addResourceHandlers来映射WEB-INF下的资源,如引用[2]中的例子。 另外,引用[3]的警告提示直接访问WEB-INF路径会被拦截,所以必须通过控制器跳转,否则出现404或警告。这也需要强调避免直接放置可访问的JSP在WEB-INF下,除非有明确的安全需求。 最后,总结两者的主要区别,并给出建议的使用场景,比如公开和内部页面,同时提醒配置时的注意事项,如资源路径的正确性和视图解析器的设置。可能还需要提到常见的错误,如直接链接到WEB-INF下的JSP导致无法访问,或者静态资源引用失败的问题,以及如何解决这些问题,如使用绝对路径或配置资源处理器。</think>#### 一、核心区别概述 在 Java EE 和 Spring MVC 项目中,`webapp/` 和 `webapp/WEB-INF/` 目录对 JSP 文件的 **访问权限** 和 **安全性** 有本质差异: | **目录** | **直接 URL 访问** | **需控制器转发** | **安全性** | **典型用途** | |-------------------|------------------|------------------|-----------------|-------------------------| | `webapp/` | ✅ 允许 | ❌ 不需要 | 低(公开) | 公开页面(如登录页) | | `webapp/WEB-INF/` | ❌ 禁止 | ✅ 必须 | 高(受保护) | 内部页面(如后台管理页) | --- #### 二、详细对比分析 ##### 1. **直接访问权限** - **`webapp/` 目录** - 可直接通过浏览器 URL 访问,例如: ```text http://localhost:8080/index.jsp # 直接访问 webapp/index.jsp ``` - 适用于无需权限校验的页面(如帮助文档、静态展示页)。 - **`webapp/WEB-INF/` 目录** - **禁止直接访问**:若尝试直接输入路径(如 `http://localhost:8080/WEB-INF/admin.jsp`),会返回 **404 错误** 或触发安全警告[^3]。 - 必须通过 **控制器转发** 访问,例如 Spring MVC 中通过 `@RequestMapping` 跳转: ```java @GetMapping("/admin") public String adminPage() { return "admin"; // 实际映射到 WEB-INF/admin.jsp } ``` ##### 2. **安全性差异** - **`WEB-INF/` 目录的特殊性**: - Java EE 规范规定,`WEB-INF/` 下的内容对客户端隐藏,只能通过服务器内部转发访问[^1]。 - 可防止用户绕过权限控制直接访问敏感页面(如订单详情、用户管理)。 - **`webapp/` 目录的风险**: - 若将敏感页面(如 `user-info.jsp`)直接放在此目录下,可能被恶意用户通过 URL 直接访问,导致数据泄露。 ##### 3. **静态资源引用问题** - **`WEB-INF/` 下的 JSP 引用静态资源(CSS/JS)**: - 若静态资源(如 `style.css`)也放在 `WEB-INF/` 下,需配置 **资源处理器** 明确开放访问权限[^2]: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/WEB-INF/resources/"); } } ``` - JSP 中需使用 **绝对路径** 引用资源: ```jsp <link href="${pageContext.request.contextPath}/resources/style.css" rel="stylesheet"> ``` - **`webapp/` 下的 JSP 引用静态资源**: - 可直接使用相对路径或默认静态资源目录(如 `webapp/static/`),无需额外配置。 --- #### 三、实际应用场景建议 | **场景** | **推荐目录** | **理由** | |-----------------------|-------------------|-------------------------------------------------------------------------| | 登录页、帮助页 | `webapp/` | 允许直接访问,降低权限校验复杂度 | | 后台管理、订单详情页 | `WEB-INF/` | 强制通过控制器转发,可集成权限拦截器[^4] | | 需引用大量静态资源的页面 | `webapp/static/` | 避免因路径嵌套导致资源加载失败(与 `WEB-INF/` 隔离) | --- #### 四、常见问题与解决方案 1. **问题:`WEB-INF/` 下的 JSP 无法加载 CSS/JS** - **原因**:未正确配置资源处理器或路径错误。 - **解决**: - 配置 `ResourceHttpRequestHandler` 开放静态资源路径[^2]。 - 在 JSP 中使用 `<%@ pageContext.request.contextPath %>` 动态生成根路径。 2. **问题:直接访问 `WEB-INF/` 下的 JSP 导致警告** - **日志示例**: ```text WARN ResourceHttpRequestHandler: Path with "WEB-INF": [webapp/WEB-INF/admin.jsp][^3] ``` - **解决**:检查是否错误地通过 URL 直接访问,确保所有请求均通过控制器转发。 3. **问题:`webapp/` 下的敏感页面被直接访问** - **解决**: - 将敏感页面移至 `WEB-INF/`。 - 使用拦截器对 `webapp/` 下的特定路径添加权限校验[^4]。 --- #### 五、总结 - **`webapp/`**:适合公开页面,直接访问便捷,但需注意安全风险。 - **`WEB-INF/`**:强制通过控制器转发,提升安全性,但需配置资源路径和视图解析。 - **关键配置**: ```java // Spring MVC 视图解析器配置示例 @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); // JSP 存放路径 resolver.setSuffix(".jsp"); return resolver; } ``` --- #### 相关问题 1. 如何通过 Spring Security 控制 `webapp/` 目录下页面的访问权限? 2. 在 Spring Boot 中如何正确配置 JSP 和静态资源的路径? 3. 为什么 `WEB-INF/` 下的 JSP 必须通过控制器转发?
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Asia_ZhangQQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值