You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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环境变量读取对应配置时失败,进而引发依赖注入异常。

解决步骤

  1. 添加配置项到配置文件
    在src/main/resources目录下找到或新建application.properties,添加:

    encryption.salt.rounds=10
    

    若使用application.yml则添加:

    encryption:
      salt:
        rounds: 10
    

    10是BCrypt常用盐轮次,可根据需求调整(取值范围4-31)。

  2. 验证配置文件位置
    确保配置文件放在src/main/resources下,这是Spring Boot默认加载配置的路径,不要放错位置。

  3. 排除其他潜在问题

    • 检查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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:14:58