且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Spring Boot和Jersey产生ClassNotFound

更新时间:2022-03-16 00:06:10

Jersey classpath scanning limitations

对可执行jar布局的更改意味着在 泽西岛的类路径扫描现在也影响可执行的jar文件 作为可执行的war文件.要变通解决此问题,您可以 希望被泽西岛扫描的物品应包装在一个罐子中并包括在内 作为BOOT-INF/lib中的依赖项.然后,Spring Boot启动器应 配置为在启动时解压缩这些罐子,以便Jersey可以扫描 他们的内容.

The change to the layout of executable jars means that a limitation in Jersey’s classpath scanning now affects executable jar files as well as executable war files. To work around the problem, classes that you wish to be scanned by Jersey should be packaged in a jar and included as a dependency in BOOT-INF/lib. The Spring Boot launcher should then be configured to unpack those jars on start up so that Jersey can scan their contents.

这是一个已知的问题,有一个未合并的打开的请求然而.我建议您参考问题,其中提到了一些解决方法.

This is a known problem and there is a open pull request that's not merged yet. I suggest you refer this issue which mentions some workarounds.

解决方法

  1. 配置Boot的Maven插件以解压缩包含该插件的jar 包

  1. Configure Boot's Maven plugin to unpack the jars containing that package

使用以下解决方法

jersey 1:

import java.util.Map;

import javax.annotation.PostConstruct;
import javax.ws.rs.Path;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.sun.jersey.api.core.DefaultResourceConfig;

@Component
public class RestApplication extends DefaultResourceConfig {

    private static final Logger log = LoggerFactory.getLogger(RestApplication.class);

    public RestApplication() {
        getFeatures().put("com.sun.jersey.api.json.POJOMappingFeature", true);
    }

    @Autowired
    ApplicationContext appCtx;

    @PostConstruct
    public void setup() {
        log.info("Rest classes found:");
        Map<String,Object> beans = appCtx.getBeansWithAnnotation(Path.class);
        for (Object o : beans.values()) {
            log.info(" -> " + o.getClass().getName());
            getSingletons().add(o);
        }
    }

}
and

    @Autowired
    RestApplication restApplication;

    @Bean
    public ServletRegistrationBean jersey() {
        ServletRegistrationBean bean = new ServletRegistrationBean();
        bean.setServlet(new ServletContainer(restApplication));
        bean.addInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
        bean.setUrlMappings(Arrays.asList("/rest/*"));
        return bean;
    }
jersery2:

import java.util.Map;

import javax.annotation.PostConstruct;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Path;

import org.glassfish.jersey.server.ResourceConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.sun.jersey.api.core.ResourceConfig;

@Component
@ApplicationPath("/rest")
public class JerseyConfig extends ResourceConfig {

    private static final Logger log = LoggerFactory.getLogger(JerseyConfig.class);

    @Autowired
    ApplicationContext appCtx;

    @PostConstruct
    public void setup() {
        log.info("Rest classes found:");
        Map<String,Object> beans = appCtx.getBeansWithAnnotation(Path.class);
        for (Object o : beans.values()) {
            log.info(" -> " + o.getClass().getName());
            register(o);
        }
    }

}