ApplicationListener<ContextRefreshedEvent>在App启动时不执行

问题描述 投票:0回答:1

我是编程新手,尝试根据手册制作一个简单的应用程序,实现用户、角色和权限。我使用 Sprint 3.3.3 和 Java 17。

手册建议创建一个 Loader 类,该类将在构建应用程序时填充数据库。因此,无需求助于纯 SQL,就可以创建第一个管理员、创建角色和角色权限。

SetupDataLoader
类实现
ApplicationListener<ContextRefreshedEvent>
接口。该类用 @Component 注释进行标记。我还尝试了 onApplicationEvent 方法来用注释 @EventListener 进行标记。

但是当APP启动时,类中的代码并没有被执行。每次启动后,我都会检查 db 的内容,发现 User 表中没有添加新行。我还尝试从该代码块向控制台输出一条消息 - 它没有输出。

我的应用程序

实体

@Entity
@Table(name = "users")
@Data
public class UserEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Column(name = "login")
    private String login;

    @Column(name = "password")
    private String password;

    @ManyToMany
    @JoinTable(
        name = "users_roles",
        joinColumns = @JoinColumn(
            name = "user_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(
            name = "role_id", referencedColumnName = "id"))
    private Collection<RoleEntity> roles;
    
    public UserEntity() {}
}

@Entity
@Table(name = "roles")
@Data
public class RoleEntity {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany
    @JoinTable(
        name = "roles_privileges", 
        joinColumns = @JoinColumn(
          name = "role_id", referencedColumnName = "id"), 
        inverseJoinColumns = @JoinColumn(
          name = "privilege_id", referencedColumnName = "id"))
    private Collection<PrivilegeEntity> privileges;

    public RoleEntity() {}

    public RoleEntity(final String name) {
        this.name = name;
    }   
}

@Entity
@Table(name = "priveleges")
@Data
public class PrivilegeEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToMany(mappedBy = "privileges")
    private Collection<RoleEntity> roles;

    public PrivilegeEntity() {}

    public PrivilegeEntity(final String name) {
        this.name = name;
    }
}

回购

public interface UserRepo extends CrudRepository<UserEntity, Long> {

    Optional<UserEntity> findByLogin (String login);
    
}

public interface RoleRepo extends CrudRepository<RoleEntity, Long> {

    Optional<RoleEntity> findByName(String name);

}

public interface PrivilegeRepo extends CrudRepository<PrivilegeEntity, Long> {

    Optional<PrivilegeEntity> findByName(String name);

}

顺序设置:

@EnableWebSecurity 
@Configuration
public class SequrityConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(AbstractHttpConfigurer::disable)
            .securityContext((securityContext) -> securityContext.requireExplicitSave(true))
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers(HttpMethod.GET, "/roleHierarchy")
                .hasRole("STAFF"));

        return http.build();
    }
    
    @Bean
    public SecurityExpressionHandler<FilterInvocation> customWebSecurityExpressionHandler() {
        DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
        expressionHandler.setRoleHierarchy(roleHierarchy());
        return expressionHandler;
    }

    @Bean
    public RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        String hierarchy = "ROLE_ADMIN > ROLE_MODER \n ROLE_MODER > ROLE_STAFF";
        roleHierarchy.setHierarchy(hierarchy);
        return roleHierarchy;
    }
    
}

最后

@Component
public class SetupDataLoader implements ApplicationListener<ContextRefreshedEvent> {

    private boolean alreadySetup = false;

    @Autowired
    UserRepo userRepo;

    @Autowired
    RoleRepo roleRepo;

    @Autowired
    PrivilegeRepo privilegeRepo;

    @Autowired
    PasswordEncoder passwordEncoder; 

    // API

    @Override
    @Transactional
    public void onApplicationEvent(final @NonNull ContextRefreshedEvent event) {
        if (alreadySetup) {
            return;
        }

        // == create init privileges
        final PrivilegeEntity readPrivilege = createPrivilege("READ_PRIVILEGE");
        final PrivilegeEntity userWritePrivilege = createPrivilege("USER_WRITE_PRIVILEGE");
        final PrivilegeEntity switchStatePrivilege = createPrivilege("CHANGE_STATE_PRIVILEGE");
        final PrivilegeEntity switchWritePrivilege = createPrivilege("SWITCH_WRITE_PRIVILEGE");
        final PrivilegeEntity commentWritePrivilege = createPrivilege("COMMENT_WRITE_PRIVILEGE");

        // == create init roles;
        final List<PrivilegeEntity> adminPrivileges = new ArrayList<>(Arrays
            .asList(readPrivilege, 
                    userWritePrivilege, 
                    switchStatePrivilege, 
                    switchWritePrivilege, 
                    commentWritePrivilege));

        final List<PrivilegeEntity> moderPrivileges = new ArrayList<>(Arrays
            .asList(readPrivilege, 
                    switchWritePrivilege, 
                    commentWritePrivilege));
                    
        final List<PrivilegeEntity> staffPrivileges = new ArrayList<>(Arrays.asList(readPrivilege));

        final RoleEntity adminRole = createRole("ROLE_ADMIN", adminPrivileges);
        createRole("ROLE_MODER", moderPrivileges);
        createRole("ROLE_STAFF", staffPrivileges);

        // == create init users FIRST ADMIN in db
        createUser("ADMIN", "ADMIN", new ArrayList<>(Arrays.asList(adminRole)));

        alreadySetup = true;
    }

    @Transactional
    public PrivilegeEntity createPrivilege(final String name) {
        Optional<PrivilegeEntity> optPrivilege = privilegeRepo.findByName(name);
        PrivilegeEntity privilege;

        if (optPrivilege.isPresent()) 
            privilege = optPrivilege.get();
        else {
            privilege = new PrivilegeEntity(name);
            privilege = privilegeRepo.save(privilege);
        }

        return privilege;
    }

    @Transactional
    public RoleEntity createRole(final String name, final Collection<PrivilegeEntity> privileges) {
        Optional<RoleEntity> optRole = roleRepo.findByName(name);
        RoleEntity role;

        if (optRole.isPresent()) 
            role = optRole.get();
        else {
            role = new RoleEntity(name);
        }
        role.setPrivileges(privileges);
        role = roleRepo.save(role);
        return role;
    }

    @Transactional
    public UserEntity createUser(final String login, final String password, final Collection<RoleEntity> roles) {
        Optional<UserEntity> optUser = userRepo.findByLogin(login);
        UserEntity user;

        if (optUser.isPresent()) 
            user = optUser.get();
        else {
            user = new UserEntity();
            user.setLogin(login);
            user.setPassword(passwordEncoder.encode(password));
        }
        user.setRoles(roles);
        user = userRepo.save(user);
        return user;
    }
}

我尝试了互联网上的各种解决方案,但每次尝试后我都会检查我的数据库,一切都是一样的:


prototype=# select * from users;
 id | login | password 
----+-------+----------
(0 rows)

请告诉我为什么

SetapDataLoader.java
中的代码没有被执行?

java spring spring-security applicationcontext
1个回答
0
投票

只需将此类添加到您的应用程序中,然后检查日志中是否出现“应用程序就绪”消息即可。

@Component
public class ApplicationReadyEventDemo {

    private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationReadyEventDemo.class);

    @EventListener(ApplicationReadyEvent.class)
    public void onApplicationReady(ApplicationReadyEvent event) {
        LOGGER.info("Application ready");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.