在这个页面上,我们将把Spring Boot RESTful 服务与 Angular 8 集成,逐步执行创建、读取、更新和删除(CRUD)操作。Angular 是最流行的开源 Web 应用程序框架之一,而 Spring Boot 使您可以轻松地创建可以“直接运行”的独立、生产就绪的应用程序。
您将构建什么
在这个演示中,您将从头开始创建 Spring Boot RESTful API(后端)和 Angular 8 用户界面(前端)来执行以下操作:
- 添加学生
- 查看学生名单
- 编辑学生
- 删除学生
为了更容易理解,我们将本教程分为两部分:
- 后端→ 使用 Spring Boot 创建 REST 端点并使用 Spring Data JPA 访问数据库。
- 前端→ 使用 Angular 8 创建用户界面服务(网页)。
先决条件
我们在创建这个 Spring Boot + Angular 8 CRUD 应用程序时使用了以下技术。
- 后端
- Spring Boot 2.1.9.RELEASE
- Java 8
- Spring Data JPA
- MySQL 数据库
- 前端
- Nodejs v10.16.2
- npm 6.9.0
- Angular CLI 8.3.3
让我们开始真正的编码……
1.后端-API开发
我们将创建一个公开 GET、ADD、EDIT、DELETE API 的 Spring Boot 应用程序,以便客户端可以使用它。
1.1 需要依赖
将以下依赖项添加到您的pom.xml文件中。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.websparrow</groupId>
<artifactId>AgularDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Demo</name>
<description>Demo project for Spring Boot+ Angular 8</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.2 项目结构
我们在 STS 4 IDE 中的应用程序的最终项目结构将如下所示:
1.3 创建数据库
打开您的 MySQL 数据库并通过以下命令创建一个新数据库。
#create database <database-name-of-your-choice>;
CREATE DATABASE spring_angular;
您还可以使用之前创建的数据库。
不用担心创建表,Spring Data JPA 会管理它。
1.4 应用程序.properties
在application.properties文件中设置您的数据库连接字符串、服务器端口、上下文路径等。
application.properties
# Set application port and context path
server.servlet.context-path=/api
server.port=8080
# MySQL database connection strings
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/spring_angular
# JPA property settings
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true
1.5 实体
创建一个Student
包含学生所有属性的类。
Student.java
package org.websparrow.entity;
@Entity
@Table(name = "student")
public class Student implements Serializable {
private static final long serialVersionUID = 1681261145191719508L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String firstName;
private String lastName;
private String email;
// Generate Getters and Setters...
}
1.6 存储库
该StudentRepository
接口将扩展JpaRepository
公开 CRUD 方法的接口。
package org.websparrow.repository;
@Repository
public interface StudentRepository extends JpaRepository<Student, Integer> {
}
1.7 数据访问层(DAO)
StudentDAO
类将自动装配StudentRepository
接口以在数据库级别执行操作。
package org.websparrow.dao;
@Repository
public class StudentDAO {
@Autowired
private StudentRepository studentRepository;
public List<Student> get() {
return studentRepository.findAll();
}
public Student save(Student student) {
return studentRepository.save(student);
}
public void delete(int id) {
studentRepository.deleteById(id);
}
}
1.8 服务
服务层实现业务逻辑并从DAO对象调用方法。
StudentService.java
package org.websparrow.service;
@Service
public class StudentService {
@Autowired
private StudentDAO studentDAO;
public List<Student> get() {
return studentDAO.get();
}
public Student save(Student student) {
return studentDAO.save(student);
}
public void delete(int id) {
studentDAO.delete(id);
}
}
1.9 型号
Response
模型类负责以有组织的格式显示 API 响应。
Response.java
package org.websparrow.model;
public class Response {
// Generate Getters and Setters...
private Object data;
private Date date;
public Response(Object data, Date date) {
super();
this.data = data;
this.date = date;
}
}
1.10 控制器
创建StudentController
将公开以下端点的类:
1. /api/student :获取学生列表
2. /api/student : POST添加一个新学生
3. /api/student : PUT更新现有学生
4. /api/student : DELETE删除学生
package org.websparrow.controller;
@RestController(value = "/student")
public class StudentController {
@Autowired
private StudentService studentService;
@GetMapping
public ResponseEntity<Response> get() {
return ResponseEntity.status(HttpStatus.OK)
.body(new Response(studentService.get(), new Date()));
}
@PostMapping
public ResponseEntity<Response> save(@RequestBody Student student) {
return ResponseEntity.status(HttpStatus.OK)
.body(new Response(studentService.save(student), new Date()));
}
@PutMapping
public ResponseEntity<Response> update(@RequestBody Student student) {
return ResponseEntity.status(HttpStatus.OK)
.body(new Response(studentService.save(student), new Date()));
}
@DeleteMapping
public ResponseEntity<Response> delete(@RequestParam("id") int id) {
studentService.delete(id);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response(true, new Date()));
}
}
1.11 Web MVC 配置
当我们尝试在后端项目之外使用 JavaScript 使用 API 时,Web 浏览器会发出有关CORS的警告。因此,为了处理这个问题,我们允许所有来源与我们的 API 连接。
package org.websparrow.config;
@Configuration
@EnableWebMvc
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET",
"HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH");
WebMvcConfigurer.super.addCorsMappings(registry);
}
}
最后,REST API 的开发完成并可以使用了。
2.前端-UI开发
用户界面是人类可以与计算机(应用程序)交互的地方。Angular 8 用于创建用户界面并将使用上述 API。
要进行前端开发,您必须按照以下步骤操作:
1.根据您的操作系统下载 Nodejs 表单,链接如下:
2.安装 Nodejs 后安装 Angular CLI:它是一个命令行工具,用于在您的机器上全局构建、搭建和安装 angular-cli:
npm install -g @angular/cli
3.通过键入以下命令创建一个 Angular 项目。它将创建一个骨架项目结构,如下所示:
ng new springboot-angular8-ui
4.让我们进入新创建的 Angular 项目:
cd springboot-angular8-ui
2.1 项目结构
在 VS Code 中通过命令创建的 Angular 项目的基本骨架ng new springboot-angular8-ui
如下所示:
让我们讨论一下上述结构中的一些主要文件和目录:
2.1.1 package.json
package.json文件是 Angular/Node 系统的主要构建块。它是包含项目元数据和依赖项的清单文件。NPM使用package.json文件来管理应用程序、依赖项和打包。您可以使用命令创建上述文件npm init
,这将是我们下一篇文章的一部分。
2.1.2 tsconfig.json
tsconfig.json文件指导编译器生成 JavaScript 文件。它指定编译项目所需的根文件和编译器选项。
2.1.3 angular.json
该文件提供有关 Angular 应用程序环境的信息,该环境告诉系统在构建项目时替换哪些文件。它还描述了将项目的构建放在哪里以及将使用什么样的编译过程ex: aot
或jit
.
2.1.4 源
此文件夹包含根级应用程序项目。
2.1.5 节点模块
它为整个项目提供npm包。
2.1.6 package-lock.json
当npm修改node_modules树或package.json时,会自动创建此文件。它描述了依赖关系树,以便保证队友、部署和持续集成安装完全相同的依赖关系。因此,用户不需要将node_modules推送到存储库。
2.2 接口
创建Student
与数据库具有相同字段的接口:
ng g i interface/student
student.interface.ts
export interface Student {
id: number,
firstName: string,
lastName: string,
email: string
}
2.3 服务
现在让我们创建一个将使用 REST API 的服务。HttpClient
用于与后端服务通信。在项目结构中使用以下命令。
ng g s services/web
此命令将创建一个可注入服务,您将从中使用 REST API。
HttpClientModule
在app.module.ts中导入。该HttpClient
服务包含在其中,HttpClientModule
因此我们需要先导入它以启动XSRFrequest
.
import { HttpClientModule } from "@angular/common/http";
添加HttpClientModule
内部导入:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
与后端服务实现基于 REST 的通信。为此,您需要使用为浏览器公开的Angular 应用程序提供HTTPHttpClient
客户端 API的包。@angular/common/http
XMLHttpRequest
web.service.ts
import { environment } from "../../environments/environment";
import { Observable } from 'rxjs';
import { Student } from '../interface/student.interface';
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
@Injectable()
export class WebService {
constructor(private httpClient: HttpClient) { }
serverUrl: string = "http://localhost:8080/api/"
get(url: string): Observable<any> {
return this.httpClient.get(this.serverUrl + url);
}
post(url: string, data: Student): Observable<any> {
return this.httpClient.post(this.serverUrl + url, data);
}
put(url: string, data: Student): Observable<any> {
return this.httpClient.put(this.serverUrl + url, data);
}
delete(url: string, data: Student): Observable<any> {
return this.httpClient.delete(this.serverUrl + url, { params: { id: data.id + "" } });
}
}
在app.module.ts中向提供者添加服务。您必须需要使用提供程序配置注入器,否则它将不知道如何创建依赖项。
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule
],
providers: [WebService],
bootstrap: [AppComponent]
})
export class AppModule { }
2.4 组件
组件是 Angular 应用程序的基本 UI 构建块。它控制应用程序的视图。创建student-view
将显示学生列表的组件:
ng g c student-view
通过使用这个命令,你的大部分工作都是由 Angular CLI 完成的,你不需要在app.module.ts中声明你的组件
2.4.1 设计HTML页面
现在让我们设计 HTML 页面。Bootstrap CSS 用于在此应用程序中进行样式设置,因此您需要安装以下软件包:
npm install bootstrap –save
如果您不想在应用程序中包含 Bootstrap CSS,则可以跳过此步骤。
在样式部分内的angular.json文件中添加bootstrap.min.css文件。
angular.json
"styles": [
"src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
]
student-view.component.html
<div class="container">
<div class="row">
<h1 style="text-align: center;">Spring Boot + Angular 8 CRUD Example</h1>
</div>
<div class="row">
<form [formGroup]="myForm" (ngSubmit)="submitForm(myForm)">
<div class="form-row align-items-center">
<div class="col-auto">
<label class="sr-only" for="inlineFormInput">First Name</label>
<input type="text" class="form-control mb-2" id="inlineFormInput" placeholder="First name"
formControlName="firstName">
</div>
<div class="col-auto">
<label class="sr-only" for="inlineFormInputGroup">Last Name</label>
<input type="text" class="form-control" id="inlineFormInput" placeholder="Last name"
formControlName="lastName">
</div>
<div class="col-auto">
<label class="sr-only" for="inlineFormInputGroup">Email</label>
<input type="text" class="form-control" id="inlineFormInput" placeholder="Email"
formControlName="email">
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-2" [disabled]="!myForm.valid">Save</button>
</div>
</div>
</form>
</div>
<div class="row">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Email</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let student of usersList; let i=index">
<th scope="row">{{i+1}}</th>
<td>{{student.firstName}}</td>
<td>{{student.lastName}}</td>
<td>{{student.email}}</td>
<td>
<span style="margin-right: 10px"><button (click)="edit(student)"
class="btn btn-primary mb-2">Edit</button> </span>
<span><button (click)="delete(student)" class="btn btn-primary mb-2">Delete</button></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
编写组件以执行我们之前讨论的操作:
student-view.component.ts
import { Component, OnInit } from '@angular/core';
import { Student } from '../interface/student.interface';
import { FormGroup, FormBuilder, FormControl, Validators, Form } from '@angular/forms';
import { WebService } from '../sevices/web.service';
@Component({
selector: 'app-student-view',
templateUrl: './student-view.component.html',
styleUrls: ['./student-view.component.css']
})
export class StudentViewComponent implements OnInit {
ngOnInit(): void {
this.createForm();
this.getData();
}
url: string = 'student';
title = 'Spring Boot + Angular 8 CRUD Example';
usersList: Array<Student>
student: Student = undefined
myForm: FormGroup;
constructor(private webService: WebService, private formBuilder: FormBuilder) { }
private createForm() {
this.myForm = this.formBuilder.group({
firstName: new FormControl(this.student ? this.student.firstName : '', Validators.required),
lastName: new FormControl(this.student ? this.student.lastName : '', Validators.required),
email: new FormControl(this.student ? this.student.email : '', Validators.required)
});
}
private submitForm(data: FormGroup) {
if (data.valid)
this.addStudent(data.value)
}
getData(): void {
this.webService.get(this.url).subscribe(res => {
let response = JSON.parse(JSON.stringify(res))
this.usersList = response.data
})
}
addStudent(student: Student): void {
if (this.student)
student.id = this.student.id
this.webService.post(this.url, student).subscribe(res => {
let response = JSON.parse(JSON.stringify(res))
this.getData()
this.myForm.reset()
this.student = undefined
}, error => {
})
}
edit(student: Student): void {
this.student = student
this.myForm.controls['firstName'].setValue(this.student.firstName)
this.myForm.controls['lastName'].setValue(this.student.lastName)
this.myForm.controls['email'].setValue(this.student.email)
}
delete(student: Student): void {
this.webService.delete(this.url, student).subscribe(res => {
let data = JSON.parse(JSON.stringify(res))
this.getData()
}, error => {
})
}
}
因为我们在我们的应用程序中使用表单。所以,我们需要用和更新我们的app.module.ts。FormsModule
ReactiveFormsModule
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { HttpClientModule } from "@angular/common/http";
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StudentViewComponent } from './student-view/student-view.component';
import { WebService } from "./sevices/web.service";
@NgModule({
declarations: [
AppComponent,
StudentViewComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
AppRoutingModule
],
providers: [WebService],
bootstrap: [AppComponent]
})
export class AppModule { }
现在最后一步是使用您的选择器更新app.component.html文件StutentViewComponent
:
<app-student-view></app-student-view>
此标记将呈现您的学生视图组件。
3. 测试应用
最终完成后端(API)和前端(UI)的开发。要测试应用程序,您需要执行以下步骤:
1.启动您使用 Spring Boot 开发的后端 (API) 应用程序。
2.转到创建 Angular 项目的前端 (UI) 目录并点击以下命令:
npm install
它将安装必要的依赖项/库/模块。
3.安装模块后,使用以下命令启动前端 (UI) 应用程序:
npm start
4.现在,打开您喜欢的 Web 浏览器并点击 http://localhost:4200 URL 并执行 CRUD 操作。