gpt4 book ai didi

java - Spring @CacheEvict 不工作

转载 作者:搜寻专家 更新时间:2023-11-01 03:33:21 25 4
gpt4 key购买 nike

我有 Spring MVC 的经验,但第一次使用缓存。这些是我已经完成的步骤。

步骤:1

//在 spring 配置中

@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("user");
}

//缓存对象

public class CachedUser {   
private String username;
private String token;
// Public getter-setter
}

//AuthServiceImp

@Service
public class AuthServiceImp implements AuthService {

@Override
@Cacheable(value="user", key="#token")
@Transactional
public CachedUser loadUserDetailsFromDb(String username, String token) {
// codes here
}

@Override
@CacheEvict(value="user", key="#token")
@Transactional
public void removeUser(String username, String token) {
// codes here
}
}

//我的过滤器

public class AuthenticationTokenFilter extends UsernamePasswordAuthenticationFilter {
AuthService authService = WebApplicationContextUtils
.getRequiredWebApplicationContext(this.getServletContext())
.getBean(AuthService.class);
CachedUser user = this.authService.loadUserDetailsFromDb(username, authToken);
}

// Controller

@RestController
public class AuthenticationController {
@Autowired
private AuthService authService;
@GetMapping("logout2")
public ResponseModel logout(@RequestAttribute("username") String username,
HttpServletRequest request) {
String token = request.getHeader(tokenHeader);
authService.removeUser(username, token);
return new ResponseModel(200,"Success",null);
}
}

每当从 AuthenticationTokenFilter 调用 loadUserDetailsFromDb 时,它都会返回缓存的对象(显然第一次调用除外)。这意味着 @Cacheable(value="user", key="#token") 工作正常。

但即使在我注销并调用 authService.removeUser() 之后,调用 loadUserDetailsFromDb() 也会获取缓存的对象。这意味着 @CacheEvict(value="user", key="#token") 不工作。

步骤:2

引用this并将 removeUser() 移动到另一个服务(比如 CacheServiceImp implements CacheService ),但同样的问题。

步骤:3

引用 this并且,据我所知,将 @Cache* 注释移动到接口(interface) AuthService,出现以下错误。

java.lang.IllegalArgumentException: Null key returned for cache operation (maybe you are using named params on classes without debug info?)

注意: 是不是逐出的问题,因为我是从不同的类中调用@Cacheable@CacheEvict 方法。这是来自 AuthenticationTokenFilterAuthenticationController

最佳答案

在玩弄了我的代码、头脑和互联网之后,我终于解决了这个问题。这是我的 Spring(安全)配置中的错误,我未能随问题一起发布。

错误 1:

SecurityInitializer类中

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {    
public SecurityInitializer() {
super(WebSecurityConfiguration.class);
}

}

由于该项目包含 Spring MVC 配置,因此不得实现构造函数。所以删除了构造函数。然后,此类只需为每个 URL 注册 springSecurityFilterChain 过滤器。

错误 2:(上述问题的真正原因)

我以两种方式添加了我的AuthenticationTokenFilter:

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// other overrides
@Override
protected Filter[] getServletFilters() {
return new Filter[]{ new AuthenticationTokenFilter() };
}
}

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
// Other config
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
//Other config
httpSecurity.addFilterBefore(authTokenFilter,
UsernamePasswordAuthenticationFilter.class);
}
}

这使得过滤器被调用两次,一次在 Spring 上下文中,另一次作为普通 Servlet 过滤器

因此删除了 WebAppInitializer 中的配置

额外的改变

WebSecurityConfiguration 中删除了 @ComponentScan,因为它已经在 SpringMvcConfig 中。 这需要在同一上下文中加载两个配置。通过以下代码完成。

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { SpringMvcConfig.class, WebSecurityConfiguration.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
// Removed filter registering from here (Mistake 2)
}

最后,一切正常:)

关于java - Spring @CacheEvict 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40956057/

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