问题描述
我正在使用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 ServletRegistrationBean
s 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:
-
对其中一个Jersey应用程序使用Spring Boot自动配置,并添加另一个
ServletRegistrationBean
为您的另一个。需要注意的一点是,创建的ServletRegistrationBean
的ResourceConfig
不应该是Spring组件(即没有@Component
或@Configuration
),否则您仍将面临同样的错误。
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 theResourceConfig
for your createdServletRegistrationBean
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 ServletRegistrationBean
s. 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启动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!