リクエストオブジェクトを取得できないときにユーザーがログインしたセッション情報にアクセスする方法について説明します.


まず、この問題は長い間困っていて、ずっともっと適切な方法で解決できるかどうかを考えていました.次はまず需要を説明しましょう.理解していないところがあれば、疑問を提起して、良いアドバイスをしてください.ありがとうございます.
 
プロジェクトフレームワークはSSHであることはよく知られていますが、ユーザーログイン操作後、ユーザーログイン情報をセッションに押し込むのが一般的で、一般的にユーザーはデータのメンテナンス時にuserSessionの基本情報、例えば新規、修正、削除などを使用します.一般的にこのような操作では,要求の多くはaction入口からであるため,requestオブジェクトは必然的に取得できると考えられる.しかし、私たちの今のプロジェクトは少し特殊です.まず、私たちのプロジェクトの基本的な状況を紹介しましょう.
システムはブラウズ版とメンテナンス版の開発に分けられ、この2つの開発は2つの独立した開発チームによって行われ、1人の技術マネージャーが中間で協調しているだけなので、開発の過程で一部のメンテナンス版で発生したバグは現場でブラウズ版を開発した私たちがメンテナンスし、バグを修正しなければならない.
 
(以上はプロジェクトの大まかな背景資料ですが、以下を重点的に見ることができます)
ユーザがデータの新規、変更、削除を行う際にログを記録し、ログを記録するにはHibernateのブロッキングを利用して操作するが、Hibernateのブロッキングはsave()、update()、delete()などの方法でのみブロックされ、私がテストした限りnativateのsql文はブロックされないため、問題が発生した.sql文(delete from table where id=1)でデータを削除する場合、Hibernateイベントブロッカーはそれをブロックしません.偶然なことに、私たちのプロジェクトのすべてのエンティティがデータを削除する際にsql文で操作を行い、ログを記録することはありません.後でこの問題を発見するまで、関連する場所が多いため、以前のコードをすべて更新することは不可能で、既存のコードでわずかな修正しかできません. 
 
以前の実装は、次のような状況でした.
すべてのエンティティ削除メソッドを含むクラスAllDeleteSQLを作成します.JAvaでは,ユーザがデータを削除する際にこのクラスの静的メソッドを呼び出すだけで,データを入力したIDが削除操作を完了する(同様にHibernate操作イベントブロッカーによってログをブロックして記録できると考えている),このときrequestパラメータが入力されず,実際の結果ログの記録に失敗した.
私は今、解決策を考えています.
クラスを追加JAvaクラス、中にはThreadLocalのグローバル静的変数があり、ユーザーはログイン操作を行う際に、ユーザーのセッション情報をこのクラスのThreadLocal変数に格納し、次回は直接この変数から取得し、具体的なコードは以下の通りである.
    ThreadLocalUtil.java
   package **.**;
import **.UserSession;

/**
 *   :        session   
 *                    session  
 * @author Administrator
 */
public class ThreadLocalUtil {

	private static volatile ThreadLocal<UserSession> localSession = new ThreadLocal<UserSession>();  //  session   ThreadLocal    
	
	public ThreadLocalUtil() {
	}
	
	
	/**
	 *     session  set    localSession    
	 * @param us
	 */
	public static synchronized void setUserSessionToThreadLocal(UserSession us) {
		localSession.set(us);
	}
	
	/**
	 *      localSession      session  
	 * @return localSession
	 */
	public static synchronized UserSession getUserSessionToThreadLocal() {
		return localSession.get();
	}
	
	/**
	 *       localSession          
	 */
	public static void removeUserSession() {
		if(localSession.get()!=null) {
			localSession.remove();
		}
	}

}

 AllDeleteSQL.JAvaの一部の方法:
import **.UserSession;
import **.ThreadLocalUtil;

public class AllDeleteSQL {
	
	static CommDelete commDelete = CommDelete.getCommDelete();
	
	/**
	 *       
	 */
	public static String[] getRequirementDeleteSql(Long entityId, Long dataId){
		String sql = commDelete.delCommInfo(entityId, dataId);
		sql = sql + "update REQUIREMENT set DEL_FLAG = 1 where ID = " + dataId;
		sql = sql + ";";
		sql = sql + "update REQ_COMM set DEL_FLAG = 1 where REQ_ID = " + dataId;
		sql = sql + ";";
		sql = sql + getDelelteLogSQL(entityId,dataId);
		return sql.split(";");
	}
	
	/**
	 *                SQL
	 */
	public static String getDelelteLogSQL(Long entityId,Long dataId) {
		
		UserSession us = ThreadLocalUtil.getUserSessionToThreadLocal();
		StringBuilder dSql = new StringBuilder();
		if(us==null) {
			return "";
		} else {
			dSql.append("INSERT INTO EAM_LOG");
			dSql.append("(ID,  LOG_ENTITY,  LOG_DATA_ID,  LOG_TYPE,  LOG_ORG_ID,  LOG_PERSON_ID,  LOG_DATE)");
			dSql.append(" VALUES (");
			dSql.append(Long.parseLong(SequencerUtil.getSequence()));
			dSql.append(", ");
			dSql.append("(SELECT T.ENTITY_NAME_EN_FULL FROM EAM_ENTITY T WHERE T.ID=").append(entityId).append(")");
			dSql.append(", ");
			dSql.append("'" + dataId + "'");
			dSql.append(", ");
			dSql.append("'    '");
			dSql.append(", ");
			dSql.append("'" + us.getUserOrgId() + "'");
			dSql.append(", ");
			dSql.append("'" + us.getUserArchPersonId() + "'");
			dSql.append(", ");
			dSql.append("'" + DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss") + "'");
			dSql.append(" )");
			
			return dSql.toString();
		}
	}
}

ユーザーログイン時に要求されたアクションアクション部分コード:
        		//   session     ThreadLocal 
        		UserSession us = (UserSession)request.getSession().getAttribute(Constants.USER_KEY);
        		ThreadLocalUtil.setUserSessionToThreadLocal(us);

 
以上は一部のコードしか貼られていませんが、本体部分はすべて出てきて、私がこの問題を解決する考えを理解しているかどうか分かりません.strutsのaction要求はすべてスレッドが安全ではありません.ここでも私がなぜThreadLocalUtilにいるのか分かりません.JAvaでは同期メソッドを用いてアクセスを行い,マルチスレッドで同期変数更新後の値にリアルタイムでアクセスできるようにした.
ここで問題は解決されたと思います.私がテストしたとき、結果はそうではありません.AllDeleteSQLです.JAvaのgetDelelteLogSQL(args)メソッドではUserSessionus=ThreadLocalUtil.getUserSessionToThreadLocal();文はユーザーsession情報を取得するために来て、実際にこのように取得したus情報は安定していないで、時には空で、時には正確で、私が複数のブラウザで異なるユーザーにログインする時、取得したus情報は時には空で、時には現在のユーザーのsession情報で、時には他のユーザーのsession情報で、記録したログは正確ではなくて、問題は依然として徹底的に解決できません.
考えてみれば、解決策が得られず、関連資料がどのように処理されているのか、根源といえば、やはり私自身の基礎知識がしっかりしていないからだ.
 
ここでまず説明したいのは、ThreadLocalでユーザーsession情報にアクセスする案は、私たちの技術マネージャーが提案したもので、この方法で現在の問題を解決できると言っていますが、私は仕事をしていないので、ここで自分のニーズを説明して、皆さんと議論して、似たような状況に遭遇したことがあるかどうかを見てほしいということです.あなたたちがどのように解決したのか、私に勉強させてください.
 
もしあなたが辛抱強く見終わったら、私の表現能力に疑問を提起して、貴重な意見を提出することを歓迎して、そしてあなたにありがとうと言います;
もしあなたが見終わったら、私が今直面している問題に対してあなたの意見を発表することができて、あなたに深く感謝します.
最後に皆さんのお仕事が順調でありますように^^;