SpringBoot釋出事件,監聽事件
阿新 • • 發佈:2021-10-20
SpringBoot釋出事件,監聽事件
業務型別:像傳送郵箱,記錄登入日誌這種,程式可以不等待它們完成之後再返回響應。
- ApplicationEventPublisher 事件釋出介面
- @Async:非同步註解 可以加上執行緒池的名字
- @EventListener:監聽事件註解,加上此註解的方法才能監聽
這裡以記錄日誌為例
1.定義日誌實體類
/** * 賬戶登入日誌實體類 * * @author * @date */ @Data @Builder @AllArgsConstructor @NoArgsConstructor public class AccountLoginLog implements Serializable { private Long id; /** * 賬號id */ private Long accountId; /** * 賬號名稱 */ private String accountName; /** * 手機號 */ private String accountMobile; /** * 單位名稱 */ private String departmentName; /** * ip地址 */ private String ip; /** * ip地址所在區域省 */ private String ipProvince; /** * ip地址所在區域市 */ private String ipCity; /** * 1登入/2登出 */ private Integer type; /** * 成功/失敗 */ private Boolean success; /** * 說明 */ private String memo; /** * 建立時間 */ private Date createdAt; /** * 修改時間 */ private Date updatedAt; /** * 登入日誌型別列舉 * * @author * @date */ @Getter @AllArgsConstructor(access = AccessLevel.PRIVATE) public enum Type { /** * 登入 */ LOGIN(1, "登入"), /** * 退出 */ LOGOUT(2, "登出"); private Integer code; private String value; public static String getName(int code) { Optional<Type> find = Arrays.stream(values()).filter(c -> Objects.equals(c.getCode(), code)).findFirst(); return find.map(Type::getValue).orElse(null); } public static boolean isCodeLegal(int code) { Optional<?> find = Arrays.stream(values()).filter(c -> Objects.equals(c.getCode(), code)).findFirst(); return find.isPresent(); } } }
2.將實體類再次進行封裝一層
沒有很複雜的邏輯可以不用
/**
* 登入日誌記錄
*
* @author
* @date
*/
@Data
@Builder
public class LoginLogEvent implements Serializable {
/**
* 登入日誌
*/
private AccountLoginLog accountLoginLog;
}
3.定義事件釋出器
/** * 登入日誌記錄事件釋出 * * @author * @date */ @Component public class LoginLogEventPublisher { @Autowired private ApplicationEventPublisher applicationEventPublisher; @Autowired private DepartmentManager departmentManager; /** * 釋出登入成功日誌 * * @param account 當前登入使用者 * @param ipRegion IP * @param memo 說明 */ public void publishLoginSuccessLog(Account account, IPRegion ipRegion, String memo) { publishEvent(account.getId(), account.getName(), account.getMobile(), getDepartmentName(account.getDepartmentId()), ipRegion, AccountLoginLog.Type.LOGIN.getCode(), true, memo); } /** * 釋出登入失敗日誌 * * @param account 當前登入使用者 * @param ipRegion IP * @param memo 說明 */ public void publishLoginFailLog(Account account, IPRegion ipRegion, String memo) { publishEvent(account.getId(), account.getName(), account.getMobile(), getDepartmentName(account.getDepartmentId()), ipRegion, AccountLoginLog.Type.LOGIN.getCode(), false, memo); } /** * 釋出登出(退出登入)日誌 * * @param account 登入使用者 * @param ipRegion IP * @param memo 說明 */ public void publishLogout(Account account, IPRegion ipRegion, String memo) { publishEvent(account.getId(), account.getName(), account.getMobile(), getDepartmentName(account.getDepartmentId()), ipRegion, AccountLoginLog.Type.LOGOUT.getCode(), true, memo); } /** * 釋出登入事件 * * @param accountId 使用者ID * @param accountName 使用者姓名 * @param accountMobile 手機號 * @param departmentName 單位部門 * @param ipRegion IP * @param type 型別 * @param success 成功失敗 * @param memo 說明 */ private void publishEvent(Long accountId, String accountName, String accountMobile, String departmentName, IPRegion ipRegion, int type, boolean success, String memo) { LoginLogEvent loginLogEvent = LoginLogEvent.builder() .accountLoginLog(AccountLoginLog.builder() .accountId(accountId).accountName(accountName) .accountMobile(accountMobile).departmentName(departmentName) .ip(ipRegion.getIp()).ipProvince(ipRegion.getProvince()).ipCity(ipRegion.getCity()) .type(type).success(success).memo(memo) .build()) .build(); applicationEventPublisher.publishEvent(loginLogEvent); } /** * 部門名稱 */ private String getDepartmentName(Long departmentId) { if (departmentId != null) { Department department = departmentManager.findOne(departmentId); return department != null ? department.getName() : null; } else { return null; } } }
4.定義事件處理器
/** * 操作日誌記錄 * * @author * @date */ @Component public class LoginLogEventProcessor { @Autowired private AccountLoginLogManager accountLoginLogManager; @Async @EventListener public void handleLoginLogEvent(LoginLogEvent loginLogEvent) { //記錄日誌 accountLoginLogManager.log(loginLogEvent.getAccountLoginLog()); } }
accountLoginLogManager為service提供者,提供處理日誌方法,這裡呼叫log方法將登入日誌儲存在mysql中以及es中,具體業務程式碼不再展示。