本节主要是讲解了项目搭建时候需要的基本结果,如lombook注解帮我减少繁琐的Getter和Setter方法,Swagger接口文档帮我们前后端更好的协调开发,以及统一接口工具类,自定义全局异常和单元测试等。通过本节,可以让我们更好的了解项目开发的基础搭建过程。
记录、交流、实践,让每一份付出皆可看见,让你我共同前行😁
1.Lombook引入
Lombook注解是一个可以通过简单的注解形式来帮我们简化消除一些必须有但显得很臃肿的Java代码工具。
- @Getter / @Setter:作用于类上时,为所有成员变量生成 getter/setter 方法;作用于成员变量上时,仅为该变量生成 getter/setter 方法。
- @ToString:作用于类,覆盖默认的 toString () 方法,生成包含类信息和成员变量的字符串。
- @EqualsAndHashCode:作用于类,覆盖默认的 equals 和 hashCode 方法,方便对象之间的比较和哈希操作。
- @NoArgsConstructor:作用于类,生成无参构造器。
- @AllArgsConstructor:作用于类,生成包含所有成员变量的全参构造器。
- @Data:作用于类上,是 @ToString、@EqualsAndHashCode、@Getter、@Setter、@RequiredArgsConstructor 的集合,可简化多个注解的使用。
- @Log / @Slf4j:作用于类上,生成日志变量,用于记录日志(需项目中已添加 log 依赖)。若注解不生效,需检查 Lombok 插件配置,更新插件并重启 idea。
- 在common模块添加maven依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--项目中添加 spring-boot-starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 修改聚合工程里面的Lombook作用域范围
<!--https://mvnrepository.com/artifact/org.projectlombok/lombok/1.18.16-->
<!--scope=provided,说明它只在编译阶段生效,不需要打入包中, Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<!--<scope>provided</scope>-->
</dependency>
2.Swagger接口文档
一个方便前后端交互的接口文档。
官方网站:Swagger 文档 | Swagger Docs - Swagger 中文
在common里面添加SwaggerUI13.0的依赖。
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
- 创建SwaggerConfiguration配置类
@Component
@EnableOpenApi
@Data
public class SwaggerConfiguration {
@Bean
public Docket webApiDoc() {
return new Docket(DocumentationType.OAS_30)
.groupName("用户微服务接口文档")
// 接口文档的URL地址
.pathMapping("/")
// 是否启用
.enable(true)
.apiInfo(apiInfo())
// 指定生成接口的包名
.select()
.apis(RequestHandlerSelectors.basePackage("com.guslegend"))
.paths(PathSelectors.ant("/api/**"))
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("天空商城")
.description("微服务接口文档")
.contact(new Contact("guslegend", "https://github.com/guslegend", "guslegend@163.com"))
.version("1.0")
.build();
}
}
- 如果是进行分组的话:
@Bean
public Docket adminApiDoc(){
return new Docket(DocumentationType.OAS_30)
.groupName("管理端接口文档")
.pathMapping("/")
// 定义是否开启swagger,false为关闭,可以通过变量控制,线上关闭
.enable(true)
//配置api文档元信息
.apiInfo(apiInfo())
// 选择哪些接口作为swagger的doc发布
.select()
.apis(RequestHandlerSelectors.basePackage("com.guslegend"))
//正则匹配请求路径,并分配至当前分组
.paths(PathSelectors.ant("/admin/**"))
.build();
}
- 自定义登录令牌
@Component
@EnableOpenApi
@Data
public class SwaggerConfiguration {
@Bean
public Docket webApiDoc() {
return new Docket(DocumentationType.OAS_30)
.groupName("用户微服务接口文档")
.pathMapping("/")
//定义是否开启swagger, false为关闭
.enable(true)
//配置api文档元信息
.apiInfo(apiInfo())
//选择那些接口作为swagger的doc发布
.select()
.apis(RequestHandlerSelectors.basePackage("com.guslegend"))
//正则匹配请求路径, 并分配到当前组
.paths(PathSelectors.ant("/api/**"))
.build()
//新版swagger3.0配置
.globalRequestParameters(getGlobalRequestParameters())
.globalResponses(HttpMethod.GET, getGlobalResponseMessage())
.globalResponses(HttpMethod.POST, getGlobalResponseMessage());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("1024电商平台")
.description("微服务接口文档")
.contact(new Contact("guslegend","http://guslegend.com","1670547022@qq.com"))
.version("12")
.build();
}
/**
* 生成全局通用参数, 支持配置多个响应参数
* @return
*/
private List<RequestParameter> getGlobalRequestParameters() {
List<RequestParameter> parameters = new ArrayList<>();
parameters.add(new RequestParameterBuilder()
.name("token")
.description("登录令牌")
.in(ParameterType.HEADER)
.query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
.required(false)
.build());
// parameters.add(new RequestParameterBuilder()
// .name("version")
// .description("版本号")
// .required(true)
// .in(ParameterType.HEADER)
// .query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
// .required(false)
// .build());
return parameters;
}
/**
* 生成通用响应信息
* @return
*/
private List<Response> getGlobalResponseMessage() {
List<Response> responseList = new ArrayList<>();
responseList.add(new ResponseBuilder().code("4xx").description("请求错误,根据code和msg检查").build());
return responseList;
}
}
3.统一接口封装工具类
我们在这里规定状态码用6位数字,前三位表示服务,后三位表示接口。
用户服务200,优惠券服务300,商品服务400,订单服务500。统一状态码用BizCodeEnum表示。
public enum BizCodeEnum {
/**
* 通用操作码
*/
OPS_REPEAT(110001,"重复操作"),
//====== 用户服务模块 ======
/**
*验证码
*/
CODE_TO_ERROR(210001,"接收号码不合规"),
CODE_LIMITED(210002,"验证码发送过快"),
CODE_ERROR(210003,"验证码错误"),
CODE_CAPTCHA(210101,"图形验证码错误"),
/**
* 账号
*/
ACCOUNT_REPEAT(220001,"账号已经存在"),
ACCOUNT_UNREGISTER(220002,"账号不存在"),
ACCOUNT_PWD_ERROR(220003,"账号或者密码错误");
//====== 用户服务模块 ======
@Getter
private String message;
@Getter
private int code;
private BizCodeEnum(int code, String message){
this.code = code;
this.message = message;
}
}
- 统一接口协议JsonData
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JsonData {
/**
* 状态码 0 表示成功,1表示处理中,-1表示失败
*/
private Integer code;
/**
* 数据
*/
private Object data;
/**
* 描述
*/
private String msg;
/**
* 成功,传入数据
* @return
*/
public static JsonData buildSuccess() {
return new JsonData(0, null, null);
}
/**
* 成功,传入数据
* @param data
* @return
*/
public static JsonData buildSuccess(Object data) {
return new JsonData(0, data, null);
}
/**
* 失败,传入描述信息
* @param msg
* @return
*/
public static JsonData buildError(String msg) {
return new JsonData(-1, null, msg);
}
/**
* 自定义状态码和错误信息
* @param code
* @param msg
* @return
*/
public static JsonData buildCodeAndMsg(int code, String msg) {
return new JsonData(code, null, msg);
}
/**
* 传入枚举,返回信息
* @param codeEnum
* @return
*/
public static JsonData buildResult(BizCodeEnum codeEnum){
return JsonData.buildCodeAndMsg(codeEnum.getCode(),codeEnum.getMessage());
}
}
4.自定义全局异常
- 自定义全局异常
/**
* 全局异常处理
*/
@Data
public class BizException extends RuntimeException {
private Integer code;
private String msg;
public BizException(Integer code, String message) {
super(message);
this.code = code;
this.msg = message;
}
public BizException(BizCodeEnum bizCodeEnum) {
super(bizCodeEnum.getMessage());
this.code = bizCodeEnum.getCode();
this.msg = bizCodeEnum.getMessage();
}
}
- 自定义异常处理器
@ControllerAdvice
@Slf4j
public class ExceptionHandle {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public JsonData Handle(Exception e) {
if (e instanceof BizException) {
BizException bizException = (BizException) e;
log.info("[业务异常]{}", e);
return JsonData.buildCodeAndMsg( bizException.getCode(),bizException.getMsg());
} else {
log.info("[系统异常]{}", e);
return JsonData.buildError("全局异常,未知错误");
}
}
}
5.单元测试
- 首先我们需要创建启动类UserAoolication
@SpringBootApplication
@MapperScan("com.guslegend")
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
- 然后我们要创建application.yml配置类
server:
port: 9001
spring:
application:
name: shop-user-service
#数据库配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/fly-shop-user?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
#配置plus打印sql日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#设置日志级别,ERROR/WARN/INFO/DEBUG,默认是INFO以上才显示
logging:
level:
root: INFO
- 在common模块中添加maven依赖
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
- 在用户微服务模块中添加单元测代码
@RunWith(SpringRunner.class)
@SpringBootTest(classes = UserApplication.class)
@Slf4j
public class AddressTest {
@Autowired
private AddressService addressService;
@Test
public void test() {
AddressDO addressDO = new AddressDO();
log.info("addressDO:{}", addressDO);
}
}
- 测试结果
2025-08-30 19:22:10.165 INFO 24080 --- [ main] com.guslegend.test.AddressTest : addressDO:AddressDO(id=null, userId=null, defaultStatus=null, receiveName=null, phone=null, province=null, city=null, region=null, detailAddress=null, createTime=null)