在上一章有稍微讓大家看一下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 Map users = 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/

留言
張貼留言