gpt4 book ai didi

java - 无法在 Servlet 筛选器中 Autowiring 具有请求范围的组件

转载 作者:行者123 更新时间:2023-12-02 03:50:46 24 4
gpt4 key购买 nike

我有一个位于 Controller 前面的请求过滤器。此过滤器检索用户配置文件并设置具有请求范围的 userProfile 组件的属性,然后传递到下一个过滤器。

当尝试从过滤器内部访问userProfile时,该属性尚未成功 Autowiring 。

尝试从过滤器内部 Autowiring userProfile 时,我看到以下异常:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.userProfile': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

但是,当尝试从 Controller 内部访问userProfile时,该属性已成功 Autowiring 。

如何成功 Autowiring 过滤器内的 userProfile 组件?

请求过滤器:

@Component
public class JwtAuthenticationFilter extends GenericFilterBean implements Filter {

@Autowired
public UserProfile userProfile;

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain next) throws IOException, ServletException {

....

userProfile
.username(authorizedUser.username())
.email(authorizedUser.email())
.firstName(authorizedUser.firstName())
.lastName(authorizedUser.lastName());
}
}

Controller :

@CrossOrigin
@RestController
@RequestMapping("/users")
public class UsersController {

@Autowired
public UserProfile userProfile;

@GetMapping(
path = "/current",
produces = MediaType.APPLICATION_JSON_VALUE
)
@ResponseStatus(HttpStatus.OK)
public String currentUser() throws ResponseFormatterException {

System.out.println(userProfile.email());
}
}

用户个人资料:

@Component
@RequestScope
public class UserProfile {

@Getter @Setter
@Accessors(fluent = true)
@JsonProperty("username")
private String username;

@Getter @Setter
@Accessors(fluent = true)
@JsonProperty("email")
private String email;

@Getter @Setter
@Accessors(fluent = true)
@JsonProperty("firstName")
private String firstName;

@Getter @Setter
@Accessors(fluent = true)
@JsonProperty("lastName")
private String lastName;
}

安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfigurator extends WebSecurityConfigurerAdapter {

@Autowired
private JwtAuthenticatingFilter jwtAuthenticatingFilter;

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(getAuthenticator());
}

public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/actuator/**")
.antMatchers("/favicon.ico");
}

protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/favicon.ico").permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.addFilterBefore(getFilter(), SessionManagementFilter.class)
.authenticationProvider(getAuthenticator())
.exceptionHandling()
.authenticationEntryPoint(new HttpAuthenticationEntryPoint());
}

protected AbstractAuthenticator getAuthenticator() {
return new JwtAuthenticator();
}

protected AuthenticatingFilter getFilter() {
return jwtAuthenticatingFilter;
}
}

最佳答案

我认为问题可能是您正在尝试将请求范围的 bean(较小范围)注入(inject)到单例范围 bean(较大范围)中。有几个原因导致此方法不起作用:

  • 实例化单例时,没有 Activity 的请求范围
  • 对于第二个请求,单例将使用为第一个请求注入(inject)的同一个过时 Bean。

您可以使用 javax.inject.Provider 按需延迟注入(inject)请求范围的 bean 来解决此问题。

@Component
public class JwtAuthenticationFilter extends GenericFilterBean implements Filter {

@Autowired
public Provider<UserProfile> userProfileProvider;

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain next) throws IOException, ServletException {

....

userProfileProvider.get()
.username(authorizedUser.username())
.email(authorizedUser.email())
.firstName(authorizedUser.firstName())
.lastName(authorizedUser.lastName());
}
}

Spring 有一个类似的接口(interface)org.springframework.beans.factory.ObjectFactory,如果您在设置 Provider 的依赖项时遇到困难,可以使用它。

@Component
public class JwtAuthenticationFilter extends GenericFilterBean implements Filter {

@Autowired
public ObjectFactory<UserProfile> userProfileFactory;

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain next) throws IOException, ServletException {

....

userProfileFactory.getObject()
.username(authorizedUser.username())
.email(authorizedUser.email())
.firstName(authorizedUser.firstName())
.lastName(authorizedUser.lastName());
}
}

关于java - 无法在 Servlet 筛选器中 Autowiring 具有请求范围的组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56780484/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com