spring angular crud应用程序
在本节中,我们将开发一个crud(创建-读取-更新-删除)web应用程序。该应用程序包含学生表单,该表单包含crud功能,例如添加,查看,删除和更新学生。在这种集成中,我们使用spring boot处理后端部分,使用angular处理前端部分。
工作应用程序
- 一旦我们将应用程序部署到服务器上,就会在web浏览器中生成学生表格。
- 该表单有助于添加和查看学生。
- 点击添加学生链接后,页面会重定向到创建学生表格,我们可以通过填写所需的详细信息并提交来添加学生。
- 使用查看学生链接,我们可以获取现有学生的详细信息。在这里,每个学生还包含更新和删除链接。
- 因此,我们可以更新学生的详细信息,也可以从数据库中删除他们。
- 完成后,在网络浏览器中提供url http://localhost: 4200/。
要使用的工具
- 使用任何ide来开发spring和hibernate项目。可能是sts/eclipse/netbeans。在这里,我们正在使用sts(spring工具套件)。
- 用于数据库的mysql。
- 使用任何ide来开发angular项目。它可能是visual studio代码/sublime。在这里,我们正在使用visual studio code。
- 服务器: apache tomcat/jboss/glassfish/weblogic/websphere。
我们使用的技术
在这里,我们正在使用以下技术:
- springboot2
- hibernate5
- angular6
- mysql
创建数据库
让我们创建数据库 indigo 。无需创建表,因为hibernate会自动创建它。
spring模块
让我们看看我们需要遵循的spring boot的目录结构:
要开发crud应用程序,请执行以下步骤: -
- 将依赖项添加到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> <parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.1.4.release</version> <relativepath/> <!-- lookup parent from repository --> </parent> <groupid>com.main</groupid> <artifactid>student</artifactid> <version>0.0.1-snapshot</version> <name>student</name> <description>demo project for spring boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-devtools</artifactid> <optional>true</optional> </dependency> <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> <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>
- 创建配置类
我们执行基于注释的配置,而不是xml。因此,我们创建一个类config.java并在其中指定所需的配置。但是,还有一个配置类studentapplication.java。此类由spring boot自动提供。q
config.java
package config; import java.util.properties; import javax.sql.datasource; import org.springframework.beans.factory.annotation.value; import org.springframework.boot.autoconfigure.enableautoconfiguration; import org.springframework.boot.autoconfigure.orm.jpa.hibernatejpaautoconfiguration; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.componentscan; import org.springframework.context.annotation.componentscans; import org.springframework.context.annotation.configuration; import org.springframework.jdbc.datasource.drivermanagerdatasource; import org.springframework.orm.hibernate5.hibernatetransactionmanager; import org.springframework.orm.hibernate5.localsessionfactorybean; import org.springframework.transaction.annotation.enabletransactionmanagement; import org.springframework.web.servlet.view.internalresourceviewresolver; @configuration @enabletransactionmanagement @enableautoconfiguration(exclude = { hibernatejpaautoconfiguration.class}) @componentscans(value = { @componentscan("boot.entry"), @componentscan("model"), @componentscan("controller"), @componentscan("dao"), @componentscan("miscallaneous"), @componentscan("service")}) public class config { @value("${db.driver}") private string db_driver; @value("${db.password}") private string db_password; @value("${db.url}") private string db_url; @value("${db.username}") private string db_username; @value("${hibernate.dialect}") private string hibernate_dialect; @value("${hibernate.show_sql}") private string hibernate_show_sql; @value("${hibernate.hbm2ddl.auto}") private string hibernate_hbm2ddl_auto; @value("${entitymanager.packagestoscan}") private string entitymanager_packages_to_scan; @bean public localsessionfactorybean sessionfactory() { localsessionfactorybean sessionfactory = new localsessionfactorybean(); sessionfactory.setdatasource(datasource()); sessionfactory.setpackagestoscan(entitymanager_packages_to_scan); properties hibernateproperties = new properties(); hibernateproperties.put("hibernate.dialect", hibernate_dialect); hibernateproperties.put("hibernate.show_sql", hibernate_show_sql); hibernateproperties.put("hibernate.hbm2ddl.auto", hibernate_hbm2ddl_auto); sessionfactory.sethibernateproperties(hibernateproperties); return sessionfactory; } @bean public datasource datasource() { drivermanagerdatasource datasource = new drivermanagerdatasource(); datasource.setdriverclassname(db_driver); datasource.seturl(db_url); datasource.setusername(db_username); datasource.setpassword(db_password); return datasource; } @bean public hibernatetransactionmanager transactionmanager() { hibernatetransactionmanager txmanager = new hibernatetransactionmanager(); txmanager.setsessionfactory(sessionfactory().getobject()); return txmanager; } @bean public internalresourceviewresolver jspviewresolver() { internalresourceviewresolver resolver= new internalresourceviewresolver(); resolver.setprefix("/views/"); resolver.setsuffix(".jsp"); return resolver; } }
studentapplication.java
package config; import org.springframework.boot.springapplication; import org.springframework.boot.autoconfigure.springbootapplication; @springbootapplication public class studentapplication { public static void main(string[] args) { springapplication.run(studentapplication.class, args); } }
- 创建实体类
在这里,我们将创建一个entity/pojo(普通的旧java对象)类。
student.java
package model; import javax.persistence.entity; import javax.persistence.generatedvalue; import javax.persistence.generationtype; import javax.persistence.id; import javax.persistence.table; @entity @table(name="student") public class student { @id @generatedvalue(strategy=generationtype.identity) private int student_id; private string student_name; private string student_email; private string student_branch; public int getstudent_id() { return student_id; } public void setstudent_id(int student_id) { this.student_id = student_id; } public string getstudent_name() { return student_name; } public void setstudent_name(string student_name) { this.student_name = student_name; } public string getstudent_email() { return student_email; } public void setstudent_email(string student_email) { this.student_email = student_email; } public string getstudent_branch() { return student_branch; } public void setstudent_branch(string student_branch) { this.student_branch = student_branch; } }
- 创建dao界面
在这里,我们正在创建dao界面以执行与数据库相关的操作。
student_dao.java
package dao; import java.util.list; import model.student; public interface student_dao { public boolean savestudent(student student); public list<student> getstudents(); public boolean deletestudent(student student); public list<student> getstudentbyid(student student); public boolean updatestudent(student student); }
- 创建dao接口实现类
student_dao_imp.java
package dao; import java.util.list; import org.hibernate.session; import org.hibernate.sessionfactory; import org.hibernate.query.query; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.repository; import model.student; @repository public class student_dao_imp implements student_dao{ @autowired private sessionfactory sessionfactory; @override public boolean savestudent(student student) { boolean status=false; try { sessionfactory.getcurrentsession().save(student); status=true; } catch (exception e) { e.printstacktrace(); } return status; } @override public list<student> getstudents() { session currentsession = sessionfactory.getcurrentsession(); query<student> query=currentsession.createquery("from student", student.class); list<student> list=query.getresultlist(); return list; } @override public boolean deletestudent(student student) { boolean status=false; try { sessionfactory.getcurrentsession().delete(student); status=true; } catch (exception e) { e.printstacktrace(); } return status; } @override public list<student> getstudentbyid(student student) { session currentsession = sessionfactory.getcurrentsession(); query<student> query=currentsession.createquery("from student where student_id=:student_id", student.class); query.setparameter("student_id", student.getstudent_id()); list<student> list=query.getresultlist(); return list; } @override public boolean updatestudent(student student) { boolean status=false; try { sessionfactory.getcurrentsession().update(student); status=true; } catch (exception e) { e.printstacktrace(); } return status; } }
- 创建服务层接口
在这里,我们正在创建一个服务层接口,充当dao和实体类之间的桥梁。
student_service.java
package service; import java.util.list; import model.student; public interface student_service { public boolean savestudent(student student); public list<student> getstudents(); public boolean deletestudent(student student); public list<student> getstudentbyid(student student); public boolean updatestudent(student student); }
- 创建服务层实现类
student_service_imp.java
package service; import java.util.list; import org.springframework.beans.factory.annotation.autowired; import org.springframework.stereotype.service; import org.springframework.transaction.annotation.transactional; import dao.student_dao; import model.student; @service @transactional public class student_service_imp implements student_service { @autowired private student_dao studentdao; @override public boolean savestudent(student student) { return studentdao.savestudent(student); } @override public list<student> getstudents() { return studentdao.getstudents(); } @override public boolean deletestudent(student student) { return studentdao.deletestudent(student); } @override public list<student> getstudentbyid(student student) { return studentdao.getstudentbyid(student); } @override public boolean updatestudent(student student) { return studentdao.updatestudent(student); } }
- 创建控制器类
controller.java
package controller; import java.util.list; import org.springframework.beans.factory.annotation.autowired; import org.springframework.web.bind.annotation.crossorigin; import org.springframework.web.bind.annotation.deletemapping; import org.springframework.web.bind.annotation.getmapping; import org.springframework.web.bind.annotation.pathvariable; 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 model.student; import service.student_service; @restcontroller @crossorigin(origins="http://localhost:4200") @requestmapping(value="/api") public class controller { @autowired private student_service studentservice; @postmapping("save-student") public boolean savestudent(@requestbody student student) { return studentservice.savestudent(student); } @getmapping("students-list") public list<student> allstudents() { return studentservice.getstudents(); } @deletemapping("delete-student/{student_id}") public boolean deletestudent(@pathvariable("student_id") int student_id,student student) { student.setstudent_id(student_id); return studentservice.deletestudent(student); } @getmapping("student/{student_id}") public list<student> allstudentbyid(@pathvariable("student_id") int student_id,student student) { student.setstudent_id(student_id); return studentservice.getstudentbyid(student); } @postmapping("update-student/{student_id}") public boolean updatestudent(@requestbody student student,@pathvariable("student_id") int student_id) { student.setstudent_id(student_id); return studentservice.updatestudent(student); } }
- 编辑application.properties文件
在这里,我们正在编辑 src/main/resources 文件夹中的 application.properties 文件。以下文件包含配置属性。
application.properties
# database db.driver= com.mysql.jdbc.driver db.url= jdbc:mysql://localhost:3306/indigo db.username=root db.password= # hibernate hibernate.dialect=org.hibernate.dialect.mysql5dialect hibernate.show_sql=true hibernate.hbm2ddl.auto=update entitymanager.packagestoscan=model
angular模块
让我们看看angular的目录结构:
- 创建一个angular项目
使用以下命令创建一个angular项目:
ng新的angular
此处, angular 是项目的名称。
安装bootstrap css框架
使用以下命令
npm install bootstrap@3.3.7 --save
现在,在style.css中包含以下代码文件。
@import "~bootstrap/dist/css/bootstrap.css";
安装angular-datatable
使用以下命令在项目中安装angular数据表。
npm install angular-datatable --save
必须包含 app.module.ts 文件的导入数组中的datatablemodule 。
- 生成组件
在visual studio中打开项目,然后使用以下命令生成angular组件:
ng gc addstudent
ng gc studentlist
我们还使用以下命令创建服务类: -
ng gs学生
- 编辑 app.module.ts 文件 导入路由-在这里,我们正在导入路由文件(app-routing.module.ts),并将其包含在imports数组中。
- 导入reactiveformsmodule -在这里,我们将导入 reactiveformsmodule 用于反应形式,并在imports数组中指定它。
- 导入httpmodule -在这里,我们为服务器请求导入 httpmodule ,并在import数组中指定它。
- 注册服务类-在这里,我们提到了提供者数组中的服务类。
import { browsermodule } from '@angular/platform-browser'; import { ngmodule } from '@angular/core'; import { approutingmodule } from './app-routing.module'; import { appcomponent } from './app.component'; import { formsmodule, reactiveformsmodule } from '@angular/forms'; import { httpclientmodule } from '@angular/common/http'; import {datatablesmodule} from 'angular-datatables'; import { studentlistcomponent } from './student-list/student-list.component'; import { addstudentcomponent } from './add-student/add-student.component'; @ngmodule({ declarations: [ appcomponent, studentlistcomponent, addstudentcomponent, ], imports: [ browsermodule, approutingmodule, formsmodule, reactiveformsmodule, httpclientmodule, datatablesmodule ], providers: [], bootstrap: [appcomponent] }) export class appmodule { }
- 编辑 app-routing.module.ts 文件
import { ngmodule } from '@angular/core'; import { routes, routermodule } from '@angular/router'; import { studentlistcomponent } from './student-list/student-list.component'; import { addstudentcomponent } from './add-student/add-student.component'; const routes: routes = [ { path: '', redirectto: 'view-student', pathmatch: 'full' }, { path: 'view-student', component: studentlistcomponent }, { path: 'add-student', component: addstudentcomponent }, ]; @ngmodule({ imports: [routermodule.forroot(routes)], exports: [routermodule] }) export class approutingmodule { }
- 编辑 app.component.html 文件
<div class="container-fluid"> <nav class="navbar navbar-expand-sm bg-dark navbar-dark"> <ul class="navbar-nav"> <li class="nav-item "> <a routerlink="view-student" class="nav-link" class="btn btn-primary active" role="button" >view student</a> </li> <li class="nav-item"> <a routerlink="add-student" class="nav-link" class="btn btn-primary active" role="button" >add student</a> </li> </ul> </nav> <router-outlet></router-outlet> </div>
- 创建 student.ts 类
让我们使用以下命令创建课程: -
ng g class student
现在,在 student 类中指定必填字段。
export class student { student_id:number; student_name:string; student_email:string; student_branch:string; }
此类的目的是将指定的字段与spring实体类的字段进行映射。
- 编辑 student.service.ts 文件
import { injectable } from '@angular/core'; import { httpclient } from '@angular/common/http'; import { observable } from 'rxjs'; @injectable({ providedin: 'root' }) export class studentservice { private baseurl = 'http://localhost:8080/api/'; constructor(private http:httpclient) { } getstudentlist(): observable<any> { return this.http.get(`${this.baseurl}`+'students-list'); } createstudent(student: object): observable<object> { return this.http.post(`${this.baseurl}`+'save-student', student); } deletestudent(id: number): observable<any> { return this.http.delete(`${this.baseurl}/delete-student/${id}`, { responsetype: 'text' }); } getstudent(id: number): observable<object> { return this.http.get(`${this.baseurl}/student/${id}`); } updatestudent(id: number, value: any): observable<object> { return this.http.post(`${this.baseurl}/update-student/${id}`, value); } }
- 编辑 add-student.component.ts 文件
import { component, oninit } from '@angular/core'; import { studentservice } from '../student.service'; import {formcontrol,formgroup,validators} from '@angular/forms'; import { student } from '../student'; @component({ selector: 'app-add-student', templateurl: './add-student.component.html', styleurls: ['./add-student.component.css'] }) export class addstudentcomponent implements oninit { constructor(private studentservice:studentservice) { } student : student=new student(); submitted = false; ngoninit() { this.submitted=false; } studentsaveform=new formgroup({ student_name:new formcontrol('' , [validators.required , validators.minlength(5) ] ), student_email:new formcontrol('',[validators.required,validators.email]), student_branch:new formcontrol() }); savestudent(savestudent){ this.student=new student(); this.student.student_name=this.studentname.value; this.student.student_email=this.studentemail.value; this.student.student_branch=this.studentbranch.value; this.submitted = true; this.save(); } save() { this.studentservice.createstudent(this.student) .subscribe(data => console.log(data), error => console.log(error)); this.student = new student(); } get studentname(){ return this.studentsaveform.get('student_name'); } get studentemail(){ return this.studentsaveform.get('student_email'); } get studentbranch(){ return this.studentsaveform.get('student_branch'); } addstudentform(){ this.submitted=false; this.studentsaveform.reset(); } }
- 编辑 add-student.component.html 文件
<h3>create student</h3> <div class="row"> <div class="col-sm-4"></div> <div class="col-sm-4" > <div [hidden]="submitted" style="width: 400px;"> <form [formgroup]="studentsaveform" #savestudent (ngsubmit)="savestudent(savestudent)"> <div class="form-group"> <label for="name">student name</label> <input type="text" class="form-control" formcontrolname="student_name" data-toggle="tooltip" data-placement="right" title="enter student name" > <div class="alert alert-danger" *ngif = "(studentname.touched) && (studentname.invalid)" style="margin-top: 5px;"> <span *ngif="studentname.errors.required">student name is required <span *ngif = "studentname.errors.minlength"> minlength error </div> </div> <div class="form-group"> <label for="name">student email</label> <input type="text" class="form-control" formcontrolname="student_email" data-toggle="tooltip" data-placement="right" title="enter student email"> <div class="alert alert-danger" *ngif = "(studentemail.touched) && (studentemail.invalid)" style="margin-top: 5px;"> <span *ngif="studentemail.errors.required">student email is required <span *ngif = "studentemail.errors.email"> invalid email format </div> </div> <div class="form-group"> <label for="branch">student branch</label> <select class="form-control" formcontrolname="student_branch" data-toggle="tooltip" data-placement="right" title="select student branch"> <option value="null">--select branch--</option> <option value="b-tech">b-tech</option> <option value="bca">bca</option> <option value="mca">mca</option> <option value="m-tech">m-tech</option> </select> </div> <button type="submit" class="btn btn-success">submit</button> </form> </div> </div> <div class="col-sm-4"></div> </div> <div class="row"> <div class="col-sm-4"></div> <div class="col-sm-4"> <div [hidden]="!submitted"> <h4>student added successfully!</h4> <button (click)="addstudentform()" class='btn btn-primary'>add more student</button> </div> </div> <div class="col-sm-4"></div> </div>
单击 添加学生时,将生成以下页面:
现在,填写所需的详细信息,然后提交以添加学生。
- 编辑 student-list.component.ts 文件
import { component, oninit } from '@angular/core'; import { studentservice } from '../student.service'; import { student } from '../student'; import { observable,subject } from "rxjs"; import {formcontrol,formgroup,validators} from '@angular/forms'; @component({ selector: 'app-student-list', templateurl: './student-list.component.html', styleurls: ['./student-list.component.css'] }) export class studentlistcomponent implements oninit { constructor(private studentservice:studentservice) { } studentsarray: any[] = []; dtoptions: datatables.settings = {}; dttrigger: subject<any>= new subject(); students: observable<student[]>; student : student=new student(); deletemessage=false; studentlist:any; isupdated = false; ngoninit() { this.isupdated=false; this.dtoptions = { pagelength: 6, statesave:true, lengthmenu:[[6, 16, 20, -1], [6, 16, 20, "all"]], processing: true }; this.studentservice.getstudentlist().subscribe(data =>{ this.students =data; this.dttrigger.next(); }) } deletestudent(id: number) { this.studentservice.deletestudent(id) .subscribe( data => { console.log(data); this.deletemessage=true; this.studentservice.getstudentlist().subscribe(data =>{ this.students =data }) }, error => console.log(error)); } updatestudent(id: number){ this.studentservice.getstudent(id) .subscribe( data => { this.studentlist=data }, error => console.log(error)); } studentupdateform=new formgroup({ student_id:new formcontrol(), student_name:new formcontrol(), student_email:new formcontrol(), student_branch:new formcontrol() }); updatestu(updstu){ this.student=new student(); this.student.student_id=this.studentid.value; this.student.student_name=this.studentname.value; this.student.student_email=this.studentemail.value; this.student.student_branch=this.studentbranch.value; console.log(this.studentbranch.value); this.studentservice.updatestudent(this.student.student_id,this.student).subscribe( data => { this.isupdated=true; this.studentservice.getstudentlist().subscribe(data =>{ this.students =data }) }, error => console.log(error)); } get studentname(){ return this.studentupdateform.get('student_name'); } get studentemail(){ return this.studentupdateform.get('student_email'); } get studentbranch(){ return this.studentupdateform.get('student_branch'); } get studentid(){ return this.studentupdateform.get('student_id'); } changeisupdate(){ this.isupdated=false; } }
- 编辑 student-list.component.html 文件
<div class="panel panel-default"> <div class="panel-heading"> <h1 style="text-align: center">students</h1><br> <div class="row" [hidden]="!deletemessage"> <div class="col-sm-4"></div> <div class="col-sm-4"> <div class="alert alert-info alert-dismissible"> <button type="button" class="close" data-dismiss="alert">×</button> <strong>student data deleted</strong> </div> </div> <div class="col-sm-4"></div> </div> </div> <div class="panel-body"> <table class="table table-hover table-sm" datatable [dtoptions]="dtoptions" [dttrigger]="dttrigger" > <thead class="thead-light"> <tr> <th>student name</th> <th>student email</th> <th>student branch</th> <th>action</th> </tr> </thead> <tbody> <tr *ngfor="let student of students "> <td>{{student.student_name}}</td> <td>{{student.student_email}}</td> <td>{{student.student_branch}}</td> <td><button (click)="deletestudent(student.student_id)" class='btn btn-primary'><i class="fa fa-futboll-0">delete</i></button> <button (click)="updatestudent(student.student_id)" class='btn btn-info' data-toggle="modal" data-target="#mymodal">update</button> </td> </tr> </tbody><br> </table> </div> </div> <div class="modal" id="mymodal"> <div class="modal-dialog"> <div class="modal-content"> <form [formgroup]="studentupdateform" #updstu (ngsubmit)="updatestu(updstu)"> <!-- modal header --> <div class="modal-header"> <h4 class="modal-title" style="text-align: center">update student</h4> </div> <!-- modal body --> <div class="modal-body" *ngfor="let student of studentlist " > <div [hidden]="isupdated"> <input type="hidden" class="form-control" formcontrolname="student_id" [(ngmodel)]="student.student_id"> <div class="form-group"> <label for="name">student name</label> <input type="text" class="form-control" formcontrolname="student_name" [(ngmodel)]="student.student_name" > </div> <div class="form-group"> <label for="name">student email</label> <input type="text" class="form-control" formcontrolname="student_email" [(ngmodel)]="student.student_email"> </div> <div class="form-group"> <label for="name">student branch</label> <select class="form-control" formcontrolname="student_branch" required> <option value="b-tech" [selected]="'b-tech' == student.student_branch">b-tech</option> <option value="bca" [selected]="'bca' == student.student_branch">bca</option> <option value="mca" [selected]="'mca' == student.student_branch" >mca</option> <option value="m-tech" [selected]="'m-tech' == student.student_branch">m-tech</option> </select> </div> </div> <div [hidden]="!isupdated"> <h4>student detail updated!</h4> </div> </div> <!-- modal footer --> <div class="modal-footer" > <button type="submit" class="btn btn-success" [hidden]="isupdated">update</button> <button type="button" class="btn btn-danger" data-dismiss="modal" (click)="changeisupdate()">close</button> </div> </form> </div> </div> </div>
单击 查看学生时,将生成以下页面:
单击 更新学生时,将出现以下引导程序模式:
在这里,我们可以更新现有学生的详细信息。
单击 delete (删除),现有学生将被删除从数据库中。让我们在删除特定学生后查看结果。
spring angular文件上传 spring angular登录和注销 spring angular搜索字段