进行一个简单的项目创建并打包发布到虚拟机。
使用Spring Initializer初始化,jdk为本地的1.8
注意开始生成项目之前,选择管理工具,一定要选择gradle
选择项目依赖的时候,这里并不需要很多的依赖,因为我们只是需要在浏览器访问我们项目,并能够在页面上答应一句话即可。所以,我们只需要选中web即可。其他的不需要添加。
依赖选择完成之后就点击下一步即可。在 模块导入对话框内勾选 “Use auto-import”,这样有在配置文件内添加所需的新的依赖包的时候可以自动下载导入。
后面的基本不需要做更改。但是当进入到idea的主界面之后要稍微等待一会,因为gradle需要下载依赖。
当我们看到如上图,控制台全部加载完成,大体项目就已经构建完了。然后我们可以开始代码部分了。
对于目录结构详解可以参照 https://www.jianshu.com/p/f33bb06e447e
在build.gradle配置文件中添加maven仓库地址,可以在这里下载所需包。这里用的是国内阿里云镜像
// maven repositories
repositories {
maven{
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
在代码部分 /src/main 文件夹下建立webapp文件夹,用来存放前端部分。
进入webapp, 用shell输入CLI 命令 ng new
,空间名为demo-app。这里需要提前安装好Angular CLI (npm install -g @angular/cli)
ng new demo-app
需要安装必要的npm包和其他依赖项,可能需要几分钟。还会创建以下工作区和初始项目文件:
新的工作区,其根目录名叫 demo-app
一个最初的骨架应用项目,同样叫做demo-app(位于 src
子目录下)。
一个端到端测试项目(位于 e2e 子目录下)。
相关的配置文件。
所需的包 文件夹node_modulus。其中package.json文件内包含了所需的包,可以在里面添加。添加之后在demo-app目录下运行 npm install 进行安装。
angular的默认端口号是4200(在配置文件 node_modules/@angular/cli/lib/config/schema.json 中定义). 如果有需要修改端口的话可以参照 https://www.cnblogs.com/xinjie-just/articles/7567623.html
在build.gralde 中添加angular的路径。以及sourceSets设置。sourceSets可以指定哪些源文件要被编译,哪些要排除。其中$projectDir 是脚本提供的默认项目地址。
// angular setting
def webAppDir = "$projectDir/src/main/webapp/demo-app"
// source setting
sourceSets {
main {
resources {
srcDirs = ["$webAppDir/dist", "$projectDir/src/main/resources"]
}
}
}
使用本地MySQL建立数据库 demodata。打开MySQL, 输入:
create database demodata;
创建调用该项目数据的账号和密码:
create user 'demo'@'localhost' identified by 'demo';
grant all on demodata.* to 'demo'@'localhost';
这样就可以使用该账号调用数据库。账号信息需要在配置文件application.properties里面完善。服务启动后,会根据该文件连接数据库。
在build.gradle里面添加JPA的依赖库。jpa可以通过注释 @Entity ,@Id 等识别数据对应的表
// JPA (Java Persistence API)
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
// mysql connection
compile 'mysql:mysql-connector-java'
创建springboot项目时,会在resources目录下生成一个空的application.properties配置文件,springboot启动时加载该配置文件。application.properties(或者application.yml)中包含系统属性、环境变量、命令参数这类信息。
这些参数配置不一定要写在application.properties里面,可以在application.properties里面配置指定自定义配置文件名称和位置:(但是无论怎么配置,spring-boot都会读取加载application.properties文件)
在application.properties里面自定义的属性可以在应用中通过添加 @Value 注解来加载。
关于文件内容详解可参照 https://blog.csdn.net/fly_leopard/article/details/78498804
添加服务器端口,这里指定端口为1230:
# server
server.port=1230
添加数据库连接参数。
# Database
# 若数据不存在,则自动创建
spring.jpa.hibernate.ddl-auto=create
# 数据库连接设置。名称(demodata),ip和端口
spring.datasource.url=jdbc:mysql://localhost:3306/demodata?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
# 数据库login用户名和密码
spring.datasource.username=demo
spring.datasource.password=demo
这里第一次jpa识别数据 (@Entity等)用create,之后再改为update,重新启动服务器,即可自动更新。
这里做一个简单的应用,输入 人名和身高,点击提交信息存入数据库,并返回服务端的信息。点击检查列出所有数据库内数据。点击清空删除所有数据。如下图所示
启动前端,在 webapp\demo-app 目录下打开shell,输入 ng serve。就可以对组件代码进行编译,以及启动服务。
启动后可以在 4200 端口访问页面。angular项目创建时默认有一个页面。主页的组件是app.component。
在工作区内创建文件如下图目录所示
其中:
在主页面app.component.html 中添加该子组件。这样可以在主页中显示该组件。
Welcome to {{ title }}!
输入名字:
输入身高:
后端返回的信息是:
{{message}}
-
{{data.id}}
{{data.name}}
{{data.height}}
填写输入框或者点击按钮之后会触发在demo.component.ts 中定义的方法。
import { Component, OnInit } from '@angular/core';
import {DemoService} from "../demo.service";
import {Demo} from "../demo";
@Component({
selector: 'app-demo',
templateUrl: './demo.component.html',
styleUrls: ['./demo.component.scss']
})
export class DemoComponent implements OnInit {
// message变量用于接受后端返回的信息。demodata存放需要发送的信息,
// 这里需要初始化demodata。以防止在初始化的时候报错
public message : any;
public demodata : Demo = {"id" : null, "name" : null, "height" : null};
public demodatas : Demo[];
// 在构建组件的同时就需要注入服务
constructor(
private demoService : DemoService,
) { }
ngOnInit() {
}
// 输入框的change事件调用以更新demo的name
updateName(value: string) {
this.demodata.name = value;
}
// 输入框的change事件调用以更新demo的height
updateHeight(value: number) {
this.demodata.height = value;
}
// 增加新数据
submitInfo() {
// 调用demoService中的方法,该方法为Observable模式,调用subscribe
// 方法进行后续处理,这里将获取的message赋予本组件变量。即可以通过
// 双向绑定改变前端显示
this.demoService.addToDatabase(this.demodata)
.subscribe(msg => {
this.message = msg.msg;
})
}
// 查看已提交数据
checkData() {
this.demoService.checkDatabase()
.subscribe(data => {
this.demodatas = data
})
}
// 清空所有数据
clearData() {
this.demoService.clearDatabase()
.subscribe(msg => {
this.message = msg.msg;
})
}
}
demo component 中的提交,查看和删除的方法需要调用DemoService中的方法发起http通信。并作为观察者进行后续操作。
import { Injectable } from '@angular/core';
import {Observable} from "rxjs";
import {Demo} from "./demo";
import {HttpClient, HttpHeaders} from "@angular/common/http";
@Injectable({
providedIn: 'root'
})
export class DemoService {
constructor(
//HttpClient 是 Angular 通过 HTTP 与远程服务器通讯的机制
private http : HttpClient
) { }
// 发送给服务端的api。端口为server.port
private api = 'http://localhost:1230/demo/';
// 观察者模式方法。用post方法发送Demo类型数据,并等待返回的信息
// 返回的是json格式,可以在本地建立数据模型,这里用any类型接受
addToDatabase(demodata : Demo):Observable {
return this.http.post(this.api + 'newData/', demodata)
}
checkDatabase():Observable {
return this.http.get(this.api + 'getData/')
}
clearDatabase():Observable {
return this.http.delete(this.api + 'clearData/')
}
}
服务中引入了 @angular/common/http 中的 HttpClient 客户端,要让 HttpClient 在应用中随处可用,打开根模块 AppModule(app.module.ts),从 @angular/common/http 中导入 HttpClientModule
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { DemoComponent } from './demo/demo.component';
import {HttpClientModule} from "@angular/common/http";
@NgModule({
declarations: [
AppComponent,
DemoComponent
],
imports: [
BrowserModule,
AppRoutingModule,
// Http 客户端
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
export class Demo {
// 保存数据库中的id, name 以及 height
id : number;
name: string;
height: number;
}
前面已经完成了前端程序,即输入信息并发送http请求给后端。这里后端利用controller程序获取该请求,并返回信息。
在源程序目录 src\main\java 下面创建名为 Controllers 和 Models 的package。并在Controllers中创建程序 DemoController, 用于接受前端请求以及进行处理。
在Models文件夹下创建模型文件Demodata,以及用于操作数据的接口文件DemodataRepository。DemodataRepository类是 CurReposity接口的继承。该接口是一个操作集合。若不对方法进行个性化,无需任何修改,只需要创建一个空内容的接口文件即可。对于每个表,都需要有一个自己的接口文件。
另外,建立用于返回信息数据的Message数据文件。
具体代码如下:
package com.example.demo.Controllers;
import com.example.demo.Models.Demodata;
import com.example.demo.Models.DemodataRepository;
import com.example.demo.Models.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
// 标明是controller的bean
@RestController
// 允许跨域访问。前端端口为4200。server端口为1230
@CrossOrigin(origins = "http://localhost:4200")
@RequestMapping(path = "/demo")
public class DemoController {
// 该注释告诉springboot,去帮助实现Repository接口。否则,抛空指针异常。
@Autowired
private DemodataRepository demodataRepository;
//增加数据
@PostMapping(value = "/newData")
// Springboot将返回的类,以JSON字符串形式输出。这里使用Message model建立json格式数据
public Message addNewData(@RequestBody Demodata demodata) {
Message msg = new Message();
// save后自动添加id
demodataRepository.save(demodata);
msg.setMsg("The info of " + demodata.getName() + " has been added with the ID: " + demodata.getId());;
return msg;
}
// 获取数据
@GetMapping(value = "/getData")
// 这里返回的是Iterable类型数据,为可迭代类型。可被循环访问
public Iterable getDemodatas() {
return demodataRepository.findAll();
}
// 删除数据
@DeleteMapping(value = "/clearData")
public Message clearDemodatas() {
demodataRepository.deleteAll();
Message msg = new Message();
msg.setMsg("The database has been cleared");
return msg;
}
}
package com.example.demo.Models;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
// 标明是Entity,以被jpa识别为数据,映射到MySQL数据库。必须与@Id注解 结合使用
@Entity
public class Demodata {
// 标注表的唯一标识
@Id
// 标注表的该列,为自动生成数据
@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
private Integer id;
private String name;
private Integer height;
// 对应每个变量,建立get和set方法
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
}
package com.example.demo.Models;
import org.springframework.data.repository.CrudRepository;
public interface DemodataRepository extends CrudRepository {
}
package com.example.demo.Models;
public class Message {
// Message 类不需要往数据库里存放,不用标识为@Entity。只需建立
// 数据模型类即可
private String msg;
public void setMsg(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
}
右键点击DemoApplication,选择 Run "DemoApplication" 以启动服务端。
同时可以看到,在程序源目录下会自动创建图中所示的out文件夹。用以存放编译后的程序文件。这个路径可以在 Idea中的File -> Project Structure 对话框中的 Project Settings中 设置。
第一次启动成功后,记得把application.properties 中的 spring.jpa.hibernate.ddl-auto 改为 update,不然每次启动服务都要重新建立数据表。更新之后再重新启动服务器,就可以持续更新数据库了。
spring.jpa.hibernate.ddl-auto = update
具体操作效果如下:
添加数据。输入数据,点击“提交”增加入数据库。这里ID为9因为之前添加过数据,即使清空,还是会继续递增。
检查数据。添加几个数据后,点击“检查”查看所有数据
删除数据。点击“清空”将所有数据删除,再点击“检查”发现已经没有数据显示。
至此,简单的功能已经增加完毕。
之前已经申请过云虚拟机,现在将发布到云上,OS为Linux CentOS
在工作区根目录下建立名为startServerLinux的bash文件,用于启动项目的jar包。在src/main/webapp/demo-app下建立startClientLinux的bash文件,用于编译和启动客户端。文件具体如下:
startServerLinux:
在window下可以直接运行 gradle.build
如果是Linux 或者 mac 命令为 ./gradlew build
运行之后会在根目录下的build\libs 生成打包好的jar包。
修改权限
建立数据库
修改api
修改gradle.build中mysql commection的版本