1、创建一个springboot项目
如何创建就不多讲述了,以下为所选依赖
2、配置yml.文件
数据库改为你本地的数据库
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/jpa_student?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: root
jpa:
show-sql: true #显示SQL语句
hibernate:
ddl-auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
database: mysql # 配置现在使用的数据库
3、实体类
运行时会自动生成表,注意表名不能与数据库名一样
package com.nebula.jpa_vue.pojo;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table(name = "student") //表名
/**
* 学生 实体类
*/
public class Student {
@Id //主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //自动增长
// 编号
private Integer id;
// 姓名
private String name;
// 性别
private String sex;
// 年级编号
private Integer gradeId;
}
4、dao层
继承JpaRepository<T,ID>
package com.nebula.jpa_vue.dao;
import com.nebula.jpa_vue.pojo.Student;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* 学生 dao接口
*/
public interface StudentDao extends JpaRepository<Student, Integer> {
}
5、service层
package com.nebula.jpa_vue.service;
import com.nebula.jpa_vue.pojo.Student;
import org.springframework.data.domain.Page;
/**
* 学生 服务接口
*/
public interface StudentService {
/**
* 分页查询
*
* @param pageNum 页码
* @param pageSize 每页显示条数
* @return
*/
Page<Student> paging(Integer pageNum, Integer pageSize);
/**
* 保存学生信息
* 用于添加、编辑
*
* @param student 学生对象
* @return
*/
Student save(Student student);
/**
* 根据编号删除学生信息
*
* @param id 学生编号
*/
void deleteById(Integer id);
}
6、实现类
package com.nebula.jpa_vue.service.impl;
import com.nebula.jpa_vue.dao.StudentDao;
import com.nebula.jpa_vue.pojo.Student;
import com.nebula.jpa_vue.service.StudentService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 学生 服务实现类
*/
@Service
public class StudentServiceImpl implements StudentService {
@Resource
StudentDao studentDao;
/**
* 分页查询
*
* @param pageNum 页码
* @param pageSize 每页显示条数
* @return
*/
@Override
public Page<Student> paging(Integer pageNum, Integer pageSize) {
PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize);
return studentDao.findAll(pageRequest);
}
/**
* 保存学生信息
* 用于添加、编辑
*
* @param student 学生对象
* @return
*/
@Override
public Student save(Student student) {
return studentDao.save(student);
}
/**
* 根据编号删除学生信息
*
* @param id 学生编号
*/
@Override
public void deleteById(Integer id) {
studentDao.deleteById(id);
}
}
7、控制层
@Api @ApiOperation 为swagger自带注解
package com.nebula.jpa_vue.controller;
import com.nebula.jpa_vue.pojo.Student;
import com.nebula.jpa_vue.service.StudentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 学生 控制层
*/
@RestController
@Api(value = "Spring-data-jpa+vue+swagger 实现一个前端后分离的小Demo") //说明该类的作用
public class StudentController {
@Resource
StudentService studentService;
/**
* 分页查询
*
* @param pageNum 当前页码
* @return
*/
@GetMapping("/student/{pageNum}")
@ApiOperation(value = "分页查询", notes = "分页查询学生信息") //增加方法说明
@ResponseBody
public Page<Student> paging(@PathVariable("pageNum") Integer pageNum) {
if (pageNum == null) {
pageNum = 1;
}
return studentService.paging(pageNum, 3);
}
/**
* 保存学生信息
* 用于保存、编辑
*
* @param student 学生对象
* @return
*/
@PostMapping("/save")
@ApiOperation(value = "添加学生", notes = "添加学生信息") //增加方法说明
public Student save(@RequestBody Student student) {
System.out.println(student.getName());
return studentService.save(student);
}
/**
* 根据编号删除学生信息
*
* @param id 学生编号
* @return
*/
@DeleteMapping("/delete")
@ApiOperation(value = "删除学生", notes = "根据学生id删除学生信息") //增加方法说明
public int delete(Integer id) {
try {
studentService.deleteById(id);
return 1;
} catch (Exception e) {
return 0;
}
}
}
8、配置swagger
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。
作用:
1. 接口的文档在线自动生成。
2. 功能测试。
-
添加swagger依赖
<!--添加对swagger的依赖--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency>
-
创建Swagger2配置类
package com.nebula.jpa_vue.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class SwaggerConfig { /** * 创建API应用 * apiInfo() 增加API相关信息 * 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现, * 本例采用指定扫描的包路径来定义指定要建立API的目录。 * * @return */ @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.nebula.jpa_vue.controller")) .paths(PathSelectors.any()) .build(); } /** * 创建该API的基本信息(这些基本信息会展现在文档页面中) * 访问地址:http://项目实际地址/swagger-ui.html * @return */ private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Spring Boot中使用Swagger2实现前后端分离开发") .description("Spring-data-jpa+vue+swagger 实现一个前端后分离的小Demo") .termsOfServiceUrl("https://www.baidu.com/") .contact("星了个云") .version("1.0") .build(); } }
-
在启动类中加@EnableSwagger2
package com.nebula.jpa_vue; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import springfox.documentation.swagger2.annotations.EnableSwagger2; @SpringBootApplication @EnableSwagger2 public class JpaVueApplication { public static void main(String[] args) { SpringApplication.run(JpaVueApplication.class, args); } }
9、解决跨域
package com.nebula.jpa_vue.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
//跨域配置
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
//重写父类提供的跨域请求处理的接口
public void addCorsMappings(CorsRegistry registry) {
//添加映射路径
registry.addMapping("/**")
//放行哪些原始域
.allowedOrigins("*")
//是否发送Cookie信息
.allowCredentials(true)
//放行哪些原始域(请求方式)
.allowedMethods("GET", "POST", "PUT", "DELETE")
//放行哪些原始域(头部信息)
.allowedHeaders("*")
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
.exposedHeaders("Header1", "Header2");
}
};
}
}
10、最终项目结构
启动Spring Boot程序,访问:http://localhost:8080/swagger-ui.html
点击可看到我们所写的接口
展开可看接口详情,可测试
最后送上前端代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jpa_vue</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.js"></script>
<style>
#app{
margin-top: 15vh;
}
input {
text-align: center
}
</style>
</head>
<body style="text-align: center;">
<div id="app">
<table border="1" cellspacing="0" cellpadding="20" style="margin: 0px auto;">
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年级</th>
<th>操作</th>
</tr>
<template v-for="(student, i) in studentList">
<tr>
<td>{{student.id}}</td>
<td>{{student.name}}</td>
<td>{{student.sex}}</td>
<td>{{student.gradeId}}</td>
<td>
<a href="#" @click="Enit(student)">编辑</a>
<a href="#" @click="Delete(student.id)">删除</a>
</td>
</tr>
</template>
<template>
<tr>
<td>
<!-- readonly 不可编辑 -->
<input type="text" name="id" value="" placeholder="编号" readonly="readonly" v-model="student.id" />
</td>
<td>
<input type="text" name="name" value="" placeholder="姓名" v-model="student.name" />
</td>
<td>
<input type="text" name="sex" value="" placeholder="性别" v-model="student.sex" />
</td>
<td>
<input type="text" name="gradeId" value="" placeholder="年级" v-model="student.gradeId" />
</td>
<td>
<button type="button" @click="Save">保存</button>
</td>
</tr>
</template>
</table>
<p>{{pages}}/{{pageNum}}</p>
<button @click="Paging(1)">首页</button>
<button @click="Paging(pageNum-1)" v-if="pageNum-1>0">上一页</button>
<button @click="Paging(pageNum+1)" v-if="pageNum+1<=pages">下一页</button>
<button @click="Paging(pages)">尾页</button>
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
student: {
id: '',
name: '',
sex: '',
gradeId: ''
},
studentList: [],
// 总页码
pages: '',
// 当前页码
pageNum: ''
},
methods: {
// 分页
Paging(pageNum) {
if (pageNum == null) {
pageNum = 1
}
let that = this;
axios({
method: 'get',
url: 'http://localhost:8080/student/' + pageNum,
}).then(function (response) {
// 总页码
that.pages = response.data.totalPages;
// 当前页码
that.pageNum = response.data.pageable.pageNumber + 1;
// 学生集合
that.studentList = response.data.content;
}).catch(function (error) {
console.log('分页查询失败')
})
},
// 保存
Save() {
let that = this;
let student = JSON.stringify(that.student);
axios.post('http://localhost:8080/save', student, {
headers: {
'content-type': 'application/json;charset=utf-8'
}
}).then(res => {
// 添加成功 重新请求数据
that.Paging();
// 清空v-modle中的数据
that.student = {};
}).catch(err => {
console.error('保存失败');
})
},
// 删除
Delete(id) {
let that = this;
axios({
method: 'delete',
url: 'http://localhost:8080/delete',
params: {
id: id
}
}).then(function (response) {
// 删除成功 重新请求数据
that.Paging();
}).catch(function (error) {
console.log('删除失败')
})
},
// 编辑
Enit(student) {
this.student = student;
}
},
//窗体加载时初始化学生信息
created() {
this.Paging();
},
})
</script>
</body>
</html>
效果图