aplicativo Angular com back-end Java
- #Java
- #Angular
Pré-requisitos:
Java
Angular CLI
VSCode
ngx-bootstrap
Estrutura do Projeto:
Vamos entender a estrutura do projeto para este projeto. Precisamos ter duas pastas completamente diferentes para java e angular. É sempre uma boa prática ter pastas completamente diferentes para cada um. Dessa forma, você terá uma arquitetura limpa ou qualquer outro problema relacionado à mesclagem de arquivos.
Se você observar a estrutura do projeto acima, todo o aplicativo Angular reside na pasta src/main/ui e o código Java reside na pasta src/main/java. Todos os recursos estão na pasta /src/main/resources, como propriedades, ativos estáticos, etc.
API Java
Usamos spring boot e muitas outras ferramentas, como Spring Devtools, Spring Actuator, etc. Hoje em dia, quase todos os aplicativos têm inicialização por mola e é uma estrutura baseada em Java de código aberto usada para criar um micro serviço. Ele é desenvolvido pela Pivotal Team e é usado para criar aplicativos de mola autônomos e prontos para produção.
Começamos com Spring initializr e selecionamos todas as dependências e geramos o arquivo zip.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
<version>1.4.199</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
<!-- QueryDSL -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Aqui estão o arquivo de inicialização de primavera e o controlador com duas rotas, uma com solicitação GET e outra com solicitação POST.
package com.bbtutorials.users;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class UsersApplication {
public static void main(String[] args) {
SpringApplication.run(UsersApplication.class, args);
}
}
package com.bbtutorials.users.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.bbtutorials.users.entity.Users;
import com.bbtutorials.users.links.UserLinks;
import com.bbtutorials.users.service.UsersService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@RequestMapping("/api/")
public class UsersController {
@Autowired
UsersService usersService;
@GetMapping(path = UserLinks.LIST_USERS)
public ResponseEntity<?> listUsers() {
log.info("UsersController: list users");
List<Users> resource = usersService.getUsers();
return ResponseEntity.ok(resource);
}
@PostMapping(path = UserLinks.ADD_USER)
public ResponseEntity<?> saveUser(@RequestBody Users user) {
log.info("UsersController: list users");
Users resource = usersService.saveUser(user);
return ResponseEntity.ok(resource);
}
}
Este banco de dados H2 é apenas para desenvolvimento. Ao construir este projeto para produção, você pode substituí-lo por qualquer banco de dados de sua escolha. Você pode executar este banco de dados autônomo sem seu aplicativo. Veremos como podemos configurar com o spring boot.
Primeiro, precisamos adicionar algumas propriedades ao arquivo application.properties em /src/main/resources
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
Em segundo lugar, adicione o arquivo SQL abaixo no mesmo local.
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INT PRIMARY KEY,
FIRST_NAME VARCHAR(250) NOT NULL,
LAST_NAME VARCHAR(250) NOT NULL,
EMAIL VARCHAR(250) NOT NULL
);
INSERT INTO users (ID, FIRST_NAME, LAST_NAME, EMAIL) VALUES
(1, 'first', 'last 1', 'abc1@gmail.com'),
(2, 'first', 'last 2', 'abc2@gmail.com'),
(3, 'first', 'last 3', 'abc3@gmail.com');
Em terceiro lugar, inicie o aplicativo e o Spring Boot cria esta tabela na inicialização. Depois que o aplicativo for iniciado, você poderá acessar esta URL http://localhost:8080/api/h2-console e acessar o banco de dados no navegador da web. Certifique-se de ter o mesmo URL JDBC, nome de usuário e senha do arquivo de propriedades.
Vamos adicionar os arquivos de repositório, arquivos de serviço e classes de entidade conforme abaixo e iniciar o aplicativo de inicialização de primavera.
package com.bbtutorials.users.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import lombok.Data;
@Entity
@Data
public class Users {
@Id
@Column
private long id;
@Column
@NotNull(message="{NotNull.User.firstName}")
private String firstName;
@Column
@NotNull(message="{NotNull.User.lastName}")
private String lastName;
@Column
@NotNull(message="{NotNull.User.email}")
private String email;
}
package com.bbtutorials.users.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import com.bbtutorials.users.entity.Users;
@RepositoryRestResource()
public interface UsersRepository extends JpaRepository<Users, Integer>, JpaSpecificationExecutor<Users>, QuerydslPredicateExecutor<Users> {}
package com.bbtutorials.users.service;
import java.util.List;
import org.springframework.stereotype.Component;
import com.bbtutorials.users.entity.Users;
import com.bbtutorials.users.repository.UsersRepository;
@Component
public class UsersService {
private UsersRepository usersRepository;
public UsersService(UsersRepository usersRepository) {
this.usersRepository = usersRepository;
}
public List<Users> getUsers() {
return usersRepository.findAll();
}
public Users saveUser(Users users) {
return usersRepository.save(users);
}
}
Você pode iniciar o aplicativo de duas maneiras: você pode clicar com o botão direito do mouse no UsersApplication e executá-lo como um aplicativo java ou executar as etapas a seguir.
// mvn install
mvn clean install
// run the app
java -jar target/<repo>.war
Agora o código java está sendo executado na porta 8080. Agora é hora de olhar para o aplicativo Angular. Todo o aplicativo Angular está na pasta src/main/ui. Você pode criar com este comando ng new ui. Não vou colocar todos os arquivos aqui.
Vamos ver alguns arquivos importantes aqui. Aqui está o arquivo de serviço que chama a API Java.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class AppService {
constructor(private http: HttpClient) { }
rootURL = '/api';
getUsers() {
return this.http.get(this.rootURL + '/users');
}
addUser(user: any, id: number) {
user.id = id;
return this.http.post(this.rootURL + '/user', user);
}
}
Aqui está o componente de aplicativo que se inscreve nessas chamadas e obtém os dados da API.
import { Component, OnDestroy } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { AppService } from './app.service';
import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnDestroy {
constructor(private appService: AppService) {}
title = 'angular-nodejs-example';
userForm = new FormGroup({
firstName: new FormControl('', Validators.nullValidator && Validators.required),
lastName: new FormControl('', Validators.nullValidator && Validators.required),
email: new FormControl('', Validators.nullValidator && Validators.required)
});
users: any[] = [];
userCount = 0;
destroy$: Subject<boolean> = new Subject<boolean>();
onSubmit() {
this.appService.addUser(this.userForm.value, this.userCount + 1).pipe(takeUntil(this.destroy$)).subscribe(data => {
console.log('message::::', data);
this.userCount = this.userCount + 1;
console.log(this.userCount);
this.userForm.reset();
});
}
getAllUsers() {
this.appService.getUsers().pipe(takeUntil(this.destroy$)).subscribe((users: any[]) => {
this.userCount = users.length;
this.users = users;
});
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.unsubscribe();
}
ngOnInit() {
this.getAllUsers();
}
}
Interação entre Angular e API Java
Na fase de desenvolvimento, o aplicativo Angular está sendo executado na porta 4200 com a ajuda de um servidor webpack dev e API Java em execução na porta 8080.
Deve haver alguma interação entre esses dois. Podemos fazer proxy de todas as chamadas de API para a API Java. Angular fornece um método de proxy embutido. Primeiro, precisamos definir o seguinte proxy.conf.json na pasta src/main/ui.
{
"/api": {
"target": "http://localhost:8080",
"secure": false
}
}
Se você observar o arquivo, todos os caminhos que começam com /api serão redirecionados para http://localhost:8080 onde a API Java está sendo executada. Em seguida, você precisa definir em angular.json na parte de serviço com a chave proxyConfig. Aqui está o arquivo angular.json completo.
Depois de configurado, você pode executar o aplicativo Angular na porta 4200 e a API java na 8080 ainda fazê-los funcionar juntos.
// java API (Terminal 1)
mvn clean install
java -jar target/<war file name>
// Angular app (Terminal 2)
npm start