本文介绍了公共和私人资源使用不同的路径Jersey + Spring启动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Spring boot + Jersey + Spring security, I want to have public and private endpoints, I want an schema as follow:


  • / rest - 我的根上下文

  • / public - 我想将公共端点放在此上下文中,它必须位于根上下文中,例如 / rest / public / pings

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

  • /rest -- My root context
  • /public -- I want to place my public endpoints in this context, It must be inside of the root context like /rest/public/pings
  • /private -- I want to place my private endpoints in this context, It must be inside of the root context like /rest/private/accounts

我的配置如下:

泽西配置:

@Configuration
@ApplicationPath("/rest")
public class RestConfig extends ResourceConfig {
    public RestConfig() {
        register(SampleResource.class);
    }
}

Spring security 配置:

@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();
    }

}

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

The question is how can I register two application paths inside of my /rest context, one for /public and the other one for /private ?

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

NOTE: I tried to create another ResourceConfig as follow:

@Configuration
@ApplicationPath("/rest/public")
public class RestPublicConfig extends ResourceConfig{
    public RestPublicConfig() {
        register(PingResource.class);
    }
}

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

But I'm getting the next error:

 No qualifying bean of type [org.glassfish.jersey.server.ResourceConfig] is defined: expected single matching bean but found 2: restConfig,restPublicConfig

感谢您的帮助:)

推荐答案

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

In a servlet container, the Jersey runtime, runs as either a servlet or as a servlet filter. How spring boot configures servlets and filters is through ServletRegistrationBeans and FilterRegistrationBeans, respectively. To get an idea of how that configuration works behind scenes, you can look at the source code for the JerseyAutoConfiguration

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

In the JerseyAutoConfiguration, you can see that a ResourceConfig is injected, and that is the ResourceConfig used to create the Jersey servlet or Jersey filter (depending on your choice of configuration). So the reason for the error is that you can't have ambiguous beans, which you have two ResourceConfig beans. So Spring doesn't know which one to inject.

可以做什么,每个<$ c $使用两个不同的servlet C> ResourceConfig 。问题是Spring Boot只为你挂了一个针对Jersey的servlet,所以你需要自己配置另一个servlet。有两种选择:

What you can do though, is use two different servlets for each ResourceConfig. The problem is that Spring Boot only hooks you up with one servlet for Jersey, so you need to configure the other one yourself. There are two options:


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

  1. Use the Spring Boot auto-configuration for one of the Jersey applications, and add another ServletRegistrationBean for your other one. The one thing to note is that the ResourceConfig for your created ServletRegistrationBean should not be a Spring component (i.e. no @Component or @Configuration), or else you will still face the same error.

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;
}


  • 根本不要使用Spring Boot配置。只需创建两个 ServletRegistrationBean 。在这种情况下,您的 ResourceConfig 类都不应该是Spring bean。

  • Don't use the Spring Boot configuration at all. Just create two ServletRegistrationBeans. In this case, none of your ResourceConfig classes should be Spring beans.

    @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;
    }
    


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

    Personally, I prefer the second option, as it is easier to reason about the configurations when they are all in one place.

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

    Another thing to note is that the two Jersey applications will be completely independent, meaning you will need to register providers (like filters) for both applications

    这篇关于公共和私人资源使用不同的路径Jersey + Spring启动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-12 18:11