AdminService + AdminServiceImpl
AdminController
作为后端学习项目,源码阅读先从项目的Service层和Controller层着手,搞清楚项目的业务逻辑。
一、Service层 & Controller层
1. Service层:
- Service层主要负责业务模块的逻辑应用设计。同样是首先设计接口,再设计其实现的类,接着再Spring的配置文件中配置其实现的关联。这样我们就可以在应用中调用Service接口来进行业务处理。
- Service层的业务实现,具体要调用到已定义的DAO层的接口(数据库操作),封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。
2. Controller层
- Controller层负责具体的业务模块流程的控制,在此层里面要调用Serice层的接口来控制业务流程,控制的配置也同样是在Spring的配置文件里面进行
- 针对具体的业务流程,会有不同的控制器,我们具体的设计过程中可以将流程进行抽象归纳,设计出可以重复利用的子单元流程模块,这样不仅使程序结构变得清晰,也大大减少了代码量。
由Service层和Controller层的概念可知,Service层主要负责确定服务逻辑(抽象),具体的实现流程下放到Controller层中实现。在项目中这两层的接口/对象往往是一一对应的,所以选择将其放在一起阅读。
二、Service层
Service层目录下还有Service接口对应的具体实现类,放在子目录impl中,直接跟Service层源码一起分析。
1. AdminService
(1)变量设置
int ACCESS_TOKEN_EXPIRED_SECONDS = 24 * 3600; // 访问令牌过期时间(秒)
int REFRESH_TOKEN_EXPIRED_DAYS = 30; // 刷新令牌过期时间(天)
String LOG_PATH = "logs/spring.log"; // 日志路径
(2)方法功能
@NonNull
User authenticate(@NonNull LoginParam loginParam); // 验证用户名、密码
@NonNull
AuthToken authCodeCheck(@NonNull LoginParam loginParam); // 验证authCode,创建相应的auth令牌验证authCode,创建相应的auth令牌
void clearToken(); // 清除验证信息
void sendResetPasswordCode(@NonNull ResetPasswordParam param); // 重置密码,会发送邮件到注册邮箱(包含一个Code)
void resetPasswordByCode(@NonNull ResetPasswordParam param); // 通过上述Code重置密码
@NonNull
EnvironmentDTO getEnvironments(); // 获取系统环境(DTO层)
@NonNull
AuthToken refreshToken(@NonNull String refreshToken); // 刷新身份令牌
String getLogFiles(@NonNull Long lines); // 获取日志内容
LoginPreCheckDTO getUserEnv(@NonNull String username); // 获取用户登录环境,重新检测登录后环境的DTO
2.AdminServiceImpl
(1) 变量设置
- 在AdminServiceImpl实现类中设计到了许多其他Service中的方法,具体如下。是因为在AdminServiceImpl中还需要实现其他接口定义的业务逻辑,所以引入这些接口。
private final OptionService optionService;
private final UserService userService;
private final MailService mailService;
private final AbstractStringCacheStore cacheStore;
private final HaloProperties haloProperties;
private final ApplicationEventPublisher eventPublisher;
- AdminServiceImpl的构造函数为有参构造,下列变量参数全部传入,对下列所有变量进行初始化赋值。
public AdminServiceImpl(
OptionService optionService,
UserService userService,
MailService mailService,
AbstractStringCacheStore cacheStore,
HaloProperties haloProperties,
ApplicationEventPublisher eventPublisher) {
this.optionService = optionService;
this.userService = userService;
this.mailService = mailService;
this.cacheStore = cacheStore;
this.haloProperties = haloProperties;
this.eventPublisher = eventPublisher;
}
(2) 具体方法:
① User authenticate(@NonNull LoginParam loginParam)
- 继承自AdminService接口;
- 主要功能:
- 为从loginParam变量中获取用户名和密码,并且进行各种判断(如果变量不合法,则写入日志/抛出异常);
- 否则将loginParam中的合法变量封装成user对象返回。
@Override
@NonNull
public User authenticate(@NonNull LoginParam loginParam) {
... // 省略不重要代码
final User user;
try {
user = Validator.isEmail(username) // 获取用户:通过用户名/通过Email
? userService.getByEmailOfNonNull(username) :
userService.getByUsernameOfNonNull(username);
} catch (NotFoundException e) { // 如果找不到用户,日志记录错误且event输出登录失败
log.error("Failed to find user by name: " + username);
eventPublisher.publishEvent(
new LogEvent(this, loginParam.getUsername(), LogType.LOGIN_FAILED,
loginParam.getUsername()));
throw new BadRequestException(mismatchTip);
}
userService.mustNotExpire(user); // 用户是否过期
if (!userService.passwordMatch(user, loginParam.getPassword())) { // 密码是否匹配
eventPublisher.publishEvent(
new LogEvent(this, loginParam.getUsername(), LogType.LOGIN_FAILED,
loginParam.getUsername()));
throw new BadRequestException(mismatchTip);
}
return user; // 返回唯一user
}
② AuthToken authCodeCheck(@NonNull LoginParam loginParam)
- 继承自AdminService接口;
- 主要功能:
- 通过①方法获取用户user,然后在user/loginParam中获取两部验证码,并且验证。
- 检查是否重复登录
③ void clearToken()
- 继承自AdminService接口;
- 主要功能:用户注销功能的实现。(进行了一些特殊情况的)
④ void sendResetPasswordCode(ResetPasswordParam param)
- 继承自AdminService接口;
- 主要功能:
- 判断验证码是否已经存在缓存中,从而判断是否重复获取验证码。如果是第一次获取则继续,如果不是则抛出异常
- 通过邮箱/用户名+验证码的方式进行验证
- 产生验证码,并且将验证码放入缓存中,设置过期时间为5min
- 判断是否启动STMP服务,若未启用,抛出异常
- 若一切正常,发送密码更改邮件 + (密码更改)验证码
⑤ void resetPasswordByCode(ResetPasswordParam param)
- 继承自AdminService接口;
- 主要功能:判断(密码更改)验证码是否匹配,从而确定是否更改密码。
⑥ EnvironmentDTO getEnvironments()
- 继承自AdminService接口;
- 主要功能:进行一些环境的设置(数据库,Halo版本等)
⑦ AuthToken refreshToken(@NonNull String refreshToken)
- 继承自AdminService接口;
- 主要功能:刷新身份验证。通过user对象,在缓存中查找,将旧身份验证信息删除。并且返回新的身份验证令牌。
⑧ AuthToken buildAuthToken(@NonNull User user)
- 实现类自身方法
- 主要功能:通过user对象生成新的身份验证令牌。并且将新身份令牌存入缓存中。
三、 Controller层
1. AdminController ("/api/admin")
(1) 调用的Service层:
- 主要调用了AdminService和OptionalService,有参构造传入参数
private final AdminService adminService;
private final OptionService optionService;
public AdminController(AdminService adminService, OptionService optionService) {
this.adminService = adminService;
this.optionService = optionService;
}
(2) 主要功能:
① boolean isInstall()
- 判断是否登录
- “/is_installed”
② LoginPreCheckDTO authPreCheck(@RequestBody @Valid LoginParam loginParam)
- 二次验证码验证
- “login/precheck”
③ AuthToken auth(@RequestBody @Valid LoginParam loginParam)
- 通过loginParam获取用户令牌并且返回
- “login”
④ void logout()
- 注销账户
- “logout”
⑤ void sendResetCode(@RequestBody @Valid ResetPasswordParam param)
- 发送重置密码验证码
- “password/code”
⑥ void resetPassword(@RequestBody @Valid ResetPasswordParam param)
- 重置密码
- “password/reset”
四、总结
- Admin相关的主要功能:管理注册和登录功能
- 对用户状态的判断(注册/非注册,登录/非登录)
- 用户密码更改(邮件验证)
- 登录/登出
- Controller层中实现的方法就是简单的调用Service接口中的方法;而传入Service接口的时候,往往传入的是ServiceImpl的实现类,这种结构能够对程序实现解耦。
- 在今天的源码阅读过程中,需要加强认知的几个对象
- LoginParam
- User
- OptionalService
- AuthToken