框架搭建说明
1 框架构架图
2 后台框架具体说明
后端框架:springboot2.1.8+springmvc+mybatisPlus3.2
开发语言:java
数据库:mysql5.7
缓存数据库:redis
权限框架:shiro
网关:Spring Gateway
注册中心: 阿里巴巴 nacos eureka(已经停止更新)
熔断器:Sentinel
消息队列:RocketMQ
全文日志分析:ElasticSearch+Logstash+Kibana
数据源管理:druid
所用工具:lombok
开发工具:IntelliJ IDEA
数据设计工具:Power Designer
项目版本控制工具:git
文档管理工具:svn
3.模块搭建具体说明
- 准备nacos
-
nacos 的官方地址
内有文档手册
https://nacos.io/zh-cn/index.html
下载页面
- nacos 安装
解压打开安装目录的bin下的双击运行startup即可(windows运行cmd,linux运行sh) - 服务中集成了配置中心,注册中心和管理中心只需要导入相应的包即可使用
-
- 创建父模块
- 创建一个mavean项目
删除多余的src - 配置pom.xml管理版本
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.springboot</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <name>demo</name> <description>项目的父工程root</description> <!--子模块管理--> <modules> <module>authority</module> <module>base</module> <module>sort-test</module> <module>cloud-gateway</module> <module>rocketmq-consumer</module> <module>rocketmq-provider</module> <module>elasticsearch</module> </modules> <properties> <java.version>1.8</java.version> <!--项目构建的编码--> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!--日志框架--> <slf4j.version>1.7.25</slf4j.version> <logback.version>1.2.3</logback.version> <!--json工具--> <fastjson.version>1.2.24</fastjson.version> <!--数据连接池管理工具--> <druid.version>1.1.10</druid.version> <!--redis--> <jedis.version>2.9.0</jedis.version> <!--添加MySql依赖--> <mysql.version>8.0.15</mysql.version> <!--测试类工具--> <junit.version>4.12</junit.version> <!--代码简化lombok--> <lombok.version>1.16.6</lombok.version> <!--集成mybatisPlus--> <mybatis-plus.version>3.1.1</mybatis-plus.version> <!--添加模板引擎依赖默认的--> <velocity-engine-core.version>2.1</velocity-engine-core.version> <dynamic.datasource.boot.version>2.5.4</dynamic.datasource.boot.version> <swagger.ui>2.9.2</swagger.ui> </properties> <!--dependencyManagement用于管理依赖版本号--> <dependencyManagement> <dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>${dynamic.datasource.boot.version}</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.6</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.29</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.1.9.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <version>2.1.8.RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version> ${velocity-engine-core.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.0.7.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!--import druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId> org.springframework.boot </groupId> <artifactId> spring-boot-configuration-processor </artifactId> <optional> true </optional> <version>2.0.3.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${jedis.version}</version> </dependency> <!-- jwt --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.2</version> </dependency> <!-- Excel工具 --> <dependency> <groupId>com.wuwenze</groupId> <artifactId>ExcelKit</artifactId> <version>2.0.72</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.ui}</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <!-- sql 打印 --> <dependency> <groupId>p6spy</groupId> <artifactId>p6spy</artifactId> <version>3.8.5</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.ui}</version> </dependency> <!-- ip2region --> <dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>1.7.2</version> </dependency> <!--shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency> <!-- shiro+redis缓存插件 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>2.1.10.RELEASE</version> </dependency> <!--springCloud相关jar包--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>0.9.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <nonFilteredFileExtensions> <nonFilteredFileExtension>woff</nonFilteredFileExtension> <nonFilteredFileExtension>woff2</nonFilteredFileExtension> <nonFilteredFileExtension>eot</nonFilteredFileExtension> <nonFilteredFileExtension>ttf</nonFilteredFileExtension> <nonFilteredFileExtension>svg</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <delimiters> <delimiter>@</delimiter> </delimiters> <useDefaultDelimiters>false</useDefaultDelimiters> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <excludes> <exclude>**/*.woff</exclude> <exclude>**/*.woff2</exclude> <exclude>**/*.ttf</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> <filtering>false</filtering> <includes> <include>**/*.woff</include> <include>**/*.woff2</include> <include>**/*.ttf</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build> <repositories> <repository> <id>nexus-aliyun</id> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </repository> </repositories> </project>
可以酌情减少多余的包
- 创建一个mavean项目
- 创建普通子模块
- 数据库配置
pom<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.10</version> </dependency>
ymlspring: application: name: senta-base #项目名称方便feign调用 cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #nacos注册中心地址 sentinel: transport: dashboard: 127.0.0.1:8888 #sentinel服务管理地址 #eager: true autoconfigure: exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 为了某些版本的springboot @SpringBootApplication(exclude= {DataSourceAutoConfiguration.class}) 无法生效 #json 时间戳统一转换 jackson: time-zone: GMT+8 date-format: yyyy-MM-dd HH:mm:ss # 设置静态文件路径,js,css等 thymeleaf: prefix: classpath:/static/ suffix: .html datasource: # 使用druid数据源 设置druid数据源网页登录账号密码 因为是多数据源所以配置在这里 druid: stat-view-servlet: login-username: admin #网页登录账号 登录地址 http://localhost:端口号/项目名称/druid/index.html login-password: 123456 #登录密码 本项目登录地址是 http://localhost:9092/base/druid/index.html # 配置多数据源 dynamic: primary: db1 #设置默认的数据源或者数据源组,默认值即为db1 datasource: # db1: # driver-class-name: com.mysql.cj.jdbc.Driver # url: jdbc:mysql://127.0.0.1:3306/jeecg_boot_os?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=true&serverTimezone=GMT%2B8 # username: ** # password: ** db1: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/senta-service-mdt2.0?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=GMT%2B8 username: ** password: ** db2: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3309/rocketmq?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=true&serverTimezone=GMT%2B8 username: ** password: ** #配置druid数据源的相关参数 不需要单独在写DruidConfiguration.java的配置类 druid: initial-size: 5 #初始化大小 min-idle: 5 #最小连接数 maxActive: 20 #最大连接数 maxWait: 60000 #获取连接等待超时时间单位毫秒 timeBetweenEvictionRunsMillis: 60000 # 间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 minEvictableIdleTimeMillis: 300000 #一个连接在池中最小生存的时间,单位是毫秒 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true #空闲时测试 testOnBorrow: false testOnReturn: false poolPreparedStatements: true # 打开PSCache,并且指定每个连接上PSCache的大小 maxPoolPreparedStatementPerConnectionSize: 20 #每个连接大小的最大池准备语句数 filters: config,stat,wall #配置监控统计拦截的filters,去掉后监控界面SQL无法进行统计,’wall’用于防火墙 connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000 # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter web-stat-filter: # 配置DruidStatFilter enabled: true url-pattern: /* exclusions: /druid/*, *.js ,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico, stat-view-servlet: # 配置DruidStatViewServlet url-pattern: /druid/* #请求前缀 allow: 127.0.0.1,192.168.0.17 # IP白名单(没有配置或者为空,则允许所有访问) deny: 192.168.1.73 # IP黑名单 (存在共同时,deny优先于allow) reset-enable: false # 禁用HTML页面上的“Reset All”功能 http: encoding: force: true management: # 端点检查(健康检查) endpoints: web: exposure: include: "*" base-path: /actuator enabled-by-default: true endpoint: health: enabled: true info: enabled: true server: port: 8007 #开启feign对sentinel的支持 feign: sentinel: enabled: true # 配置mybatis-plus mybatis-plus: # 配置扫描xml mapper-locations: classpath:com/springboot/base/mapper/xml/*.xml # 实体扫描,多个package用逗号或者分号分隔 type-aliases-package: com.springboot.base.entity configuration: # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: # 关闭MP3.0自带的banner banner: false db-config: #主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)"; id-type: auto # 默认数据库表下划线命名 table-underline: true db-type: mysql #逻辑删除配置 logic-not-delete-value: 1 #删除前 logic-delete-value: 0 #删除后
- 集成nacos和配置中心
<!-- Spring Boot Begin --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Spring Boot End -->
<!-- Spring Cloud Begin --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
@EnableDiscoveryClient //开启服务发现 public class Application{ public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
spring: application: # 应用名称 name: spring-gateway cloud: # 使用 Naoos 作为服务注册发现 nacos: discovery: server-addr: 127.0.0.1:8848 # 使用 Sentinel 作为熔断器 sentinel: transport: port: 8721 dashboard: localhost:8888 # 路由网关配置 gateway: # 设置与服务注册发现组件结合,这样可以采用服务名的路由策略 discovery: locator: enabled: true # 配置路由规则 routes: - id: SENTA-SORT uri: lb://senta-sort predicates: - Method=GET,POST - Path=/sort/** - id: SENTA-auth uri: lb://senta-authority predicates: - Method=GET,POST - Path=/authority-cf/** - id: SENTA-BASE uri: lb://senta-base predicates: - Method=GET,POST - Path=/base/** server: port: 9000 # 目前无效 feign: sentinel: enabled: true # 目前无效 management: endpoints: web: exposure: include: "*" # 暴露端点 server: port: 9001 endpoint: health: show-details: always # 配置日志级别,方别调试 logging: level: org.springframework.cloud.gateway: debug
- 集成feign和sentinel和端口检查
<!-- 端点检查、健康检查--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
@MapperScan("com.springboot.gateway.mapper") @SpringBootApplication(exclude= {DataSourceAutoConfiguration.class}) //数据库 @EnableDiscoveryClient //启用注册中心发现 @EnableFeignClients //启用feign客户端 public class SortTestApplication{ public static void main(String[] args) { SpringApplication.run(SortTestApplication.class, args); } }
@FeignClient(value = "senta-sort",fallback = ProviderFailBack.class) public interface ProviderClient { /** * 调用base模块的方法 * 调用格式 @GetMapping("/项目名称/模块名称/请求方法") * @param name 参数名称 * @return sys-user中hello的具体返回数据 */ @GetMapping("/ssort/sys-user/hello") String hello(@RequestParam(value = "name",defaultValue = "nacos",required = false)String name); /** * 调用base模块的方法 * 调用格式 @GetMapping("/项目名称/模块名称/请求方法") * @return sys-user中hello的具体返回数据 */ @GetMapping("/ssort/sys-user/abc") String abc(); }
- 集成网关
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
配置参考以上的配置中
- 集成Elasticsearch
<!-- ES --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.10</version> </dependency>
直接调用接口已经包含了大部分基础操作/** * @author anyang * Email: 1300378587@qq.com * Created Date:2019-11-19 11:01 */ //@Repository public interface **Repository extends ElasticsearchRepository<主题类,主键类型>{ }
一下是生成数据库到es的工具类,依赖mybatisPlus,可稍作修改即可支持所有/** * @author anyang * Email: 1300378587@qq.com * Created Date:2019-11-28 14:16 */ public interface ElasticUtil<T>{ boolean createIndex( ); boolean deleteIndex( ); } ====================================================== package com.senta.elasticsearch.utils; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import lombok.extern.slf4j.Slf4j; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.query.IndexQuery; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; /** * @author anyang * Email: 1300378587@qq.com * Created Date:2019-11-21 17:18 */ @Slf4j public class EsUtil <T> implements ElasticUtil<T>{ private Class<T> aClass; private String indexName; private String docType ; private String keyField; private ElasticsearchTemplate elasticsearchTemplate; public void setElasticsearchTemplate(ElasticsearchTemplate elasticsearchTemplate){ this.elasticsearchTemplate = elasticsearchTemplate; } EsUtil(Class<T> aClass,String indexName,String docType,String keyField){ this.docType = docType; this.indexName = indexName; this.aClass = aClass; this.keyField = keyField; } EsUtil(Class<T> aClass,String indexName,String docType,String keyField,ElasticsearchTemplate elasticsearchTemplate){ this.elasticsearchTemplate = elasticsearchTemplate; this.docType = docType; this.indexName = indexName; this.aClass = aClass; this.keyField = keyField; } /** * 测试结果为数据适配在10w-15w之间,随着数据深分页的增加,速度减慢,由150000/30s --> 150000/75s * 其中90%的时间消耗在MySQL,但是由于Elasticsearch是异步执行数据的,初步期望数据流量在10M/s以内为最佳 * 另,RocketMQ的消息传递在单条消息有限制,10M以内,所以建议单条数据不宜过大,当然在实时通过过程中一般 * 不会遇到如此大的数据量,暂不设置限制 * * 该方法仅在初始化导入数据时使用 * @param cacheCount 缓存的每页数据条数 * @param elasticsearchTemplate ElasticsearchTemplate 是springboot集成后自带的建议模板 * @param service 输入用户的尸体service实现,依赖MybatisPlus * @return */ public boolean doDataToEsFromDB(final long cacheCount, ElasticsearchTemplate elasticsearchTemplate, IService<T> service){ setElasticsearchTemplate(elasticsearchTemplate); //当目标索引库存在进行以下操作 if(elasticsearchTemplate.indexExists(aClass)){ if(cacheCount>150000L){ log.warn("缓存容量偏大,建议单次数据小于20M,建议10w条/次"); } //查询次数 int currentSelectTime = 1; //导入次数 int currentIndexTime = 1; //定义当前页数 long currenPage = 1; //获取对应的类 final int totalCount = service.count(); final long pageCount = totalCount/cacheCount +1; while(currenPage<=pageCount){ //开始查询记录 准备 Page<T> billingItemDisPage = new Page<>(); billingItemDisPage.setSize(cacheCount); billingItemDisPage.setCurrent(currenPage); billingItemDisPage.setTotal(totalCount); log.info("第"+currentSelectTime+"次开始从数据库查询 "+ LocalDateTime.now()); IPage<T> page = service.page(billingItemDisPage); log.info("第"+currentSelectTime+"次结束从数据库查询 "+ LocalDateTime.now()); //取出对象中的数据 List<T> dbList = page.getRecords(); //保存到es if(dbList != null && dbList.size()>0){ //判断查询有结果 ArrayList<IndexQuery> queries = new ArrayList<>(); dbList.forEach(item -> { Object id = null; try{ Class<?> theClass = item.getClass(); Method method = theClass.getMethod(keyField, null); Object invoke = method.invoke(item, null); id = invoke; }catch(NoSuchMethodException | InvocationTargetException | IllegalAccessException e){ log.error(e.getMessage()); } if(id == null){ throw new UnsupportedOperationException("主键值不允许为null"); } //创建对象 IndexQuery indexQuery = new IndexQuery(); indexQuery.setId(id.toString()); indexQuery.setObject(item); indexQuery.setIndexName(indexName); indexQuery.setType(docType); //添加到集合 queries.add(indexQuery); }); log.info("开始第 "+currentIndexTime+" 导入"); elasticsearchTemplate.bulkIndex(queries); log.info("导入第"+currentIndexTime+" 已派发"); } //重定义索引范围 currentIndexTime++; //重定义下一次搜索次数 currentSelectTime++; //设置下一页 currenPage = page.getCurrent() + 1L; } log.info("数据库迁移拷贝完成"); return true; } return false; } public boolean createIndex(){ return doCreateIndex(); } @Override public boolean deleteIndex(){ return elasticsearchTemplate.deleteIndex(indexName); } public boolean doCreateIndex() { boolean result = false; if(elasticsearchTemplate == null){ log.error("缺elasticsearchTemplate对象 -- null"); }else{ if(elasticsearchTemplate.indexExists(indexName)){ boolean delResult = elasticsearchTemplate.deleteIndex(indexName); if(delResult){ result = elasticsearchTemplate.createIndex(aClass); } }else result = elasticsearchTemplate.createIndex(aClass); } return result; } } ============================================================================== package com.senta.elasticsearch.utils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.stereotype.Component; import java.lang.annotation.Annotation; import java.lang.reflect.Field; /** * @author anyang * Email: 1300378587@qq.com * Created Date:2019-11-22 09:57 * 测试完成,初步构建合格,功能正常 */ @Component public class EsUtilBuilder { @Autowired private static ElasticsearchTemplate elasticsearchTemplate; public static <T> EsUtil build(Class<T> buiderClass ){ if(buiderClass == null){ throw new NullPointerException("传入类不予许为null"); } Annotation classAnnotation = buiderClass.getAnnotation(Document.class); Document theDocument = null; if(classAnnotation instanceof Document) { theDocument = (Document)classAnnotation ; } //获取文档注解 if(theDocument == null){ throw new NullPointerException("该类不是一个文档类型,需要@Document "); } String indexName = theDocument.indexName(); String docType = theDocument.type(); //如果获取索引和类型失败则抛出异常 if(StringUtils.isBlank(indexName) || StringUtils.isBlank(docType)){ throw new UnsupportedOperationException("确少相关的配置"); } //寻找主键 final Field[] fields = buiderClass.getDeclaredFields(); Field keyField = null; for(Field field : fields ){ //获取主键字段 Annotation annotation = field.getAnnotation(org.springframework.data.annotation.Id.class); if(annotation != null){ keyField = field; break; } } if(keyField == null){ throw new UnsupportedOperationException("缺少相关主键"); } return new EsUtil<T>(buiderClass,indexName,docType,toGetter(keyField.getName()),elasticsearchTemplate); } public static String toGetter(String fieldname) { if (fieldname == null || fieldname.length() == 0) { return null; } /* If the second char is upper, make 'get' + field name as getter name. For example, eBlog -> geteBlog */ if (fieldname.length() > 2) { String second = fieldname.substring(1, 2); if (second.equals(second.toUpperCase())) { return new StringBuffer("get").append(fieldname).toString(); } } /* Common situation */ fieldname = new StringBuffer("get").append(fieldname.substring(0, 1).toUpperCase()) .append(fieldname.substring(1)).toString(); return fieldname; } }
- 集成RocketMQ
<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> </dependency>
提供方
@GetMapping("/mqtest/psend") public String psend( String name) throws InterruptedException{ DefaultMQProducer producer = rocketMQTemplate.getProducer(); //创建消息,设置topic和body Message msg = new Message(mqTopic,"sort消息体".getBytes()); //发送消息 Rocketmq rocketmq = sendMessage(producer,msg); //保存到数据库 boolean saveResult = rocketmqService.save(rocketmq); log.info("消息发送完毕,消息保存: "+ LocalDateTime.now()); return " producer服务发送: 端口: " + port+" time: "+ LocalDateTime.now(); } private Rocketmq sendMessage(DefaultMQProducer producer,Message msg) throws InterruptedException{ //创建记录保存对象 String localResult = ""; Rocketmq rocketmq = new Rocketmq(); rocketmq.setInfo("sort send message"); rocketmq.setType("0"); SendResult result = null ; try{ producer.setProducerGroup(producerGroup); //发送消息 result = producer.send(msg); localResult = localResult+result; rocketmq.setResult(localResult); }catch(RemotingException e){ rocketmq.setResult(e.getMessage()); log.error("Remoting Exception ",e); }catch(MQClientException e){ rocketmq.setResult(e.getMessage()); log.error("MQClient Exception ",e); }catch(MQBrokerException e){ rocketmq.setResult(e.getMessage()); log.error("MQBroker Exception ",e); } return rocketmq; }
消费方
/** * Created by anyang * Email: 1300378587@qq.com * Created Date:2019-11-12 09:48 */ @Slf4j @Component @RocketMQMessageListener(topic = "xst-mq",consumerGroup = "${rocketmq.consumer.group}",messageModel = MessageModel.CLUSTERING) //订阅主题= "springboot-rocketmq",消费者组, messageModel:消费模式【广播,负载均衡】 public class Cusumer implements RocketMQListener<MessageExt>{ @Autowired RocketmqService rocketmqService; @Override public void onMessage(MessageExt message){ String msgId = message.getMsgId(); String body = new String(message.getBody()); log.info("收到消息:: "+msgId); //创建对象保存进程的情况 //sdsdsd Rocketmq rocketmq = new Rocketmq(); rocketmq.setInfo("massage received " + msgId); rocketmq.setResult(body); rocketmq.setType("1"); boolean save = rocketmqService.save(rocketmq); log.info("保存消息:: "+message+" "+(save?"成功":"失败")+ LocalDateTime.now()); } }
来源:oschina
链接:https://my.oschina.net/u/4108086/blog/3135311