• 后端SpringBoot+前端Vue前后端分离的项目(一)


    前言:后端使用SpringBoot框架,前端使用Vue框架,做一个前后端分离的小项目,需求:实现一个表格,具备新增、删除、修改的功能。

    目录

    一、数据库表的设计

    二、后端实现

    环境配置

    数据处理-增删改查

    model层

    mapper层

    XML配置

    Service层

    controller层

    单元测试

    三、前后端交互

    配置

    vite.config.ts文件配置

    创建axios实例 

    业务请求

    四、前端实现

    环境配置

    Main.vue

    interface接口

    五、效果展示

    六、总结


    一、数据库表的设计

    设计了一个merchandise表,id是编号,唯一的,类型为int,category是一级类别,type是二级类别,name是商品的名称,sum_quantity是总数量,sold_quantity是售卖的数量。

    数据库里的字段名使用的是下划线连接,在java中变量命名一般使用驼峰式,需要在application.properties文件中进行配置

    mybatis.configuration.map-underscore-to-camel-case=true

    二、后端实现

    model层

    1. package com.mrjj.java.model;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. @Data
    6. @NoArgsConstructor
    7. @AllArgsConstructor
    8. public class merchandise {
    9. public int id;
    10. public String category;
    11. public String type;
    12. public String name;
    13. public String sum_quantity;
    14. public String sold_quantity;
    15. }

    环境配置

    引入需要的依赖

    1. org.springframework.boot
    2. spring-boot-starter-web
    3. org.springframework.boot
    4. spring-boot-starter-tomcat
    5. provided
    6. org.springframework.boot
    7. spring-boot-starter-test
    8. test
    9. org.mybatis.spring.boot
    10. mybatis-spring-boot-starter
    11. 2.2.2
    12. mysql
    13. mysql-connector-java
    14. 8.0.19
    15. org.mybatis.generator
    16. mybatis-generator-core
    17. 1.4.0
    18. org.springframework.boot
    19. spring-boot-starter-thymeleaf
    20. org.projectlombok
    21. lombok
    22. com.baomidou
    23. mybatis-plus-boot-starter
    24. 3.5.3

     完成application.properties文件的配置,连接mysql

    1. server.port=8888
    2. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    3. spring.datasource.url=jdbc:mysql://localhost:3306/mrjj?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
    4. spring.datasource.username=root
    5. spring.datasource.password=123456
    6. mybatis.mapper-locations=classpath:/mapper/*.xml
    7. mybatis.configuration.map-underscore-to-camel-case=true

    数据处理-增删改查

    model层

    映射数据库中的字段

    1. package com.mrjj.java.model;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. @Data
    6. @NoArgsConstructor
    7. @AllArgsConstructor
    8. public class Merchandise {
    9. public int id;
    10. public String merchandiseCategory;
    11. public String merchandiseType;
    12. public String merchandiseName;
    13. public int sumQuantity;
    14. public int soldQuantity;
    15. }

    返回结果字段

    1. package com.mrjj.java.model;
    2. import lombok.AllArgsConstructor;
    3. import lombok.Data;
    4. import lombok.NoArgsConstructor;
    5. @Data
    6. @NoArgsConstructor
    7. @AllArgsConstructor
    8. public class Result {
    9. private Integer code;
    10. private String msg;
    11. private T data;
    12. public Result(String msg, Integer code) {
    13. this.msg = msg;
    14. this.code = code;
    15. }
    16. public Result(T data) {
    17. this.data = data;
    18. this.code = 1000;
    19. }
    20. public static Result success(T data) {
    21. Result result = new Result<>(data);
    22. result.setCode(200);
    23. result.setMsg("请求成功");
    24. return result;
    25. }
    26. public static Result success(String msg, T data) {
    27. Result result = new Result<>(data);
    28. result.setCode(200);
    29. result.setMsg(msg);
    30. return result;
    31. }
    32. public static Result fail(int code, String message, T data) {
    33. Result resultData = new Result<>();
    34. resultData.setCode(code);
    35. resultData.setMsg(message);
    36. resultData.setData(data);
    37. return resultData;
    38. }
    39. }

    mapper层

    1. package com.mrjj.java.mapper;
    2. import com.mrjj.java.model.Merchandise;
    3. import org.apache.ibatis.annotations.*;
    4. import java.util.List;
    5. @Mapper
    6. public interface MerchandiseMapper {
    7. @Select("select * from merchandise")
    8. List getMerchandise();
    9. @Insert("insert into merchandise values(#{id},#{merchandiseCategory},#{merchandiseType},#{merchandiseName},#{sumQuantity},#{soldQuantity})")
    10. int addMerchandise(Merchandise merchandise);
    11. @Delete("delete from merchandise where id=#{id}")
    12. int deleteOneMerchandise(@Param("id") Long id);
    13. int updateMerchandise(List merchandise);
    14. }

    XML配置

    注意!!!

    要配置上allowMultiQueries=true,才能批量处理!!!这个问题查了蛮久的!!!

    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.mrjj.java.mapper.MerchandiseMapper">
    6. <delete id="deleteMoreMerchandise">
    7. delete from merchandise
    8. <where>
    9. <foreach collection="list" separator="," item="item" open="id in (" close=")">
    10. #{item}
    11. foreach>
    12. where>
    13. delete>
    14. <update id="updateMerchandise" parameterType="java.util.List">
    15. <foreach collection="list" item="item" separator=";">
    16. update merchandise
    17. <set>
    18. <if test="#{item.merchandiseCategory}!=null">
    19. merchandise_category=#{item.merchandiseCategory},
    20. if>
    21. <if test="#{item.merchandiseType}!=null">
    22. merchandise_type=#{item.merchandiseType},
    23. if>
    24. <if test="#{item.merchandiseName}!=null">
    25. merchandise_name=#{item.merchandiseName},
    26. if>
    27. <if test="#{item.sumQuantity}!=null">
    28. sum_quantity=#{item.sumQuantity},
    29. if>
    30. <if test="#{item.soldQuantity}!=null">
    31. sold_quantity=#{item.soldQuantity},
    32. if>
    33. set>
    34. where id=#{item.id}
    35. foreach>
    36. update>
    37. mapper>

    Service层

    1. package com.mrjj.java.service;
    2. import java.util.List;
    3. public interface MerchandiseService {
    4. int deleteMoreMerchandise(List ids);
    5. }
    1. package com.mrjj.java.service.impl;
    2. import com.mrjj.java.mapper.MerchandiseMapper;
    3. import com.mrjj.java.service.MerchandiseService;
    4. import org.springframework.stereotype.Service;
    5. import javax.annotation.Resource;
    6. import java.util.List;
    7. @Service("MerchandiseService")
    8. public class MerchandiseServiceImpl implements MerchandiseService {
    9. @Resource
    10. MerchandiseMapper merchandiseMapper;
    11. @Override
    12. public int deleteMoreMerchandise(List ids) {
    13. int delCount = 0;
    14. for (Long id : ids) {
    15. delCount += merchandiseMapper.deleteOneMerchandise(id);
    16. }
    17. System.out.println("删除了" + delCount + "条用例");
    18. return delCount;
    19. }
    20. }

    controller层

    1. package com.mrjj.java.controller;
    2. import com.mrjj.java.mapper.MerchandiseMapper;
    3. import com.mrjj.java.model.Merchandise;
    4. import com.mrjj.java.model.Result;
    5. import com.mrjj.java.service.MerchandiseService;
    6. import org.springframework.web.bind.annotation.*;
    7. import org.springframework.web.servlet.ModelAndView;
    8. import javax.annotation.Resource;
    9. import java.util.List;
    10. @RestController
    11. @RequestMapping("/mrjjMerchandise")
    12. public class MerchandiseController {
    13. @Resource
    14. MerchandiseMapper merchandiseMapper;
    15. @Resource
    16. MerchandiseService merchandiseService;
    17. @GetMapping
    18. public Result listMerchandise() {
    19. List Marchandise = merchandiseMapper.getMerchandise();
    20. System.out.println("查到的商品是" + Marchandise);
    21. return Result.success(Marchandise);
    22. }
    23. @GetMapping("/view")
    24. public ModelAndView showMerchandise() {
    25. ModelAndView MarchandiseView = new ModelAndView();
    26. List Marchandise = merchandiseMapper.getMerchandise();
    27. MarchandiseView.addObject("mrjjMarchandiseView", Marchandise);
    28. MarchandiseView.setViewName("mrjjMarchandise");
    29. return MarchandiseView;
    30. }
    31. @PostMapping
    32. public Result addMerchandise(@RequestBody Merchandise merchandise) {
    33. int i = merchandiseMapper.addMerchandise(merchandise);
    34. if (i > 0) {
    35. return Result.success(merchandise);
    36. } else {
    37. return Result.fail(210, "新增商品信息失败", merchandise);
    38. }
    39. }
    40. @PutMapping
    41. public Result updateMerchandise(@RequestBody List MerchandiseList) {
    42. System.out.println("修改");
    43. int i = merchandiseMapper.updateMerchandise(MerchandiseList);
    44. if (i > 0)
    45. return Result.success("修改商品信息成功");
    46. else
    47. return Result.fail(230, "修改商品信息失败", MerchandiseList);
    48. }
    49. @DeleteMapping("/{id}")
    50. public Result deleteOneMerchandise(@PathVariable Long id) {
    51. System.out.println(id);
    52. int i = merchandiseMapper.deleteOneMerchandise(id);
    53. System.out.println("删除的结果是:" + i);
    54. if (i > 0) {
    55. return Result.success("删除商品成功");
    56. } else {
    57. return Result.fail(240, "删除商品信息用例失败", "删除商品信息失败");
    58. }
    59. }
    60. @DeleteMapping("/ids/{ids}")
    61. public int deleteMoreMerchandise(@PathVariable List ids) {
    62. return merchandiseService.deleteMoreMerchandise(ids);
    63. }
    64. }

    单元测试

    1. package com.mrjj.java.controller;
    2. import com.mrjj.java.model.Result;
    3. import org.junit.jupiter.api.Test;
    4. import org.junit.runner.RunWith;
    5. import org.springframework.boot.test.context.SpringBootTest;
    6. import org.springframework.test.annotation.Rollback;
    7. import org.springframework.test.context.junit4.SpringRunner;
    8. import org.springframework.transaction.annotation.Transactional;
    9. import javax.annotation.Resource;
    10. import java.util.ArrayList;
    11. import java.util.List;
    12. @SpringBootTest
    13. @RunWith(SpringRunner.class)
    14. @Transactional
    15. @Rollback(value=true)
    16. class MerchandiseControllerTest {
    17. @Resource
    18. MerchandiseController merchandiseController;
    19. @Test
    20. public void testQuery() {
    21. Result queryData = merchandiseController.listMerchandise();
    22. System.out.println(queryData);
    23. }
    24. @Test
    25. public void testDelete(){
    26. Result deleteData = merchandiseController.deleteOneMerchandise(4L);
    27. System.out.println(deleteData);
    28. }
    29. @Test
    30. public void testDeleteMore(){
    31. List list1 = new ArrayList<>();
    32. list1.add(0,5L);
    33. list1.add(1,4L);
    34. int deleteMoreData = merchandiseController.deleteMoreMerchandise(list1);
    35. System.out.println(deleteMoreData);
    36. }
    37. }

    三、前后端交互

    配置

    大致画了个流程图

    可以看到在发送请求时,路径以及变了 

    vite.config.ts文件配置

    target是本地服务的地址和端口号

    添加的路径/mrjj

    1. server:{
    2. open:true,
    3. proxy:{
    4. '/mrjj': {
    5. target: 'http://localhost:8888',
    6. changeOrigin: true,
    7. rewrite: (path) => path.replace(/^\/mrjj/, ''),
    8. },
    9. }
    10. }

    创建axios实例 

    1. import axios, { type AxiosResponse } from 'axios'
    2. const instance = axios.create({
    3. baseURL: '/mrjj',
    4. timeout: 30000,
    5. headers: { 'Content-Type': 'application/json;charset=utf-8' }
    6. })
    7. instance.interceptors.response.use(
    8. function (response: AxiosResponse) {
    9. const { code } = response.data
    10. if (code === 200) {
    11. return response.data
    12. }
    13. },
    14. function (error) {
    15. return Promise.reject(error)
    16. }
    17. )
    18. export default instance

    业务请求

    baseURL对应本地服务的接口地址

    导出后端服务增删改查方法

    1. import request from '../request'
    2. import axios, { type AxiosPromise } from 'axios'
    3. import type { MrjjMerchandise } from '@/types/merchandises/type'
    4. const instance = axios.create({
    5. baseURL: '/mrjjMerchandise',
    6. timeout: 30000,
    7. headers: { 'Content-Type': 'application/json;charset=utf-8' }
    8. })
    9. export default instance
    10. export function listMerchandiseApi(): AxiosPromise<MrjjMerchandise[]> {
    11. return request({
    12. url: '/mrjjMerchandise',
    13. method: 'get'
    14. })
    15. }
    16. export function addMerchandiseApi(data: MrjjMerchandise) {
    17. return request({
    18. url: '/mrjjMerchandise',
    19. method: 'post',
    20. data: data
    21. })
    22. }
    23. export function changeMerchandiseApi(data: MrjjMerchandise) {
    24. return request({
    25. url: '/mrjjMerchandise',
    26. method: 'put',
    27. data
    28. })
    29. }
    30. export function deleteMerchandiseApi(ids: string) {
    31. return request({
    32. url: '/mrjjMerchandise/ids/' + ids,
    33. method: 'delete'
    34. })
    35. }

    四、前端实现

    环境配置

    1. import { createApp } from 'vue'
    2. import App from './App.vue'
    3. import ElementPlus from 'element-plus'
    4. import 'element-plus/dist/index.css'
    5. import zhCn from 'element-plus/es/locale/lang/zh-cn'
    6. import VXETable from 'vxe-table'
    7. import 'vxe-table/lib/style.css'
    8. import router from './router'
    9. createApp(App).use(router).use(ElementPlus, { locale: zhCn }).use(VXETable).mount('#app')

    Main.vue