Spring Boot电商后端启动失败求助:Bean依赖与配置问题
Spring Boot电商后端启动失败:无法解析配置占位符${encryption.salt.rounds}
我正在学习全栈开发,这是我的入门项目。我的Spring Boot电商后端无法启动,一开始怀疑是@Bean相关的类未被扫描问题,试过修改pom.xml依赖、给Bean命名都没解决。启动时抛出UnsatisfiedDependencyException异常,核心原因是无法解析配置占位符${encryption.salt.rounds}。
错误日志
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2023-10-27T21:34:20.993+01:00 ERROR 71951 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'authenticationController' defined in file [/Users/main/Documents/ecommerceBackend/target/classes/com/nea/ecommerceBackend/api/controller/auth/AuthenticationController.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'userService' defined in file [/Users/main/Documents/ecommerceBackend/target/classes/com/nea/ecommerceBackend/service/UserService.class]: Unsatisfied dependency expressed through constructor parameter 1: Error creating bean with name 'encryptionService': Injection of autowired dependencies failed at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:801) ~[spring-beans-6.0.13.jar:6.0.13] ... Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'encryption.salt.rounds' in value "${encryption.salt.rounds}" ...
相关代码文件
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.5</version> <relativePath/> </parent> <groupId>com.nea</groupId> <artifactId>ecommerceBackend</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ecommerceBackend</name> <description>Nea E-commerce website. </description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ... </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
AuthenticationController类
package com.nea.ecommerceBackend.api.controller.auth; import com.nea.ecommerceBackend.api.model.LoginBody; import com.nea.ecommerceBackend.api.model.LoginResponse; import com.nea.ecommerceBackend.api.model.RegistrationBody; import com.nea.ecommerceBackend.exception.UserAlreadyExistException; import com.nea.ecommerceBackend.service.UserService; import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/auth") public class AuthenticationController { private UserService userService; public AuthenticationController(UserService userService) { this.userService = userService; } @PostMapping("/register") public ResponseEntity registerUser(@Valid @RequestBody RegistrationBody registrationBody){ try { userService.registerUser(registrationBody); return ResponseEntity.ok().build(); } catch (UserAlreadyExistException ex) { return ResponseEntity.status(HttpStatus.CONFLICT).build(); } } @PostMapping("/login") public ResponseEntity<LoginResponse> loginUser(@Valid @RequestBody LoginBody loginBody){ String jwt = userService.loginUser(loginBody); if(jwt == null){ return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); } else { LoginResponse response = new LoginResponse(); response.setJwt(jwt); return ResponseEntity.ok(response); } } }
EncryptionService类
package com.nea.ecommerceBackend.service; import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.crypto.bcrypt.BCrypt; import org.springframework.stereotype.Service; @Service public class EncryptionService { @Value("${encryption.salt.rounds}") public int saltRounds; private String salt; @PostConstruct public void postConstruct(){ salt = BCrypt.gensalt(saltRounds); } public String encryptPassword(String password){ return BCrypt.hashpw(password, salt); } public boolean verifyPassword(String password, String hash){ return BCrypt.checkpw(password, hash); } }
UserService类
package com.nea.ecommerceBackend.service; import com.nea.ecommerceBackend.api.model.LoginBody; import com.nea.ecommerceBackend.api.model.RegistrationBody; import com.nea.ecommerceBackend.exception.UserAlreadyExistException; import com.nea.ecommerceBackend.model.LocalUser; import com.nea.ecommerceBackend.model.dao.LocalUserDAO; import org.springframework.stereotype.Service; import java.util.Optional; @Service public class UserService { private LocalUserDAO localUserDAO; private EncryptionService encryptionService; private JWTService jwtService; public UserService(LocalUserDAO localUserDAO, EncryptionService encryptionService, JWTService jwtService) { this.localUserDAO = localUserDAO; this.encryptionService = encryptionService; this.jwtService = jwtService; } public LocalUser registerUser(RegistrationBody registrationBody) throws UserAlreadyExistException { if(localUserDAO.findByEmailIgnoreCase(registrationBody.getEmail()).isPresent() || localUserDAO.findByUsernameIgnoreCase(registrationBody.getUsername()).isPresent()){ throw new UserAlreadyExistException(); } LocalUser user = new LocalUser(); user.setEmail(registrationBody.getEmail()); user.setFirstname(registrationBody.getFirstName()); user.setLastname((registrationBody.getLastName())); user.setUsername(registrationBody.getUsername()); user.setPassword(encryptionService.encryptPassword(registrationBody.getPassword())); return localUserDAO.save(user); } public String loginUser(LoginBody loginBody) { Optional<LocalUser> opUser = localUserDAO.findByUsernameIgnoreCase(loginBody.getUsername()); if (opUser.isPresent()) { LocalUser user = opUser.get(); if (encryptionService.verifyPassword(loginBody.getPassword(), user.getPassword())) { return jwtService.generateJWT(user); } } return null; } }
WebSecurityConfig类
package com.nea.ecommerceBackend.api.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration public class WebSecurityConfig { @Bean(name = "security") public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ http .csrf((csrf) -> csrf.disable()) .cors(Customizer.withDefaults()) .authorizeHttpRequests((authorize) -> authorize .anyRequest().permitAll() ); return http.build(); } }
问题原因与解决方案
核心问题
异常根源是Spring无法找到${encryption.salt.rounds}的配置值,你没有在配置文件中定义这个属性,@Value注解尝试从Spring环境变量读取对应配置时失败,进而引发依赖注入异常。
解决步骤
添加配置项到配置文件
在src/main/resources目录下找到或新建application.properties,添加:encryption.salt.rounds=10若使用
application.yml则添加:encryption: salt: rounds: 1010是BCrypt常用盐轮次,可根据需求调整(取值范围4-31)。
验证配置文件位置
确保配置文件放在src/main/resources下,这是Spring Boot默认加载配置的路径,不要放错位置。排除其他潜在问题
- 检查
EncryptionService的@Service注解是否正确(代码中已正确添加,包路径也在主应用类扫描范围内,无需额外调整)。 - 若自定义了
@ComponentScan,需确保com.nea.ecommerceBackend.service包被包含,默认情况下Spring Boot会扫描主应用类所在包及其子包,只要主应用类在com.nea.ecommerceBackend下就没问题。
- 检查
额外建议
可以给@Value添加默认值,避免配置缺失导致启动失败:
@Value("${encryption.salt.rounds:10}") public int saltRounds;
这样即使配置文件中没有该属性,也会自动使用默认值10。
内容的提问来源于stack exchange,提问作者entorso
相关产品推荐
相关产品推荐

