セッション構造 さっそく写真をご覧ください 上の図をよく見ると、次のような結論が導き出されます。
まず、HttpSession ラッパー クラスを見てみましょう。 標準セッションファサード このクラスでは、外観パターン(Facde)の実践的な応用を学ぶことができます。その定義は以下の通りです。 パブリッククラスStandardSessionFacadeはHttpSessionを実装します では、このクラスはどのようにして Session 機能を実装するのでしょうか。次のコードから、このクラスが HttpSession の実際の実装クラスではなく、実際の HttpSession 実装クラスのラッパーであり、デザイン パターンのファサード モードである HttpSession インターフェイスのメソッドのみを公開していることは簡単にわかります。 プライベート最終HttpSessionセッション; パブリックStandardSessionFacade(HttpSessionセッション) { this.session = セッション; } では、HttpSession 実装クラスを使用しないのはなぜでしょうか? 図 1 によると、 HttpSession の実際の実装クラスは さらに、ファサード クラスを経由せずに 実際、それは可能です。リフレクション メカニズムを通じて @GetMapping("/s") パブリック String sessionTest(HttpSession httpSession) は、ClassNotFoundException、NoSuchFieldException、IllegalAccessException をスローします { StandardSessionFacade セッション = (StandardSessionFacade) httpSession; クラス targetClass = Class.forName(session.getClass().getName()); // 可視性を変更する フィールド standardSessionField = targetClass.getDeclaredField("session"); 標準セッションフィールドにアクセス可能(true)を設定します。 //StandardSession を取得します。 standardSession = (StandardSession) standardSessionField.get(session); standardSession.getManager().toString() を返します。 } 標準セッション このクラスの定義は次のとおりです パブリッククラスStandardSessionは実装します HttpSession、セッション、シリアル化可能 インターフェースを通じて、JavaEE 標準の 図 1 では、 シリアル化 前のセクションで、リフレクション メカニズムを通じて @GetMapping("/s") パブリック void sessionTest(HttpSession httpSession、HttpServletResponse 応答) は、ClassNotFoundException、NoSuchFieldException、IllegalAccessException、IOException をスローします { StandardSessionFacade セッション = (StandardSessionFacade) httpSession; クラス targetClass = Class.forName(session.getClass().getName()); // 可視性を変更する フィールド standardSessionField = targetClass.getDeclaredField("session"); 標準セッションフィールドにアクセス可能(true)を設定します。 //StandardSession を取得します。 standardSession = (StandardSession) standardSessionField.get(session); //観察のためにいくつかのデータを保存しますstandardSession.setAttribute("msg","hello,world"); standardSession.setAttribute("user","kesan"); standardSession.setAttribute("パスワード", "いいね"); standardSession.setAttribute("tel", 10086L); //シリアル化された結果を Http レスポンスに直接書き込みます。ObjectOutputStream objectOutputStream = new ObjectOutputStream(response.getOutputStream()); standardSession.writeObjectData(オブジェクト出力ストリーム); } 何も問題がなければ、このインターフェースにアクセスするブラウザはダウンロード操作を実行し、最終的にファイルを取得します。 シリアル化されたファイルがどのようにデータを整理するかを調べることはあまり意味がないので、お勧めしません。 本当に興味があるなら、次のコード リスナー JavaEE 標準では、 パブリック void setAttribute(文字列名、オブジェクト値、ブール値通知) { //無関係なコードを省略//上記で構成されたイベントリスナーを取得しますObject listeners[] = context.getApplicationEventListeners(); if (リスナー == null) { 戻る; } (int i = 0; i < listeners.length; i++) { //HttpSessionAttributeListener のみが実行可能 if (!(listeners[i] instanceof HttpSessionAttributeListener)) { 続く; } HttpSessionAttributeListener リスナー = (HttpSessionAttributeListener) listeners[i]; 試す { //現在のスレッドでリスナーの処理メソッドを呼び出す if (unbound != null) { if (unbound != value || manager.getNotifyAttributeListenerOnUnchangedValue()) { // キーの値が変更された場合は、リスナーの attributeReplaced メソッドを呼び出します。context.fireContainerEvent("beforeSessionAttributeReplaced", listener); if (イベント == null) { イベント = 新しい HttpSessionBindingEvent(getSession(), name, unbound); } リスナー.attributeReplaced(イベント); context.fireContainerEvent("afterSessionAttributeReplaced", リスナー); } } それ以外 { //新しいキーが追加された場合は、attributeAdded メソッドを実行します。context.fireContainerEvent("beforeSessionAttributeAdded", listener); if (イベント == null) { イベント = 新しい HttpSessionBindingEvent(getSession(), 名前、値); } リスナー.attributeAdded(イベント); context.fireContainerEvent("afterSessionAttributeAdded", リスナー); } } キャッチ (Throwable t) { //例外処理} } } セッションライフサイクル セッションを保存する方法 Sessionの構造を理解した上で、 まず、 パブリックStandardSession(マネージャーマネージャー) { // デフォルトで呼び出されている Object クラスのコンストラクターを呼び出します // ここで再度宣言します。目的がわかりません。このクラスには以前に親クラスがあったのでしょうか? 素晴らしい(); this.manager = マネージャー; //アクセスカウントを有効にするかどうか if (ACTIVITY_CHECK) { accessCount = 新しい AtomicInteger(); } } 保護された Map<String, Session> sessions = 新しい ConcurrentHashMap<>(); このプロパティを調べると、 Session に関連するすべての操作は セッションを作成する方法 では、セッションはどのように作成されるのでしょうか?私は次のメソッド
(1000*60*カウンター)/(int)(現在 - 最古)
パブリックセッションcreateSession(String sessionId) { // セッションが制限を超えているかどうかを確認し、超えている場合は例外をスローします if ((maxActiveSessions >= 0) && (getActiveSessions() >= maxActiveSessions)) { 拒否されたセッション++; 新しいTooManyActiveSessionsExceptionをスローします( sm.getString("managerBase.createSession.ise"), 最大アクティブセッション数); } //このメソッドは StandardSession オブジェクトを作成します Session session = createEmptySession(); //セッション内の必要な属性を初期化します。session.setNew(true); //セッションは利用可能ですか? session.setValid(true); //作成時間 session.setCreationTime(System.currentTimeMillis()); //最大セッションタイムアウトを設定します。session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60); 文字列 id = セッションID; id == nullの場合{ id = セッションIDを生成する(); } セッションIDを設定します。 セッションカウンタ++; // セッションが作成された時刻を記録します。これは、セッションの作成率をカウントするために使用されます。 // 同様に、セッションの有効期限である ExpireRate があります。 // 他のスレッドが sessionCreationTiming を操作する可能性があるため、SessionTiming をロックする必要があります。timing = new SessionTiming(session.getCreationTime(), 0); 同期 (セッション作成タイミング) { //sessionCreationTimingはLinkedListです //したがって、ポーリングはリンク リストの先頭にあるデータ、つまり最も古いデータを削除します sessionCreationTiming.add(timing); セッション作成タイミング.poll(); } セッションを返す。 } セッションの破棄 Session を破棄するには、 @オーバーライド パブリック void 削除(セッション セッション、ブール値 更新) { // 期限切れのセッション情報をカウントする必要があるかどうかを確認します if (update) { 長いtimeNow = System.currentTimeMillis(); 整数タイムアライブ = (int) (timeNow - session.getCreationTimeInternal())/1000; セッションの最大アライブ時間を更新します(timeAlive); 期限切れセッションを増加および取得します。 SessionTiming タイミング = new SessionTiming(timeNow, timeAlive); 同期 (セッション有効期限) { セッション有効期限を追加します。タイミングを設定します。 セッション有効期限.poll(); } } //マップからセッションを削除する if (session.getIdInternal() != null) { セッションを削除します。 } } 破壊の時 積極的な破壊
パブリックボイド無効化() { if (!isValidInternal()) 新しい IllegalStateException をスローする (sm.getString("standardSession.invalidate.ise")); // このセッションを期限切れにする 期限切れ(); } @オーバーライド パブリックボイド有効期限(){ 有効期限が切れます(true); } パブリックvoid有効期限(ブール値通知) { //コードを省略//ConcurrentHashMap からセッションを削除します manager.remove(this, true); //省略されたコードは主に、セッションが破棄されることを各リスナーに通知するためのものです} タイムアウト破壊 アクティブな破棄に加えて、セッションの有効期限を設定することもできます。有効期限が切れると、バックグラウンド スレッドによってセッションがアクティブに破棄されます。セッションの有効期限を短く設定し、 下の図に示すように、セッションに 30 秒のタイムアウトを設定します。 次に メソッドにブレークポイントを設定し、以下に示すように30秒間待ちます。 Tomcat は、サブコンポーネントの @オーバーライド パブリック void backgroundProcess() { カウント = (カウント + 1) % プロセス有効期限頻度; (カウント == 0)の場合 プロセス有効期限切れ(); } パブリックボイドプロセス期限切れ() { 長いtimeNow = System.currentTimeMillis(); セッション sessions[] = findSessions(); int 有効期限は 0 です。 ログのデバッグが有効かどうか log.debug("" + getName() + " の期限切れセッションを " + timeNow + " sessioncount " + sessions.length に開始します); //JConsole の図から、isValid によって expire メソッドが呼び出される可能性があることがわかります。for (int i = 0; i < sessions.length; i++) { セッション[i]がnullの場合、セッション[i].isValid()がtrueになります。 ここで期限切れ++; } } 長いtimeEnd = System.currentTimeMillis(); ログのデバッグが有効かどうか log.debug("期限切れセッションの終了 " + getName() + " processingTime " + (timeEnd - timeNow) + " 期限切れセッション: " + expireHere); 処理時間 += ( 終了時間 - 現在時間 ); } /** * このメソッドは、定期的にコンテキスト/コンテナによって呼び出されます。 * ベースで、マネージャーが実装できるようにします * セッションの期限切れなどの定期的なタスクを実行するメソッド。 */ パブリック void backgroundProcess(); 要約する Session のデータ構造を下図に示します。簡単に言うと、 つまり、セッションに個別のデータを追加する代わりに、以下に示すように個別のデータをオブジェクトにカプセル化するとパフォーマンスが向上します。 //悪い httpSession.setAttribute("user","kesan"); httpSession.setAttribute("ニックネーム","いいね"); httpSession.setAttribute("sex","男"); .... //良い ユーザー kesan = userDao.getUser() httpSession.setAttribute("user", kesan); セッションのリスナーを構成すると、セッションへの変更によってリスナー メソッドが現在のスレッドで直接実行されるため、リスナー内でブロックされる可能性のあるメソッドを実行しないことが最善です。 Tomcat はバックグラウンド スレッドを開始し、定期的に 思考の移行 オブジェクト生成率アルゴリズム このアルゴリズムの設計は非常に興味深く、他のプロジェクトにも適用できるため、次のようにまとめられます。 まず、固定サイズ (たとえば 100) のリンク リストが生成され、null 要素で埋められます。 新しいオブジェクトが作成されると、作成時刻がリンク リスト (もちろん、カプセル化されたオブジェクト) の末尾に追加され、リンク リストの先頭ノードが削除されます。このとき、削除されるオブジェクトは、null ノードか、リンク リストに最初に追加されたノードのいずれかです。オブジェクトの生成率を計算する場合は、リンク リスト内の null 以外の要素の数をカウントし、現在の時刻とオブジェクトが最初に作成された時刻の差で割って、率を取得します。 (時間単位の変換に注意してください) 以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: MySQL 5.7 における基本的な JSON 操作ガイド
以前は、フロートはレイアウトによく使用されていましたが、フローティングレイアウトを使用すると親要素の...
バイナリ docker 19.03 バージョンがインストール後に docker0 ブリッジを自動的に...
1. データベースにログインするには、rootユーザーを使用することをお勧めします。 mysql -...
1.17.9 本当はもっと美味しいNginx のダウンロード アドレス: https://nginx...
PHP7が出たので、最新バージョンのファンとしては、早速アップグレードして体験してみました。しかし...
コンテンツ プロパティは CSS 2.1 で導入され、:before および :after 疑似要素...
なぜログを読む必要があるのでしょうか?たとえば、コンテナの起動に失敗したがプロンプトが表示されない場...
しばらく前にシステムを再インストールしましたが、バックアップを取っていなかったので、コンピューター上...
テキストシャドウテキストに影を追加します。テキストとテキスト装飾に複数のシャドウを追加することができ...
目次1. 仮想DOMとは何ですか? 2. 仮想 DOM が必要な理由3. 仮想DOMはどのようにして...
目次JSONとはなぜこの技術なのでしょうか? JSONの使い方- データ形式- メモ- JSには2つ...
実際の開発では、MySQL の主キーは重複できず、主キーが自動的にインクリメントされることがあります...
フロントエンドの担当者であれば、面接でも仕事中でも、「CSS を使用して中央揃えにする」という効果に...
目次序文環境の準備カテゴリコンポーネントアプリのコンポーネント1. デフォルトスロット2. 名前付き...
需要シナリオ: 既存の PXC 環境には大量のデータがあります。新しく購入したサーバーをこのクラスタ...