Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将spring boot与RESTEasy集成_Spring_Spring Boot_Jax Rs_Resteasy - Fatal编程技术网

将spring boot与RESTEasy集成

将spring boot与RESTEasy集成,spring,spring-boot,jax-rs,resteasy,Spring,Spring Boot,Jax Rs,Resteasy,我正在尝试一个Spring引导应用程序的原型。我来自Guice JAX-RS应用程序,因此与Spring MVC相比,我更喜欢标准JAX-RS注释。我已经让Jetty站起来并提供服务: @Configuration @Import({ResteasyBootstrap.class, SpringBeanProcessorServletAware.class, HttpServletDispatcher.class}) public class EmbeddedJetty { @Bean

我正在尝试一个Spring引导应用程序的原型。我来自Guice JAX-RS应用程序,因此与Spring MVC相比,我更喜欢标准JAX-RS注释。我已经让Jetty站起来并提供服务:

@Configuration
@Import({ResteasyBootstrap.class, SpringBeanProcessorServletAware.class, HttpServletDispatcher.class})
public class EmbeddedJetty {
    @Bean
    @Singleton
    public EmbeddedServletContainerFactory servletContainer() {
        JettyEmbeddedServletContainerFactory factory = new JettyEmbeddedServletContainerFactory();
        factory.setPort(9000);
        factory.setSessionTimeout(10, TimeUnit.MINUTES);
        return factory;
    }
}
然而,我就是不知道如何正确连接RESTEasy。使用上面的
SpringBeanProcessorServletAware
时,似乎在使用
ServletContextAware
之前,
ServletContext
没有通过
ServletContextAware注入:

java.lang.NullPointerException: null
    at org.jboss.resteasy.plugins.spring.SpringBeanProcessorServletAware.getRegistry(SpringBeanProcessorServletAware.java:30)
    at org.jboss.resteasy.plugins.spring.SpringBeanProcessor.postProcessBeanFactory(SpringBeanProcessor.java:247)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:284)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:174)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:680)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:522)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766)
我还尝试了使用SpringContextLoaderListener,但这似乎与SpringBoot注释ConfigEmbeddedWebApplicationContext类冲突


我使用的是spring boot 1.3.3和spring framework 4.3.0。rc1

这里是一个完整的工作示例

  • 首先,一个JAX-RS端点示例:

    @Path("/api")
    public class SampleResource {
        @GET
        @Path("/sample")
        @Produces(MediaType.APPLICATION_JSON)
        public String getSample() {
            return "Some JSON";
        }
    }
    
  • 接下来,是加载所有端点的JAX-RS配置类

    import javax.ws.rs.core.Application;
    
    public class RestEasyConfig extends Application {
        @Override
        public Set<Class<?>> getClasses() {
            Set<Class<?>> classes = new HashSet<>();
            classes.add(SampleRest.class);
            return classes;
        }
    }
    
    导入javax.ws.rs.core.Application;
    公共类RestEasyConfig扩展了应用程序{
    @凌驾
    public Set>classes=new HashSet();
    添加(sampleest.class);
    返回类;
    }
    }
    
  • 最后,在Spring配置中,初始化RESTEast过滤器并通知框架它的存在

    import org.springframework.boot.context.embedded.FilterRegistrationBean;
    import org.jboss.resteasy.plugins.server.servlet.FilterDispatcher;
    ...
    
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        Map<String, String> initParams = new HashMap<>();
        initParams.put("javax.ws.rs.Application", RestEasyConfig.class.getCanonicalName());
    
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new FilterDispatcher());
        registrationBean.setInitParameters(initParams);
        return registrationBean;
    } 
    
    import org.springframework.boot.context.embedded.FilterRegistrationBean;
    导入org.jboss.resteasy.plugins.server.servlet.FilterDispatcher;
    ...
    @豆子
    公共过滤器注册bean过滤器注册bean(){
    Map initParams=new HashMap();
    initParams.put(“javax.ws.rs.Application”,RestEasyConfig.class.getCanonicalName());
    FilterRegistrationBean registrationBean=新的FilterRegistrationBean();
    setFilter(新的FilterDispatcher());
    setInitParameters(initParams);
    返回注册bean;
    } 
    
    您的端点应该已启动并正在运行。如果类路径上缺少FilterDispatcher类,请将库添加到生成描述符中


  • 另一个答案是,您的资源不能作为SpringBean使用,此自动配置将正确集成它们:

    配置类:

    @Configuration
    @ConditionalOnWebApplication
    public class RestEasyAutoConfigurer {
    
    
        private Environment environment;   
    
        @Bean(name = "resteasyDispatcher")
        public ServletRegistrationBean resteasyServletRegistration() {
            ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HttpServletDispatcher(), getPrefix()
                    + "/*");
            registrationBean.setInitParameters(ImmutableMap.of("resteasy.servlet.mapping.prefix", "/rs/")); // set prefix here
            registrationBean.setLoadOnStartup(1);
            return registrationBean;
        }
    
        @Bean(destroyMethod = "cleanup")
        public static RestEasySpringInitializer restEasySpringInitializer() {
            return new RestEasySpringInitializer();
        }    
    
        @Bean
        // use Spring Boot configured Jackson
        public CustomResteasyJackson2Provider jackson2Provider(ObjectMapper mapper) {
            return new CustomResteasyJackson2Provider(mapper); 
        }
    
        public static class RestEasySpringInitializer
                implements
                    ServletContextInitializer,
                    ApplicationContextAware,
                    BeanFactoryPostProcessor {
    
            private ResteasyDeployment deployment;
    
            private ConfigurableApplicationContext applicationContext;
    
            private ConfigurableListableBeanFactory beanFactory;
    
            public void cleanup() {
                deployment.stop();
            }
    
            @Override
            public void onStartup(ServletContext servletContext) throws ServletException {
                ListenerBootstrap config = new ListenerBootstrap(servletContext);
                deployment = config.createDeployment();
                deployment.start();
    
                servletContext.setAttribute(ResteasyProviderFactory.class.getName(), deployment.getProviderFactory());
                servletContext.setAttribute(Dispatcher.class.getName(), deployment.getDispatcher());
                servletContext.setAttribute(Registry.class.getName(), deployment.getRegistry());
    
                SpringBeanProcessor processor = new SpringBeanProcessor(deployment.getDispatcher(),
                        deployment.getRegistry(), deployment.getProviderFactory());
                processor.postProcessBeanFactory(beanFactory);
                applicationContext.addApplicationListener(processor);
            }
    
            @Override
            public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                this.beanFactory = beanFactory;
            }
    
            @Override
            public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
                this.applicationContext = (ConfigurableApplicationContext) applicationContext;
            }
        }
    }
    
    而杰克逊的提供者:

    @Provider
    @Consumes({"application/*+json", "text/json"})
    @Produces({"application/*+json", "text/json"})
    public class CustomResteasyJackson2Provider extends ResteasyJackson2Provider {
        private ObjectMapper mapper;
    
        public CustomResteasyJackson2Provider(ObjectMapper mapper) {
            this.mapper = mapper;
        }
    
        @Override
        public ObjectMapper locateMapper(Class<?> type, MediaType mediaType) {
            return Optional.ofNullable(_mapperConfig.getConfiguredMapper()).orElse(mapper);
        }    
    }
    
    @Provider
    @使用({“application/*+json”,“text/json”})
    @产生({“application/*+json”,“text/json”})
    公共类CustomResteasyJackson2Provider扩展了ResteasyJackson2Provider{
    私有对象映射器映射器;
    公共CustomResteasyJackson2Provider(对象映射器映射器){
    this.mapper=mapper;
    }
    @凌驾
    公共对象映射器locateMapper(类类型,MediaType,MediaType){
    返回可选的.ofNullable(_-mapperConfig.getConfiguredMapper()).orElse(映射器);
    }    
    }
    

    注意:这是Spring Boot 1.3.3/RESTEasy 3.0.16的工作配置,您可以使用RESTEasy Spring Boot starter。以下是您的操作方法:

    添加POM依赖项

    将下面的Maven依赖项添加到Spring引导应用程序pom文件中

    <dependency>
       <groupId>com.paypal.springboot</groupId>
       <artifactId>resteasy-spring-boot-starter</artifactId>
       <version>2.1.1-RELEASE</version>
       <scope>runtime</scope>
    </dependency>
    
    注册JAX-RS资源和提供者

    只要将它们定义为Springbean,它们就会自动注册。请注意,JAX-RS资源可以是单例的,也可以是请求范围的,而JAX-RS提供者必须是单例的


    .

    退房。这是一个启动开发者写的谢谢!我尝试过这个方法,但正如Jeff S所说,这意味着RESTEasy资源不是Spring生命周期的一部分——例如,no@PostConstruct annotations fire。请记住,“另一个答案不会将您的资源作为Spring bean”,这是不正确的。下面我的回答中提到的RESTEasy Spring引导状态器功能齐全,包括自动将每个资源和提供者注册为SpringBean,此外还自动注册JAX-RS应用程序子类。
    package com.test;
    
    import org.springframework.stereotype.Component;
    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;
    
    @Component
    @ApplicationPath("/sample-app/")
    public class JaxrsApplication extends Application {
    }