Pendahuluan Layanan Istirahat
Restful Service adalah model arsitektur yang telah menjadi lebih populer dalam beberapa tahun terakhir. Layanan webnya yang ringan memainkan Native Get, Put, Posting, dan Hapus Protokol HTTP. Dibandingkan dengan SOAP yang kompleks dan XML-RPC, layanan Web Mode REST jelas lebih ringkas, dan semakin banyak layanan web mulai mengadopsi desain dan implementasi gaya istirahat. Misalnya, Amazon.com menyediakan layanan web yang dekat dengan gaya istirahat untuk pencarian buku; Layanan web yang disediakan oleh Yahoo juga merupakan gaya istirahat. Istirahat tidak selalu merupakan pilihan yang tepat. Ini telah menjadi populer sebagai metode merancang layanan web yang lebih sedikit mengandalkan middleware berpemilik, seperti server aplikasi, daripada pada metode berbasis SOAP dan WSDL. Dalam arti tertentu, dengan menekankan standar internet awal seperti URI dan HTTP, istirahat adalah regresi terhadap pendekatan web sebelum era server aplikasi besar.
Contoh seperti yang ditunjukkan pada gambar berikut:
Kunci untuk menggunakan istirahat adalah cara abstrak sumber daya. Semakin tepat abstraksi, semakin baik penerapan istirahat.
Prinsip -prinsip utama layanan istirahat:
1. Berikan semua objek ID
2. Hubungkan objek bersama
3. Gunakan metode standar
4. Representasi Sumber Daya Ganda
5. Komunikasi tanpa kewarganegaraan
Artikel ini memperkenalkan cara membangun kerangka kerja layanan peristirahatan sederhana berdasarkan boot musim semi, dan cara mengimplementasikan otentikasi layanan rest melalui anotasi khusus
Membangun kerangka kerja
pom.xml
Pertama, perkenalkan dependensi terkait, gunakan mongoDB untuk database, dan gunakan redis untuk cache
CATATAN: Tidak ada tomcat yang digunakan di sini, tapi overow
<dependency> <GroupId> org.springframework.boot </groupid> <ArtifactId> Spring-boot-starter </arttifactid> </dependency> <sependency> <groupid> org.springframework. <GroupId> org.springframework.boot </groupid> <ArTifactId> Spring-boot-starter-web </t Artifactid> <ckscuxions> <scuplusion> <groupid> org.springframework.boot </groupid> <Artifactid> Spring-boot-starter-tombam </art/groupid> <Artifactid> <GroupId> org.springframework.boot </groupid> <ArtifactId> Spring-boot-starter-underTow </t Artifactid> </gandendency> <!-Dukungan Redis-> <sendendency> <Roupid> org.springframework.boot </groupid> <Artifactid> <artfact-boots-stas-bootter.boots </groupid> <Arttifactid> Spring-boots-stas-bootter.boot </groupid> <ArtiFacTID> Spring-boots-stas-bootter.boots </groupID> <ArttifactD> Spring-boots-stas-starter.boot </groupID> <ArttifactD> Spring-boots-stas-starter. <!-Dukungan MongoDB-> <dependency> <GroupId> org.springframework.boot </groupid> <ArTifactId> Spring-boot-starter-data-mongoDB </artifactid> </dependency>
Perkenalkan Layanan Web Dukungan Spring-Boot-Starter-Web
Memperkenalkan Spring-Boot-Starter-Data-Redis dan Spring-Boot-Starter-Data-MongoDB dapat dengan mudah menggunakan MongoDB dan Redis
File konfigurasi
Fungsi profil
Untuk memfasilitasi perbedaan antara lingkungan pengembangan dan lingkungan online, fungsi profil dapat digunakan untuk menambahkannya di application.properties
spring.profiles.active=dev
Kemudian tambahkan aplikasi-dev.properties sebagai file konfigurasi dev.
Konfigurasi mondb
Cukup konfigurasikan alamat database
spring.data.mongodb.uri = mongodb: // ip: port/database? readpreference = primerPreferred
Konfigurasi Redis
spring.redis.database = 0 # redis Alamat server spring.redis.host = ip # redis server port port spring.redis.port = 6379 # redis server koneksi kata sandi (default kosong) spring.redis.password = # MAXICE JUMLAH KONEKSI DALAM POOL KONEKSI POOL (Menggunakan Nilai-Nilai negatif berarti No Limit) Spring.redis.pool.Max-Action-Active) NOMECTICE POOL POOL (Menggunakan Nilai-Nilai negatif berarti No Limit) Spring.redis.pool.Max-Action-ACTIMUM) POOL POOL KONEKSIONAL (Menggunakan Nilai-Nilai Negatif berarti Batas No Limit) Spring.Redis.pool.Max-Accial = 8 spring.redis.pool.max-wait = -1 # koneksi idle maksimum dalam koneksi pool spring.redis.pool.max-idle = 8 # koneksi idle minimum dalam koneksi pool spring.redis.pool.min-idle = 0 # Connection Timeout (MS) spring.redis.timeout = 0
Akses data
mongdb
Akses ke mongDB sangat sederhana. Anda dapat secara langsung mendefinisikan antarmuka memperluas mongorepository. Selain itu, dapat mendukung sintaks JPA, misalnya:
@ComponentPublic Interface userrepository memperluas mongorepository <user, integer> {pengguna publik findbyusername (string username);}Saat menggunakannya, cukup tambahkan anotasi @Autowired.
@ComponentPublic Class AuthService memperluas BASESERVICE {@Autowired userrepository userrepository; }Akses Redis
Gunakan StringRedistemplate untuk mengakses Redis secara langsung
@ComponentPublic Class BaseService {@Autowired dilindungi MongoTemplate MongoTemplate; @Autowired dilindungi StringRedistemplate StrreDistemplate; }Simpan data:
.stringredistemplate.opsforvalue (). Set (token_key, user.getId ()+"", token_max_age, timeunit.seconds);
Hapus Data:
StringRedistemplate.delete (getFormattoken (AccessToken, platform));
Layanan Web
Tentukan kelas pengontrol, tambahkan restcontroller, dan gunakan permintaan permintaan untuk mengatur rute url
@RestControllerPublic Class AuthController memperluas Basecontroller {@RequestMapping (value = {"/"}, menghasilkan = "Application/json; charset = utf-8", metode = {requestMethod.get, requestMethod.post}) @Response Publicing String Main () {helly hello! " }}Sekarang mulailah, Anda harus dapat melihat Hello World! Dia
Otentikasi Layanan
Mekanisme AccessToken Sederhana
Berikan antarmuka login. Setelah otentikasi berhasil, AccessToken dihasilkan. Saat mengakses antarmuka di masa depan, AccessToken dibawa. Server menggunakan AccessToken untuk menentukan apakah itu pengguna yang sah.
Untuk kenyamanan, Anda dapat menyimpan AccessToken ke Redis dan mengatur periode validitas.
String token = encryptionutils.sha256Hex (string.format ("%s%s", user.getusername (), system.currentTimeMillis ())); String token_key = getFormattoken (token, platform); this.stringredistemplate.opsforvalue (). Set (token_key, user.getId ()+"", token_max_age, timeunit.seconds);Otentikasi Identitas Interceptor
Untuk memfasilitasi otentikasi identitas terpadu, interseptor dapat dibuat berdasarkan mekanisme pencegat Spring untuk melakukan otentikasi terpadu.
Kelas publik AuthCheckInterceptor mengimplementasikan handlerinterceptor {}Untuk membuat interseptor mulai berlaku, satu langkah lagi diperlukan untuk menambahkan konfigurasi:
@ConfigurationPublic Kelas SesionKonfigurasi memperluas WebMvCconfigurerAdapter {@Autowired authcheckInterceptor AuthCheckInterceptor; @Override public void addInterceptors (interceptorregistry registry) {super.addInterceptors (registry); // Tambahkan Interceptor Registry.AddInterceptor (AuthCheckInterceptor) .AddPathPatterns ("/**"); }}Anotasi Otentikasi Kustom
Untuk memperbaiki otentikasi izin, misalnya, beberapa antarmuka hanya dapat diakses oleh orang -orang dengan izin spesifik, dan dapat dengan mudah diselesaikan melalui anotasi khusus. Dalam anotasi khusus, cukup tambahkan peran.
/*** Anotasi verifikasi izin*/@target (elementType.method) @retention (retentionpolicy.runtime) @documentedpublic @interface authcheck {/*** Daftar peran* @return*/string [] Default {};}Logika Inspeksi:
Selama antarmuka ditambahkan dengan anotasi authcheck, itu harus menjadi pengguna yang dicatat
Jika peran ditentukan, selain masuk, pengguna juga harus memiliki peran yang sesuai.
String [] degnaturls = string baru [] {"/user/.*", "/cat/.*", "/app/.*", "/error"}; public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception { // 0 Verify public parameters if(!checkParams("platform",httpServletRequest,httpServletResponse)){ return false; } // 1. Abaikan verifikasi URL string url = httpservletrequest.getRequesturi (). ToString (); for (String Impanurl: IGLANCEURLS) {if (url.matches (IGNURLL)) {return true; }} // 2. Verifikasi kueri anotasi handlermethod handlermethod = (handlermethod) handler; Metode metode = handlermethod.getMethod (); // query annotation authcheck authcheck = method.getAnnotation (authcheck.class); if (authcheck == null) {// tidak ada anotasi, tidak ada pengembalian true; } // 3. Jika ada anotasi, periksa AccessToken terlebih dahulu jika (! CheckParams ("AccessToken", httpservletRequest, httpservletResponse)) {return false; } // Periksa apakah token kedaluwarsa userid = authservice.getUserIdfromToken (httpservletrequest.getParameter ("accessToken"), httpservletrequest.getParameter ("platform")); if (userid == null) {logger.debug ("accessToken") timeout "); output (responseresult.builder.error (" accessToken kedaluwar ifcheck.Roles ()! = NULL && AUTHCHECK.ROLS (). Gagal (! IsMatch) {return false;}} true; Enkapsulasi hasil respons layanan
Tambahkan pembangun untuk memfasilitasi generasi hasil akhir
Public Class Responseresult {Public Static Class Builder {Responseresult Responseresult; Peta <String, Object> datamap = maps.newHashMap (); public builder () {this.responseresult = new responseresult (); } public builder (state string) {this.Responseresult = new responseresult (state); } public static Builder newBuilder () {return new Builder (); } Public Static Builder Success () {return new Builder ("Success"); } Kesalahan pembangun statis publik (pesan string) {builder builder = new builder ("error"); builder.responseresult.setError (pesan); pembangun kembali; } public builder append (tombol string, data objek) {this.datamap.put (key, data); kembalikan ini; } / *** Setel data daftar* @param data data* @return* / public builder setListData (daftar <?> Data) {this.datamap.put ("result", dataS); this.datamap.put ("Total", datas.size ()); kembalikan ini; } public builder setData (data objek) {this.datamap.clear (); this.responseresult.setData (data); kembalikan ini; } boolean wrapData = false; / ** * Bungkus data dalam data * @param wrapdata * @return */ wrap pembangun publik (boolean wrapData) {this.wrapData = wrapData; kembalikan ini; } public string build () {jsonObject jsonObject = new jsonobject (); jsonobject.put ("state", this.responseresult.getState ()); if (this.ResponsUnt.getState (). Equals ("error")) {jsonobject.put ("error", this.responseresult.getError ()); } if (this.responseresult.getData ()! = null) {jsonobject.put ("data", json.toJson (this.responseresult.getData ())); } else if (datamap.size ()> 0) {if (wrapData) {jsonobject data = new jsonobject (); datamap.foreach ((key, value) -> {data.put (key, value);}); jsonobject.put ("data", data); } else {datamap.foreach ((key, value) -> {jsonobject.put (key, value);}); }} return jsonobject.toJsonstring (); }} status string pribadi; data objek pribadi; kesalahan string pribadi; Public String getError () {return error; } public void setError (string error) {this.error = error; } public responseresult () {} public responseresult (String rc) {this.state = rc; } / ** * kembali saat berhasil * @param rc * @param hasil * / responseeresult publik (string rc, hasil objek) {this.state = rc; this.data = hasil; } public String getState () {return state; } public void setState (state string) {this.state = state; } objek publik getData () {return data; } public void setData (data objek) {this.data = data; }} Lebih elegan saat menelepon
@RequestMapping (value = {"/user/login", "/pc/user/login"}, menghasilkan = "application/json; charset = utf-8", method = {requestMethod.get, requestMethod.post}) @responseBody Login publik (string nama pengguna, string kata sandi string, integer) {platform integer) {Plasters. if (user! = null) {// Masuk ke string token = authservice.upDateToken (user, platform); return responseresult.builder .success (). lappend ("accessToken", token). lampai ("userid", user.getid ()) .build (); } return responseresult.builder.error ("Pengguna tidak ada atau kata sandi salah"). Build (); } terlindung string error (pesan string) {return responseresult.builder.error (pesan) .build (); } Protected String Success () {return responseresult.builder .success () .build (); } String Protected SuccessDataList (Daftar <?> Data) {return responseresult.builder .success () .wrap (true) // data package.setListData (data) .build (); }Meringkaskan
Di atas adalah seluruh konten artikel ini. Saya berharap konten artikel ini memiliki nilai referensi tertentu untuk studi atau pekerjaan semua orang. Jika Anda memiliki pertanyaan, Anda dapat meninggalkan pesan untuk berkomunikasi. Terima kasih atas dukungan Anda ke wulin.com.