Jersey2中如何注入Spring组件

本文详细介绍如何在Jersey RESTful服务中整合Spring框架,包括Maven依赖配置、注解使用及常见问题解决,如@Autowired与@Qualifier的正确应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引入Maven依赖

下面以Jersey 2.0和Spring 3.0版本为例。

<!-- jersey基础依赖-->
<dependency>
	<groupId>org.glassfish.jersey.core</groupId>
	<artifactId>jersey-server</artifactId>
	<version>2.0</version>
</dependency>
<dependency>
	<groupId>org.glassfish.jersey.containers</groupId>
	<artifactId>jersey-container-servlet</artifactId>
	<version>2.0</version>
</dependency>

<!-- 
1、核心内容:配置该组件后就可以在Jersey Resource类中通过注解注入Spring组件了。
2、该组件目前已支持Spring4和Spring5,只需将artifactId修改为jersey-spring4或者jersey-spring5,并调整相应版本号即可。
-->
<dependency>
	<groupId>org.glassfish.jersey.ext</groupId>
	<artifactId>jersey-spring3</artifactId>
	<version>2.2</version>
</dependency>

代码示例

// 使用Spring的Service注解生成实现类
@Service
public class WorkServiceImpl implements WorkService {
	...
}

@Path("/work")
public class WorkResource {

	// 使用Spring的Autowired注解
	@Autowired
	private WorkService	workService;

	@Path("/")
	@POST
	@Produces(MediaType.TEXT_PLAIN)
	public void accept(@BeanParam WorkVO work) {
		workService.accept(work);
	}
}

可能会遇到的问题

一般情况下,上边代码中的workService可以被正常调用。但是如果项目中WorkService接口有多个实现类,此时在Spring环境下就不可以按照接口类型(byType)进行注入了,而只能按照名称(byName)注入,所以需要在@Service中增加beanName,例如:

@Service("weixinWorkService")
public class WeixinWorkServiceImpl implements WorkService {
	...
}

@Service("appWorkService")
public class AppWorkServiceImpl implements WorkService {
	...
}

这时如果想在WorkService中注入WeixinWorkServiceImpl,我们可能首先想到的是使用javax.annotation.Resource注解,将代码修改成:

@Path("/work")
public class WorkResource {

	// 使用Javax的Resource注解
	@Resource(name = "weixinWorkService")
	private WorkService	workService;

	@Path("/")
	@POST
	@Produces(MediaType.TEXT_PLAIN)
	public void accept(@BeanParam WorkVO work) {
		workService.accept(work);
	}
}

但运行代码后发现控制台会报出空指针异常,然后定位到是workService为null导致的。

后来经过一系列尝试并追踪到相关源码才发现,原来Jersey-Spring3组件只支持Spring的@Autowired和@Qualifier,根本就不会解析@Resource。

Jersey-Spring3中负责解析注入组件的是org.glassfish.jersey.server.spring.AutowiredInjectResolver类。

public class AutowiredInjectResolver implements InjectionResolver<Autowired> {

 	@Override
    public Object resolve(Injectee injectee, ServiceHandle<?> root) {
        AnnotatedElement parent = injectee.getParent();
        String beanName = null;
        if(parent != null) {
        	// 划重点:解析@Qualifier注解,尝试获取beanName
            Qualifier an = parent.getAnnotation(Qualifier.class); 
            if(an != null) {
                beanName = an.value();
            }
        }
        return getBeanFromSpringContext(beanName, injectee.getRequiredType());
    }

    private Object getBeanFromSpringContext(String beanName, Type beanType) {
        Class<?> bt = getClassFromType(beanType);
        // 划重点:如果beanName不为空,则通过名称获取Spring 
        if(beanName != null) { bean
            return ctx.getBean(beanName, bt);
        }
        // 划重点:如果beanName为空,则按照类型获取
        Map<String, ?> beans = ctx.getBeansOfType(bt);
        // 划重点:如果未获取到bean或者获取到多个bean,则返回null。
        // 如果一个接口有多个实现类但没有定义@Qualifier时,注入也会失败,运行代码后会报出NPE。
        if(beans == null || beans.size() != 1) {
            LOGGER.warning(LocalizationMessages.NO_BEANS_FOUND_FOR_TYPE(beanType)); 
            return null;
        }
        return beans.values().iterator().next();
    }
}

找到原因后,解决就很容易了。

@Path("/work")
public class WorkResource {

	// 同时使用Autowired和Qualifier
	@Autowired
	@Qualifier(name = "weixinWorkService")
	private WorkService	workService;

	......
}

小结

  1. Jersey2支持通过注解与Spring进行整合,但仅支持@Autowired和@Qualifier。
  2. 不同框架或者组件对于注解的支持范围可能是不同的。因为平时使用Spring比较多,所以很容易混淆。
  3. 尽量使用统一的技术栈。例如,在没有特殊情况下,Spring环境可以使用SpringMVC替换Jersey。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值