Backend Development Guide: Spring Boot Project Initialization, Version Management, and Common Utilities
This article walks through the challenges of setting up a Java backend environment, demonstrates how to create a Spring Boot project, explains version compatibility between Spring Cloud, Spring Boot, and Kafka, and provides reusable code snippets for exception handling, logging, CORS, Swagger, and response wrapping, along with recommended tools.
The author, a senior architect, starts by describing how environment setup is the most painful part of Java backend development and why developers often resort to cracked IDEs.
Project Initialization – After installing an IDE, a Spring Boot project is created, resulting in a fresh project structure with a main class, configuration files, and a test starter.
Version Management – Compatibility tables are shown for Spring Cloud ↔ Spring Boot and Spring Boot ↔ Kafka, with links to the official version matrices ( https://spring.io/projects/spring-cloud and https://spring.io/projects/spring-kafka ). A real‑world mismatch (Kafka server 0.11 vs client 3.0.4) caused an UnsupportedVersionException :
?,?:Exception thrown when sending a message with key='null' and payload='byte[205]' to topic notify org.apache.kafka.common.errors.UnsupportedVersionException: Attempting to use idempotence with a broker which does not support the required message format (v2). The broker must be version *0.11* or later.Maven – Maven is introduced as the tool that resolves dependency conflicts, with its homepage ( https://maven.apache.org/index.html ) and a brief description of its benefits.
Global Exception Handler
@RestControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(value = {MethodArgumentNotValidException.class})
public ResponseResult
handleValidException(MethodArgumentNotValidException ex, HttpServletResponse httpServletResponse) {
log.error("[GlobalExceptionHandler][handleValidException] 参数校验exception", ex);
return wrapperBindingResult(ex.getBindingResult(), httpServletResponse);
}
private ResponseResult
wrapperBindingResult(BindingResult bindingResult, HttpServletResponse httpServletResponse) {
StringBuilder errorMsg = new StringBuilder();
for (ObjectError error : bindingResult.getAllErrors()) {
if (error instanceof FieldError) {
errorMsg.append(((FieldError) error).getField()).append(": ");
}
errorMsg.append(error.getDefaultMessage() == null ? "" : error.getDefaultMessage());
}
httpServletResponse.setStatus(HttpStatus.BAD_REQUEST.value());
return ResponseResult.failed(ResultCode.FAILED.getCode(), null);
}
}Logging Aspect
@Aspect
@Slf4j
@Component
public class WebLogAspect {
@Pointcut("@within(org.springframework.stereotype.Controller) || @within(org.springframework.web.bind.annotation.RestController)")
public void cutController() {}
@Before("cutController()")
public void doBefore(JoinPoint point) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String url = request.getRequestURL().toString();
List
list = Lists.newArrayList();
for (Object obj : point.getArgs()) {
if (obj instanceof MultipartFile || obj instanceof HttpServletRequest || obj instanceof HttpServletResponse || obj instanceof BindingResult) {
continue;
}
list.add(obj);
}
log.info("请求 uri:[{}],params:[{}]", url, StringUtils.join(list, ","));
}
@AfterReturning(returning = "response", pointcut = "cutController()")
public void doAfterReturning(Object response) {
if (response != null) {
log.info("请求返回result:[{}]", JSONUtil.toJsonStr(response));
}
}
}CORS Configuration
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Lists.newArrayList("*"));
config.setAllowCredentials(true);
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}Swagger Configuration
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public Docket docket() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo()).enable(true)
.select()
.apis(RequestHandlerSelectors.basePackage("com.vines.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("项目描述")
.description("基础服务项目描述")
.contact(new Contact("作者", "作者URL", "作者Email"))
.version("1.0")
.build();
}
}Standard Response Wrapper
@Data
public class ResponseResult
{
private int code;
private String message;
private T data;
public static
ResponseResult
success(T data) {
ResponseResult
r = new ResponseResult<>();
r.setCode(ResultCode.SUCCESS.getCode());
r.setMessage(ResultCode.SUCCESS.getMessage());
r.setData(data);
return r;
}
public static
ResponseResult
success() { /* ... */ }
public static
ResponseResult failed(int code, String message) { /* ... */ }
public static boolean isSucceed(ResponseResult r) { return r.getCode() == ResultCode.SUCCESS.getCode(); }
}Common Tools – The article recommends embedded versions of Redis ( https://github.com/kstyrc/embedded-redis ), MariaDB ( https://github.com/mariadb ), and Kafka (Spring‑Kafka starter), as well as utility libraries such as Hutool ( https://hutool.cn/ ), MyBatis‑Plus ( https://baomidou.com/ ), MapStruct ( https://mapstruct.org/ ) and Redisson ( https://github.com/redisson/redisson ).
In conclusion, while IDE installation is tedious, mismatched runtime and test environments cause far greater delays; the author encourages readers to discuss these issues and share solutions.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.