極簡的Restful框架推薦->Resty(服務端+客戶端)

dreampie發表於2015-01-28

resty 一款極簡的restful的輕量級的web框架

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

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

提醒:因框架還在開發第一個正式專案,所以會有細微調整,更新提醒頻繁,您可以在個人設定->Notification center->Watching->Email 關閉郵件提醒,感謝您的理解和支援

下載jar包: Resty jar

一、獨有優點:

1.極簡的route設計:

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

2.極簡的activerecord設計,資料操作只需短短的一行,支援批量儲存物件

//批量儲存
  User u1 = new User().set("username", "test").set("providername", "test").set("password", "123456");
  User u2 = new User().set("username", "test").set("providername", "test").set("password", "123456");
  User.dao.save(u1,u2);

  //普通儲存
  User u = new User().set("username", "test").set("providername", "test").set("password", "123456");
  u.save();

  //更新
  u.update();
  //條件更新
  User.dao.updateBy(columns,where,paras);
  User.dao.updateAll(columns,paras);

  //刪除
  u.deleted();
  //條件刪除
  User.dao.deleteBy(where,paras);
  User.dao.deleteAll();

  //查詢
  User.dao.findById(id);
  User.dao.findBy(where,paras);
  User.dao.findAll();

  //分頁
  User.dao.paginateBy(pageNumber,pageSize,where,paras);
  User.dao.paginateAll(pageNumber,pageSize);

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

  Client client=null;//建立客戶端物件
  //啟動resty-example專案,即可測試客戶端
  String apiUrl = "http://localhost:8081/api/v1.0";
  //如果不需要 使用賬號登陸
  //client = new Client(apiUrl);
  //如果有賬號許可權限制  需要登陸
  client = new Client(apiUrl, "/tests/login", "u", "123");

  //該請求必須  登陸之後才能訪問  未登入時返回 401  未認證
  ClientRequest authRequest = new ClientRequest("/users", HttpMethod.GET);
  ResponseData authResult = client.build(authRequest).ask();
  System.out.println(authResult.getData());

  //get
  ClientRequest getRequest = new ClientRequest("/tests", HttpMethod.GET);
  ResponseData getResult = client.build(getRequest).ask();
  System.out.println(getResult.getData());

  //post
  ClientRequest postRequest = new ClientRequest("/tests", HttpMethod.POST);
  postRequest.addParameter("test", Jsoner.toJSONString(Maper.of("a", "諤諤")));
  ResponseData postResult = client.build(postRequest).ask();
  System.out.println(postResult.getData());

  //put
  ClientRequest putRequest = new ClientRequest("/tests/x", HttpMethod.PUT);
  ResponseData putResult = client.build(putRequest).ask();
  System.out.println(putResult.getData());


  //delete
  ClientRequest deleteRequest = new ClientRequest("/tests/a", HttpMethod.DELETE);
  ResponseData deleteResult = client.build(deleteRequest).ask();
  System.out.println(deleteResult.getData());


  //upload
  ClientRequest uploadRequest = new ClientRequest("/tests/resty", HttpMethod.POST);
  uploadRequest.addUploadFiles("resty", ClientTest.class.getResource("/resty.jar").getFile());
  uploadRequest.addParameter("des", "test file  paras  測試筆");
  ResponseData uploadResult = client.build(uploadRequest).ask();
  System.out.println(uploadResult.getData());


  //download  支援斷點續傳
  ClientRequest downloadRequest = new ClientRequest("/tests/file", HttpMethod.GET);
  downloadRequest.setDownloadFile(ClientTest.class.getResource("/resty.jar").getFile().replace(".jar", "x.jar"));
  ResponseData downloadResult = client.build(downloadRequest).ask();
  System.out.println(downloadResult.getData());

4.支援多資料來源和巢狀事務(使用場景:需要訪問多個資料庫的應用,或者作為公司內部的資料中介軟體向客戶端提供資料訪問api等)

 // 在resource裡使用事務,也就是controller裡,rest的世界認為所以的請求都表示資源,所以這兒叫resource
  @GET("/users")
  @Transaction(name = {DS.DEFAULT_DS_NAME, "demo"}) //多資料來源的事務,如果你只有一個資料庫  直接@Transaction 不需要引數
  public User transaction() {
  //TODO 用model執行資料庫的操作  只要有操作丟擲異常  兩個資料來源 都會回滾  雖然不是分散式事務  也能保證程式碼塊的資料執行安全
  }

  // 如果你需要在service裡實現事務,通過java動態代理(必須使用介面,jdk設計就是這樣)
  public interface UserService {
    @Transaction(name = {DS.DEFAULT_DS_NAME, "demo"})//service裡新增多資料來源的事務,如果你只有一個資料庫  直接@Transaction 不需要引數
    public User save(User u);
  }
  // 在resource裡使用service層的 事務
  // @Transaction(name = {DS.DEFAULT_DS_NAME, "demo"})的註解需要寫在service的介面上
  // 注意java的自動代理必須存在介面
  // TransactionAspect 是事務切面 ,你也可以實現自己的切面比如日誌的Aspect,實現Aspect介面
  // 再private UserService userService = AspectFactory.newInstance(new UserServiceImpl(), new TransactionAspect(),new LogAspect());
  private UserService userService = AspectFactory.newInstance(new UserServiceImpl(), new TransactionAspect());

5.極簡的許可權設計,你只需要實現一個簡單介面和新增一個攔截器,即可實現基於url的許可權設計

  public void configInterceptor(InterceptorLoader interceptorLoader) {
    //許可權攔截器 放在第一位 第一時間判斷 避免執行不必要的程式碼
    interceptorLoader.add(new SecurityInterceptor(new MyAuthenticateService()));
  }

  //實現介面
  public class MyAuthenticateService implements AuthenticateService {
    //登陸時 通過name獲取使用者的密碼和許可權資訊
    public Principal findByName(String name) {
      DefaultPasswordService defaultPasswordService = new DefaultPasswordService();

      Principal principal = new Principal(name, defaultPasswordService.hash("123"), new HashSet<String>() {{
        add("api");
      }});
      return principal;
    }
    //基礎的許可權總表  所以的url許可權都放在這兒  你可以通過 檔案或者資料庫或者直接程式碼 來設定所有許可權
    public Set<Credential> loadAllCredentials() {
      Set<Credential> credentials = new HashSet<Credential>();
      credentials.add(new Credential("GET", "/api/v1.0/users**", "users"));
      return credentials;
    }
  }

6.極簡的快取設計,可擴充套件,非常簡單即可啟用model的自動快取功能

  public void configConstant(ConstantLoader constantLoader) {
    //啟用快取並在要自動使用快取的model上  開啟快取@Table(name = "sec_user", cached = true)
    constantLoader.setCacheEnable(true);
  }

  @Table(name = "sec_user", cached = true)
  public class User extends Model<User> {
    public static User dao = new User();

  }

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

  @GET("/files")
  public File file() {
    return new File(path);
  }

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

  @POST("/files")
  public UploadedFile file() {
    //Hashtable<String, UploadedFile> uploadedFiles=getFiles();
    return getFile(name);
  }

9.當然也是支援傳統的web開發,你可以自己實現資料解析,在config裡新增自定義的解析模板

  public void configConstant(ConstantLoader constantLoader) {
    // 通過字尾來返回不同的資料型別  你可以自定義自己的  render  如:FreemarkerRender
    //預設已新增json和text的支援,只需要把自定義的Render add即可
    // constantLoader.addRender("json", new JsonRender());
  }

極簡Restful框架 - Resty 開發群: 極簡Restful框架 - Resty

二、執行example示例:

1.執行根目錄下的pom.xml->install (命令列: mvn clean install -Dmaven.test.skip=true ,install時跳過測試,因為測試需要連線資料庫,沒有資料庫會失敗,把相關的外掛安裝到本地,功能完善之後釋出到maven就不需要這樣了)

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

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

4.執行resty-example下的pom.xml->tomcat7-maven-plugin:run,啟動example程式

提醒:推薦idea作為開發ide,使用分模組的多module開發

License MIT

相關文章