Angular + SpringBoot + PostgreSQL
Extrémité avant: angulaire (TypeScript) Backend: Spring Boot (Java) DB: PostgreSQL
En référence à cet article, j'ai essayé de faire ce que dit le titre. Tutoriel angulaire + J'ai essayé Spring Boot
Création d'un projet avec Spring Initializer
Créé avec Maven Project
Les dépendances incluent postgreSQL Driver
et Lombok
.
Le nom est approprié
environnement
Cet article est fait sur Mac, mais il fonctionne bien sur Windows. (7 a été confirmé, mais 10 ne sait pas)
% sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.2
BuildVersion: 19C57
% osascript -e 'version of app "IntelliJ IDEA"'
2019.3.1
% java --version
java 11.0.4 2019-07-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.4+10-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.4+10-LTS, mixed mode)
% postgres --version
postgres (PostgreSQL) 12.1
% ng --version
Angular CLI: 8.3.4
Node: 11.12.0
OS: darwin x64
Angular:
...
Package Version
------------------------------------------------------
@angular-devkit/architect 0.803.4
@angular-devkit/core 8.3.4
@angular-devkit/schematics 8.3.4
@schematics/angular 8.3.4
@schematics/update 0.803.4
rxjs 6.4.0
PostgreSQL Nous partirons du principe que PostgreSQL est déjà installé. Cette fois, j'utilise un schéma.
CREATE SCHEMA tutorial
CREATE TABLE tutorial.heroes(
id INT,
name VARCHAR(64)
)
INSERT INTO tutorial.heroes VALUES
(1, 'capitaine Amérique'),
(2, 'Homme de fer'),
(3, 'Ponton'),
(4, 'Alors Odinson'),
(5, 'Veuve noire'),
(6, 'Oeil de faucon'),
(7, 'Wijon'),
(8, 'Sorcière écarlate'),
(9, 'Faucon'),
(10, 'Machine de guerre'),
(11, 'Capitaine Marvel');
Maintenant, PostgreSQL est prêt.
Angular Nous partirons du principe que tout le Tutoriel angulaire a été terminé.
Remplacez la classe de service heroUrl par l'URL de l'API REST.
hero.service.ts
...
//Abréviation
export class HeroService {
// private heroesUrl = 'api/heroes'; //URL de l'API Web
private heroesUrl = 'http://localhost:8080'; // <=Ajouter ici
httpOptions = {
headers: new HttpHeaders({ "Content-Type": "application/json" })
};
constructor(
private http: HttpClient,
private messageService: MessageService
) {}
//Abréviation
...
app.module.ts
Pour obtenir les données en touchant réellement l'API au lieu de se moquer Mettez en commentaire le HttpClientInMemoryWebApiModule qui se comporte comme un serveur API.
app.module.ts
@NgModule({
declarations: [
AppComponent,
HeroesComponent,
HeroDetailComponent,
MessagesComponent,
DashboardComponent,
HeroSearchComponent
],
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
HttpClientModule
// HttpClientInMemoryWebApiModule.forRoot(
// InMemoryDataService, { dataEncapsulation: false }
// )
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
heroes.component.ts
add(name: string): void {
name = name.trim();
//↓ Ajoutez 1 au dernier élément comme ID du nouveau héros
let id = this.heroes.slice(-1)[0].id + 1;
if (!name) { return; }
//Ajouter un identifiant et passer l'argument en tant que héros
this.heroService.addHero({ name, id } as Hero)
.subscribe(hero => {
this.heroes.push(hero);
});
}
Ceci termine les changements angulaires.
Hero class Créez une classe de héros pour la définition de type de héros. Depuis que j'utilise Lombok, je n'ai pas besoin de setter et de getter. (Dans Intellij, vous devez mettre lombok dans Plugin)
Hero.java
package tutorial.tutorial.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@AllArgsConstructor
@Data
@NoArgsConstructor
@ToString
public class Hero {
private Integer id;
private String name;
}
HeroDAO class Créez une classe DAO pour accéder à la base de données. Créez tous les traitements CRUD.
HeroDAO.java
package tutorial.tutorial.model;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class HeroDAO {
/**
*Méthode pour établir les informations de connexion à la base de données
*
* @retour des informations de connexion conn
*/
public Connection getConnection() throws ClassNotFoundException, SQLException {
//Préparer les variables pour stocker les informations de connexion
Connection conn = null;
//Initialisation
Class.forName("org.postgresql.Driver");
//Entrez les informations de la base de données
conn = DriverManager.getConnection("jdbc:postgresql://localhost/postgres?currentSchema=tutorial", "postgres", "postgres");
//Désactiver l'autocommit
conn.setAutoCommit(false);
//Renvoie les informations de connexion
return conn;
}
/**
*Méthode pour obtenir et renvoyer tous les héros
*
* @retourner la liste des types de héros héros
*/
public List<Hero> findAll() throws ClassNotFoundException, SQLException {
//Préparer les variables pour stocker les informations de connexion
Connection conn = null;
//Pour stocker les instances de la classe dto
List<Hero> heroes = new ArrayList<>();
//Se connecter à la base de données
try {
conn = getConnection();
//Création d'objets pour l'exécution d'instructions SQL
Statement pstmt = conn.createStatement();
//Émission de l'instruction SELECT
String sql = "SELECT * FROM tutorial.heroes";
//Obtenir le résultat de l'exécution de l'instruction SQL (valeur reçue de la base de données)
ResultSet rs = pstmt.executeQuery(sql);
//Répétez la valeur reçue de DB pour le nombre d'enregistrements
while (rs.next()) {
// Hero(DTO)Créer une instance de la classe
Hero dto = new Hero();
//Définir la valeur de l'ID de colonne
dto.setId(rs.getInt("id"));
//Définir la valeur du nom de la colonne
dto.setName(rs.getString("name"));
//Stocker l'instance dans la liste
heroes.add(dto);
//Passer au traitement d'enregistrement suivant avec l'instruction while(s'il y a)
}
//Instruction de capture d'erreur
} catch (SQLException e) {
e.printStackTrace();
//Traitement à exécuter indépendamment du fait qu'une exception se produise
} finally {
//Si le contenu de conn est inclus, déconnectez la connexion db
if (conn != null) {
conn.close();
}
}
//Renvoie une liste d'instances de la classe DTO
return heroes;
}
/**
*Une méthode pour obtenir et retourner Hero qui correspond à l'id reçu en argument
*
* @param id
* @return selectedHero
*/
public Hero findOneHero(int id) throws ClassNotFoundException, SQLException {
Connection conn = null;
Hero selectedHero = new Hero();
//Se connecter à la base de données
try {
conn = getConnection();
//Émission de l'instruction SELECT
String sql = "SELECT * FROM tutorial.heroes WHERE id = ?";
//Création d'objets pour l'exécution d'instructions SQL
PreparedStatement pstmt = conn.prepareStatement(sql);
//Définissez l'identifiant reçu comme argument dans l'espace réservé.
pstmt.setInt(1, id);
//Obtenir le résultat de l'exécution de l'instruction SQL (valeur reçue de la base de données)
ResultSet rs = pstmt.executeQuery();
//Définissez la valeur reçue du DB sur dto.
while (rs.next()) {
// Hero(DTO)Créer une instance de la classe
Hero dto = new Hero();
//Définir la valeur de l'ID de colonne
dto.setId(rs.getInt("id"));
//Définir la valeur du nom de la colonne
dto.setName(rs.getString("name"));
//
selectedHero = dto;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
return selectedHero;
}
/**
*Une méthode pour mettre à jour Hero qui correspond à l'id reçu dans l'argument
*
* @param hero
*/
public void updateHero(Hero hero) throws ClassNotFoundException, SQLException {
Connection conn = null;
try {
conn = getConnection();
String sql = "UPDATE tutorial.heroes SET name = ? WHERE id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, hero.getName());
pstmt.setInt(2, hero.getId());
pstmt.executeUpdate();
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
}
/**
*Une méthode pour supprimer Hero qui correspond à l'id reçu dans l'argument
*
* @id du paramètre id du héros que vous souhaitez effacer
*/
public void deleteHero(int id) throws ClassNotFoundException, SQLException {
Connection conn = null;
try {
conn = getConnection();
String sql = "DELETE FROM tutorial.heroes WHERE id = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
pstmt.executeUpdate();
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
}
/**
*Une méthode pour insérer un nouveau héros avec l'id et le nom reçus comme arguments
*
* @param hero
*/
public void createHero(Hero hero) throws ClassNotFoundException, SQLException {
Connection conn = null;
try {
conn = getConnection();
String sql = "INSERT INTO tutorial.heroes VALUES(?, ?)";
//Création d'objets pour l'exécution d'instructions SQL
PreparedStatement pstmt = conn.prepareStatement(sql);
//Définissez l'identifiant reçu comme argument dans l'espace réservé.
pstmt.setInt(1, hero.getId());
pstmt.setString(2, hero.getName());
//Obtenir le résultat de l'exécution de l'instruction SQL (valeur reçue de la base de données)
pstmt.executeUpdate();
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
}
}
HeroController class
Créez une API REST. J'ai créé les cinq suivants. --GetHeroes renvoie tous les héros --getHero pour renvoyer le héros associé à l'id
Les données reçues selon le didacticiel sont définies sur Hero.
HeroContoller.java
package tutorial.tutorial.controller;
import org.springframework.web.bind.annotation.*;
import tutorial.tutorial.model.*;
import java.sql.SQLException;
import java.util.*;
@RestController
public class HeroController {
/**
*Une méthode qui reçoit tous les héros de la classe DAO
*
* @return heroList
*/
@GetMapping("/")
public List<Hero> getHeroes() throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
List<Hero> heroes = dao.findAll();
List<Hero> heroList = new ArrayList<>();
heroList.addAll(heroes);
return heroList;
}
/**
*Une méthode qui reçoit le héros associé à l'id de la classe DAO
*
* @param id
* @return hero
*/
@GetMapping("/{id}")
public Hero getHero(@PathVariable Integer id) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
Hero hero = dao.findOneHero(id);
return hero;
}
/**
*Une méthode à INSÉRER avec l'id et le nom reçus dans la classe DAO
*
* @param newHero
* @return hero
*/
@PostMapping("/")
public Hero create(@RequestBody Hero newHero) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
dao.createHero(newHero);
return newHero;
}
/**
*Une méthode pour SUPPRIMER le héros associé à l'id dans la classe DAO
*
* @param id
*/
@DeleteMapping("/{id}")
public void delete(@PathVariable Integer id) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
dao.deleteHero(id);
}
/**
*Une méthode pour METTRE À JOUR le héros associé à l'id dans la classe DAO
*
* @param updatedHero
*/
@PutMapping("/")
public Hero update(@RequestBody Hero updatedHero) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
dao.updateHero(updatedHero);
return updatedHero;
}
}
Pour des raisons de sécurité, ajax etc. ne peut acquérir des ressources de la même origine que par SOP. Étant donné que les numéros de port sont cette fois différents entre Angular et Spring Boot, il est nécessaire d'activer CORS afin de libérer le SOP uniquement entre les origines approuvées.
WebConfig.java
package tutorial.tutorial.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer{
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*")
//Spécifiez le numéro de port à autoriser(Côté angulaire)
.allowedOrigins("http://localhost:3000")
//Liste des méthodes autorisées
.allowedMethods("GET", "POST", "DELETE", "PUT")
//En-tête autorisé
.allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept")
.allowCredentials(false).maxAge(3600);
}
}
Lançons TutorialApplication et Angular. Vous pouvez confirmer que l'API est appelée et que la base de données est en cours d'utilisation.
Afin de comprendre à quoi ressemble l'application Web, j'ai effectué un échange en utilisant Angular comme frontal, Spring Boot comme back-end et PostgreSQL comme base de données, qui sont étroitement liés à Ionic que j'utilise habituellement. ..
Recommended Posts