How to Upgrade the mall‑tiny Spring Boot Scaffold to 2.7.0: Tips and Code Changes
This article introduces the open‑source mall‑tiny rapid‑development scaffold, explains its core features and integration with the mall‑admin‑web front‑end, and provides a step‑by‑step guide to upgrading it to Spring Boot 2.7.0, covering Swagger, Spring Security, MyBatis‑Plus, circular‑dependency resolution, and CORS configuration.
mall‑tiny Project Overview
mall‑tiny is a rapid‑development scaffold based on Spring Boot and MyBatis‑Plus, featuring complete permission management and integration with the mall‑admin‑web Vue front‑end. It has over 1100 stars on GitHub.
Project address: https://github.com/macrozheng/mall-tiny
Project Demo
mall‑tiny can be seamlessly connected to the mall‑admin‑web front‑end, exposing only permission‑related features.
Front‑end project address: https://github.com/macrozheng/mall-admin-web
Technical Stack
The upgrade adds Spring Boot 2.7.0 and updates other dependencies to their latest versions, including Spring Security 5.7.1, MyBatis‑Plus 3.5.1, Swagger‑UI 3.0.0, Redis 5.0, Docker 18.09.0, Druid 1.2.9, Hutool 5.8.0, JWT 0.9.1, Lombok 1.18.24, etc.
Database Schema
Only nine tables related to permission management are retained, simplifying customization.
API Documentation
After upgrading Swagger, the documentation URL changes to
http://localhost:8080/swagger-ui/.
Upgrade Process
Common issues when upgrading to Spring Boot 2.7.0 and their solutions.
Swagger Upgrade
When moving from Spring Boot 2.6.x, add a
BeanPostProcessorbean to fix compatibility; the old @Api description attribute is deprecated, use @Tag and @Api tags instead.
<code>/**
* Swagger API documentation configuration
* Created by macro on 2018/4/26.
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig extends BaseSwaggerConfig {
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}
</code>Spring Security Upgrade
WebSecurityConfigurerAdapter is deprecated; configure a
SecurityFilterChainbean instead.
<code>/**
* SpringSecurity 5.4.x+ new configuration
* Created by macro on 2019/11/5.
*/
@Configuration
public class SecurityConfig {
@Autowired
private IgnoreUrlsConfig ignoreUrlsConfig;
@Autowired
private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
@Autowired
private DynamicSecurityService dynamicSecurityService;
@Autowired
private DynamicSecurityFilter dynamicSecurityFilter;
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();
// Permit URLs that do not need protection
for (String url : ignoreUrlsConfig.getUrls()) {
registry.antMatchers(url).permitAll();
}
// Allow OPTIONS for CORS
registry.antMatchers(HttpMethod.OPTIONS).permitAll();
// Require authentication for any request
registry.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.accessDeniedHandler(restfulAccessDeniedHandler)
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
if (dynamicSecurityService != null) {
registry.and().addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class);
}
return httpSecurity.build();
}
}
</code>MyBatis‑Plus Upgrade
The generator now uses a builder pattern.
<code>/**
* MyBatisPlus code generator
* Created by macro on 2020/8/20.
*/
public class MyBatisPlusGenerator {
/**
* Initialize global configuration
*/
private static GlobalConfig initGlobalConfig(String projectPath) {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(projectPath + "/src/main/java");
globalConfig.setAuthor("macro");
globalConfig.setOpen(false);
globalConfig.setSwagger2(true);
globalConfig.setBaseResultMap(true);
globalConfig.setFileOverride(true);
globalConfig.setDateType(DateType.ONLY_DATE);
globalConfig.setEntityName("%s");
globalConfig.setMapperName("%sMapper");
globalConfig.setXmlName("%sMapper");
globalConfig.setServiceName("%sService");
globalConfig.setServiceImplName("%sServiceImpl");
globalConfig.setControllerName("%sController");
return globalConfig;
}
}
</code> <code>/**
* MyBatisPlus code generator
* Created by macro on 2020/8/20.
*/
public class MyBatisPlusGenerator {
/**
* Initialize global configuration
*/
private static GlobalConfig initGlobalConfig(String projectPath) {
return new GlobalConfig.Builder()
.outputDir(projectPath + "/src/main/java")
.author("macro")
.disableOpenDir()
.enableSwagger()
.fileOverride()
.dateType(DateType.ONLY_DATE)
.build();
}
}
</code>Circular Dependency Resolution
Enable circular references in Spring Boot 2.6+ via
spring.main.allow-circular-references:true.
Extract shared beans into separate configuration classes (e.g., CommonSecurityConfig) to avoid circular dependencies.
Use a SpringUtil helper to obtain beans programmatically.
<code>/**
* Spring utility class
* Created by macro on 2020/3/3.
*/
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
// Get applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
// Get bean by name
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
// Get bean by class
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
// Get bean by name and class
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
</code>CORS Issue
In Spring Boot 2.7.0,
allowedOriginsno longer accepts "*". Use
allowedOriginPatternsinstead.
<code>/**
* Global CORS configuration
* Created by macro on 2019/7/27.
*/
@Configuration
public class GlobalCorsConfig {
/**
* CORS filter allowing all origins
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// Allow all domains
config.addAllowedOriginPattern("*");
// Allow credentials
config.setAllowCredentials(true);
// Allow all headers
config.addAllowedHeader("*");
// Allow all methods
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
</code>Conclusion
The mall‑tiny scaffold has been upgraded to Spring Boot 2.7.0, with updated dependencies and configuration changes such as Swagger, Spring Security, MyBatis‑Plus, circular‑dependency handling, and CORS settings. Adopting the new APIs ensures cleaner and more maintainable code.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.