SprinBoot-data-jpa整合Vue使用Swagger2实现前后端分离

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)

猜你喜欢

转载自blog.csdn.net/Lijunhaodeboke/article/details/90814801