【问题标题】:sparkjava: Do routes have to be in main method?sparkjava:路线必须在主要方法中吗?
【发布时间】:2016-04-30 19:25:49
【问题描述】:

我是 sparkjava 的新手,总体上喜欢它。但是,是否必须在 main 方法中定义新的路由/端点?对于任何重要的 Web 应用程序,这将导致很长的 main 方法,或者我需要有多个 main 方法(因此在多个实例之间拆分服务器资源)。

这两个 sparkjava 文档页面似乎在 main 方法中定义了路由:http://sparkjava.com/documentation.html#routes,这里是http://sparkjava.com/documentation.html#getting-started

还有其他我没有看到的方法吗?粗略的谷歌搜索并没有向我展示更好的方法......

=========

这是我根据 Andrew 的回答所做的完整解决方案。在我看来,在 main 方法之外添加端点应该是 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;
    }
}

【问题讨论】:

    标签: routes spark-java


    【解决方案1】:

    您可以根据需要设置路线。您只需要在主线程中调用设置方法。例如

     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());
        }
     }
    

    【讨论】:

      【解决方案2】:

      当需要配置多个端点时,您可以使用以下设计理念:

      首先,创建一个builder界面:

      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.");
          }
      }
      

      你应该能够在你的 main 方法中使用这个上下文类(也可以在你的测试类中):

      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();
      }
      

      Obs.:Since version 2.5,spark java 通过 Service.ignite() api 支持多个实例。

      【讨论】:

        【解决方案3】:

        您还可以将 Spring 集成到您的 Spark 应用程序中。这就是我配置路线的方式。

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

        这让我可以避免在 SparkApp 的 Main 方法中设置调用步骤。

        【讨论】:

        • 感谢您的想法。
        【解决方案4】:

        好吧,我猜 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();
        

        declareCatchAllRoute() 只是:

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

        可以很好地满足我的需要,不需要任何新的抽象。

        HTH

        【讨论】:

          猜你喜欢
          • 2015-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-04
          • 2022-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多