我正在尝试将Spring Boot应用程序原型化。我来自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
保释失败,似乎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
,但这似乎与spring-boot AnnotationConfigEmbeddedWebApplicationContext
类冲突。
我正在使用spring-boot 1.3.3和spring-framework 4.3.0.rc1
答案 0 :(得分:6)
另一个答案是没有资源作为spring bean,这个自动配置会正确地整合它们:
配置类:
@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);
}
}
注意:这是Spring Boot 1.3.3 / RESTEasy 3.0.16的工作配置
答案 1 :(得分:3)
您可以使用RESTEasy Spring Boot启动程序。这是你如何做到的:
添加POM依赖关系
将下面的Maven依赖项添加到Spring Boot应用程序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应用程序类
只需将您的JAX-RS应用程序类(Application的子类)定义为Spring bean,它就会自动注册。请参阅下面的示例。有关详细信息,请参阅How to use RESTEasy Spring Boot Starter中的 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 {
}
注册JAX-RS资源和提供商
只需将它们定义为Spring bean,它们就会自动注册。请注意,JAX-RS资源可以是单例或请求作用域,而JAX-RS提供者必须是单例。
答案 2 :(得分:1)
这是完全有效的例子。
首先,示例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;
}
}
最后,在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;
}
您的终端应该正常运行。如果您在类路径上缺少FilterDispatcher类,请将resteasy-jaxrs库添加到构建描述符中。