Page tree
Skip to end of metadata
Go to start of metadata

Recently Updated


BLOG OSSEZ 博客内容更新

HoneyMoose
HoneyMoose 的清新小站
Travis CI eval ./gradlew assemble 错误
问题 在进行 Travis CI 进行集成编译的时候出现错误。 <-------------> 0% WAITINGThe command "eval ./gradlew assemble " failed. Retrying, 2 of 3. FAILURE: Build failed with an exception. * What went wrong: Task 'assemble' not found in root project 'asciidoc-docs'. * Try: Run gradlew tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 0s <-------------> 0% WAITINGThe command "eval ./gradlew assemble " failed. Retrying, 3 of 3. 具体的错误信息如下: BUILD FAILED in 8s <-------------> 0% WAITINGThe command "eval ./gradlew assemble " failed. Retrying, 2 of 3. FAILURE: Build failed with an exception. * What went wrong: Task 'assemble' not found in root project 'asciidoc-docs'. * Try: Run gradlew tasks to […]
Travis CI Could not find or load main class org.gradle.wrapper.GradleWrapperMain 错误
问题 在 Travis CI 编译的时候出现 Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain 错误。 详细的错误日志为: Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain The command "eval ./gradlew assemble " failed. Retrying, 2 of 3. Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain The command "eval ./gradlew assemble " failed. Retrying, 3 of 3. Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain The command "eval ./gradlew assemble " failed 3 times. The command "./gradlew assemble" failed and exited with 1 during . Your build has been stopped.   解决方法 看看你提交的代码中 gradle 文件夹有没有提交上去。 如果没有提交这个文件夹的话,需要将源代码中的 gradle 提交到代码库上。
HyperSQL 链接参数中文件的路径
如果我们在系统中配置下面的连接参数: spring.datasource.url=jdbc:hsqldb:file:~/db/cwiki-us-jpetstore 我们怎么知道 hsqldb 数据库的存储路径在哪里?   请参考下面的解答: 在 Windows 系统中,如果你登录的用户名为 yhu 的话。 那么这个数据库文件在 :C:\Users\yhu\db 中存储。
Maven 在 pom.xml 文件中配置 repositories 仓库
如果你希望在你的项目中使用独立的 repositories 。 例如,你希望配置使用自己的 https://maven.ossez.com/repository/internal 作为仓库。 例如,修改后的 pom.xml 文件如下: <repositories> <repository> <id>maven-ossez</id> <name>OSSEZ Repository</name> <url>https://maven.ossez.com/repository/internal</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>maven-ossez</id> <name>OSSEZ Repository</name> <url>https://maven.ossez.com/repository/internal</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories>
Flyway Validate failed: Migration checksum mismatch for migration version 1.0.0.01 错误
在运行系统的时候出现错误: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Validate failed: Migration checksum mismatch for migration version 1.0.0.01 -> Applied to database : 1062144176 -> Resolved locally : 1432425380   尝试使用命令: > mvn flyway:migrate 来对校验进行合并  
Angular 服务
英雄指南的 HeroesComponent 目前获取和显示的都是模拟数据。 本节课的重构完成之后,HeroesComponent 变得更精简,并且聚焦于为它的视图提供支持。这也让它更容易使用模拟服务进行单元测试。 如果你希望从 GitHub 上查看我们提供测试的源代码,你可以访问下面的链接:https://github.com/cwiki-us-angular/cwiki-us-angular-tour-of-hero-services 为什么需要服务 组件不应该直接获取或保存数据,它们不应该了解是否在展示假数据。 它们应该聚焦于展示数据,而把数据访问的职责委托给某个服务。 本节课,你将创建一个 HeroService,应用中的所有类都可以使用它来获取英雄列表。 不要使用 new 来创建此服务,而要依靠 Angular 的依赖注入机制把它注入到 HeroesComponent 的构造函数中。 服务是在多个“互相不知道”的类之间共享信息的好办法。 你将创建一个 MessageService,并且把它注入到两个地方: HeroService 中,它会使用该服务发送消息。 MessagesComponent 中,它会显示其中的消息。 创建 HeroService 使用 Angular CLI 创建一个名叫 hero 的服务。 ng generate service hero 该命令会在src/app/hero.service.ts中生成HeroService类的骨架。HeroService类的代码如下: src/app/hero.service.ts (new service) import { Injectable } from '@angular/core'; @Injectable({   providedIn: 'root', }) export class HeroService {   constructor() { } } @Injectable() 服务 注意,这个新的服务导入了 Angular 的 Injectable 符号,并且给这个服务类添加了 @Injectable() 装饰器。 它把这个类标记为依赖注入系统的参与者之一。HeroService 类将会提供一个可注入的服务,并且它还可以拥有自己的待注入的依赖。 目前它还没有依赖,但是很快就会有了。 @Injectable() 装饰器会接受该服务的元数据对象,就像 @Component() 对组件类的作用一样。 获取英雄数据 HeroService 可以从任何地方获取数据:Web 服务、本地存储(LocalStorage)或一个模拟的数据源。 从组件中移除数据访问逻辑,意味着将来任何时候你都可以改变目前的实现方式,而不用改动任何组件。 这些组件不需要了解该服务的内部实现。 这节课中的实现仍然会提供模拟的英雄列表。 导入 Hero 和 HEROES。 import { Hero } from './hero'; import { HEROES } from './mock-heroes'; 添加一个 getHeroes 方法,让它返回模拟的英雄列表。 getHeroes(): Hero[] {   return HEROES; } 提供(provide) HeroService 在要求 Angular 把 HeroService 注入到 HeroesComponent 之前,你必须先把这个服务提供给依赖注入系统。稍后你就要这么做。 你可以通过注册提供商来做到这一点。提供商用来创建和交付服务,在这个例子中,它会对 HeroService 类进行实例化,以提供该服务。 现在,你需要确保 HeroService 已经作为该服务的提供商进行过注册。 你要用一个注入器注册它。注入器就是一个对象,负责在需要时选取和注入该提供商。 默认情况下,Angular CLI 命令 ng generate service 会通过给 @Injectable 装饰器添加元数据的形式,用根注入器将你的服务注册成为提供商。 如果你看看 HeroService 紧前面的 @Injectable() 语句定义,就会发现 providedIn 元数据的值是 ‘root’: @Injectable({   providedIn: 'root', }) @ Injectable ({ providedIn: 'root', }) 当你在顶层提供该服务时,Angular 就会为 HeroService 创建一个单一的、共享的实例,并把它注入到任何想要它的类上。 在 @Injectable 元数据中注册该提供商,还能允许 Angular 通过移除那些完全没有用过的服务来进行优化。 要了解关于提供商的更多知识,参见提供商部分。 要了解关于注入器的更多知识,参见依赖注入指南。 现在 HeroService 已经准备好插入到 HeroesComponent 中了。 这是一个过渡性的代码范例,它将会允许你提供并使用 HeroService。此刻的代码和最终代码相差很大。 修改 HeroesComponent 打开 HeroesComponent 类文件。 删除 HEROES 的导入语句,因为你以后不会再用它了。 转而导入 HeroService。 src/app/heroes/heroes.component.ts (import HeroService) import { HeroService } from '../hero.service'; 把 heroes 属性的定义改为一句简单的声明。 heroes: Hero[]; 注入 HeroService 往构造函数中添加一个私有的 heroService,其类型为 HeroService。 constructor(private heroService: HeroService) { } 这个参数同时做了两件事:1. 声明了一个私有 heroService 属性,2. 把它标记为一个 HeroService 的注入点。 当 Angular 创建 HeroesComponent 时,依赖注入系统就会把这个 heroService 参数设置为 HeroService 的单例对象。 添加 getHeroes() 创建一个函数,以从服务中获取这些英雄数据。 getHeroes(): void {   this.heroes = this.heroService.getHeroes(); } 在 ngOnInit 中调用它 你固然可以在构造函数中调用 getHeroes(),但那不是最佳实践。 让构造函数保持简单,只做初始化操作,比如把构造函数的参数赋值给属性。 构造函数不应该做任何事。 它当然不应该调用某个函数来向远端服务(比如真实的数据服务)发起 HTTP […]
Angular 主从组件
此刻,HeroesComponent 同时显示了英雄列表和所选英雄的详情。 把所有特性都放在同一个组件中,将会使应用“长大”后变得不可维护。 你要把大型组件拆分成小一点的子组件,每个子组件都要集中精力处理某个特定的任务或工作流。 本页面中,你将迈出第一步 —— 把英雄详情移入一个独立的、可复用的 HeroDetailComponent。 HeroesComponent 将仅仅用来表示英雄列表。 HeroDetailComponent 将用来表示所选英雄的详情。 你可以访问下面的链接 https://github.com/cwiki-us-angular/cwiki-us-angular-tour-of-heroes-master-detail 从 GitHub 上查看我们提供源代码。 制作 HeroDetailComponent 使用 Angular CLI 生成一个名叫 hero-detail 的新组件。 ng generate component hero-detail 这个命令会做这些事: 创建一个目录 src/app/hero-detail. 在这个目录中会生成四个文件: 作为组件样式的 CSS 文件。 作为组件模板的 HTML 文件。 存放组件类 HeroDetailComponent 的 TypeScript 文件。 HeroDetailComponent 类的测试文件。 该命令还会把 HeroDetailComponent 添加到 src/app/app.module.ts 文件中 @NgModule 的 declarations 列表中。 编写模板 从 HeroesComponent 模板的底部把表示英雄详情的 HTML 代码剪切粘贴到所生成的 HeroDetailComponent 模板中。 所粘贴的 HTML 引用了 selectedHero。 新的 HeroDetailComponent 可以展示任意英雄,而不仅仅所选的。因此还要把模板中的所有 selectedHero 替换为 hero。 完工之后,HeroDetailComponent 的模板应该是这样的: src/app/hero-detail/hero-detail.component.html <div *ngIf="hero">   <h2>{{hero.name | uppercase}} Details</h2>   <div><span>id: </span>{{hero.id}}</div>   <div>     <label>name:       <input [(ngModel)]="hero.name" placeholder="name"/>     </label>   </div> </div> 添加 @Input() hero 属性 HeroDetailComponent 模板中绑定了组件中的 hero 属性,它的类型是 Hero。 打开 HeroDetailComponent 类文件,并导入 Hero 符号。 src/app/hero-detail/hero-detail.component.ts (import Hero) import { Hero } from '../hero'; hero 属性必须是一个带有 @Input() 装饰器的输入属性,因为外部的 HeroesComponent 组件将会绑定到它。就像这样: <app-hero-detail [hero]="selectedHero"></app-hero-detail> 修改 @angular/core 的导入语句,导入 Input 符号。 src/app/hero-detail/hero-detail.component.ts (import Input) import { Component, OnInit, Input } from '@angular/core'; 添加一个带有 @Input() 装饰器的 hero 属性。 @Input() hero: Hero; 这就是你要对 HeroDetailComponent 类做的唯一一项修改。 没有其它属性,也没有展示逻辑。这个组件所做的只是通过 hero 属性接收一个英雄对象,并显示它。 显示 HeroDetailComponent HeroesComponent 仍然是主从视图。 在你从模板中剪切走代码之前,它自己负责显示英雄的详情。现在它要把这个职责委托给 HeroDetailComponent 了。 这两个组件将会具有父子关系。 当用户从列表中选择了某个英雄时,父组件 HeroesComponent 将通过把要显示的新英雄发送给子组件 HeroDetailComponent,来控制子组件。 你不用修改 HeroesComponent 类,但是要修改它的模板。 修改 HeroesComponent 的模板 HeroDetailComponent 的选择器是 'app-hero-detail'。 把 <app-hero-detail> 添加到 HeroesComponent 模板的底部,以便把英雄详情的视图显示到那里。 把 HeroesComponent.selectedHero 绑定到该元素的 hero 属性,就像这样: heroes.component.html (HeroDetail binding) <app-hero-detail [hero]="selectedHero"></app-hero-detail> [hero]="selectedHero" 是 Angular 的属性绑定语法。 这是一种单向数据绑定。从 HeroesComponent 的 selectedHero 属性绑定到目标元素的 hero 属性,并映射到了 HeroDetailComponent 的 hero 属性。 现在,当用户在列表中点击某个英雄时,selectedHero 就改变了。 当 selectedHero 改变时,属性绑定会修改 HeroDetailComponent 的 hero 属性,HeroDetailComponent 就会显示这个新的英雄。 修改后的 HeroesComponent 的模板是这样的: heroes.component.html <h2>My Heroes</h2> <ul class="heroes">   <li *ngFor="let hero of heroes"     [class.selected]="hero === selectedHero"     (click)="onSelect(hero)">     <span class="badge">{{hero.id}}</span> {{hero.name}}   </li> </ul> <app-hero-detail [hero]="selectedHero"></app-hero-detail> 浏览器刷新,应用又像以前一样开始工作了。 修改了什么? 像以前一样,一旦用户点击了一个英雄的名字,该英雄的详情就显示在了英雄列表下方。 现在,HeroDetailComponent 负责显示那些详情,而不再是 HeroesComponent。 把原来的 HeroesComponent 重构成两个组件带来了一些优点,无论是现在还是未来: 你通过缩减 HeroesComponent 的职责简化了该组件。 你可以把 HeroDetailComponent 改进成一个功能丰富的英雄编辑器,而不用改动父组件 HeroesComponent。 你可以改进 HeroesComponent,而不用改动英雄详情视图。 将来你可以在其它组件的模板中重复使用 HeroDetailComponent。 查看最终代码 你的应用应该变成了这样 在线例子 / 下载范例。本页所提及的代码文件如下: […]
Angular 显示英雄列表
在本页面,你将扩展《英雄指南》应用,让它显示一个英雄列表, 并允许用户选择一个英雄,查看该英雄的详细信息。 创建模拟(mock)英雄数据 你需要一些英雄数据以供显示。 最终,你会从远端的数据服务器获取它。但是目前,你需要创建一些模拟英雄(some mock heroes),并假设这些数据是从远程服务器上获取的。 在 src/app/ 文件夹中创建一个名叫 mock-heroes.ts 的文件。 定义一个包含十个英雄的常量数组 HEROES,并导出它。 该文件是这样的。 src/app/mock-heroes.ts import { Hero } from './hero'; export const HEROES: Hero[] = [   { id: 11, name: 'Mr. Nice' },   { id: 12, name: 'Narco' },   { id: 13, name: 'Bombasto' },   { id: 14, name: 'Celeritas' },   { id: 15, name: 'Magneta' },   { id: 16, name: 'RubberMan' },   { id: 17, name: 'Dynama' },   { id: 18, name: 'Dr IQ' },   { id: 19, name: 'Magma' },   { id: 20, name: 'Tornado' } ]; 显示英雄 你要在 HeroesComponent 的顶部显示这个英雄列表。 打开 HeroesComponent 类文件,并导入模拟的 HEROES 数据。 src/app/heroes/heroes.component.ts import { HEROES } from '../mock-heroes'; 往类中添加一个 heroes 属性,这样可以暴露出这些英雄,以供绑定。 src/app/heroes/heroes.component.ts export class HeroesComponent implements OnInit {   heroes = HEROES; 使用 *ngFor 列出这些英雄 打开 HeroesComponent 的模板文件,并做如下修改: 在顶部添加 <h2> 然后添加表示无序列表的 HTML 元素(<ul>) 在 <ul> 中插入一个 <li> 元素,以显示单个 hero 的属性。 点缀上一些 CSS 类(稍后你还会添加更多 CSS 样式)。 完成后应该如下显示: heroes.component.html heroes.component.html (heroes template) content_copy <h2>My Heroes</h2> <ul class="heroes">   <li>     <span class="badge">{{hero.id}}</span> {{hero.name}}   </li> </ul> 现在,把 <li> 修改成这样: <li *ngFor="let hero of heroes"> *ngFor 是一个 Angular 的复写器(repeater)指令。 它会为列表中的每项数据复写它的宿主元素。 在这个例子中 <li> 就是 *ngFor 的宿主元素 heroes 就是来自 HeroesComponent 类的列表。 当依次遍历这个列表时,hero 会为每个迭代保存当前的英雄对象。 不要忘了 ngFor 前面的星号(*),它是该语法中的关键部分。 浏览器刷新之后,英雄列表出现了。 给英雄们应用样式表 英雄列表应该富有吸引力,并且当用户把鼠标移到某个英雄上和从列表中选中某个英雄时,应该给出视觉反馈。 在教程的第一章,你曾在 styles.css 中为整个应用设置了一些基础的样式。 但那个样式表并不包含英雄列表所需的样式。 固然,你可以把更多样式加入到 styles.css,并且放任它随着你添加更多组件而不断膨胀。 但还有更好的方式。你可以定义属于特定组件的私有样式,并且让组件所需的一切(代码、HTML 和 CSS)都放在一起。 这种方式让你在其它地方复用该组件更加容易,并且即使全局样式和这里不一样,组件也仍然具有期望的外观。 你可以用多种方式定义私有样式,或者内联在 @Component.styles 数组中,或者在 @Component.styleUrls 所指出的样式表文件中。 当 CLI 生成 HeroesComponent 时,它也同时为 HeroesComponent 创建了空白的 heroes.component.css 样式表文件,并且让 @Component.styleUrls 指向它,就像这样: src/app/heroes/heroes.component.ts @Component({   selector: 'app-heroes',   templateUrl: './heroes.component.html',   styleUrls: ['./heroes.component.css'] }) 打开 heroes.component.css 文件,并且把 HeroesComponent 的私有 CSS 样式粘贴进去。 你可以在本指南底部的查看最终代码中找到它们。 @Component 元数据中指定的样式和样式表都是局限于该组件的。 heroes.component.css 中的样式只会作用于 HeroesComponent,既不会影响到组件外的 HTML,也不会影响到其它组件中的 HTML。 主从结构 当用户在主列表中点击一个英雄时,该组件应该在页面底部显示所选英雄的详情。 在本节,你将监听英雄条目的点击事件,并更新英雄的详情。 添加 click 事件绑定 […]
Angular 英雄编辑器
应用程序现在有了基本的标题。 接下来你要创建一个新的组件来显示英雄信息并且把这个组件放到应用程序的外壳里去。 创建英雄组件 使用 Angular CLI 创建一个名为 heroes 的新组件。 ng generate component heroes CLI 创建了一个新的文件夹, src/app/heroes/,并生成了 HeroesComponent 的 4 个文件。 HeroesComponent 的类文件如下: heroes.component.ts import { Component, OnInit } from '@angular/core'; @Component({   selector: 'app-heroes',   templateUrl: './heroes.component.html',   styleUrls: ['./heroes.component.css'] }) export class HeroesComponent implements OnInit {   constructor() { }   ngOnInit() {   } } 你要从 Angular 核心库中导入  Component  符号,并为组件类加上 @ Component  注解。 @Component 是一个修饰器函数,这个函数为组件指定了 Angular 元数据。 CLI 自动生成了三个元数据属性: selector — 组件的 CSS 元素选择器。 templateUrl — 组件模板文件的位置。 styleUrls — 组件私有 CSS 样式表文件的位置。 CSS 元素选择器 app-heroes 用来在父组件的模板中匹配 HTML 元素的名称,以识别出该组件。 ngOnInit 是一个生命周期钩子(lifecycle hook),Angular 在创建完组件后很快就会调用 ngOnInit。这里是放置初始化逻辑的好地方。 始终要 export 这个组件类,以便于在其它地方(比如 AppModule)导入它。 添加一个 hero 属性 往 HeroesComponent 中添加一个 hero 属性,用来表示一个名叫 “Windstorm” 的英雄。 hero = 'Windstorm'; 显示英雄 打开模板文件 heroes.component.html。删除 Angular CLI 自动生成的默认内容,改为到 hero 属性的数据绑定。 heroes.component.html {{hero}} 显示 HeroesComponent 视图 要显示 HeroesComponent 你必须把它加到壳组件 AppComponent 的模板中。 别忘了,app-heroes 就是 HeroesComponent 的 元素选择器(element selector)。 所以,只要把 <app-heroes> 元素添加到 AppComponent 的模板文件(app.component.html)中就可以了,就放在标题下方。 app.component.html <h1>{{title}}</h1> <app-heroes></app-heroes> 如果 CLI 的 ng serve 命令仍在运行,浏览器就会自动刷新,并且同时显示出应用的标题和英雄的名字。 创建一个 Hero 类 真实的英雄当然不仅仅只有一个名字。 在 src/app 文件夹中为 Hero 类创建一个文件,并添加 id 和 name 属性。 src/app/hero.ts export class Hero {   id: number;   name: string; } 回到 HeroesComponent 类,并且导入这个 Hero 类。 把组件的 hero 属性的类型重构为 Hero。 然后以 1 为 id、以 “Windstorm” 为名字初始化它。 修改后的 HeroesComponent 类应该是这样的: src/app/heroes/heroes.component.ts import {Component, OnInit} from '@angular/core'; import {Hero} from '../hero'; @Component({   selector: 'app-heroes',   templateUrl: './heroes.component.html',   styleUrls: ['./heroes.component.css'] }) export class HeroesComponent implements OnInit {   hero: Hero = {     id: 1,     name: 'Windstorm'   };   constructor() {   }   ngOnInit() {   } } 页面显示变得不正常了,因为你刚刚把 hero 从字符串改成了对象。 显示 hero 对象 […]
Angular 英雄示例教程
英雄指南教程(Tour of Heroes)涵盖了 Angular 的基本知识。 在本教程中,你将构建一个应用,来帮助人事代理机构来管理一群英雄。 这个入门级 app 包含很多数据驱动的应用所需的特性。 它需要获取并显示英雄的列表、编辑所选英雄的详情,并且在包含有英雄数据的不同视图之间进行导航。 在本教程的最后,你的应用可以做下面的工作: 使用Angular 的内置指令(Angular directives)来显示 / 隐藏元素,并显示英雄数据的列表。 创建 Angular 组件(Angular components)以显示英雄的详情,并显示一个英雄数组。 为只读数据使用单向数据绑定。 添加可编辑字段,使用双向数据绑定来更新模型。 为用户事件绑定组件方法(component methods),比如相应用户键盘输入和点击。 让用户可以在主列表中选择一个英雄,然后在详情视图中编辑他。 使用管道来格式化数据。 创建共享的服务来管理这些英雄。 使用路由在不同的视图及其组件之间导航。 你将学到足够的 Angular 知识和足够的信心来让 Angular 提供你所需的支持。 完成本教程的所有步骤之后,最终的应用会是这样的:live example / download example。 你将要构建什么 下面是本教程有关界面的构想:本应用开始界面为”Dashboard(主面板)”视图,在这个视图中显示最勇敢的英雄。 你可以单击主面板上的两个链接(”Dashboard” 和 “Heroes”)来在主面板视图和英雄视图之间进行导航。 如果你在主面板中单击英雄名称 “Magneta” 时,路由将会打开 “Hero Details(英雄详细)”页面。在这个页面中,你可以对英雄的名字进行修改。 单击 “Back(返回按钮)”,应用将会让你返回到 Dashboard(主面板)页面中。顶部的链接能够让你在任何时候都能够返回到主页面。如果你单击  “Heroes(英雄列表)”,引用将会将英雄以列表显示。 当你单击不同英雄的名字的时候,一个只读的“微型详情视图”会在列表的下方显示,以体现你的选择。 你可以点击 “View Details(查看详情)” 按钮进入所选英雄的编辑视图。 下面这张图汇总了所有可能的导航选项。 下面是本应用的动态展示:   https://www.cwiki.us/display/AngularZH/Tutorial


  • No labels