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

核心思想:
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 省略...
}
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 省略...
}
@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, "服務器處理異常");
}
}
}
public interface WebService {
ResponseBean add(UserBean userBean);
}
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 省略...
}
<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>
<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>
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("添加成功");
}
}
}
| 優點 | 缺點 |
|---|---|
|
|
適用場景:內部微服務輕量通信、異構系統集成、快速原型開發、對性能要求不極致但靈活性要求高的業務。