首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

基於 REST 服務實現輕量級 RPC 框架:架構設計與完整實戰代碼

     編輯:Java 綜合教學

基於 REST 服務實現輕量級 RPC 框架:架構設計與完整實戰代碼

雖然業界已有成熟的 RPC 框架(如 Dubbo、Motan),但理解如何從零構建一個基於 HTTP/REST 的輕量級 RPC 框架,對於掌握分布式系統通信本質、定制化業務場景極有幫助。本文將完整展示:架構原理、REST 服務端構建、RPC 客戶端封裝、Spring 配置整合、調用測試及優缺點總結。

1. 架構原理:REST + 代理封裝 = RPC

RPC架構圖

核心思想:

  1. 服務端:暴露標準 REST API(HTTP + JSON),接收統一入口請求,內部路由到具體業務方法。
  2. 客戶端:封裝 HTTP 調用細節,提供類似本地方法調用的接口(動態代理或具體實現類),對上層業務透明化網絡通信。
  3. 統一協議:約定請求參數(method 名、JSON 參數、Token 驗證)與響應結構(統一 ReturnBean),實現跨語言、跨平台互通。

2. 服務端實現:統一入口 + 反射路由

2.1 統一響應封裝:ResponseBean

public class ResponseBean implements Serializable {
    private static final long serialVersionUID = -1L;
    public static final int SUCCESS = 10;
    public static final int FAILURE = 20;
    public static final int LOCKED = 30;
    public static final int EXCEPTION = 40;

    private int returnCode;      // 業務狀態碼
    private String returnMsg;    // 業務提示信息
    private int dataCount;       // 數據條數
    private String returnData;   // JSON 字符串數據
    private Object returnObject; // 任意對象數據
    // 構造方法、Getter/Setter 省略...
}

2.2 業務接口與實現:ApiService

public interface ApiService {
    String getToken();
    ResponseBean add(String reqJson);
}

public class ApiServiceImpl implements ApiService {
    @Autowired private UserDao userDao;
    private String token; // 用於客戶端驗證

    public ResponseBean add(String reqJson) {
        ResponseBean rb = new ResponseBean(ResponseBean.SUCCESS, "調用成功");
        try {
            Map map = JsonUtil.g.fromJson(reqJson, HashMap.class);
            // 參數提取、業務邏輯、數據庫操作...
            UserBean userBean = new UserBean();
            userBean.setUsername(map.get("username").toString());
            // ... 設置其他字段
            int count = userDao.add(userBean);
            rb.setReturnData(JsonUtil.g.toJson(count));
        } catch (Exception e) {
            log.error(e.getStackTrace());
            rb.setReturnCode(ResponseBean.FAILURE);
            rb.setReturnMsg("服務器異常");
        }
        return rb;
    }
    // getter/setter 省略...
}

2.3 統一 HTTP 入口:ApiController(核心路由分發)

@Controller
@RequestMapping("/api")
public class ApiController {
    @Autowired private ApiService apiService;

    @RequestMapping(value = "/exec", method = RequestMethod.POST)
    @ResponseBody
    public Object exec(@RequestParam("m") String methodName,
                       @RequestParam("reqJson") String reqJson,
                       @RequestParam("token") String token) {
        // 1. Token 驗證
        if (!token.equals(apiService.getToken())) {
            return new ResponseBean(ResponseBean.FAILURE, "校驗失敗");
        }
        // 2. 反射查找方法
        Method method;
        try {
            method = apiService.getClass().getMethod(methodName, String.class);
        } catch (Exception e) {
            return new ResponseBean(ResponseBean.FAILURE, "方法不存在: " + methodName);
        }
        // 3. 參數校驗
        if (StringUtils.isEmpty(reqJson)) {
            return new ResponseBean(ResponseBean.FAILURE, "參數為空");
        }
        // 4. 調用業務方法並返回
        try {
            return method.invoke(apiService, reqJson);
        } catch (Exception e) {
            return new ResponseBean(ResponseBean.FAILURE, "服務器處理異常");
        }
    }
}

3. RPC 客戶端封裝:屏蔽 HTTP 細節

3.1 定義業務接口:WebService

public interface WebService {
    ResponseBean add(UserBean userBean);
}

3.2 實現 HTTP 調用邏輯:WebserviceImpl

public class WebserviceImpl implements WebService {
    private final static Log log = LogFactory.getLog(WebserviceImpl.class);
    private String url;   // 服務端地址,如 https://host:port/api/exec
    private String token; // 驗證 Token

    @Override
    public ResponseBean add(UserBean userBean) {
        Map<String, String> params = new HashMap<>();
        params.put("token", token);
        params.put("reqJson", JsonUtil.g.toJson(userBean));
        params.put("m", "add"); // 指定調用服務端的方法名

        try {
            String responseJson = HttpClientUtil.executeHttpRequestUTF(url, params);
            return JsonUtil.g.fromJson(responseJson, ResponseBean.class);
        } catch (Exception e) {
            ResponseBean rb = new ResponseBean();
            rb.setReturnObject(e);
            return rb;
        }
    }
    // setter 省略...
}

4. Spring 配置整合

4.1 服務端配置

<mvc:annotation-driven />
<mvc:default-servlet-handler />

<bean id="apiService" class="com.lp.rpc.impl.ApiServiceImpl">
    <property name="token" value="41729ff3-3406-4fc5-aeca-04f98892999b" />
</bean>

4.2 客戶端配置

<bean id="webService" class="com.lp.rpc.impl.WebserviceImpl">
    <property name="url" value="https://192.168.0.101:8088/api/exec" />
    <property name="token" value="41729ff3-3406-4fc5-aeca-04f98892999b" />
</bean>

5. 客戶端調用測試

public class AppMain {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("application-config.xml");
        WebService webService = (WebService) ctx.getBean("webService");

        UserBean user = new UserBean();
        user.setUsername("lisi");
        user.setPassword("123456");
        user.setRealname("李四");
        user.setUserroleid(2);
        user.setCreatedate(new Date());

        ResponseBean result = webService.add(user);
        if ("1".equals(result.getReturnData().toString())) {
            System.out.println("添加成功");
        }
    }
}

6. 總結與優缺點分析

優點缺點
  • 架構簡單,上手快,無額外依賴框架
  • 基於 HTTP/JSON,跨語言、跨平台、穿透防火牆能力強
  • 可自定義協議細節(簽名、加密、壓縮、熔斷等)
  • 調試方便,瀏覽器/Postman 可直接測試
  • 性能不如基於 Netty 的二進制 RPC(序列化/網絡開銷大)
  • 安全性需自行加強(簽名、HTTPS、防重放)
  • 服務治理能力弱(無內置註冊發現、負載均衡、熔斷降級)
  • URL 維護成本高,服務端重啟可能導致調用失敗

適用場景:內部微服務輕量通信、異構系統集成、快速原型開發、對性能要求不極致但靈活性要求高的業務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved