iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
Software Development

掌握Java神器,駕馭SpringBoot猛獸系列 第 27

第27日 搭配Spring IoC做Comamnd指令

  • 分享至 

  • xImage
  •  

昨日用會員登入註冊的範例,來說明Spring Security符合驗證規則的路由,如何排除特定請求路徑,並使用AuthenticationManager驗證使用者登入,順便說明了IoC和Bean元件的觀念,今天來用管理者帳號的例子,說明使用@Autowride注入介面,如何解決多個實作類別的問題,以及登入使用者角色

建立admin 資料表

為了方便示範,管理者資料表就與 member相同,只修改資料表名稱

CREATE TABLE `admin` (
	`id` BIGINT(19) NOT NULL AUTO_INCREMENT,
	`account` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
	`password` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
	`name` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8mb4_general_ci',
	PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB;

在資料庫新增管理者帳號

由於 Spring Boot 不像 Laravel 提供項 artisan 這類能在終端機執行的指令,為了方便建立帳號,模仿這個設計實現自定義指令,順便學習自動配置的進階用法

實現流程是建一個Package專門放指令,這裡就叫 com.app.console,並在這個Package下負責呼叫執行指令的類別 MainCommand,這裡要添加@ComponentScan並定義Package,用意是在執行Spring Boot時,可以從特定 Package開始掃描Bean元件時,如果沒有特別設定,會從執行 SpringApplication.run方法的Package開始查找Bean元件

@ComponentScan({ "com.app.console", "com.app.demo" })
@SpringBootApplication
public class MainCommand {

    public static void main(String[] args) {

        try {
            /**
             * 1. 要執行的指令名稱對應Bean名稱
             * 2. 第 0 個參數固定為 指令名稱
            */
            String taskName = args[0];
            ApplicationContext context = SpringApplication.run(MainCommand.class, args);
            Handler handler = (Handler) context.getBean(taskName);

            // 第二個參數即執行指令要使用的參數,
            List<String> handleArgs = Collections.emptyList();
            if (args.length > 1) {
                for (int index = 1; index < args.length; index++) {
                    handleArgs.add(args[index]);
                }
            }

            handler.run(handleArgs);
            System.out.println("執行邏輯處理結束");
        } catch (Exception ex) {
            // 未輸入任務名稱參數或沒有符合的Bean名稱會拋出錯誤,視為無定義指令
            System.out.println("執行異常,檢查執行任務是否已定義");
        }

        System.exit(0);
    }

    @Bean(name = "CreateAdmin")
    public CreateAdmin getHandler() {
        return new CreateAdmin();
    }
}

同層Package定義邏輯實作的類別,類別名稱即為任務名稱,以及通用介面,規範必須實作run方法的實作

// com.app.console.Handler
interface Handler {
    /**
     * @param args command 輸入的參數
     * 
     * @return void 
    */
    public void run(List<String> args);
}

// 指令名稱 CreateAdmin 對應 Bean 名稱
class CreateAdmin implements Handler {
    @Autowired
    private AdminDao adminDao;

    @Autowired
    private PasswordEncoder pwdEncoder;

    public void run(List<String> args) throws Exception {

        // 0跟1為帳號密碼 未輸入表示異常
        String account = args.get(0);
        String password = args.get(1);
        System.out.println("Check Account & Password");
        if (account == null || password == null) {
            throw new Exception("遺失帳號或密碼");
        }

        Admin newAdmin = Admin.builder()
                .account(account)
                .password(pwdEncoder.encode(password))
                .name("管理者")
                .build();

        int result = adminDao.create(newAdmin);
        System.out.printf("Add new admin Success status %d\n", result);
    }
}

調整 pom.xml

由於 專案目錄下會有多個類使用 @SprongBootApplication 註釋,需要指定起始 class
執行 spring-boot:run 指令才不會有異常,作法是在 properties新增 start-class 屬性

	<properties>
		<java.version>17</java.version>
		<start-class>com.app.demo.DemoApplication</start-class>
	</properties>

最後用 mvn 執行Bytecode,指令如下

mvn exec:java -Dexec.mainClass=com.app.console.MainCommand -Dexec.args="CreateAdmin 管理者帳號 密碼"

打開資料庫可以看到,成功建立管理者帳號,完成用終端機操作IoC容器黑魔法


上一篇
第26日 從實務看IoC容器與Bean
下一篇
第28日 來做管理後台登入
系列文
掌握Java神器,駕馭SpringBoot猛獸30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言