使用不同的路径为公共和私人资源Jersey + Spring启动

Ale*_*sta 12 java rest spring jersey spring-boot

我正在使用Spring boot + Jersey + Spring安全性,我想拥有公共和私有端点,我想要一个架构如下:

  • / rest - 我的根上下文
  • / public - 我想将我的公共端点放在这个上下文中,它必须在根上下文中/rest/public/pings
  • / private - 我想将我的私有端点放在这个上下文中,它必须在根上下文中/rest/private/accounts

我的配置如下:

泽西配置:

@Configuration
@ApplicationPath("/rest")
public class RestConfig extends ResourceConfig {
    public RestConfig() {
        register(SampleResource.class);
    }
}
Run Code Online (Sandbox Code Playgroud)

Spring安全配置:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

........

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/rest/public/**").permitAll();
        http.antMatcher("/rest/**").authorizeRequests().anyRequest().fullyAuthenticated().and().httpBasic();
        http.csrf().disable();
    }

}
Run Code Online (Sandbox Code Playgroud)

问题是如何在my/rest上下文中注册两个应用程序路径,一个用于/ public,另一个用于/ private?

注意:我尝试创建另一个ResourceConfig,如下所示:

@Configuration
@ApplicationPath("/rest/public")
public class RestPublicConfig extends ResourceConfig{
    public RestPublicConfig() {
        register(PingResource.class);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我得到了下一个错误:

 No qualifying bean of type [org.glassfish.jersey.server.ResourceConfig] is defined: expected single matching bean but found 2: restConfig,restPublicConfig
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助 :)

Pau*_*tha 13

在servlet容器中,Jersey运行时作为servlet或servlet过滤器运行.spring boot如何配置servlet和过滤器分别是通过ServletRegistrationBeans和FilterRegistrationBeans.要了解该配置如何在幕后工作,您可以查看该源代码JerseyAutoConfiguration

JerseyAutoConfiguration,你可以看到a ResourceConfig被注入,那就是ResourceConfig用来创建Jersey servlet或Jersey过滤器(取决于你选择的配置).所以错误的原因是你不能有不明确的bean,你有两个ResourceConfigbean.所以Spring不知道要注入哪一个.

但你可以做的是为每个使用两个不同的servlet ResourceConfig.问题是Spring Boot只为你提供了一个针对Jersey的servlet,所以你需要自己配置另一个.有两种选择:

  1. 对其中一个Jersey应用程序使用Spring Boot自动配置,为另一个应用程序添加另一个ServletRegistrationBean.需要注意的一点是,ResourceConfig你创建的ServletRegistrationBean不应该是Spring组件(即no @Component@Configuration),否则你仍然会面临同样的错误.

    public class PublicConfig extends ResourceConfig {
        public PublicConfig() {
            register(PingResource.class);
        }
    }
    ...
    // in your Spring Boot configuration class
    @Bean
    public ServletRegistrationBean publicJersey() {
        ServletRegistrationBean publicJersey 
                = new ServletRegistrationBean(new ServletContainer(new PublicConfig()));
        publicJersey.addUrlMappings("/rest/public/*");
        publicJersey.setName("PublicJersey");
        publicJersey.setLoadOnStartup(0);
        return publicJersey;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 根本不要使用Spring Boot配置.只需创建两个ServletRegistrationBean.在这种情况下,您的ResourceConfig类都不应该是Spring bean.

    @Bean
    public ServletRegistrationBean publicJersey() {
        ServletRegistrationBean publicJersey 
                = new ServletRegistrationBean(new ServletContainer(new PublicConfig()));
        publicJersey.addUrlMappings("/rest/public/*");
        publicJersey.setName("PublicJersey");
        publicJersey.setLoadOnStartup(0);
        return publicJersey;
    }
    
    @Bean
    public ServletRegistrationBean privateJersey() {
        ServletRegistrationBean privateJersey 
               = new ServletRegistrationBean(new ServletContainer(new PrivateConfig()));
        privateJersey.addUrlMappings("/rest/private/*");
        privateJersey.setName("PrivateJersey");
        privateJersey.setLoadOnStartup(1);
        return privateJersey;
    }
    
    Run Code Online (Sandbox Code Playgroud)

就个人而言,我更喜欢第二种选择,因为当它们都在一个地方时,更容易推断配置.

另外需要注意的是,两个Jersey应用程序将完全独立,这意味着您需要为两个应用程序注册提供程序(如过滤器)


use*_*685 0

您将不被允许为您的资源类创建两个 bean。您也可以使用单个资源类来实现您想要实现的目标。

这是一个例子:

@Path("rest")
public class SampleResourceClass {

  @Path("/public/pings")
  @GET
  public Responce getPings(){
    /* Code Here */
  }

  @Path("/private/accounts")
  @GET
  public Response getAccounts(){
    /* Code Here */
  }
}
Run Code Online (Sandbox Code Playgroud)