基于Swing的Client-Server应用多类型请求处理实现咨询
方案实现步骤
1. 定义两端共享的公共类
首先定义请求类型枚举,两端同步维护即可:
// 两端都要引入的公共枚举 public enum RequestType { LOGIN, GET_ALL_USERS, ADD_USER, DELETE_USER }
再定义通用请求封装类,实现Serializable接口支持序列化传输,把请求类型和请求参数整合在一起:
// 两端共享的请求封装类 public class Request implements Serializable { // 固定序列化ID,避免两端类版本不一致导致反序列化报错 private static final long serialVersionUID = 1L; private RequestType type; // 通用参数容器,登录请求放User对象,查询请求可以放查询条件 private Object data; public Request(RequestType type, Object data) { this.type = type; this.data = data; } // 补充对应getter方法 public RequestType getType() { return type; } public Object getData() { return data; } }
2. 客户端逻辑改造
发送请求前先封装为Request对象,不需要单独处理请求类型的传输逻辑:
// 改造后的登录方法 public void loginUser(User user) { // try-with-resources语法会自动关闭资源,不需要手动写close逻辑,更安全 try (Socket server = new Socket("127.0.0.1", 12345); ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream()); ObjectInputStream in = new ObjectInputStream(server.getInputStream())) { // 封装登录请求 Request request = new Request(RequestType.LOGIN, user); out.writeObject(request); out.flush(); User getUserInfo = (User) in.readObject(); // 后续处理登录返回结果 } catch(IOException | ClassNotFoundException e) { System.out.println(e.getMessage()); } } // 新增获取所有用户请求示例 public List<User> getAllUsers() { try (Socket server = new Socket("127.0.0.1", 12345); ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream()); ObjectInputStream in = new ObjectInputStream(server.getInputStream())) { // 封装查询所有用户请求,无参数传null即可 Request request = new Request(RequestType.GET_ALL_USERS, null); out.writeObject(request); out.flush(); return (List<User>) in.readObject(); } catch(IOException | ClassNotFoundException e) { System.out.println(e.getMessage()); return Collections.emptyList(); } }
3. 服务端逻辑改造
从输入流读取Request对象后,通过switch匹配类型分发到对应处理逻辑即可:
public void server() { try { System.out.println("Server is listening"); // accept放在死循环里持续监听客户端连接 while (true) { Socket client = serverListener.accept(); // 每个客户端请求分配独立线程处理,避免阻塞其他客户端连接 new Thread(() -> handleClientRequest(client)).start(); } } catch(IOException e) { System.out.println(e.getMessage()); e.printStackTrace(); } } // 拆分请求处理逻辑,避免server方法过于臃肿 private void handleClientRequest(Socket client) { try (ObjectInputStream in = new ObjectInputStream(client.getInputStream()); ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream())) { Request request = (Request) in.readObject(); // 按请求类型分发处理 switch (request.getType()) { case LOGIN: User loginUser = (User) request.getData(); User loginResult = loginUser(loginUser); out.writeObject(loginResult); break; case GET_ALL_USERS: List<User> allUsers = getAllUsers(); out.writeObject(allUsers); break; // 其他请求类型的处理分支自行补充 default: out.writeObject(new RuntimeException("不支持的请求类型")); } out.flush(); } catch (IOException | ClassNotFoundException e) { System.out.println(e.getMessage()); } finally { try { client.close(); } catch (IOException e) { e.printStackTrace(); } } } // 原有登录逻辑改造,接收User参数返回处理结果 private User loginUser(User user) { // 原有登录校验逻辑不变 return user; } // 新增获取所有用户的业务逻辑方法 private List<User> getAllUsers() { // 实现查询所有用户的数据库操作等逻辑 return new ArrayList<>(); }
最佳实践说明
你最初的思路属于CS架构的通用实现,完全符合规范,额外优化建议:
- 业务逻辑不要和网络处理逻辑耦合,请求分发只做类型匹配,实际业务处理放在独立的Service层类中
- 可以新增统一的响应封装类,把响应状态码、响应数据、错误信息统一封装,客户端处理更统一
- 如果需要支持长连接不要每次请求都关闭Socket,可复用连接减少握手开销
内容的提问来源于stack exchange,提问作者user12954275
相关产品推荐
相关产品推荐

