CRUD-Beispiel mit Spring Boot, REST und AngularJS
1. Das Zweck des Artikel
Im Artikel werde ich Sie bei der Erstellung einer einfachen Applikation anleiten, die die Technologies Spring Boot, Rest und AngularJS kombiniert. Zuerst können Sie die Applikation vorschauen, die wir implementieren werden:
AngularJS ist eine Open-Source-Code Bibliothek und basiert auf Javascript, und hilft Ihnen bei der Aufbau der Applikation Single Page . In der Unterricht werde ich eine Seite erstellen und die Seite zeigt die Liste von Mitarbeiter an, gleichzeitig erlaubt Sie, die Mitarbeiter einzufügen, zu löschen und bearbeiten.
Die Fragen werden in diese Unterricht erwähnt werden:
- Eine ApplikationSpring Boot erstellen.
- Die REST API mit der Funktionen erstellen: die Daten abfragen, erstellen, ändern und löschen.
- AngularJS ruft auf REST API auf um die Daten abzufragen und die Daten auf die Interface anzuzeigen. AngularJS ruft auf REST API auf um die Daten zu löschen, erstellen und bearbeiten.
In der letzten Unterricht werde ich die Applikation laufen und den Operationsgrundsatz von AngularJS in jeder bestimmten Funktion erklären.
2. Das Projekt Spring Boot erstellen
Auf Eclipse erstelen Sie ein Projekt Spring Boot:
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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.o7planning</groupId>
<artifactId>SpringBootAngularJS</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringBootAngularJS</name>
<description>Spring Boot + AngularJS</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
spring.thymeleaf.cache=false
SpringBootAngularJsApplication.java
package org.o7planning.sbangularjs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootAngularJsApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAngularJsApplication.class, args);
}
}
3. Model, DAO
Employee.java
package org.o7planning.sbangularjs.model;
public class Employee {
private Long empId;
private String empNo;
private String empName;
private String position;
public Employee() {
}
public Employee(EmployeeForm empForm) {
this.empId = empForm.getEmpId();
this.empNo = empForm.getEmpNo();
this.empName = empForm.getEmpName();
this.position = empForm.getPosition();
}
public Employee(Long empId, String empNo, String empName, String position) {
this.empId = empId;
this.empNo = empNo;
this.empName = empName;
this.position = position;
}
public Long getEmpId() {
return empId;
}
public void setEmpId(Long empId) {
this.empId = empId;
}
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
EmployeeForm.java
package org.o7planning.sbangularjs.model;
public class EmployeeForm {
private Long empId;
private String empNo;
private String empName;
private String position;
public Long getEmpId() {
return empId;
}
public void setEmpId(Long empId) {
this.empId = empId;
}
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
EmployeeDAO.java
package org.o7planning.sbangularjs.dao;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.o7planning.sbangularjs.model.Employee;
import org.o7planning.sbangularjs.model.EmployeeForm;
import org.springframework.stereotype.Repository;
@Repository
public class EmployeeDAO {
private static final Map<Long, Employee> empMap = new HashMap<Long, Employee>();
static {
initEmps();
}
private static void initEmps() {
Employee emp1 = new Employee(1L, "E01", "Smith", "Clerk");
Employee emp2 = new Employee(2L, "E02", "Allen", "Salesman");
Employee emp3 = new Employee(3L, "E03", "Jones", "Manager");
empMap.put(emp1.getEmpId(), emp1);
empMap.put(emp2.getEmpId(), emp2);
empMap.put(emp3.getEmpId(), emp3);
}
public Long getMaxEmpId() {
Set<Long> keys = empMap.keySet();
Long max = 0L;
for (Long key : keys) {
if (key > max) {
max = key;
}
}
return max;
}
public Employee getEmployee(Long empId) {
return empMap.get(empId);
}
public Employee addEmployee(EmployeeForm empForm) {
Long empId= this.getMaxEmpId()+ 1;
empForm.setEmpId(empId);
Employee newEmp = new Employee(empForm);
empMap.put(newEmp.getEmpId(), newEmp);
return newEmp;
}
public Employee updateEmployee(EmployeeForm empForm) {
Employee emp = this.getEmployee(empForm.getEmpId());
if(emp!= null) {
emp.setEmpNo(empForm.getEmpNo());
emp.setEmpName(empForm.getEmpName());
emp.setPosition(empForm.getPosition());
}
return emp;
}
public void deleteEmployee(Long empId) {
empMap.remove(empId);
}
public List<Employee> getAllEmployees() {
Collection<Employee> c = empMap.values();
List<Employee> list = new ArrayList<Employee>();
list.addAll(c);
return list;
}
}
4. Controller, Rest Controller
MainController.java
package org.o7planning.sbangularjs.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MainController {
@RequestMapping("/")
public String welcome() {
return "index";
}
}
MainRESTController.java
package org.o7planning.sbangularjs.controller;
import java.util.List;
import org.o7planning.sbangularjs.dao.EmployeeDAO;
import org.o7planning.sbangularjs.model.Employee;
import org.o7planning.sbangularjs.model.EmployeeForm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MainRESTController {
@Autowired
private EmployeeDAO employeeDAO;
// URL:
// http://localhost:8080/SomeContextPath/employees
// http://localhost:8080/SomeContextPath/employees.xml
// http://localhost:8080/SomeContextPath/employees.json
@RequestMapping(value = "/employees", //
method = RequestMethod.GET, //
produces = { MediaType.APPLICATION_JSON_VALUE, //
MediaType.APPLICATION_XML_VALUE })
@ResponseBody
public List<Employee> getEmployees() {
List<Employee> list = employeeDAO.getAllEmployees();
return list;
}
// URL:
// http://localhost:8080/SomeContextPath/employee/{empId}
// http://localhost:8080/SomeContextPath/employee/{empId}.xml
// http://localhost:8080/SomeContextPath/employee/{empId}.json
@RequestMapping(value = "/employee/{empId}", //
method = RequestMethod.GET, //
produces = { MediaType.APPLICATION_JSON_VALUE, //
MediaType.APPLICATION_XML_VALUE })
@ResponseBody
public Employee getEmployee(@PathVariable("empId") Long empId) {
return employeeDAO.getEmployee(empId);
}
// URL:
// http://localhost:8080/SomeContextPath/employee
// http://localhost:8080/SomeContextPath/employee.xml
// http://localhost:8080/SomeContextPath/employee.json
@RequestMapping(value = "/employee", //
method = RequestMethod.POST, //
produces = { MediaType.APPLICATION_JSON_VALUE, //
MediaType.APPLICATION_XML_VALUE })
@ResponseBody
public Employee addEmployee(@RequestBody EmployeeForm empForm) {
System.out.println("(Service Side) Creating employee with empNo: " + empForm.getEmpNo());
return employeeDAO.addEmployee(empForm);
}
// URL:
// http://localhost:8080/SomeContextPath/employee
// http://localhost:8080/SomeContextPath/employee.xml
// http://localhost:8080/SomeContextPath/employee.json
@RequestMapping(value = "/employee", //
method = RequestMethod.PUT, //
produces = { MediaType.APPLICATION_JSON_VALUE, //
MediaType.APPLICATION_XML_VALUE })
@ResponseBody
public Employee updateEmployee(@RequestBody EmployeeForm empForm) {
System.out.println("(Service Side) Editing employee with Id: " + empForm.getEmpId());
return employeeDAO.updateEmployee(empForm);
}
// URL:
// http://localhost:8080/SomeContextPath/employee/{empId}
@RequestMapping(value = "/employee/{empId}", //
method = RequestMethod.DELETE, //
produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
@ResponseBody
public void deleteEmployee(@PathVariable("empId") Long empId) {
System.out.println("(Service Side) Deleting employee with Id: " + empId);
employeeDAO.deleteEmployee(empId);
}
}
5. Javascript, Css, View
index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.js"></script>
<script th:src="@{/main.js}"></script>
<link th:href="@{/main.css}" rel="stylesheet" />
<head>
<body ng-app="EmployeeManagement" ng-controller="EmployeeController">
<h3>
CRUD: Spring Boot + Rest + AngularJS
</h3>
<form ng-submit="submitEmployee()">
<table border="0">
<tr>
<td>Emp Id</td>
<td>{{employeeForm.empId}}</td>
</tr>
<tr>
<td>Emp No</td>
<td><input type="text" ng-model="employeeForm.empNo" /></td>
</tr>
<tr>
<td>Emp Name</td>
<td><input type="text" ng-model="employeeForm.empName" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit" class="blue-button" />
</td>
</tr>
</table>
</form>
<br/>
<a class="create-button" ng-click="createEmployee()">Create Employee</a>
<table border="1">
<tr>
<th>Emp Id</th>
<th>Emp No</th>
<th>Emp Name</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<!-- $scope.employees -->
<tr ng-repeat="employee in employees">
<td> {{ employee.empId }}</td>
<td> {{ employee.empNo }}</td>
<td >{{ employee.empName }}</td>
<td>
<a ng-click="editEmployee(employee)" class="edit-button">Edit</a>
</td>
<td>
<a ng-click="deleteEmployee(employee)" class="delete-button">Delete</a>
</td>
</tr>
</table>
</body>
</html>
main.css
table {
border-collapse: collapse;
}
table td, th {
padding: 5px;
}
.create-button {
color: blue;
cursor: pointer;
padding: 5px;
}
.edit-button {
padding: 2px 5px;
background: #25A6E1;
cursor: pointer;
}
.delete-button {
padding: 2px 5px;
background: #CD5C5C;
cursor: pointer;
}
main.js
var app = angular.module("EmployeeManagement", []);
// Controller Part
app.controller("EmployeeController", function($scope, $http) {
$scope.employees = [];
$scope.employeeForm = {
empId: 1,
empNo: "",
empName: ""
};
// Now load the data from server
_refreshEmployeeData();
// HTTP POST/PUT methods for add/edit employee
// Call: http://localhost:8080/employee
$scope.submitEmployee = function() {
var method = "";
var url = "";
if ($scope.employeeForm.empId == -1) {
method = "POST";
url = '/employee';
} else {
method = "PUT";
url = '/employee';
}
$http({
method: method,
url: url,
data: angular.toJson($scope.employeeForm),
headers: {
'Content-Type': 'application/json'
}
}).then(_success, _error);
};
$scope.createEmployee = function() {
_clearFormData();
}
// HTTP DELETE- delete employee by Id
// Call: http://localhost:8080/employee/{empId}
$scope.deleteEmployee = function(employee) {
$http({
method: 'DELETE',
url: '/employee/' + employee.empId
}).then(_success, _error);
};
// In case of edit
$scope.editEmployee = function(employee) {
$scope.employeeForm.empId = employee.empId;
$scope.employeeForm.empNo = employee.empNo;
$scope.employeeForm.empName = employee.empName;
};
// Private Method
// HTTP GET- get all employees collection
// Call: http://localhost:8080/employees
function _refreshEmployeeData() {
$http({
method: 'GET',
url: '/employees'
}).then(
function(res) { // success
$scope.employees = res.data;
},
function(res) { // error
console.log("Error: " + res.status + " : " + res.data);
}
);
}
function _success(res) {
_refreshEmployeeData();
_clearFormData();
}
function _error(res) {
var data = res.data;
var status = res.status;
var header = res.header;
var config = res.config;
alert("Error: " + status + ":" + data);
}
// Clear the form
function _clearFormData() {
$scope.employeeForm.empId = -1;
$scope.employeeForm.empNo = "";
$scope.employeeForm.empName = ""
};
});
6. Den Operationsgrundsatz erklären
OK, jetzt können Sie die Applikation laufen und sehen wie AngularJS in jeder bestimmten Funktion
Die Funktion von der Anzeige der Mitarbeitersliste
Wenn die Webseite läuft, wird AngularJS auf REST API aufrufen um die Liste von Mitarbeiter zu entnehmen. Die Daten wird auf die Variable $scope.employees gelagert. Und AngularJS wird sie in die Interface anzeigen. Wenn die Daten von $scope.employees ändert, wird AngularJS automatically die Interface aktualisieren.
AngularJS ruft auf REST API auf um die Liste der Mitarbeiter (Employee) zu nehmen und die genommenen Daten in der Variable $scope.employees zu lagern.
// Private Method
// HTTP GET- get all employees collection
// Call: http://localhost:8080/employees
function _refreshEmployeeData() {
$http({
method: 'GET',
url: '/employees'
}).then(
function(res) { // success
$scope.employees = res.data;
},
function(res) { // error
console.log("Error: " + res.status + " : " + res.data);
}
);
}
.....
AngularJS zeigt die Daten in der Variable $scope.employees in die Interface an:
<table border="1">
<tr>
<th>Emp Id</th>
<th>Emp No</th>
<th>Emp Name</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<!-- $scope.employees -->
<tr ng-repeat="employee in employees">
<td> {{ employee.empId }}</td>
<td> {{ employee.empNo }}</td>
<td >{{ employee.empName }}</td>
<td>
<a ng-click="editEmployee(employee)" class="edit-button">Edit</a>
</td>
<td>
<a ng-click="deleteEmployee(employee)" class="delete-button">Delete</a>
</td>
</tr>
</table>
Die Funktion zur Bearbeitung der Information von Mitarbeiter:
AngularJS kann zweiseitig die Daten zwischen Model und View binden (two-way binding). D.h wenn der Benutzer die Daten auf View eingibt, wird diese Daten automatisch in Model aktualisiert werden und umgekehrt wenn die Daten auf Model ändert, wird es auf View angezeigt.
AngularJS verwendet das Attribut (attribute) ng-model zur die zweiseitige Bindung (2-way binding) zwischen Model und View:
<form ng-submit="submitEmployee()">
<table border="0">
<tr>
<td>Emp Id</td>
<td>{{employeeForm.empId}}</td>
</tr>
<tr>
<td>Emp No</td>
<td><input type="text" ng-model="employeeForm.empNo" /></td>
</tr>
<tr>
<td>Emp Name</td>
<td><input type="text" ng-model="employeeForm.empName" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit" class="blue-button" />
</td>
</tr>
</table>
</form>
Der Benutzer klickt auf den Button "Edit", und die Funktion $scope.editEmployee wird aufgeruft
<a ng-click="editEmployee(employee)" class="edit-button">Edit</a>
Javascript:
// JavaScript: When user Click to Edit button:
$scope.editEmployee = function(employee) {
$scope.employeeForm.empId = employee.empId;
$scope.employeeForm.empNo = employee.empNo;
$scope.employeeForm.empName = employee.empName;
};
// SAVE !!
// HTTP POST/PUT methods for add/edit employee
// Call: http://localhost:8080/employee
$scope.submitEmployee = function() {
var method = "";
var url = "";
if ($scope.employeeForm.empId == -1) {
method = "POST";
url = '/employee';
} else {
method = "PUT";
url = '/employee';
}
$http({
method: method,
url: url,
data: angular.toJson($scope.employeeForm),
headers: {
'Content-Type': 'application/json'
}
}).then(_success, _error);
};
Die Funktion von der Löschung der Mitarbeiter (Employee):
Um einen Mitarbeiter (Employee) zu löschen, ruft AngularJS auf REST API auf um die Löschung eines Mitarbeiter zu anfordern. Wenn erfolgreich, wird es auf REST API weiter aufrufen um die Liste der Mitarbeiter abzufragen und in die Interface anzuzeigen.
// HTTP DELETE- delete employee by Id
// Call: http://localhost:8080/employee/{empId}
$scope.deleteEmployee = function(employee) {
$http({
method: 'DELETE',
url: '/employee/' + employee.empId
}).then(_success, _error);
};
.....
function _success(res) {
_refreshEmployeeData();
_clearFormData();
}
function _error(res) {
var data = res.data;
var status = res.status;
var header = res.header;
var config = res.config;
alert("Error: " + status + ":" + data);
}
7. Bonus: Die Funktion success und error
Im AngularJS gibt es 2 Maßnahmen um die Funktion success und error zu benutzen:
- Die Funktion success & error mit einem Parameter
- Die Funktion success & error mit 4 Paramater
- success & error with 1 parameter:
$http.get('/someURL').then(
// Success
function(response) {
var data = response.data;
var status = response.status;
var header = response.header;
var config = response.config;
// ...
},
// Error
function(response) {
var data = response.data;
var status = response.status;
var header = response.header;
var config = response.config;
// ...
}
);
- success & error with 4 parameters:
$http.get('/someURL')
// Success
.success(
function(data, status, header, config) {
// ...
}
)
// Error
.error(
function(data, status, header, config) {
// error handler
}
);
Anleitungen Spring Boot
- Installieren Sie die Spring Tool Suite für Eclipse
- Die Anleitung zum Sping für den Anfänger
- Die Anleitung zum Spring Boot für den Anfänger
- Gemeinsame Eigenschaften von Spring Boot
- Die Anleitung zu Spring Boot und Thymeleaf
- Die Anleitung zu Spring Boot und FreeMarker
- Die Anleitung zu Spring Boot und Groovy
- Die Anleitung zu Spring Boot und Mustache
- Die Anleitung zu Spring Boot und JSP
- Die Anleitung zu Spring Boot, Apache Tiles, JSP
- Verwenden Sie Logging im Spring Boot
- Anwendungsüberwachung mit Spring Boot Actuator
- Erstellen Sie eine mehrsprachige Webanwendung mit Spring Boot
- Verwenden Sie im Spring Boot mehrere ViewResolver
- Verwenden Sie Twitter Bootstrap im Spring Boot
- Die Anleitung zu Spring Boot Interceptor
- Die Anleitung zu Spring Boot, Spring JDBC und Spring Transaction
- Die Anleitung zu Spring JDBC
- Die Anleitung zu Spring Boot, JPA und Spring Transaction
- Die Anleitung zu Spring Boot und Spring Data JPA
- Die Anleitung zu Spring Boot, Hibernate und Spring Transaction
- Spring Boot, JPA und H2-Datenbank integrieren
- Die Anleitung zu Spring Boot und MongoDB
- Verwenden Sie mehrere DataSource mit Spring Boot und JPA
- Verwenden Sie mehrere DataSource mit Spring Boot und RoutingDataSource
- Erstellen Sie eine Login-Anwendung mit Spring Boot, Spring Security, Spring JDBC
- Erstellen Sie eine Login-Anwendung mit Spring Boot, Spring Security, JPA
- Erstellen Sie eine Benutzerregistrierungsanwendung mit Spring Boot, Spring Form Validation
- Beispiel für OAuth2 Social Login im Spring Boot
- Führen Sie geplante Hintergrundaufgaben in Spring aus
- CRUD Restful Web Service Beispiel mit Spring Boot
- Beispiel Spring Boot Restful Client mit RestTemplate
- CRUD-Beispiel mit Spring Boot, REST und AngularJS
- Sichere Spring Boot RESTful Service mit Basic Authentication
- Sicherer Spring Boot RESTful Service mit Auth0 JWT
- Beispiel Upload file mit Spring Boot
- Beispiel Download File mit Spring Boot
- Das Beispiel: Spring Boot File Upload mit jQuery Ajax
- Das Beispiel File Upload mit Spring Boot und AngularJS
- Erstellen Sie eine Warenkorb-Webanwendung mit Spring Boot, Hibernate
- Die Anleitung zu Spring Email
- Erstellen Sie eine einfache Chat-Anwendung mit Spring Boot und Websocket
- Stellen Sie die Spring Boot-Anwendung auf Tomcat Server bereit
- Stellen Sie die Spring Boot-Anwendung auf Oracle WebLogic Server bereit
- Installieren Sie ein kostenloses Let's Encrypt SSL-Zertifikat für Spring Boot
- Konfigurieren Sie Spring Boot so, dass HTTP zu HTTPS umgeleitet wird
Show More