-
Notifications
You must be signed in to change notification settings - Fork 0
/
db.json
executable file
·1 lines (1 loc) · 117 KB
/
db.json
1
{"meta":{"version":1,"warehouse":"2.2.0"},"models":{"Asset":[{"_id":"themes/typing/source/fancybox/blank.gif","path":"fancybox/blank.gif","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/fancybox_loading.gif","path":"fancybox/fancybox_loading.gif","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/fancybox_loading@2x.gif","path":"fancybox/fancybox_loading@2x.gif","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/fancybox_overlay.png","path":"fancybox/fancybox_overlay.png","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/fancybox_sprite.png","path":"fancybox/fancybox_sprite.png","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/fancybox_sprite@2x.png","path":"fancybox/fancybox_sprite@2x.png","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/jquery.fancybox.css","path":"fancybox/jquery.fancybox.css","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/jquery.fancybox.pack.js","path":"fancybox/jquery.fancybox.pack.js","modified":1,"renderable":1},{"_id":"themes/typing/source/css/donate.css","path":"css/donate.css","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/jquery.fancybox.js","path":"fancybox/jquery.fancybox.js","modified":1,"renderable":1},{"_id":"themes/typing/source/css/source.css","path":"css/source.css","modified":1,"renderable":1},{"_id":"themes/typing/source/css/typing.css","path":"css/typing.css","modified":1,"renderable":1},{"_id":"themes/typing/source/css/font-awesome.min.css","path":"css/font-awesome.min.css","modified":1,"renderable":1},{"_id":"themes/typing/source/js/typing.js","path":"js/typing.js","modified":1,"renderable":1},{"_id":"themes/typing/source/images/bitcoin.svg","path":"images/bitcoin.svg","modified":1,"renderable":1},{"_id":"themes/typing/source/images/alipay.svg","path":"images/alipay.svg","modified":1,"renderable":1},{"_id":"themes/typing/source/images/github.svg","path":"images/github.svg","modified":1,"renderable":1},{"_id":"themes/typing/source/images/like.svg","path":"images/like.svg","modified":1,"renderable":1},{"_id":"themes/typing/source/images/paypal.svg","path":"images/paypal.svg","modified":1,"renderable":1},{"_id":"themes/typing/source/images/wechat.svg","path":"images/wechat.svg","modified":1,"renderable":1},{"_id":"themes/typing/source/images/favicon.ico","path":"images/favicon.ico","modified":1,"renderable":1},{"_id":"themes/typing/source/fonts/fontawesome-webfont.woff","path":"fonts/fontawesome-webfont.woff","modified":1,"renderable":1},{"_id":"themes/typing/source/fonts/fontawesome-webfont.woff2","path":"fonts/fontawesome-webfont.woff2","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-buttons.css","path":"fancybox/helpers/jquery.fancybox-buttons.css","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/helpers/fancybox_buttons.png","path":"fancybox/helpers/fancybox_buttons.png","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-media.js","path":"fancybox/helpers/jquery.fancybox-media.js","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-buttons.js","path":"fancybox/helpers/jquery.fancybox-buttons.js","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-thumbs.css","path":"fancybox/helpers/jquery.fancybox-thumbs.css","modified":1,"renderable":1},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-thumbs.js","path":"fancybox/helpers/jquery.fancybox-thumbs.js","modified":1,"renderable":1},{"_id":"themes/typing/source/fonts/fontawesome-webfont.eot","path":"fonts/fontawesome-webfont.eot","modified":1,"renderable":1},{"_id":"themes/typing/source/fonts/FontAwesome.otf","path":"fonts/FontAwesome.otf","modified":1,"renderable":1},{"_id":"themes/typing/source/fonts/fontawesome-webfont.ttf","path":"fonts/fontawesome-webfont.ttf","modified":1,"renderable":1},{"_id":"themes/typing/source/fonts/fontawesome-webfont.svg","path":"fonts/fontawesome-webfont.svg","modified":1,"renderable":1}],"Cache":[{"_id":"source/.DS_Store","hash":"1be4eb84f6c9af249f6795d1078149aa3ca3fb47","modified":1532325320000},{"_id":"themes/typing/.editorconfig","hash":"daaa8757fac18f8735fadd0a37a42c06f421ca14","modified":1521181986000},{"_id":"themes/typing/LICENSE","hash":"d623c40b9ca68f50dd01a5d536d4f20cd2d15ad0","modified":1521181986000},{"_id":"themes/typing/CHANGELOG.md","hash":"6e242c9aed9bc63804b421563570f2ec36657605","modified":1521181986000},{"_id":"themes/typing/.gitignore","hash":"23ca468ea129826bae6890eb34b5c14f69865902","modified":1521181986000},{"_id":"themes/typing/README.md","hash":"6a79cf9d7649208e3f4e5a745e39a849758f2e3a","modified":1521181986000},{"_id":"themes/typing/_config.yml","hash":"f99801faef5145da1b94b8c45f14cde51e896058","modified":1521195848000},{"_id":"themes/typing/makefile","hash":"10862792b615b1423c6631109fb39fb87f9fe52c","modified":1521181986000},{"_id":"themes/typing/package.json","hash":"6eea79e869dbcd5a5dacd6e727976071f1d1dde5","modified":1521181986000},{"_id":"source/_posts/.DS_Store","hash":"31a367bc166f1cbb8ffe8d57864903385af2caf2","modified":1532415444000},{"_id":"source/_posts/why-write-Blogg.md","hash":"d89ecf44e9ab1d39a877d6f47993a090ee5c3cb1","modified":1531122402000},{"_id":"source/_posts/关于商业保险.md","hash":"2786e8cee7cc551133692d65c4027ae3c70bff51","modified":1531133545000},{"_id":"source/_posts/mac下实现Thrift java.md","hash":"2d5ddf9470397dd7408148c28eac61c685f98b7b","modified":1531895848000},{"_id":"source/_posts/spring-boot-一-入门篇.md","hash":"d06fd6999aeb8285c3f3f295d8c784262da200db","modified":1532482368000},{"_id":"source/_posts/推荐一个好用的录制gif程序.md","hash":"1dca6156e3016780135db3366e1cf702ec41b7f8","modified":1532324626000},{"_id":"source/about/index.md","hash":"083a965447cd06107855c03019793902efc38604","modified":1521182970000},{"_id":"themes/typing/.git/HEAD","hash":"acbaef275e46a7f14c1ef456fff2c8bbe8c84724","modified":1521181986000},{"_id":"themes/typing/.git/description","hash":"9635f1b7e12c045212819dd934d809ef07efa2f4","modified":1521181980000},{"_id":"themes/typing/.git/config","hash":"847efd6b81446dcb711c3244c2cc0052ae0a3b6d","modified":1521181986000},{"_id":"themes/typing/.git/index","hash":"6f1da0f805fe5636af5ce702f1ad47b235cd1342","modified":1521181986000},{"_id":"themes/typing/.git/packed-refs","hash":"7c0a5c8be20dc6b27b4c28aaf663e82c20b4d6ea","modified":1521181986000},{"_id":"themes/typing/languages/default.yml","hash":"3891b82f656b0464025ad1c615e4af75e08be187","modified":1521181986000},{"_id":"themes/typing/languages/en.yml","hash":"3891b82f656b0464025ad1c615e4af75e08be187","modified":1521181986000},{"_id":"themes/typing/languages/es.yml","hash":"e1713cf5cfb2e3c360f695c04e6832be104f616a","modified":1521181986000},{"_id":"themes/typing/languages/fr.yml","hash":"3fcdd2f9aaca82776c67e5031fde5b2471f579bb","modified":1521181986000},{"_id":"themes/typing/languages/nl.yml","hash":"e252497f4f7be71626b1f1b1f2c2092d271f8957","modified":1521181986000},{"_id":"themes/typing/languages/ru.yml","hash":"21374dc47e37b8405d9a66d43bf00e8a1e072ac1","modified":1521181986000},{"_id":"themes/typing/languages/zh-TW.yml","hash":"104a62c7171d467bf9851556c5bb88b93dd285d6","modified":1521181986000},{"_id":"themes/typing/languages/no.yml","hash":"f5fbf6302a76bae16825792b2b606ad81ee887f9","modified":1521181986000},{"_id":"themes/typing/languages/zh-CN.yml","hash":"78365c98a707bfb708bdaa17ac192e1a8c9f922c","modified":1521181986000},{"_id":"themes/typing/layout/category.ejs","hash":"e932f65c5bc294dc4dd07c023468cfcfeb3ec66a","modified":1521181986000},{"_id":"themes/typing/layout/archive.ejs","hash":"82264d348a7f089fe6df645ecd02fb43fbdaa6a1","modified":1521181986000},{"_id":"themes/typing/layout/index.ejs","hash":"c642b5a5ae07c1aa651ee292cfdd13dea62d9650","modified":1521181986000},{"_id":"themes/typing/layout/layout.ejs","hash":"003325528c3029f98c4d860f7fac3ee929866d14","modified":1521181986000},{"_id":"themes/typing/layout/page.ejs","hash":"f93d8ea38272ca1956134f13760a5a59a01657cf","modified":1521181986000},{"_id":"themes/typing/layout/post.ejs","hash":"f93d8ea38272ca1956134f13760a5a59a01657cf","modified":1521181986000},{"_id":"themes/typing/layout/tag.ejs","hash":"b79e597b4c18473a60337c395bb8f9bc4ed728da","modified":1521181986000},{"_id":"themes/typing/preview/preview.png","hash":"33b39c8a626db45ee473ce3e3d0e37ebd9fb83d3","modified":1521181986000},{"_id":"source/_posts/spring-boot-一-入门篇/03.jpg","hash":"012a163606f62ac45d55c5944e2ac41f1e05a5c4","modified":1532415464000},{"_id":"source/_posts/推荐一个好用的录制gif程序/03.jpg","hash":"012a163606f62ac45d55c5944e2ac41f1e05a5c4","modified":1532415357000},{"_id":"themes/typing/.git/hooks/applypatch-msg.sample","hash":"4de88eb95a5e93fd27e78b5fb3b5231a8d8917dd","modified":1521181980000},{"_id":"themes/typing/.git/hooks/commit-msg.sample","hash":"ee1ed5aad98a435f2020b6de35c173b75d9affac","modified":1521181980000},{"_id":"themes/typing/.git/hooks/fsmonitor-watchman.sample","hash":"f7c0aa40cb0d620ff0bca3efe3521ec79e5d7156","modified":1521181980000},{"_id":"themes/typing/.git/hooks/pre-applypatch.sample","hash":"f208287c1a92525de9f5462e905a9d31de1e2d75","modified":1521181980000},{"_id":"themes/typing/.git/hooks/post-update.sample","hash":"b614c2f63da7dca9f1db2e7ade61ef30448fc96c","modified":1521181980000},{"_id":"themes/typing/.git/hooks/pre-commit.sample","hash":"36aed8976dcc08b5076844f0ec645b18bc37758f","modified":1521181980000},{"_id":"themes/typing/.git/hooks/pre-push.sample","hash":"5c8518bfd1d1d3d2c1a7194994c0a16d8a313a41","modified":1521181980000},{"_id":"themes/typing/.git/hooks/pre-rebase.sample","hash":"288efdc0027db4cfd8b7c47c4aeddba09b6ded12","modified":1521181980000},{"_id":"themes/typing/.git/hooks/pre-receive.sample","hash":"705a17d259e7896f0082fe2e9f2c0c3b127be5ac","modified":1521181980000},{"_id":"themes/typing/.git/hooks/prepare-commit-msg.sample","hash":"2584806ba147152ae005cb675aa4f01d5d068456","modified":1521181980000},{"_id":"themes/typing/.git/hooks/update.sample","hash":"e729cd61b27c128951d139de8e7c63d1a3758dde","modified":1521181980000},{"_id":"themes/typing/.git/info/exclude","hash":"c879df015d97615050afa7b9641e3352a1e701ac","modified":1521181980000},{"_id":"themes/typing/.git/logs/HEAD","hash":"ba271b184e5fe41f703ce7c202060c4a4f12a43d","modified":1521181986000},{"_id":"themes/typing/layout/_partial/after-footer.ejs","hash":"fb80ed8c9cdbf56a06ea56774f3869b39583fe48","modified":1521181986000},{"_id":"themes/typing/layout/_partial/baidu_tongji.ejs","hash":"5b623332c2ce799c7829bffa01a779e4f002a97a","modified":1521181986000},{"_id":"themes/typing/layout/_partial/archive-post.ejs","hash":"ee1bcc3b71149218847b18039d67e78532ec78dd","modified":1521181986000},{"_id":"themes/typing/layout/_partial/archive.ejs","hash":"55a1def0bb0df894ce5d54272f7dcbf509abfa9e","modified":1521181986000},{"_id":"themes/typing/layout/_partial/article.ejs","hash":"fee94f5c76a2adf1bd9b5a65514272db4424f7a3","modified":1521181986000},{"_id":"themes/typing/layout/_partial/footer.ejs","hash":"491d8a40062025181fd3e7d4842c18f5072280c6","modified":1521181986000},{"_id":"themes/typing/layout/_partial/gauges-analytics.ejs","hash":"ace3000bd3e01d03041d5be24f7640b6c003a5b5","modified":1521181986000},{"_id":"themes/typing/layout/_partial/google-analytics.ejs","hash":"1ccc627d7697e68fddc367c73ac09920457e5b35","modified":1521181986000},{"_id":"themes/typing/layout/_partial/head.ejs","hash":"d0633669cbb3cf297d417db20d5199b19f8e14f8","modified":1521181986000},{"_id":"themes/typing/layout/_partial/header.ejs","hash":"85814e1e12e6700669e886a8b5155b7ab04c124f","modified":1521181986000},{"_id":"themes/typing/source/fancybox/blank.gif","hash":"2daeaa8b5f19f0bc209d976c02bd6acb51b00b0a","modified":1521181986000},{"_id":"themes/typing/source/fancybox/fancybox_loading.gif","hash":"1a755fb2599f3a313cc6cfdb14df043f8c14a99c","modified":1521181986000},{"_id":"themes/typing/source/fancybox/fancybox_loading@2x.gif","hash":"273b123496a42ba45c3416adb027cd99745058b0","modified":1521181986000},{"_id":"themes/typing/source/fancybox/fancybox_overlay.png","hash":"b3a4ee645ba494f52840ef8412015ba0f465dbe0","modified":1521181986000},{"_id":"themes/typing/source/fancybox/fancybox_sprite.png","hash":"17df19f97628e77be09c352bf27425faea248251","modified":1521181986000},{"_id":"themes/typing/source/fancybox/fancybox_sprite@2x.png","hash":"30c58913f327e28f466a00f4c1ac8001b560aed8","modified":1521181986000},{"_id":"themes/typing/source/fancybox/jquery.fancybox.css","hash":"2e54d51d21e68ebc4bb870f6e57d3bfb660d4f9c","modified":1521181986000},{"_id":"themes/typing/source/fancybox/jquery.fancybox.pack.js","hash":"2da892a02778236b64076e5e8802ef0566e1d9e8","modified":1521181986000},{"_id":"themes/typing/source/css/donate.css","hash":"892d49fa4dea81669a080923f25bfa18c8da3840","modified":1521181986000},{"_id":"themes/typing/source/fancybox/jquery.fancybox.js","hash":"58193c802f307ec9bc9e586c0e8a13ebef45d2f8","modified":1521181986000},{"_id":"themes/typing/source/css/source.css","hash":"c354df91c8a97757be3e415bef6d1f309c11c0b5","modified":1521181986000},{"_id":"themes/typing/source/css/typing.css","hash":"f7b02c8f288ef96e56cedccacb621a9fdefadcc1","modified":1521181986000},{"_id":"themes/typing/source/css/font-awesome.min.css","hash":"88af80502c44cd52ca81ffe7dc7276b7eccb06cf","modified":1521181986000},{"_id":"themes/typing/source/js/typing.js","hash":"b466c47cba32d7e318f4f7280643bbf1ff59bb0f","modified":1521181986000},{"_id":"themes/typing/source/images/bitcoin.svg","hash":"eeb2ee8cf44ba5c298baeed84bb90866f4814955","modified":1521181986000},{"_id":"themes/typing/source/images/alipay.svg","hash":"292ea040e865c1d0be259703ff850570b3bdfc97","modified":1521181986000},{"_id":"themes/typing/source/images/github.svg","hash":"90ba9a3b0dc19e70e742a39b014194f801e00f97","modified":1521181986000},{"_id":"themes/typing/source/images/like.svg","hash":"22a2754dc454d7b0321b70914fb2936b8d2ea8ab","modified":1521181986000},{"_id":"themes/typing/source/images/paypal.svg","hash":"e916dea1c1bba1bc935510310f65b2c9328a401a","modified":1521181986000},{"_id":"themes/typing/source/images/wechat.svg","hash":"30418295bed44bcc4b29076eb7deed49cf4d6c1c","modified":1521181986000},{"_id":"source/_posts/spring-boot-一-入门篇/04.jpg","hash":"9674c1b96cb5996d98101aae1afdf1f60415bb25","modified":1532415927000},{"_id":"themes/typing/source/images/favicon.ico","hash":"a406f59014c0138e066ee27824f9aa9309f0039f","modified":1521194892000},{"_id":"themes/typing/source/fonts/fontawesome-webfont.woff","hash":"28b782240b3e76db824e12c02754a9731a167527","modified":1521181986000},{"_id":"themes/typing/source/fonts/fontawesome-webfont.woff2","hash":"d6f48cba7d076fb6f2fd6ba993a75b9dc1ecbf0c","modified":1521181986000},{"_id":"source/_posts/推荐一个好用的录制gif程序/img1.jpg","hash":"4cb3fd8c97f2d84469acc584d4ca9bee61c33243","modified":1532316918000},{"_id":"source/_posts/推荐一个好用的录制gif程序/img2.jpg","hash":"043c0f854eaefacf52c44ed4f9185e05fd5e6f64","modified":1532317147000},{"_id":"themes/typing/.git/objects/pack/pack-a98d2510517c8bebf73ef4d489de7d73904356b1.idx","hash":"6f92863edba54cf599496e79385d454333ec30e8","modified":1521181986000},{"_id":"themes/typing/.git/refs/heads/master","hash":"1f46b79b8489e8d5eeff27d1b1ef763c761f1511","modified":1521181986000},{"_id":"themes/typing/layout/_partial/post/date.ejs","hash":"c3ae1c7f1486ff2dc27ddd6805d13ad119950387","modified":1521181986000},{"_id":"themes/typing/layout/_partial/post/gallery.ejs","hash":"b0bf3f5d923c261ca2b5fabab513f1ec2708c8ca","modified":1521181986000},{"_id":"themes/typing/layout/_partial/post/category.ejs","hash":"280d1ab7595e6a1881a49d207dc45cadf50090cb","modified":1521181986000},{"_id":"themes/typing/layout/_partial/post/nav.ejs","hash":"6b3459fc69e7019d048f0cd13f3c1ff32708aac1","modified":1521181986000},{"_id":"themes/typing/layout/_partial/post/tag.ejs","hash":"b52aa363c2ca79316fca9f20267cb43a2ab53386","modified":1521181986000},{"_id":"themes/typing/layout/_partial/post/title.ejs","hash":"d4a460a35e2112d0c7414fd5e19b3a16093f1caf","modified":1521181986000},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-buttons.css","hash":"6394c48092085788a8c0ef72670b0652006231a1","modified":1521181986000},{"_id":"themes/typing/source/fancybox/helpers/fancybox_buttons.png","hash":"e385b139516c6813dcd64b8fc431c364ceafe5f3","modified":1521181986000},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-media.js","hash":"e14c32cc6823b81b2f758512f13ed8eb9ef2b454","modified":1521181986000},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-buttons.js","hash":"4c9c395d705d22af7da06870d18f434e2a2eeaf9","modified":1521181986000},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-thumbs.css","hash":"b88b589f5f1aa1b3d87cc7eef34c281ff749b1ae","modified":1521181986000},{"_id":"themes/typing/source/fancybox/helpers/jquery.fancybox-thumbs.js","hash":"83cdfea43632b613771691a11f56f99d85fb6dbd","modified":1521181986000},{"_id":"themes/typing/source/fonts/fontawesome-webfont.eot","hash":"d980c2ce873dc43af460d4d572d441304499f400","modified":1521181986000},{"_id":"themes/typing/source/fonts/FontAwesome.otf","hash":"048707bc52ac4b6563aaa383bfe8660a0ddc908c","modified":1521181986000},{"_id":"themes/typing/source/fonts/fontawesome-webfont.ttf","hash":"13b1eab65a983c7a73bc7997c479d66943f7c6cb","modified":1521181986000},{"_id":"themes/typing/preview/preview-dark-mode.png","hash":"4eaf8d046cf3e06373d93efcefb2ef126d9486cc","modified":1521181986000},{"_id":"themes/typing/.git/logs/refs/heads/master","hash":"ba271b184e5fe41f703ce7c202060c4a4f12a43d","modified":1521181986000},{"_id":"themes/typing/.git/refs/remotes/origin/HEAD","hash":"d9427cda09aba1cdde5c69c2b13c905bddb0bc51","modified":1521181986000},{"_id":"themes/typing/.git/logs/refs/remotes/origin/HEAD","hash":"ba271b184e5fe41f703ce7c202060c4a4f12a43d","modified":1521181986000},{"_id":"themes/typing/source/fonts/fontawesome-webfont.svg","hash":"b5483b11f8ba213e733b5b8af9927a04fec996f6","modified":1521181986000},{"_id":"source/_posts/spring-boot-一-入门篇/02.gif","hash":"548a26ed5cec9caef484891233229bf0aa929593","modified":1532403111000},{"_id":"source/_posts/推荐一个好用的录制gif程序/giftest.gif","hash":"9c706761b5fbb72bb86645a87ae79a618e3e98ce","modified":1532324565000},{"_id":"source/_posts/spring-boot-一-入门篇/01.gif","hash":"ec443044dd55e453b138d1867dab818700158370","modified":1532402667000},{"_id":"themes/typing/.git/objects/pack/pack-a98d2510517c8bebf73ef4d489de7d73904356b1.pack","hash":"968b4ed620c5dad17373fbebbf5b023a812b32d6","modified":1521181986000},{"_id":"public/about/index.html","hash":"71de803fdfc355cbe549b484a770d5fcc7a06853","modified":1532482403417},{"_id":"public/2018/03/16/why-write-Blogg/index.html","hash":"6b9a396c4ea91a6f5d940f6b6af77bfda078e0d3","modified":1532482403442},{"_id":"public/2018/07/23/推荐一个好用的录制gif程序/index.html","hash":"b53d465d2ff1d19af324f3826f292f00197531ed","modified":1532482403444},{"_id":"public/archives/index.html","hash":"7bfac0909abb778fda352a51e7349f69d7dddb97","modified":1532482403444},{"_id":"public/index.html","hash":"be1cbf18d88b769ef73bf79db5d29a9b7d6531ed","modified":1532482403444},{"_id":"public/archives/2017/07/index.html","hash":"dbadcd87c3822212a23ea2ccd6cfc051b99470bc","modified":1532482403444},{"_id":"public/2018/07/09/关于商业保险/index.html","hash":"5933792ac9c75a6010a5cb5d11cc89c3107e5401","modified":1532482403444},{"_id":"public/archives/2018/03/index.html","hash":"a2bf2c8c1b7d7dd6ef85068db51912616f32f1eb","modified":1532482403444},{"_id":"public/archives/2018/07/index.html","hash":"e934d30b9d3b417cf5929f8b1fb63a0cb28632b2","modified":1532482403448},{"_id":"public/archives/2018/index.html","hash":"bcdf2e5e772cc8ffb039ad13ac77648322dddcf7","modified":1532482403448},{"_id":"public/tags/技术-thrift/index.html","hash":"44742b2ed19838190f0b59a0125adbd3f9cf2aae","modified":1532482403448},{"_id":"public/tags/杂谈/index.html","hash":"262bccbb05acc8dbeb4a527374a4efdc1d9267e0","modified":1532482403448},{"_id":"public/archives/2017/index.html","hash":"e23c713d548cabe4573647b2c875abb4ff8b032e","modified":1532482403449},{"_id":"public/2017/07/17/mac下实现Thrift java/index.html","hash":"07679c9fe8e83889ba61b6e2bfff619fa3eae0be","modified":1532482403449},{"_id":"public/fancybox/blank.gif","hash":"2daeaa8b5f19f0bc209d976c02bd6acb51b00b0a","modified":1532482403453},{"_id":"public/fancybox/fancybox_loading.gif","hash":"1a755fb2599f3a313cc6cfdb14df043f8c14a99c","modified":1532482403453},{"_id":"public/fancybox/fancybox_overlay.png","hash":"b3a4ee645ba494f52840ef8412015ba0f465dbe0","modified":1532482403453},{"_id":"public/fancybox/fancybox_loading@2x.gif","hash":"273b123496a42ba45c3416adb027cd99745058b0","modified":1532482403453},{"_id":"public/fancybox/fancybox_sprite.png","hash":"17df19f97628e77be09c352bf27425faea248251","modified":1532482403453},{"_id":"public/fancybox/fancybox_sprite@2x.png","hash":"30c58913f327e28f466a00f4c1ac8001b560aed8","modified":1532482403453},{"_id":"public/images/bitcoin.svg","hash":"eeb2ee8cf44ba5c298baeed84bb90866f4814955","modified":1532482403453},{"_id":"public/images/alipay.svg","hash":"292ea040e865c1d0be259703ff850570b3bdfc97","modified":1532482403453},{"_id":"public/images/github.svg","hash":"90ba9a3b0dc19e70e742a39b014194f801e00f97","modified":1532482403453},{"_id":"public/images/paypal.svg","hash":"e916dea1c1bba1bc935510310f65b2c9328a401a","modified":1532482403453},{"_id":"public/fancybox/helpers/fancybox_buttons.png","hash":"e385b139516c6813dcd64b8fc431c364ceafe5f3","modified":1532482403453},{"_id":"public/images/wechat.svg","hash":"30418295bed44bcc4b29076eb7deed49cf4d6c1c","modified":1532482403453},{"_id":"public/images/like.svg","hash":"22a2754dc454d7b0321b70914fb2936b8d2ea8ab","modified":1532482403453},{"_id":"public/2018/07/23/推荐一个好用的录制gif程序/03.jpg","hash":"012a163606f62ac45d55c5944e2ac41f1e05a5c4","modified":1532482403453},{"_id":"public/images/favicon.ico","hash":"a406f59014c0138e066ee27824f9aa9309f0039f","modified":1532482403456},{"_id":"public/fonts/fontawesome-webfont.woff","hash":"28b782240b3e76db824e12c02754a9731a167527","modified":1532482403457},{"_id":"public/fonts/fontawesome-webfont.woff2","hash":"d6f48cba7d076fb6f2fd6ba993a75b9dc1ecbf0c","modified":1532482403458},{"_id":"public/fancybox/jquery.fancybox.css","hash":"aaa582fb9eb4b7092dc69fcb2d5b1c20cca58ab6","modified":1532482403462},{"_id":"public/css/donate.css","hash":"ddd86c23355b24bb3d36e6d16eb8af0f81aefbe7","modified":1532482403462},{"_id":"public/js/typing.js","hash":"b793b6e7ec3284b7274033a01eb3341307acf068","modified":1532482403463},{"_id":"public/fancybox/helpers/jquery.fancybox-buttons.css","hash":"1a9d8e5c22b371fcc69d4dbbb823d9c39f04c0c8","modified":1532482403463},{"_id":"public/fancybox/helpers/jquery.fancybox-buttons.js","hash":"dc3645529a4bf72983a39fa34c1eb9146e082019","modified":1532482403463},{"_id":"public/fancybox/helpers/jquery.fancybox-thumbs.css","hash":"4ac329c16a5277592fc12a37cca3d72ca4ec292f","modified":1532482403463},{"_id":"public/fancybox/helpers/jquery.fancybox-media.js","hash":"294420f9ff20f4e3584d212b0c262a00a96ecdb3","modified":1532482403463},{"_id":"public/fancybox/helpers/jquery.fancybox-thumbs.js","hash":"47da1ae5401c24b5c17cc18e2730780f5c1a7a0c","modified":1532482403463},{"_id":"public/fonts/fontawesome-webfont.eot","hash":"d980c2ce873dc43af460d4d572d441304499f400","modified":1532482403463},{"_id":"public/fonts/FontAwesome.otf","hash":"048707bc52ac4b6563aaa383bfe8660a0ddc908c","modified":1532482403463},{"_id":"public/fonts/fontawesome-webfont.ttf","hash":"13b1eab65a983c7a73bc7997c479d66943f7c6cb","modified":1532482403463},{"_id":"public/2018/07/23/推荐一个好用的录制gif程序/img1.jpg","hash":"4cb3fd8c97f2d84469acc584d4ca9bee61c33243","modified":1532482403463},{"_id":"public/2018/07/23/推荐一个好用的录制gif程序/img2.jpg","hash":"043c0f854eaefacf52c44ed4f9185e05fd5e6f64","modified":1532482403464},{"_id":"public/css/source.css","hash":"74abd55491cff070d6a995bb644a2113da88e533","modified":1532482403469},{"_id":"public/fancybox/jquery.fancybox.pack.js","hash":"9e0d51ca1dbe66f6c0c7aefd552dc8122e694a6e","modified":1532482403473},{"_id":"public/css/typing.css","hash":"2ae4314da99ffdbf809939413fc12ac8ac45ce7c","modified":1532482403473},{"_id":"public/css/font-awesome.min.css","hash":"512c7d79033e3028a9be61b540cf1a6870c896f8","modified":1532482403476},{"_id":"public/fonts/fontawesome-webfont.svg","hash":"b5483b11f8ba213e733b5b8af9927a04fec996f6","modified":1532482403478},{"_id":"public/fancybox/jquery.fancybox.js","hash":"d08b03a42d5c4ba456ef8ba33116fdbb7a9cabed","modified":1532482403480},{"_id":"public/2018/07/23/推荐一个好用的录制gif程序/giftest.gif","hash":"9c706761b5fbb72bb86645a87ae79a618e3e98ce","modified":1532482403486}],"Category":[],"Data":[],"Page":[{"title":"about","date":"2018-03-16T06:49:30.000Z","_content":"","source":"about/index.md","raw":"---\ntitle: about\ndate: 2018-03-16 14:49:30\n---\n","updated":"2018-03-16T06:49:30.000Z","path":"about/index.html","comments":1,"layout":"page","_id":"cjk0gge0j000150klkfyi1fe6","content":"","site":{"data":{}},"excerpt":"","more":""}],"Post":[{"title":"why write Blog?","date":"2018-03-16T10:33:28.000Z","_content":"## 为什么要写自己的博客\n我一直是一个不爱写作的人,也是不太擅长写作的人,直到我看到一篇博文[【为什么你应该(从现在开始就)写博客】](http://mindhacks.cn/2009/02/15/why-you-should-start-blogging-now/),受益匪浅,建议大家看一下,从中找到灵感,里面有句话我比较认同:用博客的形式来记录下你有价值的思考,会带来很多好处,却没有任何明显的坏处。闲来无事不知道要做什么的时候,就多去看看同行的博客,会带来意想不到的效果。\n<br>\n\n其实本人打算写博客的初衷是单纯记录用过的技术、方案,便于后期忘记了再从头找资料,用博客记录下来即便是忘了再回来看的时候也能快速的回忆起来,毕竟自己写过的东西印象才最深刻。当然这是初衷,现在看来博客的用处远不止这些,看过那些大牛的博客后得到些感触,写出有价值的文章、写出自己独立的思考、提高个人影响力(当然要基于你有价值的博文,很难,厚积薄发也不是不可能),努力最终都会有回报,等N年后你会感谢自己曾经的努力。\n<br>\n\n刚开始写博客最大的阻力是不知道怎么写,虽然我现在也不知道怎么写出有价值的博文,但不管成与败,首先得迈出第一步,然后做一个爱思考、爱总结的人。\n\n## 怎样搭建自己的博客\n建议使用很火的开源工具hexo,比较热门的主题next, 使用的主题来源于geekplux,感谢!具体的搭建方法,网上教程有很多,我懒,不再赘述\n\n\n## 怎么写博客\n博客大牛们大都借助一些语言、工具,写出清洁、易读的文章\n- markdown [点我学习语法](https://www.appinn.com/markdown);省去排版的烦恼,重点回归到文字本身;可以用工具效率更高\n * MarkdownPad 2\n * atom(强烈建议使用,基于markdown,尝试用了很多工具,这个是我最爱的)\n * [geekplux](https://geekplux.com/markdown-editor/)\n * [mdeditor](https://www.zybuluo.com/mdeditor)\n* org-mode\n\n\n## 推荐有意思的博客和网站\n* http://mindhacks.cn/\n* https://geekplux.com/\n* https://www.v2ex.com/?r=s284745061\n","source":"_posts/why-write-Blogg.md","raw":"---\ntitle: why write Blog?\ndate: 2018-03-16 18:33:28\ntags: 杂谈\n---\n## 为什么要写自己的博客\n我一直是一个不爱写作的人,也是不太擅长写作的人,直到我看到一篇博文[【为什么你应该(从现在开始就)写博客】](http://mindhacks.cn/2009/02/15/why-you-should-start-blogging-now/),受益匪浅,建议大家看一下,从中找到灵感,里面有句话我比较认同:用博客的形式来记录下你有价值的思考,会带来很多好处,却没有任何明显的坏处。闲来无事不知道要做什么的时候,就多去看看同行的博客,会带来意想不到的效果。\n<br>\n\n其实本人打算写博客的初衷是单纯记录用过的技术、方案,便于后期忘记了再从头找资料,用博客记录下来即便是忘了再回来看的时候也能快速的回忆起来,毕竟自己写过的东西印象才最深刻。当然这是初衷,现在看来博客的用处远不止这些,看过那些大牛的博客后得到些感触,写出有价值的文章、写出自己独立的思考、提高个人影响力(当然要基于你有价值的博文,很难,厚积薄发也不是不可能),努力最终都会有回报,等N年后你会感谢自己曾经的努力。\n<br>\n\n刚开始写博客最大的阻力是不知道怎么写,虽然我现在也不知道怎么写出有价值的博文,但不管成与败,首先得迈出第一步,然后做一个爱思考、爱总结的人。\n\n## 怎样搭建自己的博客\n建议使用很火的开源工具hexo,比较热门的主题next, 使用的主题来源于geekplux,感谢!具体的搭建方法,网上教程有很多,我懒,不再赘述\n\n\n## 怎么写博客\n博客大牛们大都借助一些语言、工具,写出清洁、易读的文章\n- markdown [点我学习语法](https://www.appinn.com/markdown);省去排版的烦恼,重点回归到文字本身;可以用工具效率更高\n * MarkdownPad 2\n * atom(强烈建议使用,基于markdown,尝试用了很多工具,这个是我最爱的)\n * [geekplux](https://geekplux.com/markdown-editor/)\n * [mdeditor](https://www.zybuluo.com/mdeditor)\n* org-mode\n\n\n## 推荐有意思的博客和网站\n* http://mindhacks.cn/\n* https://geekplux.com/\n* https://www.v2ex.com/?r=s284745061\n","slug":"why-write-Blogg","published":1,"updated":"2018-07-09T07:46:42.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjk0gge0d000050klfnoeo8z2","content":"<h2 id=\"为什么要写自己的博客\"><a href=\"#为什么要写自己的博客\" class=\"headerlink\" title=\"为什么要写自己的博客\"></a>为什么要写自己的博客</h2><p>我一直是一个不爱写作的人,也是不太擅长写作的人,直到我看到一篇博文<a href=\"http://mindhacks.cn/2009/02/15/why-you-should-start-blogging-now/\" target=\"_blank\" rel=\"noopener\">【为什么你应该(从现在开始就)写博客】</a>,受益匪浅,建议大家看一下,从中找到灵感,里面有句话我比较认同:用博客的形式来记录下你有价值的思考,会带来很多好处,却没有任何明显的坏处。闲来无事不知道要做什么的时候,就多去看看同行的博客,会带来意想不到的效果。<br><br></p>\n<p>其实本人打算写博客的初衷是单纯记录用过的技术、方案,便于后期忘记了再从头找资料,用博客记录下来即便是忘了再回来看的时候也能快速的回忆起来,毕竟自己写过的东西印象才最深刻。当然这是初衷,现在看来博客的用处远不止这些,看过那些大牛的博客后得到些感触,写出有价值的文章、写出自己独立的思考、提高个人影响力(当然要基于你有价值的博文,很难,厚积薄发也不是不可能),努力最终都会有回报,等N年后你会感谢自己曾经的努力。<br><br></p>\n<p>刚开始写博客最大的阻力是不知道怎么写,虽然我现在也不知道怎么写出有价值的博文,但不管成与败,首先得迈出第一步,然后做一个爱思考、爱总结的人。</p>\n<h2 id=\"怎样搭建自己的博客\"><a href=\"#怎样搭建自己的博客\" class=\"headerlink\" title=\"怎样搭建自己的博客\"></a>怎样搭建自己的博客</h2><p>建议使用很火的开源工具hexo,比较热门的主题next, 使用的主题来源于geekplux,感谢!具体的搭建方法,网上教程有很多,我懒,不再赘述</p>\n<h2 id=\"怎么写博客\"><a href=\"#怎么写博客\" class=\"headerlink\" title=\"怎么写博客\"></a>怎么写博客</h2><p>博客大牛们大都借助一些语言、工具,写出清洁、易读的文章</p>\n<ul>\n<li>markdown <a href=\"https://www.appinn.com/markdown\" target=\"_blank\" rel=\"noopener\">点我学习语法</a>;省去排版的烦恼,重点回归到文字本身;可以用工具效率更高<ul>\n<li>MarkdownPad 2</li>\n<li>atom(强烈建议使用,基于markdown,尝试用了很多工具,这个是我最爱的)</li>\n<li><a href=\"https://geekplux.com/markdown-editor/\" target=\"_blank\" rel=\"noopener\">geekplux</a></li>\n<li><a href=\"https://www.zybuluo.com/mdeditor\" target=\"_blank\" rel=\"noopener\">mdeditor</a></li>\n</ul>\n</li>\n</ul>\n<ul>\n<li>org-mode</li>\n</ul>\n<h2 id=\"推荐有意思的博客和网站\"><a href=\"#推荐有意思的博客和网站\" class=\"headerlink\" title=\"推荐有意思的博客和网站\"></a>推荐有意思的博客和网站</h2><ul>\n<li><a href=\"http://mindhacks.cn/\" target=\"_blank\" rel=\"noopener\">http://mindhacks.cn/</a></li>\n<li><a href=\"https://geekplux.com/\" target=\"_blank\" rel=\"noopener\">https://geekplux.com/</a></li>\n<li><a href=\"https://www.v2ex.com/?r=s284745061\" target=\"_blank\" rel=\"noopener\">https://www.v2ex.com/?r=s284745061</a></li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"为什么要写自己的博客\"><a href=\"#为什么要写自己的博客\" class=\"headerlink\" title=\"为什么要写自己的博客\"></a>为什么要写自己的博客</h2><p>我一直是一个不爱写作的人,也是不太擅长写作的人,直到我看到一篇博文<a href=\"http://mindhacks.cn/2009/02/15/why-you-should-start-blogging-now/\" target=\"_blank\" rel=\"noopener\">【为什么你应该(从现在开始就)写博客】</a>,受益匪浅,建议大家看一下,从中找到灵感,里面有句话我比较认同:用博客的形式来记录下你有价值的思考,会带来很多好处,却没有任何明显的坏处。闲来无事不知道要做什么的时候,就多去看看同行的博客,会带来意想不到的效果。<br><br></p>\n<p>其实本人打算写博客的初衷是单纯记录用过的技术、方案,便于后期忘记了再从头找资料,用博客记录下来即便是忘了再回来看的时候也能快速的回忆起来,毕竟自己写过的东西印象才最深刻。当然这是初衷,现在看来博客的用处远不止这些,看过那些大牛的博客后得到些感触,写出有价值的文章、写出自己独立的思考、提高个人影响力(当然要基于你有价值的博文,很难,厚积薄发也不是不可能),努力最终都会有回报,等N年后你会感谢自己曾经的努力。<br><br></p>\n<p>刚开始写博客最大的阻力是不知道怎么写,虽然我现在也不知道怎么写出有价值的博文,但不管成与败,首先得迈出第一步,然后做一个爱思考、爱总结的人。</p>\n<h2 id=\"怎样搭建自己的博客\"><a href=\"#怎样搭建自己的博客\" class=\"headerlink\" title=\"怎样搭建自己的博客\"></a>怎样搭建自己的博客</h2><p>建议使用很火的开源工具hexo,比较热门的主题next, 使用的主题来源于geekplux,感谢!具体的搭建方法,网上教程有很多,我懒,不再赘述</p>\n<h2 id=\"怎么写博客\"><a href=\"#怎么写博客\" class=\"headerlink\" title=\"怎么写博客\"></a>怎么写博客</h2><p>博客大牛们大都借助一些语言、工具,写出清洁、易读的文章</p>\n<ul>\n<li>markdown <a href=\"https://www.appinn.com/markdown\" target=\"_blank\" rel=\"noopener\">点我学习语法</a>;省去排版的烦恼,重点回归到文字本身;可以用工具效率更高<ul>\n<li>MarkdownPad 2</li>\n<li>atom(强烈建议使用,基于markdown,尝试用了很多工具,这个是我最爱的)</li>\n<li><a href=\"https://geekplux.com/markdown-editor/\" target=\"_blank\" rel=\"noopener\">geekplux</a></li>\n<li><a href=\"https://www.zybuluo.com/mdeditor\" target=\"_blank\" rel=\"noopener\">mdeditor</a></li>\n</ul>\n</li>\n</ul>\n<ul>\n<li>org-mode</li>\n</ul>\n<h2 id=\"推荐有意思的博客和网站\"><a href=\"#推荐有意思的博客和网站\" class=\"headerlink\" title=\"推荐有意思的博客和网站\"></a>推荐有意思的博客和网站</h2><ul>\n<li><a href=\"http://mindhacks.cn/\" target=\"_blank\" rel=\"noopener\">http://mindhacks.cn/</a></li>\n<li><a href=\"https://geekplux.com/\" target=\"_blank\" rel=\"noopener\">https://geekplux.com/</a></li>\n<li><a href=\"https://www.v2ex.com/?r=s284745061\" target=\"_blank\" rel=\"noopener\">https://www.v2ex.com/?r=s284745061</a></li>\n</ul>\n"},{"title":"关于商业保险","date":"2018-07-09T10:33:28.000Z","_content":"## 关于商业保险\n最近新上映的电影《我不是药神》很火,v2ex上有人发起了关于商业保险怎么买的话题,引来了各路大神pk,mark下,商业保险应该买,但不能盲目买,尤其是国内保险公司的各种套路,买之前仔细看合同。\n\n[看了《我不是药神》感触特别大,那么有推荐的商业重大疾病保险吗](https://www.v2ex.com/t/468947#reply78)","source":"_posts/关于商业保险.md","raw":"---\ntitle: 关于商业保险\ndate: 2018-07-09 18:33:28\ntags: 杂谈\n---\n## 关于商业保险\n最近新上映的电影《我不是药神》很火,v2ex上有人发起了关于商业保险怎么买的话题,引来了各路大神pk,mark下,商业保险应该买,但不能盲目买,尤其是国内保险公司的各种套路,买之前仔细看合同。\n\n[看了《我不是药神》感触特别大,那么有推荐的商业重大疾病保险吗](https://www.v2ex.com/t/468947#reply78)","slug":"关于商业保险","published":1,"updated":"2018-07-09T10:52:25.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjk0gge0m000250klen530dcn","content":"<h2 id=\"关于商业保险\"><a href=\"#关于商业保险\" class=\"headerlink\" title=\"关于商业保险\"></a>关于商业保险</h2><p>最近新上映的电影《我不是药神》很火,v2ex上有人发起了关于商业保险怎么买的话题,引来了各路大神pk,mark下,商业保险应该买,但不能盲目买,尤其是国内保险公司的各种套路,买之前仔细看合同。</p>\n<p><a href=\"https://www.v2ex.com/t/468947#reply78\" target=\"_blank\" rel=\"noopener\">看了《我不是药神》感触特别大,那么有推荐的商业重大疾病保险吗</a></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"关于商业保险\"><a href=\"#关于商业保险\" class=\"headerlink\" title=\"关于商业保险\"></a>关于商业保险</h2><p>最近新上映的电影《我不是药神》很火,v2ex上有人发起了关于商业保险怎么买的话题,引来了各路大神pk,mark下,商业保险应该买,但不能盲目买,尤其是国内保险公司的各种套路,买之前仔细看合同。</p>\n<p><a href=\"https://www.v2ex.com/t/468947#reply78\" target=\"_blank\" rel=\"noopener\">看了《我不是药神》感触特别大,那么有推荐的商业重大疾病保险吗</a></p>\n"},{"title":"推荐一个好用的录制gif程序","date":"2018-07-23T03:06:28.000Z","_content":"最近发现一个比较好用的gif录制软件,支持mac和windows,而且还是免费的,地址:[https://www.cockos.com/licecap/](https://www.cockos.com/licecap/)\n## 安装方法\n![](推荐一个好用的录制gif程序/img1.jpg)\n\n如上图,下载相应系统的安装包,另外mac下可以使用homebrew命令来安装,非常方便\n\n\tbrew cask install LICEcap\n\t\n## 使用方法\n![](推荐一个好用的录制gif程序/img2.jpg)\n左边可以调节截屏框大小,右边是开始、暂停和结束按钮,结束后保存在本地,mac下右击使用浏览器打开,preview不能打开gif文件\n\n## 效果展示\n![](推荐一个好用的录制gif程序/giftest.gif)\n","source":"_posts/推荐一个好用的录制gif程序.md","raw":"---\ntitle: 推荐一个好用的录制gif程序\ndate: 2018-07-23 11:06:28\ntags: 杂谈\n---\n最近发现一个比较好用的gif录制软件,支持mac和windows,而且还是免费的,地址:[https://www.cockos.com/licecap/](https://www.cockos.com/licecap/)\n## 安装方法\n![](推荐一个好用的录制gif程序/img1.jpg)\n\n如上图,下载相应系统的安装包,另外mac下可以使用homebrew命令来安装,非常方便\n\n\tbrew cask install LICEcap\n\t\n## 使用方法\n![](推荐一个好用的录制gif程序/img2.jpg)\n左边可以调节截屏框大小,右边是开始、暂停和结束按钮,结束后保存在本地,mac下右击使用浏览器打开,preview不能打开gif文件\n\n## 效果展示\n![](推荐一个好用的录制gif程序/giftest.gif)\n","slug":"推荐一个好用的录制gif程序","published":1,"updated":"2018-07-23T05:43:46.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjk0gge0s000450klcivntlka","content":"<p>最近发现一个比较好用的gif录制软件,支持mac和windows,而且还是免费的,地址:<a href=\"https://www.cockos.com/licecap/\" target=\"_blank\" rel=\"noopener\">https://www.cockos.com/licecap/</a></p>\n<h2 id=\"安装方法\"><a href=\"#安装方法\" class=\"headerlink\" title=\"安装方法\"></a>安装方法</h2><p><img src=\"/2018/07/23/推荐一个好用的录制gif程序/img1.jpg\" alt=\"\"></p>\n<p>如上图,下载相应系统的安装包,另外mac下可以使用homebrew命令来安装,非常方便</p>\n<pre><code>brew cask install LICEcap\n</code></pre><h2 id=\"使用方法\"><a href=\"#使用方法\" class=\"headerlink\" title=\"使用方法\"></a>使用方法</h2><p><img src=\"/2018/07/23/推荐一个好用的录制gif程序/img2.jpg\" alt=\"\"><br>左边可以调节截屏框大小,右边是开始、暂停和结束按钮,结束后保存在本地,mac下右击使用浏览器打开,preview不能打开gif文件</p>\n<h2 id=\"效果展示\"><a href=\"#效果展示\" class=\"headerlink\" title=\"效果展示\"></a>效果展示</h2><p><img src=\"/2018/07/23/推荐一个好用的录制gif程序/giftest.gif\" alt=\"\"></p>\n","site":{"data":{}},"excerpt":"","more":"<p>最近发现一个比较好用的gif录制软件,支持mac和windows,而且还是免费的,地址:<a href=\"https://www.cockos.com/licecap/\" target=\"_blank\" rel=\"noopener\">https://www.cockos.com/licecap/</a></p>\n<h2 id=\"安装方法\"><a href=\"#安装方法\" class=\"headerlink\" title=\"安装方法\"></a>安装方法</h2><p><img src=\"/2018/07/23/推荐一个好用的录制gif程序/img1.jpg\" alt=\"\"></p>\n<p>如上图,下载相应系统的安装包,另外mac下可以使用homebrew命令来安装,非常方便</p>\n<pre><code>brew cask install LICEcap\n</code></pre><h2 id=\"使用方法\"><a href=\"#使用方法\" class=\"headerlink\" title=\"使用方法\"></a>使用方法</h2><p><img src=\"/2018/07/23/推荐一个好用的录制gif程序/img2.jpg\" alt=\"\"><br>左边可以调节截屏框大小,右边是开始、暂停和结束按钮,结束后保存在本地,mac下右击使用浏览器打开,preview不能打开gif文件</p>\n<h2 id=\"效果展示\"><a href=\"#效果展示\" class=\"headerlink\" title=\"效果展示\"></a>效果展示</h2><p><img src=\"/2018/07/23/推荐一个好用的录制gif程序/giftest.gif\" alt=\"\"></p>\n"},{"title":"mac下使用 Thrift java","date":"2017-07-17T02:33:28.000Z","_content":"# 简介\nThrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Go,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器。thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。<br>\n本文主要介绍 Thrift 开发流程,并给出 Java 开发 Thrfit 应用的实例。\n\n本文的开发环境为: macOS Sierra 10.12.6\n\n# Thrift开发概述\nThrift用接口描述语言(Interface description language,IDL)来描述不同编程语言之间的接口。Thrift开发环境包含两个部分:Thrift编译器和语言相关的库。Thrift编译器用来根据IDL生成语言相关的接口代码框架,我们可以使用这个框架很方便的实现客户端和服务器的代码。语言相关的库则封装了不同编程语言之间通信的内部实现,让我们解放双手着重处理业务逻辑。根据编程语言的不同,构建相关库的方法也不同。\n\n## 开发前的准备\n* 在[Thrift官方下载页面](http://thrift.apache.org/download)下载Thrift编译器,如果希望从源代码编译Thrift编译器,则跳过这一步。官网只提供了windows下的编译器,thrift-0.10.0.exe,使用非windows跳过此步骤,mac系统请参考[Mac下安装Thrift](#Mac下安装Thrift)。\n* 在[Thrift官方下载页面](http://thrift.apache.org/download)下载Thrift源代码。源代码中包含了编译器的代码和语言相关的库的代码。本例下载的源代码为:thrift-0.10.0.tar.gz 。下载后解压到合适的目录。如果希望从源代码编译Thrift编译器,请参阅Thrift源代码根目录下的README.md。[官网教程 Building from source](http://thrift.apache.org/docs/BuildingFromSource)\n* 构建语言相关的库(如果需要的话)。\n\n<span id=\"Mac下安装Thrift\"></span>\n## Mac下安装Thrift\n在mac下安装软件跟Linux安装比较类似,在安装Thrift之前需要先安装依赖。\n### 安装BOOST\n下载:[http://www.boost.org/](http://www.boost.org/) (boost_1_57_0.tar.gz)<br>\n拷贝到/usr/local目录下并解压:\n\n\ttar -zvxf boost_1_57_0.tar.gz\n切换目录:\n\n\tcd boost_1_57_0\n执行命令:\n\n\t./bootstrap.sh —prefix=PATH_TO_BOOST \n\tsudo ./b2 threading=multi address-model=64 variant=release stage install\n\t\n./bootstrap.sh该命令用于生成bjam可执行文件,这个东西就是用来编译boost库<br>\n\n### 安装 libevent\n下载:[http://libevent.org/](http://libevent.org/) (libevent-2.0.21-stable.tar.gz)\n\n拷贝到/usr/local目录下并解压:\n\n\ttar -zvxf libevent-2.0.21-stable.tar.gz \n\n切换目录:\n\n\tcd libevent-2.0.21-stable \n\n执行命令:\n\n\t./configure —-prefix=/usr/local \n\tmake \n\tsudo make install \n\t\n执行make时报如下错误,需要安装openssl; 这是由于mac默认安装了openssl但是没有安装对应的include头文件和lib库,故这里使用homebrew(参考https://brew.sh/index_zh-cn.html)来安装最新的openssl\n\n\tfatal error: 'openssl/bio.h' file not found\n使用homebrew 安装\n\n\tbrew install openssl\n安装后,连接到libevent目录下\n\n\tln -s /usr/local/Cellar/openssl/1.0.2o_2/include/openssl /usr/local/libevent-2.1.8-stable/include\n\t\n成功后再执行 make和sudo make install命令就不报错了\n\n### 安装 Apache Thrift\n下载:[http://thrift.apache.org/](http://thrift.apache.org/) (thrift-0.8.0.tar.gz)\n\n解压:\n\n\ttar -zvxf thrift-0.8.0.tar.gz\n\n切换目录:\n\n\tcd thrift-0.8.0.tar.gz \n\n编译命令:\n\n\t./configure --prefix=/usr/local/ --with-boost=/usr/local --with-libevent=/usr/local\n\n安装命令:\n\n\tsudo make install\n\n可以查看安装是否成功和版本\n\n\tthrift -version\n\n注意版本选择:选择Thrift 0.8.0版本,选择高的版本会报bison版本低的错误,在安装0.8.0时也报了一些错误,不过不影响正常使用\n\n最新版0.11.0 在mac中如果用上面步骤安装不成功,可以使用如下方式安装\n\n\tbrew install thrift\n\n## 开发流程\n* 使用IDL定义服务器和客户端之间的接口。利用Thrift编译器编译该IDL文件,生成语言相关的代码框架。\n* 利用已经生成的代码框架,实现客户端和服务器的业务逻辑。\n\n## 构建语言相关的库\n语言相关的库代码在Thrift源代码的lib下,每种语言一个目录,比如C++就在cpp目录下。在每种语言的目录下,都有一个README.md用来描述该语言库的构建和使用方法。语言相关的库根据编程语言的不同,构建的方式也不同。如果是编译型语言的话,则需要编译。本篇只提供java案例\n\n<span id=\"构建Java库\"></span>\n## 构建Java库\n本例构建环境:<br>\n\n\tjava version \"1.8.0_131\"\n\tApache Ant(TM) version 1.10.5\n\n在编译之前请确保正确安装和配置了 JDK 和 Ant。\n\nJava库源代码目录为:[Thrift源代码目录]\\lib\\java。Java库需要使用Ant 来编译。管理员方式打开命令行,切换到Java库元源代码目录,执行:<br>\n\n>ant\n\n编译后会在 build 子目录下找到 libthrift-0.10.0.jar,这就是我们需要的开发包。在 build/lib 下是 libthrift-0.10.0.jar 的依赖包。\n\n# 使用IDL定义接口\nThrift 中 IDL 文件以 .thrift 为后缀。该文件用来描述服务器与客户端之间的接口。在编写 thrift 文件之前,还需要了解一下用以描述接口的语法。\n## 注释\nThrift 支持三种注释:<br>\n脚本注释,用 # 表示,例如:<br>\n>\\#这是一个注释\n\n块注释,用 /* 和 */ 表示。<br>\n>\n/*<br>\n * 这是一个注释<br>\n */<br>\n\n\n单行注释,用 // 表示。<br>\n\n>// 这是一个注释\n\n## 基本类型\n| 类型\t| 描述\n| :--------: | :------:\n| bool\t| 布尔类型,1byte\n| i8\t| 有符号整形,8bits,即byte\n| i16\t| 有符号整型,16bits\n| i32\t| 有符号整型,32bits\n| i64\t| 有符号整型,64bits\n| double\t| 浮点型,64bits\n| string\t| 字符串\n| binary\t| Blob,byte数组\n| map<t1,t2>\t| map\n| list<t1>\t| 有序列表\n| set<t1>\t| 无重复元素的容器\n## 常量\n常量用const表示:\n\n\tconst i32 MATHPATH = 256\n\n## 枚举\n用 enum 定义枚举。枚举类型是32位的整数。值是可选的,从1开始。\n\n\tenum Operation {\n\t ADD = 1,\n\t SUBTRACT = 2,\n\t MULTIPLY = 3,\n\t DIVIDE = 4\n\t}\n\n## 结构体\n即java中的bean, 结构体用 struct 表示,是基本的复合数据类型,由若干字段组成。每个字段由整型ID,类型,名称和可选的默认值组成。字段可以声明为 optional,表示如果没有被设置,则不进行序列化。\n\n\tstruct Work {\n\t 1: i32 num1 = 0,\n\t 2: i32 num2,\n\t 3: Operation op,\n\t 4: optional string comment,\n\t}\n\n结构体也可以定义为异常:\n\n\texception InvalidOperation {\n\t 1: i32 whatOp,\n\t 2: string why\n\t}\n\t\n## 服务\n服务类似 class, 用 service 关键字定义。服务可以用 extends 关键字继承其他服务。service 由一系列方法组成。方法由返回值,参数列表和一个可选的异常列表组成。参数列表和异常列表的语法和结构体的语法一样。\n\n\tservice Calculator extends shared.SharedService {\n\t\n\t void ping(),\n\t\n\t i32 add(1:i32 num1, 2:i32 num2),\n\t\n\t i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),\n\t\n\t /**\n\t * oneway 表示客户端发送请求后不需要响应。onway 方法返回值必须是void \n\t */\n\t oneway void zip()\n\t\n\t}\n\t\n## include 指令\n用 include 指令包含其他 thrift 文件:\n\n\tinclude \"another.thrift\"\n\n## namespace 指令\nnamespace 指令指定语言相关的名称空间:\n\n\tnamespace cpp nscpp # 指定C++的名称空间为 nscpp\n\tnamespace java nsjava # 指定Java的包为 nsjava\n\n## typedef 指令\ntypedef 指令用来指定类型别名,和 C 一样。\n\n\ttypedef i32 MyInteger\n\n# 编译IDL文件\nThrift 编译器的用法如下:\n\n\tthrift [options] file\n\n可以通过 –help 选项来了解具体用法:\n\n\tthrift --help\n\n通常用以下命令将IDL编译成语言相关的接口代码,-r(recurse的首字母)表示递归生成被包含的文件,--gen后面接生成的语言。\n\n\tthrift-0.10.0.exe -r --gen java ICalc.thrift\n\t\n# 实例详解\n下面分别给出 JAVA开发 Thrift 应用的实例。需要注意的是某种语言开发的服务器和任何语言开发的客户端都可以实现互联,这正是 Thrift 的特性之一。\n\n## Java开发实例\n本例开发环境:\n\n\tjava version \"1.8.0_131\"\n\tApache Ant(TM) version 1.10.1\n\n在开发之前应确保 Java 的 Thrift 包已经编译好,如果还没有编译好,请参见[构建Java库](#构建Java库)。\n\n首先建立如下所示的目录结构。其中 com/cynhard/thrift/test 是包的路径,可以根据自己的域名进行调整。iface, server, client三个目录分别用来存放接口,服务器,客户端的代码。build.xml是Ant构建文件。\n\t\n\t[somewhere]\n\t |-calc/\n\t |-com/\n\t | |-cynhard/\n\t | |-thrift/\n\t | |-test/\n\t | |-iface/ -- 接口文件目录\n\t | | |-ICalc.thrift -- 接口文件\n\t | |-server/ -- 服务器目录\n\t | | |-Server.java -- 服务器实现文件\n\t | |-client/ -- 客户端目录\n\t | |-Client.java -- 客户端实现文件\n\t |-build.xml -- ant 文件\n\t \n## 定义接口\n打开 ICalc.thrift 文件,编写接口代码如下。注意包名应该根据自己的实际路径调整。\n\nICalc.thrift\n\n\tnamespace java com.cynhard.thrift.test.iface\n\t\n\tservice ICalc {\n\t i32 add(1:i32 num1, 2:i32 num2),\n\t}\n## 实现服务器\n打开 Server.java,编写服务器代码如下。注意包名应该根据自己的实际路径调整。\n\nServer.java\n\tpackage com.cynhard.thrift.test.server;\n\t\n\timport org.apache.thrift.TException;\n\timport org.apache.thrift.server.TServer;\n\timport org.apache.thrift.server.TServer.Args;\n\timport org.apache.thrift.server.TSimpleServer;\n\timport org.apache.thrift.transport.TServerSocket;\n\timport org.apache.thrift.transport.TServerTransport;\n\timport com.cynhard.thrift.test.iface.ICalc;\n\t\n\tpublic class Server {\n\t\n\t static class CalcHandler implements ICalc.Iface {\n\t @Override\n\t public int add(int num1, int num2) throws TException {\n\t return num1 + num2;\n\t }\n\t }\n\t\n\t public static void main(String[] args) {\n\t try {\n\t CalcHandler handler = new CalcHandler();\n\t ICalc.Processor processor = new ICalc.Processor(handler);\n\t TServerTransport serverTransport = new TServerSocket(9090);\n\t TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));\n\t\n\t System.out.println(\"Starting the server...\");\n\t server.serve(); \n\t } catch (Exception e) { \n\t e.printStackTrace(); \n\t } \n\t }\n\t}\n## 实现客户端\t\n打开 Client.java,编写客户端代码如下。注意包名应该根据自己的实际路径调整。\n\nClient.java\n\n\tpackage com.cynhard.thrift.test.client;\n\t\n\timport org.apache.thrift.TException;\n\timport org.apache.thrift.transport.TTransport;\n\timport org.apache.thrift.transport.TSocket;\n\timport org.apache.thrift.protocol.TBinaryProtocol;\n\timport org.apache.thrift.protocol.TProtocol;\n\timport com.cynhard.thrift.test.iface.ICalc;\n\t\n\tpublic class Client {\n\t public static void main(String[] args) {\n\t try {\n\t TTransport transport = new TSocket(\"localhost\", 9090);\n\t transport.open();\n\t\n\t TProtocol protocol = new TBinaryProtocol(transport);\n\t ICalc.Client client = new ICalc.Client(protocol);\n\t System.out.println(client.add(1, 2));\n\t\n\t transport.close();\n\t } catch (TException e) {\n\t e.printStackTrace();\n\t }\n\t }\n\t}\n\t\n## 构建工程\n打开 build.xml,编写构建配置如下。注意路径属性需要根据实际路径进行修改。\n\nbuild.xml\n\n\t<?xml version=\"1.0\"?>\n\t<project name=\"calc\" basedir=\".\" default=\"build\">\n\n <property name=\"thrift.lib.dir\" value=\"/Users/zhouguangsheng/project/study/Thrift/thrift-0.11.0/lib/java/build\"/>\n <property name=\"thrift.compiler.dir\" value=\"/Users/zhouguangsheng/project/study/Thrift/thrift-0.11.0/lib/java/build\"/>\n <property name=\"interface.dir\" value=\"${basedir}\\com\\cynhard\\thrift\\test\\iface\"/>\n\n <path id=\"master-classpath\">\n <fileset dir=\"${thrift.lib.dir}\">\n <include name=\"**\\*.jar\"/>\n </fileset>\n <pathelement path=\".\"/>\n </path>\n\n <target name=\"build\" description=\"Compile Calc\">\n \t<!-- 如果单独编译thrift文件,注释下面exec这段 -->\n <exec executable=\"${thrift.compiler.dir}/libthrift-0.11.0.jar\">\n <arg line=\"--gen java -out ${basedir} ${interface.dir}\\ICalc.thrift\"/>\n </exec>\n <javac>\n <src path=\".\"/>\n <classpath refid=\"master-classpath\"/>\n </javac>\n </target>\n\n <target name=\"run_server\" description=\"Run server\">\n <java fork=\"true\" failonerror=\"yes\" classname=\"com.zgs.thrift.test.server.Server\">\n <classpath refid=\"master-classpath\"/>\n </java>\n </target>\n\n <target name=\"run_client\" description=\"Run client\">\n <java fork=\"true\" failonerror=\"yes\" classname=\"com.zgs.thrift.test.client.Client\">\n <classpath refid=\"master-classpath\"/>\n </java>\n </target>\n\n\t</project>\n\n上面的工作完成后,就可以开始构建工程了。以管理员权限打开命令提示符,切换到 项目根目录。执行以下命令编译工程:\n\n\tant build\n\t\n直接编译可能会不成功,thrift文件也可以单独编译,ant build.xml文件中移除,只编译java\n\n\tthrift -gen java -out /Users/zhouguangsheng/project/study/Thrift/thriftDemo/ /Users/zhouguangsheng/project/study/Thrift/thriftDemo/com/zgs/thrift/test/iface/ICalc.thrift\n-out参数为编译的java文件要存放的路径\n\t\n编译成功后,服务器和客户端相应的class文件就生成在了相应的目录中。下面就可以开始测试了。\n\n## 测试\n执行以下命令运行服务器。\n\n\tant run_server\n\n输出结果如下,可以看到输出了 Starting the server...,表明服务器已经启动。\n\n\tBuildfile: G:\\projects\\java\\calc\\build.xml\n\t\n\trun_server:\n\t [java] Starting the server...\n\n因为服务器在一个单独的窗口运行,为了测试客户端,需要打开另一个命令提示符,同样切换到 calc 目录。执行以下命令运行客户端:\n\n\tant run_client\n\n输出结果如下,可以看到返回了正确的结果:3 。\n\n\tBuildfile: G:\\projects\\java\\calc\\build.xml\n\t\n\trun_client:\n\t [java] Received 1\n\t [java] 3\n\t\n\tBUILD SUCCESSFUL\n\tTotal time: 0 seconds","source":"_posts/mac下实现Thrift java.md","raw":"---\ntitle: mac下使用 Thrift java\ndate: 2017-07-17 10:33:28\ntags: 技术,thrift\n---\n# 简介\nThrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Go,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器。thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。<br>\n本文主要介绍 Thrift 开发流程,并给出 Java 开发 Thrfit 应用的实例。\n\n本文的开发环境为: macOS Sierra 10.12.6\n\n# Thrift开发概述\nThrift用接口描述语言(Interface description language,IDL)来描述不同编程语言之间的接口。Thrift开发环境包含两个部分:Thrift编译器和语言相关的库。Thrift编译器用来根据IDL生成语言相关的接口代码框架,我们可以使用这个框架很方便的实现客户端和服务器的代码。语言相关的库则封装了不同编程语言之间通信的内部实现,让我们解放双手着重处理业务逻辑。根据编程语言的不同,构建相关库的方法也不同。\n\n## 开发前的准备\n* 在[Thrift官方下载页面](http://thrift.apache.org/download)下载Thrift编译器,如果希望从源代码编译Thrift编译器,则跳过这一步。官网只提供了windows下的编译器,thrift-0.10.0.exe,使用非windows跳过此步骤,mac系统请参考[Mac下安装Thrift](#Mac下安装Thrift)。\n* 在[Thrift官方下载页面](http://thrift.apache.org/download)下载Thrift源代码。源代码中包含了编译器的代码和语言相关的库的代码。本例下载的源代码为:thrift-0.10.0.tar.gz 。下载后解压到合适的目录。如果希望从源代码编译Thrift编译器,请参阅Thrift源代码根目录下的README.md。[官网教程 Building from source](http://thrift.apache.org/docs/BuildingFromSource)\n* 构建语言相关的库(如果需要的话)。\n\n<span id=\"Mac下安装Thrift\"></span>\n## Mac下安装Thrift\n在mac下安装软件跟Linux安装比较类似,在安装Thrift之前需要先安装依赖。\n### 安装BOOST\n下载:[http://www.boost.org/](http://www.boost.org/) (boost_1_57_0.tar.gz)<br>\n拷贝到/usr/local目录下并解压:\n\n\ttar -zvxf boost_1_57_0.tar.gz\n切换目录:\n\n\tcd boost_1_57_0\n执行命令:\n\n\t./bootstrap.sh —prefix=PATH_TO_BOOST \n\tsudo ./b2 threading=multi address-model=64 variant=release stage install\n\t\n./bootstrap.sh该命令用于生成bjam可执行文件,这个东西就是用来编译boost库<br>\n\n### 安装 libevent\n下载:[http://libevent.org/](http://libevent.org/) (libevent-2.0.21-stable.tar.gz)\n\n拷贝到/usr/local目录下并解压:\n\n\ttar -zvxf libevent-2.0.21-stable.tar.gz \n\n切换目录:\n\n\tcd libevent-2.0.21-stable \n\n执行命令:\n\n\t./configure —-prefix=/usr/local \n\tmake \n\tsudo make install \n\t\n执行make时报如下错误,需要安装openssl; 这是由于mac默认安装了openssl但是没有安装对应的include头文件和lib库,故这里使用homebrew(参考https://brew.sh/index_zh-cn.html)来安装最新的openssl\n\n\tfatal error: 'openssl/bio.h' file not found\n使用homebrew 安装\n\n\tbrew install openssl\n安装后,连接到libevent目录下\n\n\tln -s /usr/local/Cellar/openssl/1.0.2o_2/include/openssl /usr/local/libevent-2.1.8-stable/include\n\t\n成功后再执行 make和sudo make install命令就不报错了\n\n### 安装 Apache Thrift\n下载:[http://thrift.apache.org/](http://thrift.apache.org/) (thrift-0.8.0.tar.gz)\n\n解压:\n\n\ttar -zvxf thrift-0.8.0.tar.gz\n\n切换目录:\n\n\tcd thrift-0.8.0.tar.gz \n\n编译命令:\n\n\t./configure --prefix=/usr/local/ --with-boost=/usr/local --with-libevent=/usr/local\n\n安装命令:\n\n\tsudo make install\n\n可以查看安装是否成功和版本\n\n\tthrift -version\n\n注意版本选择:选择Thrift 0.8.0版本,选择高的版本会报bison版本低的错误,在安装0.8.0时也报了一些错误,不过不影响正常使用\n\n最新版0.11.0 在mac中如果用上面步骤安装不成功,可以使用如下方式安装\n\n\tbrew install thrift\n\n## 开发流程\n* 使用IDL定义服务器和客户端之间的接口。利用Thrift编译器编译该IDL文件,生成语言相关的代码框架。\n* 利用已经生成的代码框架,实现客户端和服务器的业务逻辑。\n\n## 构建语言相关的库\n语言相关的库代码在Thrift源代码的lib下,每种语言一个目录,比如C++就在cpp目录下。在每种语言的目录下,都有一个README.md用来描述该语言库的构建和使用方法。语言相关的库根据编程语言的不同,构建的方式也不同。如果是编译型语言的话,则需要编译。本篇只提供java案例\n\n<span id=\"构建Java库\"></span>\n## 构建Java库\n本例构建环境:<br>\n\n\tjava version \"1.8.0_131\"\n\tApache Ant(TM) version 1.10.5\n\n在编译之前请确保正确安装和配置了 JDK 和 Ant。\n\nJava库源代码目录为:[Thrift源代码目录]\\lib\\java。Java库需要使用Ant 来编译。管理员方式打开命令行,切换到Java库元源代码目录,执行:<br>\n\n>ant\n\n编译后会在 build 子目录下找到 libthrift-0.10.0.jar,这就是我们需要的开发包。在 build/lib 下是 libthrift-0.10.0.jar 的依赖包。\n\n# 使用IDL定义接口\nThrift 中 IDL 文件以 .thrift 为后缀。该文件用来描述服务器与客户端之间的接口。在编写 thrift 文件之前,还需要了解一下用以描述接口的语法。\n## 注释\nThrift 支持三种注释:<br>\n脚本注释,用 # 表示,例如:<br>\n>\\#这是一个注释\n\n块注释,用 /* 和 */ 表示。<br>\n>\n/*<br>\n * 这是一个注释<br>\n */<br>\n\n\n单行注释,用 // 表示。<br>\n\n>// 这是一个注释\n\n## 基本类型\n| 类型\t| 描述\n| :--------: | :------:\n| bool\t| 布尔类型,1byte\n| i8\t| 有符号整形,8bits,即byte\n| i16\t| 有符号整型,16bits\n| i32\t| 有符号整型,32bits\n| i64\t| 有符号整型,64bits\n| double\t| 浮点型,64bits\n| string\t| 字符串\n| binary\t| Blob,byte数组\n| map<t1,t2>\t| map\n| list<t1>\t| 有序列表\n| set<t1>\t| 无重复元素的容器\n## 常量\n常量用const表示:\n\n\tconst i32 MATHPATH = 256\n\n## 枚举\n用 enum 定义枚举。枚举类型是32位的整数。值是可选的,从1开始。\n\n\tenum Operation {\n\t ADD = 1,\n\t SUBTRACT = 2,\n\t MULTIPLY = 3,\n\t DIVIDE = 4\n\t}\n\n## 结构体\n即java中的bean, 结构体用 struct 表示,是基本的复合数据类型,由若干字段组成。每个字段由整型ID,类型,名称和可选的默认值组成。字段可以声明为 optional,表示如果没有被设置,则不进行序列化。\n\n\tstruct Work {\n\t 1: i32 num1 = 0,\n\t 2: i32 num2,\n\t 3: Operation op,\n\t 4: optional string comment,\n\t}\n\n结构体也可以定义为异常:\n\n\texception InvalidOperation {\n\t 1: i32 whatOp,\n\t 2: string why\n\t}\n\t\n## 服务\n服务类似 class, 用 service 关键字定义。服务可以用 extends 关键字继承其他服务。service 由一系列方法组成。方法由返回值,参数列表和一个可选的异常列表组成。参数列表和异常列表的语法和结构体的语法一样。\n\n\tservice Calculator extends shared.SharedService {\n\t\n\t void ping(),\n\t\n\t i32 add(1:i32 num1, 2:i32 num2),\n\t\n\t i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),\n\t\n\t /**\n\t * oneway 表示客户端发送请求后不需要响应。onway 方法返回值必须是void \n\t */\n\t oneway void zip()\n\t\n\t}\n\t\n## include 指令\n用 include 指令包含其他 thrift 文件:\n\n\tinclude \"another.thrift\"\n\n## namespace 指令\nnamespace 指令指定语言相关的名称空间:\n\n\tnamespace cpp nscpp # 指定C++的名称空间为 nscpp\n\tnamespace java nsjava # 指定Java的包为 nsjava\n\n## typedef 指令\ntypedef 指令用来指定类型别名,和 C 一样。\n\n\ttypedef i32 MyInteger\n\n# 编译IDL文件\nThrift 编译器的用法如下:\n\n\tthrift [options] file\n\n可以通过 –help 选项来了解具体用法:\n\n\tthrift --help\n\n通常用以下命令将IDL编译成语言相关的接口代码,-r(recurse的首字母)表示递归生成被包含的文件,--gen后面接生成的语言。\n\n\tthrift-0.10.0.exe -r --gen java ICalc.thrift\n\t\n# 实例详解\n下面分别给出 JAVA开发 Thrift 应用的实例。需要注意的是某种语言开发的服务器和任何语言开发的客户端都可以实现互联,这正是 Thrift 的特性之一。\n\n## Java开发实例\n本例开发环境:\n\n\tjava version \"1.8.0_131\"\n\tApache Ant(TM) version 1.10.1\n\n在开发之前应确保 Java 的 Thrift 包已经编译好,如果还没有编译好,请参见[构建Java库](#构建Java库)。\n\n首先建立如下所示的目录结构。其中 com/cynhard/thrift/test 是包的路径,可以根据自己的域名进行调整。iface, server, client三个目录分别用来存放接口,服务器,客户端的代码。build.xml是Ant构建文件。\n\t\n\t[somewhere]\n\t |-calc/\n\t |-com/\n\t | |-cynhard/\n\t | |-thrift/\n\t | |-test/\n\t | |-iface/ -- 接口文件目录\n\t | | |-ICalc.thrift -- 接口文件\n\t | |-server/ -- 服务器目录\n\t | | |-Server.java -- 服务器实现文件\n\t | |-client/ -- 客户端目录\n\t | |-Client.java -- 客户端实现文件\n\t |-build.xml -- ant 文件\n\t \n## 定义接口\n打开 ICalc.thrift 文件,编写接口代码如下。注意包名应该根据自己的实际路径调整。\n\nICalc.thrift\n\n\tnamespace java com.cynhard.thrift.test.iface\n\t\n\tservice ICalc {\n\t i32 add(1:i32 num1, 2:i32 num2),\n\t}\n## 实现服务器\n打开 Server.java,编写服务器代码如下。注意包名应该根据自己的实际路径调整。\n\nServer.java\n\tpackage com.cynhard.thrift.test.server;\n\t\n\timport org.apache.thrift.TException;\n\timport org.apache.thrift.server.TServer;\n\timport org.apache.thrift.server.TServer.Args;\n\timport org.apache.thrift.server.TSimpleServer;\n\timport org.apache.thrift.transport.TServerSocket;\n\timport org.apache.thrift.transport.TServerTransport;\n\timport com.cynhard.thrift.test.iface.ICalc;\n\t\n\tpublic class Server {\n\t\n\t static class CalcHandler implements ICalc.Iface {\n\t @Override\n\t public int add(int num1, int num2) throws TException {\n\t return num1 + num2;\n\t }\n\t }\n\t\n\t public static void main(String[] args) {\n\t try {\n\t CalcHandler handler = new CalcHandler();\n\t ICalc.Processor processor = new ICalc.Processor(handler);\n\t TServerTransport serverTransport = new TServerSocket(9090);\n\t TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));\n\t\n\t System.out.println(\"Starting the server...\");\n\t server.serve(); \n\t } catch (Exception e) { \n\t e.printStackTrace(); \n\t } \n\t }\n\t}\n## 实现客户端\t\n打开 Client.java,编写客户端代码如下。注意包名应该根据自己的实际路径调整。\n\nClient.java\n\n\tpackage com.cynhard.thrift.test.client;\n\t\n\timport org.apache.thrift.TException;\n\timport org.apache.thrift.transport.TTransport;\n\timport org.apache.thrift.transport.TSocket;\n\timport org.apache.thrift.protocol.TBinaryProtocol;\n\timport org.apache.thrift.protocol.TProtocol;\n\timport com.cynhard.thrift.test.iface.ICalc;\n\t\n\tpublic class Client {\n\t public static void main(String[] args) {\n\t try {\n\t TTransport transport = new TSocket(\"localhost\", 9090);\n\t transport.open();\n\t\n\t TProtocol protocol = new TBinaryProtocol(transport);\n\t ICalc.Client client = new ICalc.Client(protocol);\n\t System.out.println(client.add(1, 2));\n\t\n\t transport.close();\n\t } catch (TException e) {\n\t e.printStackTrace();\n\t }\n\t }\n\t}\n\t\n## 构建工程\n打开 build.xml,编写构建配置如下。注意路径属性需要根据实际路径进行修改。\n\nbuild.xml\n\n\t<?xml version=\"1.0\"?>\n\t<project name=\"calc\" basedir=\".\" default=\"build\">\n\n <property name=\"thrift.lib.dir\" value=\"/Users/zhouguangsheng/project/study/Thrift/thrift-0.11.0/lib/java/build\"/>\n <property name=\"thrift.compiler.dir\" value=\"/Users/zhouguangsheng/project/study/Thrift/thrift-0.11.0/lib/java/build\"/>\n <property name=\"interface.dir\" value=\"${basedir}\\com\\cynhard\\thrift\\test\\iface\"/>\n\n <path id=\"master-classpath\">\n <fileset dir=\"${thrift.lib.dir}\">\n <include name=\"**\\*.jar\"/>\n </fileset>\n <pathelement path=\".\"/>\n </path>\n\n <target name=\"build\" description=\"Compile Calc\">\n \t<!-- 如果单独编译thrift文件,注释下面exec这段 -->\n <exec executable=\"${thrift.compiler.dir}/libthrift-0.11.0.jar\">\n <arg line=\"--gen java -out ${basedir} ${interface.dir}\\ICalc.thrift\"/>\n </exec>\n <javac>\n <src path=\".\"/>\n <classpath refid=\"master-classpath\"/>\n </javac>\n </target>\n\n <target name=\"run_server\" description=\"Run server\">\n <java fork=\"true\" failonerror=\"yes\" classname=\"com.zgs.thrift.test.server.Server\">\n <classpath refid=\"master-classpath\"/>\n </java>\n </target>\n\n <target name=\"run_client\" description=\"Run client\">\n <java fork=\"true\" failonerror=\"yes\" classname=\"com.zgs.thrift.test.client.Client\">\n <classpath refid=\"master-classpath\"/>\n </java>\n </target>\n\n\t</project>\n\n上面的工作完成后,就可以开始构建工程了。以管理员权限打开命令提示符,切换到 项目根目录。执行以下命令编译工程:\n\n\tant build\n\t\n直接编译可能会不成功,thrift文件也可以单独编译,ant build.xml文件中移除,只编译java\n\n\tthrift -gen java -out /Users/zhouguangsheng/project/study/Thrift/thriftDemo/ /Users/zhouguangsheng/project/study/Thrift/thriftDemo/com/zgs/thrift/test/iface/ICalc.thrift\n-out参数为编译的java文件要存放的路径\n\t\n编译成功后,服务器和客户端相应的class文件就生成在了相应的目录中。下面就可以开始测试了。\n\n## 测试\n执行以下命令运行服务器。\n\n\tant run_server\n\n输出结果如下,可以看到输出了 Starting the server...,表明服务器已经启动。\n\n\tBuildfile: G:\\projects\\java\\calc\\build.xml\n\t\n\trun_server:\n\t [java] Starting the server...\n\n因为服务器在一个单独的窗口运行,为了测试客户端,需要打开另一个命令提示符,同样切换到 calc 目录。执行以下命令运行客户端:\n\n\tant run_client\n\n输出结果如下,可以看到返回了正确的结果:3 。\n\n\tBuildfile: G:\\projects\\java\\calc\\build.xml\n\t\n\trun_client:\n\t [java] Received 1\n\t [java] 3\n\t\n\tBUILD SUCCESSFUL\n\tTotal time: 0 seconds","slug":"mac下实现Thrift java","published":1,"updated":"2018-07-18T06:37:28.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjk0gge1d000a50kl6a40om8b","content":"<h1 id=\"简介\"><a href=\"#简介\" class=\"headerlink\" title=\"简介\"></a>简介</h1><p>Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Go,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器。thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。<br><br>本文主要介绍 Thrift 开发流程,并给出 Java 开发 Thrfit 应用的实例。</p>\n<p>本文的开发环境为: macOS Sierra 10.12.6</p>\n<h1 id=\"Thrift开发概述\"><a href=\"#Thrift开发概述\" class=\"headerlink\" title=\"Thrift开发概述\"></a>Thrift开发概述</h1><p>Thrift用接口描述语言(Interface description language,IDL)来描述不同编程语言之间的接口。Thrift开发环境包含两个部分:Thrift编译器和语言相关的库。Thrift编译器用来根据IDL生成语言相关的接口代码框架,我们可以使用这个框架很方便的实现客户端和服务器的代码。语言相关的库则封装了不同编程语言之间通信的内部实现,让我们解放双手着重处理业务逻辑。根据编程语言的不同,构建相关库的方法也不同。</p>\n<h2 id=\"开发前的准备\"><a href=\"#开发前的准备\" class=\"headerlink\" title=\"开发前的准备\"></a>开发前的准备</h2><ul>\n<li>在<a href=\"http://thrift.apache.org/download\" target=\"_blank\" rel=\"noopener\">Thrift官方下载页面</a>下载Thrift编译器,如果希望从源代码编译Thrift编译器,则跳过这一步。官网只提供了windows下的编译器,thrift-0.10.0.exe,使用非windows跳过此步骤,mac系统请参考<a href=\"#Mac下安装Thrift\">Mac下安装Thrift</a>。</li>\n<li>在<a href=\"http://thrift.apache.org/download\" target=\"_blank\" rel=\"noopener\">Thrift官方下载页面</a>下载Thrift源代码。源代码中包含了编译器的代码和语言相关的库的代码。本例下载的源代码为:thrift-0.10.0.tar.gz 。下载后解压到合适的目录。如果希望从源代码编译Thrift编译器,请参阅Thrift源代码根目录下的README.md。<a href=\"http://thrift.apache.org/docs/BuildingFromSource\" target=\"_blank\" rel=\"noopener\">官网教程 Building from source</a></li>\n<li>构建语言相关的库(如果需要的话)。</li>\n</ul>\n<p><span id=\"Mac下安装Thrift\"></span></p>\n<h2 id=\"Mac下安装Thrift\"><a href=\"#Mac下安装Thrift\" class=\"headerlink\" title=\"Mac下安装Thrift\"></a>Mac下安装Thrift</h2><p>在mac下安装软件跟Linux安装比较类似,在安装Thrift之前需要先安装依赖。</p>\n<h3 id=\"安装BOOST\"><a href=\"#安装BOOST\" class=\"headerlink\" title=\"安装BOOST\"></a>安装BOOST</h3><p>下载:<a href=\"http://www.boost.org/\" target=\"_blank\" rel=\"noopener\">http://www.boost.org/</a> (boost_1_57_0.tar.gz)<br><br>拷贝到/usr/local目录下并解压:</p>\n<pre><code>tar -zvxf boost_1_57_0.tar.gz\n</code></pre><p>切换目录:</p>\n<pre><code>cd boost_1_57_0\n</code></pre><p>执行命令:</p>\n<pre><code>./bootstrap.sh —prefix=PATH_TO_BOOST \nsudo ./b2 threading=multi address-model=64 variant=release stage install\n</code></pre><p>./bootstrap.sh该命令用于生成bjam可执行文件,这个东西就是用来编译boost库<br></p>\n<h3 id=\"安装-libevent\"><a href=\"#安装-libevent\" class=\"headerlink\" title=\"安装 libevent\"></a>安装 libevent</h3><p>下载:<a href=\"http://libevent.org/\" target=\"_blank\" rel=\"noopener\">http://libevent.org/</a> (libevent-2.0.21-stable.tar.gz)</p>\n<p>拷贝到/usr/local目录下并解压:</p>\n<pre><code>tar -zvxf libevent-2.0.21-stable.tar.gz \n</code></pre><p>切换目录:</p>\n<pre><code>cd libevent-2.0.21-stable \n</code></pre><p>执行命令:</p>\n<pre><code>./configure —-prefix=/usr/local \nmake \nsudo make install \n</code></pre><p>执行make时报如下错误,需要安装openssl; 这是由于mac默认安装了openssl但是没有安装对应的include头文件和lib库,故这里使用homebrew(参考<a href=\"https://brew.sh/index_zh-cn.html)来安装最新的openssl\" target=\"_blank\" rel=\"noopener\">https://brew.sh/index_zh-cn.html)来安装最新的openssl</a></p>\n<pre><code>fatal error: 'openssl/bio.h' file not found\n</code></pre><p>使用homebrew 安装</p>\n<pre><code>brew install openssl\n</code></pre><p>安装后,连接到libevent目录下</p>\n<pre><code>ln -s /usr/local/Cellar/openssl/1.0.2o_2/include/openssl /usr/local/libevent-2.1.8-stable/include\n</code></pre><p>成功后再执行 make和sudo make install命令就不报错了</p>\n<h3 id=\"安装-Apache-Thrift\"><a href=\"#安装-Apache-Thrift\" class=\"headerlink\" title=\"安装 Apache Thrift\"></a>安装 Apache Thrift</h3><p>下载:<a href=\"http://thrift.apache.org/\" target=\"_blank\" rel=\"noopener\">http://thrift.apache.org/</a> (thrift-0.8.0.tar.gz)</p>\n<p>解压:</p>\n<pre><code>tar -zvxf thrift-0.8.0.tar.gz\n</code></pre><p>切换目录:</p>\n<pre><code>cd thrift-0.8.0.tar.gz \n</code></pre><p>编译命令:</p>\n<pre><code>./configure --prefix=/usr/local/ --with-boost=/usr/local --with-libevent=/usr/local\n</code></pre><p>安装命令:</p>\n<pre><code>sudo make install\n</code></pre><p>可以查看安装是否成功和版本</p>\n<pre><code>thrift -version\n</code></pre><p>注意版本选择:选择Thrift 0.8.0版本,选择高的版本会报bison版本低的错误,在安装0.8.0时也报了一些错误,不过不影响正常使用</p>\n<p>最新版0.11.0 在mac中如果用上面步骤安装不成功,可以使用如下方式安装</p>\n<pre><code>brew install thrift\n</code></pre><h2 id=\"开发流程\"><a href=\"#开发流程\" class=\"headerlink\" title=\"开发流程\"></a>开发流程</h2><ul>\n<li>使用IDL定义服务器和客户端之间的接口。利用Thrift编译器编译该IDL文件,生成语言相关的代码框架。</li>\n<li>利用已经生成的代码框架,实现客户端和服务器的业务逻辑。</li>\n</ul>\n<h2 id=\"构建语言相关的库\"><a href=\"#构建语言相关的库\" class=\"headerlink\" title=\"构建语言相关的库\"></a>构建语言相关的库</h2><p>语言相关的库代码在Thrift源代码的lib下,每种语言一个目录,比如C++就在cpp目录下。在每种语言的目录下,都有一个README.md用来描述该语言库的构建和使用方法。语言相关的库根据编程语言的不同,构建的方式也不同。如果是编译型语言的话,则需要编译。本篇只提供java案例</p>\n<p><span id=\"构建Java库\"></span></p>\n<h2 id=\"构建Java库\"><a href=\"#构建Java库\" class=\"headerlink\" title=\"构建Java库\"></a>构建Java库</h2><p>本例构建环境:<br></p>\n<pre><code>java version "1.8.0_131"\nApache Ant(TM) version 1.10.5\n</code></pre><p>在编译之前请确保正确安装和配置了 JDK 和 Ant。</p>\n<p>Java库源代码目录为:[Thrift源代码目录]\\lib\\java。Java库需要使用Ant 来编译。管理员方式打开命令行,切换到Java库元源代码目录,执行:<br></p>\n<blockquote>\n<p>ant</p>\n</blockquote>\n<p>编译后会在 build 子目录下找到 libthrift-0.10.0.jar,这就是我们需要的开发包。在 build/lib 下是 libthrift-0.10.0.jar 的依赖包。</p>\n<h1 id=\"使用IDL定义接口\"><a href=\"#使用IDL定义接口\" class=\"headerlink\" title=\"使用IDL定义接口\"></a>使用IDL定义接口</h1><p>Thrift 中 IDL 文件以 .thrift 为后缀。该文件用来描述服务器与客户端之间的接口。在编写 thrift 文件之前,还需要了解一下用以描述接口的语法。</p>\n<h2 id=\"注释\"><a href=\"#注释\" class=\"headerlink\" title=\"注释\"></a>注释</h2><p>Thrift 支持三种注释:<br><br>脚本注释,用 # 表示,例如:<br></p>\n<blockquote>\n<p>#这是一个注释</p>\n</blockquote>\n<p>块注释,用 /<em> 和 </em>/ 表示。<br></p>\n<blockquote>\n</blockquote>\n<p>/*<br></p>\n<ul>\n<li>这是一个注释<br><br>*/<br></li>\n</ul>\n<p>单行注释,用 // 表示。<br></p>\n<blockquote>\n<p>// 这是一个注释</p>\n</blockquote>\n<h2 id=\"基本类型\"><a href=\"#基本类型\" class=\"headerlink\" title=\"基本类型\"></a>基本类型</h2><table>\n<thead>\n<tr>\n<th style=\"text-align:center\">类型</th>\n<th style=\"text-align:center\">描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\">bool</td>\n<td style=\"text-align:center\">布尔类型,1byte</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">i8</td>\n<td style=\"text-align:center\">有符号整形,8bits,即byte</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">i16</td>\n<td style=\"text-align:center\">有符号整型,16bits</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">i32</td>\n<td style=\"text-align:center\">有符号整型,32bits</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">i64</td>\n<td style=\"text-align:center\">有符号整型,64bits</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">double</td>\n<td style=\"text-align:center\">浮点型,64bits</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">string</td>\n<td style=\"text-align:center\">字符串</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">binary</td>\n<td style=\"text-align:center\">Blob,byte数组</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">map<t1,t2></td>\n<td style=\"text-align:center\">map</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">list<t1></t1></td>\n<td style=\"text-align:center\">有序列表</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">set<t1></t1></td>\n<td style=\"text-align:center\">无重复元素的容器</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"常量\"><a href=\"#常量\" class=\"headerlink\" title=\"常量\"></a>常量</h2><p>常量用const表示:</p>\n<pre><code>const i32 MATHPATH = 256\n</code></pre><h2 id=\"枚举\"><a href=\"#枚举\" class=\"headerlink\" title=\"枚举\"></a>枚举</h2><p>用 enum 定义枚举。枚举类型是32位的整数。值是可选的,从1开始。</p>\n<pre><code>enum Operation {\n ADD = 1,\n SUBTRACT = 2,\n MULTIPLY = 3,\n DIVIDE = 4\n}\n</code></pre><h2 id=\"结构体\"><a href=\"#结构体\" class=\"headerlink\" title=\"结构体\"></a>结构体</h2><p>即java中的bean, 结构体用 struct 表示,是基本的复合数据类型,由若干字段组成。每个字段由整型ID,类型,名称和可选的默认值组成。字段可以声明为 optional,表示如果没有被设置,则不进行序列化。</p>\n<pre><code>struct Work {\n 1: i32 num1 = 0,\n 2: i32 num2,\n 3: Operation op,\n 4: optional string comment,\n}\n</code></pre><p>结构体也可以定义为异常:</p>\n<pre><code>exception InvalidOperation {\n 1: i32 whatOp,\n 2: string why\n}\n</code></pre><h2 id=\"服务\"><a href=\"#服务\" class=\"headerlink\" title=\"服务\"></a>服务</h2><p>服务类似 class, 用 service 关键字定义。服务可以用 extends 关键字继承其他服务。service 由一系列方法组成。方法由返回值,参数列表和一个可选的异常列表组成。参数列表和异常列表的语法和结构体的语法一样。</p>\n<pre><code>service Calculator extends shared.SharedService {\n\n void ping(),\n\n i32 add(1:i32 num1, 2:i32 num2),\n\n i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),\n\n /**\n * oneway 表示客户端发送请求后不需要响应。onway 方法返回值必须是void \n */\n oneway void zip()\n\n}\n</code></pre><h2 id=\"include-指令\"><a href=\"#include-指令\" class=\"headerlink\" title=\"include 指令\"></a>include 指令</h2><p>用 include 指令包含其他 thrift 文件:</p>\n<pre><code>include "another.thrift"\n</code></pre><h2 id=\"namespace-指令\"><a href=\"#namespace-指令\" class=\"headerlink\" title=\"namespace 指令\"></a>namespace 指令</h2><p>namespace 指令指定语言相关的名称空间:</p>\n<pre><code>namespace cpp nscpp # 指定C++的名称空间为 nscpp\nnamespace java nsjava # 指定Java的包为 nsjava\n</code></pre><h2 id=\"typedef-指令\"><a href=\"#typedef-指令\" class=\"headerlink\" title=\"typedef 指令\"></a>typedef 指令</h2><p>typedef 指令用来指定类型别名,和 C 一样。</p>\n<pre><code>typedef i32 MyInteger\n</code></pre><h1 id=\"编译IDL文件\"><a href=\"#编译IDL文件\" class=\"headerlink\" title=\"编译IDL文件\"></a>编译IDL文件</h1><p>Thrift 编译器的用法如下:</p>\n<pre><code>thrift [options] file\n</code></pre><p>可以通过 –help 选项来了解具体用法:</p>\n<pre><code>thrift --help\n</code></pre><p>通常用以下命令将IDL编译成语言相关的接口代码,-r(recurse的首字母)表示递归生成被包含的文件,–gen后面接生成的语言。</p>\n<pre><code>thrift-0.10.0.exe -r --gen java ICalc.thrift\n</code></pre><h1 id=\"实例详解\"><a href=\"#实例详解\" class=\"headerlink\" title=\"实例详解\"></a>实例详解</h1><p>下面分别给出 JAVA开发 Thrift 应用的实例。需要注意的是某种语言开发的服务器和任何语言开发的客户端都可以实现互联,这正是 Thrift 的特性之一。</p>\n<h2 id=\"Java开发实例\"><a href=\"#Java开发实例\" class=\"headerlink\" title=\"Java开发实例\"></a>Java开发实例</h2><p>本例开发环境:</p>\n<pre><code>java version "1.8.0_131"\nApache Ant(TM) version 1.10.1\n</code></pre><p>在开发之前应确保 Java 的 Thrift 包已经编译好,如果还没有编译好,请参见<a href=\"#构建Java库\">构建Java库</a>。</p>\n<p>首先建立如下所示的目录结构。其中 com/cynhard/thrift/test 是包的路径,可以根据自己的域名进行调整。iface, server, client三个目录分别用来存放接口,服务器,客户端的代码。build.xml是Ant构建文件。</p>\n<pre><code>[somewhere]\n |-calc/\n |-com/\n | |-cynhard/\n | |-thrift/\n | |-test/\n | |-iface/ -- 接口文件目录\n | | |-ICalc.thrift -- 接口文件\n | |-server/ -- 服务器目录\n | | |-Server.java -- 服务器实现文件\n | |-client/ -- 客户端目录\n | |-Client.java -- 客户端实现文件\n |-build.xml -- ant 文件\n</code></pre><h2 id=\"定义接口\"><a href=\"#定义接口\" class=\"headerlink\" title=\"定义接口\"></a>定义接口</h2><p>打开 ICalc.thrift 文件,编写接口代码如下。注意包名应该根据自己的实际路径调整。</p>\n<p>ICalc.thrift</p>\n<pre><code>namespace java com.cynhard.thrift.test.iface\n\nservice ICalc {\n i32 add(1:i32 num1, 2:i32 num2),\n}\n</code></pre><h2 id=\"实现服务器\"><a href=\"#实现服务器\" class=\"headerlink\" title=\"实现服务器\"></a>实现服务器</h2><p>打开 Server.java,编写服务器代码如下。注意包名应该根据自己的实际路径调整。</p>\n<p>Server.java<br> package com.cynhard.thrift.test.server;</p>\n<pre><code>import org.apache.thrift.TException;\nimport org.apache.thrift.server.TServer;\nimport org.apache.thrift.server.TServer.Args;\nimport org.apache.thrift.server.TSimpleServer;\nimport org.apache.thrift.transport.TServerSocket;\nimport org.apache.thrift.transport.TServerTransport;\nimport com.cynhard.thrift.test.iface.ICalc;\n\npublic class Server {\n\n static class CalcHandler implements ICalc.Iface {\n @Override\n public int add(int num1, int num2) throws TException {\n return num1 + num2;\n }\n }\n\n public static void main(String[] args) {\n try {\n CalcHandler handler = new CalcHandler();\n ICalc.Processor processor = new ICalc.Processor(handler);\n TServerTransport serverTransport = new TServerSocket(9090);\n TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));\n\n System.out.println("Starting the server...");\n server.serve(); \n } catch (Exception e) { \n e.printStackTrace(); \n } \n }\n}\n</code></pre><h2 id=\"实现客户端\"><a href=\"#实现客户端\" class=\"headerlink\" title=\"实现客户端\"></a>实现客户端</h2><p>打开 Client.java,编写客户端代码如下。注意包名应该根据自己的实际路径调整。</p>\n<p>Client.java</p>\n<pre><code>package com.cynhard.thrift.test.client;\n\nimport org.apache.thrift.TException;\nimport org.apache.thrift.transport.TTransport;\nimport org.apache.thrift.transport.TSocket;\nimport org.apache.thrift.protocol.TBinaryProtocol;\nimport org.apache.thrift.protocol.TProtocol;\nimport com.cynhard.thrift.test.iface.ICalc;\n\npublic class Client {\n public static void main(String[] args) {\n try {\n TTransport transport = new TSocket("localhost", 9090);\n transport.open();\n\n TProtocol protocol = new TBinaryProtocol(transport);\n ICalc.Client client = new ICalc.Client(protocol);\n System.out.println(client.add(1, 2));\n\n transport.close();\n } catch (TException e) {\n e.printStackTrace();\n }\n }\n}\n</code></pre><h2 id=\"构建工程\"><a href=\"#构建工程\" class=\"headerlink\" title=\"构建工程\"></a>构建工程</h2><p>打开 build.xml,编写构建配置如下。注意路径属性需要根据实际路径进行修改。</p>\n<p>build.xml</p>\n<pre><code><?xml version="1.0"?>\n<project name="calc" basedir="." default="build">\n\n<property name="thrift.lib.dir" value="/Users/zhouguangsheng/project/study/Thrift/thrift-0.11.0/lib/java/build"/>\n<property name="thrift.compiler.dir" value="/Users/zhouguangsheng/project/study/Thrift/thrift-0.11.0/lib/java/build"/>\n<property name="interface.dir" value="${basedir}\\com\\cynhard\\thrift\\test\\iface"/>\n\n<path id="master-classpath">\n <fileset dir="${thrift.lib.dir}">\n <include name="**\\*.jar"/>\n </fileset>\n <pathelement path="."/>\n</path>\n\n<target name="build" description="Compile Calc">\n <!-- 如果单独编译thrift文件,注释下面exec这段 -->\n <exec executable="${thrift.compiler.dir}/libthrift-0.11.0.jar">\n <arg line="--gen java -out ${basedir} ${interface.dir}\\ICalc.thrift"/>\n </exec>\n <javac>\n <src path="."/>\n <classpath refid="master-classpath"/>\n </javac>\n</target>\n\n<target name="run_server" description="Run server">\n <java fork="true" failonerror="yes" classname="com.zgs.thrift.test.server.Server">\n <classpath refid="master-classpath"/>\n </java>\n</target>\n\n<target name="run_client" description="Run client">\n <java fork="true" failonerror="yes" classname="com.zgs.thrift.test.client.Client">\n <classpath refid="master-classpath"/>\n </java>\n</target>\n\n</project>\n</code></pre><p>上面的工作完成后,就可以开始构建工程了。以管理员权限打开命令提示符,切换到 项目根目录。执行以下命令编译工程:</p>\n<pre><code>ant build\n</code></pre><p>直接编译可能会不成功,thrift文件也可以单独编译,ant build.xml文件中移除,只编译java</p>\n<pre><code>thrift -gen java -out /Users/zhouguangsheng/project/study/Thrift/thriftDemo/ /Users/zhouguangsheng/project/study/Thrift/thriftDemo/com/zgs/thrift/test/iface/ICalc.thrift\n</code></pre><p>-out参数为编译的java文件要存放的路径</p>\n<p>编译成功后,服务器和客户端相应的class文件就生成在了相应的目录中。下面就可以开始测试了。</p>\n<h2 id=\"测试\"><a href=\"#测试\" class=\"headerlink\" title=\"测试\"></a>测试</h2><p>执行以下命令运行服务器。</p>\n<pre><code>ant run_server\n</code></pre><p>输出结果如下,可以看到输出了 Starting the server…,表明服务器已经启动。</p>\n<pre><code>Buildfile: G:\\projects\\java\\calc\\build.xml\n\nrun_server:\n [java] Starting the server...\n</code></pre><p>因为服务器在一个单独的窗口运行,为了测试客户端,需要打开另一个命令提示符,同样切换到 calc 目录。执行以下命令运行客户端:</p>\n<pre><code>ant run_client\n</code></pre><p>输出结果如下,可以看到返回了正确的结果:3 。</p>\n<pre><code>Buildfile: G:\\projects\\java\\calc\\build.xml\n\nrun_client:\n [java] Received 1\n [java] 3\n\nBUILD SUCCESSFUL\nTotal time: 0 seconds\n</code></pre>","site":{"data":{}},"excerpt":"","more":"<h1 id=\"简介\"><a href=\"#简介\" class=\"headerlink\" title=\"简介\"></a>简介</h1><p>Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Go,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器。thrift允许你定义一个简单的定义文件中的数据类型和服务接口。以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。<br><br>本文主要介绍 Thrift 开发流程,并给出 Java 开发 Thrfit 应用的实例。</p>\n<p>本文的开发环境为: macOS Sierra 10.12.6</p>\n<h1 id=\"Thrift开发概述\"><a href=\"#Thrift开发概述\" class=\"headerlink\" title=\"Thrift开发概述\"></a>Thrift开发概述</h1><p>Thrift用接口描述语言(Interface description language,IDL)来描述不同编程语言之间的接口。Thrift开发环境包含两个部分:Thrift编译器和语言相关的库。Thrift编译器用来根据IDL生成语言相关的接口代码框架,我们可以使用这个框架很方便的实现客户端和服务器的代码。语言相关的库则封装了不同编程语言之间通信的内部实现,让我们解放双手着重处理业务逻辑。根据编程语言的不同,构建相关库的方法也不同。</p>\n<h2 id=\"开发前的准备\"><a href=\"#开发前的准备\" class=\"headerlink\" title=\"开发前的准备\"></a>开发前的准备</h2><ul>\n<li>在<a href=\"http://thrift.apache.org/download\" target=\"_blank\" rel=\"noopener\">Thrift官方下载页面</a>下载Thrift编译器,如果希望从源代码编译Thrift编译器,则跳过这一步。官网只提供了windows下的编译器,thrift-0.10.0.exe,使用非windows跳过此步骤,mac系统请参考<a href=\"#Mac下安装Thrift\">Mac下安装Thrift</a>。</li>\n<li>在<a href=\"http://thrift.apache.org/download\" target=\"_blank\" rel=\"noopener\">Thrift官方下载页面</a>下载Thrift源代码。源代码中包含了编译器的代码和语言相关的库的代码。本例下载的源代码为:thrift-0.10.0.tar.gz 。下载后解压到合适的目录。如果希望从源代码编译Thrift编译器,请参阅Thrift源代码根目录下的README.md。<a href=\"http://thrift.apache.org/docs/BuildingFromSource\" target=\"_blank\" rel=\"noopener\">官网教程 Building from source</a></li>\n<li>构建语言相关的库(如果需要的话)。</li>\n</ul>\n<p><span id=\"Mac下安装Thrift\"></span></p>\n<h2 id=\"Mac下安装Thrift\"><a href=\"#Mac下安装Thrift\" class=\"headerlink\" title=\"Mac下安装Thrift\"></a>Mac下安装Thrift</h2><p>在mac下安装软件跟Linux安装比较类似,在安装Thrift之前需要先安装依赖。</p>\n<h3 id=\"安装BOOST\"><a href=\"#安装BOOST\" class=\"headerlink\" title=\"安装BOOST\"></a>安装BOOST</h3><p>下载:<a href=\"http://www.boost.org/\" target=\"_blank\" rel=\"noopener\">http://www.boost.org/</a> (boost_1_57_0.tar.gz)<br><br>拷贝到/usr/local目录下并解压:</p>\n<pre><code>tar -zvxf boost_1_57_0.tar.gz\n</code></pre><p>切换目录:</p>\n<pre><code>cd boost_1_57_0\n</code></pre><p>执行命令:</p>\n<pre><code>./bootstrap.sh —prefix=PATH_TO_BOOST \nsudo ./b2 threading=multi address-model=64 variant=release stage install\n</code></pre><p>./bootstrap.sh该命令用于生成bjam可执行文件,这个东西就是用来编译boost库<br></p>\n<h3 id=\"安装-libevent\"><a href=\"#安装-libevent\" class=\"headerlink\" title=\"安装 libevent\"></a>安装 libevent</h3><p>下载:<a href=\"http://libevent.org/\" target=\"_blank\" rel=\"noopener\">http://libevent.org/</a> (libevent-2.0.21-stable.tar.gz)</p>\n<p>拷贝到/usr/local目录下并解压:</p>\n<pre><code>tar -zvxf libevent-2.0.21-stable.tar.gz \n</code></pre><p>切换目录:</p>\n<pre><code>cd libevent-2.0.21-stable \n</code></pre><p>执行命令:</p>\n<pre><code>./configure —-prefix=/usr/local \nmake \nsudo make install \n</code></pre><p>执行make时报如下错误,需要安装openssl; 这是由于mac默认安装了openssl但是没有安装对应的include头文件和lib库,故这里使用homebrew(参考<a href=\"https://brew.sh/index_zh-cn.html)来安装最新的openssl\" target=\"_blank\" rel=\"noopener\">https://brew.sh/index_zh-cn.html)来安装最新的openssl</a></p>\n<pre><code>fatal error: 'openssl/bio.h' file not found\n</code></pre><p>使用homebrew 安装</p>\n<pre><code>brew install openssl\n</code></pre><p>安装后,连接到libevent目录下</p>\n<pre><code>ln -s /usr/local/Cellar/openssl/1.0.2o_2/include/openssl /usr/local/libevent-2.1.8-stable/include\n</code></pre><p>成功后再执行 make和sudo make install命令就不报错了</p>\n<h3 id=\"安装-Apache-Thrift\"><a href=\"#安装-Apache-Thrift\" class=\"headerlink\" title=\"安装 Apache Thrift\"></a>安装 Apache Thrift</h3><p>下载:<a href=\"http://thrift.apache.org/\" target=\"_blank\" rel=\"noopener\">http://thrift.apache.org/</a> (thrift-0.8.0.tar.gz)</p>\n<p>解压:</p>\n<pre><code>tar -zvxf thrift-0.8.0.tar.gz\n</code></pre><p>切换目录:</p>\n<pre><code>cd thrift-0.8.0.tar.gz \n</code></pre><p>编译命令:</p>\n<pre><code>./configure --prefix=/usr/local/ --with-boost=/usr/local --with-libevent=/usr/local\n</code></pre><p>安装命令:</p>\n<pre><code>sudo make install\n</code></pre><p>可以查看安装是否成功和版本</p>\n<pre><code>thrift -version\n</code></pre><p>注意版本选择:选择Thrift 0.8.0版本,选择高的版本会报bison版本低的错误,在安装0.8.0时也报了一些错误,不过不影响正常使用</p>\n<p>最新版0.11.0 在mac中如果用上面步骤安装不成功,可以使用如下方式安装</p>\n<pre><code>brew install thrift\n</code></pre><h2 id=\"开发流程\"><a href=\"#开发流程\" class=\"headerlink\" title=\"开发流程\"></a>开发流程</h2><ul>\n<li>使用IDL定义服务器和客户端之间的接口。利用Thrift编译器编译该IDL文件,生成语言相关的代码框架。</li>\n<li>利用已经生成的代码框架,实现客户端和服务器的业务逻辑。</li>\n</ul>\n<h2 id=\"构建语言相关的库\"><a href=\"#构建语言相关的库\" class=\"headerlink\" title=\"构建语言相关的库\"></a>构建语言相关的库</h2><p>语言相关的库代码在Thrift源代码的lib下,每种语言一个目录,比如C++就在cpp目录下。在每种语言的目录下,都有一个README.md用来描述该语言库的构建和使用方法。语言相关的库根据编程语言的不同,构建的方式也不同。如果是编译型语言的话,则需要编译。本篇只提供java案例</p>\n<p><span id=\"构建Java库\"></span></p>\n<h2 id=\"构建Java库\"><a href=\"#构建Java库\" class=\"headerlink\" title=\"构建Java库\"></a>构建Java库</h2><p>本例构建环境:<br></p>\n<pre><code>java version "1.8.0_131"\nApache Ant(TM) version 1.10.5\n</code></pre><p>在编译之前请确保正确安装和配置了 JDK 和 Ant。</p>\n<p>Java库源代码目录为:[Thrift源代码目录]\\lib\\java。Java库需要使用Ant 来编译。管理员方式打开命令行,切换到Java库元源代码目录,执行:<br></p>\n<blockquote>\n<p>ant</p>\n</blockquote>\n<p>编译后会在 build 子目录下找到 libthrift-0.10.0.jar,这就是我们需要的开发包。在 build/lib 下是 libthrift-0.10.0.jar 的依赖包。</p>\n<h1 id=\"使用IDL定义接口\"><a href=\"#使用IDL定义接口\" class=\"headerlink\" title=\"使用IDL定义接口\"></a>使用IDL定义接口</h1><p>Thrift 中 IDL 文件以 .thrift 为后缀。该文件用来描述服务器与客户端之间的接口。在编写 thrift 文件之前,还需要了解一下用以描述接口的语法。</p>\n<h2 id=\"注释\"><a href=\"#注释\" class=\"headerlink\" title=\"注释\"></a>注释</h2><p>Thrift 支持三种注释:<br><br>脚本注释,用 # 表示,例如:<br></p>\n<blockquote>\n<p>#这是一个注释</p>\n</blockquote>\n<p>块注释,用 /<em> 和 </em>/ 表示。<br></p>\n<blockquote>\n</blockquote>\n<p>/*<br></p>\n<ul>\n<li>这是一个注释<br><br>*/<br></li>\n</ul>\n<p>单行注释,用 // 表示。<br></p>\n<blockquote>\n<p>// 这是一个注释</p>\n</blockquote>\n<h2 id=\"基本类型\"><a href=\"#基本类型\" class=\"headerlink\" title=\"基本类型\"></a>基本类型</h2><table>\n<thead>\n<tr>\n<th style=\"text-align:center\">类型</th>\n<th style=\"text-align:center\">描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:center\">bool</td>\n<td style=\"text-align:center\">布尔类型,1byte</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">i8</td>\n<td style=\"text-align:center\">有符号整形,8bits,即byte</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">i16</td>\n<td style=\"text-align:center\">有符号整型,16bits</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">i32</td>\n<td style=\"text-align:center\">有符号整型,32bits</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">i64</td>\n<td style=\"text-align:center\">有符号整型,64bits</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">double</td>\n<td style=\"text-align:center\">浮点型,64bits</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">string</td>\n<td style=\"text-align:center\">字符串</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">binary</td>\n<td style=\"text-align:center\">Blob,byte数组</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">map<t1,t2></td>\n<td style=\"text-align:center\">map</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">list<t1></t1></td>\n<td style=\"text-align:center\">有序列表</td>\n</tr>\n<tr>\n<td style=\"text-align:center\">set<t1></t1></td>\n<td style=\"text-align:center\">无重复元素的容器</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"常量\"><a href=\"#常量\" class=\"headerlink\" title=\"常量\"></a>常量</h2><p>常量用const表示:</p>\n<pre><code>const i32 MATHPATH = 256\n</code></pre><h2 id=\"枚举\"><a href=\"#枚举\" class=\"headerlink\" title=\"枚举\"></a>枚举</h2><p>用 enum 定义枚举。枚举类型是32位的整数。值是可选的,从1开始。</p>\n<pre><code>enum Operation {\n ADD = 1,\n SUBTRACT = 2,\n MULTIPLY = 3,\n DIVIDE = 4\n}\n</code></pre><h2 id=\"结构体\"><a href=\"#结构体\" class=\"headerlink\" title=\"结构体\"></a>结构体</h2><p>即java中的bean, 结构体用 struct 表示,是基本的复合数据类型,由若干字段组成。每个字段由整型ID,类型,名称和可选的默认值组成。字段可以声明为 optional,表示如果没有被设置,则不进行序列化。</p>\n<pre><code>struct Work {\n 1: i32 num1 = 0,\n 2: i32 num2,\n 3: Operation op,\n 4: optional string comment,\n}\n</code></pre><p>结构体也可以定义为异常:</p>\n<pre><code>exception InvalidOperation {\n 1: i32 whatOp,\n 2: string why\n}\n</code></pre><h2 id=\"服务\"><a href=\"#服务\" class=\"headerlink\" title=\"服务\"></a>服务</h2><p>服务类似 class, 用 service 关键字定义。服务可以用 extends 关键字继承其他服务。service 由一系列方法组成。方法由返回值,参数列表和一个可选的异常列表组成。参数列表和异常列表的语法和结构体的语法一样。</p>\n<pre><code>service Calculator extends shared.SharedService {\n\n void ping(),\n\n i32 add(1:i32 num1, 2:i32 num2),\n\n i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),\n\n /**\n * oneway 表示客户端发送请求后不需要响应。onway 方法返回值必须是void \n */\n oneway void zip()\n\n}\n</code></pre><h2 id=\"include-指令\"><a href=\"#include-指令\" class=\"headerlink\" title=\"include 指令\"></a>include 指令</h2><p>用 include 指令包含其他 thrift 文件:</p>\n<pre><code>include "another.thrift"\n</code></pre><h2 id=\"namespace-指令\"><a href=\"#namespace-指令\" class=\"headerlink\" title=\"namespace 指令\"></a>namespace 指令</h2><p>namespace 指令指定语言相关的名称空间:</p>\n<pre><code>namespace cpp nscpp # 指定C++的名称空间为 nscpp\nnamespace java nsjava # 指定Java的包为 nsjava\n</code></pre><h2 id=\"typedef-指令\"><a href=\"#typedef-指令\" class=\"headerlink\" title=\"typedef 指令\"></a>typedef 指令</h2><p>typedef 指令用来指定类型别名,和 C 一样。</p>\n<pre><code>typedef i32 MyInteger\n</code></pre><h1 id=\"编译IDL文件\"><a href=\"#编译IDL文件\" class=\"headerlink\" title=\"编译IDL文件\"></a>编译IDL文件</h1><p>Thrift 编译器的用法如下:</p>\n<pre><code>thrift [options] file\n</code></pre><p>可以通过 –help 选项来了解具体用法:</p>\n<pre><code>thrift --help\n</code></pre><p>通常用以下命令将IDL编译成语言相关的接口代码,-r(recurse的首字母)表示递归生成被包含的文件,–gen后面接生成的语言。</p>\n<pre><code>thrift-0.10.0.exe -r --gen java ICalc.thrift\n</code></pre><h1 id=\"实例详解\"><a href=\"#实例详解\" class=\"headerlink\" title=\"实例详解\"></a>实例详解</h1><p>下面分别给出 JAVA开发 Thrift 应用的实例。需要注意的是某种语言开发的服务器和任何语言开发的客户端都可以实现互联,这正是 Thrift 的特性之一。</p>\n<h2 id=\"Java开发实例\"><a href=\"#Java开发实例\" class=\"headerlink\" title=\"Java开发实例\"></a>Java开发实例</h2><p>本例开发环境:</p>\n<pre><code>java version "1.8.0_131"\nApache Ant(TM) version 1.10.1\n</code></pre><p>在开发之前应确保 Java 的 Thrift 包已经编译好,如果还没有编译好,请参见<a href=\"#构建Java库\">构建Java库</a>。</p>\n<p>首先建立如下所示的目录结构。其中 com/cynhard/thrift/test 是包的路径,可以根据自己的域名进行调整。iface, server, client三个目录分别用来存放接口,服务器,客户端的代码。build.xml是Ant构建文件。</p>\n<pre><code>[somewhere]\n |-calc/\n |-com/\n | |-cynhard/\n | |-thrift/\n | |-test/\n | |-iface/ -- 接口文件目录\n | | |-ICalc.thrift -- 接口文件\n | |-server/ -- 服务器目录\n | | |-Server.java -- 服务器实现文件\n | |-client/ -- 客户端目录\n | |-Client.java -- 客户端实现文件\n |-build.xml -- ant 文件\n</code></pre><h2 id=\"定义接口\"><a href=\"#定义接口\" class=\"headerlink\" title=\"定义接口\"></a>定义接口</h2><p>打开 ICalc.thrift 文件,编写接口代码如下。注意包名应该根据自己的实际路径调整。</p>\n<p>ICalc.thrift</p>\n<pre><code>namespace java com.cynhard.thrift.test.iface\n\nservice ICalc {\n i32 add(1:i32 num1, 2:i32 num2),\n}\n</code></pre><h2 id=\"实现服务器\"><a href=\"#实现服务器\" class=\"headerlink\" title=\"实现服务器\"></a>实现服务器</h2><p>打开 Server.java,编写服务器代码如下。注意包名应该根据自己的实际路径调整。</p>\n<p>Server.java<br> package com.cynhard.thrift.test.server;</p>\n<pre><code>import org.apache.thrift.TException;\nimport org.apache.thrift.server.TServer;\nimport org.apache.thrift.server.TServer.Args;\nimport org.apache.thrift.server.TSimpleServer;\nimport org.apache.thrift.transport.TServerSocket;\nimport org.apache.thrift.transport.TServerTransport;\nimport com.cynhard.thrift.test.iface.ICalc;\n\npublic class Server {\n\n static class CalcHandler implements ICalc.Iface {\n @Override\n public int add(int num1, int num2) throws TException {\n return num1 + num2;\n }\n }\n\n public static void main(String[] args) {\n try {\n CalcHandler handler = new CalcHandler();\n ICalc.Processor processor = new ICalc.Processor(handler);\n TServerTransport serverTransport = new TServerSocket(9090);\n TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));\n\n System.out.println("Starting the server...");\n server.serve(); \n } catch (Exception e) { \n e.printStackTrace(); \n } \n }\n}\n</code></pre><h2 id=\"实现客户端\"><a href=\"#实现客户端\" class=\"headerlink\" title=\"实现客户端\"></a>实现客户端</h2><p>打开 Client.java,编写客户端代码如下。注意包名应该根据自己的实际路径调整。</p>\n<p>Client.java</p>\n<pre><code>package com.cynhard.thrift.test.client;\n\nimport org.apache.thrift.TException;\nimport org.apache.thrift.transport.TTransport;\nimport org.apache.thrift.transport.TSocket;\nimport org.apache.thrift.protocol.TBinaryProtocol;\nimport org.apache.thrift.protocol.TProtocol;\nimport com.cynhard.thrift.test.iface.ICalc;\n\npublic class Client {\n public static void main(String[] args) {\n try {\n TTransport transport = new TSocket("localhost", 9090);\n transport.open();\n\n TProtocol protocol = new TBinaryProtocol(transport);\n ICalc.Client client = new ICalc.Client(protocol);\n System.out.println(client.add(1, 2));\n\n transport.close();\n } catch (TException e) {\n e.printStackTrace();\n }\n }\n}\n</code></pre><h2 id=\"构建工程\"><a href=\"#构建工程\" class=\"headerlink\" title=\"构建工程\"></a>构建工程</h2><p>打开 build.xml,编写构建配置如下。注意路径属性需要根据实际路径进行修改。</p>\n<p>build.xml</p>\n<pre><code><?xml version="1.0"?>\n<project name="calc" basedir="." default="build">\n\n<property name="thrift.lib.dir" value="/Users/zhouguangsheng/project/study/Thrift/thrift-0.11.0/lib/java/build"/>\n<property name="thrift.compiler.dir" value="/Users/zhouguangsheng/project/study/Thrift/thrift-0.11.0/lib/java/build"/>\n<property name="interface.dir" value="${basedir}\\com\\cynhard\\thrift\\test\\iface"/>\n\n<path id="master-classpath">\n <fileset dir="${thrift.lib.dir}">\n <include name="**\\*.jar"/>\n </fileset>\n <pathelement path="."/>\n</path>\n\n<target name="build" description="Compile Calc">\n <!-- 如果单独编译thrift文件,注释下面exec这段 -->\n <exec executable="${thrift.compiler.dir}/libthrift-0.11.0.jar">\n <arg line="--gen java -out ${basedir} ${interface.dir}\\ICalc.thrift"/>\n </exec>\n <javac>\n <src path="."/>\n <classpath refid="master-classpath"/>\n </javac>\n</target>\n\n<target name="run_server" description="Run server">\n <java fork="true" failonerror="yes" classname="com.zgs.thrift.test.server.Server">\n <classpath refid="master-classpath"/>\n </java>\n</target>\n\n<target name="run_client" description="Run client">\n <java fork="true" failonerror="yes" classname="com.zgs.thrift.test.client.Client">\n <classpath refid="master-classpath"/>\n </java>\n</target>\n\n</project>\n</code></pre><p>上面的工作完成后,就可以开始构建工程了。以管理员权限打开命令提示符,切换到 项目根目录。执行以下命令编译工程:</p>\n<pre><code>ant build\n</code></pre><p>直接编译可能会不成功,thrift文件也可以单独编译,ant build.xml文件中移除,只编译java</p>\n<pre><code>thrift -gen java -out /Users/zhouguangsheng/project/study/Thrift/thriftDemo/ /Users/zhouguangsheng/project/study/Thrift/thriftDemo/com/zgs/thrift/test/iface/ICalc.thrift\n</code></pre><p>-out参数为编译的java文件要存放的路径</p>\n<p>编译成功后,服务器和客户端相应的class文件就生成在了相应的目录中。下面就可以开始测试了。</p>\n<h2 id=\"测试\"><a href=\"#测试\" class=\"headerlink\" title=\"测试\"></a>测试</h2><p>执行以下命令运行服务器。</p>\n<pre><code>ant run_server\n</code></pre><p>输出结果如下,可以看到输出了 Starting the server…,表明服务器已经启动。</p>\n<pre><code>Buildfile: G:\\projects\\java\\calc\\build.xml\n\nrun_server:\n [java] Starting the server...\n</code></pre><p>因为服务器在一个单独的窗口运行,为了测试客户端,需要打开另一个命令提示符,同样切换到 calc 目录。执行以下命令运行客户端:</p>\n<pre><code>ant run_client\n</code></pre><p>输出结果如下,可以看到返回了正确的结果:3 。</p>\n<pre><code>Buildfile: G:\\projects\\java\\calc\\build.xml\n\nrun_client:\n [java] Received 1\n [java] 3\n\nBUILD SUCCESSFUL\nTotal time: 0 seconds\n</code></pre>"}],"PostAsset":[{"_id":"source/_posts/推荐一个好用的录制gif程序/img1.jpg","slug":"img1.jpg","post":"cjk0gge0s000450klcivntlka","modified":1,"renderable":0},{"_id":"source/_posts/推荐一个好用的录制gif程序/img2.jpg","slug":"img2.jpg","post":"cjk0gge0s000450klcivntlka","modified":1,"renderable":0},{"_id":"source/_posts/推荐一个好用的录制gif程序/03.jpg","post":"cjk0gge0s000450klcivntlka","slug":"03.jpg","modified":1,"renderable":1},{"_id":"source/_posts/推荐一个好用的录制gif程序/giftest.gif","slug":"giftest.gif","post":"cjk0gge0s000450klcivntlka","modified":1,"renderable":0}],"PostCategory":[],"PostTag":[{"post_id":"cjk0gge0d000050klfnoeo8z2","tag_id":"cjk0gge0q000350kllfg6vj69","_id":"cjk0gge0x000650kli6mkhin6"},{"post_id":"cjk0gge0m000250klen530dcn","tag_id":"cjk0gge0q000350kllfg6vj69","_id":"cjk0gge13000850klty7o0dho"},{"post_id":"cjk0gge0s000450klcivntlka","tag_id":"cjk0gge0q000350kllfg6vj69","_id":"cjk0gge16000950klcg2f3oul"},{"post_id":"cjk0gge1d000a50kl6a40om8b","tag_id":"cjk0gge1f000b50kl15tqsedy","_id":"cjk0gge1g000c50klr7c5ut4p"}],"Tag":[{"name":"杂谈","_id":"cjk0gge0q000350kllfg6vj69"},{"name":"技术,thrift","_id":"cjk0gge1f000b50kl15tqsedy"}]}}