@Value注解字段传递至DTO层返回null的技术求助
问题分析与解决方案
看起来你遇到的核心问题是Spring的@Value注入未生效,加上映射逻辑没处理配置类数据,导致服务层拿到ConstantClass的null值。下面一步步拆解问题并给出修复方案:
1. 先修复ConstantClass的注入问题
你的ConstantClass存在两个关键错误:
- 没有被Spring容器管理,导致@Value注解完全不起作用
- 错误的无参构造函数,试图在Spring完成注入前获取值
修正后的ConstantClass代码
// 添加@Component让Spring扫描并创建实例 @Component public class ConstantClass { // 用final保证不可变,更安全 private final String hostName; private final String pathStart; // 构造注入:Spring会自动把配置文件中的值注入到构造参数中 public ConstantClass( @Value("${api.url}") String hostName, @Value("${sign.path}") String pathStart ) { this.hostName = hostName; this.pathStart = pathStart; } // 提供getter方法供外部访问 public String getHostName() { return hostName; } public String getPathStart() { return pathStart; } }
这样Spring会在启动时自动读取application.properties中的值并注入到ConstantClass实例中。
2. 修正MyClass的实例化与依赖传递
你的MyClass构造函数名写错了(应该是MyClass而非DocumentToSignRestRequest),而且需要确保使用Spring管理的ConstantClass实例,而不是手动new一个未注入的对象。
修正后的MyClass代码
public class MyClass { private OptionClass optionClass; private ConstantClass constantClass; // 修正构造函数名,确保参数是Spring注入的ConstantClass public MyClass(OptionClass optionClass, ConstantClass constantClass) { this.optionClass = optionClass; this.constantClass = constantClass; } // 按需添加getter/setter }
3. 修正Controller中的映射逻辑
documentToPrepare是请求体,只包含OptionClass的业务数据,不会包含ConstantClass的配置项,所以ModelMapper无法自动映射这部分数据。你需要手动将Spring管理的ConstantClass值设置到DTO中:
优化后的Controller代码
@RestController public class YourController { // 注入Spring管理的实例,不要每次请求new ModelMapper @Autowired private ConstantClass constantClass; @Autowired private ModelMapper modelMapper; @Autowired private DocumentService documentService; @PostMapping( value="/sign", consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE} ) public MyClassRest prepareDocument(@RequestBody DocumentToPrepare documentToPrepare) throws Exception { // 1. 映射请求体到MyClassDto的Option部分 MyClassDto myClassDto = modelMapper.map(documentToPrepare, MyClassDto.class); // 2. 手动设置ConstantClass的配置值到DTO中 // 如果MyClassDto包含ConstantClass对象: // myClassDto.setConstantClass(constantClass); // 如果MyClassDto直接包含hostName/pathStart字段: myClassDto.setHostName(constantClass.getHostName()); myClassDto.setPathStart(constantClass.getPathStart()); // 3. 调用服务层(注意原代码的documentDto应该是myClassDto的笔误) DocumentDto signedDocument = documentService.signDocument(myClassDto); // 4. 映射返回结果 return modelMapper.map(signedDocument, MyClassRest.class); } }
4. 额外优化:将ModelMapper配置为Spring Bean
不要每次请求都new ModelMapper,建议全局配置一个Bean:
@Configuration public class ModelMapperConfig { @Bean public ModelMapper modelMapper() { return new ModelMapper(); } }
这样调整后,ConstantClass的配置值就能正常注入,服务层也能拿到正确的非null值了。
内容的提问来源于stack exchange,提问作者davidvera
相关产品推荐
相关产品推荐

