升级SpringBoot 2.3.0

This commit is contained in:
macro 2020-08-08 11:05:09 +08:00
parent 6a9f12024d
commit 08625b0ca5
50 changed files with 1137 additions and 1060 deletions

View File

@ -5,14 +5,23 @@ services:
container_name: mall-admin
ports:
- 8080:8080
volumes:
- /mydata/app/mall-admin/logs:/var/logs
- /etc/localtime:/etc/localtime
environment:
- 'TZ="Asia/Shanghai"'
external_links:
- redis:redis #可以用redis这个域名访问redis服务
- mysql:db #可以用db这个域名访问mysql服务
mall-search:
image: mall/mall-search:1.0-SNAPSHOT
container_name: mall-search
ports:
- 8081:8081
volumes:
- /mydata/app/mall-search/logs:/var/logs
- /etc/localtime:/etc/localtime
environment:
- 'TZ="Asia/Shanghai"'
external_links:
- elasticsearch:es #可以用es这个域名访问elasticsearch服务
- mysql:db #可以用db这个域名访问mysql服务
@ -21,6 +30,11 @@ services:
container_name: mall-portal
ports:
- 8085:8085
volumes:
- /mydata/app/mall-portal/logs:/var/logs
- /etc/localtime:/etc/localtime
environment:
- 'TZ="Asia/Shanghai"'
external_links:
- redis:redis #可以用redis这个域名访问redis服务
- mongo:mongo #可以用mongo这个域名访问mongo服务

View File

@ -14,7 +14,7 @@ services:
- /mydata/mysql/data/conf:/etc/mysql/conf.d #配置文件挂载
- /mydata/mysql/log:/var/log/mysql #日志文件挂载
redis:
image: redis:3.2
image: redis:5
container_name: redis
command: redis-server --appendonly yes
volumes:
@ -40,7 +40,7 @@ services:
- 5672:5672
- 15672:15672
elasticsearch:
image: elasticsearch:6.4.0
image: elasticsearch:7.6.2
container_name: elasticsearch
environment:
- "cluster.name=elasticsearch" #设置集群名称为elasticsearch
@ -52,8 +52,24 @@ services:
ports:
- 9200:9200
- 9300:9300
logstash:
image: logstash:7.6.2
container_name: logstash
environment:
- TZ=Asia/Shanghai
volumes:
- /mydata/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf #挂载logstash的配置文件
depends_on:
- elasticsearch #kibana在elasticsearch启动之后再启动
links:
- elasticsearch:es #可以用es这个域名访问elasticsearch服务
ports:
- 4560:4560
- 4561:4561
- 4562:4562
- 4563:4563
kibana:
image: kibana:6.4.0
image: kibana:7.6.2
container_name: kibana
links:
- elasticsearch:es #可以用es这个域名访问elasticsearch服务
@ -64,7 +80,7 @@ services:
ports:
- 5601:5601
mongo:
image: mongo:3.2
image: mongo:4.2.5
container_name: mongo
volumes:
- /mydata/mongo/db:/data/db #数据文件挂载

View File

@ -1,149 +0,0 @@
# docker环境部署
## docker环境安装
### docker安装
1. 安装yum-utils
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
2. 为yum源添加docker仓库位置
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
3. 安装docker:
yum install docker-ce
4. 启动docker:
systemctl start docker
常见命令见document/reference文件夹中的docker.md
5. 安装上传下载插件:
yum -y install lrzsz
### docker compose安装
1. 下载地址https://github.com/docker/compose/releases
2. 安装地址:/usr/local/bin/docker-compose
3. 设置为可执行sudo chmod +x /usr/local/bin/docker-compose
4. 测试是否安装成功docker-compose --version
## mysql安装
### 下载镜像文件
docker pull mysql:5.7
### 创建实例并启动
docker run -p 3306:3306 --name mysql \
-v /mydata/mysql/log:/var/log/mysql \
-v /mydata/mysql/data:/var/lib/mysql \
-v /mydata/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
> 参数说明
- -p 3306:3306将容器的3306端口映射到主机的3306端口
- -v /mydata/mysql/conf:/etc/mysql将配置文件夹挂在到主机
- -v /mydata/mysql/log:/var/log/mysql将日志文件夹挂载到主机
- -v /mydata/mysql/data:/var/lib/mysql/:将配置文件夹挂载到主机
- -e MYSQL_ROOT_PASSWORD=root初始化root用户的密码
### 通过容器的mysql命令行工具连接
docker exec -it mysql mysql -uroot -proot
### 设置远程访问
grant all privileges on *.* to 'root' @'%' identified by 'root';
flush privileges;
### 进入容器文件系统
docker exec -it mysql /bin/bash
## redis安装
### 下载镜像文件
docker pull redis:3.2
### 创建实例并启动
docker run -p 6379:6379 --name redis -v /mydata/redis/data:/data -d redis:3.2 redis-server --appendonly yes
### 使用redis镜像执行redis-cli命令连接
docker exec -it redis redis-cli
## nginx安装
### 下载镜像文件
docker pull nginx:1.10
### 创建实例并启动
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-d nginx:1.10
### 修改nginx配置
1. 将容器内的配置文件拷贝到当前目录docker container cp nginx:/etc/nginx .
2. 修改文件名称mv nginx conf
3. 终止容器docker stop nginx
4. 执行命令删除原容器docker rm $ContainerId
5. 执行以下命令:
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.10
## rabbitmq安装
### 下载镜像文件
docker pull rabbitmq:management
### 创建实例并启动
docker run -d --name rabbitmq --publish 5671:5671 \
--publish 5672:5672 --publish 4369:4369 --publish 25672:25672 --publish 15671:15671 --publish 15672:15672 \
rabbitmq:management
## elasticsearch安装
### 下载镜像文件
docker pull elasticsearch:6.4.0
### 创建实例并运行
docker run -p 9200:9200 -p 9300:9300 --name elasticsearch \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-d elasticsearch:6.4.0
### 测试
访问会返回版本信息http://192.168.1.66:9200/
### 安装目录位置
/usr/share/elasticsearch
### 安装head插件(可以不安装,仅用于测试)
1. 进入docker内部bash:docker exec -it elasticsearch /bin/bash
2. 安装插件具体参考https://github.com/mobz/elasticsearch-head
3. 测试http://192.168.1.66:9200/_plugin/head/
### 安装中文分词器IKAnalyzer
1. 进入docker内部bash:docker exec -it elasticsearch /bin/bash
2. 安装中文分词插件执行以下命令elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip
3. 测试:
- 访问header插件打开地址http://192.168.1.66:9200/_plugin/head/
- 选择复合查询输入地址POST:http://192.168.1.66:9200/_analyze
- 输入参数JSON:{"analyzer":"ik","text":"我们是大数据开发人员"}
## mongodb安装
### 下载镜像文件
docker pull mongo:3.2
### 创建实例并运行
docker run -p 27017:27017 --name mongo -v /mydata/mongo/db:/data/db -d mongo:3.2
### 使用mongo命令进入容器
docker exec -it mongo mongo
## SpringBoot应用命令部署
**docker容器间进行连接才能互相访问**
### 部署mall-admin
docker run -p 8080:8080 --name mall-admin \
--link mysql:db \
-v /etc/timezone:/etc/timezone \
-v /etc/localtime:/etc/localtime \
-v /mydata/app/admin/logs:/var/logs \
-d mall/mall-admin:1.0-SNAPSHOT
### 部署mall-search
docker run -p 8081:8081 --name mall-search \
--link elasticsearch:es \
--link mysql:db \
-v /etc/timezone:/etc/timezone \
-v /etc/localtime:/etc/localtime \
-v /mydata/app/search/logs:/var/logs \
-d mall/mall-search:1.0-SNAPSHOT
### 部署mall-port
docker run -p 8085:8085 --name mall-portal \
--link mysql:db \
--link redis:redis \
--link mongo:mongo \
-v /etc/timezone:/etc/timezone \
-v /etc/localtime:/etc/localtime \
-v /mydata/app/portal/logs:/var/logs \
-d mall/mall-portal:1.0-SNAPSHOT
## SpringBoot应用自动化部署
### 部署文件
document/docker/docker-compose.yml
### 部署命令
docker-compose up -d

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>localhost:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<root level="INFO">
<appender-ref ref="LOGSTASH" />
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@ -1,14 +0,0 @@
input {
tcp {
mode => "server"
host => "0.0.0.0"
port => 4560
codec => json_lines
}
}
output {
elasticsearch {
hosts => "es:9200"
index => "springboot-logstash-%{+YYYY.MM.dd}"
}
}

View File

@ -0,0 +1,49 @@
input {
tcp {
mode => "server"
host => "0.0.0.0"
port => 4560
codec => json_lines
type => "debug"
}
tcp {
mode => "server"
host => "0.0.0.0"
port => 4561
codec => json_lines
type => "error"
}
tcp {
mode => "server"
host => "0.0.0.0"
port => 4562
codec => json_lines
type => "business"
}
tcp {
mode => "server"
host => "0.0.0.0"
port => 4563
codec => json_lines
type => "record"
}
}
filter{
if [type] == "record" {
mutate {
remove_field => "port"
remove_field => "host"
remove_field => "@version"
}
json {
source => "message"
remove_field => ["message"]
}
}
}
output {
elasticsearch {
hosts => "localhost:9200"
index => "mall-%{type}-%{+YYYY.MM.dd}"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<?PowerDesigner AppLocale="UTF16" ID="{7BB41C87-EFE8-409A-A86E-B1C3FCE34F8C}" Label="" LastModificationDate="1582621151" Name="mall" Objects="1197" Symbols="156" Target="MySQL 5.0" Type="{CDE44E21-9669-11D1-9914-006097355D9B}" signature="PDM_DATA_MODEL_XML" version="16.5.0.3982"?>
<?PowerDesigner AppLocale="UTF16" ID="{7BB41C87-EFE8-409A-A86E-B1C3FCE34F8C}" Label="" LastModificationDate="1586932707" Name="mall" Objects="1188" Symbols="156" Target="MySQL 5.0" Type="{CDE44E21-9669-11D1-9914-006097355D9B}" signature="PDM_DATA_MODEL_XML" version="16.5.0.3982"?>
<!-- do not edit this file -->
<Model xmlns:a="attribute" xmlns:c="collection" xmlns:o="object">
@ -12,7 +12,7 @@
<a:Code>mall</a:Code>
<a:CreationDate>1521705583</a:CreationDate>
<a:Creator>zhenghong</a:Creator>
<a:ModificationDate>1580869150</a:ModificationDate>
<a:ModificationDate>1586932560</a:ModificationDate>
<a:Modifier>zhenghong</a:Modifier>
<a:PackageOptionsText>[FolderOptions]
@ -238,7 +238,7 @@ Constraint declaration=No
Physical Options=Yes
[FolderOptions\Physical Objects\Database Generation\Table&amp;&amp;Column\Foreign key]
Create=No
Create=Yes
Drop=Yes
Comment=Yes
@ -13122,9 +13122,9 @@ LABL 0 新宋体,8,N</a:FontList>
<a:Code>member_id</a:Code>
<a:CreationDate>1522303390</a:CreationDate>
<a:Creator>zhenghong</a:Creator>
<a:ModificationDate>1522303400</a:ModificationDate>
<a:ModificationDate>1586932707</a:ModificationDate>
<a:Modifier>zhenghong</a:Modifier>
<a:DataType>int</a:DataType>
<a:DataType>bigint</a:DataType>
</o:Column>
<o:Column Id="o717">
<a:ObjectID>0E5CDA77-D030-43C4-8F3F-62F1DDAF2321</a:ObjectID>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 192 KiB

10
document/sh/Dockerfile Normal file
View File

@ -0,0 +1,10 @@
# 该镜像需要依赖的基础镜像
FROM java:8
# 将当前目录下的jar包复制到docker容器的/目录下
ADD mall-admin-1.0.1-SNAPSHOT.jar /mall-admin-1.0.1-SNAPSHOT.jar
# 声明服务运行在8088端口
EXPOSE 8080
# 指定docker容器启动时运行jar包
ENTRYPOINT ["java", "-jar","/mall-admin-1.0.1-SNAPSHOT.jar"]
# 指定维护者的名字
MAINTAINER macro

28
document/sh/run.sh Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
# 定义应用组名
group_name='mall'
# 定义应用名称
app_name='mall-admin'
# 定义应用版本
app_version='1.0.1-SNAPSHOT'
# 定义应用环境
profile_active='prod'
echo '----copy jar----'
docker stop ${app_name}
echo '----stop container----'
docker rm ${app_name}
echo '----rm container----'
docker rmi ${group_name}/${app_name}:${app_version}
echo '----rm image----'
# 打包编译docker镜像
docker build -t ${group_name}/${app_name}:${app_version} .
echo '----build image----'
docker run -p 8080:8080 --name ${app_name} \
--link mysql:db \
--link redis:redis \
-e 'spring.profiles.active'=${profile_active} \
-e TZ="Asia/Shanghai" \
-v /etc/localtime:/etc/localtime \
-v /mydata/app/${app_name}/logs:/var/logs \
-d ${group_name}/${app_name}:${app_version}
echo '----start container----'

View File

@ -29,14 +29,14 @@
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -1,144 +0,0 @@
package com.macro.mall.bo;
/**
* Controller层的日志封装类
* Created by macro on 2018/4/26.
*/
public class WebLog {
/**
* 操作描述
*/
private String description;
/**
* 操作用户
*/
private String username;
/**
* 操作时间
*/
private Long startTime;
/**
* 消耗时间
*/
private Integer spendTime;
/**
* 根路径
*/
private String basePath;
/**
* URI
*/
private String uri;
/**
* URL
*/
private String url;
/**
* 请求类型
*/
private String method;
/**
* IP地址
*/
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;
}
}

View File

@ -1,78 +0,0 @@
package com.macro.mall.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.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
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.
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.macro.mall.controller"))
.paths(PathSelectors.any())
.build()
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("mall后台系统")
.description("mall后台模块")
.contact("macro")
.version("1.0")
.build();
}
private List<ApiKey> securitySchemes() {
//设置请求头信息
List<ApiKey> result = new ArrayList<>();
ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");
result.add(apiKey);
return result;
}
private List<SecurityContext> securityContexts() {
//设置需要登录认证的路径
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() {
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;
}
}

View File

@ -0,0 +1,27 @@
package com.macro.mall.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 API文档相关配置
* 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.controller")
.title("mall后台系统")
.description("mall后台相关接口文档")
.contactName("macro")
.version("1.0")
.enableSecurity(true)
.build();
}
}

View File

@ -1,13 +1,13 @@
package com.macro.mall.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.macro.mall.common.service.RedisService;
import com.macro.mall.dao.UmsAdminRoleRelationDao;
import com.macro.mall.mapper.UmsAdminRoleRelationMapper;
import com.macro.mall.model.UmsAdmin;
import com.macro.mall.model.UmsAdminRoleRelation;
import com.macro.mall.model.UmsAdminRoleRelationExample;
import com.macro.mall.model.UmsResource;
import com.macro.mall.security.service.RedisService;
import com.macro.mall.service.UmsAdminCacheService;
import com.macro.mall.service.UmsAdminService;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -17,4 +17,12 @@ spring:
database: 0 # Redis数据库索引默认为0
port: 6379 # Redis服务器连接端口
password: # Redis服务器连接密码默认为空
timeout: 300ms # 连接超时时间(毫秒)
timeout: 300ms # 连接超时时间(毫秒)
logging:
level:
root: info
com.macro.mall: debug
logstash:
host: localhost

View File

@ -20,4 +20,11 @@ spring:
timeout: 300ms # 连接超时时间(毫秒)
logging:
path: /var/logs #配置日志生成路径
file:
path: /var/logs
level:
root: info
com.macro.mall: info
logstash:
host: logstash

View File

@ -1,4 +1,6 @@
spring:
application:
name: mall-admin
profiles:
active: dev #默认为开发环境
servlet:
@ -15,7 +17,7 @@ jwt:
tokenHeader: Authorization #JWT存储的请求头
secret: mall-admin-secret #JWT加解密使用的密钥
expiration: 604800 #JWT的超期限时间(60*60*24*7)
tokenHead: 'Bearer ' #JWT负载中拿到开头
tokenHead: 'Bearer ' #JWT负载中拿到开头
redis:
database: mall
@ -63,10 +65,3 @@ minio:
bucketName: mall #存储桶名称
accessKey: minioadmin #访问的key
secretKey: minioadmin #访问的秘钥
logging:
level:
root: info #日志配置DEBUG,INFO,WARN,ERROR
com.macro.mall: debug
# file: demo_log.log #配置日志生成路径
# path: /var/logs #配置日志文件名称

View File

@ -1,31 +0,0 @@
<?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"/>
<!--应用名称-->
<property name="APP_NAME" value="mall-admin"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/logs}"/>
<contextName>${APP_NAME}</contextName>
<!--每天记录日志到文件appender-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--输出到logstash的appender-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>localhost:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root>
</configuration>

View File

@ -19,6 +19,26 @@
</parent>
<dependencies>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
@ -27,18 +47,6 @@
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,68 @@
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();
}
}

View File

@ -1,47 +1,45 @@
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();
}

View File

@ -0,0 +1,47 @@
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;
}

View File

@ -0,0 +1,68 @@
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 {
/**
* 操作描述
*/
private String description;
/**
* 操作用户
*/
private String username;
/**
* 操作时间
*/
private Long startTime;
/**
* 消耗时间
*/
private Integer spendTime;
/**
* 根路径
*/
private String basePath;
/**
* URI
*/
private String uri;
/**
* URL
*/
private String url;
/**
* 请求类型
*/
private String method;
/**
* IP地址
*/
private String ip;
/**
* 请求参数
*/
private Object parameter;
/**
* 返回结果
*/
private Object result;
}

View File

@ -1,10 +1,9 @@
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() {
}

View File

@ -1,4 +1,4 @@
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结构中的属性

View File

@ -1,9 +1,8 @@
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);
}

View File

@ -0,0 +1,196 @@
<?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>

View File

@ -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>

View File

@ -1,37 +0,0 @@
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();
}
}

View File

@ -0,0 +1,28 @@
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();
}
}

View File

@ -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:

View File

@ -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>

View File

@ -0,0 +1,27 @@
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();
}
}

View File

@ -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;

View File

@ -1,11 +1,10 @@
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;

View File

@ -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

View File

@ -35,8 +35,14 @@ spring:
virtual-host: /mall
username: mall
password: mall
publisher-confirms: true #如果对异步消息需要回调必须设置为true
# 日志配置
logging:
path: /var/logs
logging:
file:
path: /var/logs
level:
root: info
com.macro.mall: info
logstash:
host: logstash

View File

@ -1,4 +1,6 @@
spring:
application:
name: mall-portal
profiles:
active: dev #默认为开发环境

View File

@ -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) {

View File

@ -1,38 +0,0 @@
package com.macro.mall.search.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文档相关配置
* Created by macro on 2018/4/26.
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.macro.mall.search.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("mall搜索系统")
.description("mall搜索模块")
.contact("macro")
.version("1.0")
.build();
}
}

View File

@ -0,0 +1,27 @@
package com.macro.mall.search.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.search.controller")
.title("mall搜索系统")
.description("mall搜索相关接口文档")
.contactName("macro")
.version("1.0")
.enableSecurity(false)
.build();
}
}

View File

@ -5,7 +5,6 @@ import com.macro.mall.search.domain.EsProduct;
import com.macro.mall.search.domain.EsProductRelatedInfo;
import com.macro.mall.search.repository.EsProductRepository;
import com.macro.mall.search.service.EsProductService;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
@ -14,10 +13,10 @@ import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.filter.InternalFilter;
import org.elasticsearch.search.aggregations.bucket.nested.InternalNested;
import org.elasticsearch.search.aggregations.bucket.terms.LongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.filter.ParsedFilter;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
@ -28,7 +27,10 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
@ -39,6 +41,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -53,7 +56,7 @@ public class EsProductServiceImpl implements EsProductService {
@Autowired
private EsProductRepository productRepository;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Override
public int importAll() {
List<EsProduct> esProductList = productDao.getAllEsProductList(null);
@ -157,7 +160,12 @@ public class EsProductServiceImpl implements EsProductService {
nativeSearchQueryBuilder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC));
NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build();
LOGGER.info("DSL:{}", searchQuery.getQuery().toString());
return productRepository.search(searchQuery);
SearchHits<EsProduct> searchHits = elasticsearchRestTemplate.search(searchQuery, EsProduct.class);
if(searchHits.getTotalHits()<=0){
return new PageImpl<>(null,pageable,0);
}
List<EsProduct> searchProductList = searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList());
return new PageImpl<>(searchProductList,pageable,searchHits.getTotalHits());
}
@Override
@ -196,7 +204,12 @@ public class EsProductServiceImpl implements EsProductService {
builder.withPageable(pageable);
NativeSearchQuery searchQuery = builder.build();
LOGGER.info("DSL:{}", searchQuery.getQuery().toString());
return productRepository.search(searchQuery);
SearchHits<EsProduct> searchHits = elasticsearchRestTemplate.search(searchQuery, EsProduct.class);
if(searchHits.getTotalHits()<=0){
return new PageImpl<>(null,pageable,0);
}
List<EsProduct> searchProductList = searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList());
return new PageImpl<>(searchProductList,pageable,searchHits.getTotalHits());
}
return new PageImpl<>(null);
}
@ -225,16 +238,14 @@ public class EsProductServiceImpl implements EsProductService {
.field("attrValueList.name"))));
builder.addAggregation(aggregationBuilder);
NativeSearchQuery searchQuery = builder.build();
return elasticsearchTemplate.query(searchQuery, response -> {
LOGGER.info("DSL:{}",searchQuery.getQuery().toString());
return convertProductRelatedInfo(response);
});
SearchHits<EsProduct> searchHits = elasticsearchRestTemplate.search(searchQuery, EsProduct.class);
return convertProductRelatedInfo(searchHits);
}
/**
* 将返回结果转换为对象
*/
private EsProductRelatedInfo convertProductRelatedInfo(SearchResponse response) {
private EsProductRelatedInfo convertProductRelatedInfo(SearchHits<EsProduct> response) {
EsProductRelatedInfo productRelatedInfo = new EsProductRelatedInfo();
Map<String, Aggregation> aggregationMap = response.getAggregations().getAsMap();
//设置品牌
@ -253,14 +264,14 @@ public class EsProductServiceImpl implements EsProductService {
productRelatedInfo.setProductCategoryNames(productCategoryNameList);
//设置参数
Aggregation productAttrs = aggregationMap.get("allAttrValues");
List<LongTerms.Bucket> attrIds = ((LongTerms) ((InternalFilter) ((InternalNested) productAttrs).getProperty("productAttrs")).getProperty("attrIds")).getBuckets();
List<? extends Terms.Bucket> attrIds = ((ParsedLongTerms) ((ParsedFilter) ((ParsedNested) productAttrs).getAggregations().get("productAttrs")).getAggregations().get("attrIds")).getBuckets();
List<EsProductRelatedInfo.ProductAttr> attrList = new ArrayList<>();
for (Terms.Bucket attrId : attrIds) {
EsProductRelatedInfo.ProductAttr attr = new EsProductRelatedInfo.ProductAttr();
attr.setAttrId((Long) attrId.getKey());
List<String> attrValueList = new ArrayList<>();
List<StringTerms.Bucket> attrValues = ((StringTerms) attrId.getAggregations().get("attrValues")).getBuckets();
List<StringTerms.Bucket> attrNames = ((StringTerms) attrId.getAggregations().get("attrNames")).getBuckets();
List<? extends Terms.Bucket> attrValues = ((ParsedStringTerms) attrId.getAggregations().get("attrValues")).getBuckets();
List<? extends Terms.Bucket> attrNames = ((ParsedStringTerms) attrId.getAggregations().get("attrNames")).getBuckets();
for (Terms.Bucket attrValue : attrValues) {
attrValueList.add(attrValue.getKeyAsString());
}

View File

@ -16,4 +16,14 @@ spring:
elasticsearch:
repositories:
enabled: true
cluster-nodes: 127.0.0.1:9300
elasticsearch:
rest:
uris: localhost:9200
logging:
level:
root: info
com.macro.mall: debug
logstash:
host: localhost

View File

@ -12,12 +12,20 @@ spring:
stat-view-servlet: #访问监控网页的登录用户名和密码
login-username: druid
login-password: druid
data:
elasticsearch:
repositories:
enabled: true
cluster-nodes: es:9300
elasticsearch:
rest:
uris: es:9200
logging:
path: /var/logs #配置日志生成路径
file:
path: /var/logs
level:
root: info
com.macro.mall: info
logstash:
host: logstash

View File

@ -1,4 +1,6 @@
spring:
application:
name: mall-search
profiles:
active: dev #默认为开发环境
@ -10,10 +12,5 @@ mybatis:
- classpath:dao/*.xml
- classpath*:com/**/mapper/*.xml
logging:
level:
root: info
com.macro.mall: debug

View File

@ -2,14 +2,12 @@ package com.macro.mall.search;
import com.macro.mall.search.dao.EsProductDao;
import com.macro.mall.search.domain.EsProduct;
import com.macro.mall.search.repository.EsProductRepository;
import org.elasticsearch.action.search.SearchResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.ResultsExtractor;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@ -21,7 +19,7 @@ public class MallSearchApplicationTests {
@Autowired
private EsProductDao productDao;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
private ElasticsearchRestTemplate elasticsearchTemplate;
@Test
public void contextLoads() {
}
@ -32,8 +30,9 @@ public class MallSearchApplicationTests {
}
@Test
public void testEsProductMapping(){
elasticsearchTemplate.putMapping(EsProduct.class);
Map mapping = elasticsearchTemplate.getMapping(EsProduct.class);
IndexOperations indexOperations = elasticsearchTemplate.indexOps(EsProduct.class);
indexOperations.putMapping(indexOperations.createMapping(EsProduct.class));
Map mapping = indexOperations.getMapping();
System.out.println(mapping);
}

View File

@ -1,63 +1,15 @@
package com.macro.mall.security.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import com.macro.mall.common.config.BaseRedisConfig;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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相关配置
* Redis配置类
* Created by macro on 2020/3/2.
*/
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@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);
objectMapper.enableDefaultTyping(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);
}
public class RedisConfig extends BaseRedisConfig {
}

25
pom.xml
View File

@ -22,7 +22,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
@ -42,11 +42,11 @@
<swagger-annotations.version>1.6.0</swagger-annotations.version>
<mybatis-generator.version>1.3.7</mybatis-generator.version>
<mybatis.version>3.4.6</mybatis.version>
<mysql-connector.version>8.0.16</mysql-connector.version>
<spring-data-commons.version>2.1.5.RELEASE</spring-data-commons.version>
<mysql-connector.version>8.0.15</mysql-connector.version>
<spring-data-commons.version>2.3.0.RELEASE</spring-data-commons.version>
<jjwt.version>0.9.0</jjwt.version>
<aliyun-oss.version>2.5.0</aliyun-oss.version>
<logstash-logback.version>4.8</logstash-logback.version>
<logstash-logback.version>5.3</logstash-logback.version>
<minio.version>3.0.10</minio.version>
<guava.version>20.0</guava.version>
<mall-common.version>1.0-SNAPSHOT</mall-common.version>
@ -55,10 +55,6 @@
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
@ -73,12 +69,17 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>