首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

SpringMVC 在 Controller 中優雅獲取 Session 的實作範例

     編輯:Java 相關知識

在 SpringMVC 開發中,Controller 方法若需存取 Session 資料,最直觀的方式是在方法簽名中直接宣告 HttpSession 參數,框架會自動注入。例如:

@RequestMapping(value = "/logout")
public String logout(HttpSession session) {
    session.removeAttribute("user");
    return "/login";
}

雖然這樣寫法簡單直接,但會讓 Controller 強依賴 Servlet API,不利於單元測試與程式碼的純粹性(POJO 化)。為了解耦,我們可以自訂註解搭配 HandlerMethodArgumentResolver 實現參數自動解析,從 Session 中取值並注入 Controller 方法參數。

核心思路

  1. 定義一個註解 @SessionScope,可標註在方法或參數上,屬性 value 指定 Session 中的鍵名。
  2. 實作 SessionScopeMethodArgumentResolver 實作 HandlerMethodArgumentResolver 介面,在 supportsParameter 判斷參數或方法是否帶有該註解,在 resolveArgument 中從 NativeWebRequest 的 Session 作用域取值並回傳。
  3. 在 SpringMVC 設定檔中將該 Resolver 註冊到 RequestMappingHandlerAdapter 的 customArgumentResolvers 列表。

程式碼實作

1. 自訂註解

@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SessionScope {
    String value();
}

2. 參數解析器

public class SessionScopeMethodArgumentResolver implements HandlerMethodArgumentResolver {
    private static final Logger logger = LoggerFactory.getLogger(SessionScopeMethodArgumentResolver.class);

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(SessionScope.class)
                || parameter.getMethodAnnotation(SessionScope.class) != null;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        String attrName = null;
        SessionScope ann = parameter.getParameterAnnotation(SessionScope.class);
        if (ann != null) {
            attrName = ann.value();
        } else {
            ann = parameter.getMethodAnnotation(SessionScope.class);
            if (ann != null) attrName = StringUtils.defaultString(ann.value());
        }
        if (attrName != null) {
            return webRequest.getAttribute(attrName, RequestAttributes.SCOPE_SESSION);
        }
        return null;
    }
}

3. SpringMVC 設定註冊

<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <bean class="com.example.resolver.SessionScopeMethodArgumentResolver" />
    </mvc:argument-resolvers>
</mvc:annotation-driven>
<mvc:default-servlet-handler />

注意: mvc:annotation-driven 必須在 mvc:default-servlet-handler 之前宣告,否則可能導致靜態資源處理異常。

使用範例

在方法層級標註,參數名自動對應 Session 鍵值:

@RequestMapping(value = "/index")
@SessionScope("currentUser")
public ModelAndView index(User currentUser) {
    ModelAndView mav;
    if (currentUser == null || currentUser.getId() == null) {
        mav = new ModelAndView("/login");
    } else {
        mav = new ModelAndView("/index");
    }
    return mav;
}

或在參數層級標註:

@RequestMapping(value = "/welcome")
public String welcome(@SessionScope("currentUser") User currentUser) {
    return "/main";
}

補充說明

Session 資料的寫入(如登入後放入使用者物件)仍建議搭配 @SessionAttributes 與 ModelMap 方式,或整合 Apache Shiro 等安全框架由其統一管理 Subject 與 Session,架構更清晰。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved