Подтвердить что ты не робот

Написание пользовательских фильтров для Play! 2.2 в Java

У меня простой сценарий: автоматически добавляйте заголовок ответа на каждый HTTP-ответ; и я хочу сделать это на Java.

В src/play-filters-helpers/src/main/java/play/filters/* есть примеры Actions, которые можно использовать в качестве аннотаций. Я бы не хотел добавлять @AddMyHeader к каждому обработчику.

Глядя на Scala Фильтры в src/play-filters-helpers/src/main/scala/play/filters/* и GzipFilter, я вижу ясный механизм, но я не достаточно знаком с Scala для экстраполяции на Java.

Итак: куда мне идти?

4b9b3361

Ответ 1

К сожалению, пока еще нет хорошего способа создания и использования фильтров из Java. Но вы можете легко справиться с Scala.

Создайте новый файл app/filters/AddResponseHeader.scala, содержащий:

package filters

import play.api.mvc._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

object AddResponseHeader extends Filter {
  def apply(f: (RequestHeader) => Future[SimpleResult])(rh: RequestHeader): Future[SimpleResult] = {
    val result = f(rh)
    result.map(_.withHeaders("FOO" -> "bar"))
  }
}

И создайте новый файл app/Global.scala, содержащий:

import filters.AddResponseHeader
import play.api.mvc.WithFilters

object Global extends WithFilters(AddResponseHeader)

Для каждого ответа должен применяться новый заголовок ответа.

UPDATE: есть способ использовать это в файле Global.java:

@Override
public <T extends EssentialFilter> Class<T>[] filters() {
    return new Class[] {AddResponseHeader.class};
}

И также измените object AddResponseHeader выше на class AddResponseHeader.

Ответ 2

Чтобы добавить настраиваемый фильтр (MyFilter.class), создайте файл Global.java в корневом пакете. Протестировано в PlayFramework 2.3.x и Java (JDK8)

import play.GlobalSettings;
import play.api.mvc.EssentialFilter;

public class Global extends GlobalSettings {
    @Override
    public <T extends EssentialFilter> Class<T>[] filters() {
        return new Class[]{MyFilter.class};
    }
}

Ответ 3

Для создания Play Filters нет хорошего API Java. Тем не менее, вы можете адаптировать существующие API Scala в хороший шаблон Java.

Например:

import play.api.mvc.*;
import scala.Function1;
import scala.concurrent.Future;
import scala.runtime.AbstractFunction1;

public abstract class JavaFilter implements Filter {

@Override
public Future<Result> apply(Function1<RequestHeader, Future<Result>> nextFilter, RequestHeader requestHeader) {
    return nextFilter
            .apply(requestHeader)
            .map(new AbstractFunction1<Result, Result>() {
                     @Override
                     public Result apply(Result currentResult) {
                         return Apply(currentResult, requestHeader);
                     }
                 },
                    play.api.libs.concurrent.Execution.defaultContext());
}

@Override
public EssentialAction apply(EssentialAction next) {
    return Filter$class.apply(this, next);
}

public abstract Result Apply(Result currentResult, RequestHeader requestHeader);
}

Пример реализации:

import play.api.mvc.RequestHeader;
import play.api.mvc.Result;

public class HelloFilter extends JavaFilter {

@Override
public Result Apply(Result currentResult, RequestHeader requestHeader) {
    if (requestHeader.headers().get("X-Filter").isDefined()) {
        ResultAdapter resultAdapter = new ResultAdapter(currentResult);
        return resultAdapter.WithHeader("X-Hello", "World!");
    }
    return currentResult;
  }
}

Для дальнейшего объяснения того, как это работает, см. мою статью в блоге об этом здесь