Spring Boot+Vite+Vue3二手商城

软件环境

  • node .js v16.16.0

  • npm v8.11.0

  • jdk v1.8

  • vite v2.9.13

  • 后端JAVAIDE

    • idea 2022.2.1
  • 前端开发IDE

    • webStrom 2022.2.1

    • HBuilderX 3.6.14

  • maven-3.8.6-bin

前端框架搭建

vite 搭建

1
2
3
4
5
# npm 7+, 需要额外的双横线:
npm init vite@latest 项目名称 -- --template vue
cd 安装路径
npm install
npm run dev

引入element-plus

1
npm install element-plus --save

引入vue-router

1
npm install vue-router -S

修改vite项目下的main.js

1
2
3
4
5
6
7
8
9
10
import { createApp } from 'vue'
import ElementPlus from 'element-plus'//引入element-plus框架
import 'element-plus/dist/index.css'//应用element-plus样式
import App from './App.vue'
import router from './router'//引入vue-router

const app = createApp(App)

app.use(ElementPlus).use(router).mount('#app')
//.use(ElementPlus).use(router)使用引入的组件

前端框架编写

编写router配置

  • 在src目录下创建router目录

  • 在目录下床架index.js来配置路由文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import {
createRouter,
createWebHistory,
} from 'vue-router'

// 默认的网页标题
const defaultTitle = 'home';

// 配置路由文件
const routes = [
{
// 对应的路由路径
path: '/',
name: 'Home',
// 对应的页面
component: () => import('../views/Home.vue'),
// 对应页面的名称
meta: {hidden: true, title: "主页"}
},
]

// 创建路由对象
const router = createRouter({
history: createWebHistory("/"),
routes: routes,
})

// 改变对应页面的标题
router.beforeEach((to, from, next) => {
document.title = to.meta.title ? to.meta.title : defaultTitle;
next();
});
/**

- 输出对象
*/
export default router;

应用router配置

  • 在src目录下创建views目录,即具体的路由界面

  • 在views目录下创建需要的页面

  • 改写App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
<router-view />
</template>

<script>

</script>

<style>
* {
margin: 0;
padding: 0;
}
</style>

运行前端框架

1
npm run dev

编写登录页面

页面主体

编写SM.MS图床上传(巨坑)

在vite.config.js中配置跨域设置

1
2
3
4
5
6
7
8
9
10
server:{
proxy: {
'/api': {
secure: false,
changeOrigin: true,
target: 'https://smms.app/api/v2/',
rewrite: path => path.replace(/^\/api/, '')
}
}
}

编写前端请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<input type="file" accept="image/*" ref="picture" multiple="multiple" @change="getPicture($event)"/>
</template>

<script setup>
import axios from "axios";
function getPicture(e) {
const formData = new FormData();
formData.append("smfile", e.target.files[0]);
axios({
method: "POST",
url: "/api/upload",//sm.ms图床
headers: {'Content-Type': 'multipart/form-data', 'Authorization': 'kNpYkOLitfvgPOkitOTBwDfzNzGPMDLY'},
data: formData
}).then((response) => {
// 在控制台输出响应体中图片在服务器中的url地址
console.log(response.data)//response.data就有返回的图片地址
});
} //存储图片
</script>

<style>

</style>

后端框架搭建

配置maven(提高导包速度)

  • apache-maven-3.8.6\conf\setting.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>

<mirror>
<id>uk</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://uk.maven.org/maven2/</url>
</mirror>

<mirror>
<id>CN</id>
<name>OSChina Central</name>
<url>http://maven.oschina.net/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>

<mirror>
<id>nexus</id>
<name>internal nexus repository</name>
<url>http://repo.maven.apache.org/maven2</url>
<mirrorOf>central</mirrorOf>
</mirror>

设置idea

安装插件

  • MyBatisX

  • LomBok(默认已安装)

更改文件编码格式

  • 全改为UTF-8

改UTF-8

设置maven路径

设置maven路径

创建Spring-Boot项目

  • 使用idea自动搭建Spring-Boot项目

  • 选择生成器中的Spring Initializer

  • 将服务器URL改为:start.aliyun.com

  • 类型选择Maven

  • Java版本选Java8

  • 创建项目

    • 选择组件

    • Spring Web (SpringMVC)

    • Mybatis

    • Lombok

编写后端框架

设置application.properties来链接数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 应用名称
spring.application.name=demo
#下面这些内容是为了让MyBatis映射
#指定Mybatis的Mapper文件
mybatis.mapper-locations=classpath:mappers/*xml
#指定Mybatis的实体目录
mybatis.type-aliases-package=com.example.demo.entity
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/数据库名称?serverTimezone=GMT%2b8&characterEncoding=utf8
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=root
# 应用服务 WEB 访问端口
server.port=8080

解决跨域问题

  • 在路径下新建common 包

  • 新建Java类,命名为CorsConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;

@Configuration
public class CorsConfig {

// 当前跨域请求最大有效时长。这里默认1天
private static final long MAX_AGE = 24 * 60 * 60;

@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
corsConfiguration.setMaxAge(MAX_AGE);
source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
return new CorsFilter(source);
}
}

创建Mapper(接口)目录

在resources文件下创建mapper目录(mybatis.mapper-locations=classpath:mappers/*xml由上方该条语句来确定创建目录的位置)

创建entity(实体)类

  • 创建entity包,用于管理不同实例entity类

  • 以实例User为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 引入lombok,快速创建get,set函数
import lombok.Data;

// 标记为lombok的Data
@Data
public class User {
// 根据数据库设置对应数据类型
private Integer id;
private String username;
private String password;
private String sex;
private Integer age;
private String phone;
private String email;
private String address;
private String avatar;
}

创建和编写dao(工具)类

  • 创建dao包,用于管理不同实例dao类

  • 以实例UserDao为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

// 为controller类中使用@Autowired自动注入
@Mapper
public interface UserDao {
// 创建函数后使用Alt+Enter快捷键通过插件快速创建对应的Mapper(需要先创建Mapper接口)

// 寻找表中所有元素
List<User> findAll();

User findById(Integer id);

// @Param("username") String username 传入参数,且参数名称为"username"
User getByUser(@Param("username") String username, @Param("password") String password);

// 添加后会返回向表中添加元素的个数
int insert(User user);

int update(User user);

int deleteById(Integer id);

User findByUser(String username);
}
  • 配置相应Mapper.xml的文件头部来相互链接

  • 以UserMapper.xml文件为例

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="对应Dao类的空间地址">
</mapper>

编写Mapper(写SQL查询语句)文件

  • 以UserMapper.xml为例

  • 增:

1
2
3
4
<insert id="insert">
INSERT INTO `user`(username, password,sex,age,phone,email,address,avatar)
values (#{username}, #{password},#{sex},#{age},#{phone},#{email},#{address},#{avatar});
</insert>
  • 删:
1
2
3
4
5
<delete id="deleteById">
DELETE
from `user`
where id = #{id};
</delete>
  • 改(使用了动态判断):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<update id="update">
update `user`
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
<if test="sex != null and sex != ''">
sex = #{sex},
</if>
<if test="age != null">
age = #{age},
</if>
<if test="phone != null and phone != ''">
phone = #{phone},
</if>
<if test="email != null and email != ''">
email = #{email},
</if>
<if test="address != null and address != ''">
address = #{address},
</if>
<if test="avatar != null and avatar != ''">
avatar = #{avatar},
</if>
</set>
where id = #{id}
</update>
  • 查:

查询所有:

1
2
3
4
<select id="findAll" resultType="com.example.demo.entity.User">
SELECT *
FROM user;
</select>

通过Id查询

1
2
3
4
5
<select id="findById" resultType="com.example.demo.entity.User">
SELECT *
FROM user
WHERE id = #{id};
</select>

通过用户名和密码查询

1
2
3
4
5
6
<select id="getByUser" resultType="com.example.demo.entity.User">
SELECT *
FROM user
WHERE username = #{username}
AND password = #{password};
</select>

创建Result(返回数据打包)类

  • 在common包中创建Result类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.example.demo.common;

import lombok.Data;

@Data
public class Result {
private String code;
private String msg;
private Object data;

private static final String SUCCESS_CODE = "200";
private static final String SUCCESS_MSG = "请求成功";
private static final String ERROR_CODE = "-1";

// 成功的返回的函数(无参数)
public static Result success() {
Result result = new Result();
result.setCode(SUCCESS_CODE);
result.setMsg(SUCCESS_MSG);
return result;
}

// 有返回参数的函数
public static Result success(Object data) {
Result result = success();
result.setData(data);
return result;
}

// 请求失败后,返回一个失败原因
public static Result error(String msg) {
Result result = new Result();
result.setCode(ERROR_CODE);
result.setMsg(msg);
return result;
}
}

创建和编写controller(控制)类

  • 创建controller包,用于管理不同实例controller类

  • 以UserController为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package com.example.demo.controller;

import com.example.demo.common.Result;
import com.example.demo.dao.UserDao;
import com.example.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

// 设置该类为控制器类
@RestController
// 设置默认访问路径,即通过"127.0.0.1/user"来访问接口
@RequestMapping("/user")
public class UserController {

// 自动注入
@Autowired
private UserDao userDao;

// Get接口
@GetMapping
public Result findAll() {
return Result.success(userDao.findAll());
}

// @PathVariable需要一个参数时
@GetMapping("/{id}")
public Result findById(@PathVariable Integer id) {
return Result.success(userDao.findById(id));
}

@GetMapping("/username/{username}")
public Result findByUser(@PathVariable String username) {
return Result.success(userDao.findByUser(username));
}


// @RequestBody 需要多个参数时,直接把前端的对象转换为实体类
@PostMapping
public Result save(@RequestBody User user) {
// 一旦不满足要求就直接返回失败
if (user.getUsername() == null || user.getPassword() == null) {
return Result.error("参数错误");
}
Result result =Result.success(userDao.insert(user));
return result;
}

@PostMapping("/login")
public Result login(@RequestBody User user) {
if (user.getUsername() == null || user.getPassword() == null) {
return Result.error("参数错误");
}
User result = userDao.getByUser(user.getUsername(), user.getPassword());

if (result == null) {
return Result.error("账号或密码错误");
}

return Result.success(result);
}

@PutMapping
public Result update(@RequestBody User user) {
if (user.getId() == null) {
return Result.error("参数错误");
}
userDao.update(user);
return Result.success();
}

@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
if (id == null || id == 0) {
return Result.error("参数错误");
}
return Result.success(userDao.deleteById(id) == 1);
}
}