Angular + SpringBoot + PostgreSQL
Frontend: Angular (TypeScript) Backend: Spring Boot (Java) DB: PostgreSQL
Mit Bezug auf diesen Artikel habe ich versucht, das zu machen, was der Titel sagt. Angular Tutorial + Ich habe Spring Boot ausprobiert
Erstellen eines Projekts mit Spring Initializer Erstellt mit Maven Project Zu den Abhängigkeiten gehören "postgreSQL Driver" und "Lombok".
Der Name ist angemessen
Umgebung
Dieser Artikel wurde unter Mac erstellt, funktioniert jedoch unter Windows einwandfrei. (7 wurde bestätigt, 10 weiß es nicht)
% 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 Wir gehen davon aus, dass PostgreSQL bereits installiert ist. Dieses Mal verwende ich ein Schema.
CREATE SCHEMA tutorial
CREATE TABLE tutorial.heroes(
id INT,
name VARCHAR(64)
)
INSERT INTO tutorial.heroes VALUES
(1, 'Kapitän Amerika'),
(2, 'Ironman'),
(3, 'Hulk'),
(4, 'Also Odinson'),
(5, 'Schwarze Witwe'),
(6, 'Falkenauge'),
(7, 'Wijon'),
(8, 'Scharlachrote Hexe'),
(9, 'Falke'),
(10, 'Kriegsmaschine'),
(11, 'Captain Marvel');
Jetzt ist PostgreSQL fertig.
Angular Wir gehen davon aus, dass alle Angular Tutorial abgeschlossen sind.
Ändern Sie die Serviceklasse heroUrl in die REST-API-URL.
hero.service.ts
...
//Abkürzung
export class HeroService {
// private heroesUrl = 'api/heroes'; //Web-API-URL
private heroesUrl = 'http://localhost:8080'; // <=Hier hinzufügen
httpOptions = {
headers: new HttpHeaders({ "Content-Type": "application/json" })
};
constructor(
private http: HttpClient,
private messageService: MessageService
) {}
//Abkürzung
...
app.module.ts
Um die Daten zu erhalten, indem Sie tatsächlich auf die API klicken, anstatt sich zu verspotten Kommentieren Sie das HttpClientInMemoryWebApiModule aus, das sich wie ein API-Server verhält.
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();
//↓ Addiere 1 zum letzten Element als ID des neuen Helden
let id = this.heroes.slice(-1)[0].id + 1;
if (!name) { return; }
//ID hinzufügen und Argument als Held übergeben
this.heroService.addHero({ name, id } as Hero)
.subscribe(hero => {
this.heroes.push(hero);
});
}
Damit sind die Winkeländerungen abgeschlossen.
Hero class Erstellen Sie eine Heldenklasse für die Definition des Heldentyps. Da ich Lombok benutze, brauche ich keinen Setter und Getter. (In Intellij müssen Sie Lombok in Plugin setzen)
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 Erstellen Sie eine DAO-Klasse, um auf die Datenbank zuzugreifen. Erstellen Sie die gesamte CRUD-Verarbeitung.
HeroDAO.java
package tutorial.tutorial.model;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class HeroDAO {
/**
*Methode zum Herstellen von DB-Verbindungsinformationen
*
* @Informationen zur Verbindungsverbindung zurückgeben
*/
public Connection getConnection() throws ClassNotFoundException, SQLException {
//Bereiten Sie Variablen zum Speichern von Verbindungsinformationen vor
Connection conn = null;
//Initialisieren
Class.forName("org.postgresql.Driver");
//Geben Sie die DB-Informationen ein
conn = DriverManager.getConnection("jdbc:postgresql://localhost/postgres?currentSchema=tutorial", "postgres", "postgres");
//Deaktivieren Sie die automatische Festschreibung
conn.setAutoCommit(false);
//Gibt Verbindungsinformationen zurück
return conn;
}
/**
*Methode, um alle Helden zu erhalten und zurückzugeben
*
* @Heldenliste zurückgeben Heldenliste
*/
public List<Hero> findAll() throws ClassNotFoundException, SQLException {
//Bereiten Sie Variablen zum Speichern von Verbindungsinformationen vor
Connection conn = null;
//Zum Speichern von Instanzen der Klasse dto
List<Hero> heroes = new ArrayList<>();
//Verbindung zur Datenbank herstellen
try {
conn = getConnection();
//Objekterstellung zum Ausführen von SQL-Anweisungen
Statement pstmt = conn.createStatement();
//Ausgabe der SELECT-Anweisung
String sql = "SELECT * FROM tutorial.heroes";
//Ruft das Ausführungsergebnis der SQL-Anweisung ab (Wert von DB empfangen)
ResultSet rs = pstmt.executeQuery(sql);
//Wiederholen Sie den von DB empfangenen Wert für jeden Datensatz
while (rs.next()) {
// Hero(DTO)Erstellen Sie eine Instanz der Klasse
Hero dto = new Hero();
//Stellen Sie den Spalten-ID-Wert ein
dto.setId(rs.getInt("id"));
//Legen Sie den Wert des Spaltennamens fest
dto.setName(rs.getString("name"));
//Instanz in Liste speichern
heroes.add(dto);
//Fahren Sie mit der while-Anweisung mit der nächsten Datensatzverarbeitung fort(Wenn da ist)
}
//Fehler catch-Anweisung
} catch (SQLException e) {
e.printStackTrace();
//Verarbeitung, die ausgeführt werden soll, unabhängig davon, ob eine Ausnahme auftritt
} finally {
//Wenn der Inhalt von conn enthalten ist, trennen Sie die Datenbankverbindung
if (conn != null) {
conn.close();
}
}
//Gibt eine Liste der Instanzen der DTO-Klasse zurück
return heroes;
}
/**
*Eine Methode zum Abrufen und Zurückgeben von Hero, die der als Argument erhaltenen ID entspricht
*
* @param id
* @return selectedHero
*/
public Hero findOneHero(int id) throws ClassNotFoundException, SQLException {
Connection conn = null;
Hero selectedHero = new Hero();
//Verbindung zur Datenbank herstellen
try {
conn = getConnection();
//Ausgabe der SELECT-Anweisung
String sql = "SELECT * FROM tutorial.heroes WHERE id = ?";
//Objekterstellung zum Ausführen von SQL-Anweisungen
PreparedStatement pstmt = conn.prepareStatement(sql);
//Legen Sie die empfangene ID als Argument im Platzhalter fest.
pstmt.setInt(1, id);
//Ruft das Ausführungsergebnis der SQL-Anweisung ab (Wert von DB empfangen)
ResultSet rs = pstmt.executeQuery();
//Setzen Sie den von DB empfangenen Wert auf dto.
while (rs.next()) {
// Hero(DTO)Erstellen Sie eine Instanz der Klasse
Hero dto = new Hero();
//Stellen Sie den Spalten-ID-Wert ein
dto.setId(rs.getInt("id"));
//Legen Sie den Wert des Spaltennamens fest
dto.setName(rs.getString("name"));
//
selectedHero = dto;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
return selectedHero;
}
/**
*Eine Methode zum Aktualisieren von Hero, die mit der im Argument empfangenen ID übereinstimmt
*
* @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();
}
}
}
/**
*Eine Methode zum Löschen von Hero, die mit der im Argument empfangenen ID übereinstimmt
*
* @param id id des Helden, den Sie löschen möchten
*/
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();
}
}
}
/**
*Eine Methode zum Einfügen eines neuen Helden mit der ID und dem Namen, die als Argumente empfangen wurden
*
* @param hero
*/
public void createHero(Hero hero) throws ClassNotFoundException, SQLException {
Connection conn = null;
try {
conn = getConnection();
String sql = "INSERT INTO tutorial.heroes VALUES(?, ?)";
//Objekterstellung zum Ausführen von SQL-Anweisungen
PreparedStatement pstmt = conn.prepareStatement(sql);
//Legen Sie die empfangene ID als Argument im Platzhalter fest.
pstmt.setInt(1, hero.getId());
pstmt.setString(2, hero.getName());
//Ruft das Ausführungsergebnis der SQL-Anweisung ab (Wert von DB empfangen)
pstmt.executeUpdate();
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
}
}
HeroController class
Erstellen Sie eine REST-API. Ich habe die folgenden fünf erstellt. --GetHeroes gibt alle Helden zurück --getHero, um den mit id verknüpften Helden zurückzugeben --Erstelle einen neuen Helden
Die gemäß dem Tutorial empfangenen Daten sind auf Hero eingestellt.
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 {
/**
*Eine Methode, die alle Helden aus der DAO-Klasse empfängt
*
* @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;
}
/**
*Eine Methode, die den mit der ID verknüpften Helden von der DAO-Klasse empfängt
*
* @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;
}
/**
*Eine Methode zum EINFÜGEN mit der empfangenen ID und dem Namen in der DAO-Klasse
*
* @param newHero
* @return hero
*/
@PostMapping("/")
public Hero create(@RequestBody Hero newHero) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
dao.createHero(newHero);
return newHero;
}
/**
*Eine Methode zum LÖSCHEN des mit id in der DAO-Klasse verknüpften Helden
*
* @param id
*/
@DeleteMapping("/{id}")
public void delete(@PathVariable Integer id) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
dao.deleteHero(id);
}
/**
*Eine Methode zum AKTUALISIEREN des Helden, der der ID in der DAO-Klasse zugeordnet ist
*
* @param updatedHero
*/
@PutMapping("/")
public Hero update(@RequestBody Hero updatedHero) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
dao.updateHero(updatedHero);
return updatedHero;
}
}
Aus Sicherheitsgründen kann Ajax usw. nur von SOP Ressourcen desselben Ursprungs erwerben. Da sich die Portnummern diesmal zwischen Angular und Spring Boot unterscheiden, muss CORS aktiviert werden, um die SOP nur zwischen vertrauenswürdigen Ursprüngen freizugeben.
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("/*")
//Geben Sie die zuzulassende Portnummer an(Winkelseite)
.allowedOrigins("http://localhost:3000")
//Liste der zulässigen Methoden
.allowedMethods("GET", "POST", "DELETE", "PUT")
//Zulässiger Header
.allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept")
.allowCredentials(false).maxAge(3600);
}
}
Lassen Sie uns TutorialApplication und Angular ausführen. Sie können bestätigen, dass die API aufgerufen wird und die Datenbank betrieben wird.
Um zu verstehen, wie die Webanwendung aussieht, habe ich einen Austausch mit Angular als Front-End, Spring Boot als Back-End und PostgreSQL als Datenbank durchgeführt, die eng mit Ionic verwandt sind, das ich normalerweise verwende. ..
Recommended Posts