從用戶界面到數據庫的Angular自動填充

一位開發人員展示了他為Angular和Spring Boot編寫的大量代碼,他用它創建了一個完整的堆棧Web應用程序。

該MovieManager項目用於管理我的電影的收集和使用角度和Spring啟動PostgreSQL的做到這一點。

該項目用於演示如何為電影標題構建自動完成搜索框。自動完成框在前端使用Bootstrap 4,在後端使用PostgreSQL的Spring Boot。重點在於如何將本地Angular / RxJS與Spring Boot以及關係數據庫一起使用。

從用戶界面到數據庫的Angular自動填充

前端

前端使用Angular與RxJS和Bootstrap 4進行造型。Angular和RxJS具有創建輸入並將其連接到後端REST服務的功能。

然後,在每次擊鍵之後,服務的結果將在輸入下方的div中顯示和更新。Bootstrap提供CSS類來設置組件的樣式。

前端有三部分:

  1. 帶輸入標籤和輸出div的div模板。

  2. 具有表單控件的組件類,用於將輸入標記與服務方法相連接。

  3. 向服務器發出REST請求的服務類。

在搜索組件中,我使用了以下 模板:

...

Searchfor Movie Title

Loading

...

第1-2行創建一個可變寬度和一行的Bootstrap容器。

第4行為自動填充功能創建引導列。

第5-8行創建一個輸入組,它用一個標籤顯示樣式化輸入,並將Angular form控件鏈接movieTitle 到輸入。

如果在輸入中輸入了某些內容,第9行將創建結果div。

如果服務從服務器檢索電影,則第10行顯示文本“加載”。

第11行顯示了從服務器加載的電影的路由器鏈接。這 routerLink 是電影組件與電影ID的路由。 *ngFor 對服務器發送的電影進行迭代,並且 async 意味著電影是在到達時顯示其數據的觀察者。鏈接的文本是電影標題。

在搜索組件中,我使用了以下類:

@Component({

selector: 'app-search',

templateUrl: './search.component.html',

styleUrls: ['./search.component.scss']

})

export class SearchComponent implements OnInit {

generes: Genere[];

movieTitle = new FormControl();

movies: Observable;

movieActor = new FormControl();

actors: Observable;

importMovies: Movie[] = [];

importMovieTitle = new FormControl();

actorsLoading = false;

moviesLoading = false;

importMoviesLoading = false;

showMenu = false;

moviesByGenere: Movie[] = [];

moviesByGenLoading = false;

constructor(private actorService: ActorsService, private movieService: MoviesService, private userService: UsersService) { }

ngOnInit() {

this.actors = this.movieActor.valueChanges

.debounceTime(400)

.distinctUntilChanged()

.do(() => this.actorsLoading = true)

.switchMap(name => this.actorService.findActorByName(name))

.do(() => this.actorsLoading = false);

this.movies = this.movieTitle.valueChanges

.debounceTime(400)

.distinctUntilChanged()

.do(() => this.moviesLoading = true)

.switchMap(title => this.movieService.findMovieByTitle(title))

.do(() => this.moviesLoading = false);

this.userService.allGeneres().subscribe(res => this.generes = res);

}

第1-6行使用註釋和OnInit 界面創建搜索組件。

第9行為movieTitle 用戶輸入創建 表單控件。

第16行創建 moviesLoading 布爾值來顯示加載文本。

第31行將movieTitle 表單控件與 valueChanges observable和Observable結果鏈接起來movies。

第32-33行在請求到後端之間添加了400 ms的超時時間,並且只在輸入發生更改時才發送請求。

第34行設置顯示模板中加載文本的布爾值。

第35行用於 switchMap 丟棄正在運行的請求並向服務發送新的請求。

第36行設置將加載文本設置為false的布爾值。

這是管理所有電影數據的電影服務:

@Injectable()

export class MoviesService {

private _reqOptionsArgs = { headers: new HttpHeaders().set( 'Content-Type', 'application/json' ) };

constructor(private http: HttpClient) { }

...

public findMovieByTitle(title: string) :Observable {

if(!title) {

return Observable.of([]);

}

return this.http.get('/rest/movie/'+title, this._reqOptionsArgs).catch(error => {

console.error( JSON.stringify( error ) );

return Observable.throw( error );

});

}

...

}

第1-2行MoviesService 用註釋創建。

第3行創建HTTP頭。

第5行是獲取注入的HttpClient的構造函數。

Observable 如果標題為空,則第10-12行將返回 空白。

第13-16行將HTTP請求發送到服務器,捕獲服務器錯誤,記錄它們並引發錯誤。

後端

後端在Spring Boot中使用JPA和PostgreSQL完成。它使用Spring Boot功能為REST界面和服務提供服務,以管理存儲庫並圍繞服務調用創建事務。這些事務需要支持MovieManager中的電影功能的導入和刪除。

存儲庫使用JPA創建一個查詢,查找包含(區分大小寫)用戶輸入的標題字符串的用戶電影的電影標題。

REST服務是在這個類中創建的:

@RestController

@RequestMapping("rest/movie")

public class MovieController {

@Autowired

private MovieManagerService service;

...

@RequestMapping(value="/{title}", method=RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

public ResponseEntity> getMovieSearch(@PathVariable("title") String titleStr) throws InterruptedException {

List movies = this.service.findMovie(titleStr);

return new ResponseEntity>(movies, HttpStatus.OK);

}

...

}

第5-6行注入了MovieManagerService。它管理事務,並且是電影數據的公共服務。

第10-11行設置了RequestMapping並獲得請求字符串的標題值。

第12行從這個標題字符串的MovieManagerService讀取電影列表。

第13行將電影列表包裝在ResponseEntity中並返回它。

主要的電影服務是在這個類中創建的:

@Transactional

@Service

public class MovieManagerService {

@Autowired

private CrudMovieRepository crudMovieRep;

@Autowired

private CrudCastRepository crudCastRep;

@Autowired

private CrudActorRepository crudActorRep;

@Autowired

private CrudGenereRepository crudGenereRep;

@Autowired

private CrudUserRepository crudUserRep;

@Autowired

private CustomRepository customRep;

@Autowired

private AppUserDetailsService auds;

...

public List findMovie(String title) {

List result = this.customRep.findByTitle(title).stream()

.map(m -> Converter.convert(m)).collect(Collectors.toList());

return result;

}

...

}

第14-15行獲得 CustomRepository 注入。這是所有非CRUD DB請求的回購。

第23-24行將Movie Dtos中的Movie實體列表轉換為可以由該序列化 RestController 並返回Dto列表。

自定義庫在此創建類:

@Repository

public class CustomRepository {

@PersistenceContext

private EntityManager em;

@Autowired

private CrudUserRepository crudUserRep;

...

public List findByTitle(String title) {

User user = getCurrentUser();

List results = em.createQuery("select e from Movie e join e.users u where e.title like :title and u.id = :userid", Movie.class).setParameter("title", "%"+title+"%").setParameter("userid", user.getId()).getResultList();

return results;

}

...

}

第3-4行獲得注入Jpa的EntitiyManager。

第5-6行獲取注入的CrudUserRepository以訪問當前登錄的用戶。多用戶支持需要當前用戶。

第12-13行向EntityManager查詢電影標題包含標題字符串和當前用戶是電影所有者的電影。為此,電影和用戶實體需要被連接,然後通過電影標題和userId進行過濾。然後返回結果。

概要

Angular和RxJ具有在幾行代碼中創建自動完成的功能。諸如擊鍵之間的超時,沒有雙重請求以及丟棄陳舊結果之類的功能由本地功能支持。鏈接到valueChanges observable 的表單控件 將更新div中的結果。

DZone有一篇很好的文章,描述了Angular及其一些功能。Java開發人員熟悉依賴注入,靜態類型和註釋等許多功能,並使Angular易於學習。這使得Angular成為對前端開發感興趣的Java開發人員的非常好的框架。

後端是帶有服務和JPA存儲庫的小型REST控制器。Spring Boot使得用幾行代碼和幾個註釋創建後端成為可能。


分享到:


相關文章: