Beispielanwendung mit MongoDB von Spring Boot

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. * *

Ich werde es vorerst verschieben

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

Entwicklungsumgebung

Frühling bezogen

Maven-Projekt

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);

Fehler beim Umgang mit nicht gefundenen Seiten bei Verwendung natürlicher Routen

	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:/";
		}
	}

AngularJS verwandt

Partisierung der HTML-Vorlage (mit $ routeProvider)

	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);
	}]);

REST-API-Aufruf (mit $ http)

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();
	});

Formulareingabeprüfung

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>

Pagenation (mit UI-Bootstrap)

Auf der UI-Bootstrap-Seite (https://angular-ui.github.io/bootstrap/) wird dies erläutert.

Tabellenspalten sortieren

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 bezogen

Bootstrap CSS Override

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;
	}

Mongo Repository im Zusammenhang

MongoRepository ist eine Unterschnittstelle von PagingAndSortingRepository mit Funktionen zum Einfügen, Aktualisieren, Löschen, Suchen und Paginieren von Daten.

MongoDB-Konfiguration

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);
		}
	
	}

MongoDB-Entität

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;
		}
	}

Erweiterung des Mongo Repository

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);

Page Nation mit Mongo Repository

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);
	}

Recommended Posts

Beispielanwendung mit MongoDB von Spring Boot
Python: Anwendung der Bilderkennung mit CNN
Dies ist ein Beispiel für eine Funktionsanwendung im Datenrahmen.
Webanwendung mit Flasche (1)
Beispiel für die Verwendung von Lambda
Anwendung von Python 3 vars