spring boot集成jersey框架支持的原理

背景

工程是用的spring boot框架,但存在某些业务需要使用jersey框架提供的能力处理更方便的时候,需要集成jersey。

示例

spring boot本身提供了插拔的配置来支持集成jersey,存在多种实现写法,但是殊途同归。如下是一种写法:

1. 引入依赖

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jersey</artifactId>
        </dependency>

版本依赖于spring-boot-starter-parent

2. jersey配置,需要被spring 扫描到

@Configuration
// 上下文路径,也可以配置在application.properties,未配置的话就是所有/*的请求,当前为/jersey/*
@ApplicationPath("/jersey")
public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        // 在这里注册相关Controller或者需要的特性支持
        register(JerseyController.class);
    }
}

3. Controller实现

@Path("/api")
public class JerseyController {
    @GET
    @Path("/hello")
    public String hello() {
        return "hello";
    }
}

如上写法,请求url:/jersey/api/hello。

如果希望这个类注册到spring容器,可以考虑使用spring 的绑定注解自动扫描等相关方式注册到spring容器,如果不需要不处理。jersey有自己的一套容器系统(使用了HK2)提供了IOC、AOP等能力。

原理

上面的示例只是一个简单实现,下面说下原理

spring mvc本身的实现是注册一个DispatcherServlet,拦截所有请求,进行分发处理,而spring boot集成jersey,其实也是注册了一个jersey的servlet到servlet容器对于映射的指定请求交给它这个servlet来处理。

在spring-boot-autoconfigure包下有个类JerseyAutoConfiguration,这个类上有这个注解:

@ConditionalOnBean(type = "org.glassfish.jersey.server.ResourceConfig")

就是需要存在ResourceConfig这个类型的bean,所以上面注册JerseyConfig这个bean的时候需要继承ResourceConfig,然后上面示例中JerseryConfig这个bean需要被spring 容器找到,无论采用哪种方式,比如:使用@Configuration或者@Component等注解自动扫描,或者使用@Bean注解主动注册到java config的类中等等都可以。

下面这段代码是JerseyAutoConfiguration注册jersey 的servlet的一部分代码:

	@Bean
	@ConditionalOnMissingBean(name = "jerseyServletRegistration")
	@ConditionalOnProperty(prefix = "spring.jersey", name = "type", havingValue = "servlet", matchIfMissing = true)
	public ServletRegistrationBean jerseyServletRegistration() {
		ServletRegistrationBean registration = new ServletRegistrationBean(
				new ServletContainer(this.config), this.path);
		addInitParameters(registration);
		registration.setName(getServletRegistrationName());
		registration.setLoadOnStartup(this.jersey.getServlet().getLoadOnStartup());
		return registration;
	}

ServletRegistrationBean是spring mvc提供的一种很友好的注册servlet的实现形式,如果需要自定义动态注册servlet的时候可以考虑使用这种方法。关于内部实现,不是本文重点,不多说明了。

上面的this.config的类型是ResourceConfig,在这里的运行态的实际类型便是示例中的JerseyConfig(实际是spring创建的一个代理)。

本质就是spring boot的自动装配在满足条件的时候注册了一个jersey的servlet。

集成失败的可能原因及解决办法

有的时候可能工程环境比较复杂,影响到了spring 的bean定义的解析加载顺序。会出现写法很正确,但是集成jersey失败,比如是期望jersey处理的请求报404。

如果要确认jersey是否集成成功,查看启动日志即可,上面的原理也解释了,是注册一个jersey的servlet,所以如下面红色方框标记的日志,说明集成成功了:

当然,不同的工程配置/环境可能这个servlet注册日志出现的顺序可能不一样,只要出现有类似这个日志即可。

如果发现集成代码写的很正确,但这个jersey的servlet没有注册(没有这个日志)。那就可虑是自动配置初始化的时候出问题了,如原理解释中的在加载JerseyAutoConfiguration这个bean的时候,有一个先决条件是存在ResourceConfig类型的bean,所以如果我们示例中定义的JerseyConfig的bean加载的顺序晚于JerseyAutoConfiguration的加载的时候,就会出现这种情况。这个时候就需要让示例中的JerseyConfig的bean被提前解析到加载,这个可以根据工程的配置环境来进行调整。

如下给一种简单而又粗暴的解决办法,就是把这个bean注册到启动类中:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    @Bean
    public ResourceConfig resourceConfig() {
        return new JerseyConfig();
    }
}

还有不少其它好的解决方案,这里不多说明了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不识君的荒漠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值