如何在spring中添加可选的依赖类?

时间:2017-08-18 12:38:46

标签: java spring

我正在创建一个公共库,并希望添加一个使用ServletContext的服务。但是由于库也应该在cli环境中使用,我必须找到一种方法告诉spring忽略那里的servlet。

@Component
public class MyService {
    //only available in a web environment
    @Autowired(required = false)
    private ServletContext servletContext;
}

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <optional>true</optional>
        </dependency>

在实现项目中,我只想运行命令行界面,因此我没有包含servlet依赖项。

但是当我尝试启动时,启动时抛出以下异常: Caused by: java.lang.ClassNotFoundException: javax.servlet.ServletContext

问题:如何使用ServletContext中的CommonService而不必将依赖项添加到重用该类的每个项目中?

2 个答案:

答案 0 :(得分:3)

只需包含servlet依赖项,并使依赖项可选。所有其他选择都更糟糕。

这是一个相当轻量级的类 - 对于servlet规范3.1.0的jar来说是93K。

但是如果你绝对必须在类​​路径上没有类的情况下运行那么你可以执行以下操作......

首先让我说你遇到问题的原因不是因为ServletContext是一个字段,而是因为它是一个自动连接的字段。我写了一个小测试应用程序,并且不需要在运行时提供类的字段类型。

因此,要使其工作,您需要一个配置文件和一个命名bean。

首先,您需要按名称注入ServletContext,而不是将其键入ServletContext。这不是很好,因为当你需要使用它时,你需要将它转换为servlet上下文。

所以

@Autowired(required = false)
@Qualifier("servletContext")
Object servletContext

就是你要放在这里的。

然后创建另一个将提供serlvet上下文的类 - 这将通过一个配置文件打开 - 或者可能是@membersound引用的@ConditionalOnWebApplication仅在Spring Boot中可用。

@Configuration
@Profile("web") or @ConditionalOnWebApplication
public class ServletContextProvider {

  @Autowired
  ServletContext servletContext;

    @Bean("servletContext")
    public ServletContext getServletContext() {
      return servletContext;
    }
}

就像我说的那样,只需在类路径中包含ServletContext。

答案 1 :(得分:0)

幸运的是,有以下注释可以直接添加到课程中:

@ConditionalOnWebApplication
@ConditionalOnNotWebApplication

这样,cli环境中的spring不需要评估ServletContext bean。

当然,这需要创建两个服务类,其中每个服务类都有一个上面的注释。

public abstract class MyService {
       abstract String impl();
}

@Component
class MyServiceCLI {
       @Override
       String impl() {
             return "cli specific";
       }
}

@Component
class MyServiceWeb {
    //only available in a web environment
    @Autowired
    private ServletContext servletContext;

       @Override
       String impl() {
             //use servlet context...
             return "ctx specific";
       }

}

然后只注入@Autowired MyService

通过使实现包私有,它们对用户是不可见的,但Spring仍然会看到并创建它们。