Angular4 Spring boot
Spring Data JPA
Rest CRUD
Monoem YOUNEB
Ingénieur Consultant Java EE
Vue Globale de l’application
- Modifier le nom et le prénom puis cliquer sur le bouton Valider
- Ajouter un enregistrement : appuyer sur le bouton « Ajouter une personne »
Introduire les données puis « Valider »
2
Structure de l’application
3
Structure de la partie Angular 4
4
Partie I : Spring rest Back End
1. Création d’un projet Maven : Spring Boot Initializr project
5
6
7
2. Configuration de Spring Boot
# ===============================
# = DATA SOURCE
# ===============================
[Link] =
jdbc:mysql://localhost/persondb?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDat
etimeCode=false&serverTimezone=UTC
[Link] = root
[Link] =
[Link] = true
[Link] = SELECT 1
# ===============================
# = JPA / HIBERNATE
# ===============================
[Link]-sql = true
[Link]-auto = update
[Link]-strategy = [Link]
[Link] = [Link].MySQL5Dialect
3. Création de l’entité Person
8
a. Getter & setter
9
10
b. Constructeur par paramètres
c. Constructeur sans paramètres
d. To String
11
e. Entité « Person »
package [Link];
import [Link];
import [Link];
import [Link];
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String nom;
private String prenom;
// Getter & Setter
public Long getId() {
return id;
}
public void setId(Long id) {
[Link] = id;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
[Link] = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
12
[Link] = prenom;
}
// Constructeur par paramètres
public Person(String nom, String prenom) {
[Link] = nom;
[Link] = prenom;
}
// To String
@Override
public String toString() {
return "Person{" + "id=" + id + ", nom=" + nom + ", prenom=" + prenom + '}';
}
// Constructeur sans paramètres
public Person() {
}
}
4. Package « Repository »
13
14
package [Link];
import [Link];
import [Link];
public interface PersonRepository extends JpaRepository<Person, Long>{
}
5. Création de RestController
Le RestController sert pour réceptionner les requêtes http envoyées par Angular.
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
@RequestMapping("/rm")
@CrossOrigin(origins="[Link] allowedHeaders="*")
public class PersonController {
@Autowired
private PersonRepository personRepository;
@GetMapping("/list")
public List<Person> getPersons() {
return [Link]();
}
@GetMapping("/show/{id}")
public Person getPerson(@PathVariable Long id) {
return [Link](id);
}
@DeleteMapping("/delete/{id}")
15
public boolean deletePerson(@PathVariable Long id) {
[Link](id);
return true;
}
@PostMapping("/add")
public Person savePerson(@RequestBody Person person) {
return [Link](person);
}
@PutMapping("/update")
public Person updatePerson(@RequestBody Person person) {
return [Link](person);
}
}
6. Modification du main de notre application
package [Link];
package [Link];
import [Link];
import [Link];
import [Link];
16
import [Link];
import [Link];
import [Link];
@SpringBootApplication
public class Angular4SpringBootRestCrudApplication implements CommandLineRunner{
@Autowired
private PersonRepository personRepository;
public static void main(String[] args) {
[Link]([Link], args);
}
@Override
public void run(String... args) throws Exception{
[Link](new Person("YOUNEB","Monoem"));
[Link](new Person("MICHEL","Alexe"));
[Link](new Person("ROBERT","Lisa"));
}
7. Test de la fonction getPersons
17
Partie II : Integration d’angular4
1. Installation de nodeJs
[Link]
18
19
20
2. Vérifier la version de nodejs
Taper les touches windows + r au même temps
Tapez cmd
21
Taper node –v
Puis npm –v
Ou bien : Taper node –v & npm –v
3. Copier le path du dossier static
22
4. E:\workJee\workSpaceNetbeans8.2\Angular4SpringBootRestCRUD\src\main\resources
5. Installation du RestClient
Visiter le site d’angular CLI (command Line interface) [Link]
Shift + bouton droit sur le dossier Static
23
6. Installer npm dans le dossier static
Taper « npm install -g @angular/cli»
7. Pour créer un nouveau projet taper la commande « ng new
<nom-projet> »
Taper par exemple « ng new restperson »
24
25
8. Pour démarrer l’application taper la cmd :
cd restperson
ng serve
9. Autoriser l’accès
a. Visiter l’adresse : [Link]
b. Télécharger & installer visual studio code : [Link]
26
27
28
c. Taper la cmd suivante pour ouvrir le projet avec visual studio code :
E:\workJee\workSpaceNetbeans8.2\Angular4SpringBootRestCRUD\src\main\resources\static\re
stperson> code .
d. Ouvrir le comande line avec visual studio code :
29
10. Ou bien cliquer sur la zone en rouge
30
e. Création de la classe User dans angular
Taper la commande : ng g class person
Résultat
La classe a été sous le répertoire src/app/
31
f. Ajouter les attributs
g. Création des components pour le crud (create, read , update and delete).
Liste des person : ng g component components/listperson
h. Ajout/editer (create/ipdate) de person : ng g component components/personform
i. Editer le fichier « [Link] »
Importer RouterModule, Routes pour l’application
11. import {RouterModule, Routes} from '@angular/router';
Déclarer les routes
12. const appRoutes:Routes=[
13. {path:'list', component:ListpersonComponent},
14. {path:'add', component:PersonformComponent}
15. ]
Délarer les modules et importer les routes:
NgModule({
declarations: [
AppComponent,
ListpersonComponent,
PersonformComponent
],
imports: [
BrowserModule,
[Link](appRoutes)
],
Vue globale
32
Editer le fichier « [Link] »
Remplacer le contenu par ce ci (création d’une route par défaut qui affiche « Hello
world ! »)
Route : localhost :4200/list
33
Développement des classes services (Angular)
En angular les services sont basés sur les commandes injectables
Création de service
Taper la cmd : ng g serve shared_service/person
Importer la classe service dans : src/app/[Link]
16.
17. import { PersonService } from'./shared-service/[Link]';
Ajouter le provider de notre service
18. providers: [PersonService],
Ajouter angular : httprequest
19. import {HttpModule} from '@angular/http';
imports: [
34
BrowserModule,
HttpModule,
[Link](appRoutes)
],
Vue globale
La classe service : [Link]
Import dans [Link]
20. import {Http, Response, Headers} from '@angular/http';
Vue globale
35
import { Injectable } from '@angular/core';
import {Http, Response, Headers, RequestOptions} from '@angular/http';
import {Observable} from 'rxjs/observable';
// importer le map de rxjs
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import {Person} from '../person';
@Injectable()
export class PersonService {
private baseUrl:string='[Link]
private headers= new Headers({'Content-Type':'application/json'});
private options = new RequestOptions({headers:[Link]});
//Injection de l'http
constructor(private _http:Http) { }
getPersons(){
// '/list' est une référence au @GetMapping("/list") dans le controlleur : PersonController([Link])
return this._http.get([Link]+'/list',[Link]).map((response:Response)=>[Link]())
.catch([Link]);
}
getPerson(id:Number){
// '/show/' est une référence au @GetMapping("/show/{id}") dans le controlleur :
PersonController([Link])
return this._http.get([Link]+'/show/'+id,[Link]).map((response:Response)=>[Link]())
.catch([Link]);
}
deletePerson(id:Number){
// '/delete/{id}' est une référence au @GetMapping("/delete/{id}") dans le controlleur :
PersonController([Link])
return this._http.delete([Link]+'/delete/'+id,[Link]).map((response:Response)=>[Link]())
.catch([Link]);
}
savePerson(person:Person){
// '/add' est une référence au @GetMapping("/add") dans le controlleur : PersonController([Link])
return this._http.post([Link]+'/add',[Link](person),[Link]).map((response:Response)=>[Link]())
.catch([Link]);
}
updatePerson(person:Person){
// '/update' est une référence au @GetMapping("/add") dans le controlleur : PersonController([Link])
return
this._http.put([Link]+'/update',[Link](person),[Link]).map((response:Response)=>[Link]())
.catch([Link]);
}
errorHandle(error:Response){
return [Link](error||"Server Error");
21. Import de classe service dans [Link]
22. import {Component, OnInit } from '@angular/core';
23. import {PersonService} from '../../shared-service/[Link]';
24. import {Person} from '../../person';
25.
26. @Component({
27. selector: 'app-listperson',
28. templateUrl: './[Link]',
29. styleUrls: ['./[Link]']
30. })
31. export class ListpersonComponent implements OnInit {
32.
36
33. private persons:Person[];
34. constructor(private _personService:PersonService) { }
35.
36. ngOnInit() {
37. // appel des méthodes de [Link]
38. this._personService.getPersons().subscribe((persons)=>{
39. [Link](persons);
40. [Link]=persons;
41. },(error)=>{[Link](error);
42. })
43. }
44.
45. }
Autorisation de Restcontroller
Affichage de [Link]
46. <table>
47. <thead>
48. <th>ID</th>
49. <th>Nom</th>
50. <th>PRENOM</th>
51. </thead>
52.
53. <tbody>
54. <tr *ngFor ="let p of persons">
55. <td>{{[Link]}}</td>
56. <td>{{[Link]}}</td>
57. <td>{{[Link]}}</td>
58. </tr>
59.
60. </tbody>
61.
62. </table>
Résultat : [Link]
37
Installation de Bootstrap
Taper la cmd : npm install [email protected] –save
63. Ouvrir le fichier [Link] et modifier le style en mettant le path de bootstrap
local & sauvegarder
38
Import directly in src/[Link] or src/[Link]:
64. @import '~bootstrap/dist/css/[Link]';
Modifier le style du fichier [Link]
65. <div class="container">
66. <table class="table table-striped">
67. <thead>
68. <th>ID</th>
69. <th>Nom</th>
70. <th>PRENOM</th>
71. </thead>
72.
73. <tbody>
74. <tr *ngFor ="let p of persons">
75. <td>{{[Link]}}</td>
76. <td>{{[Link]}}</td>
77. <td>{{[Link]}}</td>
78. </tr>
79.
80. </tbody>
81.
82. </table>
83.
84. </div>
Taper la cmd : ng serve –open et consulter l’url : [Link]
39
Ajouter des boutons (nouveau, modifier & supprimer) dans : [Link]
85.
86. <div class="container">
87. <table class="table table-striped">
88. <thead>
89. <th>ID</th>
90. <th>Nom</th>
91. <th>PRENOM</th>
92. <th>Action</th>
93. </thead>
94.
95. <tbody>
96. <tr *ngFor ="let p of persons">
97. <td>{{[Link]}}</td>
98. <td>{{[Link]}}</td>
99. <td>{{[Link]}}</td>
100. <td>
101. <button class="btn btn-primary">Modifier</button>
102. <button class="btn btn-danger">Supprimer</button>
103. </td>
104. </tr>
105.
106. </tbody>
107.
108. </table>
109. <button class="btn btn-primary">Ajouter une personne</button>
40
110. </div>
111.
Résulatat
Bouton Supprimer (Delete)
Revenons au fichier [Link]
<div class="container">
<table class="table table-striped">
<thead>
<th>ID</th>
<th>Nom</th>
<th>PRENOM</th>
<th>Action</th>
</thead>
<tbody>
<tr *ngFor ="let p of persons">
<td>{{[Link]}}</td>
<td>{{[Link]}}</td>
<td>{{[Link]}}</td>
<td>
<button class="btn btn-primary">Modifier</button>
<button class="btn btn-danger" (click)="deletePerson(person)">Supprimer</button>
</td>
</tr>
</tbody>
</table>
<button class="btn btn-primary">Ajouter une personne</button>
</div>
112. Modifier le fichier [Link] et implémenter la méthode
deletperson()
import {Component, OnInit } from '@angular/core';
import {PersonService} from '../../shared-service/[Link]';
import {Person} from '../../person';
import { splitClasses } from '@angular/compiler';
@Component({
selector: 'app-listperson',
templateUrl: './[Link]',
styleUrls: ['./[Link]']
})
export class ListpersonComponent implements OnInit {
private persons:Person[];
41
constructor(private _personService:PersonService) { }
ngOnInit() {
// appel des méthodes de [Link]
this._personService.getPersons().subscribe((persons)=>{
[Link](persons);
[Link]=persons;
},(error)=>{[Link](error);
})
}
deletePerson(person){
this._personService.deletePerson([Link]).subscribe((data)=>{
[Link]([Link](person),1);
},(error)=>{[Link](error);
})
create and update implementation
1. Modifier un enregistrement
On cliquant sur le bouton « modifier » le détails du personne s’affiche dans un formulaire
puis on peut l’éditer.
a. Modifier le fichier [Link]
- Ajouter l’import de formsModule
-
- import {FormsModule} from '@angular/forms';
-
imports: [
BrowserModule,
HttpModule,
[Link](appRoutes)
],
42
Vue globale du fichier [Link]
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import { AppComponent } from './[Link]';
import { ListpersonComponent } from './components/listperson/[Link]';
import { PersonformComponent } from './components/personform/[Link]';
import { PersonService } from './shared-service/[Link]';
import {HttpModule} from '@angular/http';
import {FormsModule} from '@angular/forms';
const appRoutes:Routes=[
{path:'list', component:ListpersonComponent},
{path:'add', component:PersonformComponent}
]
@NgModule({
declarations: [
AppComponent,
ListpersonComponent,
PersonformComponent
],
imports: [
BrowserModule,
HttpModule,
FormsModule,
[Link](appRoutes)
],
providers: [PersonService],
bootstrap: [AppComponent]
})
export class AppModule { }
b. Modifier le fichier [Link]
- Importer la classe Person
- import {Person} from '../../person';
- Déclarer Person comme attribut (pour le bind dans le formulaire)
private person:Person;
- Vue globale du fichier [Link]
- import { Component, OnInit } from '@angular/core';
- import {Person} from '../../person';
43
-
- @Component({
- selector: 'app-personform',
- templateUrl: './[Link]',
- styleUrls: ['./[Link]']
- })
- export class PersonformComponent implements OnInit {
- private person:Person;
- constructor() { }
-
- ngOnInit() {
- }
-
- }
-
c. Création du formulaire « [Link] »
<div class="container">
<form>
<div class="form group">
<label for="id">ID : </label>
<input type="text" name="id" class="form-control" [(ngModel)]="[Link]">
</div>
<label for="nom">Nom : </label>
<div class="form group">
<input type="text" name="nom" class="form-control" [(ngModel)]="[Link]">
</div>
<label for="prenom">Prénom : </label>
<div class="form group">
<input type="text" name="prenom" class="form-control" [(ngModel)]="[Link]">
</div>
<input type="submit" value="Valider" class="btn btn-success">
</form>
</div>
- Visiter l’adresse : [Link]
44
- Passer l’objet Person au formulaire
Ouvrir le fichier : [Link]
<div class="container">
<table class="table table-striped">
<thead>
<th>ID</th>
<th>Nom</th>
<th>PRENOM</th>
<th>Action</th>
</thead>
<tbody>
<tr *ngFor ="let person of persons">
<td>{{[Link]}}</td>
<td>{{[Link]}}</td>
<td>{{[Link]}}</td>
<td>
<button class="btn btn-primary" (click)="showPerson(person)">Modifier</button>
<button class="btn btn-danger" (click)="deletePerson(person)">Supprimer</button>
</td>
</tr>
</tbody>
</table>
<button class="btn btn-primary" (click)="addPerson()">Ajouter une personne</button>
</div>
- Implémenter les deux méthodes : showPerson(person) & addPerson()
Déclarer la classe Personne dans le service : [Link]
Pour qu’il soit injectable
// Injection de Person
private person:Person;
Création du setter & getter
setter(person:Person){
[Link]=person;
}
getter(){
return [Link];
}
Vue globale du fichier [Link]
import { Injectable } from '@angular/core';
45
import {Http, Response, Headers, RequestOptions} from '@angular/http';
import {Observable} from 'rxjs/observable';
// importer le map de rxjs
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import {Person} from '../person';
@Injectable()
export class PersonService {
private baseUrl:string='[Link]
private headers= new Headers({'Content-Type':'application/json'});
private options = new RequestOptions({headers:[Link]});
// Injection de Person
private person:Person;
//Injection de l'http
constructor(private _http:Http) { }
getPersons(){
// '/list' est une référence au @GetMapping("/list") dans le controlleur :
PersonController([Link])
return this._http.get([Link]+'/list',[Link]).map((response:Response)=>[Link]())
.catch([Link]);
}
getPerson(id:Number){
// '/show/' est une référence au @GetMapping("/show/{id}") dans le controlleur :
PersonController([Link])
return this._http.get([Link]+'/show/'+id,[Link]).map((response:Response)=>[Link]())
.catch([Link]);
}
deletePerson(id:Number){
// '/delete/{id}' est une référence au @GetMapping("/delete/{id}") dans le controlleur :
PersonController([Link])
return this._http.delete([Link]+'/delete/'+id,[Link]).map((response:Response)=>[Link]())
.catch([Link]);
}
savePerson(person:Person){
// '/add' est une référence au @GetMapping("/add") dans le controlleur :
PersonController([Link])
return
this._http.post([Link]+'/add',[Link](person),[Link]).map((response:Response)=>[Link]())
.catch([Link]);
}
updatePerson(person:Person){
// '/update' est une référence au @GetMapping("/add") dans le controlleur :
PersonController([Link])
return
this._http.put([Link]+'/update',[Link](person),[Link]).map((response:Response)=>[Link](
))
.catch([Link]);
}
errorHandle(error:Response){
return [Link](error||"Server Error");
}
setter(person:Person){
[Link]=person;
}
getter(){
return [Link];
}
}
46
Ouvrir le fichier [Link]
import {Component, OnInit } from '@angular/core';
import {PersonService} from '../../shared-service/[Link]';
import {Person} from '../../person';
import {splitClasses } from '@angular/compiler';
// pour la redirection
import {Router} from '@angular/router';
@Component({
selector: 'app-listperson',
templateUrl: './[Link]',
styleUrls: ['./[Link]']
})
export class ListpersonComponent implements OnInit {
private persons:Person[];
constructor(private _personService:PersonService, private _router:Router) { }
ngOnInit() {
// appel des méthodes de [Link]
this._personService.getPersons().subscribe((persons)=>{
[Link](persons);
[Link]=persons;
},(error)=>{[Link](error);
})
}
deletePerson(person){
this._personService.deletePerson([Link]).subscribe((data)=>{
[Link]([Link](person),1);
},(error)=>{[Link](error);
})
showPerson(person) {
// setter la personne
this._personService.setter(person);
this._router.navigate(['/add']);
}
addPerson() {
let person=new Person();
this._personService.setter(person);
this._router.navigate(['/add']);
}
Modifier le ficher : [Link]
Pour importer le service
import { Component, OnInit } from '@angular/core';
import {Person} from '../../person';
import {PersonService} from '../../shared-service/[Link]';
import {Router} from '@angular/router';
@Component({
selector: 'app-personform',
templateUrl: './[Link]',
styleUrls: ['./[Link]']
})
export class PersonformComponent implements OnInit {
private person:Person;
constructor(private _personservice:PersonService, private _router:Router) { }
ngOnInit() {
[Link]=this._personservice.getter();
}
47
-cliquer sur modifier
- Cliquer sur « Ajouter une personne »
a. Implémentation de la méthode d’ajout
- Modifier le fichier [Link]
- <div class="container">
-
- <form (ngSubmit)="saveForm()">
- <div class="form group">
-
- <label for="id">ID : </label>
- <input type="text" name="id" class="form-control" [(ngModel)]="[Link]">
- </div>
-
- <label for="nom">Nom : </label>
- <div class="form group">
- <input type="text" name="nom" class="form-control" [(ngModel)]="[Link]">
- </div>
-
- <label for="prenom">Prénom : </label>
- <div class="form group">
- <input type="text" name="prenom" class="form-control" [(ngModel)]="[Link]">
- </div>
-
- <input type="submit" value="Valider" class="btn btn-success">
48
-
- </form>
-
- </div>
-
- Modifier le fichier [Link]
Pour ajouter ou modifier l’enregistrement
import { Component, OnInit } from '@angular/core';
import {Person} from '../../person';
import {PersonService} from '../../shared-service/[Link]';
import {Router} from '@angular/router';
@Component({
selector: 'app-personform',
templateUrl: './[Link]',
styleUrls: ['./[Link]']
})
export class PersonformComponent implements OnInit {
private person:Person;
constructor(private _personservice:PersonService, private _router:Router) { }
ngOnInit() {
[Link]=this._personservice.getter();
}
saveForm(){
if ( [Link]==undefined){
this._personservice.savePerson([Link]).subscribe((person)=>{
[Link](person);
this._router.navigate(['/list']);
},(error)=>{[Link](error);});
}else{
this._personservice.updatePerson([Link]).subscribe((person)=>{
[Link](person);
this._router.navigate(['/list']);
},(error)=>{[Link](error);});
// fin else
}
///
}
}
- Résulat : visiter l’url [Link]
- Cliquer su « Modifier »
- Modifier le nom et le prénom puis cliquer sur le bouton Valider
49
- Ajouter un enregistrement : appuyer sur le bouton « Ajouter une personne »
Introduire les données puis « Valider »
50