【发布时间】:2021-11-14 06:51:41
【问题描述】:
我无法设置属性值,即。 shortname 到 Spring Boot 中的 SessionScope bean。
这是我的课:
import java.util.Map;
public class LdapUser {
private String shortname = "";
private Map<String,String> token = null;
private String id = "";
public LdapUser() {
}
public String getshortname() {
return shortname;
}
public void setshortname(String shortname) {
this.shortname = shortname;
}
... remaining geters and setters
我的 Bean 定义在这里:
import xxx.controllers.SwitchController;
import xxx.isim.LdapUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;
@Configuration
public class RestTemplateClient {
Logger logger = LoggerFactory.getLogger(SwitchController.class);
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public LdapUser sessionScopedLdapUser() {
logger.info("LdapUser bean instance created");
return new LdapUser();
}
}
我在控制器中使用 Bean:
import xxx.errors.IsimConnectionException;
import xxx.isim.IsimConnection;
import xxx.isim.LdapUser;
import xxx.services.IsimRestApiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.Resource;
import java.security.Principal;
@Controller
public class HomeController {
private static final Logger log = LoggerFactory.getLogger(HomeController.class);
@Autowired
IsimRestApiService isimConn;
@Resource(name = "sessionScopedLdapUser")
LdapUser sessionScopedLdapUser;
@RequestMapping("/")
public String index(Principal principal) throws IsimConnectionException {
Authentication authentication = (Authentication) principal;
/
if ((authentication.getPrincipal() != null) && (authentication.isAuthenticated())) {
// set the shortname for the session
String shortname = (String)authentication.getPrincipal();
sessionScopedLdapUser.setshortname(shortname); //<-----
我的 Bean 的 shortname 值在带有箭头的行之后仍然为空,即使我正确获得了 shortname 字符串值并且该值不为空。您能否指出我在设置 bean 属性值时做错了什么。我遵循了 SessionScope Beans 的示例 here
更新:
我也尝试使用 autowired 而不是 @Resource(name = "sessionScopedLdapUser") 但执行 sessionScopedLdapUser.setshortname(shortname);
@Autowired
LdapUser sessionScopedLdapUser
在日志中我还可以看到 LdapUser bean 实例被创建了 3 次。这怎么可能?
2021-09-21 10:55:55,469 INFO [http-nio-8080-exec-4] xxx.config.RestTemplateClient: LdapUser bean instance created
2021-09-21 10:57:05,247 INFO [http-nio-8080-exec-4] xxx.config.RestTemplateClient: LdapUser bean instance created
2021-09-21 10:58:08,401 INFO [http-nio-8080-exec-4] xxx.config.RestTemplateClient: LdapUser bean instance created
想法是每个 HTTP 会话有一个 bean。我真的很困惑,希望能得到一些提示。我正在阅读这个article,这可能是因为我正在尝试将一个会话范围 bean 注入到一个 Singletone bean。
我的文件结构是:
xxx
---auth
---config
--- RestRemplateClient
---controllers
--- HomeController
---errors
---isim
--- LdapUser
---services
Mainapp
【问题讨论】:
-
您可以尝试在 HomeController 的控制器级别添加 @SessionAttributes(types = { LdapUser .class}) 吗?
-
@SessionAttributes是为了完全不同的东西。请在您的代码中包含导入语句,因为我想知道您正在使用 which@SessionScope注释。使用@Resource或@Autowired不会改变任何事情。我想知道一件事是什么时候null?你怎么检查这个?是调试器中的null,还是其他地方的null? -
嗨@M.Deinum 我很抱歉,我最初没有看到你的问题。我在原始问题中包含了导入语句。我在调试器中检查了 bean 字段
shortname的值。我尝试了@SessionScope 和@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) -
如果您签入调试器,该字段将出现
null,因为您查看的是代理而不是会话中的真实对象。所以基本上你的大脑在欺骗你。如果您检查调试器,您将看到该类型实际上类似于LdapUser$EnchangedBySpring_Cgling$12343,这将有几个回调等相关联,如果您深入挖掘,您会发现实际的会话范围实例。但现在您看到的是代理而不是实际对象。 -
非常感谢@M。 Deinum 以编程方式显示它工作正常。正如您所指出的,该字段的调试器值来自代理。我花了 2 天时间来接受这个:-)
标签: java spring-boot session-state spring-bean