休憩サービスの紹介
Restful Serviceは、近年より人気が高まっている建築モデルです。その軽量のWebサービスは、HTTPプロトコルのネイティブGET、PUT、POST、および削除を再生します。複雑なSOAPおよびXML-RPCと比較して、RESTモードWebサービスは明らかに簡潔であり、ますます多くのWebサービスがレストスタイルのデザインと実装を採用し始めています。たとえば、Amazon.comは、本検索のためにレストスタイルに近いWebサービスを提供しています。 Yahooが提供するWebサービスもレストスタイルです。休息は必ずしも正しい選択ではありません。 SOAPやWSDLベースの方法よりも、アプリケーションサーバーなどの独自のミドルウェアに依存するWebサービスを設計する方法として一般的になりました。ある意味では、URIやHTTPなどの初期のインターネット標準を強調することにより、RESTは大規模なアプリケーションサーバーの時代の前のWebアプローチへの回帰です。
次の図に示す例:
RESTを使用するための鍵は、リソースを抽象化する方法です。抽象化がより正確であればあるほど、休息の適用が良くなります。
休憩サービスの重要な原則:
1.すべてのオブジェクトにIDを与えます
2。オブジェクトを接続します
3.標準的な方法を使用します
4。リソースの複数の表現
5。ステートレス通信
この記事では、Spring Bootに基づいてSimple Rest Serviceフレームワークを構築する方法と、カスタムアノテーションを介してRESTサービス認証を実装する方法を紹介します。
フレームワークを構築します
pom.xml
まず、関連する依存関係を紹介し、データベースにMongoDBを使用し、キャッシュにRedisを使用します
注:ここではTomcatは使用されていませんが、Towです
<Dependency> groupId> org.springframework.boot </groupid> <artifactid> spring-boot-starter </artifactid> </dependency> <依存関係> olg.springframework.boot </groupid> <artifactid> spring-boot-startertest </deprency </scope> </scope> scope> scope> scope> <groupid> org.springframework.boot </groupid> <artifactid> spring-boot-starter-web </artifactid> <exclusions> <explusion> olg.springframework.boot </groupid> <artifactid> spring-boot-startertomcat </artifactid> </exprence> <groupid> org.springframework.boot </groupid> <artifactid> spring-boot-starter-dundertow </artifactid> </dependency> <! - redis support-> <dependency> <groupid> org.springframework.boot </groupid> <artifactid> spring-boot-data-redis> <! - mongodb support-> <dependency> groupid> org.springframework.boot </groupid> <artifactid> spring-boot-starter-data-mongodb </artifactid> </dependency>
Spring-Boot-Starter-WebサポートWebサービスを紹介します
spring-boot-starter-data-redisとspring-boot-starter-data-mongodbの紹介は、mongodbとredisを簡単に使用できます
構成ファイル
プロファイル機能
開発環境とオンライン環境の区別を促進するために、プロファイル機能を使用してApplication.Propertiesに追加できます。
spring.profiles.active=dev
次に、DEV構成ファイルとしてApplication-dev.Propertiesを追加します。
MONDB構成
データベースアドレスを構成するだけです
spring.data.mongodb.uri = mongodb:// ip:port/database?readpreference = primarypreferred
Redis構成
spring.redis.database = 0#redis serverアドレスspring.redis.host = ip#redis connection port spring.redis.port = 6379#redis server接続パスワード(デフォルトは空)spring.redis.password =#接続プールの接続数=接続の最大数(否定的な値を使用します)spring.redis.max-active = 8 spring.redis.pool.max-wait = -1#接続プールの最大アイドル接続poolspling.redis.pool.max-idle = 8#接続プールの最小アイドル接続spring.redis.pool.min-idle = 0
データアクセス
mongdb
MongDBへのアクセスは非常に簡単です。 Mongorepositoryを拡張するインターフェイスを直接定義できます。さらに、たとえば、JPA構文をサポートできます。
@componentPublic Interface userrepository extends mongorepository <user、integer> {public user findbyusername(string username);}それを使用するときは、@Autowiredアノテーションを追加してください。
@componentPublic Class AuthService拡張BaseService {@autowired userrepository userrepository; }Redisアクセス
stringredistemplateを使用して、redisに直接アクセスします
@componentPublic Class BaseService {@Autowired Protected MongoTemplate Mongotemplate; @Autowired Protected StringRedistEmplate StringRedistemplate; }データを保存します:
.stringRedistemplate.OpsforValue()。set(token_key、user.getId()+""、token_max_age、timeunit.seconds);
データの削除:
stringredistemplate.delete(getformattoken(accesstoken、platform));
Webサービス
コントローラークラスを定義し、retscontrollerを追加し、requestMappingを使用してURLルートを設定します
@RestControllerPublic Class AuthController拡張BaseController {@RequestMapping(value = {"/"}、生産= "application/json; charset = utf-8"、method = {requestmethod.get、requestmethod.post})@responsebody public string }}さあ、Hello Worldを見ることができるはずです!その
サービス認証
シンプルなアクセストークンメカニズム
ログインインターフェイスを提供します。認証が成功した後、AccessTokenが生成されます。将来インターフェイスにアクセスするとき、アクセストークンはそれにもたらされます。サーバーはAccessTokenを使用して、法律ユーザーかどうかを判断します。
便利なため、アクセストークンをRedisに保存して、有効期間を設定できます。
string token = encryptionutils.sha256hex(string.format( "%s%s"、user.getusername()、system.currenttimemillis())); string token_key = getformattoken(token、platform); this.stringredistemplate.opsforvalue()。
インターセプターアイデンティティ認証
統一されたアイデンティティ認証を容易にするために、統一された認証を実行するためのSpringのインターセプターメカニズムに基づいてインターセプターを作成できます。
パブリッククラスAuthCheckEnterceptorは、HandlerInterceptorを実装しています{}インターセプターを有効にするには、構成を追加するためにもう1つのステップが必要です。
@configurationPublic class Consofigurationはwebmvcconfigureradapterを拡張します{@autowired authcheckinterceptor authcheckEnterceptor; @Override public void addInterceptors(interceptorregistry registry){super.addinterceptors(registry); // Interceptor registry.AddDINTERCEPTOR(authCheckEnterceptor).addpathpatterns( "/**");を追加します。 }}カスタム認証注釈
たとえば、許可認証を改善するために、一部のインターフェイスは特定のアクセス許可を持つ人々によってのみアクセスでき、カスタムアノテーションを通じて簡単に解決できます。カスタムアノテーションでは、役割を追加するだけです。
/***許可確認Annotation*/@Target(ElementType.Method)@retention(RetentionPolicy.runtime)@documentedpublic @interface authcheck {/***役割リスト* @return*/string [] choles()default {};}検査ロジック:
インターフェイスがAuthCheckアノテーションで追加されている限り、それはユーザーに記録されている必要があります
ログインに加えて、役割が指定されている場合、ユーザーには対応する役割も必要です。
string [] Ingroreurls = new String [] {"/user/.*"、 "/cat/.*"、 "/app/.*"、 "/error"}; Public Boolean Prehandle(httpservletrequest httpservletrequest、httpservletresponse httpservletresponse、object handler)スロー例外{// 0 publicパラメーターを検証するif( "プラットフォーム"、httpservletrequest、httpservletresponse){return false; } // 1。検証url string url = httpservletrequest.getRequesturi()。toString(); for(string Ingroreurl:Ingroreurls){if(url.Matches(Ingroreurl)){return true; }} // 2。クエリ検証注釈Handlermethod Handlermethod =(Handlermethod)ハンドラー。メソッドメソッド= handlermethod.getMethod(); // Query Annotation AuthCheck authcheck = method.getAnnotation(authcheck.class); if(authcheck == null){//注釈なし、返品はtrueではありません。 } // 3。アノテーションがある場合、最初にAccessTokenをチェックしてくださいif(!checkparams( "AccessToken"、httpservletrequest、httpservletResponse)){return false; } //トークンが整数userid = authservice.getuseridfromtoken(httpservletrequest.getParameter( "AccessToken")、httpservletrequest.getParameter( "Platform")); if(userid == null){logger.debug( "AccessToken")Timeout "); output(responseresult.builder.error(" accesstoken expared ")。 authcheck.roles()!= null && holes> 0){authservice.getuser(userid);失敗した場合(!ismatch){false;}}}サービス応答結果カプセル化
ビルダーを追加して、最終結果の生成を容易にします
public class ResponseResult {public static class Builder {responseresult responseresult; map <string、object> datamap = maps.newhashmap(); public builder(){this.responseresult = new Responseresult(); } public Builder(string state){this.responseresult = new ResponseResult(state); } public static Builder newBuilder(){return new Builder(); } public static Builder success(){return new Builder( "success"); } public static Builderエラー(String Message){Builder Builder = new Builder( "Error"); Builder.responseresult.setError(メッセージ);返品ビルダー。 } public Builder append(string key、object data){this.datamap.put(key、data);これを返します。 } / ***リストデータを設定* @param Datas data* @return* / public Builder setlistdata(list <?> datas){this.datamap.put( "result"、datas); this.datamap.put( "total"、datas.size());これを返します。 } public Builder setData(オブジェクトデータ){this.datamap.clear(); this.responseresult.setdata(data);これを返します。 } boolean wrapdata = false; / ** *データのラップデータ * @param wrapdata * @return */ public Builder wrap(boolean wrapdata){this.wrapdata = wrapdata;これを返します。 } public string build(){jsonobject jsonobject = new jsonobject(); jsonobject.put( "state"、this.responseresult.getState()); if(this.responseresult.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(); }} private string state;プライベートオブジェクトデータ。プライベート文字列エラー; public string getError(){return error; } public void setError(string error){this.error = error; } public ResponseResult(){} public Responseresult(string rc){this.state = rc; } / ** *成功したときに戻ります * @param rc * @param result * / public responseresult(string rc、object result){this.state = rc; this.data = result; } public string getState(){return state; } public void setState(string state){this.state = state; } public Object getData(){return data; } public void setData(オブジェクトデータ){this.data = data; }}呼び出すときはもっとエレガントになります
@RequestMapping(value = {"/user/login"、 "/pc/user/login"}、生産= "application/json; charset = utf-8"、method = {requestmethod.get、requestmethod.post})@responsebody public string login(string username、string platident.-user = user = user = user = user = user = user = user = user = user fast erservice; if(user!= null){// string token = authservice.updateToken(user、platform); RESPONSERESULT.BUILDER .SUCCESS().APPEND( "AccessToken"、token).Append( "userId"、user.getId()).build(); } RESPONSERESULT.BUILDER.ERROR( "ユーザーは存在しないか、パスワードが間違っていない")。build(); } protected string error(string message){return responseresult.builder.error(message).build(); } protected string success(){return responseresult.builder .success().build(); }保護された文字列successdatalist(list <?> data){return responseresult.builder .success().wrap(true)// data package.setlistdata(data).build(); }要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。