Commit 08625b0c authored by macro's avatar macro
Browse files

升级SpringBoot 2.3.0

parent 6a9f1202
package com.macro.mall.common.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.macro.mall.common.service.RedisService;
import com.macro.mall.common.service.impl.RedisServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* Redis基础配置
* 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() {
//创建JSON序列化器
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//必须设置,否则无法将JSON转化为对象,会转化成Map类型
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
return serializer;
}
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
//设置Redis缓存有效期为1天
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
@Bean
public RedisService redisService(){
return new RedisServiceImpl();
}
}
package com.macro.mall.portal.config;
package com.macro.mall.common.config;
import com.macro.mall.common.domain.SwaggerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
/**
* Swagger API文档相关配置
* Created by macro on 2018/4/26.
* Swagger基础配置
* Created by macro on 2020/7/16.
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
public abstract class BaseSwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
SwaggerProperties swaggerProperties = swaggerProperties();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo(swaggerProperties))
.select()
.apis(RequestHandlerSelectors.basePackage("com.macro.mall.portal.controller"))
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getApiBasePackage()))
.paths(PathSelectors.any())
.build()
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
.build();
if (swaggerProperties.isEnableSecurity()) {
docket.securitySchemes(securitySchemes()).securityContexts(securityContexts());
}
return docket;
}
private ApiInfo apiInfo() {
private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
return new ApiInfoBuilder()
.title("mall前台系统")
.description("mall前台模块")
.contact("macro")
.version("1.0")
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail()))
.version(swaggerProperties.getVersion())
.build();
}
......@@ -75,4 +73,9 @@ public class Swagger2Config {
result.add(new SecurityReference("Authorization", authorizationScopes));
return result;
}
/**
* 自定义Swagger配置
*/
public abstract SwaggerProperties swaggerProperties();
}
package com.macro.mall.common.domain;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* Swagger自定义配置
* Created by macro on 2020/7/16.
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Builder
public class SwaggerProperties {
/**
* API文档生成基础路径
*/
private String apiBasePackage;
/**
* 是否要启用登录认证
*/
private boolean enableSecurity;
/**
* 文档标题
*/
private String title;
/**
* 文档描述
*/
private String description;
/**
* 文档版本
*/
private String version;
/**
* 文档联系人姓名
*/
private String contactName;
/**
* 文档联系人网址
*/
private String contactUrl;
/**
* 文档联系人邮箱
*/
private String contactEmail;
}
package com.macro.mall.bo;
package com.macro.mall.common.domain;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* Controller层的日志封装类
* Created by macro on 2018/4/26.
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class WebLog {
/**
* 操作描述
......@@ -50,95 +55,14 @@ public class WebLog {
*/
private String ip;
/**
* 请求参数
*/
private Object parameter;
/**
* 返回结果
*/
private Object result;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Long getStartTime() {
return startTime;
}
public void setStartTime(Long startTime) {
this.startTime = startTime;
}
public Integer getSpendTime() {
return spendTime;
}
public void setSpendTime(Integer spendTime) {
this.spendTime = spendTime;
}
public String getBasePath() {
return basePath;
}
public void setBasePath(String basePath) {
this.basePath = basePath;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Object getParameter() {
return parameter;
}
public void setParameter(Object parameter) {
this.parameter = parameter;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
}
package com.macro.mall.component;
package com.macro.mall.common.log;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.macro.mall.bo.WebLog;
import com.macro.mall.common.domain.WebLog;
import io.swagger.annotations.ApiOperation;
import net.logstash.logback.marker.Markers;
import org.aspectj.lang.JoinPoint;
......@@ -40,7 +39,7 @@ import java.util.Map;
public class WebLogAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);
@Pointcut("execution(public * com.macro.mall.controller.*.*(..))")
@Pointcut("execution(public * com.macro.mall.controller.*.*(..))||execution(public * com.macro.mall.*.controller.*.*(..))")
public void webLog() {
}
......
package com.macro.mall.security.service;
package com.macro.mall.common.service;
import java.util.List;
import java.util.Map;
......@@ -88,7 +88,7 @@ public interface RedisService {
/**
* 直接设置整个Hash结构
*/
void hSetAll(String key, Map<String, Object> map);
void hSetAll(String key, Map<String, ?> map);
/**
* 删除Hash结构中的属性
......
package com.macro.mall.security.service.impl;
package com.macro.mall.common.service.impl;
import com.macro.mall.security.service.RedisService;
import com.macro.mall.common.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
......@@ -14,7 +13,6 @@ import java.util.concurrent.TimeUnit;
* redis操作实现类
* Created by macro on 2020/3/3.
*/
@Service
public class RedisServiceImpl implements RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
......@@ -97,7 +95,7 @@ public class RedisServiceImpl implements RedisService {
}
@Override
public void hSetAll(String key, Map<String, Object> map) {
public void hSetAll(String key, Map<String, ?> map) {
redisTemplate.opsForHash().putAll(key, map);
}
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<!--引用默认日志配置-->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!--使用默认的控制台日志输出实现-->
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="springBoot"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/logs}"/>
<!--LogStash访问host-->
<springProperty name="LOG_STASH_HOST" scope="context" source="logstash.host" defaultValue="localhost"/>
<!--DEBUG日志输出到文件-->
<appender name="FILE_DEBUG"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--输出DEBUG以上级别日志-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<encoder>
<!--设置为默认的文件日志格式-->
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--设置文件命名格式-->
<fileNamePattern>${LOG_FILE_PATH}/debug/${APP_NAME}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!--设置日志文件大小,超过就重新生成文件,默认10M-->
<maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
<!--日志文件保留天数,默认30天-->
<maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy>
</appender>
<!--ERROR日志输出到文件-->
<appender name="FILE_ERROR"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--只输出ERROR级别的日志-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<!--设置为默认的文件日志格式-->
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--设置文件命名格式-->
<fileNamePattern>${LOG_FILE_PATH}/error/${APP_NAME}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!--设置日志文件大小,超过就重新生成文件,默认10M-->
<maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize>
<!--日志文件保留天数,默认30天-->
<maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy>
</appender>
<!--DEBUG日志输出到LogStash-->
<appender name="LOG_STASH_DEBUG" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<destination>${LOG_STASH_HOST}:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>Asia/Shanghai</timeZone>
</timestamp>
<!--自定义日志输出格式-->
<pattern>
<pattern>
{
"project": "mall",
"level": "%level",
"service": "${APP_NAME:-}",
"pid": "${PID:-}",
"thread": "%thread",
"class": "%logger",
"message": "%message",
"stack_trace": "%exception{20}"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<!--ERROR日志输出到LogStash-->
<appender name="LOG_STASH_ERROR" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<destination>${LOG_STASH_HOST}:4561</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>Asia/Shanghai</timeZone>
</timestamp>
<!--自定义日志输出格式-->
<pattern>
<pattern>
{
"project": "mall",
"level": "%level",
"service": "${APP_NAME:-}",
"pid": "${PID:-}",
"thread": "%thread",
"class": "%logger",
"message": "%message",
"stack_trace": "%exception{20}"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<!--业务日志输出到LogStash-->
<appender name="LOG_STASH_BUSINESS" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>${LOG_STASH_HOST}:4562</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>Asia/Shanghai</timeZone>
</timestamp>
<!--自定义日志输出格式-->
<pattern>
<pattern>
{
"project": "mall",
"level": "%level",
"service": "${APP_NAME:-}",
"pid": "${PID:-}",
"thread": "%thread",
"class": "%logger",
"message": "%message",
"stack_trace": "%exception{20}"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<!--接口访问记录日志输出到LogStash-->
<appender name="LOG_STASH_RECORD" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>${LOG_STASH_HOST}:4563</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>Asia/Shanghai</timeZone>
</timestamp>
<!--自定义日志输出格式-->
<pattern>
<pattern>
{
"project": "mall",
"level": "%level",
"service": "${APP_NAME:-}",
"class": "%logger",
"message": "%message"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<!--控制框架输出日志-->
<logger name="org.slf4j" level="INFO"/>
<logger name="springfox" level="INFO"/>
<logger name="io.swagger" level="INFO"/>
<logger name="org.springframework" level="INFO"/>
<logger name="org.hibernate.validator" level="INFO"/>
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE_DEBUG"/>
<appender-ref ref="FILE_ERROR"/>
<appender-ref ref="LOG_STASH_DEBUG"/>
<appender-ref ref="LOG_STASH_ERROR"/>
</root>
<logger name="com.macro.mall.common.log.WebLogAspect" level="DEBUG">
<appender-ref ref="LOG_STASH_RECORD"/>
</logger>
<logger name="com.macro.mall" level="DEBUG">
<appender-ref ref="LOG_STASH_BUSINESS"/>
</logger>
</configuration>
......@@ -33,6 +33,10 @@
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
</dependencies>
<build>
......
package com.macro.mall.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger API文档相关配置
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.macro.mall.demo"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("SwaggerUI演示")
.description("Demo模块")
.contact("macro")
.version("1.0")
.build();
}
}
package com.macro.mall.demo.config;
import com.macro.mall.common.config.BaseSwaggerConfig;
import com.macro.mall.common.domain.SwaggerProperties;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger相关配置
* Created by macro on 2019/4/8.
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig extends BaseSwaggerConfig {
@Override
public SwaggerProperties swaggerProperties() {
return SwaggerProperties.builder()
.apiBasePackage("com.macro.mall.demo.controller")
.title("mall-demo系统")
.description("SpringBoot版本中的一些示例")
.contactName("macro")
.version("1.0")
.enableSecurity(true)
.build();
}
}
......@@ -2,6 +2,8 @@ server:
port: 8082
spring:
application:
name: mall-demo
datasource:
url: jdbc:mysql://localhost:3306/mall?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
......@@ -12,7 +14,6 @@ spring:
servlet:
content-type: text/html
cache: false #开发时关闭缓存,不然没法看到实时页面
mybatis:
mapper-locations:
- classpath:mapper/*.xml
......@@ -20,10 +21,8 @@ mybatis:
logging:
level:
root: info #日志配置DEBUG,INFO,WARN,ERROR
root: info
com.macro.mall: debug
# file: demo_log.log #配置日志生成路径
# path: /var/logs #配置日志文件名称
host:
mall:
......
......@@ -23,6 +23,14 @@
<groupId>com.macro.mall</groupId>
<artifactId>mall-common</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
......
package com.macro.mall.portal.config;
import com.macro.mall.common.config.BaseSwaggerConfig;
import com.macro.mall.common.domain.SwaggerProperties;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Swagger2API文档的配置
* Created by macro on 2018/4/26.
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig extends BaseSwaggerConfig {
@Override
public SwaggerProperties swaggerProperties() {
return SwaggerProperties.builder()
.apiBasePackage("com.macro.mall.portal.controller")
.title("mall前台系统")
.description("mall前台相关接口文档")
.contactName("macro")
.version("1.0")
.enableSecurity(true)
.build();
}
}
......@@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.macro.mall.common.api.CommonPage;
import com.macro.mall.common.exception.Asserts;
import com.macro.mall.common.service.RedisService;
import com.macro.mall.mapper.*;
import com.macro.mall.model.*;
import com.macro.mall.portal.component.CancelOrderSender;
......@@ -13,7 +14,6 @@ import com.macro.mall.portal.dao.PortalOrderItemDao;
import com.macro.mall.portal.dao.SmsCouponHistoryDao;
import com.macro.mall.portal.domain.*;
import com.macro.mall.portal.service.*;
import com.macro.mall.security.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
......
package com.macro.mall.portal.service.impl;
import com.macro.mall.common.service.RedisService;
import com.macro.mall.mapper.UmsMemberMapper;
import com.macro.mall.model.UmsMember;
import com.macro.mall.portal.service.UmsMemberCacheService;
import com.macro.mall.security.annotation.CacheException;
import com.macro.mall.security.config.RedisConfig;
import com.macro.mall.security.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
......
......@@ -15,32 +15,29 @@ spring:
stat-view-servlet: #访问监控网页的登录用户名和密码
login-username: druid
login-password: druid
data:
mongodb:
host: localhost
port: 27017
database: mall-port
redis:
host: localhost # Redis服务器地址
database: 0 # Redis数据库索引(默认为0)
port: 6379 # Redis服务器连接端口
password: # Redis服务器连接密码(默认为空)
timeout: 300ms # 连接超时时间(毫秒)
rabbitmq:
host: localhost
port: 5672
virtual-host: /mall
username: mall
password: mall
publisher-confirms: true #如果对异步消息需要回调必须设置为true
# 日志配置
logging:
level:
org.springframework.data.mongodb.core: debug
com.macro.mall.mapper: debug
com.macro.mall.portal.dao: debug
root: info
com.macro.mall: debug
logstash:
host: localhost
......@@ -35,8 +35,14 @@ spring:
virtual-host: /mall
username: mall
password: mall
publisher-confirms: true #如果对异步消息需要回调必须设置为true
# 日志配置
logging:
path: /var/logs
file:
path: /var/logs
level:
root: info
com.macro.mall: info
logstash:
host: logstash
spring:
application:
name: mall-portal
profiles:
active: dev #默认为开发环境
......
......@@ -3,7 +3,7 @@ package com.macro.mall.search;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@SpringBootApplication(scanBasePackages = "com.macro.mall")
public class MallSearchApplication {
public static void main(String[] args) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment