当前位置: 首页 > 知识库问答 >
问题:

使用自动配置创建多个(功能)webmvc应用程序的Spring Boot

郎欣然
2023-03-14
    null
@Configuration
@AutoConfigureAfter(DaoServicesConfiguration.class)
public class MyServletConfiguration {
    @Autowired
    ApplicationContext parentApplicationContext;

    @Bean
    public ServletRegistrationBean myApi() {
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        applicationContext.setParent(parentApplicationContext);
        applicationContext.register(PropertySourcesPlaceholderConfigurer.class);
        // a few more classes registered. These classes cannot be added to 
        // the parent application context.
        // includes implementations of 
        //   WebSecurityConfigurerAdapter
        //   EmbeddedServletContainerCustomizer

        applicationContext.scan(
                // a few packages
        );

        DispatcherServlet ds = new DispatcherServlet();
        ds.setApplicationContext(applicationContext);

        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(ds, true, "/my_api/*");
        servletRegistrationBean.setName("my_api");
        servletRegistrationBean.setLoadOnStartup(1);
        return servletRegistrationBean;
    }
}

共有1个答案

靳涵亮
2023-03-14

我们使用Boot(创建带有父上下文的多servlets应用程序)也遇到了类似的问题,我们通过以下方式解决了这个问题:

1.创建您的父Spring配置,它将包含您想要共享的所有父bean。类似这样的事情:

@EnableAutoConfiguration(
    exclude = {
        //use this section if your want to exclude some autoconfigs (from Boot) for example MongoDB if you already have your own
    }
)
@Import(ParentConfig.class)//You can use here many clasess from you parent context
@PropertySource({"classpath:/properties/application.properties"})
@EnableDiscoveryClient
public class BootConfiguration {
}

2.创建类型,它将确定特定应用程序模块的类型(例如,ou的情况是REST或SOAP)。在这里,您还可以指定您所需的上下文路径或另一个特定于应用程序的数据(我将向bellow展示它将如何使用):

public final class AppModule {

    private AppType type;

    private String name;

    private String contextPath;

    private String rootPath;

    private Class<?> configurationClass;

    public AppModule() {
    }

    public AppModule(AppType type, String name, String contextPath, Class<?> configurationClass) {
        this.type = type;
        this.name = name;
        this.contextPath = contextPath;
        this.configurationClass = configurationClass;
    }

    public AppType getType() {
        return type;
    }

    public void setType(AppType type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getRootPath() {
        return rootPath;
    }

    public AppModule withRootPath(String rootPath) {
        this.rootPath = rootPath;
        return this;
    }

    public String getContextPath() {
        return contextPath;
    }

    public void setContextPath(String contextPath) {
        this.contextPath = contextPath;
    }

    public Class<?> getConfigurationClass() {
        return configurationClass;
    }

    public void setConfigurationClass(Class<?> configurationClass) {
        this.configurationClass = configurationClass;
    }

    public enum AppType {
        REST,
        SOAP
    }
}
public class BootAppContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    private List<AppModule> modules = new ArrayList<>();

    BootAppContextInitializer(List<AppModule> modules) {
        this.modules = modules;
    }

    @Override
    public void initialize(ConfigurableApplicationContext ctx) {

        for (ServletRegistrationBean bean : servletRegs(ctx)) {
            ctx.getBeanFactory()
               .registerSingleton(bean.getServletName() + "Bean", bean);
        }
    }

    private List<ServletRegistrationBean> servletRegs(ApplicationContext parentContext) {

        List<ServletRegistrationBean> beans = new ArrayList<>();

        for (AppModule module: modules) {

            ServletRegistrationBean regBean;

            switch (module.getType()) {
                case REST:
                    regBean = createRestServlet(parentContext, module);
                    break;
                case SOAP:
                    regBean = createSoapServlet(parentContext, module);
                    break;
                default:
                    throw new RuntimeException("Not supported AppType");
            }

            beans.add(regBean);
        }

        return beans;
    }

    private ServletRegistrationBean createRestServlet(ApplicationContext parentContext, AppModule module) {
        WebApplicationContext ctx = createChildContext(parentContext, module.getName(), module.getConfigurationClass());
        //Create and init MessageDispatcherServlet for REST
        //Also here you can init app specific data from AppModule, for example, 
        //you  can specify context path in the follwing way 
      //servletRegistrationBean.addUrlMappings(module.getContextPath() + module.getRootPath());
    }

    private ServletRegistrationBean createSoapServlet(ApplicationContext parentContext, AppModule module) {
        WebApplicationContext ctx = createChildContext(parentContext, module.getName(), module.getConfigurationClass());
        //Create and init MessageDispatcherServlet for SOAP
        //Also here you can init app specific data from AppModule, for example, 
        //you  can specify context path in the follwing way 
      //servletRegistrationBean.addUrlMappings(module.getContextPath() + module.getRootPath());
    }

 private WebApplicationContext createChildContext(ApplicationContext parentContext, String name,
                                                     Class<?> configuration) {
        AnnotationConfigEmbeddedWebApplicationContext ctx = new AnnotationConfigEmbeddedWebApplicationContext();
        ctx.setDisplayName(name + "Context");
        ctx.setParent(parentContext);
        ctx.register(configuration);

        Properties source = new Properties();
        source.setProperty("APP_SERVLET_NAME", name);
        PropertiesPropertySource ps = new PropertiesPropertySource("MC_ENV_PROPS", source);

        ctx.getEnvironment()
           .getPropertySources()
           .addLast(ps);

        return ctx;
    }
}
/*Example for REST app*/
@EnableWebMvc
@ComponentScan(basePackages = {
    "com.company.package1",
    "com.company.web.rest"})
@Import(SomeCommonButChildSpecificConfiguration.class)
public abstract class RestAppConfiguration extends WebMvcConfigurationSupport {

    //Some custom logic for your all REST apps

    @Autowired
    private LogRawRequestInterceptor logRawRequestInterceptor;

    @Autowired
    private LogInterceptor logInterceptor;

    @Autowired
    private ErrorRegister errorRegister;

    @Autowired
    private Sender sender;

    @PostConstruct
    public void setup() {
        errorRegister.setSender(sender);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(logRawRequestInterceptor);
        registry.addInterceptor(scopeInterceptor);
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        super.setServletContext(servletContext);
    }
}

/*Example for SOAP app*/
@EnableWs
@ComponentScan(basePackages = {"com.company.web.soap"})
@Import(SomeCommonButChildSpecificConfiguration.class)
public abstract class SoapAppConfiguration implements ApplicationContextAware {

    //Some custom logic for your all SOAP apps

    private boolean logGateWay = false;

    protected ApplicationContext applicationContext;

    @Autowired
    private Sender sender;

    @Autowired
    private ErrorRegister errorRegister;

    @Autowired
    protected WsActivityIdInterceptor activityIdInterceptor;

    @Autowired
    protected WsAuthenticationInterceptor authenticationInterceptor;

    @PostConstruct
    public void setup() {
        errorRegister.setSender(sender);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * Setup preconditions e.g. interceptor deactivation
     */
    protected void setupPrecondition() {
    }

    public boolean isLogGateWay() {
        return logGateWay;
    }

    public void setLogGateWay(boolean logGateWay) {
        this.logGateWay = logGateWay;
    }

    public abstract Wsdl11Definition defaultWsdl11Definition();
}
public final class Entrypoint {

    public static void start(String applicationName, String[] args, AppModule... modules) {
        System.setProperty("spring.application.name", applicationName);
        build(new SpringApplicationBuilder(), modules).run(args);
    }

    private static SpringApplicationBuilder build(SpringApplicationBuilder builder, AppModule[] modules) {
        return builder
                .initializers(
                    new LoggingContextInitializer(),
                    new BootAppContextInitializer(Arrays.asList(modules))
                )
                .sources(BootConfiguration.class)
                .web(true)
                .bannerMode(Banner.Mode.OFF)
                .logStartupInfo(true);
    }
}
//REST module
@ComponentScan(basePackages = {"com.module1.package.*"})
public class Module1Config extends RestAppConfiguration {
    //here you can specify all your child's Beans and etc
}

//SOAP module
@ComponentScan(
    basePackages = {"com.module2.package.*"})
public class Module2Configuration extends SoapAppConfiguration {

    @Override
    @Bean(name = "service")
    public Wsdl11Definition defaultWsdl11Definition() {
        ClassPathResource wsdlRes = new ClassPathResource("wsdl/Your_WSDL.wsdl");
        return new SimpleWsdl11Definition(wsdlRes);
    }

    @Override
    protected void setupPrecondition() {
        super.setupPrecondition();
        setLogGateWay(true);
        activityIdInterceptor.setEnabled(true);
    }
}

2.准备入口点并作为引导应用程序运行:公共类应用程序{

public static void main(String[] args) throws Exception {
    Entrypoint.start("module1",args,
                     new AppModule(AppModule.AppType.REST, "module1", "/module1/*", Module1Configuration.class),
                     new AppModule(AppModule.AppType.SOAP, "module2", "module2", Module2Configuration.class)
                    );
}

}

享受^_^

    null
 类似资料:
  • 您的帮助应该是值得赞赏的,如果需要,我将提供代码示例。

  • 我目前正在试验托管。NET CoreCLR在C应用程序中基本上实现某种插件系统。 我使用corerun源代码作为基础,开始并探索如何构建本机主机—其他教程/文档通常以某种方式失败 最后我让它工作了,我可以初始化运行库,创建AppDomain并执行.NET Core程序集。 我的下一步是运行多个程序集,因此我只是创建了第二个测试程序集,并尝试以与第一个测试程序集相同的方式执行它。 实际上,我的应用程

  • “Spring-Boot-AutoConfigure”,版本:'2.4.1'

  • 我用< code>Python和< code>Django开发了一个web应用程序,需要每天备份数据。目前,< code>Postgres被用作DBMS。 为了执行备份,我发现了<code>django dbbackup</code>模块,但要使用它,我需要运行命令<code>python manage。py dbbackup。 如何在每天的特定时间自动备份?

  • 在我的默认SpringBoot应用程序中,它具有依赖项,调用(带有)返回以下信息 但是,我的机器上有两个驱动器,所以我想查看它们的磁盘空间详细信息。所以我添加了一个配置文件: 现在,我的健康endpoint返回以下数据 (稍后我将考虑如何抑制默认的“diskSpace”条目) 然而,由于我可能想在不同的机器上运行我的应用程序,我想配置磁盘驱动器,以便在我的文件。 还加上 配置在启动期间加载并记录到

  • 如果您在开发共享库的公司工作,或者您在开源或商业库中工作,则可能需要开发自己的自动配置。 自动配置类可以捆绑在外部jar中,仍然可以通过Spring Boot获取。 自动配置可以与“启动器”相关联,该“启动器”提供自动配置代码以及您将使用它的典型库。 我们首先介绍了构建自己的自动配置需要了解的内容,然后我们将继续介绍创建自定义启动器所需的典型步骤。 可以使用演示项目来展示如何逐步创建启动器。 4.