Dies ist ein Nachdruck der README-Datei von diesem Repository.
Dies ist ein Beispiel für eine Geschäftsanwendung, die Spring Boot auf der Serverseite und AngularJS auf der Clientseite verwendet, um auf die Backend-MongoDB zuzugreifen.
Die Datenbank enthält eine Sammlung von Marken-, Modell-, Auto- und Verkaufsleistungen. Es kann diese Sammlungen hinzufügen, aktualisieren, löschen und suchen sowie die Verkaufsleistung grafisch darstellen.
Dieses Dokument enthält einen Hinweis zu den wichtigsten technischen Themen, die zum Verständnis der Anwendung erforderlich sind. Um Ihr Verständnis zu beschleunigen, sollten Sie die Spring's Guide Page Tutorials (https://spring.io/guides) durchgehen.
*Hinweis Derzeit funktionieren nicht alle Funktionen ordnungsgemäß, da in diesem Projekt die Entwicklung der Funktionen noch nicht abgeschlossen ist. * *
Installieren Sie MongoDB und starten Sie mongod im Voraus. Lassen Sie die Mongodb-Authentifizierungsfunktion nicht konfiguriert. (Es befindet sich in einem Zustand, in dem es installiert und gestartet wird, ohne etwas einzustellen.)
Git klonen dieses Projekt. Erstellen Sie ein geeignetes Verzeichnis und führen Sie den folgenden Befehl in diesem Verzeichnis aus.
$ git clone https://github.com/kazz12211/simple-mongo-crud-app.git
Führen Sie den folgenden Befehl im selben Verzeichnis aus, um die Anwendung zu starten.
$ ./mvnw spring-boot:run
Greifen Sie über Ihren Browser auf die folgende URL zu.
http://localhost:8080
Diese Anwendung ist ein Spring Boot Maven-Projekt. Abhängige Bibliotheken finden Sie in pom.xml.
RestController
Generieren Sie RestController mit der Annotation @RestController. In CRUD-Anwendungen scheint es üblich zu sein, Dateneinfügungen, Aktualisierungen, Löschungen und Suchvorgänge POST, PUT, DELETE und GET von HTTP-Anforderungen zuzuordnen.
package jp.tsubakicraft.mongocrud.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import jp.tsubakicraft.mongocrud.model.Brand;
import jp.tsubakicraft.mongocrud.service.BrandRepository;
@RestController
public class BrandController {
@Autowired
private BrandRepository repo;
@RequestMapping(value = "/api/brands/listAll", method = RequestMethod.GET)
public List<Brand> listAll() {
Sort sort = new Sort(Sort.Direction.ASC, "name");
return repo.findAll(sort);
}
@RequestMapping(value = "/api/brands", method = RequestMethod.GET)
public Page<?> listBrands(@RequestParam(value = "page", required = true) int page,
@RequestParam(value = "limit", required = true) int limit,
@RequestParam(value = "sortColumn", required = true) String column,
@RequestParam(value = "sortDir", required = true) String dir) {
Sort sort = new Sort(
new Sort.Order("asc".equalsIgnoreCase(dir) ? Sort.Direction.ASC : Sort.Direction.DESC, column));
Pageable pageRequest = new PageRequest(page, limit, sort);
Page<Brand> p = repo.findAll(pageRequest);
return p;
}
@RequestMapping(value = "/api/brands", method = RequestMethod.PUT)
public Brand updateBrand(@RequestBody Brand brand) {
Brand b = repo.findOne(brand.id);
if (b != null) {
b.name = brand.name;
repo.save(b);
}
return b;
}
@RequestMapping(value = "/api/brands", method = RequestMethod.DELETE)
public Brand deleteBrand(@RequestBody Brand brand) {
repo.delete(brand.id);
return brand;
}
@RequestMapping(value = "/api/brands", method = RequestMethod.POST)
public Brand createBrand(@RequestBody Brand brand) {
Brand b = new Brand();
b.name = brand.name;
repo.save(b);
return b;
}
}
Diese Anwendung implementiert die Page Nation-Funktion mithilfe von UI-Bootstrap in der Benutzeroberfläche. Verwenden Sie jedoch PageRequest, um Seite für Seite nach Objekten zu suchen. Um beispielsweise die Objekte der 11. bis 20. Marke zu durchsuchen, rufen Sie findAll () von PagingAndSortingRepository mit PageRequest als Argument wie folgt auf.
int page = 1;
int size = 10;
Pageable pageRequest = new PageRequest(page, size);
Page<Brand> page = repo.findAll(pageRequest);
package jp.tsubakicraft.mongocrud.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ErrorHandler {
@RequestMapping(value = "/{[path:[^\\.]*}")
public String redirect() {
return "forward:/";
}
}
in app.js
var app = angular.module("app", ['ngRoute', 'ngDialog', 'ui.bootstrap', 'chart.js']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when("/", {
controller: 'home_controller',
templateUrl: 'views/home.html'
})
.when("/brand/", {
controller: 'brand_controller',
templateUrl: 'views/brands.html'
})
.when("/newbrand/", {
controller: 'brand_controller',
templateUrl: 'views/newBrand.html'
})
.when("/model/", {
controller: 'model_controller',
templateUrl: 'views/models.html'
})
.when("/newmodel/", {
controller: 'model_controller',
templateUrl: 'views/newModel.html'
})
.when("/car/", {
controller: 'car_controller',
templateUrl: 'views/cars.html'
})
.when("/newcar/", {
controller: 'car_controller',
templateUrl: 'views/newCar.html'
})
.when("/sales/", {
controller: 'sales_controller',
templateUrl: 'views/sales.html'
})
.when("/newsales/", {
controller: 'sales_controller',
templateUrl: 'views/newSales.html'
})
.otherwise({
redirectTo: "/"
});
}]);
app.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true);
}]);
Verwenden Sie beispielsweise $ http.get (), um eine GET-Anforderung an das Stammverzeichnis / api / brand von BrandController (REST Controller) zu senden. (Siehe brand_controller.js)
app.controller("brand_controller", function($scope, $http, $location, $q, ngDialog) {
$scope.brands = [];
....
....
$scope.listBrands = function() {
$http.get("/api/brands", {params: {page: $scope.page, limit: $scope.limit, sortColumn: $scope.sortColumn, sortDir: $scope.sortDir}}).then(function(response) {
//Ich konnte die Daten normal empfangen
$scope.brands = response.data;
....
....
}, function(error) {
//HTTP-Anfrage fehlgeschlagen
....
});
};
....
....
$scope.listBrands();
});
Die Validierung kann in der HTML-Vorlage erfolgen, in dieser Anwendung jedoch im Controller. (Siehe brand_controller.js)
....
....
$scope.createBrand = function() {
if(!$scope.validateForm()) {
$http.post("/api/brands", $scope.brand).then(function(response) {
$scope.show = true;
$scope.hide = true;
$scope.hideObj = false;
$scope.showObj = false;
$scope.brandId = "";
$location.path("/brand");
}, function(error) {
$scope.error = error;
});
}
};
....
....
$scope.validateForm = function() {
$scope.validationMessages = [];
if($scope.brand.name == null || $scope.brand.name == null) {
$scope.validationMessages.push("Name is required.");
}
$scope.hasErrors = $scope.validationMessages.length > 0;
return $scope.hasErrors;
};
Bereiten Sie auf der Seite der HTML-Vorlage einen Block vor, der angezeigt werden soll, wenn ein Fehler auftritt (hasErrors of $ scope ist true).
<div class="panel panel-default">
<div class="panel-heading">ADD A BRAND</div>
<form name="brand-form">
<div ng-show="hasErrors">
<div class="alert alert-danger" role="alert">
<div ng-repeat="message in validationMessages">
<strong>{{message}}</strong></br/>
</div>
</div>
</div>
<div class="form-group">
<label for="brand-name">Name</label> <input name="brand-name"
type="text" class="form-control" ng-model="brand.name" required>
</div>
<button class="btn btn-primary" type="submit" ng-click="createBrand()">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
Save
</button>
<button class="btn btn-default" ng-click="linkTo('/brand/')">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
Cancel
</button>
</form>
</div>
Auf der UI-Bootstrap-Seite (https://angular-ui.github.io/bootstrap/) wird dies erläutert.
Code auf der Controllerseite. Geben Sie den Namen der zu sortierenden Spalte und die Sortiermethode an. (Für diese Anwendung gibt es zwei Sortiermethoden, ASC und DESC) Die Funktion sort () wird aus der HTML-Vorlage mit dem Spaltennamen als Argument aufgerufen. Wenn die als Argument übergebene Spalte mit der vorherigen Spalte identisch ist, wechseln Sie zwischen aufsteigender und absteigender Reihenfolge. Wenn sich die Spalte von der vorherigen unterscheidet, legen Sie sie in aufsteigender Reihenfolge fest und aktualisieren Sie den Spaltennamen. Suchen Sie abschließend erneut in der Datenbank. (Da es sich um eine paginierte Suche handelt, ist der durch eine Suche generierte Datenverkehr zur Datenbank gering, sodass wir erneut suchen. Wenn jedoch die Anzahl der Suchvorgänge groß ist, ist es möglicherweise besser, im Speicher zu sortieren.)
app.controller("model_controller", function($scope, $http, $location, $q, ngDialog) {
....
....
$scope.sortColumn = "name";
$scope.sortDir = "ASC";
....
....
$scope.sort = function(column) {
if($scope.sortColumn == column) {
$scope.sortDir = $scope.sortDir == "ASC" ? "DESC" : "ASC";
} else {
$scope.sortDir = "ASC";
$scope.sortColumn = column;
}
$scope.listModels();
};
});
Geben Sie auf der Seite der HTML-Vorlage die Controller-Funktion an, die ausgeführt werden soll, wenn der Mausklick auf die Spaltenüberschrift ausgeführt wird.
<th class="col-xs-3 col-ms-3 col-md-3 col-lg-4 sortableTableColumn" ng-click="sort('name')">Name</th>
Wenn Sie eine Bibliothek wie DataTable.js verwenden, die Funktionen wie Paginierung und Sortierung von in einer Tabelle angezeigten Daten enthält, ist dies einfacher, wenn Sie eine Anwendung entwickeln. Beachten Sie bitte.
Bootstrap Dies ist eine CSS-Überschreibungsmethode, die jedoch nicht auf CSS beschränkt ist. Der folgende Code überschreibt den Stil der Bootstrap-Navigationsleiste. Stellen Sie den Teil der HTML-Datei, der das CSS lädt, so ein, dass er nach dem Bootstrap-CSS geladen wird.
.navbar {
margin-bottom: 1px;
border-radius: 0px;
}
.navbar-inverse {
background-color: rgb(12, 140, 213);
border-color: rgb(12,140,213);
}
.navbar-inverse .navbar-brand {
color: #fff;
}
.navbar-inverse .navbar-nav>li>a {
color: #fff;
}
MongoRepository ist eine Unterschnittstelle von PagingAndSortingRepository mit Funktionen zum Einfügen, Aktualisieren, Löschen, Suchen und Paginieren von Daten.
Der Code, der die MongoDB-Datenbankauswahl festlegt.
package jp.tsubakicraft.mongocrud.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
@Configuration
public class MongoConfiguration extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() {
return "simplecrud";
}
@Override
public Mongo mongo() throws Exception {
return new MongoClient("127.0.0.1", 27017);
}
}
Beispiele für Marken- und Modellentitäten. Die Model-Entität verweist auf die Brand-Entität mit der Annotation @DBRef. In diesem Fall werden bei der Suche nach Modell auch die referenzierten Marken gesucht und kombiniert.
jp.tsubakicraft.mongocrud.model.Brand.java
package jp.tsubakicraft.mongocrud.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection="brand")
public class Brand {
@Id public String id;
public String name;
public Brand(String id) {
this.id = id;
}
public Brand() {
}
}
jp.tsubakicraft.mongocrud.model.Model.java
package jp.tsubakicraft.mongocrud.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection="model")
public class Model {
@Id public String id;
public String name;
@DBRef public Brand brand;
public Model() {
}
public Model(String id) {
this.id = id;
}
}
So geben Sie DBRef-Eigenschaften in Suchkriterien an.
@Query(value="{brand.$id : ?0}")
public List<Model> findByBrandId(ObjectId brandId);
So erhalten Sie die Anzahl der Sammlungen. Setzen Sie count = true als Parameter für die Annotation @Query.
@Query(value="{brand.$id : ?0}", count=true)
public Long countBrandModel(ObjectId brandId);
Rufen Sie die MongoRepository-Methode mit PageRequest auf.
@Autowired
private BrandRepository repo;
...
@RequestMapping(value="/api/brands", method=RequestMethod.GET)
public Page<Brand> listBrands(@RequestParam(value="page", required=true) int page, @RequestParam(value="limit", required=true) int limit) {
Pageable pageRequest = new PageRequest(page, limit);
return repo.findAll(pageRequest);
}