Vue+SpringBoot 前后端分离小实验
1、概述业务模型:员工+部门,多对一,实现增删改查(CRUD)后端:Spring Boot + Spring MVC + Spring REST Data前端:Vue + axios2、后端开发POM依赖<?xml version="1.0" encoding="UTF-8"?><project xmlns=&quo
1、概述
业务模型:员工+部门,多对一,实现增删改查(CRUD)
后端:Spring Boot + Spring MVC + Spring REST Data
前端:Vue + axios
2、后端开发
POM依赖
<?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>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.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-actuator</artifactId>
</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-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-bean-validators -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>2.7.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-spi -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-spi</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(1)业务实体
员工(`Employee`)
package com.example.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
@Entity(name = "tbl_emp")
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "emp_id")
private Long id;
@Column(name = "last_name",length = 100,nullable = false,unique = false)
@Size(min = 2,max = 50)
private String lastName;
@Email(message = "邮箱格式不正确!")
@Column(name = "email",length = 100,nullable = false,unique = true)
private String email;
@Column(name = "phone_number",length = 11, nullable = false,unique = false)
@Size(min = 11,max = 11)
private String phoneNumber;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Column(name = "birth")
private Date birth;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(name = "create_time",columnDefinition="timestamp default current_timestamp")
private Timestamp createTime;
@ManyToOne
@JoinColumn(name = "dept_id")
private Department department;
}
部门(`Department`)
package com.example.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import javax.validation.constraints.Size;
import java.io.Serializable;
/**
* @author Blessed
*/
@Entity(name = "tbl_dept")
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Department implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "department_id")
private Long id;
@Column(name = "department_name")
@Size(min = 2,max = 50)
private String departmentName;
}
其中用`Lombok`来简化代码长度
(2)数据访问层
`EmployeeRepository`
package com.example.demo.repository;
import com.example.demo.entity.Employee;
import io.swagger.annotations.Api;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.web.bind.annotation.CrossOrigin;
/**
* @author Blessed
*/
@Api(tags = "Employee Entity") //Swagger REST API 但是好像目前需要一些插件,由于版本冲突,不能显示
@CrossOrigin(origins = {"http://localhost:8090","null"}) //CORS 跨域请求设置
@RepositoryRestResource(path = "emp") //配置生成REST API和对应Controller,path属性指定访问路径,按道理应该是复数(emps)这里就忽略了
public interface EmployeeRepository extends JpaRepository<Employee,Long> {
}
`DepartmentRepository`
package com.example.demo.repository;
import com.example.demo.entity.Department;
import io.swagger.annotations.Api;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.web.bind.annotation.CrossOrigin;
/**
*
* @author Blessed
*/
@Api(tags = "Department Entity")
@CrossOrigin(origins = {"http://localhost:8090","null"})
@RepositoryRestResource(path = "dept")
public interface DepartmentRepository extends JpaRepository<Department,Long> {
}
到此,后端大功告成,打包
mvn clean package
通过`java -jar jarName`来启动Spring Boot项目
java -jar demo-0.0.1-SNAPSHOT.jar
项目启动
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.5.RELEASE)
......
: Mapped "{[/{repository}/{id}],methods=[HEAD],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}],methods=[GET],produces=[application/hal+json || application/json]}"
//获取对应实体的所有的记录,比如发送GET /emp 获取数据库中所有员工信息,支持分页
Mapped "{[/{repository}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}],methods=[GET],produces=[application/x-spring-data-compact+json || text/uri-list]}"
Mapped "{[/{repository}],methods=[HEAD],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}],methods=[POST],produces=[application/hal+json || application/json]}"
//添加一条记录,用JSON发送
Mapped "{[/{repository}/{id}],methods=[PATCH],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}],methods=[PUT],produces=[application/hal+json || application/json]}"
//修改实体内容,修改内容放在JSON发送
Mapped "{[/{repository}/{id}],methods=[GET],produces=[application/hal+json || application/json]}"
//获取对应id的实体信息,比如 GET /emp/2 获取ID为2的员工信息
Mapped "{[/{repository}/{id}],methods=[DELETE],produces=[application/hal+json || application/json]}"
//删除对应id的实体,比如 DELETE /emp/2 删除员工ID为2的记录
Mapped "{[/{repository}/{id}/{property}],methods=[DELETE],produces=[application/hal+json || application/json]}"
//获取详细配置信息
...
(3)Postman测试
发送 GET http://localhost:8080/emp
{
"_embedded": {
"employees": [
{
"lastName": "Blessed",
"email": "AAA@163.com",
"phoneNumber": "15850720606",
"birth": "1996-03-29T00:00:00.000+0000",
"createTime": "2018-09-18T15:11:02.000+0000",
"_links": {
"self": {
"href": "http://localhost:8080/emp/1"
},
"employee": {
"href": "http://localhost:8080/emp/1"
},
"department": {
"href": "http://localhost:8080/emp/1/department"
}
}
},
{
"lastName": "Ryan",
"email": "Rayn@163.com",
"phoneNumber": "15850720606",
"birth": "1996-02-12T00:00:00.000+0000",
"createTime": "2018-09-18T20:00:00.000+0000",
"_links": {
"self": {
"href": "http://localhost:8080/emp/2"
},
"employee": {
"href": "http://localhost:8080/emp/2"
},
"department": {
"href": "http://localhost:8080/emp/2/department"
}
}
},
{
"lastName": "Helen",
"email": "Halen@163.com",
"phoneNumber": "12345698725",
"birth": "1996-05-05T00:00:00.000+0000",
"createTime": "2018-09-19T00:00:00.000+0000",
"_links": {
"self": {
"href": "http://localhost:8080/emp/3"
},
"employee": {
"href": "http://localhost:8080/emp/3"
},
"department": {
"href": "http://localhost:8080/emp/3/department"
}
}
},
{
"lastName": "Bob",
"email": "Bob@163.com",
"phoneNumber": "15452368460",
"birth": "1996-05-05T00:00:00.000+0000",
"createTime": "2019-09-23T12:00:00.000+0000",
"_links": {
"self": {
"href": "http://localhost:8080/emp/6"
},
"employee": {
"href": "http://localhost:8080/emp/6"
},
"department": {
"href": "http://localhost:8080/emp/6/department"
}
}
},
{
"lastName": "Jack",
"email": "jack@163.com",
"phoneNumber": "25136587541",
"birth": "1996-07-12T00:00:00.000+0000",
"createTime": "2019-09-24T12:00:00.000+0000",
"_links": {
"self": {
"href": "http://localhost:8080/emp/7"
},
"employee": {
"href": "http://localhost:8080/emp/7"
},
"department": {
"href": "http://localhost:8080/emp/7/department"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/emp{?page,size,sort}",
"templated": true
},
"profile": {
"href": "http://localhost:8080/profile/emp"
}
},
"page": {
"size": 20,
"totalElements": 5,
"totalPages": 1,
"number": 0
}
}
其他方法就不一一试了
3、前端开发
简单用Vue脚手架创建项目,就一个helloworld
注意,此Hello项目的在WebStorm中启动的端口号为:8090
(1)配置代理(PS:才疏学浅,不知道为什么,不配就可能产生跨域的问题)
在`/config/index.js`中的`proxyTable`配置
proxyTable: {
'/api': {
target: 'http://127.0.0.1:8080',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
},
以后比如发请求`http://127.0.0.1:8080/emp`,变成`/api/emp`,实际的发的请求就是:`http://localhost:8090/api/emp`
所以在发`POST`、`PUT`,`DELETE`请求的跨域时候就需要匹配后端的跨域设置
在前面后端开发中,在`repository`中配置了如下的注解
@CrossOrigin(origins = {"http://localhost:8090","null"})
注意是`8090`,而不是`8080`
接下里就是简单的`axios`使用了
<template>
<div>
<button @click="queryAllEmployees">查询所有员工</button>
<button @click="addEmployee">添加员工</button>
<button @click="deleteEmployee">删除员工</button>
<button @click="updateEmployee">更新员工信息</button>
<br><br>
<button @click="deleteDept">删除部门</button>
<button @click="addDept">添加部门</button>
<button @click="updateDept">修改部门</button>
</div>
</template>
监听函数的代码为:
// import qs from 'qs'
export default {
name: 'HelloWorld',
methods: {
updateEmployee () {
this.$axios({
url: '/api/emp/1',
method: 'PUT',
data: "{\n" +
"\t\"lastName\": \"Blessed\",\n" +
"\t\"email\": \"blessed@163.com\",\n" +
"\t\"phoneNumber\": \"12365478985\",\n" +
"\t\"birth\": \"1996-03-29\",\n" +
"\t\"createTime\": \"2018-09-24T21:52:52\",\n" +
"\t\"department\": \"http://localhost:8080/dept/3\"\n" +
"}",
headers: {'Content-Type': 'application/json'}
}).then(res => {console.log(res)}).catch(err => {console.log(err)})
},
deleteEmployee () {
this.$axios({
url: '/api/emp/3',
method: 'DELETE'
}).then(res => {console.log(res)}).catch(err => {console.log(err)})
},
updateDept () {
this.$axios({
url: '/api/dept/13',
method: 'PUT',
data: "{\"departmentName\": \"前台部门\"}",
headers: {'Content-Type': 'application/json'}
}).then(
res => {console.log(res)}
).catch(err => {console.log(err)})
},
deleteDept () {
this.$axios({
url: '/api/dept/11',
method: 'DELETE'
}).then(
res => {
console.log(res)
}
).catch(
err => {
alert('失败')
}
)
},
addEmployee () {
alert('进入')
this.$axios({
url: '/api/emp',
method: 'POST',
data: "{\"lastName\": \"Jack\", \"email\": \"jack@163.com\", \"phoneNumber\": \"25136587541\", \"birth\": \"1996-07-12\", \"createTime\": \"2019-09-24T12:00:00\", \"department\": \"/api/dept/4\"}",
headers: {'Content-Type': 'application/json'}
}).then(
res => {
alert('成功')
console.log(res)
}
).catch(
err => {
alert('失败')
console.log(err)
}
)
alert('结束')
},
queryAllEmployees () {
var url = '/api/emp'
this.$axios.get(url).then(
res => {
console.log(res)
}
).catch(
err => {
console.log(err)
}
)
},
addDept () {
this.$axios({
url: '/api/dept',
method: 'post',
data: "{\"departmentName\": \"前台接待部门\"}",
headers: {'Content-Type': 'application/json'}
}).then(
res => {
console.log(res)
}
).catch(
err => {
console.log(err)
}
)
}
}
}
本人才接触Vue,就关掉了Eslint的检查,不然双引号会报错
【注意】:`data`属性应该是一个这样的格式:
{"param1": "value1", "param2": "value2"}
data: “{\"param1\": \"value1\", \"param2\": \"value2\"}”
//要是不这么发,后台会报错
另外注意的是,最好设置`Content-Type`为`application/json`
以上就可以进行简单的增删改查。而且后端再怎么复杂,只要规范暴露REST API,就不管前端什么事了
更多推荐
所有评论(0)