SprinBoot整合Vue使用Swagger2实现前后端分离
首先是后台
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>
创建Swagger工具类
SwaggerConfig 类
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.lijunhao.springdatajpa01.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2实现前后端分离开发")
.description("此项目只是练习如何实现前后端分离开发的小Demo")
.termsOfServiceUrl("https://blog.csdn.net/ca1993422")
.contact("聂长安")
.version("1.0")
.build();
}
}
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");
}
};
}
}
导入jpa需要的相关依赖后配置yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/studentdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&zeroDateTimeBehavior=CONVERT_TO_NULL
jpa:
database: mysql
hibernate:
ddl-auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true
profiles:
active: local
实体类
@Data
@Entity
public class Student {
@Id //主键标识
private String stuid;
private String name;
private String sex;
@ManyToOne /因为我这里写了两表 用这个注解标记多对一
@JoinColumn(name="gradeId") //给字段命名 用于自动生成的表字段名
private Grade grade;
}
@Data
@Entity
public class Grade {
@Id
private Long gradeId;
private String name;
}
Dao层
继承JpaRepository<实体类,主键字段>
jpa最强大的就是 所有方法都可以自动生成 简单的增删改查条件查询基本都能通过方法名自动生成 所以dao层接口不需要写方法
public interface GradeMapper extends JpaRepository<Grade,Long> {
}
public interface StudentMapper extends JpaRepository<Student,String>, JpaSpecificationExecutor<Student> {
}
Service层
@Service
public class StudentServiceImpl {
@Autowired
private StudentMapper studentMapper;
/**
* 查询所有 分页查询
* @param pageNum
* @param size
* @return
*/
public Page<Student> students(Integer pageNum, Integer size){
if(pageNum==null||pageNum<0){
pageNum=0;
}
if (size==null){
size=2;
}
return studentMapper.findAll(PageRequest.of(pageNum,size));
}
/**
* 根据id删除
* @param id
*/
public void del(String id){
try {
studentMapper.deleteById(id);
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 新增 新增和修改都是用save方法 有id执行新增反之修改
* @param student
* @return
*/
public Student add(Student student){
return studentMapper.save(student);
}
/**
* 修改
* @param student
* @return
*/
public Student upd(Student student){
return studentMapper.save(student);
}
}
Controller层
@RestController
@Api(value = "swagger ui 注释 api 级别")
public class StudentController {
@Autowired
private StudentServiceImpl studentService;
@Autowired
private GradeMapper gradeMapper;
@Autowired
private IdWorker idWorker;
@GetMapping("/students")
@ApiOperation(value = "查询所有学生", notes = "查询所有学生")
public Page<Student> findAll(Integer pageNum, Integer size) {
Page<Student> students = studentService.students(pageNum, size);
return students;
}
@GetMapping("/grades")
@ApiOperation(value = "查询所有年级", notes = "查询所有年级")
public List<Grade> findAllGrade(Integer pageNum, Integer size) {
List<Grade> grades = gradeMapper.findAll();
return grades;
}
@DeleteMapping("/student/{id}")
@ApiOperation(value = "根据id删除学生", notes = "根据id删除学生")
public int del(@PathVariable("id") String id) {
try {
studentService.del(id);
return 1;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@PostMapping("/student")
@ApiOperation(value = "新增学生", notes = "新增学生")
public Student add(@RequestBody Student student) {
Long id = idWorker.nextId();
//设置id
student.setStuid(id.toString());
return studentService.add(student);
}
@PutMapping("/student")
@ApiOperation(value = "修改学生", notes = "修改学生")
public Student upd(@RequestBody Student student) {
return studentService.upd(student);
}
}
```
着用后台基本就搞定了
swagger生成的接口文档可以通过
协议://IP地址:端口号/swagger-ui.html
如:http://localhost:8080/swagger-ui.html
#### 然后是前端
html页面
```html
<!-- 通过CDN引入Vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 通过CDN引入axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
```
首页
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 通过CDN引入Vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 通过CDN引入axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<table border="1">
<tr>
<td>#</td>
<td>姓名</td>
<td>性别</td>
<td>年级</td>
<td>操作</td>
</tr>
<tr v-for="stu in pages.content">
<td>{{stu.stuid}}</td>
<td>{{stu.name}}</td>
<td>{{stu.sex}}</td>
<td>{{stu.grade.name}}</td>
<td>
<button @click="delStudent(stu.stuid)">删除</button>
<button @click="updStudent(stu)">修改</button>
</td>
</tr>
<tr>
<td><input type="text" v-model="student.stuid" readonly></td>
<td><input type="text" v-model="student.name"></td>
<td><input type="text" v-model="student.sex"></td>
<td>
<select v-model="student.grade.gradeId">
<option value=""></option>
<option v-for="g in grades" :value="g.gradeId">{{g.name}}</option>
</select>
</td>
<td><button @click="addStudent()">提交</button></td>
</tr>
</table>
<button @click="page(0)">首页</button>
<button @click="page(pages.number-1)">上一页</button>
<button v-show="pages.number<pages.totalPages-1" @click="page(pages.number+1)">下一页</button>
<button v-show="pages.number>=pages.totalPages-1" @click="page(pages.totalPages-1)">下一页</button>
<button @click="page(pages.totalPages-1)">尾页</button>
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data: {
student: {
stuid: '',
name: '',
sex: '',
grade: {
gradeId: '',
name: ''
}
},
pages: [],
grades: []
},
methods: {
findAllStudent: function(pageNum, size) {
axios.get('http://localhost:8080/students', {
params: {
pageNum: pageNum,
size: size
}
})
.then((response) => {
this.pages = response.data;
})
.catch(function(error) {
console.log(error);
});
},
findAllGrade: function() {
axios.get('http://localhost:8080/grades')
.then((response) => {
console.log(response.data);
this.grades = response.data;
})
.catch(function(error) {
console.log(error);
});
},
addStudent() {
var _this = this;
if (_this.student.stuid != null && _this.student.stuid != '') {
axios.put('http://localhost:8080/student', _this.student, {
headers: {
"Content-Type": "application/json;charset=utf-8" //头部信息
}
})
.then((response) => {
//保存完之后查询所有的信息
_this.student.stuid = null;
_this.student.name = null;
_this.student.sex = null;
_this.student.gradeId = null;
_this.findAllStudent();
})
.catch(function(error) {
console.log(error);
});
} else {
axios.post('http://localhost:8080/student', _this.student, {
headers: {
"Content-Type": "application/json;charset=utf-8" //头部信息
}
})
.then((response) => {
//保存完之后查询所有的信息
_this.student.name = null;
_this.student.sex = null;
_this.student.gradeId = null;
_this.findAllStudent();
})
.catch(function(error) {
console.log(error);
});
}
},
delStudent(sid) {
var _this = this;
axios.delete("http://localhost:8080/student/" + sid)
.then(function(response) {
_this.findAllStudent();
})
.catch((error) => {
console.log(error)
})
},
page(pageNum) {
this.findAllStudent(pageNum, 2);
},
updStudent(stu) {
this.student = stu;
}
},
created: function() { //创建vue对象的时候自动调用查询所有的方法
this.findAllStudent();
this.findAllGrade();
}
})
</script>
</html>
```
效果
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190604224247597.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xpanVuaGFvZGVib2tl,size_16,color_FFFFFF,t_70)