天天看點

極簡的Restful API 架構推薦推薦:Resty(服務端+用戶端)

resty一款極簡的restful輕量級的web架構,擁有jfinal/activejdbc一樣的activerecord的簡潔設計,使用更簡單的restful架構。

擁有jfinal/activejdbc一樣的activerecord的簡潔設計,使用更簡單的restful架構。

restful的api設計,是作為restful的服務端最佳選擇(使用場景:用戶端和服務端解藕,用于對靜态的html用戶端(mvvm等),ios,andriod等提供服務端的api接口)

一、獨有優點:

1.極簡的route設計:

  1.   @GET("/users/:name")  //在路徑中自定義解析的參數 如果有其他符合 也可以用 /users/{name}  
  2. // 參數名就是方法變量名  除路徑參數之外的參數也可以放在方法參數裡  傳遞方式 user={json字元串}  
  3. public Map find(String name,User user) {  
  4.   // return Lister.of(name);  
  5.   return Maper.of("k1", "v1,name:" + name, "k2", "v2");//傳回什麼資料直接return,完全融入普通方法的方式  

2.極簡的activerecord設計,資料操作隻需短短的一行 ,支援批量儲存對象

  1. //批量儲存  
  2. User u1 = new User().set("username", "test").set("providername", "test").set("password", "123456");  
  3. User u2 = new User().set("username", "test").set("providername", "test").set("password", "123456");  
  4. User.dao.save(u1,u2);  
  5. //普通儲存  
  6. User u = new User().set("username", "test").set("providername", "test").set("password", "123456");  
  7. u.save();  
  8. //更新  
  9. u.update();  
  10. //條件更新  
  11. User.dao.updateBy(where,paras);  
  12. User.dao.updateAll(columns,where,paras);  
  13. //删除  
  14. u.deleted();  
  15. //條件删除  
  16. User.dao.deleteBy(where,paras);  
  17. User.dao.deleteAll();  
  18. //查詢  
  19. User.dao.findById(id);  
  20. User.dao.findBy(where,paras);  
  21. User.dao.findAll();  
  22. //分頁  
  23. User.dao.paginateBy(pageNumber,pageSize,where,paras);  
  24. User.dao.paginateAll(pageNumber,pageSize); 

3.極簡的用戶端設計,支援各種請求,檔案上傳和檔案下載下傳(支援斷點續傳)

  1. Client client=null;//建立用戶端對象  
  2. //啟動resty-example項目,即可測試用戶端  
  3. String apiUrl = "http://localhost:8081/api/v1.0";  
  4. //如果不需要 使用賬号登陸  
  5. //client = new Client(apiUrl);  
  6. //如果有賬号權限限制  需要登陸  
  7. client = new Client(apiUrl, "/tests/login", "u", "123");  
  8. //該請求必須  登陸之後才能通路  未登入時傳回 401  未認證  
  9. ClientRequest authRequest = new ClientRequest("/users", HttpMethod.GET);  
  10. ResponseData authResult = client.build(authRequest).ask();  
  11. System.out.println(authResult.getData());  
  12. //get  
  13. ClientRequest getRequest = new ClientRequest("/tests", HttpMethod.GET);  
  14. ResponseData getResult = client.build(getRequest).ask();  
  15. System.out.println(getResult.getData());  
  16. //post  
  17. ClientRequest postRequest = new ClientRequest("/tests", HttpMethod.POST);  
  18. postRequest.addParameter("test", Jsoner.toJSONString(Maper.of("a", "谔谔")));  
  19. ResponseData postResult = client.build(postRequest).ask();  
  20. System.out.println(postResult.getData());  
  21. //put  
  22. ClientRequest putRequest = new ClientRequest("/tests/x", HttpMethod.PUT);  
  23. ResponseData putResult = client.build(putRequest).ask();  
  24. System.out.println(putResult.getData());  
  25. //delete  
  26. ClientRequest deleteRequest = new ClientRequest("/tests/a", HttpMethod.DELETE);  
  27. ResponseData deleteResult = client.build(deleteRequest).ask();  
  28. System.out.println(deleteResult.getData());  
  29. //upload  
  30. ClientRequest uploadRequest = new ClientRequest("/tests/resty", HttpMethod.POST);  
  31. uploadRequest.addUploadFiles("resty", ClientTest.class.getResource("/resty.jar").getFile());  
  32. uploadRequest.addParameter("des", "test file  paras  測試筆");  
  33. ResponseData uploadResult = client.build(uploadRequest).ask();  
  34. System.out.println(uploadResult.getData());  
  35. //download  支援斷點續傳  
  36. ClientRequest downloadRequest = new ClientRequest("/tests/file", HttpMethod.GET);  
  37. downloadRequest.setDownloadFile(ClientTest.class.getResource("/resty.jar").getFile().replace(".jar", "x.jar"));  
  38. ResponseData downloadResult = client.build(downloadRequest).ask();  
  39. System.out.println(downloadResult.getData()); 

4.支援多資料源和嵌套事務(使用場景:需要通路多個資料庫的應用,或者作為公司内部的資料中間件向用戶端提供資料通路api等)5.極簡的權限設計,你隻需要實作一個簡單接口和添加一個攔截器,即可實作基于url的權限設計

  1. // 在resource裡使用事務,也就是controller裡,rest的世界認為是以的請求都表示資源,是以這兒叫resource  
  2. @GET("/users")  
  3. @Transaction(name = {DS.DEFAULT_DS_NAME, "demo"}) //多資料源的事務,如果你隻有一個資料庫  直接@Transaction 不需要參數  
  4. public User transaction() {  
  5. //TODO 用model執行資料庫的操作  隻要有操作抛出異常  兩個資料源 都會復原  雖然不是分布式事務  也能保證代碼塊的資料執行安全  
  6. }  
  7. // 如果你需要在service裡實作事務,通過java動态代理(必須使用接口,jdk設計就是這樣)  
  8. public interface UserService {  
  9.   @Transaction(name = {DS.DEFAULT_DS_NAME, "demo"})//service裡添加多資料源的事務,如果你隻有一個資料庫  直接@Transaction 不需要參數  
  10.   public User save(User u);  
  11. // 在resource裡使用service層的 事務  
  12. // @Transaction(name = {DS.DEFAULT_DS_NAME, "demo"})的注解需要寫在service的接口上  
  13. // 注意java的自動代理必須存在接口  
  14. // TransactionAspect 是事務切面 ,你也可以實作自己的切面比如日志的Aspect,實作Aspect接口  
  15. // 再private UserService userService = AspectFactory.newInstance(new UserServiceImpl(), new TransactionAspect(),new LogAspect());  
  16. private UserService userService = AspectFactory.newInstance(new UserServiceImpl(), new TransactionAspect()); 

5.極簡的權限設計,你隻需要實作一個簡單接口和添加一個攔截器,即可實作基于url的權限設計

  1. public void configInterceptor(InterceptorLoader interceptorLoader) {  //權限攔截器 放在第一位 第一時間判斷 避免執行不必要的代碼  
  2.   interceptorLoader.add(new SecurityInterceptor(new MyAuthenticateService()));  
  3. //實作接口  
  4. public class MyAuthenticateService implements AuthenticateService {    
  5. //登陸時 通過name擷取使用者的密碼和權限資訊  
  6.   public Principal findByName(String name) {  
  7.     DefaultPasswordService defaultPasswordService = new DefaultPasswordService();  
  8.     Principal principal = new Principal(name, defaultPasswordService.hash("123"), new HashSet<String>() {{  
  9.       add("api");  
  10.     }});      
  11.     return principal;  
  12.   }    
  13.   //基礎的權限總表  是以的url權限都放在這兒  你可以通過 檔案或者資料庫或者直接代碼 來設定所有權限  
  14.   public Set<Permission> loadAllPermissions() {  
  15.     Set<Permission> permissions = new HashSet<Permission>();  
  16.     permissions.add(new Permission("GET", "/api/transactions**", "api"));      
  17.     return permissions;  
  18.   }  

6.極簡的緩存設計,可擴充,非常簡單即可啟用model的自動緩存功能7.下載下傳檔案,隻需要直接return file

  1. public void configConstant(ConstantLoader constantLoader) {  
  2.   //啟用緩存并在要自動使用緩存的model上  開啟緩存@Table(name = "sec_user", cached = true)  
  3.   constantLoader.setCacheEnable(true);  
  4. @Table(name = "sec_user", cached = true)  
  5. public class User extends Model<User> {  
  6.   public static User dao = new User();  

7.下載下傳檔案,隻需要直接return file

  1. @GET("/files")  
  2. public File file() {  
  3.   return new File(path);  

8.上傳檔案,通過getFiles,getFile把檔案寫到伺服器

  1. @POST("/files")  
  2. public UploadedFile file() {  
  3.   //Hashtable<String, UploadedFile> uploadedFiles=getFiles();  
  4.   return getFile(name);  

9.當然也是支援傳統的web開發,你可以自己實作資料解析,在config裡添加自定義的解析模闆

  1.   // 通過字尾來傳回不同的資料類型  你可以自定義自己的  render  如:FreemarkerRender  
  2.   // constantLoader.addRender("json", new JsonRender());  
  3.   //預設已添加json和text的支援,隻需要把自定義的Render add即可  

二、運作example示例:

1.運作根目錄下的pom.xml->install (把相關的插件安裝到本地,功能完善之後釋出到maven就不需要這樣了)

2.在本地mysql資料庫裡建立demo,example資料庫,對應application.properties的資料庫配置

3.運作resty-example下的pom.xml->flyway-maven-plugin:migration,自動根具resources下db目錄下的資料庫檔案生成資料庫表結構

繼續閱讀