不一樣的遊戲陪玩原始碼服務端介面設計模式,值得一看

雲豹科技程式設計師發表於2021-11-05
1、常見的遊戲陪玩原始碼服務端介面設計模式是採用restful形式對外提供服務,我以使用者登入、獲取個人資訊等介面作為示例,這裡只展示主要的示例程式碼:
@RequestMapping("/user")
@RestController
public class UserController {
    @Autowired
    private UserService userService;
    /**
     * 登入
     * @return
     */
    @PostMapping("/login")
    public Result login(@RequestParam String username,
                        @RequestParam String password){
        //校驗引數
        //驗證登入資訊
        //返回登入結果
        return null;
    }
    /**
     * 獲取個人資訊
     * @param userId
     * @return
     */
    @GetMapping("/getProfile")
    public Result<User> getProfile(@RequestParam String userId){
        //查詢使用者資料
        //返回查詢結果
        return null;
    }
}
這種模式執行起來也挺好用,如果遊戲陪玩原始碼服務端介面需要身份驗證,可以在filter中對token(採用token驗證的做法比較常見)進行有效性驗證,對於不需要驗證的介面,也可以在filter中進行url的排除,如果有閘道器,這些可以在閘道器中處理,這一切執行起來也都沒有問題,在遊戲陪玩原始碼開發中經常會選擇這麼做。
今天給大家分享一下另外的一種設計方式,也是在遊戲陪玩原始碼開發中總結出來的一些設計經驗,相比restful風格的介面形式,自認為有一些優點,僅供與大家交流。 下圖是我畫的一個簡單的UML圖,從圖中可以看到,介面的入口仍然是一個Controller,它只有一個doRequest方法。它依賴一個服務工廠類BusiServiceFactory,它負責從Spring容器中獲取具體的介面實現例項,然後執行遊戲陪玩原始碼業務。
不一樣的遊戲陪玩原始碼服務端介面設計模式,值得一看
2、我以使用者登入介面為例: 介面請求的報文定義,報文分為公共引數和業務引數,我將data中的引數定義業務引數,data外層的引數定義為公共引數,目前公共引數定義了serviceName和token。
{
 #公共引數
  "serviceName": "userLogin",    #介面名稱
  "token": "",   #認證的token
 #業務引數
  "data": {
    "username": "admin",  #使用者名稱
    "password": "123456"  #密碼
  }
}
3、與之對應的,我定義了一個RequestMessage的引數物件,便於在遊戲陪玩原始碼中傳遞引數,並且也可以根據需要擴充引數,如請求的終端裝置型別、版本號等等,就不一一列出,下面是RequestMessage的定義,之所以data引數是JSONObject型別,也是方便在後面的遊戲陪玩原始碼中使用。RequestMessage定義如下:
@Setter
@Getter
public class RequestMessage {
   /**
    * 介面名稱,也是每個介面實現中bean的名稱
    */
   private String serviceName;
   /**
    * 認證資訊
    */
   private String token;
   /**
    * 請求者IP
    */
   private String remoteIp;
   /**
    * 具體業務引數
    */
   private JSONObject data;
}
4、再來看一下請求入口的MainController型別的實現,在doRequest方法中,將請求的json報文轉換成了RequestMessage 物件,然後通過BusiServiceFactory 獲取具體的介面實現bean,最後處理遊戲陪玩原始碼業務並將結果返回。具體程式碼如下:
@RequestMapping("/api/service")
@Controller
public class MainController {
   @Autowired
   private BusiServiceFactory busiServiceFactory;
   /**
    * 請求入口
    * @param request
    * @return
    */
   @PostMapping("/v1")
   @ResponseBody
   public String doRequest(HttpServletRequest request){
      Result result = Result.successResult();
      try {
         // 讀取請求內容
         String reqBody = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
         JSONObject reqJson = JSON.parseObject(reqBody);
         //轉換成RequestMessage
         RequestMessage reqMessage = JSON.toJavaObject(reqJson, RequestMessage.class);
         //設定請求者的IP地址,此處僅做示例
         reqMessage.setRemoteIp(request.getRemoteAddr());
         //根據介面名稱獲取具體的介面實現bean,最後處理業務將結果返回
         BusinessService businessService = busiServiceFactory.getBusiService(reqMessage.getServiceName());
         result = businessService.doHandle(reqMessage);
      } catch (IOException e) {
         e.printStackTrace();
         result = Result.errorResult();
      }
      return JSON.toJSONString(result);
   }
}
BusiServiceFactory 的實現相當簡單,它實現了ApplicationContextAware介面,獲取到了Spring容器的上下文,用於從容器中根據Bean名稱取得Bean。
@Component
public class BusiServiceFactory implements ApplicationContextAware {
   private ApplicationContext applicationContext;
   @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      this.applicationContext = applicationContext;
   }
   /**
    * 從spring上下文中獲取介面實現的bean
    * @param beanName
    * @return
    */
   public BusinessService getBusiService(String beanName){
      return this.applicationContext.getBean(beanName, BusinessService.class);
   }
}
當然,MainController也可以實現ApplicationContextAware介面,不用單獨寫一個BusiServiceFactory來實現,這也是可以的。但從設計的角度來講,Controller中並不關心這個實現到底從哪來,它只需要知道介面可呼叫即可。 本例中這個bean是在Spring容器中,如果遊戲陪玩原始碼服務端介面實現使用SPI的方式來配置,只需要改變一下BusiServiceFactory 的實現方式即可。這也是一種可擴充套件的原則,即在遊戲陪玩原始碼服務端介面設計的時候要充分考慮其它場景,給擴充套件留有餘地。
本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理

原文連結:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2840833/,如需轉載,請註明出處,否則將追究法律責任。

相關文章