1. 问题现象与初步诊断
当安卓应用无法连接Tomcat服务器时,通常会在Android Studio的Logcat中看到类似以下的错误信息:
java.net.ConnectException: Failed to connect to /192.168.1.100:8080或者
javax.net.ssl.SSLHandshakeException: Handshake failed首先需要确认的是基础网络连通性。在Android Studio的终端中执行:
adb shell ping 192.168.1.100如果无法ping通,说明存在网络层问题。这种情况常见于:
- 设备与服务器不在同一局域网
- 防火墙拦截了请求
- 使用了错误的IP地址
注意:模拟器访问本地Tomcat需要使用10.0.2.2这个特殊地址,而不是127.0.0.1或localhost
2. Tomcat服务端配置检查
2.1 端口监听验证
在服务器上运行:
netstat -tuln | grep 8080如果没有输出,说明Tomcat未正常启动。检查Tomcat日志:
tail -f /path/to/tomcat/logs/catalina.out2.2 连接器配置
检查server.xml中的Connector配置:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" URIEncoding="UTF-8" useBodyEncodingForURI="true" maxPostSize="2097152" />关键参数说明:
maxPostSize:影响大文件上传connectionTimeout:连接超时时间URIEncoding:解决中文乱码问题
2.3 跨域问题处理
如果前端收到CORS错误,需要在web.xml中添加:
<filter> <filter-name>CorsFilter</filter-name> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> </filter> <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>3. Android客户端网络配置
3.1 网络权限声明
AndroidManifest.xml中必须包含:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />3.2 主线程限制处理
Android不允许在主线程执行网络操作,推荐使用OkHttp:
val client = OkHttpClient() val request = Request.Builder() .url("http://your-server:8080/api") .build() client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { Log.e("NETWORK", "Connection failed", e) } override fun onResponse(call: Call, response: Response) { val body = response.body?.string() Log.d("NETWORK", "Response: $body") } })3.3 HTTPS证书处理
如果使用自签名证书,需要自定义TrustManager:
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager { override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {} override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {} override fun getAcceptedIssuers() = arrayOf<X509Certificate>() }) val sslContext = SSLContext.getInstance("SSL") sslContext.init(null, trustAllCerts, java.security.SecureRandom()) val client = OkHttpClient.Builder() .sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager) .hostnameVerifier { _, _ -> true } .build()4. JSON数据交互问题排查
4.1 数据格式验证
使用Postman测试接口返回的JSON是否有效:
{ "status": 200, "data": { "id": 123, "name": "测试数据" } }4.2 Gson解析配置
在build.gradle中添加依赖:
implementation 'com.google.code.gson:gson:2.8.9'解析示例:
data class ApiResponse( val status: Int, val data: UserData ) data class UserData( val id: Int, val name: String ) val gson = Gson() val response = gson.fromJson(jsonString, ApiResponse::class.java)4.3 日期格式处理
解决Timestamp时区问题:
val gson = GsonBuilder() .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") .create()5. 高级调试技巧
5.1 网络请求日志
在OkHttp中添加日志拦截器:
val logging = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } val client = OkHttpClient.Builder() .addInterceptor(logging) .build()5.2 Wireshark抓包分析
过滤条件示例:
ip.addr == 192.168.1.100 && tcp.port == 80805.3 服务端日志增强
在log4j.properties中添加:
log4j.logger.org.apache.catalina=DEBUG log4j.logger.org.apache.coyote=DEBUG6. 常见问题解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 连接超时 | 网络不可达 | 检查IP和端口是否正确 |
| SSL错误 | 证书不匹配 | 添加证书信任或使用HTTP |
| 400错误 | 请求格式错误 | 检查Content-Type和请求体 |
| 404错误 | 路径不存在 | 验证服务端API路径 |
| 500错误 | 服务端异常 | 查看Tomcat日志 |
| JSON解析失败 | 数据格式不符 | 用在线工具验证JSON有效性 |
7. 性能优化建议
- 连接池配置:
val client = OkHttpClient.Builder() .connectionPool(ConnectionPool(5, 5, TimeUnit.MINUTES)) .build()- 超时设置:
val client = OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build()- 缓存控制:
val cacheSize = 10 * 1024 * 1024 // 10MB val client = OkHttpClient.Builder() .cache(Cache(File(context.cacheDir, "http"), cacheSize.toLong())) .build()在实际项目中,我发现大部分连接问题都源于基础配置错误。建议按照以下顺序排查:
- 验证物理网络连通性(ping测试)
- 检查服务端是否正常监听(telnet测试)
- 确认Android权限配置
- 检查HTTPS证书有效性
- 验证API路径和参数
对于复杂的生产环境,可以考虑使用Charles或Fiddler进行中间人抓包分析,这能直观展示请求/响应的完整过程。