技术栈:
SpringBoot,MySQL, MybatisPlus, Knife4J,Lombok
项目初始化
使用Mybatis代码生成器生成实体类,mapper接口&xml文件等;
构建统一返回结果Result类,返回的提示信息统一封装在枚举类中。
项目初始化结构:

这里生成的mapper接口不带@mapper,并且,产生的是swagger2的@Api注解,这就需要我们额外操作。下面是生成代码器的代码
package cn.amebob.cv01;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;
public class CodeGenerator {
public static void main(String[] args) {
// 1. 数据库配置
String url = "jdbc:mysql://localhost:3306/test_db?serverTimezone=GMT%2B8";
String username = "root";
String password = "root";
FastAutoGenerator.create(url, username, password)
.globalConfig(builder -> {
builder.author("bob")
.enableSwagger()
.outputDir(System.getProperty("user.dir") + "/src/main/java");
})
.packageConfig(builder -> {
builder.parent("cn.amebob.cv01")
.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/mapper"));
})
.strategyConfig(builder -> {
builder.addInclude("Experience", "Profile", "Project", "ProjectTag", "Tag", "User")
.entityBuilder()
.enableLombok()
.idType(IdType.AUTO)
.enableTableFieldAnnotation()
.controllerBuilder()
.enableRestStyle();
})
.templateEngine(new FreemarkerTemplateEngine())
.execute();
System.out.println("代码生成成功!");
}
}
这里Result类可以使用@Builder,方便我们链式调用;
return Result.success(user).setMessage("查询个人资料成功");
Result,由于需要返回多次,非单例等问题,不交予Spring容器管理,这里采用静态方式创建Result对象,是静态工厂方法。
package cn.amebob.cv01.common;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
@Builder
@Data
public class Result<T> implements Serializable {
private int code;
private String message;
private T data;
private long timestamp;
public Result() {
this.timestamp = System.currentTimeMillis();
}
// 成功返回 - 无数据
public static <T> Result<T> success() {
return success(null);
}
// 成功返回 - 有数据
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(ResultCode.SUCCESS.getCode());
result.setMessage(ResultCode.SUCCESS.getMessage());
result.setData(data);
return result;
}
// 失败返回 - 默认信息
public static <T> Result<T> fail() {
return fail(ResultCode.INTERNAL_SERVER_ERROR.getMessage());
}
// 失败返回 - 自定义信息
public static <T> Result<T> fail(String message) {
Result<T> result = new Result<>();
result.setCode(ResultCode.INTERNAL_SERVER_ERROR.getCode());
result.setMessage(message);
return result;
}
}
遇到的问题
- 浏览器网络面板(Network)看到状态码是 200,但控制台(Console)却报错 CORS。
现象解释:浏览器已经把请求发出去了,后端也处理完并返回了数据,但浏览器发现响应头里没有准许跨域的标识,于是出于安全考虑,把已经到手的数据“没收”了,并抛出一个跨域错误给你的 JS 代码。
解决方法:前端跨域设置正确,但是request.js的baseURL设置为了` http://localhost:8080` 这是后端地址,这样前端就直接跳过了跨域代理。
上线后的跨域问题:
既然 Proxy 只管开发环境,项目上线后通常有两种方案:
Nginx 转发(最常用):在服务器上配置 Nginx,让 Nginx 扮演和 Proxy 同样的角色。
后端开启 CORS:在 SpringBoot 中配置
WebMvcConfigurer允许跨域。这样前端可以直接请求http://api.yourdomain.com而不需要任何代理。
- 父组件向子组件传输信息,子组件未展示
起初以为是pinia的问题,在使用调试工具后,确认pinia中数据更新。提供js、模版代码给ai,得到答案,js中获取ref对象的属性值需要使用.value
// 如果直接解构 const { profileInfo } = profileStore; 会失去响应式
const { profileInfo, loading } = storeToRefs(profileStore);
const info = profileInfo.value; //正确
const info = profileInfo;//错误
//铺数据时,模板中可以省去.value
<div v-if="profileInfo">
<h1>你好,我是 <span class="highlight">{{ profileInfo.name }}</span></h1>
<h2>{{ profileInfo.jobTitle }}</h2>
<p>{{ profileInfo.bio }}</p>
<SocialLinks :links="socialData" />
</div>
- 更改Vue组建数据请求时,导致其它页面空白
