SpringBoot e-Commerce project mall (39K + STAR) address: github.com/macrozheng/…

Abstract

I’ve written a lot of articles about mainstream technologies, and a lot of feedback from my friends is exactly what they want to learn! If appropriate, I will apply these techniques to my open source projects. Recently the mall project has been upgraded and changed a lot, so I wrote an article to introduce the updated content, hoping to be helpful to you all!

Updated Content Overview

  • Upgrade to SpringBoot 2.3.0.release;
  • Support for Elasticsearch 7.6.2;
  • The ELK log collection function is complete, and logs are collected in different scenarios.
  • Unified Swagger configuration, simplified configuration;
  • Redis unified configuration, simplified configuration;
  • Windows and Linux deployment documentation updated.

Update Introduction

Upgrade SpringBoot 2.3.0

The previous version was SpringBoot 2.1.7, which was released in August 2019, more than a year ago and is due for an update. SpringBoot 2.3.0 is released in May this year, or a relatively new version of the new features of this version of friends can see the “SpringBoot 2.3.0 new features, come with me to practice a wave!” .

Support Elasticsearch 7.6.2

Elasticsearch was forced to upgrade due to the SpringBoot version update, and of course Elasticsearch 7.x is currently the mainstream version. There are a lot of holes in the upgrade process, just check out Elasticsearch 7. X, I feel like I’m in a hole! .

The ELK log collection function is complete

The previous log collection function was not perfect, and the method of collecting logs by scenario was not adopted, but this time it was finally improved. Log collection system construction and sub-scene log collection scheme, can refer to “you actually also go to the server for logs, build a log collection system is not sweet?” .

Unified Swagger configuration

Previously, each module had its own Swagger configuration, such as mall-admin, mall-portal and mall-search, which has been unified now.

  • The first is inmall-commonThe basic configuration for Swagger is added to the moduleBaseSwaggerConfigTo be used in other modules, simply inherit the configuration and rewrite itswaggerProperties()This abstract method will do;
/** * Created by macro on 2020/7/16. */
public abstract class BaseSwaggerConfig {

    @Bean
    public Docket createRestApi(a) {
        SwaggerProperties swaggerProperties = swaggerProperties();
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo(swaggerProperties))
                .select()
                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getApiBasePackage()))
                .paths(PathSelectors.any())
                .build();
        if(swaggerProperties.isEnableSecurity()) { docket.securitySchemes(securitySchemes()).securityContexts(securityContexts());  }return docket;
    }

    private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
        return new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                .description(swaggerProperties.getDescription())
                .contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail()))
                .version(swaggerProperties.getVersion())
                .build();
    }

    private List<ApiKey> securitySchemes(a) {
        // Set the request header information
        List<ApiKey> result = new ArrayList<>();
        ApiKey apiKey = new ApiKey("Authorization"."Authorization"."header");
        result.add(apiKey);
        return result;
    }

    private List<SecurityContext> securityContexts(a) {
        // Set the path for login authentication
        List<SecurityContext> result = new ArrayList<>();
        result.add(getContextByPath("/ / *. *"));
        return result;
    }

    private SecurityContext getContextByPath(String pathRegex) {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex(pathRegex))
                .build();
    }

    private List<SecurityReference> defaultAuth(a) {
        List<SecurityReference> result = new ArrayList<>();
        AuthorizationScope authorizationScope = new AuthorizationScope("global"."accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        result.add(new SecurityReference("Authorization", authorizationScopes));
        return result;
    }

    /** * Custom Swagger configuration */
    public abstract SwaggerProperties swaggerProperties(a);
}
Copy the code
  • One of theSwaggerPropertiesClass is our custom configuration class, which configuration, see the comment clearly;
/** * Created by macro on 2020/7/16. */
@Data
@EqualsAndHashCode(callSuper = false)
@Builder
public class SwaggerProperties {
    /** * API documentation base path */
    private String apiBasePackage;
    /** * Whether to enable login authentication */
    private boolean enableSecurity;
    /**
     * 文档标题
     */
    private String title;
    /** * Document description */
    private String description;
    /** * Document version */
    private String version;
    /** * Document contact name */
    private String contactName;
    /** * Document contact url */
    private String contactUrl;
    /** * Document contact email */
    private String contactEmail;
}
Copy the code
  • inmall-adminIn modules, only inheritance is requiredBaseSwaggerConfigAnd configure itSwaggerPropertiesCan, is not very convenient!
** * Created by macro on 2018/4/26. */
@Configuration
@EnableSwagger2
public class SwaggerConfig extends BaseSwaggerConfig {

    @Override
    public SwaggerProperties swaggerProperties(a) {
        return SwaggerProperties.builder()
                .apiBasePackage("com.macro.mall.controller")
                .title("Mall Background System")
                .description("Mall background related interface document")
                .contactName("macro")
                .version("1.0")
                .enableSecurity(true) .build(); }}Copy the code

Redis configuration is unified

With Redis, we more or less customize some configurations, which are now unified.

  • The first is inmall-commonThe basic configuration of Redis is added to the moduleBaseRedisConfigWhen used in other modules, you only need to inherit the configuration.
/** * Created by macro on 2020/6/19. */
public class BaseRedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisSerializer<Object> serializer = redisSerializer();
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public RedisSerializer<Object> redisSerializer(a) {
        // Create the JSON serializer
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // Must be set, otherwise JSON cannot be converted to object, will be converted to Map type
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(objectMapper);
        return serializer;
    }

    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        // Set the Redis cache validity period to 1 dayRedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.of Days(1));
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }


    @Bean
    public RedisService redisService(a){
        return newRedisServiceImpl(); }}Copy the code
  • Like when we were inmall-securityThe module needs to use Redis, directly inherit the configuration can be;
/** * Created by macro on 2020/3/2. */
@EnableCaching
@Configuration
public class RedisConfig extends BaseRedisConfig {}Copy the code
  • When you need to manipulate Redis, inject directlyRedisServiceObject, and then use it to manipulate.
/** * UmsAdminCacheService implementation class * Created by macro on 2020/3/13
@Service
public class UmsAdminCacheServiceImpl implements UmsAdminCacheService {
    @Autowired
    private RedisService redisService;
}
Copy the code

Windows and Linux deployment documentation updated

Due to the upgrade of some components, the deployment documentation has also been updated. There are three deployment methods, and there is always a right one for you!

  • Mall deployment in Windows: www.macrozheng.com/#/deploy/ma…
  • Mall deployment in Linux (based on Docker containers) : www.macrozheng.com/#/deploy/ma…
  • Mall deployment in Linux (Docker Compose) : www.macrozheng.com/#/deploy/ma…

The project address

If you think the project is powerful, please click a Star to support!

Github.com/macrozheng/…