1.項目介紹
最近入項目之前要求熟悉一下SpringCloud Nacos微服務基於Feign接口調用並整合Swagger2進行接口文檔展示給前端,所以自己按照要求來編寫並整合了一套基於SpringCloudAlibaba Nacos、Feign、MyBatis、Swagger2的簡單微服務抽獎系統,並結合數據庫數據進行數據返回。
框架提供了基礎的微服務注冊與發現,接口Swagger訪問、MyBatis注解實現接口Dao層數據訪問,可用於快速搭建一個微服務CRUD基礎框架。
抽獎接口主要包含:添加商品接口(包含商品名稱和中獎率);抽獎接口,對添加的商品進行抽獎返回中獎商品的功能。
1.1.項目框架搭建
①項目主要結構說明:
- common-api模塊:用於存放公共的pojo類、接口返回值枚舉類、公共的抽獎函數
- consumer-product7800模塊:服務消費方
- provider-product6700模塊:服務提供方
②pom.xml依賴說明:
父工程主要pom依賴包:
其中主要的pom依賴有
spring-cloud-alibaba-dependencies
mybatis-spring-boot-starter
lombok
springfox-swagger2
swagger-bootstrap-ui

<!--統一管理jar包版本--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>4.12</junit.version> <springboot.test.version>2.5.0</springboot.test.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.18</lombok.version> <mysql.version>6.0.6</mysql.version> <druid.version>1.1.16</druid.version> <mybatis.spring.boot.version>2.1.4</mybatis.spring.boot.version> <springboot.starter.web>2.4.3</springboot.starter.web> </properties> <!--子模塊繼承之后,提供作用:鎖定版本+子module不用寫groupId和version--> <dependencyManagement> <dependencies> <!--spring boot 2.2.2--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.2.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--springcloud Hoxton.SR1--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <!--springcloud alibaba 2.1.0.RELEASE--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.1.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--mysql數據庫連接驅動包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!--web依賴包--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${springboot.starter.web}</version> </dependency> <!--alibaba druid數據庫--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!--mybatis orm框架--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.spring.boot.version}</version> </dependency> <!--lombok插件引入--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!--熱啟動部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <version>2.1.10.RELEASE</version> <scope>runtime</scope> <optional>true</optional> </dependency> <!--測試依賴包引入--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${springboot.test.version}</version> <scope>test</scope> </dependency> <!--log4j日志包--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <!--swagger2依賴--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <!--swagger第三方ui依賴--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!--排除lombok jar在打包編譯期間--> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> <!--引入mybatis逆向工程插件--> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.5</version> <configuration> <configurationFile>${basedir}/src/main/resources/mybatis-generator/generatorConfig.xml </configurationFile> <overwrite>true</overwrite> <verbose>true</verbose> </configuration> </plugin> </plugins> </build>
springcloudnacos-provider-product6700

<dependencies> <!--SpringCloud alibaba nacos--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--SpringBoot整合Web組件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--服務注冊與發現--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--日常通用jar包配置--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--api jar包引入--> <dependency> <groupId>com.fengye</groupId> <artifactId>springcloudnacos-common-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!--集合判空工具類--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.3</version> </dependency> <!--引入Swagger2組件--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!--mysql連接驅動包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!--引入ui包--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <!--swagger第三方ui依賴--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency> </dependencies>
springcloudnacos-consumer-product7800

<dependencies> <!--springcloud openfeign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--sentinel熔斷限流--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!--SpringCloud alibaba nacos--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--引入自定義的api通用包--> <dependency> <groupId>com.fengye</groupId> <artifactId>springcloudnacos-common-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!--SpringBoot整合Web組件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--日常通用jar包配置--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--引入Swagger2組件--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!--引入ui包--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <!--swagger第三方ui依賴--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.3</version> </dependency> </dependencies>
③application.yml配置
重點主要是在服務生產方provider-product6700進行數據庫連接、mybatis框架、nacos服務注冊相關的配置,具體如下:
server: port: 6700 spring: application: name: nacos-product-provider-6700 cloud: nacos: discovery: server-addr: localhost:8848 #數據庫連接池配置 datasource: username: root password: admin #假如時區報錯,增加時區配置serverTimezone=UTC url: jdbc:mysql://localhost:3306/nacosproduct?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver #整合mybatis配置 mybatis: #config-location: classpath:mybatis/mybatis-config.xml 使用了configuration注解則無需再指定mybatis-config.xml文件 mapper-locations: classpath:mybatis/mapper/*.xml configuration: #指定mybatis全局配置文件中的相關配置項 map-underscore-to-camel-case: true type-aliases-package: com.fengye.springcloud.entities #消費者將要去訪問的微服務名稱 server-url: nacos-user-service: http://nacos-product-provider
1.2.項目分包結構說明
以一個服務提供方6700來說,就是簡單地controller、mapper、service/impl,mapper層使用xml與注解結合的方式都可以。這里不再多說。
而在服務消費方7800來說,主要分為Feign接口調用與Swagger2Config配置類:
2.Swagger2/Feign接口/抽獎接口說明
2.1.Swagger2配置類
①這里主要的就是在項目中會引入Swagger2的依賴包,以及基於國人UI風格的jar包。
<!--引入Swagger2組件--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!--swagger第三方ui依賴--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency>
②編寫Swagger2Config配置類:
//將此類交給Spring管理,表示一個配置類 @Configuration //開啟Swagger2 @EnableSwagger2 public class Swagger2Config { /** * 創建API應用 * apiInfo() 增加API相關信息 * 通過select()函數返回一個ApiSelectorBuilder實例,用來控制哪些接口暴露給Swagger來展現, * 本例采用指定掃描的包路徑來定義指定要建立API的目錄 * * @return 返回Swagger的Docket配置Bean實例 */ @Bean public Docket createRestApi(Environment environment) { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .enable(true) //enable是否啟動swagger,如果為False,則swagger不能在瀏覽器中訪問 .select() //指定API對象掃描哪個包下面的controller //參數any():掃描全部; none():都不掃描 //withClassAnnotation:掃描類上的注解,參數是一個注解的反射對象 //withMethodAnnotation:掃描方法上的注解 .apis(RequestHandlerSelectors.basePackage("com.fengye.springcloud")) //過濾什么路徑 .paths(PathSelectors.any()) .build(); } /** * 創建該API的基本信息(這些基本信息會展現在文檔頁面中) * 訪問地址:http://項目實際地址/swagger-ui.html * @return 返回API基本信息 */ private ApiInfo apiInfo() { return new ApiInfoBuilder() //Swagger2展示界面的標題(重要) .title("抽獎接口API文檔") //描述信息(主要) .description("抽獎接口API文檔") .version("1.0") //.termsOfServiceUrl("https://swagger.io/docs") //.license("Apache 2.0") //.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0") //作者信息 .contact(new Contact("fengye", "https://www.cnblogs.com/yif0118/", "hyfmailsave@163.com")) .build(); } }
啟動整體的項目之后,訪問:http://localhost:7800/doc.html,即可看到具體的UI風格的API文檔界面:
2.2.Feign接口請求
Feign的接口請求調用方式主要是基於服務提供方的Controller接口,並在服務消費方編寫一個基於Controller接口一樣的Service接口層,根據服務名及對應一致的方法名進行調用。
springcloudnacos-provider-product6700
服務提供方Controller接口:

@RestController @Slf4j public class ProductController { @Autowired private ProductService productService; /** * 測試Nacos數據接口 * * @return */ @GetMapping(value = "/provider/test") public CommonResult<Product> getProductTest() { CommonResult<Product> result = new CommonResult<>(); result.setCode(ResultCodeEnum.SUCCESS.getCode()); result.setData(new Product(1, "iphone12Max", (float) 0.05)); result.setException(null); result.setMsg("測試數據接口"); result.setUrl(null); result.setSuccess(true); return result; } /** * 根據id查詢商品返回商品接口 * * @param id * @return */ @GetMapping(value = "/provider/product/{id}") public CommonResult<Product> getProductById(@PathVariable("id") Integer id) { Product product = productService.getProductById(id); if (product != null) { return new CommonResult<Product>( ResultCodeEnum.SUCCESS.getCode(), product, null, "根據id查詢商品信息成功!商品名稱為:" + product, true, null); } return new CommonResult<Product>( ResultCodeEnum.DATA_NOT_FOUND.getCode(), null, null, "根據id查詢商品信息失敗!", false, null); } /** * 獲取所有商品 * * @return */ @GetMapping(value = "/provider/getAll") public CommonResult<List<Product>> getAllProducts() { List<Product> productList = productService.getProductList(); if (CollectionUtils.isEmpty(productList)) { return new CommonResult<>( ResultCodeEnum.DATA_NOT_FOUND.getCode(), null, null, "查詢商品列表信息失敗!", false, null ); } return new CommonResult<>( ResultCodeEnum.SUCCESS.getCode(), productList, null, "查詢商品信息成功,所得到的的商品列表為:" + productList, true, null ); } /** * 添加商品接口:使用Product參數進行JSON數據插入傳遞參數 * * @param product * @return */ @PostMapping(value = "/provider/insert") public Integer insertProduct(@RequestBody Product product) { return productService.insertProduct(product); } /** * 抽獎接口:根據抽獎次數及抽獎商品的概率進行返回抽中的商品 * * @return */ @GetMapping(value = "/provider/luckyDraw") public CommonResult<Product> luckyDrawProduct() { List<Product> productList = productService.getProductList(); Product product = LotteryUtil.luckyDraw(productList); if (product == null) { return new CommonResult<>( ResultCodeEnum.PARAMS_NULL.getCode(), null, null, "未抽取到商品,謝謝惠顧!", false, null ); } return new CommonResult<>( ResultCodeEnum.SUCCESS.getCode(), product, null, "抽獎商品獲取成功!抽到的商品名稱為:" + product.getProductName(), true, null ); } }
springcloudnacos-consumer-product7800
服務消費方Servcie Feign接口:

@Component @FeignClient(value = "nacos-product-provider-6700") public interface ProductFeignService { //測試集成Nacos服務接口 @GetMapping(value = "/provider/test") public CommonResult<Product> getProductTest(); //接口名與url地址與服務生產者接口名稱相同 @GetMapping(value = "/provider/product/{id}") public CommonResult<Product> getProductById(@PathVariable("id") Integer id); //獲取所有的商品數據 @GetMapping(value = "/provider/getAll") public CommonResult<List<Product>> getAllProducts(); //編寫一個添加商品接口:包含商品名稱和中獎率 @PostMapping(value = "/provider/insert") public CommonResult<Product> insertProduct(@RequestBody Product product); //編寫一個抽獎接口,對添加的商口進行抽獎返回中獎商品 @GetMapping(value = "/provider/luckyDraw") public CommonResult<Product> luckyDrawProduct(); }
暴露給Swagger2訪問的Controller外部接口:

@RestController @Api(value = "抽獎接口演示",description = "SpringCloud Nacos測試API接口") public class ProductConsumerController { @Value("${server.port}") private String serverPort; @Autowired private ProductFeignService productFeignService; @ApiOperation(value = "獲取所有抽獎商品信息", notes = "獲取所有抽獎商品getAllProducts接口") @GetMapping(value = "/consumer/getAll") public CommonResult<List<Product>> getAllProducts(){ CommonResult<List<Product>> allProducts = productFeignService.getAllProducts(); String requestUrl = String.format("http://localhost:%s/consumer/getAll", serverPort); allProducts.setUrl(requestUrl); return allProducts; } @ApiOperation(value = "獲取商品測試test接口", notes = "test接口") @GetMapping(value = "/test") public CommonResult<Product> getProductTest(){ CommonResult<Product> productTest = productFeignService.getProductTest(); String requestUrl = String.format("http://localhost:%s/test", serverPort); productTest.setUrl(requestUrl); return productTest; } @RequestMapping(value = "/consumer/getProductById/{id}") @ApiOperation(value = "獲取對應id商品接口", notes = "根據商品id獲取商品信息") @ApiImplicitParams({ @ApiImplicitParam(paramType="query", name = "id", value = "商品id", required = true, dataType = "Integer"), }) public CommonResult<Product> getProductById(@PathVariable("id") Integer id){ CommonResult<Product> productRes = productFeignService.getProductById(id); String requestUrl = String.format("http://localhost:%s/consumer/getProductById/%s", serverPort, id); productRes.setUrl(requestUrl); return productRes; } @PostMapping(value = "/consumer/insert") @ApiOperation(value = "插入抽獎商品insert接口", notes = "插入商品接口,包含商品信息、商品抽獎概率") @ApiImplicitParams({ @ApiImplicitParam(paramType="insert", name = "id", value = "商品", required = true, dataType = "Product"), }) public CommonResult<Product> insertProduct(@RequestBody Product product){ CommonResult<Product> result = productFeignService.insertProduct(product); String requestUrl = String.format("http://localhost:%s//consumer/insert", serverPort); result.setUrl(requestUrl); return result; } //編寫一個抽獎接口,對添加的商口進行抽獎返回中獎商品 @GetMapping(value = "/consumer/luckyDraw") @ApiOperation(value = "抽獎接口", notes = "抽獎接口,根據概率返回中獎商品") public CommonResult<Product> luckyDrawProduct(){ CommonResult<Product> commonRes = productFeignService.luckyDrawProduct(); String requestUrl = String.format("http://localhost:%s//consumer/luckyDraw", serverPort); commonRes.setUrl(requestUrl); return commonRes; } }
2.3.抽獎接口實現
主要用到的抽獎商品類:
@Data @AllArgsConstructor @NoArgsConstructor @ApiModel("用戶實體類") public class Product { @ApiModelProperty("主鍵id") private Integer id; //主鍵id @ApiModelProperty("商品名稱") private String productName; //商品名稱 @ApiModelProperty("中獎率") private float winRate; //中獎率 -- 請用戶輸入小數點后兩位 }
公共接口返回值封裝類:
@Data @AllArgsConstructor @NoArgsConstructor public class CommonResult<T> { private Integer code; private T data; private String exception; private String msg; private boolean success; private String url; }
返回結果枚舉類:
@Getter public enum ResultCodeEnum { /** * 返回結果枚舉,每個枚舉代表着一個狀態 */ SUCCESS(200, "操作成功!"), ERROR(400, "操作失敗!"), DATA_NOT_FOUND(401, "查詢失敗!"), PARAMS_NULL(402, "參數不能為空!"), PARAMS_ERROR(405, "參數不合法!"), NOT_LOGIN(403, "當前賬號未登錄!"); private Integer code; private String msg; ResultCodeEnum(Integer code, String msg) { this.code = code; this.msg = msg; } }
主要的抽獎接口實現工具類:
public class LotteryUtil { /** * 抽獎設計接口: * 產生一個隨機數,0-5為一等獎商品,6-15為二等獎商品,16-40為三等獎商品,41-100為謝謝惠顧 * 在比較的時候,比較隨機數(百分比)與獲取商品的概率(百分比)的絕對值,40%以下的才中獎 * 之后計算隨機數與中獎概率的絕對值,選擇絕對值相差最小的那個為中獎商品 * @param products * @return */ public static Product luckyDraw(List<Product> products) { //1.產生一個隨機數 int probabilityCount = 100; int randomNum = (int) (Math.random()* probabilityCount); //2.41-100表示不中獎 if(randomNum > 40){ return null; } Map<String, Product> map = new HashMap<>(); List<Integer> list = new ArrayList<>(); for (Product product : products) { int intValue = new BigDecimal(product.getWinRate() * 100).intValue(); int absVal = Math.abs(randomNum - intValue); list.add(absVal); } Integer min = Collections.min(list); for (Product product : products) { int value = new BigDecimal(product.getWinRate() * 100).intValue(); if(Math.abs(randomNum - value) == min){ return product; } } return null; } }
Nacos微服務注冊中心:
使用Swagger接口測試返回中獎結果:
抽獎算法需求:抽獎接口按照添加商品接口的名稱和中獎率進行抽獎返回中獎商品,中獎率小於等於40%。即有可能按實際概率來抽獎返回不中獎情況。
抽獎算法這里實際的情況應該是按照插入獎品的實際概率0.15來計算真實的抽獎概率,本人這里實現的比較簡單,具體的抽獎概率可以
根據實際情況進行優化,也歡迎博友提出相對應的算法建議。
2.4.抽獎接口(離散算法實現)
最終晚上把抽獎接口的算法進行了實現,使用的是正態分布的離散算法,算法參考博文:抽獎概率--三種算法
下面是這種算法的具體Java代碼實現:
/** * 抽獎接口二:離散算法,具有較好的正態分布隨機性 * 竟然1-20都是靴子,21-45都是披風,那抽象成小於等於20的是靴子,大於20且小於等於45是披風, * 就變成幾個點[20,45,55,60,100],然后也是從1到99隨機取一個數R,按順序在這些點進行比較, * 知道找到第一個比R大的數的下標,比一般算法減少占用空間, * 還可以采用二分法找出R,這樣,預處理O(N),隨機數生成O(logN),空間復雜度O(N) * @param products * @return */ public static Product discreteDraw(List<Product> products){ List<Integer> integers = products.stream() .map(product -> new BigDecimal(product.getWinRate() * 100).intValue()) .collect(Collectors.toList()); //1.划分區間,將概率划分為與概率值對應的幾個點的概率區間 Integer[] arr = new Integer[integers.size()]; for (int i = 0; i < integers.size(); i++) { int sum = 0; for (int j = 0; j < i+1; j++) { sum += integers.get(j); } arr[i] = sum; } //2.最后arr就變成了0-100對應的商品的概率區間,如:[20,45,55,60,100] System.out.println("原抽獎商品的概率(%)為:" + integers); integers.forEach(System.out::println); //3.從1到99隨機取一個數R,按照順序在對這些點進行比較,找出第一個比R大的數的下標,這個下標對應就是數組中 //的抽到的商品的下標值 int probabilityCount = 100; //產生1-100的下標值 int randomNum = (int) (Math.random()* probabilityCount); //生成0-100的隨機數 int maxIndex = getMaxIndex(arr, randomNum); //4.根據索引值去查詢出中獎商品 Product target = maxIndex == -1 ? null : products.get(maxIndex); return target; } /** * * @param arr 傳入的分區后的0-100區間的概率數組arr * @param randomNum 隨機數 * @return 成功返回索引值,不成功返回-1 */ private static int getMaxIndex(Integer[] arr, int randomNum) { for (int index = 0; index < arr.length; index++) { if(arr[index] >= randomNum){ return index; } } return -1; }
另外在新增抽獎商品的接口上也增加了插入判斷概率是否大於1的容錯處理:
/** * 添加商品接口:使用Product參數進行JSON數據插入傳遞參數 * * @param product * @return */ @PostMapping(value = "/provider/insert") public Integer insertProduct(@RequestBody Product product) { int sum = productService.getProductList() .stream() .map(p -> new BigDecimal(p.getWinRate() * 100).intValue()).mapToInt(p -> p).sum(); int pVal = new BigDecimal(product.getWinRate() * 100).intValue(); int newRes = sum + pVal; //結果相加大於1,概率超過100%,返回-2,表示概率超過限制 if((pVal + newRes) > 100){ return -2; } return productService.insertProduct(product); }
這樣接口的實現就完整了。
博客示例及相關代碼已上傳至GitHub: