自定义作用域

以 HttpSession 为例,实现一个 HttpSession 作用域。

  1. public class SessionScope implements Scope {
  2. public static final ThreadLocal<HttpSession> session
  3. = new ThreadLocal<HttpSession>();
  4.  
  5. public <T> Provider<T> scope(Object key, Provider<T> provider) {
  6. HttpSession httpSession = session.get();
  7. if (httpSession == null) {
  8. return provider;
  9. }
  10. // 为了避免保存到 Session 中的 Bean 和本身 Session 中的数据 key
  11. // 出现冲突,增加一个前缀用于区分
  12. String keyStr = "session_scope_" + key.toString();
  13. Object attribute = httpSession.getAttribute(keyStr);
  14. Provider<T> finalProvider = provider;
  15. if (attribute == null) {
  16. httpSession.setAttribute(keyStr, provider);
  17. } else {
  18. finalProvider = (Provider<T>) httpSession.getAttribute(keyStr);
  19. }
  20. return finalProvider;
  21. }
  22. }

然后通过一个 Filter 每次 request 请求到来的时候把 Session 对象设置到 ThreadLocal 中。

  1. public class ConfigSession implements Filter {
  2. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  3. throws IOException, ServletException {
  4. try {
  5. if (SessionScope.session.get() != null) {
  6. SessionScope.session.remove();
  7. }
  8. SessionScope.session.set(((HttpServletRequest) request).getSession(true));
  9. chain.doFilter(request, response);
  10. } finally {
  11. if (SessionScope.session.get() != null) {
  12. SessionScope.session.remove();
  13. }
  14. }
  15. }
  16. }

最后我们在创建 Hasor 的时候把 Scope 配置上,这里由于要配置 Filter 因此使用 WebModule

  1. public class StartModule extends WebModule {
  2. public void loadModule(WebApiBinder apiBinder) throws Throwable {
  3. ...
  4. apiBinder.filter("/*").through(0, new ConfigSession());
  5. apiBinder.registerScope("session", new SessionScope());
  6. ...
  7. }
  8. }

接下来配置每次创建 UserInfo 对象时都是 Session 内唯一:

  1. apiBinder.bindType(UserInfo.class).toScope("session");