JHipster一知半解- 4.6.10 webapp-account目录

回文集目录:JHipster一知半解

概述与模块说明

经过前面对共享模块,布局部分的剖析可以看出JHipster的页面模块划分了,剩余的机构子模块,都只是根据不同的路由,替换掉主页上<outlet>部分,已完成不同的具体功能。  
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<any> {
        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

<div>
    <div class="row justify-content-center">
        <div class="col-md-8">
            <h1 jhiTranslate="register.title">Registration</h1>
            <!-- 成功提示,仅当注册成功时显示 -->
            <div class="alert alert-success" *ngIf="success" jhiTranslate="register.messages.success">
                <strong>Registration saved!</strong> Please check your email for confirmation.
            </div>
            <!-- 失败提示,仅当注册失败时显示 -->
            <div class="alert alert-danger" *ngIf="error" jhiTranslate="register.messages.error.fail">
                <strong>Registration failed!</strong> Please try again later.
            </div>
            <!-- 失败提示,仅当注册失败,且服务器返回用户已存在时显示 -->
            <div class="alert alert-danger" *ngIf="errorUserExists" jhiTranslate="register.messages.error.userexists">
                <strong>Login name already registered!</strong> Please choose another one.
            </div>
            <!-- 失败提示,仅当注册失败,且服务器返回注册Email已存在时显示 -->
            <div class="alert alert-danger" *ngIf="errorEmailExists" jhiTranslate="register.messages.error.emailexists">
                <strong>Email is already in use!</strong> Please choose another one.
            </div>
            <!-- 失败提示,仅当两个密码输入框不符时显示 -->
            <div class="alert alert-danger" *ngIf="doNotMatch" jhiTranslate="global.messages.error.dontmatch">
                The password and its confirmation do not match!
            </div>
        </div>
    </div>
    <div class="row justify-content-center">
        <div class="col-md-8">
            <!-- 窗体form定义,提交方法为register,如果注册成功,就不显示了 -->
            <form name="form" role="form" (ngSubmit)="register()" #registerForm="ngForm" *ngIf="!success">
                <div class="form-group">
                    <label class="form-control-label" for="login" jhiTranslate="global.form.username">Username</label>
                    <!-- 标准的模板方式生成窗体方式,使用ngModel绑定值到login,后面定义了一系列angular的验证器 -->
                    <input type="text" class="form-control" [(ngModel)]="registerAccount.login" id="login" name="login" #login="ngModel" placeholder="{{'global.form.username.placeholder' | translate}}" required minlength="1" maxlength="50" pattern="^[_'.@A-Za-z0-9-]*$">
                    <!-- 统一的错误提示div,包含多个small提示,根据不同的错误类型,有不同的提示 -->
                    <div *ngIf="login.dirty && login.invalid">
                        <small class="form-text text-danger" *ngIf="login.errors.required" jhiTranslate="register.messages.validate.login.required">
                            Your username is required.
                        </small>
                        <small class="form-text text-danger" *ngIf="login.errors.minlength" jhiTranslate="register.messages.validate.login.minlength">
                            Your username is required to be at least 1 character.
                        </small>
                        <small class="form-text text-danger" *ngIf="login.errors.maxlength" jhiTranslate="register.messages.validate.login.maxlength">
                            Your username cannot be longer than 50 characters.
                        </small>
                        <small class="form-text text-danger" *ngIf="login.errors.pattern" jhiTranslate="register.messages.validate.login.pattern">
                            Your username can only contain lower-case letters and digits.
                        </small>
                    </div>
                </div>
                <!-- 省略email,密码,确认密码框 -->
                
                <!-- 如果窗体不合法,就disable提交按钮 -->
                <button type="submit" [disabled]="registerForm.form.invalid" class="btn btn-primary" jhiTranslate="register.form.button">Register</button>
            </form>
            <p></p>
            <!-- 窗体之外,增加默认用户的说明 -->
            <div class="alert alert-warning">
                <span jhiTranslate="global.messages.info.authenticated.prefix">If you want to </span>
                <a class="alert-link" (click)="openLogin()" jhiTranslate="global.messages.info.authenticated.link">sign in</a><span jhiTranslate="global.messages.info.authenticated.suffix">, you can try the default accounts:<br/>- Administrator (login="admin" and password="admin") <br/>- User (login="user" and password="user").</span>
            </div>
        </div>
    </div>
</div>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容