okhttp 防止自动删除url中的./和../

本文介绍了如何利用特定方法测试任意文件读取漏洞。通过修改okhttp的源码,阻止其自动删除URL中的 ../ 字符串,从而实现对任意文件的读取。文章详细说明了如何修改HttpUrl.Builder类的push方法。

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

测试任意文件读取漏洞是需要在url中加上 ../../ 之类的字符,但是如果使用三方库Apache httpclient或okhttp,他们都会自动删除url中的  ../ ,通过修改okhttp的源码可以防止此删除,具体修改如下

修改  HttpUrl.Builder 类的 push方法,注释如下代码即可。

 

//注释掉  防止自动删除  ./  ../
// if (isDot(segment)) {
// return; // Skip '.' path segments.
// }
// if (isDotDot(segment)) {
// pop();
// return;
// }

 

转载于:https://www.cnblogs.com/SEC-fsq/p/6549374.html

src/main/java └── com.example.teacherassistant ├── config │ ├── AiConfig.java │ ├── SecurityConfig.java │ ├── WebConfig.java + │ ├── MilvusConfig.java // 向量数据库配置 + │ └── AsyncConfig.java // 异步处理配置 ├── controller │ ├── AiController.java │ ├── ContentController.java │ ├── CourseController.java │ ├── ExerciseController.java │ ├── AnalysisController.java + │ └── KnowledgeController.java // 知识库管理接口 ├── service │ ├── impl │ │ ├── AiServiceImpl.java │ │ ├── ContentServiceImpl.java │ │ ├── AnalysisServiceImpl.java + │ │ ├── KnowledgeServiceImpl.java // 知识库处理服务 + │ │ └── AssessmentServiceImpl.java // 考核生成服务 │ ├── AiService.java │ ├── ContentService.java │ ├── AnalysisService.java + │ ├── KnowledgeService.java // 知识库服务接口 + │ └── AssessmentService.java // 考核服务接口 ├── repository │ ├── CoursewareRepository.java │ ├── ExerciseRepository.java │ ├── UserRepository.java + │ ├── KnowledgeRepo.java // 知识库文档存储 + │ └── AnswerRepo.java // 学生答题存储 ├── model │ ├── entity │ │ ├── Courseware.java │ │ ├── Exercise.java │ │ ├── User.java + │ │ ├── KnowledgeDoc.java // 知识库文档实体 + │ │ ├── StudentAnswer.java // 学生答题实体 + │ │ └── KnowledgePoint.java // 知识点实体 │ ├── dto │ │ ├── AiRequest.java │ │ ├── AnalysisResult.java + │ │ ├── TeachingPlanDto.java // 教学计划DTO + │ │ └── ExerciseGenReq.java // 习题生成请求DTO │ └── enums │ └── SubjectType.java ├── util │ ├── AiPromptBuilder.java │ ├── FileUtils.java │ ├── KnowledgeExtractor.java + │ ├── VectorUtils.java // 向量计算工具 + │ ├── DocumentParser.java // 文档解析工具 + │ └── QwenClient.java // 通义API客户端 + ├── task + │ └── KnowledgeIndexTask.java // 知识库索引异步任务 └── TeacherAssistantApplication.java 请跟据我的项目结构,给出util中的代码文件
最新发布
07-11
2025-06-09 22:12:42.286 31140-31140 getEndpoint com.example.kucun2 D getEndpoint: url_add_Dingdan 2025-06-09 22:12:42.290 31140-31140 System.err com.example.kucun2 W R绫绘湭鎵惧埌: com.example.kucun2.R$String 2025-06-09 22:12:42.324 31140-31140 getEndpoint com.example.kucun2 D endpoint: nullpackage com.example.kucun2.entity.data; import android.util.Log; import com.example.kucun2.function.MyAppFnction; public abstract class SynchronizableEntity implements EntityClassGrassrootsid { /** * 添加url * @param type 操作增删改查 * @return 返回相对url */ public String getEndpoint(String type){ //从String.xml获取url Log.d("getEndpoint", "getEndpoint: "+"url_"+type+"_"+this.getClass().getSimpleName()); return MyAppFnction.getStringResource("String","url_"+type+"_"+this.getClass().getSimpleName()); } } package com.example.kucun2.entity.data; import android.util.Log; import androidx.annotation.NonNull; import com.google.gson.Gson; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Objects; import java.util.Set; import okhttp3.Call; import okhttp3.Callback; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; /** 支持数据变更自动同步的泛型集合类 @param <T> 继承自 SynchronizableEntity 的实体类型 */ public class SynchronizedList<T extends EntityClassGrassrootsid> implements List<T> { private final List<T> list = new ArrayList<>(); private final OkHttpClient client = new OkHttpClient(); private static final Gson gson = new Gson(); private static final MediaType JSON = MediaType.get(“application/json; charset=utf-8”); private final Class<T> entityClass; // 类型标记 // 添加批量操作模式标志 private boolean batchMode = false; // 属性变更监听器 private final List<PropertyChangeListener<T>> listeners = new ArrayList<>(); // 直接接受Class参数的构造函数 public SynchronizedList(Class<T> entityClass) { this.entityClass = entityClass; } // 安全的类型转换方法 private T safeCast(Object o) { if (o != null && entityClass.isInstance(o)) { return entityClass.cast(o); } return null; } public interface PropertyChangeListener<T> { void onPropertyChange(T entity, String propertyName, Object oldValue, Object newValue); } public void addPropertyChangeListener(PropertyChangeListener<T> listener) { listeners.add(listener); } public void removePropertyChangeListener(PropertyChangeListener<T> listener) { listeners.remove(listener); } // 添加方法来获取原始对象 @SuppressWarnings(“unchecked”) public T getOriginal(T proxy) { if (proxy == null) return null; // 检查是否为代理对象 if (java.lang.reflect.Proxy.isProxyClass(proxy.getClass())) { try { java.lang.reflect.InvocationHandler handler = java.lang.reflect.Proxy.getInvocationHandler(proxy); if (handler instanceof IProxyHandler) { Object original = ((IProxyHandler) handler).getOriginal(); // 安全类型检查 if (entityClass.isInstance(original)) { return (T) original; } } } catch (Exception e) { Log.e("SynchronizedList", "Failed to get proxy handler", e); } } return proxy; } /** 同步实体到后端 @param entity 要同步的实体 */ private void syncEntity(T entity) { if (batchMode) return; String operation = “add”; T originalEntity = getOriginal(entity); String endpoint = originalEntity.getEndpoint(operation); String json = gson.toJson(originalEntity); Log.d(“getEndpoint”, "endpoint: "+endpoint); RequestBody body = RequestBody.create(json, JSON); Request request = new Request.Builder() .url(endpoint) .method(getHttpMethod(operation), body) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.e(“SynchronizedList”, "同步失败: " + entity.getClass().getSimpleName(), e); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) { if (!response.isSuccessful()) { Log.e("SynchronizedList", "同步失败: " + response.code() + " - " + response.message()); } response.close(); } }); } // 添加用于批量操作的方法 public void beginBatch() { this.batchMode = true; } public void endBatch() { this.batchMode = false; // 批量结束后触发一次全量同步 syncAllEntities(); } private void syncAllEntities() { for (T entity : list) { syncEntity(entity); } } private String getHttpMethod(String operation) { switch (operation) { case “add”: return “POST”; case “update”: return “PUT”; case “delete”: return “DELETE”; default: return “POST”; } } // 获取类实现的所有接口(包括父类接口) private Class<?>[] getInterfaces(Class<?> clazz) { Set<Class<?>> interfaces = new HashSet<>(); while (clazz != null) { interfaces.addAll(Arrays.asList(clazz.getInterfaces())); clazz = clazz.getSuperclass(); } return interfaces.toArray(new Class<?>[0]); } /** 创建代理对象,用于监听属性变更 */ // 优化 createProxy 方法 private T createProxy(T original) { if (original == null) return null; // 获取实体类实现的所有接口 Set<Class<?>> interfaces = new HashSet<>(); Class<?> clazz = original.getClass(); // 收集所有接口,包括继承链中的接口 while (clazz != null) { interfaces.addAll(Arrays.asList(clazz.getInterfaces())); clazz = clazz.getSuperclass(); } // 创建代理对象 return (T) Proxy.newProxyInstance( original.getClass().getClassLoader(), interfaces.toArray(new Class<?>[0]), new EntityProxyHandler(original) ); // if (!entityClass.isInstance(original)) { // throw new IllegalArgumentException(“Invalid entity type”); // } // // 这里使用动态代理模式监听setter方法调用 // return (T) java.lang.reflect.Proxy.newProxyInstance( // original.getClass().getClassLoader(), // original.getClass().getInterfaces(), // (proxy, method, args) -> { // // 只拦截setter方法 // if (method.getName().startsWith(“set”) && args.length == 1) { // String propertyName = method.getName().substring(3); // propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); // // // 获取旧值 // Object oldValue = original.getClass() // .getMethod(“get” + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1)) // .invoke(original); // // // 调用原始方法 // Object result = method.invoke(original, args); // // // 触发监听器 // for (PropertyChangeListener<T> listener : listeners) { // listener.onPropertyChange(original, propertyName, oldValue, args[0]); // } // // // 自动同步到后端 // syncEntity(original); // return result; // } // return method.invoke(original, args); // } // ); } // 以下是List接口的实现 @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public boolean contains(Object o) { return list.contains(o); } @NonNull @Override public Iterator<T> iterator() { return list.iterator(); } @NonNull @Override public Object[] toArray() { return list.toArray(); } @NonNull @Override public <T1> T1[] toArray(@NonNull T1[] a) { return list.toArray(a); } @Override public boolean add(T t) { T proxy = createProxy(t); boolean result = list.add(proxy); if (!batchMode) { syncEntity(proxy); } return result; // 添加时创建代理 } @Override public boolean remove(Object o) { T entity = safeCast(o); if (entity != null) { syncEntity((T) entity); // 删除前同步 } return list.remove(o); } @Override public boolean containsAll(@NonNull Collection<?> c) { return list.containsAll(c); } @Override public boolean addAll(@NonNull Collection<? extends T> c) { boolean modified = false; for (T t : c) { modified |= add(t); } return modified; } @Override public boolean addAll(int index, @NonNull Collection<? extends T> c) { for (T t : c) { add(index++, t); } return true; } @Override public boolean removeAll(@NonNull Collection<?> c) { for (Object o : c) { T entity = safeCast(o); if (entity != null) { syncEntity(entity); } } return list.removeAll(c); } @Override public boolean retainAll(@NonNull Collection<?> c) { List<T> toRemove = new ArrayList<>(); for (T t : list) { if (!c.contains(t)) { toRemove.add(t); } } // 使用安全转换 for (T entity : toRemove) { syncEntity(entity); } return list.retainAll(c); } @Override public void clear() { for (T t : list) { syncEntity(t); // 清空前同步 } list.clear(); } @Override public T get(int index) { return list.get(index); } @Override public T set(int index, T element) { T old = list.set(index, createProxy(element)); if (old != null) { syncEntity(old); // 替换旧元素前同步 } return old; } @Override public void add(int index, T element) { list.add(index, createProxy(element)); } @Override public T remove(int index) { T removed = list.remove(index); if (removed != null) { syncEntity(removed); // 删除前同步 } return removed; } @Override public int indexOf(Object o) { return list.indexOf(o); } @Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); } @NonNull @Override public ListIterator<T> listIterator() { return list.listIterator(); } @NonNull @Override public ListIterator<T> listIterator(int index) { return list.listIterator(index); } @NonNull @Override public List<T> subList(int fromIndex, int toIndex) { return list.subList(fromIndex, toIndex); } // 触发属性变更通知 // 添加类型安全的属性监听 private void firePropertyChange(T entity, String propertyName, Object oldValue, Object newValue) { if (oldValue != null && newValue != null && oldValue.equals(newValue)) { return; // 值未变化时不触发监听 } for (PropertyChangeListener<T> listener : listeners) { try { listener.onPropertyChange(entity, propertyName, oldValue, newValue); } catch (Exception e) { Log.e("SynchronizedList", "Listener error", e); } } } // 修改代理处理器以支持获取原始对象 /* 完整的 EntityProxyHandler 实现 */ private class EntityProxyHandler implements IProxyHandler, java.lang.reflect.InvocationHandler { private final T original; private final Map<String, Object> propertyValues = new HashMap<>(); public EntityProxyHandler(T original) { this.original = original; cachePropertyValues(); } private void cachePropertyValues() { // 获取类信息 Class<?> clazz = original.getClass(); // 遍历所有getter方法 for (Method method : clazz.getMethods()) { String methodName = method.getName(); // 只处理getter方法 if (methodName.startsWith("get") && !methodName.equals("getClass") && method.getParameterTypes().length == 0) { try { // 获取属性名(去掉"get"并将首字母小写) String propertyName = methodName.substring(3); propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1); // 调用getter获取值 Object value = method.invoke(original); propertyValues.put(propertyName, value); } catch (Exception e) { Log.e("Wrapper", "Failed to cache property " + methodName, e); } } } } @Override public T getOriginal() { return original; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); // 只拦截setter方法 if (methodName.startsWith("set") && args != null && args.length == 1) { String propertyName = methodName.substring(3); propertyName = Character.toLowerCase(propertyName.charAt(0)) + propertyName.substring(1); Object oldValue = propertyValues.get(propertyName); Object newValue = args[0]; // 如果值未改变,不触发同步 if (Objects.equals(oldValue, newValue)) { return null; } // 调用原始对象的setter方法 Method setter = original.getClass().getMethod(methodName, newValue.getClass()); setter.invoke(original, newValue); // 更新属性缓存 propertyValues.put(propertyName, newValue); // 触发属性变更监听 firePropertyChange(original, propertyName, oldValue, newValue); // 非批量模式下自动同步 if (!batchMode) { syncEntity(original); } } // 其他接口方法直接调用原始对象 return method.invoke(original, args); } private Object getPropertyValue(String propertyName) { String getterName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); try { Method getter = original.getClass().getMethod(getterName); return getter.invoke(original); } catch (Exception e) { Log.e("ProxyHandler", "Failed to get property value: " + propertyName, e); return null; } } } // 在 SynchronizedList 类中添加 private interface IProxyHandler { Object getOriginal(); } }package com.example.kucun2.entity.data; import android.content.Context; import android.util.Log; import androidx.annotation.NonNull; import com.example.kucun2.entity.; import com.example.kucun2.entity.data.SynchronizableEntity; import com.example.kucun2.entity.data.SynchronizedList; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import okhttp3.; import org.json.JSONObject; import java.io.IOException; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; public class AppDataManager { private final Context context; private final OkHttpClient httpClient; private final Gson gson; private Map<String, SynchronizedList<? extends SynchronizableEntity>> dataCache; private static final String BASE_URL = “https://tian.sef/Kucun2”; private static final String API_ALL = “/app/all”; public AppDataManager(Context context) { this.context = context; this.gson = new Gson(); this.dataCache = new HashMap<>(); this.httpClient = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build(); } /** * 从服务器加载完整数据集 */ public void loadFullDataset(DataCallback callback) { Request request = new Request.Builder() .url(BASE_URL + API_ALL) .build(); httpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.e("AppDataManager", "Failed to load full dataset", e); callback.onFailure("Network error: " + e.getMessage()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (!response.isSuccessful()) { callback.onFailure("HTTP error: " + response.code()); return; } try { String jsonData = response.body().string(); JSONObject jsonObject = new JSONObject(jsonData); JSONObject data = jsonObject.getJSONObject("data"); // 解析各实体列表 parseEntityList(data, "bancais", Bancai.class); parseEntityList(data, "dingdans", Dingdan.class); parseEntityList(data, "mupis", Mupi.class); parseEntityList(data, "chanpins", Chanpin.class); parseEntityList(data, "kucuns", Kucun.class); parseEntityList(data, "chanpin_zujians", Chanpin_Zujian.class); parseEntityList(data, "zujians", Zujian.class); parseEntityList(data, "caizhis", Caizhi.class); parseEntityList(data, "users", User.class); callback.onSuccess(); } catch (Exception e) { Log.e("AppDataManager", "Error parsing response", e); callback.onFailure("Parsing error: " + e.getMessage()); } } }); } /** * 解析实体列表 */ private <T extends SynchronizableEntity> void parseEntityList(JSONObject data, String key, Class<T> clazz) { try { Type listType = TypeToken.getParameterized(SynchronizedList.class, clazz).getType(); SynchronizedList<T> list = gson.fromJson(data.getString(key), listType); dataCache.put(key, list); } catch (Exception e) { Log.e("AppDataManager", "Failed to parse " + key, e); } } /** * 添加实体到特定集合 */ public <T extends SynchronizableEntity> void addEntity(T entity, Class<T> clazz, DataCallback callback) { String endpoint = BASE_URL + getAddEndpointForClass(clazz); RequestBody body = RequestBody.create( gson.toJson(entity), MediaType.parse("application/json") ); Request request = new Request.Builder() .url(endpoint) .post(body) .build(); httpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { Log.e("AppDataManager", "Add entity failed", e); callback.onFailure("Network error: " + e.getMessage()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (response.isSuccessful()) { try { T newEntity = gson.fromJson(response.body().string(), clazz); SynchronizedList<T> list = (SynchronizedList<T>) dataCache.get(getCacheKeyForClass(clazz)); if (list != null) { list.add(newEntity); } callback.onSuccess(); } catch (Exception e) { callback.onFailure("Parsing error: " + e.getMessage()); } } else { callback.onFailure("API error: " + response.code()); } } }); } /** * 获取添加操作的API端点 */ private <T> String getAddEndpointForClass(Class<T> clazz) { // 基于简单的命名约定生成端点 String className = clazz.getSimpleName().toLowerCase(); return "/app/" + className + "/add"; } /** * 获取缓存键名 */ private <T> String getCacheKeyForClass(Class<T> clazz) { return clazz.getSimpleName().toLowerCase() + "s"; } /** * 从缓存获取实体列表 */ @SuppressWarnings("unchecked") public <T extends SynchronizableEntity> SynchronizedList<T> getEntityList(Class<T> clazz) { String key = getCacheKeyForClass(clazz); return (SynchronizedList<T>) dataCache.get(key); } /** * 类型安全的实体更新方法 * @param entity 要更新的实体 * @param callback 操作回调 */ @SuppressWarnings("unchecked") public <T extends SynchronizableEntity> void updateEntity(T entity, DataCallback callback) { // 使用实体类的实际类型 Class<T> entityClass = (Class<T>) entity.getClass(); updateEntity(entity, entityClass, callback); } /** * 更新实体 */ public <T extends SynchronizableEntity> void updateEntity(T entity, Class<T> clazz, DataCallback callback) { String endpoint = BASE_URL + getUpdateEndpointForClass(clazz); RequestBody body = RequestBody.create( gson.toJson(entity), MediaType.parse("application/json") ); Request request = new Request.Builder() .url(endpoint) .put(body) .build(); httpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { callback.onFailure("Network error: " + e.getMessage()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (response.isSuccessful()) { callback.onSuccess(); } else { callback.onFailure("API error: " + response.code()); } } }); } /** * 获取更新操作的API端点 */ private <T> String getUpdateEndpointForClass(Class<T> clazz) { // 基于简单命名约定生成端点 String className = clazz.getSimpleName().toLowerCase(); return "/app/" + className + "/update"; } /** * 获取用户认证令牌 */ public void authenticateUser(String username, String password, AuthCallback callback) { JSONObject authJson = new JSONObject(); try { authJson.put("username", username); authJson.put("password", password); } catch (Exception e) { callback.onFailure("Auth parameter error"); return; } RequestBody body = RequestBody.create( authJson.toString(), MediaType.parse("application/json") ); Request request = new Request.Builder() .url(BASE_URL + "/user/login") .post(body) .build(); httpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { callback.onFailure("Network error: " + e.getMessage()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (response.isSuccessful()) { try { JSONObject authResponse = new JSONObject(response.body().string()); String token = authResponse.getString("token"); callback.onSuccess(token); } catch (Exception e) { callback.onFailure("Token parsing error"); } } else { callback.onFailure("Authentication failed"); } } }); } /** * 数据加载回调接口 */ public interface DataCallback { void onSuccess(); void onFailure(String error); } /** * 认证回调接口 */ public interface AuthCallback { void onSuccess(String token); void onFailure(String error); } } E FATAL EXCEPTION: main Process: com.example.kucun2, PID: 31140 java.lang.NullPointerException: Parameter specified as non-null is null: method okhttp3.Request$Builder.url, parameter url at okhttp3.Request$Builder.url(Unknown Source:2) at com.example.kucun2.entity.data.SynchronizedList.syncEntity(SynchronizedList.java:114) at com.example.kucun2.entity.data.SynchronizedList.add(SynchronizedList.java:272) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.createAndSaveDingdan(AddInventoryFragment.java:445) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.lambda$showNewDingdanDialog$8(AddInventoryFragment.java:423) at com.example.kucun2.ui.jinhuo.AddInventoryFragment.$r8$lambda$viLBw5kNmkDSVG17JoXzuH5G85E(Unknown Source:0) at com.example.kucun2.ui.jinhuo.AddInventoryFragment$$ExternalSyntheticLambda20.onClick(D8$$SyntheticClass:0) at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:250) at android.os.Handler.dispatchMessage(Handler.java:109) at android.os.Looper.loopOnce(Looper.java:250) at android.os.Looper.loop(Looper.java:340)
06-10
package com.example.kucun2.function; import android.app.Application; import android.content.Context; import androidx.annotation.StringRes; import java.lang.reflect.Field; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.X509TrustManager; import okhttp3.OkHttpClient; public class MyAppFnction extends Application { private static MyAppFnction instance; public static OkHttpClient getClient() { return client; } private static OkHttpClient client; @Override public void onCreate() { super.onCreate(); instance = this; createSecureClient(this.getApplicationContext()); } public static String getStringResource(@StringRes int resId) { return instance.getString(resId); } public static String getStringResource(@StringRes int resId, Object... args) { return instance.getString(resId, args); } public static String getStringResource(String resourceType, String resourceName) { try { // 1. 构造完整的资源路径 String className = instance.getPackageName() + ".R$" + resourceType; // 2. 反射获取资源ID Class<?> resClass = Class.forName(className); Field field = resClass.getField(resourceName); int resId = field.getInt(null); // 静态字段获取资源ID // 3. 获取实际字符串资源 return instance.getResources().getString(resId); } catch (Exception e) { handleError(e); return null; // 或返回默认值 } } private static void handleError(Exception e) { // 异常处理逻辑 if (e instanceof ClassNotFoundException) { System.err.println("R类未找到: " + e.getMessage()); } else if (e instanceof NoSuchFieldException) { System.err.println("资源字段不存在: " + e.getMessage()); } else { e.printStackTrace(); } } public static void createSecureClient(Context context) { // 创建安全的SSL上下文 SSLContext sslContext = TLSUtils.createSSLContext(context, "selfsigned.crt"); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); X509TrustManager trustManager = TLSUtils.createTrustManager(context, "selfsigned.crt"); client = new OkHttpClient.Builder() .sslSocketFactory(socketFactory, trustManager) .hostnameVerifier((hostname, session) -> { // 开发环境直接返回true,生产环境应验证域名 return true; }) .build(); } } package com.example.kucun2.dataProcessing; import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.Log; import com.example.kucun2.entity.data.GsonFactory; import com.example.kucun2.entity.data.SynchronizableEntity; import com.example.kucun2.entity.data.SynchronizedList; import com.example.kucun2.function.MyAppFnction; import com.google.gson.Gson; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; /** * 数据加载处理器 * 职责: * - 从服务器加载全量/增量数据 * - 处理JSON解析数据转换 * - 更新数据存储并建立关联 * - 提供加载状态回调 */ public class DataLoader { private static final String TAG = "DataLoader"; private final DataCore dataCore; private final DataAssociator associator; private final Gson gson = GsonFactory.createGson(); // 加载状态跟踪 private boolean isLoading = false; public DataLoader(DataCore dataCore, DataAssociator associator) { this.dataCore = dataCore; this.associator = associator; } /** * 从服务器加载全量数据 * @param context Android上下文 * @param callback 加载结果回调 */ public void loadAllData(Context context, Data.LoadDataCallback callback) { // 主线程检查 if (Looper.myLooper() != Looper.getMainLooper()) { throw new IllegalStateException("必须在主线程调用Data.loadAllData"); } // 防止重复加载 if (isLoading) { callback.onFailure(); return; } isLoading = true; dataCore.ensurePreservedObjects(); // 获取OkHttp客户端 OkHttpClient client = MyAppFnction.getClient(); // 构建请求 Request request = new Request.Builder() .url(MyAppFnction.getApiUrl("api/data/all")) .addHeader("Authorization", "Bearer " + Data.getUser().getToken()) .build(); // 异步执行请求 client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { isLoading = false; safeCallback(callback, false); Log.e(TAG, "数据加载失败", e); } @Override public void onResponse(Call call, Response response) { try { if (!response.isSuccessful()) { throw new IOException("Unexpected code: " + response); } String jsonData = response.body().string(); parseAndAssignData(jsonData, context, callback); } catch (Exception e) { isLoading = false; safeCallback(callback, false); Log.e(TAG, "数据处理失败", e); } } }); } /** * 加载增量更新数据 * @param lastSyncTimestamp 上次同步时间戳 * @param callback 加载结果回调 */ public void loadDeltaData(long lastSyncTimestamp, Data.LoadDataCallback callback) { // 构建增量请求 Request request = new Request.Builder() .url(MyAppFnction.getApiUrl("api/data/delta?since=" + lastSyncTimestamp)) .addHeader("Authorization", "Bearer " + Data.getUser().getToken()) .build(); // 执行请求(类似loadAllData) } /** * 解析JSON数据并更新到实体列表 */ private void parseAndAssignData( String jsonData, Context context, Data.LoadDataCallback callback ) { try { // 解析JSON数据 Data.AllDataResponse allData = gson.fromJson( jsonData, Data.AllDataResponse.class ); // 更新所有列表 updateAllLists(allData); // 建立实体关联 associator.automaticAssociation(); // 标记所有实体为已修改 Data.setAllEntitiesState(SynchronizableEntity.SyncState.MODIFIED); // 保存到本地存储 DataPersistence.saveToPreferences(context); // 回调成功 isLoading = false; safeCallback(callback, true); } catch (Exception e) { isLoading = false; safeCallback(callback, false); Log.e(TAG, "数据解析失败", e); } } /** * 更新所有实体列表 */ private void updateAllLists(Data.AllDataResponse allData) { updateList(dataCore.bancais, allData.bancais); updateList(dataCore.caizhis, allData.caizhis); updateList(dataCore.mupis, allData.mupis); updateList(dataCore.chanpins, allData.chanpins); updateList(dataCore.chanpin_zujians, allData.chanpin_zujians); updateList(dataCore.dingdans, allData.dingdans); updateList(dataCore.dingdan_chanpins, allData.dingdan_chanpins); updateList(dataCore.Dingdan_chanpin_zujians, allData.Dingdan_chanpin_zujians); updateList(dataCore.kucuns, allData.kucuns); updateList(dataCore.zujians, allData.zujians); updateList(dataCore.users, allData.users); updateList(dataCore.jinhuos, allData.jinhuos); } /** * 更新单个实体列表(合并策略) */ private <T extends SynchronizableEntity> void updateList( SynchronizedList<T> existingList, List<T> newList ) { if (newList == null) return; // 创建ID映射表用于快速查找 Map<Long, T> existingMap = new HashMap<>(); for (T entity : existingList) { existingMap.put(entity.getId(), entity); } // 处理新数据:更新或添加 for (T newEntity : newList) { T existing = existingMap.get(newEntity.getId()); if (existing != null) { // 合并更新 existing.mergeFrom(newEntity); } else { // 添加新实体 existingList.add(newEntity); } } // 处理删除:标记不在新数据中的实体为删除 Set<Long> newIds = newList.stream() .map(SynchronizableEntity::getId) .collect(Collectors.toSet()); Iterator<T> iterator = existingList.iterator(); while (iterator.hasNext()) { T entity = iterator.next(); if (!newIds.contains(entity.getId())) { entity.setState(SynchronizableEntity.SyncState.DELETED); } } } /** * 安全回调到主线程 */ private void safeCallback(Data.LoadDataCallback callback, boolean success) { new Handler(Looper.getMainLooper()).post(() -> { if (callback == null) return; if (success) callback.onSuccess(); else callback.onFailure(); }); } }id是int类型 改进MyAppFnction.getApiUrl等方法
06-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值