跳到主要內容

Spring boot v1.5 (四) swagger,properties and structing your code

上一章有稍微讓大家看一下swagger怎麼跟spring boot無縫接軌,本章就深入一點來介紹swagger,把它定位在 API似乎有點薄弱,當作工具(Tools)我覺得倒很個很好的解釋,它主要提供的工具分別為 swagger core、swagger codegen、swagger editor、swagger ui等,以下是各自的說明:

  • swagger core:這是swagger的核心,使用Java撰寫出來的。
  • swagger codegen:可以依據swagger(yaml格式)產生出來的api json或是url,可產生客戶端(client)相對應的程式碼。
  • swagger editor:透過這個工具可以產生yaml,有點像是Eclipse IDE一樣,撰寫相對應的yaml,透過yaml可以產服務端(server)及客戶端(client)的程式碼,透過這裡可以玩玩看。
  • swagger ui:將這工具與你的程式結合,如上章的方式,程式啟動後就會自動生成 api 前端頁面提供使用。

調整一下原本的程式碼,增加客製化的功能,並修改原本Ex3Controller、User增加REST註解,你就會發現swagger的好用。
  • 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/

留言

這個網誌中的熱門文章

IBM MQ 5.3 如何匯出Qmgr

使用IBM MQ探險家也沒有匯出的功能,這樣其實在一些備份或是Cluster時,滿困擾的,不過你也知道IBM就是喜歡用SupportPacs等等的方式,ms03這個SupportPacs就是可以匯出Qmgr中所有的資訊也可以選擇想要的,以下是他的連結 http://www-1.ibm.com/support/docview.wss?rs=171&q1=mA1J&uid=swg24000673&loc=en_US&cs=utf-8&lang=en 若是Window的版本可以直接使用,若是unix或是linux系列的就請重新編譯了﹝makeFile﹞我有試過在RHEL編譯使用是可以的。 ※請注意一定要在有安裝MQ的Server方可執行喔 使用方式如下: saveqmgr -m xxx -v 53 -o xxx.cfg -m 指定需要匯出的Qmgr名稱 -v 版本 -o 匯出後檔案名稱 以下是相關參數的列表 Usage is: ./saveqmgr. [options], where [options] are one or more of the following optional switches -h | -? : gives help (this) -v version : determines which version of MQSC to generate and can be '2','5','51','52','53' or '6' The default is to generate mqsc at the version of the connected queue manager -m lqmgr : is the name of the local qmgr to connect (MQCONN) -r rqmgr : is the name of the remote qmgr (XMITQ name) -f [file] : allows the output file to be named, if -f is not specified, the outpu...

Ext-Js Grid + DWR

Ext-Js中有Grid的sample,想說試試看加上DWR的效果如何?感覺上還不錯,以下是我參考Ext-Js附的grid array sample,加上DWR調整一下的code,我想可能還要加上資料在Loading的效果會比較好。 array-grid.js Ext.onReady(function(){ Ext.state.Manager.setProvider(new Ext.state.CookieProvider()); // example of custom renderer function function change(val){ if(val > 0){ return ' ' + val + ' '; }else if(val ' + val + ' '; } return val; } // example of custom renderer function function pctChange(val){ if(val > 0){ return ' ' + val + '% '; }else if(val ' + val + '% '; } return val; } //要設定Dwr傳回的Map的對應格式 var recordType = Ext.data.Record.create( [ {name:"reportid",mapping:"reportid",type:"string"}, {name:"reportName",mapping:"reportName",type:"string"} ] ); var myReader = new Ext.data.JsonReader( { totalProperty:"totalSize", root:"data" },recordType ); // create the data store //這裡是很重要的,這裡還可以加上listener等等的屬性喔 var store = new Ext.da...

IBM MQ 5.3 Server安裝在RHEL 4

最近在整理一些文件,整理出來一些IBM MQ相關的文件,因為相關專案都是自己來開發,所以有些文件我個人覺得還滿有價值,其實安裝IBM MQ Server在RHEL還滿簡單的,只要注意幾個關鍵點,還有就是不要用光碟中的JRE就順多了,這個問題我有問過IBM,得到的答案是建議安裝Sun的JRE會比較好,真得讓我......步驟如下 1.先安裝RHEL 4 這裡就省略不說了 2.於Sun網站下載For Linux J2SDK1.4.2以上版本,建議下載.bin版本。進行安裝: 2.1 執行./xxx.bin,會自動解壓縮出xxx.rpm 2.2 rpm -ivh xxx.rpm 2.3 會詢問安裝目錄,請依需求安裝這裡為預設。 2.4 安裝完成後,調整/etc/profile檔案,設定JAVA_HOME指定到J2SDK安裝的目錄,並將J2SDK的bin目錄加入path中。 3.安裝IBM MQ 3.1安裝MQ需先進行License安裝,否則安裝程式不會執行,因光碟中提供的mqlicense.sh,IBM已有提供更新版,故建議下載IBM網站提供的update版本進行安裝。 ※mqlicense.sh一樣也要設定權限,chmod 755 mqlicense.sh 3.2安裝完後的license會在/tmp下建立一license的目錄所以要注意/tmp需要開777的權限Chmod 777 –R /tmp 3.3先設定變數(可以設定/etc/profile) Export LD_ASSUME_KERNEL=2.4.19 Export RPM_FORCE_NPTL=1 3.4依據下列順序安裝: rpm -i MQSeriesRuntime-5.3.0-1.i386.rpm rpm -i MQSeriesSDK-5.3.0-1.i386.rpm rpm -i MQSeriesServer-5.3.0-1.i386.rpm 3.5安裝後需要進行下列環境變數設定方可使用MQ ln –sf /opt/mqm/lib/xxx/* /opt/m...