最近公司内部系统要做数据对接,故使用 jersey 来做 restful webservice 接口设计。由于 spring boot 已经集成 jersey,估计直接导入 spring-boot-starter-jersey 就好了。

在测试时候除了遇到中文乱码之外花费了比较长的时间,其余暂时没遇到大的问题。然而发布的时候发现了一个坑。

public class JerseyConfig extends ResourceConfig {

    public JerseyConfig(){
//registerClasses(findAllClasses());
packages("com.xx");
// 注册日志
register(LoggingFeature.class);
// 异常处理
register(ExceptionHandler.class);
// 跨域过滤器注册
register(CorsFilter.class); }
}

jersey 是使用 register(Class clazz) 或者 packages("packageName") 来注册或者扫描来加载所需的类到容器中的。然而在实际项目中,使用 register(Class clazz) 会写大量的注册类,依赖性太强,而且在maven多模块中更不好处理。

而使用 packages 来扫描,在开发测试的时候倒没发现什么问题,但是使用 spring boot 打成 jar 包运行时,会产生 FileNotFound 的错误,这是因为 使用 jersey 的 packages 扫描的机制是无法扫描到 jar 中的 class 文件的。

由于使用的是 spring boot,spring 的 component scan 是可以做到的。故参考 spring 扫描机制的源码,将 jar 中的 class 文件加载进来就好了。

代码如下:

import lombok.extern.slf4j.Slf4j;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.ClassUtils; import java.io.IOException;
import java.util.HashSet;
import java.util.Set; /**
* @author gongtao
* @version 2018-04-23 10:15
**/
@Configuration
@Slf4j
public class JerseyConfig extends ResourceConfig { public JerseyConfig(){
//扫描注册
registerClasses(findAllClasses());
// 注册日志
register(LoggingFeature.class);
// 异常处理
register(ExceptionHandler.class);
// 跨域过滤器注册
register(CorsFilter.class); } /**
* 由于spring boot 打包为jar包,jersey packages 无法扫描jar对应的文件夹的文件,故自定义包扫描
* @return
*/
private Set<Class<?>> findAllClasses(){
String scanPackages = "com.xxx.eoms.innerinterface.interfaces.resource.*";
ClassLoader loader = this.getClass().getClassLoader();
Resource[] resources = new Resource[0];
try {
resources = scan(loader, scanPackages);
} catch (IOException e) {
log.error("加载class异常",e);
}
return convert(loader, resources);
} /**
* 扫描 jar 包
* @param loader
* @param packageName
* @return
* @throws IOException
*/
private Resource[] scan(ClassLoader loader, String packageName) throws IOException {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(loader);
String pattern = "classpath*:" + ClassUtils.convertClassNameToResourcePath(packageName) + "/**/*.class";
return resolver.getResources(pattern);
} /**
* 加载 class
* @param loader
* @param resource
* @return
*/
private Class<?> loadClass(ClassLoader loader,Resource resource) {
try {
CachingMetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(loader);
MetadataReader reader = metadataReaderFactory.getMetadataReader(resource);
return ClassUtils.forName(reader.getClassMetadata().getClassName(), loader);
} catch (LinkageError | ClassNotFoundException e) {
if (log.isDebugEnabled()) {
log.debug("Ignoring candidate class resource " + resource + " due to " + e);
}
return null;
} catch (Throwable e) {
if (log.isWarnEnabled()) {
log.warn("Unexpected failure when loading class resource " + resource, e);
}
return null;
}
} /**
* resources 转换为 Set<Class>
* @param loader
* @param resources
* @return
*/
private Set<Class<?>> convert(ClassLoader loader,Resource[] resources){
Set<Class<?>> classSet = new HashSet<>(resources.length);
for (Resource resource : resources){
Class<?> clazz = loadClass(loader, resource);
if (clazz != null){
classSet.add(clazz);
}
}
return classSet;
}

jersey在 spring boot 添加 packages 扫描路径支持的更多相关文章

  1. Spring boot 默认静态资源路径与手动配置访问路径的方法

    这篇文章主要介绍了Spring boot 默认静态资源路径与手动配置访问路径的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下   在application.propertis中配置 ##端口号 ...

  2. Spring Boot 添加JSP支持【转】

    Spring Boot 添加JSP支持 大体步骤: (1)            创建Maven web project: (2)            在pom.xml文件添加依赖: (3)     ...

  3. spring boot: @EnableScheduling开启计划任务支持,@Scheduled计划任务声明

    spring boot: @EnableScheduling开启计划任务支持, @Scheduled计划任务声明 package ch2.scheduler2; //日期转换方式 import jav ...

  4. spring boot 添加拦截器

    构建一个spring boot项目. 添加拦截器需要添加一个configuration @Configuration @ComponentScan(basePackageClasses = Appli ...

  5. Spring Boot 添加jersey-mvc-freemarker依赖后内置tomcat启动不了解决方案

    我在我的Spring Boot 项目的pom.xml中添加了jersey-mvc-freemarker依赖后,内置tomcat启动不了. 报错信息如下: org.springframework.con ...

  6. spring boot 添加拦截器的简单实例(springBoot 2.x版本,添加拦截器,静态资源不可访问解决方法)

    spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor 一.HandlerInterceptor HandlerInterceptor是s ...

  7. spring boot 添加整合ssl使得http变成https方法

    1. https出现的背景:(1)都知道http传输协议是裸漏的,明文传输的,极易被黑客拦截,因此,(2)人们想出的使用加密,也就是 对称加密 例如aes,不过这个由于因为对称加密需要每个客户端和服务 ...

  8. spring boot mybatis没有扫描jar中的Mapper接口

    只需要在spring boot启动类上加上注解,并指定jar包中接口文件包路径即可 如下: @ComponentScan(basePackages = "com.xx") @Map ...

  9. 为项目配置了Bean,结果Spring Boot并没有扫描到

    问题如图,而这个问题遇见的场景是因为自己在一个基础项目里面配置cros,按照网上的说法都配置了一边,结果发现前后端的通讯仍然报跨域问题.后来怀疑是否bean并没有被注入进去,导致没有生效,于是在代码中 ...

随机推荐

  1. ansj人名识别

    1.前言 ansj人名识别会用到两个字典,分别是:person/asian_name_freq.data.person/person.dic. 1.1.asian_name_freq.data 这是一 ...

  2. 【基于url权限管理 shiro(一)】--基础

    只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源.权限管理包括用户认证和授权两部分.   用户认证 1.概 ...

  3. ASP.NET三剑客 HttpApplication HttpModule HttpHandler 解析

    我们都知道,ASP.Net运行时环境中处理请求是通过一系列对象来完成的,包含HttpApplication,HttpModule, HttpHandler.之所以将这三个对象称之为ASP.NET三剑客 ...

  4. mongodb的设计特征

    MongoDB 的设计目标是高性能.可扩展.易部署.易使用,存储数据非常方便.其主要功能特性如下.   (1)面向集合存储,容易存储对象类型的数据.在MongoDB 中数据被分组存储在集合中,集合类似 ...

  5. Android base-adapter-helper 源码分析与扩展

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/44014941,本文出自:[张鸿洋的博客] 本篇博客是我加入Android 开源项 ...

  6. 一句python代码搭建FTP服务

    环境搭建: python windows/linux pip install pyftpdlib (安装失败请到这里下载:https://pypi.python.org/pypi/pyftpdlib/ ...

  7. 关于Flask-Login中session失效时间的处理

    最近需要使用Python开发web系统,主要用到的框架就是Flask,前端使用Jinja2模板引擎和Bootstrap,web容器使用Cherrypy,其中关于Login管理的使用了Flask-Log ...

  8. 【BZOJ 2713】[Violet 2]愚蠢的副官&&【BZOJ1183】[Croatian2008]Umnozak——【数位DP】

    题目链接: 2713传送门 1183传送! 题解: 由于看不懂英文题解(十个单词十一个不认识……),所以只能自己想QAQ. 其实乱搞就好= =. 首先我们发现,各位数字乘积要在1e9以下才可能有用,这 ...

  9. Linux vim常用命令

    什么是 vim? Vim是从 vi 发展出来的一个文本编辑器.代码补完.编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用. 简单的来说, vi 是老式的字处理器,不过功能已经很齐全了,但是 ...

  10. (3)STM32使用HAL库操作外部中断——实战操作

    有了上一篇的基础入门知识,使用Cube创建一个简单的外部中断就容易多了. 一.Cube配置 需求:使用PD10作为外部中断(下降沿触发)控制LED(PD12-PD14) 1.选型 STM32-F4-D ...