在上一章有稍微讓大家看一下swagger怎麼跟spring boot無縫接軌,本章就深入一點來介紹swagger,把它定位在 API似乎有點薄弱,當作工具(Tools)我覺得倒很個很好的解釋,它主要提供的工具分別為 swagger core、swagger codegen、swagger editor、swagger ui等,以下是各自的說明:
執行並連結到http://localhost:8090/swagger-ui.html,結果如圖
補充完swagger,進入本章的兩個主題,自訂屬性(application.properties)及專案結構定義,之前有提到application.properties(這裡),spring boot似乎一些主要的設定資訊都是透過這裡,一 般來說大部分專案都會使用到自己所需的設定資訊都會放在檔案中,可以透過File或是Apache Common Configuration或是其他方式進行,在spring boot當中已經把這機制放進去了,所以可以將所需的資訊放在application.properties或是resources下的其他自訂檔案中。
在專案的開發中,分類一向都是很難決定的,因為伴隨著越來越多code,系統或專案結構就變得很重要,以下的分類方式提供給大家參考,當然有些情形是依據當下或是特定的規定進行,不過大致上這樣的分類應該可以應付大部分的專案才是,主要以Layer的概念去切割,如view、controller、model等,然後再細分下去如model.entities、model.facade、controller.service、controller.integrate等,當然也有些基本的如commons、utils,參考結構如下:
參考連結:
http://blog.didispace.com/springbootproperties/
- swagger core:這是swagger的核心,使用Java撰寫出來的。
- swagger codegen:可以依據swagger(yaml格式)產生出來的api json或是url,可產生客戶端(client)相對應的程式碼。
- swagger editor:透過這個工具可以產生yaml,有點像是Eclipse IDE一樣,撰寫相對應的yaml,透過yaml可以產服務端(server)及客戶端(client)的程式碼,透過這裡可以玩玩看。
- swagger ui:將這工具與你的程式結合,如上章的方式,程式啟動後就會自動生成 api 前端頁面提供使用。
- SwaggerConfiguration.java
package louisz.springboot.example3; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import static springfox.documentation.builders.PathSelectors.regex; @Configuration @EnableSwagger2 public class SwaggerConfiguration { @Bean public Docket usersApi() { return new Docket(DocumentationType.SWAGGER_2).select() .apis(RequestHandlerSelectors.basePackage("louisz.springboot.example3")).paths(regex("/user.*")).build() .apiInfo(metaData()); } private ApiInfo metaData() { ApiInfo apiInfo = new ApiInfo("Louisz User RESTful API", "Louisz User RESTful API for blog", "1.0", "Terms of service", new Contact("Louisz Cheng", "#", "louisz6ster@gmail.com"), "Apache License Version 2.0", "https://www.apache.org/licenses/LICENSE-2.0"); return apiInfo; } }
- Ex3Controller.java
package louisz.springboot.example3; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.BeanUtils; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; @RestController @RequestMapping(value = "/user") // 上層路徑配置 @Api(value = "User Function", description = "操作User的RESTful 線上文件說明") // 最上層的說明 public class Ex3Controller { // 單一儲存庫 static Mapusers = Collections.synchronizedMap(new HashMap ()); /** * 取得所有User清單 * * @return */ @ApiOperation(value = "取得所有User清單", response = User.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "正常回覆"), @ApiResponse(code = 401, message = "你尚未驗證通過"), @ApiResponse(code = 403, message = "你沒有權限可以使用該功能"), @ApiResponse(code = 404, message = "URL錯誤") }) @RequestMapping(value = "/all", method = RequestMethod.POST) public List getUserList() { // 取得所有User List return new ArrayList (users.values()); } /** * 新增User資料,傳入User JSON資料進行新增,成功回傳success * * @param user * @return */ @ApiOperation(value = "新增一筆User的資料", response = Iterable.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "正常回覆"), @ApiResponse(code = 401, message = "你尚未驗證通過"), @ApiResponse(code = 403, message = "你沒有權限可以使用該功能"), @ApiResponse(code = 404, message = "URL錯誤") }) @RequestMapping(value = "/add", method = RequestMethod.POST) public String addUser(@ModelAttribute User user) { // 傳入Input JSON會自動轉換為User物件 users.put(user.getId(), user); return "add success"; } /** * 傳入id進行查詢,回傳User JSON * * @param id * @return */ @ApiOperation(value = "透過ID查詢User資料", response = User.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "正常回覆"), @ApiResponse(code = 401, message = "你尚未驗證通過"), @ApiResponse(code = 403, message = "你沒有權限可以使用該功能"), @ApiResponse(code = 404, message = "URL錯誤") }) @RequestMapping(value = "/find/{id}", method = RequestMethod.POST) public User findUser(@PathVariable Long id) { // Output User會自動轉換為JSON物件 return users.get(id); } /** * 傳入id及JSON User進行資料更新 * * @param id * @param user * @return */ @ApiOperation(value = "更新特定User資料", response = String.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "正常回覆"), @ApiResponse(code = 401, message = "你尚未驗證通過"), @ApiResponse(code = 403, message = "你沒有權限可以使用該功能"), @ApiResponse(code = 404, message = "URL錯誤") }) @RequestMapping(value = "/update/{id}", method = RequestMethod.POST) public String updateUser(@PathVariable Long id, @ModelAttribute User user) { // 更新User資料 User u = users.get(id); // System.out.println(u.getName()+"=>"+user.getMobileNumber()); // 使用了BeanUtils BeanUtils.copyProperties(user, u); users.put(id, u); return "update success"; } /** * 傳入id進行資料刪除,回傳success * * @param id * @return */ @ApiOperation(value = "刪除特定User資料", response = String.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "正常回覆"), @ApiResponse(code = 401, message = "你尚未驗證通過"), @ApiResponse(code = 403, message = "你沒有權限可以使用該功能"), @ApiResponse(code = 404, message = "URL錯誤") }) @RequestMapping(value = "/remove/{id}", method = RequestMethod.DELETE) public String removeUser(@PathVariable Long id) { // 刪除user資料 users.remove(id); return "delete success"; } }
- User.java
package louisz.springboot.example3; import io.swagger.annotations.ApiModelProperty; public class User { @ApiModelProperty(notes = "ID", required = true) private Long id; @ApiModelProperty(notes = "使用者姓名", required = true) private String name; @ApiModelProperty(notes = "使用者emai", required = true) private String email; @ApiModelProperty(notes = "使用者手機號碼") private String mobileNumber; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getMobileNumber() { return mobileNumber; } public void setMobileNumber(String mobileNumber) { this.mobileNumber = mobileNumber; } }
執行並連結到http://localhost:8090/swagger-ui.html,結果如圖
補充完swagger,進入本章的兩個主題,自訂屬性(application.properties)及專案結構定義,之前有提到application.properties(這裡),spring boot似乎一些主要的設定資訊都是透過這裡,一 般來說大部分專案都會使用到自己所需的設定資訊都會放在檔案中,可以透過File或是Apache Common Configuration或是其他方式進行,在spring boot當中已經把這機制放進去了,所以可以將所需的資訊放在application.properties或是resources下的其他自訂檔案中。
在專案的開發中,分類一向都是很難決定的,因為伴隨著越來越多code,系統或專案結構就變得很重要,以下的分類方式提供給大家參考,當然有些情形是依據當下或是特定的規定進行,不過大致上這樣的分類應該可以應付大部分的專案才是,主要以Layer的概念去切割,如view、controller、model等,然後再細分下去如model.entities、model.facade、controller.service、controller.integrate等,當然也有些基本的如commons、utils,參考結構如下:
company(公司名稱).system(系統別).layer.patterns(design pattern) company.project(專案).layer.functions(功能) company.commons(通用) company.utils(工具) company.system.commons company.system.utils
學習目的:使用自訂屬性設定檔、屬性一些進階的使用。
學習時數:1.5 hr
教學影片:- ExampleProperties.java
package louisz.springboot.example4; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; @Component // DI之後介紹 @PropertySource("classpath:example4.properties") //設定自訂的設定檔檔名及路徑 @ConfigurationProperties("app") //prefix public class ExampleProperties { //@Value("${app.name}") 也可以採用這種方式,這樣name可以不用相同,但是不建議 //,因為後續不好維護 private String name; private String version; private String nameversion; private String stringvalue; private int intvalue; private long longvalue; private int tenvalue; private int twentyvalue; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getNameversion() { return nameversion; } public void setNameversion(String nameversion) { this.nameversion = nameversion; } public String getStringvalue() { return stringvalue; } public void setStringvalue(String stringvalue) { this.stringvalue = stringvalue; } public int getIntvalue() { return intvalue; } public void setIntvalue(int intvalue) { this.intvalue = intvalue; } public long getLongvalue() { return longvalue; } public void setLongvalue(long longvalue) { this.longvalue = longvalue; } public int getTenvalue() { return tenvalue; } public void setTenvalue(int tenvalue) { this.tenvalue = tenvalue; } public int getTwentyvalue() { return twentyvalue; } public void setTwentyvalue(int twentyvalue) { this.twentyvalue = twentyvalue; } }
- TestExampleProperties.java
package louisz.springboot.example4; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.test.context.junit4.SpringRunner; //spring boot 1.4以後的方式 @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) public class TestExampleProperties { @Autowired private ExampleProperties exampleProperties;//注入 @Test public void getHello() throws Exception { //驗證是否符合預期 Assert.assertEquals(exampleProperties.getName(), "example4"); Assert.assertEquals(exampleProperties.getVersion(), "1"); Assert.assertEquals(exampleProperties.getNameversion(), "example4_1"); System.out.println(exampleProperties.getIntvalue()); System.out.println(exampleProperties.getTwentyvalue()); } }Github code(louisz.springboot.example4)
參考連結:
http://blog.didispace.com/springbootproperties/
留言
張貼留言