SpringDataJPA+SpringBoot+Swagger2+vue.js前後端分離實現基本CURD

Vue.js 是什麼

Vue (讀音 /vjuː/,類似於 view) 是一套用於構建用戶界面的漸進式框架。與其它大型框架不同的是,Vue 被設計爲可以自底向上逐層應用。Vue 的核心庫只關注視圖層,不僅易於上手,還便於與第三方庫或既有項目整合。另一方面,當與現代化的工具鏈以及各種支持類庫結合使用時,Vue 也完全能夠爲複雜的單頁應用提供驅動。

vue.js官網 ==> https://cn.vuejs.org/

vue.js菜鳥教程學習文檔 ==> https://www.runoob.com/vue2/vue-tutorial.html

Swagger 官網 ==> https://swagger.io/

Swagger 2簡介

它可以輕鬆的整合到Spring Boot中,並與Spring MVC程序配合組織出強大RESTful API文檔。它既可以減少我們創建文檔的工作量,同時說明內容又整合入實現代碼中,讓維護文檔和修改代碼整合爲一體,可以讓我們在修改代碼邏輯的同時方便的修改文檔說明。另外Swagger2也提供了強大的頁面測試功能來調試每個RESTful API。

話不多說開始擼碼

先導入pom.xml依賴

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zhaolei</groupId>
    <artifactId>jpa-swagger-vue</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>jpa-swagger-vue</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</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-thymeleaf</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>
            <optional>true</optional>
        </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>
		
		<!--下面兩個是swagger2所需要的依賴-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.8.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

(注意導入swagger2相關的依賴)
pojo實體類

package com.zhaolei.jpaswaggervue.pojo;

import lombok.Data;

import javax.persistence.*;
import java.io.Serializable;

/**
 * @author 15579
 * 2019/6/3 14:09
 * 文件說明:Student實體類
 */
@Data
@Table
@Entity //數據庫沒有此實體類對應的表就會自動生成
public class Student implements Serializable {
    //自動增長
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column
    private String name;

    @Column
    private String sex;
    
    @Column
    private  Integer gradeId;
}

Dao層

package com.zhaolei.jpaswaggervue.dao;

import com.zhaolei.jpaswaggervue.pojo.Student;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

/**
 * @author 15579
 * 2019/6/3 14:21
 * 文件說明:StudentDao層
 */
@Repository
public interface StudentDao extends JpaRepository<Student,Integer>, JpaSpecificationExecutor<Student>{
    //nativeQuery =true 表示這是原生SQL
    @Query(value = "SELECT * from student where `name` like concat('%',?,'%')",nativeQuery = true)
    Page<Student> findLikeNameByPage(String name, Pageable pageable);
}

Service層

package com.zhaolei.jpaswaggervue.service;

import com.zhaolei.jpaswaggervue.pojo.Student;
import org.springframework.data.domain.Page;

import java.util.List;

/**
 * @author 15579
 * 2019/6/4 14:26
 * 文件說明:
 */
public interface StudentService {
    /**
     * 新增學生信息
     * @param student
     * @return
     */
    Student save(Student student);

    /**
     * 修改
     * @param student
     * @return
     */
    Student update(Student student);

    /**
     * 刪除學生
     * @param id
     */
    void deleteStu(Integer id);

    /**
     * 分頁查詢
     * @param pageNum
     * @param pageSize
     * @return
     */
    Page<Student> findByPage(Integer pageNum, Integer pageSize, Student student);

    /**
     * 根據編號查詢
     * @param id
     * @return
     */
    Student findStudentById(Integer id);
}

impl層

package com.zhaolei.jpaswaggervue.service.impl;

import com.zhaolei.jpaswaggervue.dao.StudentDao;
import com.zhaolei.jpaswaggervue.pojo.Student;
import com.zhaolei.jpaswaggervue.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author 15579
 * 2019/6/4 14:27
 * 文件說明:
 */
@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentDao studentDao;

    /**
     * 新增學生信息
     *
     * @param student
     * @return
     */
    @Override
    public Student save(Student student) {
        return studentDao.save(student);
    }

    /**
     * 修改
     *
     * @param student
     * @return
     */
    @Override
    public Student update(Student student) {
        return studentDao.save(student);
    }

    /**
     * 刪除學生
     *
     * @param id
     */
    @Override
    public void deleteStu(Integer id) {
        studentDao.deleteById(id);
    }

    /**
     * 分頁查詢
     *
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Page<Student> findByPage(Integer pageNum, Integer pageSize,Student student) {
        if(pageNum==null||pageNum==0){
            pageNum=1;
        }
        if(pageSize==null||pageSize==0){
            pageSize=2;
        }
//        第一種方式模糊查詢並且分頁
//        ExampleMatcher matcher = ExampleMatcher.matching()
//                .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.startsWith())//模糊查詢匹配開頭,即{username}%
//                .withIgnorePaths("sex")
//                .withIgnorePaths("id");
//        Example<Student> example = Example.of(student, matcher);

        PageRequest of=PageRequest.of(pageNum-1,pageSize);
        //第一種方式
        // Page<Student> page=studentDao.findAll(example,of);
        //第二種方式模糊查詢並且分頁
        Page<Student> page=studentDao.findLikeNameByPage(student.getName()==null?"":student.getName(),of);
        return page;
    }

    /**
     * 根據編號查詢
     *
     * @param id
     * @return
     */
    @Override
    public Student findStudentById(Integer id) {
        return studentDao.findById(id).get();
    }
}

controller層

package com.zhaolei.jpaswaggervue.controller;

import com.zhaolei.jpaswaggervue.pojo.Student;
import com.zhaolei.jpaswaggervue.service.StudentService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

/**
 * @author 15579
 * 2019/6/3 14:28
 * 文件說明:Student控制層
 */
@RestController
@Api(value = "Swagger2 api 註釋 Student控制層")
public class StuController {
    @Autowired
    private StudentService studentService;

    //根據條件分頁查詢
    @GetMapping("/findByPage")
    @ApiOperation(value = "分頁查詢",notes = "根據姓名模糊查詢並分頁")
    public Object findByPage(Integer pageNum, Integer pageSize, Student student){
        if(pageNum==null||pageNum<=0){
            pageNum=1;
        }
        Page<Student> page = studentService.findByPage(pageNum, pageSize,student);
       return  page;
    }

    //根據ID刪除學生
    @DeleteMapping("/deleteStu")
    @ApiOperation(value = "刪除",notes = "根據ID刪除學生")
    public  int delteStu(@RequestParam("id") Integer id){
        System.out.println(id);
        try {
            studentService.deleteStu(id);
            return 1;
        }catch (Exception e){
            return 0;
        }
    }

    //修改學生信息
    @PutMapping("/updateStu")
    @ApiOperation(value = "修改",notes = "修改學生信息")
    public  Object updateStu(@RequestBody Student student){
        Student updStudent = studentService.update(student);
        return  updStudent;
    }

    //新增學生信息
    @PostMapping("/addStu")
    @ApiOperation(value = "新增",notes = "新增學生信息")
    public Object addStu(@RequestBody Student student){
        System.out.println(student.getName());
        Student save = studentService.save(student);
        return  save;
    }


    //跳轉至編輯頁面
    @GetMapping("/gotoEdit")
    @ApiOperation(value = "跳轉至編輯頁面",notes = "根據編號判斷是修改還是新增")
    public String gotoEdit(Integer id,Model model){
        if(id!=null){
            //根據ID查詢學生信息並顯示在頁面
            Student student = studentService.findStudentById(id);
            model.addAttribute("stu",student);
        }
        return "edit";
    }
}

然後編寫swagger2的配置類

package com.zhaolei.jpaswaggervue.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 {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.zhaolei.jpaswaggervue.controller"))//改成你項目的controller層路徑
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring Boot中使用Swagger2實現前後端分離開發")
                .description("此項目只是練習如何實現前後端分離開發的小Demo")
                .termsOfServiceUrl("https://blog.csdn.net/weixin_44530530")
                .contact("***")
                .version("1.0")
                .build();
    }
}

注意:需要在SpringBoot項目的應用程序入口類中開啓swagger2如下所示

package com.zhaolei.jpaswaggervue;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@EnableSwagger2      //開啓swagger2 api接口文檔
public class JpaSwaggerVueApplication {
    public static void main(String[] args) {
        SpringApplication.run(JpaSwaggerVueApplication.class, args);
    }
}

讓後就可以啓動我們的項目我的端口號是8080:瀏覽器輸入
http://localhost:8080/swagger-ui.html
然後會出現如下頁面就代表你的swagger2 ui 的api接口已經生成好了
在這裏插入圖片描述

後端代碼基本已經編寫完畢接下來使用寫前段頁面接收後端返回的json數據
我前段使用的框架是vue.js 使用的軟件是HbuilderX

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
	</head>
	<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
	<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
	<body>
		<div id="app">
			<label>姓名:</label>
			<input type="text" name="likeName" v-model="likeName" />
			<input type="button" v-on:click="findByPage(1)" value="查詢"  />
			<table border="1" cellspacing="1" cellpadding="20">
				<tr>
					<th>編號</th>
					<th>姓名</th>
					<th>性別</th>
					<th>年級</th>
					<th>操作</th>
				</tr>
				<template v-for="stu in stuList">
					<tr>
						<td>{{stu.id}}</td>
						<td>{{stu.name}}</td>
						<td>{{stu.sex}}</td>
						<td>{{stu.gradeId}}</td>
						<td>
							<a href="javascript:void(0)" v-on:click="del(stu.id)">刪除</a>
							<a href="javascript:void(0)" v-on:click="edit(stu)">編輯</a>
						</td>
					</tr>
				</template>
			</table>
			<template>
				<table>
					<tr>
						<td>
							編號:<input type="text" name="id" v-model="student.id" placeholder="編號無需自己填寫" readonly="readonly" />
						</td>
						<td>
							姓名:<input type="text" name="name" v-model="student.name" />
						</td>
						<td>
							性別:<input type="text" name="sex" v-model="student.sex" />
						</td>
						<td>
							年級:<input type="text" name="gradeId" v-model="student.gradeId" />
						</td>
						<td>
							<input type="button" value="保存" v-on:click="add(student)" />
						</td>
					</tr>
				</table>
			</template>
			<a href="javascript:void(0)" v-on:click="findByPage(1)">首頁</a>
			<a href="javascript:void(0)" v-on:click="findByPage(page.number)">上一頁</a>
			<a href="javascript:void(0)" v-on:click="findByPage(page.number+2)">下一頁</a>
			<a href="javascript:void(0)" v-on:click="findByPage(page.totalPages)">尾頁</a>
			當前第<span v-text="page.number+1"></span>頁/共{{page.totalPages}}頁
		</div>
	</body>
		<!-- vue.js代碼 -->
		<script>
		var app = new Vue({
			el: "#app",
			data: {
				likeName:"",
				student: {
					id: "",
					name: "",
					sex: "",
					gradeId: ""
				},
				stuList: [],
				page:{}
			},
			methods: {
				findByPage: function(pageNum) {
					var _this = this;
					var likeName=this.likeName;
					if(pageNum!=null||pageNum!=''){
						if(pageNum>_this.page.totalPages){
							pageNum=_this.page.totalPages
						}
					}
					axios.get('http://localhost:8080/findByPage', {
							params: {
								pageNum: pageNum,
								name: likeName
							}
						})
						.then(function(response) {
							console.log(response.data)
							_this.page=response.data;
							_this.stuList = response.data.content;
						})
						.catch(function(error) { // 請求失敗處理
							console.log(error);
						});
				},
				del: function(id) {
					var _this = this;
					console.log(id)
					let delId = id;
					axios.delete('http://localhost:8080/deleteStu', {
							params: {
								id: delId
							}
						})
						.then(function(response) {
							console.log(response.data)
							if (response.data == 1) {
								_this.findByPage();
								alert("刪除成功");
							}
						})
						.catch(function(error) { // 請求失敗處理
							console.log(error);
						});
				},
				add: function(student) {
					var _this = this;
					console.log(student.id);
					if (student.id != null&&student.id !='') {
						var stu = JSON.stringify(student);
						axios.put('http://localhost:8080/updateStu',stu, {
								headers: {
									'Content-Type':'application/json;charset=utf-8'
								}
							})
							.then(function(response) {
								alert("修改成功")
								_this.findByPage();
								_this.student.id=null;
								_this.student.name=null;
								_this.student.sex=null;
								_this.student.gradeId=null;
							})
							.catch(function(error) { // 請求失敗處理
								console.log(error);
							});

					} else {
						axios.post('http://localhost:8080/addStu',student, {
								headers: {
									'Content-Type':'application/json;charset=utf-8'
								}
							})
							.then(function(response) {
								alert("新增成功")
								_this.findByPage();
								_this.student.name=null;
								_this.student.sex=null;
								_this.student.gradeId=null;
							})
							.catch(function(error) { // 請求失敗處理
								console.log(error);
							});
					}
				},
				edit: function(student) {
					this.student = student;
				}
			},
			// 鉤子 在Vue創建時就運行
			created: function() {
				this.findByPage();
			}
		})
	</script>
</html>

注意:

  1. 對象參數類型JSON化: data:JSON.stringify(object)
  2. 頭部信息headers:“Content-Type”: “application/json; charset=UTF-8”
  3. controller層中請求方式寫爲POST
  4. 後臺controller中獲得參數方式:@RequestBody String Object
  5. String轉換爲json:JSONObject accident=JSONObject.fromObject(newsObject);

保存ctrl+r選擇瀏覽器運行 然後會發現頁面數據出不來按F12會發現報錯
在這裏插入圖片描述
出現這個錯誤的原因是因爲沒有考慮到跨域問題,所以還需要在後端SpringBoot項目添加一個解決跨域問題的配置類代碼如下:

package com.zhaolei.jpaswaggervue.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");
            }
        };
    }
}

然後重啓項目並刷新頁面
在這裏插入圖片描述
數據出來了!問題完美解決so easy!打完收功!
最後附上後端git倉庫地址:https://gitee.com/riven666/jpa-swagger-vue

發佈了26 篇原創文章 · 獲贊 12 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章