一 開發環境
後端語言 java
技術工具框架 springboot
二 實現目的
本demo適用於快速服務端呼叫微信小程式OCR介面實現,以行駛證介面為例
包括
- 圖片上傳
- 呼叫微信小程式介面實現OCR識別
- swagger3 整合呼叫 去除不必要的 - - 簡單實用,詳細檢視openapi文件
三 Demo上線
- 搭建我們的基礎環境
目錄結構如下
- pom檔案配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.59</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 整合swagger3
官網下載swagger,將dist目錄放入Resource-static下,修改dist為swagger3
開啟目錄下index.html,修改為
const ui = SwaggerUIBundle({
url: "swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
// End Swagger UI call region
window.ui = ui
官網開啟https://petstore.swagger.io/v...,模板json,儲存放到swagger3目錄下,修改內容
{
"swagger": "2.0",
"info": {
"title": "小程式服務端demo",
"description": "本文件為,小程式服務端介面描述文件swagger頁面",
"version": "1.0.0"
},
"tags": [
{
"name": "小程式後端服務",
"description": "此服務提供小程式訪問後端系統的業務實現."
}
],
"schemes": [
"http"
],
"paths": {
"/api/vehicle/upload-vehicle": {
"post": {
"tags": [
"小程式後端服務"
],
"summary": "行駛證照片上傳介面",
"description": "行駛證照片上傳介面",
"operationId": "uploadFile",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "file",
"in": "formData",
"description": "行駛證照片",
"required": true,
"type": "file"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/RestControllerResult"
}
}
}
}
}
},
"definitions": {
"RestControllerResult": {
"type": "object",
"properties": {
"success": {
"type": "boolean",
"description": "成功與否",
"default": false
},
"code": {
"type": "integer",
"description": "響應碼",
"format": "int64"
},
"infoMsgs": {
"type": "array",
"xml": {
"name": "infoMsgs",
"wrapped": true
},
"items": {
"type": "string",
"description": "資訊"
}
},
"warningMsgs": {
"type": "array",
"xml": {
"name": "warningMsgs",
"wrapped": true
},
"items": {
"type": "string",
"description": "警告資訊"
}
},
"errorMsg": {
"type": "string",
"description": "錯誤資訊"
},
"data": {
"type": "object"
}
},
"xml": {
"name": "RestControllerResult"
}
}
}
}
- application啟動類新增Feign呼叫註解
@SpringBootApplication
@EnableFeignClients
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- 配置全域性檔案 application.yml (properties修改為yml即可)
#服務配置
server:
port: 8890
compression:
enabled: true
max-http-header-size: 10000000
spring:
application:
name: ocr-demo
#外部呼叫
app:
vehicle: "https://api.weixin.qq.com"
至此,我們的基礎環境細緻的講解完畢,且完整基礎環境搭建完整,騷年們,開始程式碼!!!!
- 通用返回dto編寫
package com.example.demo.common.dto;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
/**
* 通用介面返回結果.
*
* @author : 小隱
* @since : 2019/8/21 9:44
*/
public class RestControllerResult<T> implements Serializable {
private static final long serialVersionUID = -3698136820012767666L;
private Boolean success;
private Integer code;
private List<String> infoMsgs = new LinkedList<>();
private List<String> warningMsgs = new LinkedList<>();
private String errorMsg;
private T data;
public RestControllerResult() {
}
public RestControllerResult(T t) {
this.data = t;
}
public Boolean getSuccess() {
return this.success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public Integer getCode() {
return this.code;
}
public void setCode(int code) {
this.code = code;
}
public List<String> getInfoMsgs() {
return this.infoMsgs;
}
public void setInfoMsgs(List<String> infoMsgs) {
this.infoMsgs = infoMsgs;
}
public List<String> getWarningMsgs() {
return this.warningMsgs;
}
public void setWarningMsgs(List<String> warningMsgs) {
this.warningMsgs = warningMsgs;
}
public String getErrorMsg() {
return this.errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public static <T> RestControllerResult<T> success(T data) {
RestControllerResult result = new RestControllerResult(data);
result.setSuccess(true);
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
RestControllerResult<?> that = (RestControllerResult) o;
return this.code.equals(that.code) && Objects.equals(this.success, that.success) && Objects
.equals(this.infoMsgs, that.infoMsgs) && Objects
.equals(this.warningMsgs, that.warningMsgs) && Objects
.equals(this.errorMsg, that.errorMsg) && Objects.equals(this.data, that.data);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(
new Object[]{this.success, this.code, this.infoMsgs, this.warningMsgs, this.errorMsg,
this.data});
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("RestControllerResult{");
sb.append("success=").append(this.success);
sb.append(", code=").append(this.code);
sb.append(", infoMsgs=").append(this.infoMsgs);
sb.append(", warningMsgs=").append(this.warningMsgs);
sb.append(", errorMsg='").append(this.errorMsg).append('\'');
sb.append(", data=").append(this.data);
sb.append('}');
return sb.toString();
}
}
- controller層編寫(分為api-controller)
api
package com.example.demo.api;
import com.example.demo.common.dto.RestControllerResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* 小程式請求後端系統Api.
*
* @author : 小隱
* @since : 2019/8/15 15:37
*/
@RestController
@RequestMapping("/api/vehicle")
public interface AppVehicleMiniApi {
/**
* 上傳行駛證照片.
*
* @param img 圖片
* @return result
*/
@PostMapping("upload-vehicle")
RestControllerResult uploadVehicle(@RequestParam("file") MultipartFile img);
}
controller
package com.example.demo.controller;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.api.AppVehicleMiniApi;
import com.example.demo.common.dto.RestControllerResult;
import com.example.demo.service.AppVehicleService;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
1. 小程式請求後端系統完成功能Controller.
2. 3. @author : 小隱
4. @since : 2019/8/21
*/
@RestController
public class AppVehicleMiniApiController implements AppVehicleMiniApi {
private static final Logger logger = LoggerFactory.getLogger(AppVehicleMiniApiController.class);
private static final String IMG_EMPTY = "上傳照片為空";
@Resource
private AppVehicleService appVehicleService;
@Override
public RestControllerResult uploadVehicle(MultipartFile img) {
logger.info("=======>行駛證上傳<=======");
RestControllerResult resultsDtoRestControllerResult = new RestControllerResult<>();
if (img.isEmpty()) {
logger.error(IMG_EMPTY);
resultsDtoRestControllerResult.setSuccess(false);
resultsDtoRestControllerResult.setCode(400);
resultsDtoRestControllerResult.setErrorMsg(IMG_EMPTY);
return resultsDtoRestControllerResult;
}
System.out.println(JSONObject.toJSONString(appVehicleService.ocrVehilce(img)));
resultsDtoRestControllerResult.setSuccess(true);
resultsDtoRestControllerResult.setCode(200);
resultsDtoRestControllerResult.setData(appVehicleService.ocrVehilce(img));
return resultsDtoRestControllerResult;
}
}
- service實現
package com.example.demo.service;
import org.springframework.web.multipart.MultipartFile;
/**
* 行駛證圖片上傳服務介面.
*
* @author : 小隱
* @since : 2019/8/19 15:50
*/
public interface AppVehicleService {
/**
* 識別行駛證.
*
* @param img 上傳圖片
* @return 識別結果
*/
Object ocrVehilce(MultipartFile img);
}
package com.example.demo.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.feign.AppVehicleFeign;
import com.example.demo.service.AppVehicleService;
import java.util.Map;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* 行駛證照片服務.
*
* @author : 小隱
* @since : 2019/8/19 18:11
*/
@Service
public class AppVehicleServiceImpl implements AppVehicleService {
private static final Logger logger = LoggerFactory.getLogger(AppVehicleServiceImpl.class);
@Resource
private AppVehicleFeign appVehicleFeign;
@Override
public Object ocrVehilce(MultipartFile img) {
Object value = appVehicleFeign.getWeiXinToken();
String s = JSONObject.toJSONString(value);
Map<String, Object> map = (Map<String, Object>)JSONObject.parse(s);
Object token = "";
if (map.get("access_token") != null) {
logger.info("最終token為" + map.get("access_token"));
token = map.get("access_token");
} else {
//返回失敗結果
logger.error("微信介面服務獲取token發生錯誤,錯誤程式碼 " + map.get("errcode"));
logger.error("微信介面服務獲取token發生錯誤,錯誤資訊 " + map.get("errmsg"));
}
return appVehicleFeign.ocrVehicle(img,token.toString());
}
}
- 重點戲:Feign呼叫實現
package com.example.demo.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
/**
* 行駛證處理feign.
*
* @author : 小隱
* @since : 2019/8/20 17:03
*/
@FeignClient(value = "vehicle", fallbackFactory = AppVehicleFeignFactory.class, url = "${app.vehicle}")
public interface AppVehicleFeign {
/**
* 獲取微信token.
*
* @return token
*/
@GetMapping("/cgi-bin/token?grant_type=client_credential&appid=[小程式開發id]&secret=[微信金鑰]")
Object getWeiXinToken();
/**
* 識別行駛證.
*
* @param img 照片
* @param token token
* @return 識別結果
*/
@PostMapping(value = "/cv/ocr/driving?type=photo&access_token={token}",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Object ocrVehicle(@RequestPart(value = "file") MultipartFile img,
@PathVariable(name = "token") String token);
}
package com.example.demo.feign;
import feign.hystrix.FallbackFactory;
/**
* 行駛證feign工廠.
*
* @author : 小隱
* @since : 2019/8/20 17:10
*/
public class AppVehicleFeignFactory implements FallbackFactory<AppVehicleFeign> {
@Override
public AppVehicleFeign create(Throwable throwable) {
return null;
}
}
終於可以愉快地測試了!!!!!
啟動應用,訪問地址 http://localhost:8890/swagger3/index.html
乾淨、簡潔、明瞭
點選上傳介面,try it out,選擇行駛證照片,執行
老夫手把手教學結束了!!!!
原創不易,小隱出品,轉載,請註明作者、出處,謝謝大家不吝賜教!!!!!
微訊號huc_lele,歡迎來擾!