【问题标题】:Add data to session in play framework filter在播放框架过滤器中将数据添加到会话
【发布时间】:2016-10-30 04:16:01
【问题描述】:

我在向过滤器 (EssentialFilter) 中的会话添加数据时遇到问题。

在 scala api 中有方法 Result.withSessionResult.withNewSession 但在 java api 中没有。

如何使用新会话数据从过滤器返回结果?

试图这样做:

@Override
public EssentialAction apply(final EssentialAction next) {
    return EssentialAction.of( request -> {
        if (isAllowed(request)) {
            Accumulator<ByteString, Result> accumulator = next.apply(request);
            return accumulator.map(result -> {
                Session session = result.session();
                session.put("asdf", Long.toString(System.currentTimeMillis()));
                return result;
            }, executor);
        } else {
            return Accumulator.done(Results.unauthorized());
        }
    });
}

根据我在 debug/sources 中看到的情况,当结果返回 accumulator map 块时,结果已构建 ResponseHeader,并且会话的修改不会改变任何事情。

我尝试使用 asScala() 将结果转换为 scala 并提供新的会话项目 (withSession()),但我在将 java Session 转换为 scala/play Session 时遇到问题。也许有人可以指出如何正确地做到这一点?

Session session = result.session();
session.put("asdf", Long.toString(System.currentTimeMillis()));

play.api.mvc.Session newSession = ...?

return result.asScala().withSession(newSession).asJava();

[编辑]

我得到了这个工作:

scala.collection.immutable.Map<String, String> immutableMap = new scala.collection.immutable.HashMap<String,String>().empty();
for (Map.Entry<String, String> entry : session.entrySet()) {
  immutableMap = immutableMap.$plus(new Tuple2<>(entry.getKey(), entry.getValue()));
}
play.api.mvc.Session newSession = new play.api.mvc.Session(immutableMap);

但是...如您所见,它真的很丑。没有其他更好的方法可以做到这一点吗?

【问题讨论】:

    标签: java scala playframework-2.0


    【解决方案1】:

    我建议您将过滤器完全转换为 scala。即使在那里,它也不是没有痛苦的,但是,比你也同意的那个“丑陋”的代码要好。

    一个例子是:

      import akka.stream.Materializer
      import javax.inject._
      import play.api.Logger
      import play.api.mvc._
      import scala.concurrent.{ExecutionContext, Future}
    
      @Singleton
      class ExampleFilter @Inject()(
                                       implicit override val mat: Materializer,
                                       exec: ExecutionContext) extends Filter {
    
    
        override def apply(nextFilter: RequestHeader => Future[Result])
                          (requestHeader: RequestHeader): Future[Result] = {
          // Run the next filter in the chain. This will call other filters
          // and eventually call the action. Take the result and modify it
          // by adding a new header.
    
          val start = System.currentTimeMillis()
          nextFilter(requestHeader).map { result =>
            val end = System.currentTimeMillis() - start;
            Logger.debug(s"Service time in milliseconds: ${end}")
            result.withSession(requestHeader.session + ("ServiceTime" -> s"${end}"))
          }
        }
    
      }
    

    您可能知道这一点,但请将此视为鼓励仅将 scala 用于该部分。

    不幸的是,Java 并不适合玩。您经常遇到有关转换的问题。真的很痛苦……

    编辑:

    为了在您的 java 过滤器中包含 scala 过滤器,您应该在 Filters.java 中执行以下操作:(从 play-java 示例修改)(重要部分:exampleFilter.asJava()

    @Singleton
    public class Filters implements HttpFilters {
    
      private final Environment env;
      private final EssentialFilter exampleFilter;
    
      @Inject
      public Filters(Environment env, ExampleFilter exampleFilter) {
        this.env = env;
        this.exampleFilter = exampleFilter.asJava();
      }
    
      @Override
      public EssentialFilter[] filters() {
        // Use the example filter if we're running development mode. If
        // we're running in production or test mode then don't use any
        // filters at all.
        if (env.mode().equals(Mode.DEV)) {
          return new EssentialFilter[]{exampleFilter};
        } else {
          return new EssentialFilter[]{};
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-18
      • 1970-01-01
      • 1970-01-01
      • 2016-06-21
      • 1970-01-01
      相关资源
      最近更新 更多