Spring启动 - 会话作用域组件的setter不能使用单件服务 - 字段为空
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring启动 - 会话作用域组件的setter不能使用单件服务 - 字段为空相关的知识,希望对你有一定的参考价值。
我在Spring Boot中的REST控制器后面有一个简单的服务。该服务是一个单例(默认情况下),我正在自动装配一个会话范围的bean组件,用于存储会话首选项信息并尝试从服务中填充其值。我在自动装配的组件上调用setter,但我设置的字段保持为空并且不会更改。
尝试过使用和不使用龙目岛的豆子;还有和没有在FooPref上实现Serializable;还将属性从FooPrefs复制到另一个DTO并返回它;还通过@Autowired注入以及@Inject构造函数注入。在所有这些情况下,字段保持为空。
使用spring-boot-starter-web运行Spring Boot(spring-boot-starter-parent)1.5.6.RELEASE,Java 8。
会话范围的组件:
@Component
@SessionScope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@Data
@NoArgsConstructor
public class FooPrefs implements Serializable {
private String errorMessage;
private String email;
private String firstName;
private String lastName;
}
REST控制器:
@RestController
@RequestMapping("/api/foo")
public class FooController {
@Autowired
private FooPrefs fooPrefs;
private final FooService fooService;
@Inject
public FooController(FooService fooService) {
this.fooService = fooService;
}
@PostMapping(value = "/prefs", consumes = "application/json", produces = "application/json")
public FooPrefs updatePrefs(@RequestBody Person person) {
fooService.updatePrefs(person);
// These checks are evaluating to true
if (fooPrefs.getEmail() == null) {
LOGGER.error("Email is null!!");
}
if (fooPrefs.getFirstName() == null) {
LOGGER.error("First Name is null!!");
}
if (fooPrefs.getFirstName() == null) {
LOGGER.error("First Name is null!!");
}
return fooPrefs;
}
}
服务:
@Service
@Scope(value = "singleton")
@Transactional(readOnly = true)
public class FooService {
@Autowired
private FooPrefs fooPrefs;
@Inject
public FooService(FooRepository fooRepository) {
this.fooRepository = fooRepository;
}
public void updatePrefs(Person person) {
fooRepository.updatePerson(person);
//the fields below appear to getting set correctly while debugging in the scope of this method call but after method return, all values on fooPrefs are null
fooPrefs.setEmail(person.getEmail());
fooPrefs.setFirstName(person.getFirstName());
fooPrefs.setLastName(person.getLastName());
}
}
我发现了我的问题。字段被添加到我的FooPrefs会话管理对象中,并破坏了我的客户端。这些setter实际上正在工作,并被一些错误处理代码排除在外。
以下编辑修复了JSON序列化问题:
会话范围的组件(无更改)
新Dto
@Data
@NoArgsConstructor
public class FooPrefsDto {
private String errorMessage;
private String email;
private String firstName;
private String lastName;
}
控制器(更新)
@RestController
@RequestMapping("/api/foo")
public class FooController {
private final FooService fooService;
@Inject
public FooController(FooService fooService) {
this.fooService = fooService;
}
@PostMapping(value = "/prefs", consumes = "application/json", produces = "application/json")
public FooPrefsDto updatePrefs(@RequestBody Person person) {
FooPrefsDto result = fooService.updatePrefs(person);
// results coming back correctly now
if (result.getEmail() == null) {
LOGGER.error("Email is null!!");
}
if (result.getFirstName() == null) {
LOGGER.error("First Name is null!!");
}
if (result.getFirstName() == null) {
LOGGER.error("First Name is null!!");
}
return result;
}
}
服务(更新)
@Service
@Scope(value = "singleton")
@Transactional(readOnly = true)
public class FooService {
@Autowired
private FooPrefs fooPrefs;
@Inject
public FooService(FooRepository fooRepository) {
this.fooRepository = fooRepository;
}
public FooPrefsDto updatePrefs(Person person) {
fooRepository.updatePerson(person);
//the fields below appear to getting set correctly while debugging in the scope of this method call but after method return, all values on fooPrefs are null
fooPrefs.setEmail(person.getEmail());
fooPrefs.setFirstName(person.getFirstName());
fooPrefs.setLastName(person.getLastName());
return getFooPrefsDto();
}
private FooPrefsDto getFooPrefsDto() {
FooPrefsDto retDto = new FooPrefsDto();
retDto.setEmail(fooPrefs.getEmail());
retDto.setLastName(fooPrefs.getLastName());
retDto.setFirstName(fooPrefs.getFirstName());
return retDto;
}
}
以上是关于Spring启动 - 会话作用域组件的setter不能使用单件服务 - 字段为空的主要内容,如果未能解决你的问题,请参考以下文章
Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.5.4 请求(request)会话(session)和全局会话(global session)作用域