Angular + SpringBoot + PostgreSQL
Frontend: Angular (TypeScript) Backend: Spring Boot (Java) DB: PostgreSQL
With reference to this article, I tried to make what the title says. Angular tutorial + I tried Spring Boot
You have created a project with Spring Initializer
Created with Maven Project
Dependencies include postgreSQL Driver
and Lombok
.
The name is appropriate
environment
This article is done on Mac, but it works fine on Windows. (7 has been confirmed, but 10 does not know)
% 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 We will proceed on the assumption that PostgreSQL is already installed. This time I'm using a schema.
CREATE SCHEMA tutorial
CREATE TABLE tutorial.heroes(
id INT,
name VARCHAR(64)
)
INSERT INTO tutorial.heroes VALUES
(1, 'captain America'),
(2, 'Ironman'),
(3, 'Hulk'),
(4, 'Thor Odinson'),
(5, 'Black Widow'),
(6, 'Hawkeye'),
(7, 'Wijon'),
(8, 'Scarlet witch'),
(9, 'Falcon'),
(10, 'War machine'),
(11, 'Captain Marvel');
Now PostgreSQL is ready.
Angular We will proceed on the assumption that all Angular Tutorial has been completed.
Change the service class heroUrl to the URL of the REST API.
hero.service.ts
...
//Abbreviation
export class HeroService {
// private heroesUrl = 'api/heroes'; //Web API URL
private heroesUrl = 'http://localhost:8080'; // <=Add here
httpOptions = {
headers: new HttpHeaders({ "Content-Type": "application/json" })
};
constructor(
private http: HttpClient,
private messageService: MessageService
) {}
//Abbreviation
...
app.module.ts
Because I actually hit the API instead of mocking to get the data Comment out the HttpClientInMemoryWebApiModule that behaves like an API server.
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();
//↓ Add 1 to the last element as the ID of the new hero
let id = this.heroes.slice(-1)[0].id + 1;
if (!name) { return; }
//Add id and pass arguments as Hero
this.heroService.addHero({ name, id } as Hero)
.subscribe(hero => {
this.heroes.push(hero);
});
}
This concludes the Angular changes.
Hero class Create a hero class to define the hero type. Since I am using Lombok, I don't need setters and getters. (In Intellij you need to put lombok in 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 Create a DAO class to access the database. Create all CRUD processing.
HeroDAO.java
package tutorial.tutorial.model;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class HeroDAO {
/**
*Method to establish DB connection information
*
* @return conn connection information
*/
public Connection getConnection() throws ClassNotFoundException, SQLException {
//Prepare variables to store Connection information
Connection conn = null;
//Initialization
Class.forName("org.postgresql.Driver");
//Enter DB information
conn = DriverManager.getConnection("jdbc:postgresql://localhost/postgres?currentSchema=tutorial", "postgres", "postgres");
//Disable autocommit
conn.setAutoCommit(false);
//Returns connection information
return conn;
}
/**
*Method to get and return all Hero
*
* @return heroes Hero type list
*/
public List<Hero> findAll() throws ClassNotFoundException, SQLException {
//Variable preparation for storing Connection information
Connection conn = null;
//For storing instances of dto class
List<Hero> heroes = new ArrayList<>();
//Connect to database
try {
conn = getConnection();
//Object creation for executing SQL statements
Statement pstmt = conn.createStatement();
//Issuing a SELECT statement
String sql = "SELECT * FROM tutorial.heroes";
//Get the execution result of SQL statement (value received from DB)
ResultSet rs = pstmt.executeQuery(sql);
//Repeat the value received from DB for each record
while (rs.next()) {
// Hero(DTO)Instantiate a class
Hero dto = new Hero();
//Set the column id value
dto.setId(rs.getInt("id"));
//Set the value of column name
dto.setName(rs.getString("name"));
//Store instance in List
heroes.add(dto);
//Go to the next record processing with a while statement(if there is)
}
//Error catch statement
} catch (SQLException e) {
e.printStackTrace();
//Processing to be executed regardless of whether an exception occurs
} finally {
//If the contents of conn are included, disconnect the db connection
if (conn != null) {
conn.close();
}
}
//Returns a List of instances of the DTO class
return heroes;
}
/**
*Method to get and return Hero that matches id received by argument
*
* @param id
* @return selectedHero
*/
public Hero findOneHero(int id) throws ClassNotFoundException, SQLException {
Connection conn = null;
Hero selectedHero = new Hero();
//Connect to database
try {
conn = getConnection();
//Issuing a SELECT statement
String sql = "SELECT * FROM tutorial.heroes WHERE id = ?";
//Object creation for executing SQL statements
PreparedStatement pstmt = conn.prepareStatement(sql);
//Set the id received as an argument in the placeholder.
pstmt.setInt(1, id);
//Get the execution result of SQL statement (value received from DB)
ResultSet rs = pstmt.executeQuery();
//Set the value received from DB to dto.
while (rs.next()) {
// Hero(DTO)Instantiate a class
Hero dto = new Hero();
//Set the column id value
dto.setId(rs.getInt("id"));
//Set the value of column name
dto.setName(rs.getString("name"));
//
selectedHero = dto;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
return selectedHero;
}
/**
*Method to update Hero that matches id received in 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();
}
}
}
/**
*Method to delete Hero that matches id received by argument
*
* @param id id of the hero you want to erase
*/
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();
}
}
}
/**
*Method to INSERT new Hero with id and name received as arguments
*
* @param hero
*/
public void createHero(Hero hero) throws ClassNotFoundException, SQLException {
Connection conn = null;
try {
conn = getConnection();
String sql = "INSERT INTO tutorial.heroes VALUES(?, ?)";
//Object creation for executing SQL statements
PreparedStatement pstmt = conn.prepareStatement(sql);
//Set the id received as an argument in the placeholder.
pstmt.setInt(1, hero.getId());
pstmt.setString(2, hero.getName());
//Get the execution result of SQL statement (value received from DB)
pstmt.executeUpdate();
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
}
}
HeroController class
Create a REST API. I created the following five. --GetHeroes returns all heroes --getHero to return the hero associated with id --Create a new hero create --Delete delete hero --Update hero information update
The data received according to the tutorial is set to 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 {
/**
*Method to receive all heroes from DAO class
*
* @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;
}
/**
*Method to receive hero associated with id from DAO class
*
* @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;
}
/**
*Method to INSERT with received id and name in DAO class
*
* @param newHero
* @return hero
*/
@PostMapping("/")
public Hero create(@RequestBody Hero newHero) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
dao.createHero(newHero);
return newHero;
}
/**
*Method to DELETE hero associated with id in DAO class
*
* @param id
*/
@DeleteMapping("/{id}")
public void delete(@PathVariable Integer id) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
dao.deleteHero(id);
}
/**
*Method to UPDATE hero associated with id in DAO class
*
* @param updatedHero
*/
@PutMapping("/")
public Hero update(@RequestBody Hero updatedHero) throws SQLException, ClassNotFoundException {
HeroDAO dao = new HeroDAO();
dao.updateHero(updatedHero);
return updatedHero;
}
}
For security reasons, ajax etc. can only get resources from the same origin by SOP. Since the port numbers are different between Angular and Spring Boot this time, it is necessary to enable CORS in order to release the SOP only between trusted origins.
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("/*")
//Specify the port number to allow(Angular side)
.allowedOrigins("http://localhost:3000")
//List of allowed methods
.allowedMethods("GET", "POST", "DELETE", "PUT")
//Allow headers
.allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept")
.allowCredentials(false).maxAge(3600);
}
}
Let's run TutorialApplication and Angular. You can confirm that the API is called and the DB is being operated.
In order to understand what the web application looks like, I made an exchange using Angular, which is closely related to Ionic, as the front end, Spring Boot as the back end, and PostgreSQL as the database. ..
Recommended Posts