基于SpringBoot的项目以及功能实现

1.项目介绍

这是一个简单的项目练习,用于掌握新学习的SpringBoot技术。

● 技术栈

Vue3+ElementPlus+Axios+MyBatisPlus+SpringBoot 前后端分离

前后端分离开发,前端主体框架 Vue3 + 后端基础框架 SpringBoot

  1. 前端技术栈:Vue3+Axios+ElementPlus
  2. 后端技术栈:Spring Boot + MyBatisPlus
  3. 数据库-MySQL
  4. 项目的依赖管理-Maven
  5. 分页-MyBatis Plus 的分页插件

2.功能01-搭建Vue前端工程

2.1代码实现

以下过程,前面在讲解SSM_VUE项目时已经安装过了,包括整个vue项目的创建过程、项目结构,具体看SSM整合day02的功能01实现的笔记

  1. 先下载node.js LTS 并安装node.js的npm,用于管理前端项目包依赖
  2. 创建Vue项目(需要联网)
  3. 1)创建项目,指令vue create <项目名>
  4. 2)选择 Manually select features
  5. 3)用空格键选择Bebel、Router、Vuex
  6. 4)选择3.x
  7. 5)Use history mode for router? 输入Y,回车
  8. 6)Where do you prefer placing config for Babel, ESLint, etc.? 选择In package. json
  9. 7)Save this as a preset for future projects? (y/N) 是否要保存当前的设置,根据你意思随意选择,如果选择了的话会有 Save preset as: 让你命名当前保存的设置
  10. 8)最后回车
  11. 9)创建完毕的显示结果如下
  12. 使用idea打开刚创建的vue项目,并配置项目启动
  13. 1)点击配置Configuration,配置npm方式启动项目
  14. 2)选择serve,其他保持默认,保存
  15. 3)点击运行,即可在提示的地址访问项目
  16. 停止项目,安装element-plus插件,在项目中运行指令npm install element-plus --save
  17. 在vue.config.js中修改项目的端口,防止端口占用
module.exports = {    devServer: {        port: 10000//启动端口    }}

3.功能02-创建项目基础界面

这个功能步骤在ssm整合框架day01-功能02中也有详细描述,这里不再赘述

3.1需求分析

页面原型:

3.2思路分析

使用vue3+ElementPlus完成

3.3代码实现

(1)修改Home.vue,引入表单、搜索框、按钮组件

(2)删除HelloWorld.vue组件

(3)创建components/Header.vue

(4)创建全局的global.css(src/assets/css/global.css),以后有全局样式可以放在这里

* {    margin: 0;    padding: 0;    box-sizing: border-box;}

(5)修改src/main.js,引入global.css,同时引入ElementPlus,顺便国际化

import {createApp} from 'vue'import App from './App.vue'import router from './router'import store from './store'//引入cssimport '@/assets/css/global.css' //引入ElementPlusimport ElementPlus from 'element-plus'import 'element-plus/dist/index.css'//国际化import zhCn from 'element-plus/es/locale/lang/zh-cn' createApp(App).use(store).use(router).use(ElementPlus, {locale: zhCn}).mount('#app')

(6)Header.vue,引入ElementPlus组件的下拉框

(7)创建侧边栏组件Aside.vue,引入导航菜单组件

(8)在App.vue将页面分成三部分

(9)项目的基本页面如下:

4.功能03-创建SpringBoot后端项目

4.1需求分析

项目前后端分离情况如下:分成两个子项目(前端和后端),现在来完成后端的子项目创建。

4.2代码实现

(1)创建maven项目,引入需要的依赖

    spring-boot-starter-parent    org.springframework.boot    2.5.3                 org.springframework.boot        spring-boot-starter-web        2.5.3                    mysql        mysql-connector-java        8.0.26                    org.springframework.boot        spring-boot-configuration-processor                    org.projectlombok        lombok                    org.springframework.boot        spring-boot-starter-test                    com.alibaba        druid        1.1.17                    com.baomidou        mybatis-plus-boot-starter        3.4.3    

(2)application.yml中配置port和配置DB连接信息

server:  port: 9090spring:  datasource:    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql://localhost:3306/springboot_furn?useSSL=true&useUnicode=true&characterEncoding=UTF-8    username: root    password: 123456

(3)主程序

@SpringBootApplicationpublic class Application {    public static void main(String[] args) {        SpringApplication.run(Application.class, args);    }}

测试启动,运行成功:

(4)配置数据源

package com.li.furn.config; import com.alibaba.druid.pool.DruidDataSource;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; /** * @author 李 * @version 1.0 */@Configurationpublic class DruidInitConfig {    @ConfigurationProperties("spring.datasource")    @Bean    public DataSource getDataSource(){        DruidDataSource druidDataSource = new DruidDataSource();        return druidDataSource;    }}

5.功能04-添加家居信息

5.1需求分析

在前端点击添加家居,弹出一个对话框,可以让我们填写家居的数据,填完之后点击确定,可以将数据发送到后端,然后保存到数据库表中。

5.2思路分析

  1. 完成后台代码从mapper->service->controller,并第每层代码进行测试,到controller这一层,使用postman发送http请求完成测试。
  2. 完成前台代码,使用axios发送json数据给后台,实现添加家居信息

5.3代码实现

5.3.1创建数据库和表

-- 创建数据库DROP DATABASE IF EXISTS springboot_furn;CREATE DATABASE springboot_furn;USE springboot_furn; -- 创建表CREATE TABLE furn(`id` INT(11) PRIMARY KEY AUTO_INCREMENT,#id`name` VARCHAR(64) NOT NULL,#家居名`maker` VARCHAR(64) NOT NULL,#厂商`price` DECIMAL(11,2) NOT NULL,#价格`sales` INT(11) NOT NULL,#销量`stock` INT(11) NOT NULL#库存)CHARSET=utf8;

5.3.2工具类

(2)创建 com/li/furn/util/Result.java,该工具类用于返回结果(json 格式)

package com.li.furn.util; /** * @author 李 * @version 1.0 */public class Result {    private String code;//状态码 200-success 400-fail    private String msg;//状态说明    private T data;//返回的数据,使用泛型     public Result() {    }     public Result(T data) {        this.data = data;    }     //返回需要的result对象,表示成功    public static Result success() {        Result result = new Result<>();        result.setCode("200");        result.setMsg("success");        return result;    }     //返回成功的result对象,表示成功,同时携带数据    //如果需要在static方法中使用泛型,需要在static关键字后添加    public static  Result success(T data) {        Result result = new Result<>(data);        result.setCode("200");        result.setMsg("success");        return result;    }     //返回需要的result对象-表示失败    //因为失败的原因有很多中,因此直接将其作为参数传进来    public static Result error(String code, String msg) {        Result result = new Result<>();        result.setCode(code);        result.setMsg(msg);        return result;    }     //返回成功的result对象,表示失败,同时携带数据    public static  Result error(String code, String msg, T data) {        Result result = new Result<>(data);        result.setCode(code);        result.setMsg(msg);        return result;    }     public String getCode() {        return code;    }     public void setCode(String code) {        this.code = code;    }     public String getMsg() {        return msg;    }     public void setMsg(String msg) {        this.msg = msg;    }     public T getData() {        return data;    }     public void setData(T data) {        this.data = data;    }}

5.3.3bean层

创建furn表映射的bean--Furn.java

package com.li.furn.bean; import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor; /** * @author 李 * @version 1.0 */@Data@NoArgsConstructor@AllArgsConstructorpublic class Furn {    private Integer id;    private String name;    private String maker;    private double price;    private Integer sales;    private Integer stock;}

5.3.4mapper层

创建funMapper.java接口

package com.li.furn.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.li.furn.bean.Furn;import org.apache.ibatis.annotations.Mapper; /** * @author 李 * @version 1.0 * 如果是MyBatisPlus,FurnMapper接口可以通过mp提供的BaseMapper接口来扩展功能 *///@Mapper 这里如果没有添加mapper注解,可以在主程序中指定扫描public interface FurnMapper extends BaseMapper {}

如果使用@MapperScan(basePackages = "xxx") ,需要指定到确切的包

测试FurnMapper接口

package com.li.furn; import com.li.furn.bean.Furn;import com.li.furn.mapper.FurnMapper;import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; /** * @author 李 * @version 1.0 *///注意,测试时,如果测试的类和对应源码中的类的包名不同,需要手动指定@SpringBootTestpublic class FurnMapperTest {    //装配FurnMapper对象(实际上是该接口的代理对象)    @Resource    private FurnMapper furnMapper;     @Test    public void furnMapperTest() {        Furn furn = furnMapper.selectById(1);        System.out.println("furn=" + furn);    }}

测试结果:

5.3.5service层

FurnService接口:

package com.li.furn.service; import com.baomidou.mybatisplus.extension.service.IService;import com.li.furn.bean.Furn; /** * @author 李 * @version 1.0 */ public interface FurnService extends IService {}

FurnServiceImpl实现类:

package com.li.furn.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.li.furn.bean.Furn;import com.li.furn.mapper.FurnMapper;import com.li.furn.service.FurnService;import org.springframework.stereotype.Service; /** * @author 李 * @version 1.0 */@Servicepublic class FurnServiceImpl        extends ServiceImpl        implements FurnService {}

service层测试:测试成功

package com.li.furn;...    @SpringBootTestpublic class ApplicationTest {    @Resource    private FurnService furnService;     @Test    public void furnServiceTest() {        List furns = furnService.list();        for (Furn furn : furns) {            System.out.println("furn=" + furn);        }    }}

5.3.6controller层

注意:如果是以表单形式提交数据,则不需要在参数前添加@RequestBody注解;如果使用了@RequestBody注解,要注意测试时,向后端发送的数据是json格式(Content-Type)。

package com.li.furn.controller; import com.li.furn.bean.Furn;import com.li.furn.service.FurnService;import com.li.furn.util.Result;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @author 李 * @version 1.0 * 因为当前项目为前后端分离,在默认情况下,前端发出请求 * 后端返回json数据,为了方便,我们就在类上使用@RestController */@RestController//ResponseBody+Controller@Slf4jpublic class FurnController {    @Resource    private FurnService furnService;     /**     * 完成添加添加家居信息的功能     *     * 1.因为前端发送的数据通常也是使用json格式的,     * 因此使用 @RequestBody 将前端提交的 json数据,封装成 Javabean 对象     * 2.如果前端是以表单形式提交的,则不能使用 @RequestBody     *     * @param furn     * @return     */    @PostMapping("/save")    public Result save(@RequestBody Furn furn) {        log.info("furn={}", furn);        furnService.save(furn);        return Result.success();//返回成功数据    }}

postman进行测试:(注意Headers中的Content-Type属性要指定为"application/json",否则会出错)

测试结果:

数据库显示插入成功:

5.3.7解决id自增长问题

furn表的id字段被设计为自增长,但是当实际插入数据时,如果没有给定id的值,底层执行的时候将会报错:

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: Could not set property 'id' of 'class com.li.furn.bean.Furn' with value '1640682391397732353' Cause: java.lang.IllegalArgumentException: argument type mismatch

这是因为底层没有获取到自增长字段的值。我们可以使用@TableId来解决,该注解可以标识表的主键,并且如果指定的是自增主键,会将自增主键值返回到实体类中。

Mybatis中需要使用 useGeneratedKeys,keyProperty,keyColumn 设置自增主键值的回返,在实体类对象中获取即可。在MybatisPlus中在进行数据新增时,在新增成功后,会自动的将自增的主键值返回到实体类对象中,前提是需要在实体类中使用@TableId表明主键字段,并且为自增类型。

5.3.8前端代码

(1)在前端项目中安装axios,用于发送ajax请求给后台:npm i axios -S

(2)创建工具文件src/utils/request.js,用于创建axios request对象

//引入axios// 如果在启动前端项目,提示找不到axios,把光标放在import axios from 'axios' 的 'axios' 上// 会有一个修复提示,导入 axios,点击导入即可正常使用import axios from "axios";//通过axios创建对象-request对象,用于发送请求到后端const request = axios.create({    timeout: 5000}) //对request拦截器的处理//1.可以对请求做统一的处理//2.比如统一地加入token,Content-Type等request.interceptors.request.use(    config => {        config.headers['Content-Type'] = 'application/json;charset=uft-8';        return config;    },    error => {        return Promise.reject(error)    }) //导出request对象export default request;

(3)在Home.vue中添加表单,添加添加按钮,可以出现添加家居的对话框:代码略

(4)解决跨域问题

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。在前后端分离的模式下,前后端的域名是不一致的,此时就会发生跨域访问问题。在请求的过程中我们要想回去数据一般都post/get请求,所以跨域问题出现。

解决跨域问题的方案很多,这里在vue.config.js文件中修改跨域配置来解决:

const {defineConfig} = require('@vue/cli-service')module.exports = defineConfig({    transpileDependencies: true})module.exports = {    devServer: {        port: 10000,//启动端口        proxy: {//设置代理            'api/': {//设置拦截器 拦截器格式(斜杠+拦截器名字)                target: 'http://localhost:9090',//目标地址(后端地址)                changeOrigin: true,//是否设置同源,实现跨域                pathRewrite: {//路径重写                    '/api': ''//选择忽略拦截器里面的单词                }            }        }    }}

注意,设置之后需要重新启动前端项目。

注意两点问题:

  1. 一定要确定 request.post("/api/save") 替换后是项目后台服务对应提供的API接口url,否则报404错误
  2. 当执行跨域请求时,如果浏览器仍然提示 http://localhost:9090/api/xxx
展开阅读全文

页面更新:2024-04-11

标签:功能   项目   家居   注解   端口   接口   对象   代码   测试   数据

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top