Spring Boot Project Initialization, Version Management, and Common Backend Utilities Tutorial

This article walks through creating a Spring Boot project, handling version compatibility between Spring Cloud, Spring Boot, and Kafka, demonstrates common Maven configurations, provides global exception handling and logging aspects, and lists useful backend tools such as embedded Redis, MyBatis‑Plus, and Redisson.

Top Architect
Top Architect
Top Architect
Spring Boot Project Initialization, Version Management, and Common Backend Utilities Tutorial

In this tutorial, a senior architect explains the pain points of environment setup and demonstrates how to quickly create a Spring Boot project using an IDE.

After project creation, the article shows the version compatibility matrix between Spring Cloud and Spring Boot ( https://spring.io/projects/spring-cloud) and between Spring Boot and Kafka ( https://spring.io/projects/spring-kafka), highlighting a real‑world mismatch where the Kafka broker version (0.11) does not support the client’s idempotent mode, causing an UnsupportedVersionException.

The author then introduces Maven as a dependency management tool ( https://maven.apache.org/index.html) and presents a basic Maven dependency snippet for Spring Kafka:

<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>

Next, the article provides a global exception handler using @RestControllerAdvice and Lombok’s @Slf4j, with a method to handle MethodArgumentNotValidException and a helper to format validation errors.

@RestControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public ResponseResult<String> handleValidException(MethodArgumentNotValidException ex, HttpServletResponse response) {
        log.error("[GlobalExceptionHandler][handleValidException] 参数校验exception", ex);
        return wrapperBindingResult(ex.getBindingResult(), response);
    }
    private ResponseResult<String> wrapperBindingResult(BindingResult bindingResult, HttpServletResponse response) {
        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());
        }
        response.setStatus(HttpStatus.BAD_REQUEST.value());
        return ResponseResult.failed(ResultCode.FAILED.getCode(), null);
    }
}

A logging aspect is also shown, which intercepts all controller methods to log request URLs and parameters before execution and logs the response after returning.

@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<Object> list = Lists.newArrayList();
        for (Object object : point.getArgs()) {
            if (object instanceof MultipartFile || object instanceof HttpServletRequest || object instanceof HttpServletResponse || object instanceof BindingResult) {
                continue;
            }
            list.add(object);
        }
        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));
        }
    }
}

Cross‑origin resource sharing (CORS) configuration is provided via a @Configuration class that registers a CorsFilter allowing all origins, headers, and methods.

@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 for API documentation is also included.

@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();
    }
}

The article defines a generic ResponseResult wrapper class with static factory methods for success and failure responses.

@Data
public class ResponseResult<T> {
    private int code;
    private String message;
    private T data;
    public static <T> ResponseResult<T> success(T data) { ... }
    public static <T> ResponseResult<T> success() { ... }
    public static <T> ResponseResult<T> failed(int code, String message) { ... }
    public static boolean isSucceed(ResponseResult responseResult) { ... }
}

Finally, the author lists several useful backend tools with their URLs: embedded Redis ( https://github.com/kstyrc/embedded-redis), embedded MariaDB ( https://github.com/mariadb), embedded Kafka starter, Hutool ( https://hutool.cn/), MyBatis‑Plus ( https://baomidou.com/), MapStruct ( https://mapstruct.org/), and Redisson ( https://github.com/redisson/redisson).

The article concludes with a reminder that environment configuration is often the most time‑consuming part of development and invites readers to discuss and share their experiences.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavamavenSpringBootexceptionhandlingVersionManagement
Top Architect
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.