{"id":552,"date":"2019-04-30T16:07:05","date_gmt":"2019-04-30T07:07:05","guid":{"rendered":"http:\/\/www.typea.info\/blog\/index.php\/2019\/04\/30\/google_app_enginejavaspring_bootvuetifygoogle_cloud_vision_apiocr\/"},"modified":"2019-04-30T16:07:05","modified_gmt":"2019-04-30T07:07:05","slug":"google_app_enginejavaspring_bootvuetifygoogle_cloud_vision_apiocr","status":"publish","type":"post","link":"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/30\/google_app_enginejavaspring_bootvuetifygoogle_cloud_vision_apiocr\/","title":{"rendered":"Google App Engine(Java)+Spring Boot+Vuetify\u304b\u3089\u3001Google Cloud Vision API\u3092\u547c\u3073\u51fa\u3057OCR\u3092\u5b9f\u73fe"},"content":{"rendered":"<p><a href=\"https:\/\/www.amazon.co.jp\/GCP%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%82%A8%E3%83%BC%E3%82%B9%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE-%E5%90%89%E7%A9%8D-%E7%A4%BC%E6%95%8F%E3%83%BB%E4%BB%96\/dp\/4865941959\/ref=as_li_ss_il?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;keywords=GCP&amp;qid=1556607947&amp;s=gateway&amp;sr=8-1&amp;linkCode=li2&amp;tag=typea09-22&amp;linkId=b6903fe18d3193c10d9c58dbb42c64a0\" target=\"_blank\"><img decoding=\"async\" border=\"0\" src=\"\/\/ws-fe.amazon-adsystem.com\/widgets\/q?_encoding=UTF8&amp;ASIN=4865941959&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=JP&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=typea09-22\"><\/a><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/ir-jp.amazon-adsystem.com\/e\/ir?t=typea09-22&amp;l=li2&amp;o=9&amp;a=4865941959\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\" \/><\/p>\n<ol>\n<li><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/06\/google_app_engine_java_standard_spring_boot\">Google App Engine Java Standard + Spring Boot \u74b0\u5883\u69cb\u7bc9<\/a>\n<li>\n<p><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/06\/google_app_engine_java_standard_spring_boot_thymeleaf\">Spring Boot\u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30a8\u30f3\u30b8\u30f3 Thymeleaf\u3092\u9069\u7528<\/a><\/p>\n<li>\n<p><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/06\/google_app_engine_java_spring_bootvuejs\">Spring Boot\u306bVue.js\u3092\u5229\u7528\u3059\u308b<\/a><\/p>\n<li>\n<p><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/20\/google_app_engine_java_spring_bootvuetifyajax\">Spring Boot\u306bVuetify\u5c0e\u5165\u304b\u3089\u30af\u30ed\u30b9\u30c9\u30e1\u30a4\u30f3Ajax\u901a\u4fe1<\/a><\/p>\n<li>\n<p><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/24\/google_app_engine_java_spring_bootvuetify_gae\">Spring Boot+Vuetify GAE\u3078\u30c7\u30d7\u30ed\u30a4\u3001\u52d5\u4f5c\u78ba\u8a8d<\/a><\/p>\n<li>\n<p><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/24\/visual_studio2019_xamarinformsios\">Xamarin.Forms\u30a2\u30d7\u30ea\u3092iOS\u7528\u306b\u30d3\u30eb\u30c9<\/a><\/p>\n<li>\n<p><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/28\/xamarinforms_http\">Xamarin.Forms \u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u306e\u8868\u793a\u3068 Http\u901a\u4fe1<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/29\/google_app_engine_java_spring_bootvuetify_json\">Spring Boot+Vuetify \u30d5\u30a1\u30a4\u30eb\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3068JSON\u3067\u7d50\u679c\u3092\u8fd4\u3059<\/a><\/p>\n<\/li>\n<\/ol>\n<p>\u30d5\u30a1\u30a4\u30eb\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u304c\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u3063\u305f\u306e\u3067\u3001Google Cloud Vision API\u3092\u547c\u3073\u51fa\u3057\u3001\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u305f\u753b\u50cf\u3092OCR\u89e3\u6790\u3057\u3066\u307f\u308b\u3002<\/p>\n<h2>1.Google Cloud API\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u4f7f\u7528<\/h2>\n<p>\u4ee5\u4e0b\u306eURL\u306e\u624b\u9806\u306b\u3057\u305f\u304c\u3063\u3066\u3001\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u3092\u3053\u306a\u3057\u3001\u758e\u901a\u3092\u78ba\u8a8d\u3002<\/p>\n<p><a title=\"https:\/\/cloud.google.com\/vision\/docs\/libraries?hl=ja#client-libraries-install-java\" href=\"https:\/\/cloud.google.com\/vision\/docs\/libraries?hl=ja#client-libraries-install-java\">https:\/\/cloud.google.com\/vision\/docs\/libraries?hl=ja#client-libraries-install-java<\/a><\/p>\n<p>\u3055\u3066\u3001\u4e0a\u8a18\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u3067\u306f\u3001\u30b5\u30fc\u30d3\u30b9\u30a2\u30ab\u30a6\u30f3\u30c8KEY\u3092\u30ed\u30fc\u30ab\u30eb\u3067\u7ba1\u7406\u3059\u308b\u306e\u3060\u304c\u3001GAE\u306b\u4e0a\u3052\u308b\u3068\u304d\u306b\u306f\u3069\u3046\u3059\u308b\u306e\u3060\u308d\u3046\uff1f<\/p>\n<p>\u8abf\u3079\u308b\u306e\u304c\u9762\u5012\u306a\u306e\u3067\u3001\u3044\u3063\u305f\u3093\u3001\u30c7\u30d7\u30ed\u30a4\u3001API\u547c\u3073\u51fa\u3057\u3092\u5b9f\u884c\u3057\u3066\u307f\u3066\u3001\u30a8\u30e9\u30fc\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u307f\u308b\u3002<\/p>\n<p>URL\u306b\u30a2\u30af\u30bb\u30b9\u3057\u3066\u3001API\u3092\u6709\u52b9\u5316\u3057\u306a\u3055\u3044\u3068\u3002<\/p>\n<blockquote>\n<p>[b~favophrase\/1.417820383360958412].&lt;stderr&gt;: com.google.api.gax.rpc.PermissionDeniedException: io.grpc.StatusRuntimeException: <br \/>\nPERMISSION_DENIED: Cloud Vision API has not been used in project 512734593206 before or it is disabled. <br \/>\nEnable it by visiting <a href=\"https:\/\/console.developers.google.com\/apis\/api\/vision.googleapis.com\/overview?project=99999999999\">https:\/\/console.developers.google.com\/apis\/api\/vision.googleapis.com\/overview?project=99999999999<\/a> then retry. <br \/>\nIf you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.<\/p>\n<\/blockquote>\n<p>\u30a2\u30af\u30bb\u30b9\u3059\u308b\u3068\u3001\u3042\u3041\u3001\u3053\u306e\u753b\u9762\u306d\u3002\u78ba\u304b\u306b\u3002<\/p>\n<p>\u3068\u3044\u3046\u3053\u3068\u3067\u6709\u52b9\u5316\u3059\u308b\u3002<\/p>\n<p><a href=\"https:\/\/www.typea.info\/blog\/wp-content\/uploads\/image\/Cloud-Vision-API_9C10\/enable_cloudvision_api.png\"><img loading=\"lazy\" decoding=\"async\" width=\"447\" height=\"288\" title=\"enable_cloudvision_api\" style=\"display: inline; background-image: none;\" alt=\"enable_cloudvision_api\" src=\"https:\/\/www.typea.info\/blog\/wp-content\/uploads\/image\/Cloud-Vision-API_9C10\/enable_cloudvision_api_thumb.png\" border=\"0\"><\/a><\/p>\n<h2>2.GAE Java(Spring Boot)\u5074\u306e\u5b9f\u88c5<\/h2>\n<h3>2.1 CloudVIsionService<\/h3>\n<p>Google Cloud VIsion API \u3092\u547c\u3073\u51fa\u3059\u30e6\u30fc\u30c6\u30a3\u30ea\u30c6\u30a3\u30b5\u30fc\u30d3\u30b9\u3092\u3001Spring \u30b5\u30fc\u30d3\u30b9\u3068\u3057\u3066\u4f5c\u6210\u3002<\/p>\n<p>\u4e0a\u8a18\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb\u306e\u30b5\u30f3\u30d7\u30eb\u30b3\u30fc\u30c9\u306b\u3001<a href=\"https:\/\/cloud.google.com\/vision\/docs\/ocr?hl=ja\">OCR\u306e\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8<\/a>\u3092\u898b\u306a\u304c\u3089\u3001\u5c11\u3057\u624b\u3092\u52a0\u3048\u308b\u3002<\/p>\n<p>\u30c6\u30ad\u30b9\u30c8\u304c\u3001\u753b\u50cf\u4e0a\u306b\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u4f4d\u7f6e\u60c5\u5831\u306a\u3069\u3082\u3042\u308b\u306e\u3060\u304c\u3001\u3068\u308a\u3042\u3048\u305a\u3001\u89e3\u6790\u7d50\u679c\u201ddescription\u201d \u3060\u3051\u53d6\u5f97\u3059\u308b\u3088\u3046\u306b\u3059\u308b\u3002<\/p>\n<p>\u52d5\u304b\u3057\u3066\u3044\u898b\u308b\u3068\u3001\u6700\u521d\u306b\u89e3\u6790\u7d50\u679c\u5168\u4f53\u304c\u4e0e\u3048\u3089\u308c\u3066\u3001\u4ee5\u964d\u3001\u30d6\u30ed\u30c3\u30af\u3054\u3068\u306b\u53d6\u5f97\u3067\u304d\u308b\u3088\u3046\u306a\u306e\u3067\u3001\u3068\u308a\u3042\u3048\u305a\u5148\u982d\u306e\u307f\u629c\u304d\u51fa\u3059\u3088\u3046\u306b\u30b3\u30fc\u30c9\u3092\u66f8\u3044\u3066\u304a\u304f\u3002<\/p>\n<pre class=\"prettyprint linenums\">package info.typea.google.api.cloudvision;\r\n\r\nimport java.io.ByteArrayOutputStream;\r\nimport java.io.DataInputStream;\r\nimport java.io.InputStream;\r\nimport java.util.ArrayList;\r\nimport java.util.HashMap;\r\nimport java.util.List;\r\nimport java.util.Map;\r\nimport java.util.logging.Logger;\r\n\r\nimport org.springframework.stereotype.Service;\r\n\r\nimport com.google.cloud.vision.v1.AnnotateImageRequest;\r\nimport com.google.cloud.vision.v1.AnnotateImageResponse;\r\nimport com.google.cloud.vision.v1.BatchAnnotateImagesResponse;\r\nimport com.google.cloud.vision.v1.EntityAnnotation;\r\nimport com.google.cloud.vision.v1.Feature;\r\nimport com.google.cloud.vision.v1.Feature.Type;\r\nimport com.google.cloud.vision.v1.Image;\r\nimport com.google.cloud.vision.v1.ImageAnnotatorClient;\r\nimport com.google.cloud.vision.v1.WebDetection;\r\nimport com.google.protobuf.ByteString;\r\nimport com.google.protobuf.Descriptors.FieldDescriptor;\r\n\r\n@Service\r\npublic class CloudVisionService {\r\n    private static final Logger logger = Logger.getLogger(CloudVisionService.class.getName());\r\n\r\n    public List&lt;String&gt; getOcrDocumentText(InputStream in) {\r\n        Map&lt;String, Object&gt; annotateMap = annotateImage(in, Type.DOCUMENT_TEXT_DETECTION);\r\n        \r\n        @SuppressWarnings(\"unchecked\")\r\n        List&lt;String&gt; result = (List&lt;String&gt;)annotateMap.get(\"description\");\r\n        \r\n        return result;\r\n    }\r\n    \r\n    public Map&lt;String, Object&gt; annotateImage(InputStream in, Type type) {\r\n    \r\n        Map&lt;String, Object&gt; result = new HashMap&lt;&gt;();\r\n        try(\r\n            DataInputStream reader = new DataInputStream(in);\r\n            ByteArrayOutputStream writer = new ByteArrayOutputStream();\r\n            ImageAnnotatorClient vision = ImageAnnotatorClient.create()) {\r\n            \r\n            byte[] buf = new byte[1024];\r\n            while(reader.read(buf) &gt;= 0) {\r\n                writer.write(buf);\r\n            }\r\n            byte[] data = writer.toByteArray();\r\n            ByteString imgBytes = ByteString.copyFrom(data);\r\n            \r\n            List&lt;AnnotateImageRequest&gt; requests = new ArrayList&lt;&gt;();\r\n            Image img = Image.newBuilder().setContent(imgBytes).build();\r\n            Feature feat = Feature.newBuilder().setType(type).build();\r\n            AnnotateImageRequest request = AnnotateImageRequest.newBuilder()\r\n                    .addFeatures(feat)\r\n                    .setImage(img)\r\n                    .build();\r\n            requests.add(request);\r\n            \r\n            BatchAnnotateImagesResponse response = vision.batchAnnotateImages(requests);\r\n            List&lt;AnnotateImageResponse&gt; responses = response.getResponsesList();\r\n            \r\n            for(AnnotateImageResponse res : responses) {\r\n                if (res.hasError()) {\r\n                    System.out.printf(\"Error:%s\\n\", res.getError().getMessage());\r\n                }\r\n                \r\n                switch(type) {\r\n                case TEXT_DETECTION:\r\n                case DOCUMENT_TEXT_DETECTION:\r\n                    for (EntityAnnotation annotation : res.getTextAnnotationsList()) {\r\n                        annotation.getAllFields().forEach((k,v) -&gt; {\r\n                            \/\/ TODO \u3068\u308a\u3042\u3048\u305a\u3001OCR\u306e\u89e3\u6790\u7d50\u679c\u306e\u307f\u4fdd\u6301\u3002\u5148\u982d\u306b\u3059\u3079\u3066\u3001\u4ee5\u964d\u306b\u30d6\u30ed\u30c3\u30af\uff1f\u3054\u3068\u306e\u89e3\u6790\u7d50\u679c\u304c\u683c\u7d0d\u3055\u308c\u3066\u3044\u308b\u3002\r\n                            if (\"description\".equals(k.getName())) {\r\n                                List&lt;String&gt; discriptions = (List&lt;String&gt;)result.get(\"description\");\r\n                                if (discriptions == null) {\r\n                                    discriptions = new ArrayList&lt;&gt;();\r\n                                }\r\n                                discriptions.add(v.toString());\r\n                                result.put(k.getName(), discriptions);\r\n                            }\r\n                        });\r\n                    }\r\n                    break;\r\n                \/\/ TODO \u4ed6\u306e\u30bf\u30a4\u30d7\u51e6\u7406\r\n                }\r\n            }\r\n        } catch(Exception e) {\r\n            e.printStackTrace();\r\n        }\r\n        return result;\r\n    }\r\n}\r\n<\/pre>\n<h4>2.2 \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3API<\/h4>\n<p><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/29\/google_app_engine_java_spring_bootvuetify_json\">\u30d5\u30a1\u30a4\u30eb\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3092\u53d7\u3051\u4ed8\u3051\u308b<\/a>\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306eAPI\u304b\u3089\u3001\u4e0a\u8a18\u306eCloudVisionService \u3092\u547c\u3073\u51fa\u3059\u3002@Autowired \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u4ed8\u4e0e\u3057\u305f\u30e1\u30f3\u30d0\u30fc\u3068\u3057\u3066\u5ba3\u8a00\u3057\u3066\u304a\u304f\u3002<\/p>\n<p><a href=\"https:\/\/www.typea.info\/blog\/index.php\/2019\/04\/29\/google_app_engine_java_spring_bootvuetify_json\">\u524d\u56deJSON\u3067\u8fd4\u3059\u305f\u3081\u306eMap<\/a>\u306b&#8221;text&#8221;\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u8ffd\u52a0\u3059\u308b\u3002<\/p>\n<p><pre class=\"prettyprint linenums\">@PostMapping(\"\/api\/upload-file\")\r\npublic ResponseEntity&lt;Map&lt;String,String&gt;&gt; uploadFile(\r\n        @RequestHeader(name=\"Origin\", required=false) String origin,\r\n        @RequestParam(\"file\") MultipartFile file,\r\n        @RequestParam(\"fileName\") String fileName) {\r\n    \r\n    HttpHeaders headers = new HttpHeaders();\r\n    headers.add(\"Access-Control-Allow-Origin\", origin);\r\n\r\n    List&lt;String&gt; discriptionList = null;\r\n    try {\r\n        discriptionList = cloudVisionService.getOcrDocumentText(file.getInputStream());\r\n    } catch(Exception e) {\r\n        \r\n    }\r\n    Map&lt;String,String&gt; result = new HashMap&lt;&gt;();\r\n    result.put(\"message\", \"file uploaded success.\");\r\n    result.put(\"fileName\", fileName);\r\n    result.put(\"text\", ((discriptionList == null || discriptionList.isEmpty())?\"\":discriptionList.get(0)));\r\n\r\n    return new ResponseEntity&lt;&gt;(result, headers, HttpStatus.OK);\r\n}\r\n<\/pre>\n<h2>3.Vuetify\u5074\u306e\u5b9f\u88c5<\/h2>\n<h3>3.1 OCR\u7d50\u679c\u51fa\u529b\u9818\u57df<\/h3>\n<p>UI\u5074\u3067\u3001{{ text }} \u306b\u753b\u50cf\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057OCR\u3092\u304b\u307e\u3057\u305f\u7d50\u679c\u306e\u30c6\u30ad\u30b9\u30c8\u3092\u8868\u793a\u3055\u305b\u308b\u3001\u30a8\u30ea\u30a2\u3092\u7528\u610f\u3002<\/p>\n<p><pre class=\"prettyprint linenums\">&lt;pre&gt;{{text}}&lt;\/pre&gt;<\/pre>\n<h3>3.2 Axios\u306b\u3088\u308bAjax\u901a\u4fe1<\/h3>\n<ul>\n<li>UI\u3068\u30d0\u30a4\u30f3\u30c9\u3059\u308b\u3001\u201dtext\u201d \u3092\u3001data() \u306b\u5b9a\u7fa9<\/li>\n<li>axios.post(\u2026).then((response) =&gt; { \u2026} ) \u306b\u3066\u3001this.text \u306b\u7d50\u679c\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306etext\u8981\u7d20\u3092\u30bb\u30c3\u30c8\u3059\u308b<\/li>\n<\/ul>\n<p><pre class=\"prettyprint linenums\">&lt;script&gt;\r\nimport axios from 'axios';  \r\n\r\nexport default {\r\n  name: 'FavoPhrase',\r\n  data() {\r\n    return {\r\n      file: '',\r\n      fileName: '',\r\n      text: 'initial annotate.',\r\n    }\r\n  },\r\n  methods: {\r\n    sampleAjax : function() {\r\n      axios.get(process.env.VUE_APP_API_BASE_URL + \"\/api\/hello\")\r\n        .then((res) =&gt; {\r\n          alert(\"status=\" + res.status + \":\" + res.data);\r\n        });\r\n    },\r\n    handleFileUpload: function(e) {\r\n      this.file = this.$refs.file.files[0];\r\n      if (this.file) {\r\n        this.fileName = this.file.name;\r\n      }\r\n    },\r\n    submitFile: function() {\r\n      let formData = new FormData();\r\n      formData.append('file', this.file);\r\n      formData.append('fileName', this.fileName);\r\n      console.log(formData);\r\n      axios.post(process.env.VUE_APP_API_BASE_URL + \"\/api\/upload-file\",\r\n        formData,\r\n        {\r\n          headers: {\r\n            'Content-Type': 'multipart\/formdata'\r\n          }\r\n        }\r\n      ).then((response) =&gt; {\r\n        this.text = response.data.text;\r\n        console.log(response.data);\r\n      }).catch((response) =&gt; {\r\n        alert(\"Faiure!\\n\" + response);\r\n      });\r\n    }\r\n  }\r\n}\r\n&lt;\/script&gt;\r\n<\/pre>\n<h2>3.\u52d5\u4f5c\u78ba\u8a8d<\/h2>\n<p>\u3053\u306e\u30d6\u30ed\u30b0\u306e\u5148\u982d\u90e8\u5206\u3092\u30ad\u30e3\u30d7\u30c1\u30e3\u3057\u305f\u3001\u4ee5\u4e0b\u306e\u753b\u50cf\u3092\u8aad\u307f\u8fbc\u307e\u305b\u3066\u307f\u308b\u3002<\/p>\n<h3>text.png<\/h3>\n<p><a href=\"https:\/\/www.typea.info\/blog\/wp-content\/uploads\/image\/Cloud-Vision-API_9C10\/text.png\"><img loading=\"lazy\" decoding=\"async\" width=\"485\" height=\"289\" title=\"text\" style=\"display: inline; background-image: none;\" alt=\"text\" src=\"https:\/\/www.typea.info\/blog\/wp-content\/uploads\/image\/Cloud-Vision-API_9C10\/text_thumb.png\" border=\"0\"><\/a><\/p>\n<p><\/p>\n<p><a href=\"https:\/\/www.typea.info\/blog\/wp-content\/uploads\/image\/Cloud-Vision-API_9C10\/ocr_local.png\"><img loading=\"lazy\" decoding=\"async\" width=\"605\" height=\"417\" title=\"ocr_local\" style=\"display: inline; background-image: none;\" alt=\"ocr_local\" src=\"https:\/\/www.typea.info\/blog\/wp-content\/uploads\/image\/Cloud-Vision-API_9C10\/ocr_local_thumb.png\" border=\"0\"><\/a><\/p>\n<p>\u304a\u3049\u3001\u7d50\u679c\u304c\u8868\u793a\u3055\u308c\u305f\uff01<\/p>\n<p>\u304b\u306a\u308a\u4f7f\u3048\u305d\u3046\u306a\u7d50\u679c\uff01<\/p>\n<p><a href=\"https:\/\/www.amazon.co.jp\/%E4%BB%95%E4%BA%8B%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B%EF%BC%81Google-Cloud-Platform-%E6%9C%80%E6%96%B0%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%82%A4%E3%83%B3%E3%83%95%E3%83%A9%E5%B0%8E%E5%85%A5%E3%83%9E%E3%83%8B%E3%83%A5%E3%82%A2%E3%83%AB-%E4%BB%95%E4%BA%8B%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B%EF%BC%81%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA%EF%BC%88NextPublishing%EF%BC%89-ebook\/dp\/B01D0TH4CE\/ref=as_li_ss_il?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1NGWTVVE4HNZ0&amp;keywords=google+cloud+platform&amp;qid=1556607816&amp;s=gateway&amp;sprefix=google+cloud+p,aps,385&amp;sr=8-7&amp;linkCode=li2&amp;tag=typea09-22&amp;linkId=ac8cb4927a57285ca741db884e115721\" target=\"_blank\"><img decoding=\"async\" border=\"0\" src=\"\/\/ws-fe.amazon-adsystem.com\/widgets\/q?_encoding=UTF8&amp;ASIN=B01D0TH4CE&amp;Format=_SL160_&amp;ID=AsinImage&amp;MarketPlace=JP&amp;ServiceVersion=20070822&amp;WS=1&amp;tag=typea09-22\"><\/a><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/ir-jp.amazon-adsystem.com\/e\/ir?t=typea09-22&amp;l=li2&amp;o=9&amp;a=B01D0TH4CE\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Google App Engine Java Standard + Spring Boot \u74b0\u5883\u69cb\u7bc9 Spring Boot\u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30a8\u30f3\u30b8\u30f3 Thymeleaf\u3092\u9069\u7528 Spring Boot\u306bVue.js\u3092\u5229\u7528\u3059\u308b [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"sns_share_botton_hide":"","vkExUnit_sns_title":"","_vk_print_noindex":"","sitemap_hide":"","_veu_custom_css":"","veu_display_promotion_alert":"","vkexunit_cta_each_option":"","footnotes":""},"categories":[100,19,107],"tags":[],"class_list":["post-552","post","type-post","status-publish","format-standard","hentry","category-google-cloud-platform","category-googleappengine","category-vue-js"],"veu_head_title_object":{"title":"","add_site_title":""},"_links":{"self":[{"href":"https:\/\/www.typea.info\/blog\/index.php\/wp-json\/wp\/v2\/posts\/552","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.typea.info\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.typea.info\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.typea.info\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.typea.info\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=552"}],"version-history":[{"count":0,"href":"https:\/\/www.typea.info\/blog\/index.php\/wp-json\/wp\/v2\/posts\/552\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.typea.info\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=552"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.typea.info\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=552"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.typea.info\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=552"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}