10

在 .NET 中工作过,我非常熟悉 NancyFX 和 Web API 等微型 Web 框架对 IoC 容器的支持。

在像 Sinatra(NancyFX 基于 Sinatra)这样的 Ruby 类似框架中,您似乎具有依赖注入的能力。

据我所知,由于 Java spark 应用程序作为主要方法运行,因此您似乎无法传入依赖项或 IoC 容器。

public class HelloWorld {
    public static void main(String[] args) {
        get("/hello", (req, res) -> "Hello World");
    }
}

我很难理解这样的框架在不支持的情况下如何有用。

如果这个框架不支持,是否有另一个轻量级框架(我记得 Spring 不是轻量级的,但可能情况已经改变)支持这个?

4

5 回答 5

8

Spring 可以简单地与 Spark 集成。例如

public interface Spark {

  /**
   * adds filters, routes, exceptions, websockets and others
   */
   void register();

}

@Configuration
public class SparkConfiguration {

   @Autowired(required = false)
   private List<Spark> sparks = new ArrayList<>();

   @Bean
   CommandLineRunner sparkRunner() {
       return args -> sparks.stream().forEach( spark -> spark.register());
   }

}

@Component
public class HelloSpark implements Spark {

    @Autowired
    private HelloWorldService helloWorldService;

    @Override
    public void register() {
        get("/hello", (request, response) -> helloWorldService.hello() );
    }

}

您可以在https://github.com/pmackowski/spring-boot-spark-java上找到更多信息

于 2015-11-06T22:57:29.917 回答
5

将 Guice 与 Java Spark 一起使用非常容易。基本上,您需要以SparkFilter以下方式扩展以创建 Guice 注入器。

public class SparkGuiceFilter extends SparkFilter {

    private Injector injector = null;

    @Override
    protected SparkApplication[] getApplications(final FilterConfig filterConfig) throws ServletException {
        final SparkApplication[] applications = super.getApplications(filterConfig);

        if (this.injector == null) {
            this.injector = Guice.createInjector(new MainModule());
        }

        if (applications != null && applications.length != 0) {
            for (SparkApplication application : applications) {
                this.injector.injectMembers(application);
            }
        }

        return applications;
    }
}

然后,您需要并且必须使用 Jetty 或任何其他 servlet 容器web.xml将 Spark 应用程序作为普通应用程序运行:war

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <filter>
        <filter-name>SparkGuiceFilter</filter-name>
        <filter-class>com.devng.spark.guice.SparkGuiceFilter</filter-class>
        <init-param>
            <param-name>applicationClass</param-name>
            <param-value>com.devng.spark.SparkApp</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>SparkGuiceFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

但是,这种方法存在一些限制。您不能在 Guice 中使用基于请求的范围或会话范围。如果你不需要这个,那么你很高兴,否则你需要集成 Guice Servlet Extensions 并按照官方 Guice 文档中的GuiceFilter描述web.xml添加。您还需要确保在 中使用相同的注入器实例,并且您需要按照此处所述在您的中定义 a 。GuiceFilterSparkGuiceFilterGuiceServletContextListenerweb.xml

您可以在我的 GitHub 中找到一个完整的工作示例https://github.com/devng/demo/tree/master/sparkjava-guice

于 2017-04-25T11:21:36.277 回答
3

我实际上正在尝试使用 Spark 和 Guice,据我所知,使用两者的依赖注入非常简单,至少在今天(2017 年 8 月)。

您所要做的就是:

public class MySparkApplication {

    public static void main(String[] args) {

        Injector injector = Guice.createInjector();
        SomeClass someClass = injector.getInstance(SomeClass.class);

        get("/hello", (req, res) -> someClass.getSomeString());
    }
}

它实际上似乎就这么简单。我只是按照Guice 入门指南进行操作,它可以工作。当我运行 Spark 并http://localhost:4567在浏览器中打开时,会显示从我的方法返回的字符串。

于 2017-08-12T10:04:38.177 回答
1

我最近一直在使用 Spark,它不包含开箱即用的 IoC 提供程序,但是,您可以轻松地包含 Spring 或 Guice core,这将是一个轻量级的解决方案。

您需要做的就是将依赖项添加到 Maven 并开始使用它。

作为替代方案,您可以查看Ninja,它是一个全栈框架,包括开箱即用的 Guice、JPA/Hibernate。

于 2015-10-19T14:32:16.233 回答
1

独自工作IoC with Guice。它可以在没有很多代码的情况下找到;) 链接: https ://github.com/Romain-P/SparkJava-JFast

默认情况下不需要 guice 模块,自动检测绑定对象。

public class Main {
    public static void main(String[] args) {
        /* give a class as argument for package scanning from its path recursively */
        Injector injector = SparkApplication.init(Application.class);
        injector.getInstance(Application.class).initialize();
    }
}

@Binding
public class Application {
    @Inject Service http;
    @Inject HelloController helloController;

    public void initialize() {
        http.port(8080);
        http.get("/hello", (req, res) -> helloController.hello());
    }
}

@Binding
public class HelloController {
    @Inject HelloService service;

    public Object hello() {
        //business logic
        return service.hello();
    }
}

@Binding
@Slf4j
public class HelloService {
    public Object hello() {
        log.info("hello");
        return new Object();
    }
}
于 2017-10-25T09:15:14.323 回答