1.HTTP请求
OkHttp
OkHttpUtils
的全面使用指南,整合多个来源的最佳实践,涵盖依赖配置、基础请求、文件操作、高级功能及注意事项,帮助开发者快速上手并避免常见问题。
一、依赖配置
在项目的 build.gradle
中添加依赖:
Groovy
dependencies {
// 核心库(必选)
implementation 'com.lzy.net:okhttputils:3.0.4'
// 扩展库(按需添加)
implementation 'com.lzy.net:okrx2:2.0.2' // RxJava2 支持
implementation 'com.lzy.net:okserver:2.0.5' // 下载/上传管理
}
二、基本使用
1. GET 请求
Groovy
OkHttpUtils.get("https://api.example.com/data")
.tag(this) // 设置请求标签(用于取消)
.params("page", "1") // 添加URL参数
.headers("Authorization", "token123") // 添加请求头
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
// 请求成功处理
String data = response.body();
}
@Override
public void onError(Response<String> response) {
// 请求失败处理
}
});
2. POST 请求(表单)
Groovy
Map<String, String> params = new HashMap<>();
params.put("username", "admin");
params.put("password", "123456");
OkHttpUtils.post("https://api.example.com/login")
.tag(this)
.params(params) // 添加表单参数
.execute(new JsonCallback<User>(User.class) { // 自动解析为JavaBean
@Override
public void onSuccess(Response<User> response) {
User user = response.body();
}
});
3. POST JSON 数据
Groovy
String json = new Gson().toJson(new User("admin", "123456"));
OkHttpUtils.post("https://api.example.com/login")
.postJson(json) // 直接提交JSON字符串
.execute(new StringCallback());
4. 文件上传
Groovy
File file = new File(Environment.getExternalStorageDirectory(), "test.jpg");
OkHttpUtils.post("https://api.example.com/upload")
.addFile("file", file.getName(), file) // 参数名、文件名、文件对象
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
// 上传成功
}
});
5.文件下载
Groovy
OkHttpUtils.get("https://example.com/file.zip")
.execute(new FileCallback("/sdcard/download/", "file.zip") {
@Override
public void onSuccess(Response<File> response) {
File file = response.body(); // 下载完成
}
@Override
public void downloadProgress(long currentSize, long totalSize, float progress) {
// 进度回调(UI线程)
progressBar.setProgress((int) (100 * progress));
}
});
6.高级功能,全局配置
Groovy
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
OkHttpUtils.init(this);
OkHttpUtils.getInstance()
.setConnectTimeout(30_000) // 连接超时
.setReadTimeout(30_000) // 读取超时
.addCommonHeader("App-Version", BuildConfig.VERSION_NAME) // 公共请求头
.setCertificates(getAssets().open("server.cer")); // HTTPS自签名证书[1](@ref)
}
}
7.高级功能,配置拦截器
Groovy
public class TokenInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.header("token", "user_token")
.build();
return chain.proceed(request);
}
}
// 配置拦截器
OkHttpClient client = OkHttpUtils.getInstance().getOkHttpClient()
.newBuilder()
.addInterceptor(new TokenInterceptor())
.build();
OkHttpUtils.initClient(client);
Retrofit
一、依赖配置
java
dependencies {
// Retrofit 核心库
implementation 'com.squareup.retrofit2:retrofit:2.9.0' // [2,3,4](@ref)
// Gson 转换器(JSON 解析)
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // [1,3,4](@ref)
// OkHttp 底层支持(含日志拦截器)
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0' // [1,8](@ref)
}
二**、基本使用**
1.封装实现(核心类)
java
public class RetrofitClient {
private static final int TIMEOUT = 30; // 超时时间(秒)
private static volatile Retrofit retrofit;
// 构建全局唯一 Retrofit 实例
public static Retrofit getInstance(String baseUrl) {
if (retrofit == null) {
synchronized (RetrofitClient.class) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(initOkHttpClient()) // 配置OkHttp
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
.build();
}
}
}
return retrofit;
}
// 配置OkHttp(含日志拦截器+超时设置)
private static OkHttpClient initOkHttpClient() {
return new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT, TimeUnit.SECONDS)
.build();
}
}
关键特性:
双检锁单例模式确保线程安全
统一超时和日志拦截配置
支持 RxJava 响应式编程
2. API 服务接口定义
java
public interface ApiService {
@GET("users/{id}")
Observable<User> getUserById(@Path("id") int userId); // RxJava Observable
@POST("login")
@FormUrlEncoded
Observable<LoginResponse> login(
@Field("username") String username,
@Field("password") String password
);
}
3. 网络请求基类(封装通用逻辑)
java
public abstract class BaseRepository {
protected ApiService apiService;
public BaseRepository() {
apiService = RetrofitClient.getInstance("https://api.example.com/")
.create(ApiService.class);
}
// 统一错误处理
protected <T> Observable<T> handleRequest(Observable<T> observable) {
return observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.onErrorResumeNext(throwable -> {
// 统一转换网络错误
if (throwable instanceof SocketTimeoutException) {
return Observable.error(new NetworkException("连接超时"));
} else if (throwable instanceof ConnectException) {
return Observable.error(new NetworkException("服务器不可达"));
}
return Observable.error(throwable);
});
}
}
4.调用示例
java
public class UserRepository extends BaseRepository {
// 获取用户信息
public Observable<User> getUser(int userId) {
return handleRequest(apiService.getUserById(userId));
}
// 登录操作
public Observable<LoginResponse> login(String username, String password) {
return handleRequest(apiService.login(username, password));
}
}
5. Activity 中调用
java
public class MainActivity extends AppCompatActivity {
private CompositeDisposable disposables = new CompositeDisposable();
@Override
protected void onCreate(Bundle savedInstanceState) {
UserRepository userRepo = new UserRepository();
// 请求用户数据
disposables.add(userRepo.getUser(123)
.subscribe(user -> {
Log.d("MainActivity", "用户名称: " + user.getName());
}, error -> {
Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show();
}));
// 登录请求
userRepo.login("admin", "123456")
.subscribe(response -> {
if (response.isSuccess()) {
startActivity(new Intent(this, HomeActivity.class));
}
});
}
@Override
protected void onDestroy() {
disposables.clear(); // 防止内存泄漏
super.onDestroy();
}
}
6.文件上传/下载
java
@Multipart
@POST("upload")
Observable<ResponseBody> uploadFile(@Part MultipartBody.Part file);
// 调用示例:
File file = new File("/sdcard/photo.jpg");
RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);
apiService.uploadFile(body);
2.Json解析
Gson
基于Gson封装的工具类及使用示例,支持复杂数据结构(嵌套对象、泛型集合等),并包含详细注释和最佳实践
一、依赖配置
在项目的 build.gradle
中添加依赖:
Groovy
dependencies {
implementation 'com.google.code.gson:gson:2.10.1'
}
二**、**基本使用
1.工具类封装
Groovy
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
/**
* Gson工具类(线程安全)
* 功能:对象与JSON互转、泛型集合处理、格式化输出
*/
public class GsonUtils {
// 单例模式 + 自定义配置(格式化/序列化空值)
private static final Gson GSON = new GsonBuilder()
.setPrettyPrinting() // 格式化JSON(便于阅读)
.serializeNulls() // 序列化null值字段
.create();
/**
* 对象转JSON字符串
* @param object Java对象
* @return JSON字符串
*/
public static String toJson(Object object) {
return GSON.toJson(object);
}
/**
* JSON字符串转对象
* @param json JSON字符串
* @param clazz 目标对象的Class
* @param <T> 目标类型
* @return 解析后的对象
*/
public static <T> T fromJson(String json, Class<T> clazz) {
return GSON.fromJson(json, clazz);
}
/**
* JSON转List(支持泛型)
* @param json JSON字符串
* @param clazz List元素的Class
* @param <T> 元素类型
* @return 解析后的List
*/
public static <T> List<T> fromJsonToList(String json, Class<T> clazz) {
Type type = TypeToken.getParameterized(List.class, clazz).getType();
return GSON.fromJson(json, type);
}
/**
* JSON转Map(支持泛型)
* @param json JSON字符串
* @return 解析后的Map
*/
public static <K, V> Map<K, V> fromJsonToMap(String json) {
Type type = new TypeToken<Map<K, V>>() {}.getType();
return GSON.fromJson(json, type);
}
}
2.使用示例(含复杂数据结构)
Groovy
public class User {
private String name;
private int age;
private Address address; // 嵌套对象
private List<String> hobbies; // List字段
private Map<String, String> metadata; // Map字段
// 必须有无参构造方法(Gson反序列化需要)[2](@ref)
public User() {}
// Getter/Setter方法省略(实际开发中需补充)
}
public class Address {
private String city;
private String zipCode;
public Address() {}
// Getter/Setter省略
}
3. 序列化(对象 → JSON)
java
// 构建复杂对象
Address address = new Address("New York", "10001");
List<String> hobbies = Arrays.asList("Reading", "Traveling");
Map<String, String> metadata = new HashMap<>();
metadata.put("role", "admin");
metadata.put("department", "IT");
User user = new User("John", 25, "john@example.com", address, hobbies, metadata);
// 转换为JSON(格式化输出)
String json = GsonUtils.toJson(user);
System.out.println(json);
4.输出结果
java
{
"name": "John",
"age": 25,
"email": "john@example.com",
"address": {
"city": "New York",
"zipCode": "10001"
},
"hobbies": ["Reading", "Traveling"],
"metadata": {
"role": "admin",
"department": "IT"
}
}
5. 反序列化(JSON → 对象)
java
// JSON字符串转对象
String json = "{\"name\":\"Alice\",\"age\":30,\"address\":{\"city\":\"Paris\"}}";
User user = GsonUtils.fromJson(json, User.class);
System.out.println(user.getAddress().getCity()); // 输出:Paris
// JSON转List(泛型支持)
String listJson = "[{\"name\":\"Bob\"}, {\"name\":\"Charlie\"}]";
List<User> userList = GsonUtils.fromJsonToList(listJson, User.class);
System.out.println(userList.size()); // 输出:2
// JSON转Map
String mapJson = "{\"key1\":\"value1\", \"key2\":\"value2\"}";
Map<String, String> map = GsonUtils.fromJsonToMap(mapJson);
System.out.println(map.get("key2")); // 输出:value2
6.日常使用
java
1.定制工具类
public final class JSONUtils {
//解析jsonobject,以{}开头和结尾
public static <T> T parseJSON(String jsonStr, Class<T> t) {
Gson gson = new Gson();
T bean = gson.fromJson(jsonStr, t);
return bean;
}
/**
* //jsonarry,以[]开头和结尾
* @param response
* @param type
* Type type = new TypeToken< ArrayList<实体类名>>() { }.getType();
// *
* @return
*/
public static <T> T parseJSONArray(String response, Type type) {
Gson gson = new Gson();
T data = gson.fromJson(response, type);
return data;
}
//把map转为String,很少用
public static <T> String mapToJson(Map<String, T> map) {
Gson gson = new Gson();
String jsonStr = gson.toJson(map);
return jsonStr;
}
}
2.Java Bean
public class Man {
/**
* name : 张三
* age : 18
*/
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
2.准备字符串数据
{"error_code":10005,"reason":"应用未审核超时,请提交认证"}
3.解析字符串数据
Man man = JSONUtils.parseJSON(ST, Man.class);
//获得错误码
int error_code = man.getError_code();
//错误原因
String reason = man.getReason();
4.准备数组数据
[
{
"name": "张三",
"age": 18
},
{
"name": "李四",
"age": 19
}
]
5.解析数组数据
Type type = new TypeToken<ArrayList<Man>>() { }.getType();
//获得了一个Man(类名)的集合
ArrayList<Man> first = JSONUtils.parseJSONArray(st, type);
//获得第一个人的年龄
int age = first.get(0).getAge();
Log.e("888", ""+age);
打印下是18岁哦!
注意导包导这个,不然会出错
import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;
Jackson
一、依赖配置
在项目的 build.gradle
中添加依赖:
Groovy
//jackson-databind:核心库(自动包含jackson-core和jackson-annotations)
//jackson-datatype-jsr310:支持LocalDateTime等Java 8日期类型
dependencies {
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2'
}
二**、**基本使用
1.工具类封装
java
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
public class JacksonUtil {
private static final ObjectMapper mapper = new ObjectMapper();
static {
// 基础配置
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略未知字段[6](@ref)
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略null字段[7](@ref)
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // 统一日期格式
// 注册Java 8日期模块
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 禁用时间戳格式[7](@ref)
}
// 对象 → JSON字符串
public static String toJson(Object obj) {
try {
return mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON序列化失败", e);
}
}
// JSON字符串 → 对象
public static <T> T toObject(String json, Class<T> clazz) {
try {
return mapper.readValue(json, clazz);
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON反序列化失败", e);
}
}
// JSON字符串 → 复杂集合(如List<User>)
public static <T> List<T> toList(String json, Class<T> elementClass) {
try {
return mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, elementClass));
} catch (JsonProcessingException e) {
throw new RuntimeException("JSON转List失败", e);
}
}
// JSON字符串 → 嵌套结构(如Map<String, List<Order>>)
public static <T> T toComplexObject(String json, TypeReference<T> typeRef) {
try {
return mapper.readValue(json, typeRef);
} catch (JsonProcessingException e) {
throw new RuntimeException("复杂结构转换失败", e);
}
}
}
2.基础对象转换
java
// 定义实体类
public class User {
private String name;
private Integer age;
private LocalDateTime createTime;
// Getter/Setter省略
}
// 序列化对象 → JSON
User user = new User("张三", 25, LocalDateTime.now());
String json = JacksonUtil.toJson(user);
// 输出: {"name":"张三","age":25,"createTime":"2025-08-03 14:30:00"} [3](@ref)
// 反序列化 JSON → 对象
User parsedUser = JacksonUtil.toObject(json, User.class);
System.out.println(parsedUser.getName()); // 输出: 张三
3.集合处理
java
// List序列化
List<User> userList = Arrays.asList(
new User("李四", 30, null),
new User("王五", 28, LocalDateTime.now())
);
String listJson = JacksonUtil.toJson(userList);
// 输出: [{"name":"李四","age":30},{"name":"王五","age":28,"createTime":"2025-08-03 14:35:00"}]
// List反序列化
List<User> parsedList = JacksonUtil.toList(listJson, User.class);
4. 工具类方法总结

fastjson
一、依赖配置
在项目的 build.gradle
中添加依赖:
Groovy
//jackson-databind:核心库(自动包含jackson-core和jackson-annotations)
//jackson-datatype-jsr310:支持LocalDateTime等Java 8日期类型
dependencies {
implementation 'com.alibaba:fastjson:2.0.39'
}
二**、**基本使用
1.工具类封装
java
import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.filter.Filter;
import java.util.List;
public class FastJsonUtil {
private static final ParserConfig SAFE_PARSER_CONFIG;
static {
// 安全配置:启用安全模式,禁止反序列化任意类 [7](@ref)
SAFE_PARSER_CONFIG = new ParserConfig();
SAFE_PARSER_CONFIG.setSafeMode(true);
// 可选:设置白名单(仅允许指定包下的类)[7](@ref)
SAFE_PARSER_CONFIG.addAccept("com.yourpackage.model.");
}
// 对象 → JSON 字符串(默认配置)
public static String toJson(Object obj) {
return JSON.toJSONString(obj);
}
// 对象 → JSON 字符串(自定义配置)
public static String toJson(Object obj, JSONWriter.Feature... features) {
return JSON.toJSONString(obj, features);
}
// JSON 字符串 → 对象(安全模式)
public static <T> T toBean(String json, Class<T> clazz) {
return JSON.parseObject(json, clazz, SAFE_PARSER_CONFIG);
}
// JSON 字符串 → 泛型集合(如 List<User>)
public static <T> List<T> toList(String json, Class<T> clazz) {
return JSON.parseArray(json, clazz, SAFE_PARSER_CONFIG);
}
// JSON 字符串 → 复杂嵌套结构(如 Map<String, List>)
public static <T> T toComplexType(String json, TypeReference<T> typeRef) {
return JSON.parseObject(json, typeRef, SAFE_PARSER_CONFIG);
}
}
2. 基础对象转换
java
// 定义实体类
public class User {
@JSONField(name = "user_name") // 自定义字段名 [6,7](@ref)
private String name;
@JSONField(serialize = false) // 忽略序列化 [6](@ref)
private String password;
@JSONField(format = "yyyy-MM-dd") // 日期格式化 [7](@ref)
private Date birthDate;
// Getter/Setter 省略
}
// 序列化对象 → JSON
User user = new User("张三", "123456", new Date());
String json = FastJsonUtil.toJson(user);
// 输出:{"user_name":"张三","birthDate":"2025-08-03"}
// 反序列化 JSON → 对象
User parsedUser = FastJsonUtil.toBean(json, User.class);
System.out.println(parsedUser.getName()); // 输出:张三
3. 集合处理
java
// List 序列化与反序列化
List<User> userList = Arrays.asList(
new User("李四", null, null),
new User("王五", "abc", new Date())
);
String listJson = FastJsonUtil.toJson(userList, JSONWriter.Feature.PrettyFormat);
List<User> parsedList = FastJsonUtil.toList(listJson, User.class);
3.TCP通信
netty
一、依赖配置
在build.gradle
中配置最新Netty依赖:
dependencies {
implementation 'io.netty:netty-all:4.1.97.Final' // 截至2025年8月最新稳定版[4,6](@ref)
}
二**、基本使用**
1. 封装工具类
java
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class NettyClient {
private static final int RECONNECT_DELAY = 3; // 重连间隔(秒)
private EventLoopGroup workerGroup;
private Channel channel;
private final String host;
private final int port;
private NettyListener listener;
public NettyClient(String host, int port) {
this.host = host;
this.port = port;
}
// 初始化连接
public void connect() {
workerGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workerGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder()); // 字符串解码
pipeline.addLast(new StringEncoder()); // 字符串编码
pipeline.addLast(new ClientHandler(listener)); // 业务处理器
}
});
// 异步连接
ChannelFuture future = bootstrap.connect(host, port).addListener((ChannelFutureListener) f -> {
if (!f.isSuccess()) scheduleReconnect(); // 连接失败触发重连
});
channel = future.sync().channel();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 消息发送
public void sendMessage(String msg) {
if (channel != null && channel.isActive()) {
channel.writeAndFlush(msg);
}
}
// 重连机制
private void scheduleReconnect() {
workerGroup.schedule(this::connect, RECONNECT_DELAY, TimeUnit.SECONDS);
}
// 释放资源
public void shutdown() {
if (channel != null) channel.close();
if (workerGroup != null) {
Future<?> future = workerGroup.shutdownGracefully();
future.syncUninterruptibly();
}
}
// 设置消息监听器
public void setListener(NettyListener listener) {
this.listener = listener;
}
// 内部处理器
private static class ClientHandler extends SimpleChannelInboundHandler<String> {
private final NettyListener listener;
ClientHandler(NettyListener listener) {
this.listener = listener;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
if (listener != null) listener.onMessageReceived(msg); // 消息回调
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
if (listener != null) listener.onConnectionStatusChanged(true); // 连接建立
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
if (listener != null) listener.onConnectionStatusChanged(false); // 连接断开
}
}
// 状态监听接口
public interface NettyListener {
void onMessageReceived(String message);
void onConnectionStatusChanged(boolean isConnected);
}
}
2. Activity调用示例
java
public class MainActivity extends AppCompatActivity implements NettyClient.NettyListener {
private NettyClient nettyClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化Netty客户端
nettyClient = new NettyClient("192.168.1.100", 8080);
nettyClient.setListener(this);
new Thread(() -> nettyClient.connect()).start(); // 在子线程启动连接
// 发送消息示例
findViewById(R.id.btn_send).setOnClickListener(v -> {
String msg = "Hello Server!";
nettyClient.sendMessage(msg);
});
}
// 实现监听回调
@Override
public void onMessageReceived(final String message) {
runOnUiThread(() -> {
TextView tv = findViewById(R.id.tv_response);
tv.setText("收到: " + message); // 主线程更新UI
});
}
@Override
public void onConnectionStatusChanged(final boolean isConnected) {
runOnUiThread(() -> {
String status = isConnected ? "已连接" : "连接断开";
Toast.makeText(this, "状态: " + status, Toast.LENGTH_SHORT).show();
});
}
@Override
protected void onDestroy() {
nettyClient.shutdown(); // 释放资源防止内存泄漏
super.onDestroy();
}
}
4.心跳保活
java
在ClientHandler中添加:
// 每30秒发送心跳
ctx.executor().scheduleAtFixedRate(() ->
ctx.writeAndFlush("HEARTBEAT"), 0, 30, TimeUnit.SECONDS
);
4.UDP通信
netty
一、依赖配置
在build.gradle
中配置最新Netty依赖:
dependencies {
implementation 'io.netty:netty-all:4.1.97.Final' // 截至2025年8月最新稳定版[4,6](@ref)
}
二**、基本使用**
1. UDP工具类封装
java
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Netty UDP 客户端工具类
* 功能:消息发送、接收回调、资源释放
*/
public class UdpClient {
private final Bootstrap bootstrap;
private final NioEventLoopGroup group;
private Channel channel;
private final ExecutorService threadPool;
private UdpListener listener;
public UdpClient() {
group = new NioEventLoopGroup();
bootstrap = new Bootstrap();
threadPool = Executors.newSingleThreadExecutor();
bootstrap.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true) // 支持广播
.handler(new ChannelInitializer<NioDatagramChannel>() {
@Override
protected void initChannel(NioDatagramChannel ch) {
ch.pipeline().addLast(new SimpleChannelInboundHandler<DatagramPacket>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) {
// 主线程回调 → 子线程处理
threadPool.execute(() -> {
String msg = packet.content().toString(CharsetUtil.UTF_8);
if (listener != null) {
listener.onMessageReceived(msg);
}
});
}
});
}
});
}
/**
* 绑定本地端口(Android需动态申请端口)
* @param port 本地端口(0表示随机端口)
*/
public void bind(int port) {
threadPool.execute(() -> {
try {
ChannelFuture future = bootstrap.bind(port).sync();
channel = future.channel();
if (listener != null) listener.onBindSuccess(port);
} catch (Exception e) {
if (listener != null) listener.onError(e);
}
});
}
/**
* 发送消息
* @param targetIp 目标IP
* @param targetPort 目标端口
* @param message 消息内容
*/
public void send(String targetIp, int targetPort, String message) {
if (channel == null || !channel.isActive()) return;
threadPool.execute(() -> {
try {
ByteBuf buf = Unpooled.copiedBuffer(message, CharsetUtil.UTF_8);
InetSocketAddress target = new InetSocketAddress(targetIp, targetPort);
channel.writeAndFlush(new DatagramPacket(buf, target));
} catch (Exception e) {
if (listener != null) listener.onError(e);
}
});
}
/**
* 释放资源
*/
public void shutdown() {
if (channel != null) channel.close();
group.shutdownGracefully();
threadPool.shutdown();
}
/**
* 设置事件监听
*/
public void setListener(UdpListener listener) {
this.listener = listener;
}
public interface UdpListener {
void onBindSuccess(int localPort); // 绑定成功
void onMessageReceived(String msg); // 收到消息
void onError(Throwable cause); // 发生异常
}
}
2. Activity调用示例
java
public class MainActivity extends AppCompatActivity implements UdpClient.UdpListener {
private UdpClient udpClient;
private TextView tvStatus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvStatus = findViewById(R.id.tv_status);
// 1. 初始化UDP客户端
udpClient = new UdpClient();
udpClient.setListener(this);
udpClient.bind(0); // 绑定随机端口
// 2. 发送消息示例
findViewById(R.id.btn_send).setOnClickListener(v -> {
String ip = "192.168.1.100"; // 目标服务器IP
int port = 8080; // 目标服务器端口
String msg = "Hello UDP!";
udpClient.send(ip, port, msg);
});
}
// 3. 实现监听回调
@Override
public void onBindSuccess(final int localPort) {
runOnUiThread(() -> tvStatus.setText("本地端口: " + localPort));
}
@Override
public void onMessageReceived(final String msg) {
runOnUiThread(() -> Toast.makeText(this, "收到: " + msg, Toast.LENGTH_SHORT).show());
}
@Override
public void onError(final Throwable cause) {
runOnUiThread(() -> tvStatus.setText("错误: " + cause.getMessage()));
}
@Override
protected void onDestroy() {
udpClient.shutdown(); // 释放资源
super.onDestroy();
}
}
3.注意权限
XML
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
4.注意
Android 9+ 默认禁用UDP广播,需在代码中开启:
java
bootstrap.option(ChannelOption.SO_BROADCAST, true);
**5.**WebService
ksoap2-android
一、依赖配置
在build.gradle
中配置最新Netty依赖:
Groovy
implementation 'com.google.code.ksoap2-android:ksoap2-android:3.6.4'
二**、基本使用**
1. 封装工具类
java
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SoapClientUtil {
private static final String DEFAULT_NAMESPACE = "http://example.com/";
private static final String DEFAULT_URL = "http://example.com/soap-endpoint";
private static final int THREAD_POOL_SIZE = 5;
private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
// 异步请求(推荐)
public static void callAsync(String methodName, Map<String, Object> params,
boolean isDotNet, SoapCallback callback) {
threadPool.submit(() -> {
try {
Object result = callSync(methodName, params, isDotNet);
callback.onSuccess(result);
} catch (Exception e) {
callback.onError(e);
}
});
}
// 同步请求
public static Object callSync(String methodName, Map<String, Object> params,
boolean isDotNet) throws Exception {
SoapObject request = new SoapObject(DEFAULT_NAMESPACE, methodName);
// 添加请求参数
if (params != null) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
request.addProperty(entry.getKey(), entry.getValue());
}
}
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
envelope.dotNet = isDotNet; // 适配 .NET 平台
HttpTransportSE transport = new HttpTransportSE(DEFAULT_URL);
transport.debug = true; // 开启调试日志
try {
transport.call(DEFAULT_NAMESPACE + methodName, envelope);
return envelope.getResponse(); // 返回原始响应(可转为 SoapObject/String)
} catch (Exception e) {
throw new RuntimeException("SOAP请求失败: " + e.getMessage());
}
}
// 回调接口
public interface SoapCallback {
void onSuccess(Object result);
void onError(Exception e);
}
}
2. Activity调用示例
java
// 初始化参数
String methodName = "getWeather";
Map<String, Object> params = new HashMap<>();
params.put("cityName", "Beijing");
boolean isDotNet = true; // .NET 服务需设为 true
// 发起异步请求
SoapClientUtil.callAsync(methodName, params, isDotNet, new SoapClientUtil.SoapCallback() {
@Override
public void onSuccess(Object result) {
if (result instanceof SoapObject) {
SoapObject response = (SoapObject) result;
String temperature = response.getPropertyAsString("temperature");
String weather = response.getPropertyAsString("weather");
Log.d("SOAP", "北京天气: " + weather + ",温度: " + temperature);
}
}
@Override
public void onError(Exception e) {
Log.e("SOAP", "请求失败: " + e.getMessage());
}
});