1. 程式人生 > >如何在Service層獲取使用者session中儲存的使用者資訊的方法(Filter+ThreadLocal)

如何在Service層獲取使用者session中儲存的使用者資訊的方法(Filter+ThreadLocal)

/**
 * 
 * Description: 用ThreadLocal提供一個儲存執行緒內變數的地方. <p/>
 * 客戶端程式碼可以用靜態方法儲存和獲取執行緒內變數,不需要依賴於HttpSession.
 * web層的Controller可通過此處向business層傳入user_id之類的變數
 * 
 */
@SuppressWarnings("unchecked")
public class UserSession {
    /** * 儲存變數的ThreadLocal,保持在同一執行緒中同步資料. */
    private static final ThreadLocal SESSION_MAP = new ThreadLocal();


    /** * 工具類的protected構造方法. */
    protected UserSession() {
    }

    /**
     * 獲得執行緒中儲存的屬性.
     * 
     * @param attribute
     *            屬性名稱
     * @return 屬性值
     */
    public static Object get(String attribute) {
        Map map = (Map) SESSION_MAP.get();
        System.out.println(map.toString());
        System.out.println(map.containsKey("usersession"));


        return map.get(attribute);
    }

    /**
     * 獲得執行緒中儲存的屬性,使用指定型別進行轉型.
     * 
     * @param attribute
     *            屬性名稱
     * @param clazz
     *            型別
     * @param <T>
     *            自動轉型
     * @return 屬性值
     */
    public static <T> T get(String attribute, Class<T> clazz) {

        return (T) get(attribute);
    }

    /**
     * 設定制定屬性名的值.
     * 
     * @param attribute
     *            屬性名稱
     * @param value
     *            屬性值
     */
    public static void set(String attribute, Object value) {
        Map map = (Map) SESSION_MAP.get();

        if (map == null) {
            map = new HashMap();
            SESSION_MAP.set(map);
        }

        map.put(attribute, value);
    }

}

我在使用者登入的時候 執行:

UserSession.set("User",User);

然後在我需要的service層中執行:

UserSession.get("User");
//UserSession.get("User",User.class);

此時會出現一個bug:這樣第一次取到session中的User物件,後面的請求都取不到了。

解決方法:ThreadLocal 是當前請求(前臺對後臺的每個請求都會被認為是一個獨立的執行緒)的物件。每一次執行緒請求的時候,都需要從session中把session物件取出來。放到ThreadLocal中去(最好的方式是通過filter攔截器實現)。 這樣才能從service中取得到。acegi就是這麼處理的

攔截器程式碼:

public class SessionFilterUtil implements Filter {

    public void destroy() {

    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest session_request = (HttpServletRequest) request;
        HttpServletResponse session_response = (HttpServletResponse) response;
        HttpSession session = session_request.getSession();
        User user = (User) session.getAttribute("user");
        if (user != null) {
            UserSession.set("userSession", session);
            chain.doFilter(request, response);
        } else {
            String uri = session_request.getRequestURI();         // 獲取uri資訊
            String ctx = session_request.getContextPath();         // 獲取上下文,如/專案名
            if(uri.indexOf("!") != -1){
                String method = uri.substring(uri.indexOf("!") + 1, uri.indexOf(".action"));
                if(method.equals("bistore_login")){
                    chain.doFilter(request, response);
                }
            }
            session_response.getWriter().print("<script>location.href='" + ctx + "/adf/login!bistore_login.action'</script>");
        }
    }

    public void init(FilterConfig filterConfig) throws ServletException {

    }

}