sparkjava: Должны ли маршруты быть в основном методе?

Я новичок в sparkjava, и в целом мне это нравится. Однако нужно ли определять новые маршруты/конечные точки в основном методе? Для любого важного веб-приложения это приведет к очень длинному основному методу или мне нужно иметь несколько основных методов (и, следовательно, разделить ресурсы сервера между несколькими экземплярами).

Эти две страницы документации sparkjava, по-видимому, определяют маршруты в основном методе: http://sparkjava.com/documentation.html#routes и здесь http://sparkjava.com/documentation.html#getting-started .

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

=========

Вот полное решение, которое я сделал на основе ответа Эндрю. На мой взгляд, добавление конечных точек вне основного метода должно быть частью страницы документации sparkjava:

Основной метод:

public static void main(String[] args) {
    //Do I need to do something more with the Resource instance so that sparkjava notices it and/or reads the routes?
    Resource resource= new Resource(new Service());
}

Мой ресурс:

import static spark.Spark.*;
class Resource{

    private Service service;

    Resource(Service service){
        this.service = service;
        setupEndpoints();
    }

    private void setupEndpoints() {

        get("/user/:id", "application/json",(request, response)
                -> service.find(request.params(":id")), new JsonTransformer());

        get("/users", "application/json", (request, response)
                -> service.findAll(), new JsonTransformer());
    }
}

Мой сервис:

public class Service {

    public Object find(String id) {
        return null;
    }

    public Object findAll() {
        return null;
    }
}

Мой JsonTransformer:

import spark.ResponseTransformer;
public class JsonTransformer implements ResponseTransformer {
    @Override
    public String render(Object model) throws Exception {
        return null;
    }
}

person thebiggestlebowski    schedule 24.01.2016    source источник


Ответы (4)


Вы можете установить маршруты, где вы хотите. Вам просто нужен метод настройки вызова в основном потоке. например

 public static void main(String[] args){
     Resource resource= new Resource(new Service());
 }

 class Resource{

    private Service service;

    Resource(Service service){
      this.service = service;
      setupEndpoints();
    }

    private void setupEndpoints() {

      get("/user/:id", "application/json",(request, response)
            -> service.find(request.params(":id")), new JsonTransformer());

      get("/users", "application/json", (request, response)
            -> service.findAll(), new JsonTransformer());
    }
 }
person Andrew    schedule 24.01.2016

Вот идея дизайна, которую вы можете использовать, когда нужно настроить несколько конечных точек:

Сначала создайте интерфейс конструктора:

public interface EndpointBuilder {
    void configure(Service spark, String basePath);
}

Теперь предположим, что у вас есть один из многих других ресурсов конечных точек отдыха для настройки:

public class CustomerEndpoint implements EndpointBuilder {

    private final CustomerService customerService;

    public CustomerEndpoint(CustomerService service) {
        this.customerService = service;
    }

    @Override
    public void configure(Service spark, String basePath) {

        spark.get(basePath + "/customer", (req, res) -> {
            return "hello";
        });
    }
}

Наконец, создайте класс RestContext, который будет содержать экземпляр spark и позволит вам настроить любые маршруты по вашему желанию:

public class RestContext {

    private static final Logger logger = LoggerFactory.getLogger(RestContext.class);

    private final Service spark;

    private final String basePath;

    public RestContext(int port, String basePath) {
        this.basePath = basePath;
        spark = Service.ignite().port(port); // import spark.Service;
    }

    public void addEndpoint(EndpointBuilder endpoint) {

        endpoint.configure(spark, basePath);
        logger.info("REST endpoints registered for {}.", endpoint.getClass().getSimpleName());
    }

    // Then you can even have some fun:
    public void enableCors() {

        spark.before((request, response) -> {
            response.header("Access-Control-Allow-Origin", "*");
            response.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
            response.header("Access-Control-Allow-Headers", "Content-Type, api_key, Authorization");
        });

        logger.info("CORS support enabled.");
    }
}

Вы должны иметь возможность использовать этот класс контекста в своем основном методе (и, возможно, в ваших тестовых классах):

public static void main(String... args) {

    RestContext context = new RestContext(8080, "/api");

    context.addEndpoint(new CustomerEndpoint(new CustomerService()));
    context.addEndpoint(new AnotherEndpoint()); // you can add or remove as many as you want.

    context.enableCors();
}

Набл.: Начиная с версии 2.5, spark java поддерживает несколько экземпляров через Service.ignite( ) API.

person juliaaano    schedule 17.05.2016

Вы также можете интегрировать Spring в свое приложение Spark. Вот как я настроил свои маршруты.

@Configuration
public class RoutesConfiguration {
    RoutesConfiguration() {
        get("/hello", (req, res) -> "Hello World!");
    }
}

Это позволяет мне избежать этапа вызова настройки в методе Main приложения SparkApp.

person shantanusinghal    schedule 06.02.2016
comment
Спасибо за идею. - person thebiggestlebowski; 07.02.2016

Думаю, spark-java предназначен для людей, которым не нужны тонны дополнительных настроек.

Итак, я просто поместил дополнительный метод в контроллеры с именем declareRoutes, где я разместил объявления.

Для примера приложения:

public class LoginController {

    public static void declareRoutes(){
        get(Path.Web.LOGIN, LoginController.serveLoginPage);
        post(Path.Web.LOGIN, LoginController.handleLoginPost);
        post(Path.Web.LOGOUT, LoginController.handleLogoutPost);
    }

    public static Route serveLoginPage = (Request request, Response response) -> {
        Map<String, Object> model = new HashMap<>();
        model.put("loggedOut", removeSessionAttrLoggedOut(request));
        model.put("loginRedirect", removeSessionAttrLoginRedirect(request));
        return ViewUtil.render(request, model, Path.Template.LOGIN);
    };

Итак, в моем приложении я инициализирую все маршруты следующим образом:

 // Routes

 Class[] controllers = {
          IndexController.class,
          LoginController.class,
          SandboxController.class,
          ServicesController.class };

 for (Class controller: controllers) {
         Method m = controller.getMethod("declareRoutes");
         m.invoke(m);
 }

 // Catch all
 declareCatchAllRoute();

ОбъявлениеCatchAllRoute() просто:

private void declareCatchAllRoute() {
    get("*", ViewUtil.notFound);
}

Работает достаточно хорошо для моих нужд, не требует никакой новой абстракции.

ХТН

person philippeback    schedule 23.01.2019