2016-10-17 4 views
1

У меня возникают проблемы с добавлением данных в сеанс в фильтре (EssentialFilter).Добавить данные в сеанс в фильтре фрейма воспроизведения

В scala api есть способ Result.withSession и Result.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()); 
     } 
    }); 
} 

Из того, что я вижу в отладочных/источниках, в результате времени возвращается в картах блоке аккумулятора, результат устроится ResponseHeader и модификация сессии не измените вещь.

Я попытался преобразовать результат в scala с помощью asScala() и предоставить новые элементы сеанса (withSession()), но у меня возникают проблемы с преобразованием java-сессии в 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); 

но ... как вы можете видеть, что это действительно некрасиво. Разве нет другого, более привлекательного способа сделать это?

ответ

0

Я бы предположил, что вы полностью конвертируете свой фильтр в 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 для игры не очень хорошо подходит. Вы часто сталкиваетесь с проблемами конверсий. На самом деле больно ...

редактировать:

Для того, чтобы включить фильтр SCALA среди ваших ява фильтров вы должны сделать следующее в вашем Filters.java: (модифицированный из образца плей-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[]{}; 
    } 
    } 
} 
Смежные вопросы