sparkjava:路线必须在主要方法中吗?
sparkjava: Do routes have to be in main method?
我是 sparkjava 的新手,总体上喜欢它。但是,new routes/endpoints 一定要在main方法中定义吗?对于任何重要的 Web 应用程序,这将导致一个非常长的主要方法,或者我需要有多个主要方法(因此将服务器资源分配给多个实例)。
这两个 sparkjava 文档页面似乎在 main 方法中定义了路由:http://sparkjava.com/documentation.html#routes and here http://sparkjava.com/documentation.html#getting-started.
还有其他我没有看到的方法吗?粗略 google 搜索没有告诉我更好的方法...
=========
这是我根据安德鲁的回答所做的完整解决方案。在我看来,在 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;
}
}
您可以根据需要设置路线。您只需要在主线程中调用设置方法。例如
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());
}
}
您还可以将 Spring 集成到您的 Spark 应用程序中。这就是我配置路线的方式。
@Configuration
public class RoutesConfiguration {
RoutesConfiguration() {
get("/hello", (req, res) -> "Hello World!");
}
}
这让我避免了 SparkApp 的 Main 方法中的设置调用步骤。
当有多个端点要配置时,您可以使用以下设计思路:
首先,创建一个构建器界面:
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 class 来保存 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.");
}
}
您应该能够在您的主要方法中使用此上下文 class(并且可以选择在您的测试 classes 中):
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.[= 支持多个实例15=]
好吧,我猜 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
我是 sparkjava 的新手,总体上喜欢它。但是,new routes/endpoints 一定要在main方法中定义吗?对于任何重要的 Web 应用程序,这将导致一个非常长的主要方法,或者我需要有多个主要方法(因此将服务器资源分配给多个实例)。
这两个 sparkjava 文档页面似乎在 main 方法中定义了路由:http://sparkjava.com/documentation.html#routes and here http://sparkjava.com/documentation.html#getting-started.
还有其他我没有看到的方法吗?粗略 google 搜索没有告诉我更好的方法...
=========
这是我根据安德鲁的回答所做的完整解决方案。在我看来,在 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;
}
}
您可以根据需要设置路线。您只需要在主线程中调用设置方法。例如
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());
}
}
您还可以将 Spring 集成到您的 Spark 应用程序中。这就是我配置路线的方式。
@Configuration
public class RoutesConfiguration {
RoutesConfiguration() {
get("/hello", (req, res) -> "Hello World!");
}
}
这让我避免了 SparkApp 的 Main 方法中的设置调用步骤。
当有多个端点要配置时,您可以使用以下设计思路:
首先,创建一个构建器界面:
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 class 来保存 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.");
}
}
您应该能够在您的主要方法中使用此上下文 class(并且可以选择在您的测试 classes 中):
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.[= 支持多个实例15=]
好吧,我猜 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