Note: due to the large number of codes designed in this case, it is divided into two parts to upload. This article is the first part.
1. Preparation
1.1 database
# Create category table , Primary key, primary table(1surface) CREATE TABLE t_category( cid INT PRIMARY KEY AUTO_INCREMENT, cname VARCHAR(50) ); # Create a book table, t ﹐ book, foreign key, from table(Multi table) CREATE TABLE t_book( bid INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(50), price DOUBLE(6,2), #9999.99 category_id INT #Foreign key ); # Describe one to many relationships using primary foreign key constraints ALTER TABLE t_book ADD CONSTRAINT FOREIGN KEY(category_id) REFERENCES t_category (cid); # Insert several books INSERT INTO t_category(cid,cname) VALUES(1,'Novel'); INSERT INTO t_category(cid,cname) VALUES(2,'Fantasy'); INSERT INTO t_category(cid,cname) VALUES(3,'Biography'); INSERT INTO t_book(bid,title,price,category_id) VALUES(1,'How do bad guys get it',99.9,1); INSERT INTO t_book(bid,title,price,category_id) VALUES(2,'How to practice martial arts',99.9,1); INSERT INTO t_book(bid,title,price,category_id) VALUES(3,'Break the vault of heaven',99.9,2); INSERT INTO t_book(bid,title,price,category_id) VALUES(4,'Immortal cultivation',99.9,2); INSERT INTO t_book(bid,title,price,category_id) VALUES(5,'Fairy inverse',99.9,2); INSERT INTO t_book(bid,title,price,category_id) VALUES(6,'Great Zhang Yanfeng',99.9,3); INSERT INTO t_book(bid,title,price,category_id) VALUES(7,'Those years of Tian Qirui',99.9,3); INSERT INTO t_book(bid,title,price,category_id) VALUES(8,'Xie Mingan's happy life III',99.9,3);
1.2 back end: Environment Construction
1.2.1 create project
Step 1: create maven project with Spring scaffold
1.2.2 project configuration
Step 3: modify pom.xml file and add dependency
<!--Determine spring boot Version--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.9.RELEASE</version> </parent> <dependencies> <!--web Start dependence--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--currency mapper Start dependence--> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>2.0.4</version> </dependency> <!--MySQL Database driven--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--mybatis Paging plugins--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.3</version> </dependency>
Step 4: create the application.properties file and configure the database
#Tomcat server.port=8090 #DB configuration spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/vue02?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=123456 #druid spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.initial-size=1 spring.datasource.druid.min-idle=1 spring.datasource.druid.max-active=20 spring.datasource.druid.test-on-borrow=true spring.datasource.druid.stat-view-servlet.allow=true
1.2.3 tools
Step 6: create global cross domain configuration class GlobalCorsConfig.java
package com.czxy.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; /** Global cross domain configuration class * @author yxq */ @Configuration public class GlobalCorsConfig { @Bean public CorsFilter corsFilter() { //1. Add CORS configuration information CorsConfiguration config = new CorsConfiguration(); //Which original fields are released config.addAllowedOrigin("*"); //Send Cookie information or not config.setAllowCredentials(true); //Which original domains are released (request method) config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); //get config.addAllowedMethod("PUT"); //put config.addAllowedMethod("POST"); //post config.addAllowedMethod("DELETE"); //delete config.addAllowedMethod("PATCH"); config.addAllowedHeader("*"); //2. Add mapping path UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); //3. Return to the new CorsFilter return new CorsFilter(configSource); } }
1.3 classification module: basic structure
Step 1: create Java Category and Book
package com.czxy.domain; import java.io.Serializable; import java.util.List; import javax.persistence.*; @Table(name = "t_category") public class TCategory implements Serializable { @Id @Column(name = "cid") @GeneratedValue(generator = "JDBC") private Integer cid; @Column(name = "cname") private String cname; private List<TBook> list; private static final long serialVersionUID = 1L; public List<TBook> getList() { return list; } public void setList(List<TBook> list) { this.list = list; } /** * @return cid */ public Integer getCid() { return cid; } /** * @param cid */ public void setCid(Integer cid) { this.cid = cid; } /** * @return cname */ public String getCname() { return cname; } /** * @param cname */ public void setCname(String cname) { this.cname = cname; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getClass().getSimpleName()); sb.append(" ["); sb.append("Hash = ").append(hashCode()); sb.append(", cid=").append(cid); sb.append(", cname=").append(cname); sb.append("]"); return sb.toString(); } }
package com.czxy.domain; import java.io.Serializable; import javax.persistence.*; @Table(name = "t_book") public class TBook implements Serializable { @Id @Column(name = "bid") @GeneratedValue(generator = "JDBC") private Integer bid; @Column(name = "title") private String title; @Column(name = "price") private Double price; @Column(name = "category_id") private Integer categoryId; private static final long serialVersionUID = 1L; /** * @return bid */ public Integer getBid() { return bid; } /** * @param bid */ public void setBid(Integer bid) { this.bid = bid; } /** * @return title */ public String getTitle() { return title; } /** * @param title */ public void setTitle(String title) { this.title = title; } /** * @return price */ public Double getPrice() { return price; } /** * @param price */ public void setPrice(Double price) { this.price = price; } /** * @return category_id */ public Integer getCategoryId() { return categoryId; } /** * @param categoryId */ public void setCategoryId(Integer categoryId) { this.categoryId = categoryId; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getClass().getSimpleName()); sb.append(" ["); sb.append("Hash = ").append(hashCode()); sb.append(", bid=").append(bid); sb.append(", title=").append(title); sb.append(", price=").append(price); sb.append(", categoryId=").append(categoryId); sb.append("]"); return sb.toString(); } }
Step 2: create a CategoryMapper
package com.czxy.dao; import com.czxy.domain.TCategory; import org.apache.ibatis.annotations.Mapper; @Mapper public interface TCategoryMapper extends tk.mybatis.mapper.common.Mapper<TCategory> { }
Step 3: create a CategoryService
package com.czxy.service; import org.springframework.stereotype.Service; import javax.annotation.Resource; import com.czxy.dao.TCategoryMapper; import org.springframework.transaction.annotation.Transactional; @Service @Transactional public class TCategoryService{ @Resource private TCategoryMapper tCategoryMapper; }
Step 4: CategoryController
package com.czxy.controller; import com.czxy.service.TCategoryService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController @RequestMapping("/category") public class CategoryController { @Resource private TCategoryService categoryService; }
1.5 front end: Environment Construction
1.5.1 build project
Create project
vue create vue1025
Startup project
1.5.2 layout
Modify the App.vue file to complete the page layout
<template> <div id="app"> <router-link to="/categoryList">Classified management</router-link> <router-link to="/bookList">Book management</router-link> <hr /> <!-- Component display location --> <router-view /> </div> </template> <style> #app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } #nav { padding: 30px; } #nav a { font-weight: bold; color: #2c3e50; } #nav a.router-link-exact-active { color: #42b983; } </style>
2. Classification module
2.1 query all
2.1.1 backend
Step 1: modify the CategoryService
package com.czxy.service; import com.czxy.domain.TCategory; import org.springframework.stereotype.Service; import javax.annotation.Resource; import com.czxy.dao.TCategoryMapper; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service @Transactional public class TCategoryService{ @Resource private TCategoryMapper tCategoryMapper; public List<TCategory> findAll(){ return tCategoryMapper.selectAll(); } }
Step 2: modify the CategoryController
package com.czxy.controller; import com.czxy.domain.TCategory; import com.czxy.service.TCategoryService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.List; @RestController @RequestMapping("/category") public class CategoryController { @Resource private TCategoryService tCategoryService; @GetMapping public ResponseEntity<List<TCategory>> findAll(){ List<TCategory> list = tCategoryService.findAll(); return ResponseEntity.ok(list); } }
2.1.2 front-end
Premise: install axios
npm install axios
Step 1: create the src/views/CategoryList.vue file
Step 2: modify the src/router/index.js file
Step 3: modify CategoryList.vue, the page is loaded successfully, and send ajax to query all categories
<script> import axios from 'axios' axios.defaults.baseURL = "http://localhost:8090" export default { data(){ return{ categorys:[] } }, created(){ axios.get("/category").then(res => { this.categorys = res.data }) } } </script>
Step 4: modify CategoryList.vue, data area to store data and display data
<template> <div> <table border="1"> <tr> <th>number</th> <th>Category name</th> <th>operation</th> </tr> <tr v-for="(category,index) in categorys" :key="index"> <td>{{category.cid}}</td> <td>{{category.cname}}</td> <td> Newly added modify delete </td> </tr> </table> </div> </template>
2.2 add classification
2.2.1 backend
Step 1: modify the CategoryService and add the save method
package com.czxy.service; import com.czxy.domain.TCategory; import org.springframework.stereotype.Service; import javax.annotation.Resource; import com.czxy.dao.TCategoryMapper; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service @Transactional public class TCategoryService{ @Resource private TCategoryMapper tCategoryMapper; public List<TCategory> findAll(){ return tCategoryMapper.selectAll(); } public void addCategory(TCategory tCategory){ tCategoryMapper.insert(tCategory); } }
Step 2: modify the CategoryController and add the save method
package com.czxy.controller; import com.czxy.domain.TCategory; import com.czxy.service.TCategoryService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; @RestController @RequestMapping("/category") public class CategoryController { @Resource private TCategoryService tCategoryService; @GetMapping public ResponseEntity<List<TCategory>> findAll(){ List<TCategory> list = tCategoryService.findAll(); return ResponseEntity.ok(list); } @PostMapping public ResponseEntity<Void> addCategory(@RequestBody TCategory tCategory){ tCategoryService.addCategory(tCategory); return new ResponseEntity<Void>(HttpStatus.OK); } }
2.2.2 front-end
Step 1: modify the CategoryList.vue page and add the "add" button
<template> <div> <table border="1"> <tr> <th>number</th> <th>Category name</th> <th>operation</th> </tr> <tr v-for="(category,index) in categorys" :key="index"> <td>{{category.cid}}</td> <td>{{category.cname}}</td> <td> <router-link to="/categoryAdd">Newly added</router-link> modify delete </td> </tr> </table> </div> </template>
Step 2: create the CategoryAdd.vue page
Step 3: modify route router/index.js and add route
Step 4: modify the CategoryAdd.vue page, provide the form, and bind the object
<template> <div> <table> <tr> <td>Category name</td> <td><input type="text" v-model="category.cname"></td> </tr> <tr> <td colspan="2"><input type="button" value="Newly added" ></td> </tr> </table> </div> </template> <script> import axios from 'axios' axios.defaults.baseURL = "http://localhost:8080" export default { data() { return { category:{} } } } </script> <style scoped> </style>
Step 5: modify the CategoryAdd.vue page, click the "add" button to send the ajax request
<template> <div> <table> <tr> <td>Category name</td> <td><input type="text" v-model="category.cname"></td> </tr> <tr> <td colspan="2"><input type="button" value="Newly added" @click="categoryAdd()"></td> </tr> </table> </div> </template> <script> import axios from 'axios' axios.defaults.baseURL = "http://localhost:8090" export default { data() { return { category:{} } }, methods: { categoryAdd(){ axios.post("/category",this.category).then(res => { alert("New success") this.$router.push("/categoryList") }) } }, } </script> <style scoped> </style>
2.3 modify classification
2.3.1 backend
Step 1: modify the CategoryService and add the update method
package com.czxy.service; import com.czxy.domain.TCategory; import org.springframework.stereotype.Service; import javax.annotation.Resource; import com.czxy.dao.TCategoryMapper; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service @Transactional public class TCategoryService{ @Resource private TCategoryMapper tCategoryMapper; public List<TCategory> findAll(){ return tCategoryMapper.selectAll(); } public void addCategory(TCategory tCategory){ tCategoryMapper.insert(tCategory); } public TCategory findById(Integer cid) { return tCategoryMapper.selectByPrimaryKey(cid); } public void update(TCategory category) { tCategoryMapper.updateByPrimaryKey(category); } }
Step 2: modify the CategoryController and add the update method
package com.czxy.controller; import com.czxy.domain.TCategory; import com.czxy.service.TCategoryService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; @RestController @RequestMapping("/category") public class CategoryController { @Resource private TCategoryService tCategoryService; @GetMapping public ResponseEntity<List<TCategory>> findAll(){ List<TCategory> list = tCategoryService.findAll(); return ResponseEntity.ok(list); } @PostMapping public ResponseEntity<Void> addCategory(@RequestBody TCategory tCategory){ tCategoryService.addCategory(tCategory); return new ResponseEntity<Void>(HttpStatus.OK); } @GetMapping("/{cid}") public ResponseEntity<TCategory> findById(@PathVariable("cid") Integer cid){ TCategory category = tCategoryService.findById(cid); return ResponseEntity.ok(category); } @PutMapping public ResponseEntity<String> update(@RequestBody TCategory category){ TCategoryService.update(category); return ResponseEntity.ok("Update success"); } }
2.3.2 front-end
Step 1: modify the CategoryList.vue page to add a path to modify
<template> <div> <table border="1"> <tr> <th>number</th> <th>Category name</th> <th>operation</th> </tr> <tr v-for="(category,index) in categorys" :key="index"> <td>{{category.cid}}</td> <td>{{category.cname}}</td> <td> <router-link to="/categoryAdd">Newly added</router-link> <router-link :to="'/categoryUpdate/' + category.cid">modify</router-link> //delete </td> </tr> </table> </div> </template> <script> import axios from "axios"; axios.defaults.baseURL = "http://localhost:8090"; export default { data() { return { categorys: [] }; }, created() { axios.get("/category").then(res => { this.categorys = res.data; }); } }; </script>
Step 2: create the CategoryUpdate.vue page
Step 3: modify router/index.js and configure routing path
Step 4: modify the CategoryUpdate.vue file. After the page is loaded successfully, query the details
<template> <div> <table border="1"> <tr> <td>Classification name</td> <td><input type="text" v-model="category.cname"></td> </tr> <tr> <td></td> <td><input type="button" value="To update"></td> </tr> </table> </div> </template> <script> // 1.1 import axios component import axios from 'axios' // 1.2 set basic path axios.defaults.baseURL='http://localhost:8080' export default { data() { return { category: {} } }, created() { let cid = this.$route.params.cid axios.get('/category/' + cid).then( response => { this.category = response.data console.info(response.data) }) }, } </script> <style> </style>
Step 5: modify the CategoryUpdate.vue file to complete the update operation
<template> <div> <table border="1"> <tr> <td>Classification name</td> <td> <input type="text" v-model="category.cname" /> </td> </tr> <tr> <td></td> <td> <input type="button" value="To update" @click="categoryUpdate" /> </td> </tr> </table> </div> </template> <script> // 1.1 import axios component import axios from "axios"; // 1.2 set basic path axios.defaults.baseURL = "http://localhost:8090"; export default { data() { return { category: {} }; }, methods: { categoryUpdate() { // 1.3 send ajax axios .put("/category", this.category) .then(response => { alert(response.data); this.$router.push("/categoryList"); }) .catch(error => { console.info(error); }); } }, created() { let cid = this.$route.params.cid; axios.get("/category/" + cid).then(response => { this.category = response.data; console.info(response.data); }); } }; </script> <style> </style>
2.4 delete classification
2.4.1 backend
If a category has books, it cannot be deleted.
Step 1: modify BookMapper and add findAllWithCid()
package com.czxy.dao; import com.czxy.domain.TBook; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import java.util.List; @Mapper public interface TBookMapper extends tk.mybatis.mapper.common.Mapper<TBook> { @Select("select * from t_book where category_id = #{cid}") public List<TBook> findAllWithCid(@Param("cid") Integer cid); }
Step 2: modify the CategoryService and implement the delete method
package com.czxy.service; import com.czxy.dao.TBookMapper; import com.czxy.domain.TBook; import com.czxy.domain.TCategory; import org.springframework.stereotype.Service; import javax.annotation.Resource; import com.czxy.dao.TCategoryMapper; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service @Transactional public class TCategoryService{ @Resource private TCategoryMapper tCategoryMapper; @Resource private TBookMapper tBookMapper; public List<TCategory> findAll(){ return tCategoryMapper.selectAll(); } public void addCategory(TCategory tCategory){ tCategoryMapper.insert(tCategory); } public TCategory findById(Integer cid) { return tCategoryMapper.selectByPrimaryKey(cid); } public void update(TCategory category) { tCategoryMapper.updateByPrimaryKey(category); } public void delete(Integer cid){ List<TBook> list = tBookMapper.findAllWithCid(cid); if (list != null && list.size() > 0){ throw new RuntimeException("The current classification has" + list.size() + "This book is in use, please delete it first!"); } tCategoryMapper.deleteByPrimaryKey(cid); } }
Step 3: modify the CategoryController and add the delete method
@RestController
@RequestMapping("/category")
public class CategoryController {
@Resource private CategoryService categoryService; @DeleteMapping("/{cid}") public ResponseEntity<String> delete(@PathVariable("cid") Integer cid){ try { categoryService.delete(cid); return ResponseEntity.ok("Delete successful"); } catch (Exception e) { e.printStackTrace(); return ResponseEntity.ok(e.getMessage()); } }
}
2.4.2 front-end
Step 1: modify CategoryList.vue, write categoryDelete to complete the deletion
<template> <div> <table border="1" width="400"> <tr> <td>number</td> <td>Classification name</td> <td>operation</td> </tr> <tr v-for="(category,index) in allCategory" :key="index"> <td>{{index + 1}} </td> <td>{{category.cname}} </td> <td> //View details <router-link :to="'/categoryUpdate/' + category.cid">modify</router-link> <a href="#" @click.prevent="categoryDelete(category.cid)">delete</a> </td> </tr> </table> <router-link to="/categoryAdd">Add classification</router-link> </div> </template> <script> // 1.1 import axios component import axios from 'axios' // 1.2 set basic path axios.defaults.baseURL='http://localhost:8080' export default { created() { // 1.3 after the page is loaded successfully, send ajax to query all axios.get('/category').then( response => { this.allCategory = response.data }) }, data() { return { allCategory: [] } }, methods: { categoryDelete(cid){ if(window.confirm('Are you sure you want to delete it?')){ axios.delete('/category/' + cid).then( response => { alert(response.data) }) } } }, } </script> <style> </style>
The current page cannot be refreshed. Use provide / inject to complete the refresh
The provide parent component declares a function,
In any position, the content declared by the provide r can be directly introduced through the inject descendant component
Step 2: modify the App.vue page
Refresh content by controlling display and hide
Reload() -- > changes the status to false. After the modification takes effect (this.$nextTick), immediately change the status to true
Declare reloa() as a function of all descendant components by providing
At any position of the descendant component, introduce the function of the parent component through inject: ['reload'], and call it directly through this.reload()
<template> <div id="app"> <router-link to="/categoryList">Classified management</router-link> <router-link to="/bookList">Book management</router-link> <hr/> <!-- Component display location --> <router-view v-if="isRouterAlive"/> </div> </template> <script> export default { provide () { //Allows a parent component to inject a dependency into a descendant component. Descendant components must pass inject return { reload: this.reload } }, data () { return { isRouterAlive: true } }, methods: { reload () { this.isRouterAlive = false // Delay callback after next DOM update cycle this.$nextTick(function () { this.isRouterAlive = true }) } } } </script>
Step 3: modify the CategoryList.vue page
<template> <div> <table border="1" width="400"> <tr> <td>number</td> <td>Classification name</td> <td>operation</td> </tr> <tr v-for="(category,index) in allCategory" :key="index"> <td>{{index + 1}} </td> <td>{{category.cname}} </td> <td> //View details <router-link :to="'/categoryUpdate/' + category.cid">modify</router-link> <a href="#" @click.prevent="categoryDelete(category.cid)">delete</a> </td> </tr> </table> <router-link to="/categoryAdd">Add classification</router-link> </div> </template> <script> // 1.1 import axios component import axios from 'axios' // 1.2 set basic path axios.defaults.baseURL='http://localhost:8080' export default { inject:['reload'], created() { // 1.3 after the page is loaded successfully, send ajax to query all axios.get('/category').then( response => { this.allCategory = response.data }) }, data() { return { allCategory: [] } }, methods: { categoryDelete(cid){ if(window.confirm('Are you sure you want to delete it?')){ axios.delete('/category/' + cid).then( response => { alert(response.data) this.reload() }) } } }, } </script> <style> </style>