回文集目录:JHipster一知半解
概述与模块说明
经过前面对共享模块,布局部分的剖析可以看出JHipster的页面模块划分了,剩余的机构子模块,都只是根据不同的路由,替换掉主页上部分,已完成不同的具体功能。
account目录包含账户管理的功能,有JHipster实现了一套简单而标准的模型,用户可以实现(注册-激活)、(忘记密码-修改)、密码修改、用户信息修改功能。
按照前后端分离的策略,后端仅提供API接口的调用响应,用户界面的展现,逻辑都在前端进行。主题上可以分为API服务调用,路由控制,组件逻辑与展现3个部分。
在看具体的子功能前,先查看AccountModule的部分。
@NgModule({
//引入共享模块,并forChild加载accountState路由
imports: [
JhipsterSampleApplicationNg2SharedModule,
RouterModule.forChild(accountState)
],
//声明内部的组件(相对简单,没有指令)
declarations: [
ActivateComponent,
RegisterComponent,
PasswordComponent,
PasswordStrengthBarComponent,
PasswordResetInitComponent,
PasswordResetFinishComponent,
SettingsComponent
],
//声明内部的服务,都是与后端通讯的封装
providers: [
Register,
ActivateService,
PasswordService,
PasswordResetInitService,
PasswordResetFinishService
],
//已分析过,支持‘-‘命名
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class JhipsterSampleApplicationNg2AccountModule {}
路由配置
每个component组件都需占主体部分,因此path各不相同。
activate.route.ts
export const activateRoute: Route = {
//路径名我active
path: 'activate',
component: ActivateComponent,
data: {
//无需权限
authorities: [],
pageTitle: 'activate.title'
},
//路由守卫为UserRouteAccessService,由于authorities是空数组,始终是允许的。但是守卫会调用principal.identity()从后端获取用户信息。
canActivate: [UserRouteAccessService,]
};
password.route.ts
password-reset-finish.route.ts
password-reset-init.route.ts
settings.route.ts
这几个路由也类似,password和setting增加需要“'ROLE_USER'”权限
register.route.ts
export const registerRoute: Route = {
path: 'register',
component: RegisterComponent,
data: {
authorities: [],
pageTitle: 'register.title'
}
};
可以看到registerRoute并没有声明路由守卫,因为要注册,那么必然没有用户信息,也就无需获取用户信息了。
服务调用
activate.service.ts
@Injectable()
export class ActivateService {
//注入封装过的http客户端
constructor(private http: Http) {}
//设置params,调用通讯API,返回Observable
get(key: string): Observable {
const params: URLSearchParams = new URLSearchParams();
params.set('key', key);
return this.http.get(SERVER_API_URL + 'api/activate', {
search: params
}).map((res: Response) => res);
}
}
password.service.ts
password-reset-finish.service.ts
password-reset-init.service.ts
register.service.ts.ts
代码也类似,十分简单。值得注意的是setting并没单独的service。用户信息保存是AccountService的一部分,直接调用即可。
功能组件
组件都使用模板表单的构造方式,通过在html中定义ngModel进行数据绑定,通过定义内部状态,控制表单的提示信息。以下仅分析register组件源码
register.component.ts
export class RegisterComponent implements OnInit, AfterViewInit {
confirmPassword: string;
doNotMatch: string;
error: string;
errorEmailExists: string;
errorUserExists: string;
registerAccount: any;
success: boolean;
modalRef: NgbModalRef;
//注入语言服务,登录框,注册服务,以及标签本身,绘制器
constructor(
private languageService: JhiLanguageService,
private loginModalService: LoginModalService,
private registerService: Register,
private elementRef: ElementRef,
private renderer: Renderer
) {
}
ngOnInit() {
this.success = false;
this.registerAccount = {};
}
//默认激活login按钮
ngAfterViewInit() {
this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#login'), 'focus', []);
}
register() {
//并非实时判断两个input的匹配程度,提交的时候才会判断,如果不匹配,就提示错误
if (this.registerAccount.password !== this.confirmPassword) {
this.doNotMatch = 'ERROR';
} else {
//两个密码框相符,则进行注册接口调用。
this.doNotMatch = null;
this.error = null;
this.errorUserExists = null;
this.errorEmailExists = null;
this.languageService.getCurrent().then((key) => {
this.registerAccount.langKey = key;
this.registerService.save(this.registerAccount).subscribe(() => {
this.success = true;
}, (response) => this.processError(response));
});
}
}
//通用的登录框显示
openLogin() {
this.modalRef = this.loginModalService.open();
}
//错误的response处理,出错时候返回type表示不同错误
private processError(response) {
this.success = null;
if (response.status === 400 && response.json().type === LOGIN_ALREADY_USED_TYPE) {
this.errorUserExists = 'ERROR';
} else if (response.status === 400 && response.json().type === EMAIL_ALREADY_USED_TYPE) {
this.errorEmailExists = 'ERROR';
} else {
this.error = 'ERROR';
}
}
}
register.component.html
Registration
Registration saved! Please check your email for confirmation.
Registration failed! Please try again later.
Login name already registered! Please choose another one.
Email is already in use! Please choose another one.
The password and its confirmation do not match!
If you want to
sign in, you can try the default accounts:
- Administrator (login="admin" and password="admin")
- User (login="user" and password="user").