├── .doc └── docker │ ├── docker │ ├── docker-compose-common.yml │ ├── docker-compose-kafka.yml │ └── docker-compose-rocketmq.yml ├── README.md ├── activemq ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ocean │ │ │ └── activemq │ │ │ ├── ActivemqApplication.java │ │ │ ├── config │ │ │ ├── ActiveMqName.java │ │ │ └── JmsConfig.java │ │ │ ├── consumer │ │ │ ├── queue │ │ │ │ ├── QueueConsumer.java │ │ │ │ └── QueueConsumer2.java │ │ │ └── topic │ │ │ │ ├── TopicConsumer.java │ │ │ │ └── TopicConsumer2.java │ │ │ ├── controller │ │ │ └── SendControlller.java │ │ │ └── producer │ │ │ ├── Sender.java │ │ │ ├── queue │ │ │ └── QueueSender.java │ │ │ └── topic │ │ │ └── TopicSender.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── ocean │ └── activemq │ └── ActivemqApplicationTests.java ├── case ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ocean │ │ │ ├── CaseApplication.java │ │ │ ├── strategy │ │ │ ├── MallPackageOrderStrategy.java │ │ │ ├── PackageOrderStrategy.java │ │ │ ├── PackageOrderStrategyContext.java │ │ │ └── PartnerPackageOrderStrategy.java │ │ │ └── template │ │ │ ├── AbstractPackageOrderService.java │ │ │ ├── MallPackageOrderService.java │ │ │ ├── PackageOrder.java │ │ │ ├── PackageOrderService.java │ │ │ └── PartnerPackageOrderService.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── ocean │ ├── strategy │ └── PackageOrderStrategyContextTest.java │ └── template │ └── PackageOrderServiceTest.java ├── common ├── pom.xml └── src │ ├── main │ ├── docker │ │ └── Dockerfile │ └── java │ │ └── com │ │ └── ocean │ │ └── common │ │ ├── BaseResult.java │ │ ├── ControllerExecutor.java │ │ ├── ErrorCodeEnum.java │ │ ├── ResponseResult.java │ │ └── ServiceException.java │ └── test │ └── java │ └── com │ └── ocean │ └── lambda │ └── LambdaTest.java ├── hotchpotch ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ ├── HotchpotchApplication.java │ │ │ ├── aop │ │ │ ├── AopTestController.java │ │ │ └── WebControllerAop.java │ │ │ ├── redis │ │ │ ├── client │ │ │ │ ├── RedisClient.java │ │ │ │ └── impl │ │ │ │ │ └── RedisClientImpl.java │ │ │ └── config │ │ │ │ └── RedisConfig.java │ │ │ └── thread │ │ │ ├── config │ │ │ └── TaskThreadPoolConfig.java │ │ │ ├── demo │ │ │ ├── CurrentThreadDemo.java │ │ │ ├── MultiRunDemo.java │ │ │ ├── ThreadDemo.java │ │ │ └── ThreadNumDemo.java │ │ │ ├── excute │ │ │ └── TaskExecutePool.java │ │ │ └── task │ │ │ ├── AsyncTask.java │ │ │ ├── MyCallable.java │ │ │ ├── MyRunnable.java │ │ │ └── MyThread.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── redis │ └── client │ ├── RedisHashTest.java │ ├── RedisKeyTest.java │ ├── RedisListTest.java │ ├── RedisSetTest.java │ ├── RedisStringTest.java │ └── RedisZsetTest.java ├── mybatis ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ocean │ │ │ ├── MybatisApplication.java │ │ │ ├── common │ │ │ └── DatabaseType.java │ │ │ ├── control │ │ │ └── UserController.java │ │ │ ├── dao │ │ │ ├── NewUserMapper.java │ │ │ ├── NewUserMapper.xml │ │ │ ├── OldUserMapper.java │ │ │ └── OldUserMapper.xml │ │ │ ├── datasource │ │ │ ├── DatabaseContextHolder.java │ │ │ └── MultipleDataSource.java │ │ │ ├── interceptor │ │ │ └── DataSourceInterceptor.java │ │ │ ├── model │ │ │ ├── NewUser.java │ │ │ └── OldUser.java │ │ │ └── service │ │ │ ├── UserService.java │ │ │ └── impl │ │ │ └── UserServiceImpl.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── ocean │ └── MybatisApplicationTests.java ├── pom.xml ├── rabbitmq ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ ├── config │ │ │ ├── DirectRabbitConfig.java │ │ │ ├── FanoutRabbitConfig.java │ │ │ ├── RouteRabbitConfig.java │ │ │ └── TopicRabbitConfig.java │ │ │ └── ocean │ │ │ ├── RabbitmqApplication.java │ │ │ ├── controller │ │ │ └── SendController.java │ │ │ ├── listener │ │ │ ├── fanout │ │ │ │ └── FanoutReceiver.java │ │ │ ├── hello │ │ │ │ └── HelloReceiver.java │ │ │ ├── object │ │ │ │ └── ObjectReceiver.java │ │ │ ├── route │ │ │ │ └── RouteReceiver.java │ │ │ ├── topic │ │ │ │ └── TopicReceiver.java │ │ │ └── work │ │ │ │ ├── WorkReceiverOne.java │ │ │ │ └── WorkReceiverTwo.java │ │ │ ├── model │ │ │ ├── Message.java │ │ │ └── User.java │ │ │ └── service │ │ │ ├── SendService.java │ │ │ └── impl │ │ │ └── SendServiceImpl.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── ocean │ └── RabbitmqApplicationTests.java ├── rocketmq ├── README.md ├── docker-compose-rocketmq.yml ├── pom.xml ├── rmq │ ├── brokerconf │ │ └── broker.conf │ └── readme.md ├── rocket-common │ ├── pom.xml │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── ocean │ │ │ └── rocket │ │ │ ├── annotation │ │ │ ├── EnableRocketMQConfig.java │ │ │ ├── RocketMQConsumer.java │ │ │ ├── RocketMQKey.java │ │ │ └── RocketMQProducer.java │ │ │ ├── base │ │ │ ├── AbstractMQPushConsumer.java │ │ │ ├── AbstractRocketMQConsumer.java │ │ │ └── AbstractRocketMQProducer.java │ │ │ ├── config │ │ │ ├── BaseAutoConfig.java │ │ │ ├── ConsumerAutoConfig.java │ │ │ ├── ConsumerProperties.java │ │ │ ├── ProducerAutoConfig.java │ │ │ └── ProducerProperties.java │ │ │ ├── constants │ │ │ └── MessageConstant.java │ │ │ ├── enums │ │ │ ├── ConsumeMode.java │ │ │ └── DelayTimeLevel.java │ │ │ ├── exception │ │ │ └── RocketMqException.java │ │ │ └── hook │ │ │ ├── ConsumeOneMessageAdvice.java │ │ │ ├── ProducerShutdownHook.java │ │ │ └── PushConsumerShutdownHook.java │ └── target │ │ ├── maven-archiver │ │ └── pom.properties │ │ ├── maven-status │ │ └── maven-compiler-plugin │ │ │ ├── compile │ │ │ └── default-compile │ │ │ │ ├── createdFiles.lst │ │ │ │ └── inputFiles.lst │ │ │ └── testCompile │ │ │ └── default-testCompile │ │ │ └── inputFiles.lst │ │ └── rocket-comon-1.0-SNAPSHOT.jar ├── rocket-consumer │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── ocean │ │ │ └── rocket │ │ │ ├── RocketMqConsumerApplication.java │ │ │ └── consumer │ │ │ └── Consumer.java │ │ └── resources │ │ └── application.properties └── rocket-producer │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ocean │ │ │ └── rocket │ │ │ ├── RocketMqProducerApplication.java │ │ │ └── producer │ │ │ └── Producer.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── ocean │ └── rocket │ └── producer │ └── ProducerTest.java ├── solr ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ocean │ │ │ └── solr │ │ │ ├── SolrApplication.java │ │ │ ├── config │ │ │ └── SolrConfig.java │ │ │ ├── controller │ │ │ └── ProductController.java │ │ │ ├── dao │ │ │ └── ProductDao.java │ │ │ ├── pojo │ │ │ ├── ProductModel.java │ │ │ └── ResultModel.java │ │ │ └── service │ │ │ └── ProductService.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── ocean │ └── solr │ └── SolrApplicationTests.java └── xxl-job ├── doc ├── XXL-JOB-English-Documentation.md ├── XXL-JOB官方文档.md ├── XXL-JOB架构图.pptx ├── db │ ├── tables_mysql(备份,请忽略).sql │ └── tables_xxl_job.sql └── images │ ├── cnblog-首页-每日一博-第一.png │ ├── cnblog-首页-热门动弹-第一.png │ ├── donate-alipay.jpg │ ├── donate-paypal.png │ ├── donate-wechat.png │ ├── gitee-gvp.jpg │ ├── img_6yC0.png │ ├── img_BPLG.png │ ├── img_EB65.png │ ├── img_Fgql.png │ ├── img_Hr2T.png │ ├── img_Qohm.png │ ├── img_UDSo.png │ ├── img_V3vF.png │ ├── img_Wb2o.png │ ├── img_Ypik.png │ ├── img_Z9Qr.png │ ├── img_ZAhX.png │ ├── img_ZAsz.png │ ├── img_dNUJ.png │ ├── img_eYrv.png │ ├── img_hIci.png │ ├── img_iUw0.png │ ├── img_inc8.png │ ├── img_jOAU.png │ ├── img_jrdI.png │ ├── img_o8HQ.png │ ├── img_oLlM.png │ ├── img_tJOq.png │ ├── img_tvGI.png │ ├── qq群-一个xxl同学进了58.png │ ├── xxl-logo.jpg │ └── xxl-logo.png ├── pom.xml └── xxl-job-admin ├── Dockerfile ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── xxl │ │ └── job │ │ └── admin │ │ ├── XxlJobAdminApplication.java │ │ ├── controller │ │ ├── IndexController.java │ │ ├── JobApiController.java │ │ ├── JobCodeController.java │ │ ├── JobGroupController.java │ │ ├── JobInfoController.java │ │ ├── JobLogController.java │ │ ├── annotation │ │ │ └── PermessionLimit.java │ │ ├── interceptor │ │ │ ├── CookieInterceptor.java │ │ │ ├── PermissionInterceptor.java │ │ │ └── WebMvcConfig.java │ │ └── resolver │ │ │ └── WebExceptionResolver.java │ │ ├── core │ │ ├── conf │ │ │ ├── XxlJobAdminConfig.java │ │ │ └── XxlJobDynamicSchedulerConfig.java │ │ ├── jobbean │ │ │ └── RemoteHttpJobBean.java │ │ ├── model │ │ │ ├── XxlJobGroup.java │ │ │ ├── XxlJobInfo.java │ │ │ ├── XxlJobLog.java │ │ │ ├── XxlJobLogGlue.java │ │ │ └── XxlJobRegistry.java │ │ ├── quartz │ │ │ └── XxlJobThreadPool.java │ │ ├── route │ │ │ ├── ExecutorRouteStrategyEnum.java │ │ │ ├── ExecutorRouter.java │ │ │ └── strategy │ │ │ │ ├── ExecutorRouteBusyover.java │ │ │ │ ├── ExecutorRouteConsistentHash.java │ │ │ │ ├── ExecutorRouteFailover.java │ │ │ │ ├── ExecutorRouteFirst.java │ │ │ │ ├── ExecutorRouteLFU.java │ │ │ │ ├── ExecutorRouteLRU.java │ │ │ │ ├── ExecutorRouteLast.java │ │ │ │ ├── ExecutorRouteRandom.java │ │ │ │ └── ExecutorRouteRound.java │ │ ├── schedule │ │ │ └── XxlJobDynamicScheduler.java │ │ ├── thread │ │ │ ├── JobFailMonitorHelper.java │ │ │ ├── JobRegistryMonitorHelper.java │ │ │ └── JobTriggerPoolHelper.java │ │ ├── trigger │ │ │ ├── TriggerTypeEnum.java │ │ │ └── XxlJobTrigger.java │ │ └── util │ │ │ ├── CookieUtil.java │ │ │ ├── FtlUtil.java │ │ │ ├── I18nUtil.java │ │ │ ├── JacksonUtil.java │ │ │ └── LocalCacheUtil.java │ │ ├── dao │ │ ├── XxlJobGroupDao.java │ │ ├── XxlJobInfoDao.java │ │ ├── XxlJobLogDao.java │ │ ├── XxlJobLogGlueDao.java │ │ └── XxlJobRegistryDao.java │ │ └── service │ │ ├── XxlJobService.java │ │ └── impl │ │ ├── AdminBizImpl.java │ │ └── XxlJobServiceImpl.java └── resources │ ├── application.properties │ ├── i18n │ ├── message.properties │ └── message_en.properties │ ├── logback.xml │ ├── mybatis-mapper │ ├── XxlJobGroupMapper.xml │ ├── XxlJobInfoMapper.xml │ ├── XxlJobLogGlueMapper.xml │ ├── XxlJobLogMapper.xml │ └── XxlJobRegistryMapper.xml │ ├── quartz.properties │ ├── static │ ├── adminlte │ │ ├── bower_components │ │ │ ├── Ionicons │ │ │ │ ├── css │ │ │ │ │ └── ionicons.min.css │ │ │ │ └── fonts │ │ │ │ │ ├── ionicons.eot │ │ │ │ │ ├── ionicons.svg │ │ │ │ │ ├── ionicons.ttf │ │ │ │ │ └── ionicons.woff │ │ │ ├── PACE │ │ │ │ ├── pace.min.js │ │ │ │ └── themes │ │ │ │ │ └── blue │ │ │ │ │ └── pace-theme-flash.css │ │ │ ├── bootstrap-daterangepicker │ │ │ │ ├── daterangepicker.css │ │ │ │ └── daterangepicker.js │ │ │ ├── bootstrap │ │ │ │ ├── css │ │ │ │ │ ├── bootstrap.css.map │ │ │ │ │ └── bootstrap.min.css │ │ │ │ ├── fonts │ │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ │ └── js │ │ │ │ │ └── bootstrap.min.js │ │ │ ├── datatables.net-bs │ │ │ │ ├── css │ │ │ │ │ └── dataTables.bootstrap.min.css │ │ │ │ └── js │ │ │ │ │ └── dataTables.bootstrap.min.js │ │ │ ├── datatables.net │ │ │ │ └── js │ │ │ │ │ └── jquery.dataTables.min.js │ │ │ ├── fastclick │ │ │ │ └── fastclick.js │ │ │ ├── font-awesome │ │ │ │ ├── css │ │ │ │ │ ├── font-awesome.css.map │ │ │ │ │ └── font-awesome.min.css │ │ │ │ └── fonts │ │ │ │ │ ├── FontAwesome.otf │ │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ ├── jquery-slimscroll │ │ │ │ └── jquery.slimscroll.min.js │ │ │ ├── jquery │ │ │ │ └── jquery.min.js │ │ │ └── moment │ │ │ │ └── moment.min.js │ │ ├── dist │ │ │ ├── css │ │ │ │ ├── AdminLTE.min.css │ │ │ │ └── skins │ │ │ │ │ └── _all-skins.min.css │ │ │ └── js │ │ │ │ └── adminlte.min.js │ │ └── plugins │ │ │ └── iCheck │ │ │ ├── icheck.min.js │ │ │ └── square │ │ │ ├── blue.css │ │ │ ├── blue.png │ │ │ └── blue@2x.png │ ├── favicon.ico │ ├── js │ │ ├── common.1.js │ │ ├── index.js │ │ ├── jobcode.index.1.js │ │ ├── jobgroup.index.1.js │ │ ├── jobinfo.index.1.js │ │ ├── joblog.detail.1.js │ │ ├── joblog.index.1.js │ │ └── login.1.js │ └── plugins │ │ ├── codemirror │ │ ├── addon │ │ │ └── hint │ │ │ │ ├── anyword-hint.js │ │ │ │ ├── show-hint.css │ │ │ │ └── show-hint.js │ │ ├── lib │ │ │ ├── codemirror.css │ │ │ └── codemirror.js │ │ └── mode │ │ │ ├── clike │ │ │ └── clike.js │ │ │ ├── javascript │ │ │ └── javascript.js │ │ │ ├── php │ │ │ └── php.js │ │ │ ├── powershell │ │ │ └── powershell.js │ │ │ ├── python │ │ │ └── python.js │ │ │ └── shell │ │ │ └── shell.js │ │ ├── echarts │ │ └── echarts.common.min.js │ │ ├── jquery │ │ ├── jquery.cookie.js │ │ └── jquery.validate.min.js │ │ └── layer │ │ ├── layer.js │ │ └── theme │ │ └── default │ │ ├── icon-ext.png │ │ ├── icon.png │ │ ├── layer.css │ │ ├── loading-0.gif │ │ ├── loading-1.gif │ │ └── loading-2.gif │ └── templates │ ├── common │ ├── common.exception.ftl │ └── common.macro.ftl │ ├── help.ftl │ ├── index.ftl │ ├── jobcode │ └── jobcode.index.ftl │ ├── jobgroup │ └── jobgroup.index.ftl │ ├── jobinfo │ └── jobinfo.index.ftl │ ├── joblog │ ├── joblog.detail.ftl │ └── joblog.index.ftl │ └── login.ftl └── test └── java └── com └── xxl └── job ├── admin ├── controller │ ├── AbstractSpringMvcTest.java │ └── JobInfoControllerTest.java ├── dao │ ├── XxlJobGroupDaoTest.java │ ├── XxlJobInfoDaoTest.java │ ├── XxlJobLogDaoTest.java │ ├── XxlJobLogGlueDaoTest.java │ └── XxlJobRegistryDaoTest.java └── util │ └── I18nUtilTest.java ├── adminbiz └── AdminBizTest.java └── executor └── ExecutorBizTest.java /.doc/docker/docker: -------------------------------------------------------------------------------- 1 | mvn clean package docker:build -Dmaven.test.skip=true 2 | 3 | mvn clean package docker:build -pl quartz -am -Dmaven.test.skip=true 4 | 5 | mvn clean package -pl quartz -am -Dmaven.test.skip=true 6 | 7 | docker images 8 | 9 | docker rmi 10 | 11 | docker ps -------------------------------------------------------------------------------- /.doc/docker/docker-compose-common.yml: -------------------------------------------------------------------------------- 1 | version: '1.0' 2 | services: 3 | redis: 4 | image: redis 5 | ports: 6 | - "6379:6379" -------------------------------------------------------------------------------- /.doc/docker/docker-compose-kafka.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | zookeeper: 4 | ## 镜像 5 | image: wurstmeister/zookeeper 6 | ## 对外暴露的端口号 7 | ports: 8 | - "2181:2181" 9 | kafka: 10 | ## 镜像 11 | image: wurstmeister/kafka 12 | ## 挂载位置(kafka镜像和宿主机器之间时间保持一直) 13 | volumes: 14 | - /etc/localtime:/etc/localtime 15 | ports: 16 | - "9092:9092" 17 | environment: 18 | ## 修改:宿主机IP 19 | KAFKA_ADVERTISED_HOST_NAME: 10.204.254.43 20 | ## 卡夫卡运行是基于zookeeper的 21 | KAFKA_ZOOKEEPER_CONNECT: 10.204.254.43:2181 22 | kafka-manager: 23 | ## 镜像:开源的web管理kafka集群的界面 24 | image: sheepkiller/kafka-manager 25 | environment: 26 | ## 修改:宿主机IP 27 | ZK_HOSTS: 10.204.254.43 28 | ## 暴露端口 29 | ports: 30 | - "9000:9000" -------------------------------------------------------------------------------- /.doc/docker/docker-compose-rocketmq.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | 3 | services: 4 | rmqnamesrv: 5 | image: foxiswho/rocketmq:server-4.5.2 6 | container_name: rmqnamesrv 7 | ports: 8 | - 9876:9876 9 | volumes: 10 | - ./rmq/logs:/opt/logs 11 | - ./rmq/store:/opt/store 12 | environment: 13 | JAVA_OPT_EXT: "-Duser.home=/opt -Xms128m -Xmx128m -Xmn128m" 14 | networks: 15 | rmq: 16 | aliases: 17 | - rmqnamesrv 18 | rmqbroker: 19 | image: foxiswho/rocketmq:broker-4.5.2 20 | container_name: rmqbroker 21 | ports: 22 | - 10909:10909 23 | - 10911:10911 24 | volumes: 25 | - ./rmq/logs:/opt/logs 26 | - ./rmq/store:/opt/store 27 | - ./rmq/brokerconf/broker.conf:/etc/rocketmq/broker.conf 28 | environment: 29 | JAVA_OPT_EXT: "-Duser.home=/opt -server -Xms128m -Xmx128m -Xmn128m" 30 | command: ["/bin/bash","mqbroker","-c","/etc/rocketmq/broker.conf","-n","rmqnamesrv:9876","autoCreateTopicEnable=true"] 31 | depends_on: 32 | - rmqnamesrv 33 | networks: 34 | rmq: 35 | aliases: 36 | - rmqbroker 37 | 38 | rmqconsole: 39 | image: styletang/rocketmq-console-ng 40 | container_name: rmqconsole 41 | ports: 42 | - 8180:8080 43 | environment: 44 | JAVA_OPTS: "-Drocketmq.namesrv.addr=rmqnamesrv:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" 45 | depends_on: 46 | - rmqnamesrv 47 | networks: 48 | rmq: 49 | aliases: 50 | - rmqconsole 51 | 52 | networks: 53 | rmq: 54 | name: rmq 55 | driver: bridge -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SpringBoot 2 | 利用SpringBoot整合ActiveMq、Quartz、Solr、Mybatis 3 | 4 | #Quartz 5 | 6 | Quartz整合H2数据库实现动态管理定时任务 7 | 8 | #Mybatis 9 | 10 | 利用Aop实现数据源的动态切换 11 | -------------------------------------------------------------------------------- /activemq/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.ocean 8 | springboot 9 | 0.0.1-SNAPSHOT 10 | 11 | 12 | activemq 13 | 0.0.1-SNAPSHOT 14 | jar 15 | 16 | 17 | 18 | 19 | org.springframework 20 | spring-jms 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-activemq 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/ActivemqApplication.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.jms.annotation.EnableJms; 6 | 7 | @SpringBootApplication 8 | @EnableJms 9 | public class ActivemqApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ActivemqApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/config/ActiveMqName.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq.config; 2 | 3 | public class ActiveMqName { 4 | public static final String QUEUE_ONE = "queue1"; 5 | 6 | public static final String QUEUE_TWO = "queue2"; 7 | 8 | public static final String TOPIC_ONE = "topic1"; 9 | 10 | public static final String TOPIC_TWO = "topic2"; 11 | } 12 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/config/JmsConfig.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.Primary; 6 | import org.springframework.jms.annotation.EnableJms; 7 | import org.springframework.jms.config.DefaultJmsListenerContainerFactory; 8 | import org.springframework.jms.config.JmsListenerContainerFactory; 9 | import org.springframework.jms.core.JmsTemplate; 10 | 11 | import javax.jms.ConnectionFactory; 12 | 13 | @Configuration 14 | @EnableJms 15 | public class JmsConfig { 16 | 17 | /** 18 | * queue模式的ListenerContainer 19 | * 20 | * @param activeMQConnectionFactory 21 | * @return 22 | */ 23 | @Bean 24 | public JmsListenerContainerFactory jmsListenerContainerQueue(ConnectionFactory activeMQConnectionFactory) { 25 | DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory(); 26 | bean.setConnectionFactory(activeMQConnectionFactory); 27 | return bean; 28 | } 29 | 30 | /** 31 | * topic模式的ListenerContainer 32 | * 33 | * @param activeMQConnectionFactory 34 | * @return 35 | */ 36 | @Bean 37 | public JmsListenerContainerFactory jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) { 38 | DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory(); 39 | bean.setPubSubDomain(true); 40 | bean.setConnectionFactory(activeMQConnectionFactory); 41 | return bean; 42 | } 43 | 44 | @Bean 45 | @Primary 46 | public JmsTemplate jmsQueueTemplate(ConnectionFactory connectionFactory) { 47 | JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); 48 | jmsTemplate.setPubSubDomain(false); 49 | return jmsTemplate; 50 | } 51 | 52 | @Bean 53 | public JmsTemplate jmsTopicTemplate(ConnectionFactory connectionFactory) { 54 | JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); 55 | jmsTemplate.setPubSubDomain(true); 56 | return jmsTemplate; 57 | } 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/consumer/queue/QueueConsumer.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq.consumer.queue; 2 | 3 | import com.ocean.activemq.config.ActiveMqName; 4 | import org.springframework.jms.annotation.JmsListener; 5 | import org.springframework.stereotype.Service; 6 | 7 | @Service 8 | public class QueueConsumer { 9 | 10 | @JmsListener(destination = ActiveMqName.QUEUE_ONE, containerFactory = "jmsListenerContainerQueue") 11 | public void getQueue1(String info) { 12 | System.out.println("listener1成功监听queue1消息队列,传来的值为:" + info); 13 | } 14 | 15 | @JmsListener(destination = ActiveMqName.QUEUE_ONE, containerFactory = "jmsListenerContainerQueue") 16 | public void getQueue2(String info) { 17 | System.out.println("listener2成功监听queue1消息队列,传来的值为:" + info); 18 | } 19 | 20 | @JmsListener(destination = ActiveMqName.QUEUE_TWO, containerFactory = "jmsListenerContainerQueue") 21 | public void getQueue3(String info) { 22 | System.out.println("listener3成功监听queue1消息队列,传来的值为:" + info); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/consumer/queue/QueueConsumer2.java: -------------------------------------------------------------------------------- 1 | //package com.ocean.activemq.consumer.queue; 2 | // 3 | //import org.springframework.stereotype.Service; 4 | // 5 | //import javax.jms.JMSException; 6 | //import javax.jms.Message; 7 | //import javax.jms.MessageListener; 8 | //import javax.jms.TextMessage; 9 | // 10 | //@Service 11 | //public class QueueConsumer2 implements MessageListener { 12 | // public void onMessage(Message message) { 13 | // TextMessage textMessage = (TextMessage) message; 14 | // try { 15 | // System.out 16 | // .println("QueueConsumer2:" + textMessage.getText()); 17 | // } catch (JMSException e) { 18 | // e.printStackTrace(); 19 | // } 20 | // } 21 | //} 22 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/consumer/topic/TopicConsumer.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq.consumer.topic; 2 | 3 | import org.springframework.jms.annotation.JmsListener; 4 | import org.springframework.stereotype.Service; 5 | 6 | @Service 7 | public class TopicConsumer { 8 | 9 | @JmsListener(destination = "topic1", containerFactory = "jmsListenerContainerTopic") 10 | public void getTopic1(String info) { 11 | System.out.println("topicListener1成功监听topic1消息队列,传来的值为:" + info); 12 | } 13 | 14 | @JmsListener(destination = "topic1", containerFactory = "jmsListenerContainerTopic") 15 | public void getTopic2(String info) { 16 | System.out.println("topicListener2成功监听topic1消息队列,传来的值为:" + info); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/consumer/topic/TopicConsumer2.java: -------------------------------------------------------------------------------- 1 | //package com.ocean.activemq.consumer.topic; 2 | // 3 | //import org.springframework.stereotype.Service; 4 | // 5 | //import javax.jms.JMSException; 6 | //import javax.jms.Message; 7 | //import javax.jms.MessageListener; 8 | //import javax.jms.TextMessage; 9 | // 10 | //@Service 11 | //public class TopicConsumer2 implements MessageListener { 12 | // 13 | // public void onMessage(Message message) { 14 | // TextMessage textMessage = (TextMessage) message; 15 | // try { 16 | // System.out 17 | // .println("TopicConsumer2:" + textMessage.getText()); 18 | // } catch (JMSException e) { 19 | // e.printStackTrace(); 20 | // } 21 | // } 22 | // 23 | //} 24 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/controller/SendControlller.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq.controller; 2 | 3 | import com.ocean.activemq.config.ActiveMqName; 4 | import com.ocean.activemq.producer.Sender; 5 | import com.ocean.activemq.producer.queue.QueueSender; 6 | import com.ocean.activemq.producer.topic.TopicSender; 7 | import org.apache.activemq.command.ActiveMQQueue; 8 | import org.apache.activemq.command.ActiveMQTopic; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.ResponseBody; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | import javax.jms.Destination; 16 | 17 | @RestController 18 | @RequestMapping 19 | @ResponseBody 20 | public class SendControlller { 21 | 22 | @Autowired 23 | private Sender sender; 24 | 25 | @Autowired 26 | private QueueSender queueSender; 27 | 28 | @Autowired 29 | private TopicSender topicSender; 30 | 31 | @GetMapping(value = "/add/queue") 32 | public void addQueue() { 33 | Destination destination = new ActiveMQQueue(ActiveMqName.QUEUE_ONE); 34 | sender.sendTemple(destination, "success"); 35 | } 36 | 37 | @GetMapping(value = "/add/topic") 38 | public void addTopic() { 39 | Destination destination = new ActiveMQTopic(ActiveMqName.TOPIC_ONE); 40 | sender.sendTemple(destination, "success"); 41 | } 42 | 43 | @GetMapping(value = "/creat/queue") 44 | public void creatQueue() { 45 | queueSender.send(ActiveMqName.QUEUE_ONE, "success"); 46 | } 47 | 48 | @GetMapping(value = "/creat/topic") 49 | public void creatTopic() { 50 | topicSender.send(ActiveMqName.TOPIC_ONE, "success"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/producer/Sender.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq.producer; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.jms.core.JmsMessagingTemplate; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.jms.Destination; 8 | 9 | @Service 10 | public class Sender { 11 | 12 | @Autowired 13 | private JmsMessagingTemplate jmsMessagingTemplate; 14 | 15 | public void sendTemple(Destination destination, final String message) { 16 | jmsMessagingTemplate.convertAndSend(destination, message); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/producer/queue/QueueSender.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq.producer.queue; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.beans.factory.annotation.Qualifier; 5 | import org.springframework.jms.core.JmsTemplate; 6 | import org.springframework.jms.core.MessageCreator; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.jms.JMSException; 10 | import javax.jms.Message; 11 | import javax.jms.Session; 12 | 13 | @Service 14 | public class QueueSender { 15 | 16 | @Autowired 17 | @Qualifier("jmsQueueTemplate") 18 | private JmsTemplate jmsTemplate; 19 | 20 | public void send(String queueName, final String message) { 21 | jmsTemplate.send(queueName, new MessageCreator() { 22 | public Message createMessage(Session session) throws JMSException { 23 | return session.createTextMessage(message); 24 | } 25 | }); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /activemq/src/main/java/com/ocean/activemq/producer/topic/TopicSender.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq.producer.topic; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.beans.factory.annotation.Qualifier; 5 | import org.springframework.jms.core.JmsTemplate; 6 | import org.springframework.jms.core.MessageCreator; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.jms.JMSException; 10 | import javax.jms.Message; 11 | import javax.jms.Session; 12 | 13 | @Service 14 | public class TopicSender { 15 | @Autowired 16 | @Qualifier("jmsTopicTemplate") 17 | private JmsTemplate jmsTemplate; 18 | 19 | public void send(String topicName, final String message) { 20 | jmsTemplate.send(topicName, new MessageCreator() { 21 | 22 | public Message createMessage(Session session) throws JMSException { 23 | return session.createTextMessage(message); 24 | } 25 | }); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /activemq/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #activemq 2 | #spring.activemq.brokerUrl=tcp://127.0.0.1:61616 3 | #spring.activemq.user=admin 4 | #spring.activemq.password=admin 5 | server: 6 | port: 8082 7 | spring: 8 | jms: 9 | pub-sub-domain: true 10 | activemq: 11 | broker-url: tcp://127.0.0.1:61616 12 | user: admin 13 | password: admin 14 | in-memory: false 15 | pool: 16 | enabled: false 17 | packages: 18 | trust-all: true 19 | 20 | -------------------------------------------------------------------------------- /activemq/src/test/java/com/ocean/activemq/ActivemqApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ocean.activemq; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ActivemqApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /case/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot 7 | com.ocean 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | case 13 | 0.0.1-SNAPSHOT 14 | 15 | 16 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/CaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.ocean; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CaseApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CaseApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/strategy/MallPackageOrderStrategy.java: -------------------------------------------------------------------------------- 1 | package com.ocean.strategy; 2 | 3 | import com.ocean.template.PackageOrder; 4 | import org.springframework.stereotype.Service; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 巢鲜厨包裹订单 10 | * @author 郭大海 11 | */ 12 | @Service("mallPackageOrderStrategy") 13 | public class MallPackageOrderStrategy implements PackageOrderStrategy { 14 | 15 | @Override 16 | public void process(List packageOrderList) { 17 | //1、检验包裹 18 | checkPackageOrder(packageOrderList); 19 | //2、匹配包裹订单相关数据 20 | matchPackageOrder(packageOrderList); 21 | //3、生成相应履约单 22 | generatePerformOrder(packageOrderList); 23 | } 24 | 25 | private void checkPackageOrder(List packageOrderList) { 26 | System.out.println("检验包裹"); 27 | } 28 | 29 | private void matchPackageOrder(List packageOrderList) { 30 | System.out.println("巢鲜厨电商平台包裹订单,匹配包裹订单相关数据"); 31 | } 32 | 33 | private void generatePerformOrder(List packageOrderList) { 34 | System.out.println("巢鲜厨电商平台包裹订单,生成相应履约单"); 35 | } 36 | } 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/strategy/PackageOrderStrategy.java: -------------------------------------------------------------------------------- 1 | package com.ocean.strategy; 2 | 3 | import com.ocean.template.PackageOrder; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 包裹订单处理策略接口 9 | * 10 | * @author 郭大海 11 | */ 12 | public interface PackageOrderStrategy { 13 | 14 | /** 15 | * 处理包裹订单 16 | * 17 | * @param packageOrderList 包裹订单list 18 | */ 19 | void process(List packageOrderList); 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/strategy/PackageOrderStrategyContext.java: -------------------------------------------------------------------------------- 1 | package com.ocean.strategy; 2 | 3 | import com.ocean.template.PackageOrder; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | /** 12 | * 订单包裹处理策略管理器 13 | * 14 | * @author 郭大海 15 | */ 16 | @SuppressWarnings("all") 17 | @Component 18 | public class PackageOrderStrategyContext { 19 | /** 20 | * 存储所有实现PackageOrderStrategy接口的Bean 21 | */ 22 | private final Map strategyMap = new ConcurrentHashMap<>(); 23 | 24 | /** 25 | * 注入所有实现了Strategy接口的Bean 26 | */ 27 | @Autowired 28 | public PackageOrderStrategyContext(Map strategyMap) { 29 | this.strategyMap.clear(); 30 | strategyMap.forEach((k, v) -> this.strategyMap.put(k, v)); 31 | } 32 | 33 | /** 34 | * 处理订单包裹流程 35 | */ 36 | public void process(String strategy, List packageOrderList) { 37 | strategyMap.get(strategy).process(packageOrderList); 38 | } 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/strategy/PartnerPackageOrderStrategy.java: -------------------------------------------------------------------------------- 1 | package com.ocean.strategy; 2 | 3 | import com.ocean.template.PackageOrder; 4 | import org.springframework.stereotype.Service; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 合作商户包裹订单 10 | * 11 | * @author 郭大海 12 | */ 13 | @Service("partnerPackageOrderStrategy") 14 | public class PartnerPackageOrderStrategy implements PackageOrderStrategy { 15 | 16 | @Override 17 | public void process(List packageOrderList) { 18 | //1、检验包裹 19 | checkPackageOrder(packageOrderList); 20 | //2、匹配包裹订单相关数据 21 | matchPackageOrder(packageOrderList); 22 | //3、生成相应履约单 23 | generatePerformOrder(packageOrderList); 24 | //4、发送邮件给合作商户 25 | sendEmail(packageOrderList); 26 | } 27 | 28 | private void checkPackageOrder(List packageOrderList) { 29 | System.out.println("检验包裹"); 30 | } 31 | 32 | private void matchPackageOrder(List packageOrderList) { 33 | System.out.println("巢鲜厨电商平台包裹订单,匹配包裹订单相关数据"); 34 | } 35 | 36 | private void generatePerformOrder(List packageOrderList) { 37 | System.out.println("巢鲜厨电商平台包裹订单,生成相应履约单"); 38 | } 39 | 40 | private void sendEmail(List packageOrderList) { 41 | System.out.println("发送邮件通知合作商户"); 42 | } 43 | } 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/template/AbstractPackageOrderService.java: -------------------------------------------------------------------------------- 1 | package com.ocean.template; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 包裹订单合单处理 7 | * 8 | * @author 郭大海 9 | */ 10 | @SuppressWarnings("all") 11 | public abstract class AbstractPackageOrderService implements PackageOrderService { 12 | /** 13 | * 处理包裹订单流程 14 | * @param packageOrderList 包裹订单list 15 | */ 16 | @Override 17 | public void process(List packageOrderList) { 18 | checkPackageOrder(packageOrderList); 19 | matchPackageOrder(packageOrderList); 20 | generatePerformOrder(packageOrderList); 21 | } 22 | 23 | /** 24 | * 检验包裹订单 25 | * @param packageOrderList 包裹订单list 26 | */ 27 | void checkPackageOrder(List packageOrderList) { 28 | System.out.println("同样的检验"); 29 | } 30 | 31 | /** 32 | * 匹配关联信息 33 | * @param packageOrderList 包裹订单list 34 | */ 35 | abstract void matchPackageOrder(List packageOrderList); 36 | /** 37 | * 生成相关履约单 38 | * @param packageOrderList 包裹订单list 39 | */ 40 | abstract void generatePerformOrder(List packageOrderList); 41 | } 42 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/template/MallPackageOrderService.java: -------------------------------------------------------------------------------- 1 | package com.ocean.template; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 巢鲜厨电商平台包裹订单 9 | * 10 | * @author 郭大海 11 | */ 12 | @Service("mallPackageOrderService") 13 | public class MallPackageOrderService extends AbstractPackageOrderService { 14 | 15 | @Override 16 | void matchPackageOrder(List packageOrderList) { 17 | System.out.println("巢鲜厨电商平台包裹订单,匹配包裹订单相关数据"); 18 | } 19 | 20 | @Override 21 | void generatePerformOrder(List packageOrderList) { 22 | System.out.println("巢鲜厨电商平台包裹订单,生成相应履约单"); 23 | } 24 | } 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/template/PackageOrder.java: -------------------------------------------------------------------------------- 1 | package com.ocean.template; 2 | 3 | public class PackageOrder { 4 | } 5 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/template/PackageOrderService.java: -------------------------------------------------------------------------------- 1 | package com.ocean.template; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 包裹订单处理 7 | * 8 | * @author 郭大海 9 | */ 10 | public interface PackageOrderService { 11 | 12 | /** 13 | * 处理包裹订单 14 | * 15 | * @param packageOrderList 包裹订单list 16 | */ 17 | void process(List packageOrderList); 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /case/src/main/java/com/ocean/template/PartnerPackageOrderService.java: -------------------------------------------------------------------------------- 1 | package com.ocean.template; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 合作商户包裹订单 9 | * 10 | * @author 郭大海 11 | */ 12 | @Service("partnerPackageOrderService") 13 | public class PartnerPackageOrderService extends AbstractPackageOrderService { 14 | 15 | @Override 16 | void matchPackageOrder(List packageOrderList) { 17 | System.out.println("合作商户包裹订单,匹配包裹订单相关数据"); 18 | } 19 | 20 | @Override 21 | void generatePerformOrder(List packageOrderList) { 22 | System.out.println("合作商户包裹订单,生成相应履约单"); 23 | } 24 | } 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /case/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8000 2 | -------------------------------------------------------------------------------- /case/src/test/java/com/ocean/strategy/PackageOrderStrategyContextTest.java: -------------------------------------------------------------------------------- 1 | package com.ocean.strategy; 2 | 3 | import com.ocean.CaseApplication; 4 | import com.ocean.template.PackageOrder; 5 | import org.assertj.core.util.Lists; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | import java.util.List; 13 | 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest(classes = CaseApplication.class) 16 | public class PackageOrderStrategyContextTest { 17 | 18 | @Autowired 19 | private PackageOrderStrategyContext packageOrderStrategyConText; 20 | 21 | 22 | @Test 23 | public void test() { 24 | List packageOrderList = Lists.newArrayList(); 25 | String strategy = "mallPackageOrderStrategy"; 26 | process(strategy, packageOrderList); 27 | System.out.println("===================分割线==================="); 28 | strategy = "partnerPackageOrderStrategy"; 29 | process(strategy, packageOrderList); 30 | } 31 | 32 | /** 33 | * 订单包裹处理 34 | */ 35 | private void process(String strategy, List packageOrderList) { 36 | packageOrderStrategyConText.process(strategy, packageOrderList); 37 | } 38 | 39 | 40 | 41 | 42 | } -------------------------------------------------------------------------------- /case/src/test/java/com/ocean/template/PackageOrderServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.ocean.template; 2 | 3 | import com.ocean.CaseApplication; 4 | import org.assertj.core.util.Lists; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | import javax.annotation.Resource; 11 | 12 | @RunWith(SpringRunner.class) 13 | @SpringBootTest(classes = CaseApplication.class) 14 | public class PackageOrderServiceTest { 15 | 16 | @Resource 17 | private PackageOrderService mallPackageOrderService; 18 | 19 | @Resource 20 | private PackageOrderService partnerPackageOrderService; 21 | 22 | /** 23 | * 巢鲜厨订单包裹处理 24 | */ 25 | @Test 26 | public void mallPackageOrder() { 27 | mallPackageOrderService.process(Lists.newArrayList()); 28 | } 29 | 30 | /** 31 | * 合作商户订单包裹处理 32 | */ 33 | @Test 34 | public void partnerPackageOrder() { 35 | partnerPackageOrderService.process(Lists.newArrayList()); 36 | } 37 | } 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.ocean 8 | springboot 9 | 0.0.1-SNAPSHOT 10 | 11 | 12 | common 13 | 0.0.1-SNAPSHOT 14 | jar 15 | 16 | common 17 | 公共模块 18 | 19 | 20 | -------------------------------------------------------------------------------- /common/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java:8 2 | VOLUME /tmp 3 | ADD quartz-0.0.1-SNAPSHOT.jar app.jar 4 | RUN bash -c 'touch /app.jar' 5 | EXPOSE 9000 6 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] -------------------------------------------------------------------------------- /common/src/main/java/com/ocean/common/BaseResult.java: -------------------------------------------------------------------------------- 1 | package com.ocean.common; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author guodahai 7 | * @version 2018/4/17 上午10:23 8 | */ 9 | public class BaseResult implements Serializable { 10 | 11 | private static final long serialVersionUID = 3962215109252373857L; 12 | 13 | private boolean success = true; 14 | private Integer errorCode = 200; 15 | private String errorMessage; 16 | 17 | public BaseResult() { 18 | 19 | } 20 | 21 | public boolean isSuccess() { 22 | return this.success; 23 | } 24 | 25 | public void setSuccess(boolean success) { 26 | this.success = success; 27 | } 28 | 29 | public Integer getErrorCode() { 30 | return this.errorCode; 31 | } 32 | 33 | public void setErrorCode(Integer errorCode) { 34 | this.errorCode = errorCode; 35 | } 36 | 37 | public String getErrorMessage() { 38 | return this.errorMessage; 39 | } 40 | 41 | public void setErrorMessage(String errorMessage) { 42 | this.errorMessage = errorMessage; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/com/ocean/common/ControllerExecutor.java: -------------------------------------------------------------------------------- 1 | package com.ocean.common; 2 | 3 | /** 4 | * 控制层执行抽象类 5 | * 6 | * @author guodahai 7 | * @version 2018/4/17 上午11:08 8 | */ 9 | public abstract class ControllerExecutor { 10 | 11 | private T[] param; 12 | 13 | public ControllerExecutor(T... param) { 14 | this.param = param; 15 | } 16 | 17 | public abstract void checkParam(T... param) throws ServiceException; 18 | 19 | public abstract R executeService(T... param) throws ServiceException; 20 | 21 | public ResponseResult execute(T... param) throws ServiceException { 22 | ResponseResult result = new ResponseResult<>(); 23 | try { 24 | R r = executeService(param); 25 | if (r instanceof Boolean) { 26 | Boolean b = (Boolean) r; 27 | result.setSuccess(b); 28 | } else { 29 | result.setData(r); 30 | } 31 | } catch (ServiceException e) { 32 | result.setSuccess(false); 33 | result.setErrorCode(e.getErrorCode().getCode()); 34 | result.setErrorMessage(e.getErrorMsg()); 35 | } 36 | return result; 37 | } 38 | 39 | public T[] getParam() { 40 | return param; 41 | } 42 | 43 | public void setParam(T[] param) { 44 | this.param = param; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /common/src/main/java/com/ocean/common/ErrorCodeEnum.java: -------------------------------------------------------------------------------- 1 | package com.ocean.common; 2 | 3 | /** 4 | * 错误码定义 5 | * 6 | * @author guodahai 7 | * @version 2018/4/17 上午10:52 8 | */ 9 | public enum ErrorCodeEnum { 10 | 11 | P01(417, "参数传入不符合规则"), 12 | Q01(418, "数据库查询失败"), 13 | U01(418, "数据库更新失败"), 14 | I01(418, "数据库插入失败"), 15 | D01(418, "数据库删除失败"), 16 | P99(500, "系统异常"), 17 | QUA01(419, "quartz异常"); 18 | 19 | private Integer code; 20 | private String desc; 21 | 22 | ErrorCodeEnum(Integer code, String desc) { 23 | this.code = code; 24 | this.desc = desc; 25 | } 26 | 27 | public String getDesc() { 28 | return desc; 29 | } 30 | 31 | public void setDesc(String desc) { 32 | this.desc = desc; 33 | } 34 | 35 | public Integer getCode() { 36 | return code; 37 | } 38 | 39 | public void setCode(Integer code) { 40 | this.code = code; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common/src/main/java/com/ocean/common/ResponseResult.java: -------------------------------------------------------------------------------- 1 | package com.ocean.common; 2 | 3 | /** 4 | * 数据返回Result 5 | * 6 | * @author guodahai 7 | * @version 2018/4/17 上午11:19 8 | */ 9 | public class ResponseResult extends BaseResult { 10 | private T data; 11 | 12 | public T getData() { 13 | return data; 14 | } 15 | 16 | public void setData(T data) { 17 | this.data = data; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/ocean/common/ServiceException.java: -------------------------------------------------------------------------------- 1 | package com.ocean.common; 2 | 3 | /** 4 | * 自定义异常 5 | * 6 | * @author guodahai 7 | * @version 2018/4/17 上午10:43 8 | */ 9 | public class ServiceException extends RuntimeException { 10 | 11 | private static final long serialVersionUID = -2396422934408894887L; 12 | 13 | private ErrorCodeEnum errorCode; 14 | 15 | private String errorMsg; 16 | 17 | /** 18 | * 带错误码的构造函数 19 | * 20 | * @param errorCode 21 | */ 22 | public ServiceException(ErrorCodeEnum errorCode, String errorMsg) { 23 | this.errorCode = errorCode; 24 | this.setErrorMsg(errorMsg); 25 | } 26 | 27 | public ServiceException(String message) { 28 | super(message); 29 | } 30 | 31 | /** 32 | * 带错误码的构造函数 33 | * 34 | * @param errorCode 35 | */ 36 | public ServiceException(ErrorCodeEnum errorCode) { 37 | super(errorCode.getDesc()); 38 | this.errorCode = errorCode; 39 | } 40 | 41 | /** 42 | * 获取错误码 43 | * 44 | * @return 45 | */ 46 | public ErrorCodeEnum getErrorEnum() { 47 | return errorCode; 48 | } 49 | 50 | public String getErrorMsg() { 51 | return errorMsg; 52 | } 53 | 54 | public void setErrorMsg(String errorMsg) { 55 | this.errorMsg = errorMsg; 56 | } 57 | 58 | public ErrorCodeEnum getErrorCode() { 59 | return errorCode; 60 | } 61 | 62 | public void setErrorCode(ErrorCodeEnum errorCode) { 63 | this.errorCode = errorCode; 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /hotchpotch/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | hotchpotch 7 | 1.0-SNAPSHOT 8 | jar 9 | 10 | 11 | com.ocean 12 | springboot 13 | 0.0.1-SNAPSHOT 14 | 15 | 16 | 17 | 18 | com.ocean 19 | common 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-data-redis 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | com.google.collections 33 | google-collections 34 | 35 | 36 | com.alibaba 37 | druid 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/HotchpotchApplication.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | 7 | /** 8 | * 启动类 9 | * 10 | * @author guodahai 11 | */ 12 | @SpringBootApplication 13 | @EnableAsync 14 | public class HotchpotchApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(HotchpotchApplication.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/aop/AopTestController.java: -------------------------------------------------------------------------------- 1 | package com.aop; 2 | 3 | 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | /** 8 | * 9 | * @author guodahai 10 | * @date 2016/11/19 11 | */ 12 | @RestController 13 | @RequestMapping("/aop") 14 | public class AopTestController { 15 | 16 | @RequestMapping("/testBeforeService.do") 17 | public String testBeforeService(String key, String value) { 18 | 19 | return "key=" + key + " value=" + value; 20 | } 21 | 22 | @RequestMapping("/testAfterReturning.do") 23 | public String testAfterReturning(String key) { 24 | 25 | return "key=: " + key; 26 | } 27 | 28 | @RequestMapping("/testAfterReturning01.do") 29 | public Integer testAfterReturning01(Integer key) { 30 | 31 | return key; 32 | } 33 | 34 | @RequestMapping("/testAfterThrowing.do") 35 | public String testAfterThrowing(String key) { 36 | 37 | throw new NullPointerException(); 38 | } 39 | 40 | @RequestMapping("/testAfter.do") 41 | public String testAfter(String key) { 42 | 43 | throw new NullPointerException(); 44 | } 45 | 46 | @RequestMapping("/testAfter02.do") 47 | public String testAfter02(String key) { 48 | 49 | return key; 50 | } 51 | 52 | @RequestMapping("/testAroundService.do") 53 | public String testAroundService(String key) { 54 | 55 | return "环绕通知:" + key; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/thread/config/TaskThreadPoolConfig.java: -------------------------------------------------------------------------------- 1 | package com.thread.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | /** 7 | * 连接池配置类 8 | * 9 | * @author guodahai 10 | * @version 2018/4/11 下午2:05 11 | */ 12 | @Configuration 13 | public class TaskThreadPoolConfig { 14 | 15 | @Value("${task.core.pool.size}") 16 | private int corePoolSize; 17 | 18 | @Value("${task.max.pool.size}") 19 | private int maxPoolSize; 20 | 21 | @Value("${task.queue.capacity}") 22 | private int keepAliveSeconds; 23 | 24 | @Value("${task.keep.alive.seconds}") 25 | private int queueCapacity; 26 | 27 | public int getCorePoolSize() { 28 | return corePoolSize; 29 | } 30 | 31 | public void setCorePoolSize(int corePoolSize) { 32 | this.corePoolSize = corePoolSize; 33 | } 34 | 35 | public int getMaxPoolSize() { 36 | return maxPoolSize; 37 | } 38 | 39 | public void setMaxPoolSize(int maxPoolSize) { 40 | this.maxPoolSize = maxPoolSize; 41 | } 42 | 43 | public int getKeepAliveSeconds() { 44 | return keepAliveSeconds; 45 | } 46 | 47 | public void setKeepAliveSeconds(int keepAliveSeconds) { 48 | this.keepAliveSeconds = keepAliveSeconds; 49 | } 50 | 51 | public int getQueueCapacity() { 52 | return queueCapacity; 53 | } 54 | 55 | public void setQueueCapacity(int queueCapacity) { 56 | this.queueCapacity = queueCapacity; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/thread/demo/CurrentThreadDemo.java: -------------------------------------------------------------------------------- 1 | package com.thread.demo; 2 | 3 | public class CurrentThreadDemo { 4 | public static void main(String[] args) throws InterruptedException { 5 | new Thread("custom thread"){ 6 | @Override 7 | public void run() { 8 | System.out.println("当前线程:"+Thread.currentThread().getName()); 9 | } 10 | }.start(); 11 | Thread.sleep(100); 12 | System.out.println("当前线程:"+Thread.currentThread().getName()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/thread/demo/MultiRunDemo.java: -------------------------------------------------------------------------------- 1 | package com.thread.demo; 2 | 3 | public class MultiRunDemo { 4 | public static void main(String[] args) { 5 | //传入了Runnable实现类 6 | new Thread(new MyRunnable()){ 7 | @Override 8 | public void run() { 9 | System.out.println("我是直接覆写Thread类run方法的代码..."); 10 | } 11 | }.start(); 12 | } 13 | static class MyRunnable implements Runnable{ 14 | @Override 15 | public void run() { 16 | System.out.println("我是实现Runnable接口的对象中的run方法的代码..."); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/thread/demo/ThreadDemo.java: -------------------------------------------------------------------------------- 1 | package com.thread.demo; 2 | 3 | 4 | /** 5 | * 演示多个线程可以并发执行的案例 6 | */ 7 | public class ThreadDemo { 8 | public static void main(String[] args) { 9 | //创建一个线程对象,覆盖其run方法,传入参数为线程的名字 10 | Thread t1 = new Thread() { 11 | @Override 12 | public void run() { 13 | for (int i = 1; i <= 1000; i++) { 14 | System.out.println("自定义线程循环:" + i + "次"); 15 | } 16 | } 17 | }; 18 | //调用start方法启动线程 19 | t1.start(); 20 | for (int i = 1; i <= 1000; i++) { 21 | System.out.println("主线程循环:" + i + "次"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/thread/demo/ThreadNumDemo.java: -------------------------------------------------------------------------------- 1 | package com.thread.demo; 2 | 3 | import java.lang.management.ManagementFactory; 4 | import java.lang.management.ThreadInfo; 5 | import java.lang.management.ThreadMXBean; 6 | 7 | public class ThreadNumDemo { 8 | public static void main(String[] args) { 9 | ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); 10 | ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); 11 | for (ThreadInfo threadInfo : threadInfos) { 12 | System.out.println(threadInfo.getThreadId() + "-" + threadInfo.getThreadName()); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/thread/task/AsyncTask.java: -------------------------------------------------------------------------------- 1 | package com.thread.task; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.scheduling.annotation.Async; 6 | import org.springframework.stereotype.Component; 7 | 8 | 9 | /** 10 | * @author guodahai 11 | * @version 2018/4/11 下午2:24 12 | */ 13 | @Component 14 | public class AsyncTask { 15 | 16 | private final Logger logger = LoggerFactory.getLogger(AsyncTask.class); 17 | 18 | @Async("myTaskAsyncPool") 19 | public void task(int i) { 20 | logger.info("Task:{},thread", i); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/thread/task/MyCallable.java: -------------------------------------------------------------------------------- 1 | package com.thread.task; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | 7 | import java.util.concurrent.Callable; 8 | 9 | /** 10 | * @author guodahai 11 | * @version 2018/4/11 下午4:18 12 | */ 13 | public class MyCallable implements Callable { 14 | 15 | private final Logger logger = LoggerFactory.getLogger(MyCallable.class); 16 | 17 | @Autowired 18 | private Integer i; 19 | 20 | public MyCallable(Integer i) { 21 | this.i = i; 22 | } 23 | 24 | @Override 25 | public Boolean call() throws Exception { 26 | logger.info("Task:{},thread", i); 27 | return true; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/thread/task/MyRunnable.java: -------------------------------------------------------------------------------- 1 | package com.thread.task; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * @author guodahai 8 | * @version 2018/4/11 下午4:12 9 | */ 10 | public class MyRunnable implements Runnable { 11 | 12 | private final Logger logger = LoggerFactory.getLogger(MyRunnable.class); 13 | 14 | private int i; 15 | 16 | public MyRunnable(int i) { 17 | this.i = i; 18 | } 19 | 20 | @Override 21 | public void run() { 22 | logger.info("Task:{},thread", i); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /hotchpotch/src/main/java/com/thread/task/MyThread.java: -------------------------------------------------------------------------------- 1 | package com.thread.task; 2 | 3 | 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | /** 8 | * @author guodahai 9 | * @version 2018/4/11 下午3:53 10 | */ 11 | public class MyThread extends Thread { 12 | 13 | private final Logger logger = LoggerFactory.getLogger(MyThread.class); 14 | 15 | private int i; 16 | 17 | public MyThread(int i) { 18 | this.i = i; 19 | } 20 | 21 | @Override 22 | public void run() { 23 | logger.info("Task:{},thread", i); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /hotchpotch/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #核心线程数 2 | task.core.pool.size=5 3 | #最大线程数 4 | task.max.pool.size=50 5 | #队列最大长度 6 | task.queue.capacity=1000 7 | #线程池维护线程所允许的空闲时间,默认为60s 8 | task.keep.alive.seconds=60 9 | #redis 10 | # Redis数据库索引(默认为0) 11 | spring.redis.database=0 12 | # Redis服务器地址 13 | spring.redis.host=106.14.143.39 14 | # Redis服务器连接端口 15 | spring.redis.port=6379 16 | # Redis服务器连接密码(默认为空) 17 | spring.redis.password=root 18 | # 连接池最大连接数(使用负值表示没有限制) 19 | spring.redis.pool.max-active=8 20 | # 连接池最大阻塞等待时间(使用负值表示没有限制) 21 | spring.redis.pool.max-wait=-1 22 | # 连接池中的最大空闲连接 23 | spring.redis.pool.max-idle=8 24 | # 连接池中的最小空闲连接 25 | spring.redis.pool.min-idle=0 26 | # 连接超时时间(毫秒) 27 | spring.redis.timeout=1000 28 | #spring.session.store-type=redis -------------------------------------------------------------------------------- /hotchpotch/src/test/java/com/redis/client/RedisStringTest.java: -------------------------------------------------------------------------------- 1 | package com.redis.client; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.data.redis.core.RedisTemplate; 8 | import org.springframework.data.redis.core.StringRedisTemplate; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | /** 12 | * redis测试 13 | * 14 | * @author guodahai 15 | * @version 2019/3/29 16:16 16 | */ 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest 19 | public class RedisStringTest { 20 | /** 21 | * RedisTemplate和StringRedisTemplate的区别: 22 | * 1. 两者的关系是StringRedisTemplate继承RedisTemplate。 23 | * 2. 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。 24 | * 3. SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。 25 | * StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。 26 | * RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。 27 | */ 28 | @Autowired 29 | private RedisTemplate redisTemplate; 30 | @Autowired 31 | private StringRedisTemplate stringRedisTemplate; 32 | 33 | /** 34 | * SET name "gdh" result: "name":"gdh" 35 | */ 36 | @Test 37 | public void set() { 38 | redisTemplate.opsForValue().set("name", "gdh"); 39 | } 40 | 41 | /** 42 | * SET name "gdh" result: name:"gdh" 43 | */ 44 | @Test 45 | public void set2() { 46 | stringRedisTemplate.opsForValue().set("name", "gdh"); 47 | } 48 | 49 | /** 50 | * GET name 获取指定 key 的值; 51 | */ 52 | @Test 53 | public void get() { 54 | Object value = redisTemplate.opsForValue().get("name"); 55 | System.out.println(value); 56 | } 57 | 58 | /** 59 | * GETRANGE key start end 返回 key 中字符串值的子字符; 60 | */ 61 | @Test 62 | public void getRange() { 63 | Object value = redisTemplate.opsForValue().get("name", 0, 1); 64 | System.out.println(value); 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /mybatis/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | mybatis 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | 11 | com.ocean 12 | springboot 13 | 0.0.1-SNAPSHOT 14 | 15 | 16 | 17 | 18 | 19 | org.mybatis.spring.boot 20 | mybatis-spring-boot-starter 21 | 22 | 23 | 24 | 25 | mysql 26 | mysql-connector-java 27 | 28 | 29 | 30 | com.alibaba 31 | druid 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/MybatisApplication.java: -------------------------------------------------------------------------------- 1 | package com.ocean; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class MybatisApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(MybatisApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/common/DatabaseType.java: -------------------------------------------------------------------------------- 1 | package com.ocean.common; 2 | 3 | /** 4 | * 数据源key常量 5 | * 6 | * @author guodahai 7 | * @version 2018/4/12 8 | */ 9 | public enum DatabaseType { 10 | /** 11 | * 新数据源 12 | */ 13 | NEW_DATASOURCE, 14 | /** 15 | * 旧数据源 16 | */ 17 | OLD_DATASOURCE 18 | } 19 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/control/UserController.java: -------------------------------------------------------------------------------- 1 | package com.ocean.control; 2 | 3 | 4 | import com.ocean.model.NewUser; 5 | import com.ocean.model.OldUser; 6 | import com.ocean.service.UserService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.ResponseBody; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import javax.websocket.server.PathParam; 14 | 15 | /** 16 | * @author guodahai 17 | * @version 2018/4/12 下午5:14 18 | */ 19 | @RestController 20 | @RequestMapping("user") 21 | @ResponseBody 22 | public class UserController { 23 | 24 | @Autowired 25 | private UserService userService; 26 | 27 | @GetMapping("/new") 28 | public NewUser queryNewUser(@PathParam("id") Integer id) { 29 | return userService.queryNewUser(id); 30 | } 31 | 32 | @GetMapping("/old") 33 | public OldUser queryOldUser(@PathParam("id") Integer id) { 34 | return userService.queryOldUser(id); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/dao/NewUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.ocean.dao; 2 | 3 | import com.ocean.model.NewUser; 4 | import org.apache.ibatis.annotations.Mapper; 5 | 6 | /** 7 | * @author guodahai 8 | * @version 2018/4/12 下午4:45 9 | */ 10 | @Mapper 11 | public interface NewUserMapper { 12 | 13 | NewUser queryById(Integer id); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/dao/NewUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | id, 14 | name, 15 | age, 16 | sex 17 | 18 | 19 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/dao/OldUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.ocean.dao; 2 | 3 | import com.ocean.model.OldUser; 4 | import org.apache.ibatis.annotations.Mapper; 5 | 6 | /** 7 | * @author guodahai 8 | * @version 2018/4/12 下午4:43 9 | */ 10 | @Mapper 11 | public interface OldUserMapper { 12 | 13 | OldUser queryById(Integer id); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/dao/OldUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | id, 14 | name, 15 | age, 16 | sex 17 | 18 | 19 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/datasource/DatabaseContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.ocean.datasource; 2 | 3 | import com.ocean.common.DatabaseType; 4 | 5 | /** 6 | * 数据源容器 7 | * 8 | * @author guodahai 9 | * @version 2018/4/12 10 | */ 11 | public class DatabaseContextHolder { 12 | 13 | private static final ThreadLocal contextHolder = ThreadLocal.withInitial(() -> DatabaseType.NEW_DATASOURCE); 14 | 15 | public static void setDatabaseType(DatabaseType type) { 16 | contextHolder.set(type); 17 | } 18 | 19 | public static DatabaseType getDatabaseType() { 20 | return contextHolder.get(); 21 | } 22 | 23 | public static void resetDatabaseType() { 24 | contextHolder.set(DatabaseType.NEW_DATASOURCE); 25 | } 26 | 27 | public static void clearDatabaseType() { 28 | contextHolder.remove(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/datasource/MultipleDataSource.java: -------------------------------------------------------------------------------- 1 | package com.ocean.datasource; 2 | 3 | import com.ocean.common.DatabaseType; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; 7 | 8 | /** 9 | * 动态数据源 10 | * 11 | * @author guodahai 12 | * @version 2018/4/12 下午3:01 13 | */ 14 | public class MultipleDataSource extends AbstractRoutingDataSource { 15 | 16 | private final Logger logger = LoggerFactory.getLogger(MultipleDataSource.class); 17 | 18 | /** 19 | * 设置进去的当前线程数据源进行数据源切换 20 | * 21 | * @return 数据源名称 22 | */ 23 | @Override 24 | protected Object determineCurrentLookupKey() { 25 | DatabaseType databaseType = DatabaseContextHolder.getDatabaseType(); 26 | logger.info("当前线程数据源----------------:{}", databaseType); 27 | return databaseType; 28 | } 29 | 30 | @Override 31 | public java.util.logging.Logger getParentLogger() { 32 | return null; 33 | } 34 | } -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/interceptor/DataSourceInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.ocean.interceptor; 2 | 3 | import com.ocean.common.DatabaseType; 4 | import com.ocean.datasource.DatabaseContextHolder; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.aspectj.lang.annotation.Before; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @author guodahai 14 | * @version 2018/4/13 上午9:58 15 | */ 16 | @Component 17 | @Aspect 18 | public class DataSourceInterceptor { 19 | 20 | private Logger logger = LoggerFactory.getLogger(DataSourceInterceptor.class); 21 | 22 | @Pointcut("execution(* com.ocean.dao.NewUserMapper.*(..))") 23 | public void newDataSource() { 24 | } 25 | 26 | @Before("newDataSource()") 27 | public void setNewDataSource() { 28 | DatabaseContextHolder.setDatabaseType(DatabaseType.NEW_DATASOURCE); 29 | logger.info("当前数据源为:{}", DatabaseType.NEW_DATASOURCE); 30 | } 31 | 32 | @Pointcut("execution(* com.ocean.dao.OldUserMapper.*(..))") 33 | public void oldDataSource() { 34 | } 35 | 36 | @Before("oldDataSource()") 37 | public void setoldDataSource() { 38 | DatabaseContextHolder.setDatabaseType(DatabaseType.OLD_DATASOURCE); 39 | logger.info("当前数据源为:{}", DatabaseType.OLD_DATASOURCE); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/model/NewUser.java: -------------------------------------------------------------------------------- 1 | package com.ocean.model; 2 | 3 | /** 4 | * 新的用户信息 5 | * 6 | * @author guodahai 7 | * @version 2018/4/12 下午4:46 8 | */ 9 | public class NewUser { 10 | /** 11 | * 用户id 12 | */ 13 | private Integer id; 14 | /** 15 | * 用户姓名 16 | */ 17 | private String name; 18 | /** 19 | * 用户年龄 20 | */ 21 | private Integer age; 22 | /** 23 | * 用户性别 24 | */ 25 | private String sex; 26 | 27 | public Integer getId() { 28 | return id; 29 | } 30 | 31 | public void setId(Integer id) { 32 | this.id = id; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public void setName(String name) { 40 | this.name = name; 41 | } 42 | 43 | public Integer getAge() { 44 | return age; 45 | } 46 | 47 | public void setAge(Integer age) { 48 | this.age = age; 49 | } 50 | 51 | public String getSex() { 52 | return sex; 53 | } 54 | 55 | public void setSex(String sex) { 56 | this.sex = sex; 57 | } 58 | 59 | @Override 60 | public String toString() { 61 | return "NewUserDTO{" + 62 | "id=" + id + 63 | ", name='" + name + '\'' + 64 | ", age=" + age + 65 | ", sex='" + sex + '\'' + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/model/OldUser.java: -------------------------------------------------------------------------------- 1 | package com.ocean.model; 2 | 3 | /** 4 | * 新的用户信息 5 | * 6 | * @author guodahai 7 | * @version 2018/4/12 下午4:46 8 | */ 9 | public class OldUser { 10 | /** 11 | * 用户id 12 | */ 13 | private Integer id; 14 | /** 15 | * 用户姓名 16 | */ 17 | private String name; 18 | /** 19 | * 用户年龄 20 | */ 21 | private Integer age; 22 | /** 23 | * 用户性别 24 | */ 25 | private String sex; 26 | 27 | public Integer getId() { 28 | return id; 29 | } 30 | 31 | public void setId(Integer id) { 32 | this.id = id; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public void setName(String name) { 40 | this.name = name; 41 | } 42 | 43 | public Integer getAge() { 44 | return age; 45 | } 46 | 47 | public void setAge(Integer age) { 48 | this.age = age; 49 | } 50 | 51 | public String getSex() { 52 | return sex; 53 | } 54 | 55 | public void setSex(String sex) { 56 | this.sex = sex; 57 | } 58 | 59 | @Override 60 | public String toString() { 61 | return "NewUserDTO{" + 62 | "id=" + id + 63 | ", name='" + name + '\'' + 64 | ", age=" + age + 65 | ", sex='" + sex + '\'' + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.ocean.service; 2 | 3 | import com.ocean.model.NewUser; 4 | import com.ocean.model.OldUser; 5 | 6 | /** 7 | * @author guodahai 8 | * @version 2018/4/12 下午4:51 9 | */ 10 | public interface UserService { 11 | /** 12 | * 查询新库用户信息 13 | * 14 | * @param id 15 | * @return 16 | */ 17 | public NewUser queryNewUser(Integer id); 18 | 19 | /** 20 | * 查询旧库用户信息 21 | * 22 | * @param id 23 | * @return 24 | */ 25 | public OldUser queryOldUser(Integer id); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /mybatis/src/main/java/com/ocean/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ocean.service.impl; 2 | 3 | import com.ocean.dao.NewUserMapper; 4 | import com.ocean.dao.OldUserMapper; 5 | import com.ocean.model.NewUser; 6 | import com.ocean.model.OldUser; 7 | import com.ocean.service.UserService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | /** 12 | * @author guodahai 13 | * @version 2018/4/12 下午4:55 14 | */ 15 | @Service 16 | public class UserServiceImpl implements UserService { 17 | 18 | @Autowired 19 | private NewUserMapper newUserMapper; 20 | 21 | @Autowired 22 | private OldUserMapper oldUserMapper; 23 | 24 | @Override 25 | public NewUser queryNewUser(Integer id) { 26 | return newUserMapper.queryById(id); 27 | } 28 | 29 | @Override 30 | public OldUser queryOldUser(Integer id) { 31 | return oldUserMapper.queryById(id); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /mybatis/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8089 2 | 3 | old.db.driverClass=com.mysql.jdbc.Driver 4 | old.db.jdbcUrl=jdbc:mysql://127.0.0.1:3306/old 5 | old.db.user=root 6 | old.db.password=root 7 | 8 | new.db.driverClass=com.mysql.jdbc.Driver 9 | new.db.jdbcUrl=jdbc:mysql://127.0.0.1:3306/new 10 | new.db.user=root 11 | new.db.password=root 12 | 13 | spring.datasource.initialSize=2 14 | spring.datasource.minIdle=1 15 | spring.datasource.maxActive=5 16 | spring.datasource.maxWait=6000 17 | spring.datasource.timeBetweenEvictionRunsMillis=6000 18 | spring.datasource.minEvictableIdleTimeMillis=300000 19 | spring.datasource.validationQuery=select 'x' 20 | spring.datasource.testWhileIdle=true 21 | spring.datasource.testOnBorrow=true 22 | spring.datasource.testOnReturn=true 23 | spring.datasource.poolPreparedStatements=true 24 | -------------------------------------------------------------------------------- /mybatis/src/test/java/com/ocean/MybatisApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ocean; 2 | 3 | import org.junit.Test; 4 | 5 | public class MybatisApplicationTests { 6 | 7 | @Test 8 | public void contextLoads() { 9 | } 10 | 11 | @Test 12 | public void test() { 13 | double high = 0.0001; 14 | int i = 0; 15 | while (high < 8848) { 16 | high *= 2; 17 | i++; 18 | } 19 | System.out.println(i); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rabbitmq/README.md: -------------------------------------------------------------------------------- 1 | 1、direct模式 2 | 3 | 1.1 简单模式 hello 4 | 一个生产者,一个队列,一个消费者,使用默认Exchange 5 | 生产者:只需指定routingKey rabbitTemplate.convertAndSend(routingKey, object); 6 | 消费者:监听该队列 @RabbitListener(queues = "hello") 7 | 8 | 1.2 工作队列模式work 9 | 一个生产者,一个队列,多个消费者,共享任务,排队消费 10 | 功能:一个生产者,多个消费者,每个消费者获取到的消息唯一,多个消费者只有一个队列 11 | 任务队列:避免立即做一个资源密集型任务,必须等待它完成,而是把这个任务安排到稍后再做。 12 | 我们将任务封装为消息并将其发送给队列。后台运行的工作进程将弹出任务并最终执行作业。 13 | 当有多个worker同时运行时,任务将在它们之间共享。 14 | 生产者:只需指定routingKey; rabbitTemplate.convertAndSend(routingKey, object); 15 | 消费者:多个消费者监听同一队列 @RabbitListener(queues = "work") 16 | 17 | 1.3 路由模式 Routing 18 | 说明:生产者发送消息到交换机并且要指定路由key,消费者将队列绑定到交换机时需要指定路由key 19 | 20 | 2、fanout模式 21 | 22 | 2.1 发布/订阅模式 Publish/Subscribe 23 | 功能:一个生产者发送的消息会被多个消费者获取。一个生产者、一个交换机、多个队列、多个消费者 24 | 如果消息发送到没有队列绑定的交换机上,那么消息将丢失。 25 | 交换机不能存储消息,消息存储在队列中 26 | 生产者:可以将消息发送到队列或者是交换机。 27 | 消费者:只能从队列中获取消息。 28 | 29 | 3、topic模式 30 | 31 | 3.1 topic模式 32 | 队列绑定交换机,并指定队列routing key规则,更具规则来接受生产者发送的消息 33 | 说明:生产者P发送消息到交换机X,type=topic,交换机根据绑定队列的routing key的值进行通配符匹配; 34 | 符号#:匹配一个或者多个词 topic.# 可以匹配 topic.one或者topic.one.cor 35 | 符号*:只能匹配一个词 topic.* 可以匹配 topic.one或者topic.two 36 | -------------------------------------------------------------------------------- /rabbitmq/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.ocean 8 | springboot 9 | 0.0.1-SNAPSHOT 10 | 11 | 12 | rabbitmq 13 | 0.0.1-SNAPSHOT 14 | jar 15 | 16 | 17 | 18 | 19 | com.ocean 20 | common 21 | 0.0.1-SNAPSHOT 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-amqp 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/config/DirectRabbitConfig.java: -------------------------------------------------------------------------------- 1 | package com.config; 2 | 3 | import org.springframework.amqp.core.Queue; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | 8 | /** 9 | * Exchange四种模式之一:Direct 10 | * 无需绑定Exchange,需要指定RouteKey 11 | * 12 | * @author guodahai 13 | */ 14 | @Configuration 15 | public class DirectRabbitConfig { 16 | 17 | /** 18 | * 简单模式 Hello Word 19 | * 一个生产者,一个队列,一个消费者 20 | * 21 | * @return 22 | */ 23 | @Bean 24 | public Queue helloQueue() { 25 | return new Queue("hello"); 26 | } 27 | 28 | /** 29 | * 工作队列模式Work Queue 30 | * 一个生产者,一个队列,多个消费者 31 | * 32 | * @return 33 | */ 34 | @Bean 35 | public Queue workQueue() { 36 | return new Queue("work"); 37 | } 38 | 39 | @Bean 40 | public Queue objectQueue() { 41 | return new Queue("object"); 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/config/FanoutRabbitConfig.java: -------------------------------------------------------------------------------- 1 | package com.config; 2 | 3 | import org.springframework.amqp.core.Binding; 4 | import org.springframework.amqp.core.BindingBuilder; 5 | import org.springframework.amqp.core.FanoutExchange; 6 | import org.springframework.amqp.core.Queue; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | 11 | /** 12 | * Exchange四种模式之一:Fanout 13 | * 提前绑定Exchange,不需要指定RouteKey 14 | * 一个生产者、一个交换机、多个队列、多个消费者 15 | * 16 | * @author guodahai 17 | * @version 2018/5/4 下午3:38 18 | */ 19 | @Configuration 20 | public class FanoutRabbitConfig { 21 | 22 | @Bean 23 | public Queue AMessage() { 24 | return new Queue("fanout.A"); 25 | } 26 | 27 | @Bean 28 | public Queue BMessage() { 29 | return new Queue("fanout.B"); 30 | } 31 | 32 | @Bean 33 | public Queue CMessage() { 34 | return new Queue("fanout.C"); 35 | } 36 | 37 | @Bean 38 | FanoutExchange fanoutExchange() { 39 | return new FanoutExchange("fanoutExchange"); 40 | } 41 | 42 | @Bean 43 | Binding bindingExchangeA(Queue AMessage, FanoutExchange fanoutExchange) { 44 | return BindingBuilder.bind(AMessage).to(fanoutExchange); 45 | } 46 | 47 | @Bean 48 | Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) { 49 | return BindingBuilder.bind(BMessage).to(fanoutExchange); 50 | } 51 | 52 | @Bean 53 | Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) { 54 | return BindingBuilder.bind(CMessage).to(fanoutExchange); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/config/RouteRabbitConfig.java: -------------------------------------------------------------------------------- 1 | package com.config; 2 | 3 | import org.springframework.amqp.core.Binding; 4 | import org.springframework.amqp.core.BindingBuilder; 5 | import org.springframework.amqp.core.DirectExchange; 6 | import org.springframework.amqp.core.Queue; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * 路由模式 12 | * 13 | * @author guodahai 14 | * @version 2018/5/18 下午4:51 15 | */ 16 | @Configuration 17 | public class RouteRabbitConfig { 18 | 19 | @Bean 20 | public Queue routeA() { 21 | return new Queue("route.A"); 22 | } 23 | 24 | @Bean 25 | public Queue routeB() { 26 | return new Queue("route.B"); 27 | } 28 | 29 | @Bean 30 | DirectExchange directExchange() { 31 | return new DirectExchange("routing"); 32 | } 33 | 34 | @Bean 35 | Binding bindingRouteA(Queue routeA, DirectExchange directExchange) { 36 | return BindingBuilder.bind(routeA).to(directExchange).with("info"); 37 | } 38 | 39 | @Bean 40 | Binding bindingRouteB(Queue routeB, DirectExchange directExchange) { 41 | return BindingBuilder.bind(routeB).to(directExchange).with("error"); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/RabbitmqApplication.java: -------------------------------------------------------------------------------- 1 | package com.ocean; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author guodahai 8 | */ 9 | @SpringBootApplication 10 | public class RabbitmqApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(RabbitmqApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/controller/SendController.java: -------------------------------------------------------------------------------- 1 | package com.ocean.controller; 2 | 3 | import com.ocean.common.ControllerExecutor; 4 | import com.ocean.common.ResponseResult; 5 | import com.ocean.common.ServiceException; 6 | import com.ocean.model.Message; 7 | import com.ocean.service.SendService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | /** 12 | * @author guodahai 13 | * @version 2018/4/20 下午3:37 14 | */ 15 | @RestController 16 | @RequestMapping("/send") 17 | public class SendController { 18 | 19 | @Autowired 20 | private SendService sendService; 21 | 22 | @PostMapping 23 | public ResponseResult sendHello(@RequestBody Message request) { 24 | return new ControllerExecutor(request) { 25 | 26 | @Override 27 | public void checkParam(Message... param) throws ServiceException { 28 | 29 | } 30 | 31 | @Override 32 | public Boolean executeService(Message... param) throws ServiceException { 33 | return sendService.send(request); 34 | } 35 | }.execute(request); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/listener/fanout/FanoutReceiver.java: -------------------------------------------------------------------------------- 1 | package com.ocean.listener.fanout; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 6 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * Fanout模式 11 | * 12 | * @author guodahai 13 | */ 14 | @Component 15 | public class FanoutReceiver { 16 | 17 | private final Logger logger = LoggerFactory.getLogger(FanoutReceiver.class); 18 | 19 | /** 20 | * 方法级别Listener 21 | * 22 | * @param message 23 | */ 24 | @RabbitHandler 25 | @RabbitListener(queues = "fanout.A") 26 | public void processA(String message) { 27 | logger.warn("fanout Receiver A: " + message); 28 | } 29 | 30 | 31 | @RabbitHandler 32 | @RabbitListener(queues = "fanout.B") 33 | public void processB(String message) { 34 | logger.warn("fanout Receiver B: " + message); 35 | } 36 | 37 | 38 | @RabbitHandler 39 | @RabbitListener(queues = "fanout.C") 40 | public void processC(String message) { 41 | logger.warn("fanout Receiver C: " + message); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/listener/hello/HelloReceiver.java: -------------------------------------------------------------------------------- 1 | package com.ocean.listener.hello; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 6 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author guodahai 11 | */ 12 | @Component 13 | @RabbitListener(queues = "hello") 14 | public class HelloReceiver { 15 | 16 | private final Logger logger = LoggerFactory.getLogger(HelloReceiver.class); 17 | 18 | @RabbitHandler 19 | public void process(String message) { 20 | logger.warn("Receiver : " + message); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/listener/object/ObjectReceiver.java: -------------------------------------------------------------------------------- 1 | package com.ocean.listener.object; 2 | 3 | import com.ocean.model.User; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 7 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * @author guodahai 12 | */ 13 | @Component 14 | @RabbitListener(queues = "object") 15 | public class ObjectReceiver { 16 | 17 | private final Logger logger = LoggerFactory.getLogger(ObjectReceiver.class); 18 | 19 | @RabbitHandler 20 | public void process(User user) { 21 | logger.warn("Receiver object : " + user); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/listener/route/RouteReceiver.java: -------------------------------------------------------------------------------- 1 | package com.ocean.listener.route; 2 | 3 | import com.ocean.listener.fanout.FanoutReceiver; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 7 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * @author guodahai 12 | * @version 2018/5/18 下午5:04 13 | */ 14 | @Component 15 | public class RouteReceiver { 16 | 17 | private final Logger logger = LoggerFactory.getLogger(FanoutReceiver.class); 18 | 19 | @RabbitHandler 20 | @RabbitListener(queues = "route.A") 21 | public void processA(String message) { 22 | logger.warn("route Receiver A: " + message); 23 | } 24 | 25 | 26 | @RabbitHandler 27 | @RabbitListener(queues = "route.B") 28 | public void processB(String message) { 29 | logger.warn("route Receiver B: " + message); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/listener/topic/TopicReceiver.java: -------------------------------------------------------------------------------- 1 | package com.ocean.listener.topic; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 6 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author guodahai 11 | */ 12 | @Component 13 | 14 | public class TopicReceiver { 15 | 16 | private final Logger logger = LoggerFactory.getLogger(TopicReceiver.class); 17 | 18 | @RabbitHandler 19 | @RabbitListener(queues = "message.one") 20 | public void processA(String message) { 21 | logger.warn("message.one receiver : " + message); 22 | } 23 | 24 | @RabbitHandler 25 | @RabbitListener(queues = "message.two") 26 | public void processB(String message) { 27 | logger.warn("message.two receiver : " + message); 28 | } 29 | 30 | @RabbitHandler 31 | @RabbitListener(queues = "info.one") 32 | public void processC(String message) { 33 | logger.warn("info.one receiver : " + message); 34 | } 35 | 36 | @RabbitHandler 37 | @RabbitListener(queues = "info.two") 38 | public void processD(String message) { 39 | logger.warn("info.two receiver : " + message); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/listener/work/WorkReceiverOne.java: -------------------------------------------------------------------------------- 1 | package com.ocean.listener.work; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 6 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author guodahai 11 | */ 12 | @Component 13 | @RabbitListener(queues = "work") 14 | public class WorkReceiverOne { 15 | 16 | private final Logger logger = LoggerFactory.getLogger(WorkReceiverOne.class); 17 | 18 | @RabbitHandler 19 | public void process(String message) { 20 | logger.warn("ReceiverOne: " + message); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/listener/work/WorkReceiverTwo.java: -------------------------------------------------------------------------------- 1 | package com.ocean.listener.work; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 6 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author guodahai 11 | */ 12 | @Component 13 | @RabbitListener(queues = "work") 14 | public class WorkReceiverTwo { 15 | 16 | private final Logger logger = LoggerFactory.getLogger(WorkReceiverTwo.class); 17 | 18 | @RabbitHandler 19 | public void process(String message) { 20 | logger.warn("ReceiverTwo: " + message); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/model/Message.java: -------------------------------------------------------------------------------- 1 | package com.ocean.model; 2 | 3 | /** 4 | * @author guodahai 5 | * @version 2018/4/20 下午3:53 6 | */ 7 | public class Message { 8 | 9 | /** 10 | * 交换机 11 | */ 12 | private String exchange; 13 | /** 14 | * key 15 | */ 16 | private String routeKey; 17 | /** 18 | * 消息内容 19 | */ 20 | private Object msg; 21 | 22 | public String getExchange() { 23 | return exchange; 24 | } 25 | 26 | public void setExchange(String exchange) { 27 | this.exchange = exchange; 28 | } 29 | 30 | public String getRouteKey() { 31 | return routeKey; 32 | } 33 | 34 | public void setRouteKey(String routeKey) { 35 | this.routeKey = routeKey; 36 | } 37 | 38 | public Object getMsg() { 39 | return msg; 40 | } 41 | 42 | public void setMsg(Object msg) { 43 | this.msg = msg; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "Message{" + 49 | "exchange='" + exchange + '\'' + 50 | ", routeKey='" + routeKey + '\'' + 51 | ", msg=" + msg + 52 | '}'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/model/User.java: -------------------------------------------------------------------------------- 1 | package com.ocean.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author guodahai 7 | */ 8 | public class User implements Serializable { 9 | 10 | private String name; 11 | 12 | private String pass; 13 | 14 | public String getName() { 15 | return name; 16 | } 17 | 18 | public void setName(String name) { 19 | this.name = name; 20 | } 21 | 22 | public String getPass() { 23 | return pass; 24 | } 25 | 26 | public void setPass(String pass) { 27 | this.pass = pass; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "User{" + 33 | "name='" + name + '\'' + 34 | ", pass='" + pass + '\'' + 35 | '}'; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/service/SendService.java: -------------------------------------------------------------------------------- 1 | package com.ocean.service; 2 | 3 | import com.ocean.common.ServiceException; 4 | import com.ocean.model.Message; 5 | 6 | /** 7 | * @author guodahai 8 | * @version 2018/4/20 下午3:40 9 | */ 10 | public interface SendService { 11 | 12 | /** 13 | * 消息发送 14 | * 15 | * @param request 16 | * @return 17 | */ 18 | Boolean send(Message request) throws ServiceException; 19 | 20 | /** 21 | * 简单模式、工作队列模式 22 | * 23 | * @param routingKey 24 | * @param object 25 | */ 26 | void send(String routingKey, Object object) throws ServiceException; 27 | 28 | /** 29 | * Exchange模式 30 | * 31 | * @param exchange 32 | * @param routingKey 33 | * @param object 34 | */ 35 | void send(String exchange, String routingKey, Object object) throws ServiceException; 36 | } 37 | -------------------------------------------------------------------------------- /rabbitmq/src/main/java/com/ocean/service/impl/SendServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ocean.service.impl; 2 | 3 | import com.ocean.common.ErrorCodeEnum; 4 | import com.ocean.common.ServiceException; 5 | import com.ocean.model.Message; 6 | import com.ocean.service.SendService; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.amqp.core.AmqpTemplate; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | /** 14 | * @author guodahai 15 | * @version 2018/4/20 下午3:41 16 | */ 17 | @Service 18 | public class SendServiceImpl implements SendService { 19 | 20 | private final Logger logger = LoggerFactory.getLogger(SendServiceImpl.class); 21 | 22 | @Autowired 23 | private AmqpTemplate rabbitTemplate; 24 | 25 | @Override 26 | public Boolean send(Message request) throws ServiceException { 27 | String exchange = request.getExchange(); 28 | String routingKey = request.getRouteKey(); 29 | Object object = request.getMsg(); 30 | try { 31 | if (null == exchange) { 32 | send(routingKey, object); 33 | } else { 34 | send(exchange, routingKey, object); 35 | } 36 | } catch (ServiceException e) { 37 | logger.warn("发送消息失败!"); 38 | throw new ServiceException(ErrorCodeEnum.P99); 39 | } 40 | return true; 41 | } 42 | 43 | @Override 44 | public void send(String routingKey, Object object) throws ServiceException { 45 | rabbitTemplate.convertAndSend(routingKey, object); 46 | } 47 | 48 | @Override 49 | public void send(String exchange, String routingKey, Object object) throws ServiceException { 50 | rabbitTemplate.convertAndSend(exchange, routingKey, object); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /rabbitmq/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=spring-boot-rabbitmq 2 | spring.rabbitmq.host=127.0.0.1 3 | spring.rabbitmq.port=5672 4 | spring.rabbitmq.username=guest 5 | spring.rabbitmq.password=guest -------------------------------------------------------------------------------- /rabbitmq/src/test/java/com/ocean/RabbitmqApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ocean; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RabbitmqApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /rocketmq/README.md: -------------------------------------------------------------------------------- 1 | docker run -d -p 9876:9876 -v /data/namesrv/logs:/root/logs -v /data/namesrv/store:/root/store --name rmqnamesrv rocketmqinc/rocketmq:4.4.0 sh mqnamesrv 2 | docker run -d -p 10911:10911 -p 10909:10909 -v /data/broker/logs:/root/logs -v /data/broker/store:/root/store --name rmqbroker --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" rocketmqinc/rocketmq:4.4.0 sh mqbroker 3 | docker run -e "JAVA_OPTS=-Drocketmq.namesrv.addr=127.0.0.1:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" -p 8088:8080 -d --name rmq-dashboard styletang/rocketmq-console-ng 4 | 5 | docker start rmqnamesrv rmqbroker -------------------------------------------------------------------------------- /rocketmq/docker-compose-rocketmq.yml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | 3 | services: 4 | rmqnamesrv: 5 | image: foxiswho/rocketmq:server-4.5.2 6 | container_name: rmqnamesrv 7 | ports: 8 | - 9876:9876 9 | volumes: 10 | - ./rmq/logs:/opt/logs 11 | - ./rmq/store:/opt/store 12 | environment: 13 | JAVA_OPT_EXT: "-Duser.home=/opt -Xms128m -Xmx128m -Xmn128m" 14 | networks: 15 | rmq: 16 | aliases: 17 | - rmqnamesrv 18 | rmqbroker: 19 | image: foxiswho/rocketmq:broker-4.5.2 20 | container_name: rmqbroker 21 | ports: 22 | - 10909:10909 23 | - 10911:10911 24 | volumes: 25 | - ./rmq/logs:/opt/logs 26 | - ./rmq/store:/opt/store 27 | - ./rmq/brokerconf/broker.conf:/etc/rocketmq/broker.conf 28 | environment: 29 | JAVA_OPT_EXT: "-Duser.home=/opt -server -Xms128m -Xmx128m -Xmn128m" 30 | command: ["/bin/bash","mqbroker","-c","/etc/rocketmq/broker.conf","-n","rmqnamesrv:9876","autoCreateTopicEnable=true"] 31 | depends_on: 32 | - rmqnamesrv 33 | networks: 34 | rmq: 35 | aliases: 36 | - rmqbroker 37 | 38 | rmqconsole: 39 | image: styletang/rocketmq-console-ng 40 | container_name: rmqconsole 41 | ports: 42 | - 8180:8080 43 | environment: 44 | JAVA_OPTS: "-Drocketmq.namesrv.addr=rmqnamesrv:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" 45 | depends_on: 46 | - rmqnamesrv 47 | networks: 48 | rmq: 49 | aliases: 50 | - rmqconsole 51 | 52 | networks: 53 | rmq: 54 | name: rmq 55 | driver: bridge -------------------------------------------------------------------------------- /rocketmq/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.ocean 8 | springboot 9 | 0.0.1-SNAPSHOT 10 | 11 | 12 | rocketmq 13 | 1.0-SNAPSHOT 14 | 15 | 16 | rocket-producer 17 | rocket-common 18 | rocket-consumer 19 | 20 | pom 21 | 22 | 23 | 24 | org.apache.rocketmq 25 | rocketmq-client 26 | 27 | 28 | org.projectlombok 29 | lombok 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /rocketmq/rmq/readme.md: -------------------------------------------------------------------------------- 1 | docker-compose 2 | 3 | 进入 本目录下,执行如下命令 4 | ```bash 5 | docker-compose up 6 | ``` 7 | 8 | ```bash 9 | docker start rmqnamesrv 10 | docker start rmqbroker 11 | docker start rmqconsole 12 | ``` -------------------------------------------------------------------------------- /rocketmq/rocket-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.ocean 7 | rocketmq 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | rocket-common 13 | 14 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/annotation/EnableRocketMQConfig.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * RocketMQ启用注解 7 | * 8 | * @author ocean 9 | */ 10 | @Target(ElementType.TYPE) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | @Inherited 14 | public @interface EnableRocketMQConfig { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/annotation/RocketMQConsumer.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.annotation; 2 | 3 | import com.ocean.rocket.enums.ConsumeMode; 4 | import org.apache.rocketmq.common.protocol.heartbeat.MessageModel; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.lang.annotation.*; 8 | 9 | /** 10 | * RocketMQ消费者自动装配注解 11 | * 12 | * @author ocean 13 | */ 14 | @Target(ElementType.TYPE) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | @Component 18 | public @interface RocketMQConsumer { 19 | /** 20 | * 消费group名称 21 | */ 22 | String consumerGroup(); 23 | 24 | /** 25 | * 消息topic 26 | */ 27 | String topic(); 28 | 29 | /** 30 | * 消息标签,用于区分一类消息 31 | */ 32 | String[] tag() default {"*"}; 33 | 34 | /** 35 | * 广播模式消费: BROADCASTING 36 | * 集群模式消费(默认): CLUSTERING 37 | */ 38 | MessageModel messageMode() default MessageModel.CLUSTERING; 39 | 40 | /** 41 | * 并发消费(默认): CONCURRENTLY 42 | * 顺序消费: ORDERLY 43 | */ 44 | ConsumeMode consumeMode() default ConsumeMode.CONCURRENTLY; 45 | } 46 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/annotation/RocketMQKey.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 用来标识作为消息key的字段,尽可能全局唯一 7 | * prefix 会作为前缀拼到字段值前面 8 | * 9 | * @author ocean 10 | */ 11 | @Target(ElementType.FIELD) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Documented 14 | public @interface RocketMQKey { 15 | String prefix() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/annotation/RocketMQProducer.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.annotation; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import java.lang.annotation.*; 6 | 7 | /** 8 | * RocketMQ生产者自动装配注解 9 | * 10 | * @author ocean 11 | */ 12 | @Target(ElementType.TYPE) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Documented 15 | @Component 16 | public @interface RocketMQProducer { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/base/AbstractRocketMQConsumer.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.base; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.rocketmq.common.message.MessageExt; 6 | import org.springframework.util.Assert; 7 | 8 | import java.lang.reflect.ParameterizedType; 9 | import java.lang.reflect.Type; 10 | 11 | /** 12 | * RocketMQ消费者基类 13 | * 14 | * @author ocean 15 | */ 16 | @Slf4j 17 | public abstract class AbstractRocketMQConsumer { 18 | 19 | /** 20 | * 反序列化解析消息 21 | * 22 | * @param message 消息体 23 | * @return 序列化结果 24 | */ 25 | protected T parseMessage(MessageExt message) { 26 | if (message == null || message.getBody() == null) { 27 | return null; 28 | } 29 | final Type type = this.getMessageType(); 30 | if (type instanceof Class) { 31 | if (type.getTypeName().equals(String.class.getName())) { 32 | return (T) new String(message.getBody()); 33 | } 34 | try { 35 | T data = JSON.parseObject(new String(message.getBody()), type); 36 | return data; 37 | } catch (Exception e) { 38 | log.warn("Parse message json fail:{}", new String(message.getBody()), e); 39 | } 40 | } else { 41 | log.warn("Parse msg fail: {}", message); 42 | } 43 | return null; 44 | } 45 | 46 | /** 47 | * 解析消息类型 48 | * 49 | * @return 消息类型 50 | */ 51 | protected Type getMessageType() { 52 | Type superType = this.getClass().getGenericSuperclass(); 53 | if (superType instanceof ParameterizedType) { 54 | ParameterizedType parameterizedType = (ParameterizedType) superType; 55 | Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); 56 | Assert.isTrue(actualTypeArguments.length == 1, "Number of type arguments must be 1"); 57 | return actualTypeArguments[0]; 58 | } else { 59 | // 如果没有定义泛型,解析为Object 60 | return Object.class; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/config/BaseAutoConfig.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.config; 2 | 3 | import com.ocean.rocket.annotation.EnableRocketMQConfig; 4 | import com.ocean.rocket.base.AbstractMQPushConsumer; 5 | import com.ocean.rocket.constants.MessageConstant; 6 | import org.springframework.beans.BeansException; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.autoconfigure.AutoConfigureAfter; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 10 | import org.springframework.context.ApplicationContext; 11 | import org.springframework.context.ApplicationContextAware; 12 | import org.springframework.context.annotation.Configuration; 13 | import org.springframework.core.env.StandardEnvironment; 14 | 15 | import javax.annotation.PostConstruct; 16 | 17 | /** 18 | * RocketMQ基本配置 19 | * 20 | * @author ocean 21 | */ 22 | @Configuration 23 | @ConditionalOnBean(annotation = EnableRocketMQConfig.class) 24 | @AutoConfigureAfter(AbstractMQPushConsumer.class) 25 | public class BaseAutoConfig implements ApplicationContextAware { 26 | @Autowired 27 | protected StandardEnvironment standardEnvironment; 28 | 29 | ApplicationContext applicationContext; 30 | 31 | @Override 32 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 33 | this.applicationContext = applicationContext; 34 | } 35 | 36 | @PostConstruct 37 | public void setClientLoggerProperties() { 38 | setSystemProperty(MessageConstant.ROCKETMQ_CLIENT_LOG_LOADCONFIG); 39 | setSystemProperty(MessageConstant.ROCKETMQ_CLIENT_LOGROOT); 40 | setSystemProperty(MessageConstant.CLIENT_LOG_LEVEL); 41 | } 42 | 43 | private void setSystemProperty(String key) { 44 | if (standardEnvironment.containsProperty(key)) { 45 | System.setProperty(key, standardEnvironment.getProperty(key)); 46 | } 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/config/ConsumerProperties.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.config; 2 | 3 | import lombok.Data; 4 | import org.apache.rocketmq.client.ClientConfig; 5 | import org.apache.rocketmq.common.consumer.ConsumeFromWhere; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | 8 | /** 9 | * RocketMQ的consumer配置参数 10 | * 11 | * @author ocean 12 | */ 13 | @Data 14 | @ConfigurationProperties(prefix = ConsumerProperties.PREFIX) 15 | public class ConsumerProperties extends ClientConfig { 16 | public static final String PREFIX = "rocket.consumer"; 17 | 18 | private String namesrvAddr; 19 | /** 20 | * 是否开启VIP通道 21 | */ 22 | private boolean vipChannelEnabled = false; 23 | 24 | /** 25 | * Max re-consume times. -1 means 16 times. 26 | * If messages are re-consumed more than {@link #maxReconsumeTimes} before success, it's be directed to a deletion 27 | * queue waiting. 28 | */ 29 | private int maxReconsumeTimes = -1; 30 | 31 | /** 32 | * Maximum number of retry to perform internally before claiming consume failure. 33 | */ 34 | private int retryTimesWhenConsumeFailed = 16; 35 | 36 | /** 37 | * Maximum amount of time in minutes a message may block the consuming thread. 38 | */ 39 | private long consumeTimeout = 15; 40 | 41 | /** 42 | * Consuming point on consumer booting. 43 | */ 44 | private String consumeFromWhere = ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET.toString(); 45 | } 46 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/config/ProducerProperties.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.config; 2 | 3 | import lombok.Data; 4 | import org.apache.rocketmq.client.ClientConfig; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | 7 | /** 8 | * RocketMQ的producer配置参数 9 | * 10 | * @author ocean 11 | */ 12 | @Data 13 | @ConfigurationProperties(prefix = ProducerProperties.PREFIX) 14 | public class ProducerProperties extends ClientConfig { 15 | public static final String PREFIX = "rocket.producer"; 16 | /** 17 | * namesrv地址 18 | */ 19 | private String namesrvAddr; 20 | /** 21 | * 生产者Group名称 22 | */ 23 | private String producerGroup; 24 | /** 25 | * 是否开启VIP通道 26 | */ 27 | private boolean vipChannelEnabled = false; 28 | 29 | /** 30 | * Number of queues to create per default topic. 31 | */ 32 | private volatile int defaultTopicQueueNums = 4; 33 | 34 | /** 35 | * Timeout for sending messages. 36 | */ 37 | private int sendMsgTimeout = 3000; 38 | 39 | /** 40 | * Maximum number of retry to perform internally before claiming sending 41 | * failure in synchronous mode. 42 | * This may potentially cause message duplication which is up to application 43 | * developers to resolve. 44 | */ 45 | private int retryTimesWhenSendFailed = 3; 46 | 47 | /** 48 | * Maximum number of retry to perform internally before claiming sending 49 | * failure in asynchronous mode. 50 | *

51 | *

52 | * This may potentially cause message duplication which is up to application 53 | * developers to resolve. 54 | */ 55 | private int retryTimesWhenSendAsyncFailed = 3; 56 | 57 | /** 58 | * Indicate whether to retry another broker on sending failure internally. 59 | */ 60 | private boolean retryAnotherBrokerWhenNotStoreOK = false; 61 | 62 | /** 63 | * Maximum allowed message size in bytes. 64 | * 4M 65 | */ 66 | private int maxMessageSize = 1024 * 1024 * 4; 67 | 68 | /** 69 | * 是否启用事务 70 | */ 71 | private boolean transaction = false; 72 | } 73 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/constants/MessageConstant.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.constants; 2 | 3 | /** 4 | * 消息常量 5 | * 6 | * @author 003238 7 | */ 8 | public class MessageConstant { 9 | /** 10 | * 默认字符编码 11 | */ 12 | public final static String DEFAULT_CHARSET = "UTF-8"; 13 | 14 | /** 15 | * rocketmq是否加载客户端日志 16 | */ 17 | public final static String ROCKETMQ_CLIENT_LOG_LOADCONFIG = "rocketmq.client.log.loadconfig"; 18 | 19 | /** 20 | * rocketmq日志路径 21 | */ 22 | public final static String ROCKETMQ_CLIENT_LOGROOT = "rocket.client.logRoot"; 23 | 24 | /** 25 | * rocketmq日志级别 26 | */ 27 | public static final String CLIENT_LOG_LEVEL = "rocket.client.logLevel"; 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/enums/ConsumeMode.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.enums; 2 | 3 | /** 4 | * 消费类型 5 | * 6 | * @author 003238 7 | */ 8 | public enum ConsumeMode { 9 | /** 10 | * consume delivered messages concurrently 11 | */ 12 | CONCURRENTLY, 13 | 14 | /** 15 | * consume delivered messages orderly, one queue, one thread 16 | */ 17 | ORDERLY 18 | } 19 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/enums/DelayTimeLevel.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.enums; 2 | 3 | /** 4 | * 延长消息时间段枚举 5 | * 6 | * @author ocean 7 | */ 8 | public enum DelayTimeLevel { 9 | /** 10 | * 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h 11 | */ 12 | SECOND_1(1), 13 | SECOND_5(2), 14 | SECOND_10(3), 15 | SECOND_30(4), 16 | MINUTE_1(5), 17 | MINUTE_2(6), 18 | MINUTE_3(7), 19 | MINUTE_4(8), 20 | MINUTE_5(9), 21 | MINUTE_6(10), 22 | MINUTE_7(11), 23 | MINUTE_8(12), 24 | MINUTE_9(13), 25 | MINUTE_10(14), 26 | MINUTE_20(15), 27 | MINUTE_30(16), 28 | HOUR_1(17), 29 | HOUR_2(18); 30 | 31 | private int level; 32 | 33 | DelayTimeLevel(int level) { 34 | this.level = level; 35 | } 36 | 37 | public int getLevel() { 38 | return level; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/exception/RocketMqException.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.exception; 2 | 3 | /** 4 | * RocketMQ自定义异常 5 | * 6 | * @author 003238 7 | */ 8 | public class RocketMqException extends RuntimeException { 9 | 10 | private static final long serialVersionUID = -3878975849119141383L; 11 | 12 | public RocketMqException(String msg) { 13 | super(msg); 14 | } 15 | 16 | public RocketMqException(String msg, Throwable cause) { 17 | super(msg, cause); 18 | } 19 | 20 | public RocketMqException(Throwable cause) { 21 | super(cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/hook/ConsumeOneMessageAdvice.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.hook; 2 | 3 | import org.apache.rocketmq.common.message.MessageExt; 4 | 5 | /** 6 | * @author 003238 7 | */ 8 | public interface ConsumeOneMessageAdvice { 9 | String hookName(); 10 | 11 | void consumeMessageBefore(final MessageExt msg); 12 | 13 | void consumeMessageAfter(final MessageExt msg); 14 | } 15 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/hook/ProducerShutdownHook.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.hook; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.apache.rocketmq.client.producer.MQProducer; 5 | 6 | /** 7 | * MQProducer关闭hook 8 | * 9 | * @author 003238 10 | */ 11 | @Slf4j 12 | public class ProducerShutdownHook extends Thread { 13 | 14 | private MQProducer producer; 15 | 16 | public ProducerShutdownHook(MQProducer producer) { 17 | this.producer = producer; 18 | } 19 | 20 | @Override 21 | public void run() { 22 | if (producer != null) { 23 | log.info("MQProducer shutdownHook"); 24 | producer.shutdown(); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/src/main/java/com/ocean/rocket/hook/PushConsumerShutdownHook.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.hook; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; 5 | 6 | /** 7 | * DefaultMQPushConsumer关闭hook 8 | * 9 | * @author 003238 10 | */ 11 | @Slf4j 12 | public class PushConsumerShutdownHook extends Thread { 13 | 14 | private DefaultMQPushConsumer consumer; 15 | 16 | public PushConsumerShutdownHook(DefaultMQPushConsumer consumer) { 17 | this.consumer = consumer; 18 | } 19 | 20 | @Override 21 | public void run() { 22 | if (consumer != null) { 23 | log.info("DefaultMQPushConsumer shutdownHook:{}", consumer.getConsumerGroup()); 24 | consumer.shutdown(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Apache Maven 2 | #Wed Sep 18 19:09:18 CST 2019 3 | version=1.0-SNAPSHOT 4 | groupId=com.ocean 5 | artifactId=rocket-common 6 | -------------------------------------------------------------------------------- /rocketmq/rocket-common/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/rocketmq/rocket-common/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst -------------------------------------------------------------------------------- /rocketmq/rocket-common/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/rocketmq/rocket-common/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst -------------------------------------------------------------------------------- /rocketmq/rocket-common/target/rocket-comon-1.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/rocketmq/rocket-common/target/rocket-comon-1.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /rocketmq/rocket-consumer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | rocketmq 7 | com.ocean 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | rocket-consumer 13 | 14 | 15 | 16 | com.ocean 17 | rocket-common 18 | 1.0-SNAPSHOT 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /rocketmq/rocket-consumer/src/main/java/com/ocean/rocket/RocketMqConsumerApplication.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket; 2 | 3 | import com.ocean.rocket.annotation.EnableRocketMQConfig; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | /** 8 | * @author guodahai 9 | */ 10 | @EnableRocketMQConfig 11 | @SpringBootApplication 12 | public class RocketMqConsumerApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(RocketMqConsumerApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rocketmq/rocket-consumer/src/main/java/com/ocean/rocket/consumer/Consumer.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.consumer; 2 | 3 | import com.ocean.rocket.annotation.RocketMQConsumer; 4 | import com.ocean.rocket.base.AbstractMQPushConsumer; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.rocketmq.common.message.MessageExt; 7 | 8 | /** 9 | * 生产者 10 | * 11 | * @author ocean 12 | */ 13 | @Slf4j 14 | @RocketMQConsumer(consumerGroup = "ocean", topic = "topic") 15 | public class Consumer extends AbstractMQPushConsumer { 16 | 17 | @Override 18 | public boolean processMessage(String message, MessageExt messageExt) { 19 | log.warn("Consumer========"); 20 | return true; 21 | } 22 | } -------------------------------------------------------------------------------- /rocketmq/rocket-consumer/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | rocket.producer.namesrvAddr=127.0.0.1:9876 2 | rocket.producer.producerGroup=ocean 3 | rocket.producer.vipChannelEnabled=false 4 | rocket.consumer.namesrvAddr=127.0.0.1:9876 5 | rocket.consumer.vipChannelEnabled=false 6 | rocket.client.log.loadconfig=false 7 | server.port=8082 8 | -------------------------------------------------------------------------------- /rocketmq/rocket-producer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.ocean 8 | rocketmq 9 | 1.0-SNAPSHOT 10 | 11 | 12 | rocket-producer 13 | 14 | 15 | 16 | com.ocean 17 | rocket-common 18 | 1.0-SNAPSHOT 19 | 20 | 21 | -------------------------------------------------------------------------------- /rocketmq/rocket-producer/src/main/java/com/ocean/rocket/RocketMqProducerApplication.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket; 2 | 3 | import com.ocean.rocket.annotation.EnableRocketMQConfig; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | /** 8 | * @author guodahai 9 | */ 10 | @EnableRocketMQConfig 11 | @SpringBootApplication 12 | public class RocketMqProducerApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(RocketMqProducerApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rocketmq/rocket-producer/src/main/java/com/ocean/rocket/producer/Producer.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.producer; 2 | 3 | import com.ocean.rocket.annotation.RocketMQProducer; 4 | import com.ocean.rocket.base.AbstractRocketMQProducer; 5 | import org.apache.rocketmq.client.producer.SendResult; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * 生产者 10 | * 11 | * @author ocean 12 | */ 13 | @Component 14 | @RocketMQProducer 15 | public class Producer extends AbstractRocketMQProducer { 16 | 17 | /** 18 | * 重写此方法处理发送后的逻辑 19 | * 20 | * @param sendResult 发送结果 21 | */ 22 | @Override 23 | public void doAfterSyncSend(SendResult sendResult) { 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /rocketmq/rocket-producer/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | rocket.producer.namesrvAddr=127.0.0.1:9876 2 | rocket.producer.producerGroup=ocean 3 | rocket.producer.vipChannelEnabled=false 4 | rocket.consumer.namesrvAddr=127.0.0.1:9876 5 | rocket.consumer.vipChannelEnabled=false 6 | rocket.client.log.loadconfig=false 7 | server.port=8081 -------------------------------------------------------------------------------- /rocketmq/rocket-producer/src/test/java/com/ocean/rocket/producer/ProducerTest.java: -------------------------------------------------------------------------------- 1 | package com.ocean.rocket.producer; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.ocean.rocket.RocketMqProducerApplication; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.apache.rocketmq.client.exception.MQClientException; 8 | import org.apache.rocketmq.client.producer.LocalTransactionState; 9 | import org.apache.rocketmq.client.producer.SendResult; 10 | import org.apache.rocketmq.client.producer.TransactionListener; 11 | import org.apache.rocketmq.common.message.Message; 12 | import org.apache.rocketmq.common.message.MessageExt; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import org.springframework.boot.test.context.SpringBootTest; 16 | import org.springframework.test.context.junit4.SpringRunner; 17 | 18 | import javax.annotation.Resource; 19 | 20 | @Slf4j 21 | @RunWith(SpringRunner.class) 22 | @SpringBootTest(classes = RocketMqProducerApplication.class) 23 | public class ProducerTest { 24 | 25 | @Resource 26 | private Producer producer; 27 | 28 | /** 29 | * 发送同步消息 30 | */ 31 | @Test 32 | public void test() { 33 | SendResult sendResult = producer.syncSend("topic", null, "message"); 34 | log.info(JSON.toJSONString(sendResult)); 35 | } 36 | 37 | /** 38 | * 发送事务消息 39 | * 40 | * @throws MQClientException 41 | */ 42 | @Test 43 | public void sendMessageInTransaction() throws MQClientException { 44 | String str = ""; 45 | producer.sendMessageInTransaction("topic", null, "message", str, new TransactionListener() { 46 | 47 | @Override 48 | public LocalTransactionState executeLocalTransaction(Message msg, Object arg) { 49 | //TODO 执行本地事务 50 | if (StringUtils.isEmpty(str)) { 51 | return LocalTransactionState.ROLLBACK_MESSAGE; 52 | } 53 | return LocalTransactionState.COMMIT_MESSAGE; 54 | } 55 | 56 | @Override 57 | public LocalTransactionState checkLocalTransaction(MessageExt msg) { 58 | //TODO 检查本地事务 59 | return LocalTransactionState.COMMIT_MESSAGE; 60 | } 61 | }); 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /solr/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | solr 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | solr 11 | Demo project for Spring Boot 12 | 13 | 14 | com.ocean 15 | springboot 16 | 0.0.1-SNAPSHOT 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-data-solr 23 | 24 | 25 | org.apache.solr 26 | solr-solrj 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /solr/src/main/java/com/ocean/solr/SolrApplication.java: -------------------------------------------------------------------------------- 1 | package com.ocean.solr; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SolrApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SolrApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /solr/src/main/java/com/ocean/solr/config/SolrConfig.java: -------------------------------------------------------------------------------- 1 | package com.ocean.solr.config; 2 | 3 | import org.apache.solr.client.solrj.SolrServer; 4 | import org.apache.solr.client.solrj.impl.HttpSolrServer; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | @Configuration 10 | public class SolrConfig { 11 | 12 | @Value("${spring.data.solr.host}") 13 | private String URL; 14 | 15 | @Bean 16 | public SolrServer solrServer() { 17 | HttpSolrServer solrServer = new HttpSolrServer(URL); 18 | return solrServer; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /solr/src/main/java/com/ocean/solr/controller/ProductController.java: -------------------------------------------------------------------------------- 1 | package com.ocean.solr.controller; 2 | 3 | import com.ocean.solr.pojo.ResultModel; 4 | import com.ocean.solr.service.ProductService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | 10 | /** 11 | * 商品搜索controller 12 | *

Title: ProductController

13 | *

Description:

14 | *

Company: www.itcast.cn

15 | * 16 | * @version 1.0 17 | */ 18 | @Controller 19 | public class ProductController { 20 | 21 | @Autowired 22 | private ProductService productService; 23 | 24 | @RequestMapping("/list") 25 | public String productSearch(String queryString, String catalog_name, String price, 26 | String sort, Integer page, Model model) throws Exception { 27 | //调用服务查询商品列表 28 | ResultModel resultModel = productService.queryProduct(queryString, catalog_name, price, sort, page); 29 | //传递给页面 30 | model.addAttribute("queryString", queryString); 31 | model.addAttribute("catalog_name", catalog_name); 32 | model.addAttribute("price", price); 33 | model.addAttribute("sort", sort); 34 | model.addAttribute("page", page); 35 | model.addAttribute("result", resultModel); 36 | //返回逻辑视图 37 | return "product_list"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /solr/src/main/java/com/ocean/solr/dao/ProductDao.java: -------------------------------------------------------------------------------- 1 | package com.ocean.solr.dao; 2 | 3 | import com.ocean.solr.pojo.ProductModel; 4 | import com.ocean.solr.pojo.ResultModel; 5 | import org.apache.solr.client.solrj.SolrQuery; 6 | import org.apache.solr.client.solrj.SolrServer; 7 | import org.apache.solr.client.solrj.response.QueryResponse; 8 | import org.apache.solr.common.SolrDocument; 9 | import org.apache.solr.common.SolrDocumentList; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Repository; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | 18 | /** 19 | * 商品搜索dao 20 | *

Title: ProductDao

21 | *

Description:

22 | *

Company: www.itcast.cn

23 | * @version 1.0 24 | */ 25 | @Repository 26 | public class ProductDao { 27 | 28 | @Autowired 29 | private SolrServer solrServer; 30 | 31 | public ResultModel search(SolrQuery query) throws Exception { 32 | //执行查询 33 | QueryResponse response = solrServer.query(query); 34 | //取查询结果 35 | SolrDocumentList solrDocumentList = response.getResults(); 36 | //取查询结果总记录数 37 | ResultModel resultModel = new ResultModel(); 38 | resultModel.setRecordCount(solrDocumentList.getNumFound()); 39 | //商品列表 40 | List productList = new ArrayList<>(); 41 | //取结果集 42 | for (SolrDocument solrDocument : solrDocumentList) { 43 | //创建一个商品对象 44 | ProductModel productModel = new ProductModel(); 45 | productModel.setPid((String) solrDocument.get("id")); 46 | productModel.setCatalog_name((String) solrDocument.get("product_catalog_name")); 47 | //取高亮显示 48 | Map>> highlighting = response.getHighlighting(); 49 | List list = highlighting.get(solrDocument.get("id")).get("product_name"); 50 | String productName = ""; 51 | if (list != null && list.size() > 0) { 52 | productName = list.get(0); 53 | } else { 54 | productName = (String) solrDocument.get("product_name"); 55 | } 56 | productModel.setName(productName); 57 | productModel.setPicture((String) solrDocument.get("product_picture")); 58 | productModel.setPrice((float) solrDocument.get("product_price")); 59 | //添加到商品列表 60 | productList.add(productModel); 61 | } 62 | //添加到返回结果 63 | resultModel.setProductList(productList); 64 | return resultModel; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /solr/src/main/java/com/ocean/solr/pojo/ProductModel.java: -------------------------------------------------------------------------------- 1 | package com.ocean.solr.pojo; 2 | 3 | public class ProductModel { 4 | // 商品编号 5 | private String pid; 6 | // 商品名称 7 | private String name; 8 | // 商品分类名称 9 | private String catalog_name; 10 | // 价格 11 | private float price; 12 | // 商品描述 13 | private String description; 14 | // 图片名称 15 | private String picture; 16 | 17 | public String getPid() { 18 | return pid; 19 | } 20 | 21 | public void setPid(String pid) { 22 | this.pid = pid; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public String getCatalog_name() { 34 | return catalog_name; 35 | } 36 | 37 | public void setCatalog_name(String catalog_name) { 38 | this.catalog_name = catalog_name; 39 | } 40 | 41 | public float getPrice() { 42 | return price; 43 | } 44 | 45 | public void setPrice(float price) { 46 | this.price = price; 47 | } 48 | 49 | public String getDescription() { 50 | return description; 51 | } 52 | 53 | public void setDescription(String description) { 54 | this.description = description; 55 | } 56 | 57 | public String getPicture() { 58 | return picture; 59 | } 60 | 61 | public void setPicture(String picture) { 62 | this.picture = picture; 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /solr/src/main/java/com/ocean/solr/pojo/ResultModel.java: -------------------------------------------------------------------------------- 1 | package com.ocean.solr.pojo; 2 | 3 | import java.util.List; 4 | 5 | public class ResultModel { 6 | // 商品列表 7 | private List productList; 8 | // 商品总数 9 | private Long recordCount; 10 | // 总页数 11 | private int pageCount; 12 | // 当前页 13 | private int curPage; 14 | 15 | public List getProductList() { 16 | return productList; 17 | } 18 | 19 | public void setProductList(List productList) { 20 | this.productList = productList; 21 | } 22 | 23 | public Long getRecordCount() { 24 | return recordCount; 25 | } 26 | 27 | public void setRecordCount(Long recordCount) { 28 | this.recordCount = recordCount; 29 | } 30 | 31 | public int getPageCount() { 32 | return pageCount; 33 | } 34 | 35 | public void setPageCount(int pageCount) { 36 | this.pageCount = pageCount; 37 | } 38 | 39 | public int getCurPage() { 40 | return curPage; 41 | } 42 | 43 | public void setCurPage(int curPage) { 44 | this.curPage = curPage; 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /solr/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8111 3 | 4 | spring: 5 | mvc: 6 | view: 7 | prefix: /WEB-INF/pages/ 8 | suffix: .jsp 9 | 10 | spring.data.solr.host: http://127.0.0.1:8080/solr -------------------------------------------------------------------------------- /solr/src/test/java/com/ocean/solr/SolrApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ocean.solr; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SolrApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /xxl-job/doc/XXL-JOB架构图.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/XXL-JOB架构图.pptx -------------------------------------------------------------------------------- /xxl-job/doc/images/cnblog-首页-每日一博-第一.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/cnblog-首页-每日一博-第一.png -------------------------------------------------------------------------------- /xxl-job/doc/images/cnblog-首页-热门动弹-第一.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/cnblog-首页-热门动弹-第一.png -------------------------------------------------------------------------------- /xxl-job/doc/images/donate-alipay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/donate-alipay.jpg -------------------------------------------------------------------------------- /xxl-job/doc/images/donate-paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/donate-paypal.png -------------------------------------------------------------------------------- /xxl-job/doc/images/donate-wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/donate-wechat.png -------------------------------------------------------------------------------- /xxl-job/doc/images/gitee-gvp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/gitee-gvp.jpg -------------------------------------------------------------------------------- /xxl-job/doc/images/img_6yC0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_6yC0.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_BPLG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_BPLG.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_EB65.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_EB65.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_Fgql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_Fgql.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_Hr2T.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_Hr2T.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_Qohm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_Qohm.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_UDSo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_UDSo.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_V3vF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_V3vF.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_Wb2o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_Wb2o.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_Ypik.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_Ypik.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_Z9Qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_Z9Qr.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_ZAhX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_ZAhX.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_ZAsz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_ZAsz.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_dNUJ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_dNUJ.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_eYrv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_eYrv.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_hIci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_hIci.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_iUw0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_iUw0.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_inc8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_inc8.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_jOAU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_jOAU.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_jrdI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_jrdI.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_o8HQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_o8HQ.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_oLlM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_oLlM.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_tJOq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_tJOq.png -------------------------------------------------------------------------------- /xxl-job/doc/images/img_tvGI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/img_tvGI.png -------------------------------------------------------------------------------- /xxl-job/doc/images/qq群-一个xxl同学进了58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/qq群-一个xxl同学进了58.png -------------------------------------------------------------------------------- /xxl-job/doc/images/xxl-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/xxl-logo.jpg -------------------------------------------------------------------------------- /xxl-job/doc/images/xxl-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/doc/images/xxl-logo.png -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:7-jre-slim 2 | MAINTAINER xuxueli 3 | 4 | ENV PARAMS="" 5 | 6 | ENV TZ=PRC 7 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 8 | 9 | ADD target/xxl-job-admin-*.jar /app.jar 10 | 11 | ENTRYPOINT ["sh","-c","java -jar /app.jar $PARAMS"] -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/XxlJobAdminApplication.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author xuxueli 2018-10-28 00:38:13 8 | */ 9 | @SpringBootApplication 10 | public class XxlJobAdminApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(XxlJobAdminApplication.class, args); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobApiController.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller; 2 | 3 | import com.xxl.job.admin.controller.annotation.PermessionLimit; 4 | import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler; 5 | import com.xxl.job.core.biz.AdminBiz; 6 | import org.springframework.beans.factory.InitializingBean; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | /** 16 | * Created by xuxueli on 17/5/10. 17 | */ 18 | @Controller 19 | public class JobApiController implements InitializingBean { 20 | 21 | 22 | @Override 23 | public void afterPropertiesSet() throws Exception { 24 | 25 | } 26 | 27 | @RequestMapping(AdminBiz.MAPPING) 28 | @PermessionLimit(limit=false) 29 | public void api(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 30 | XxlJobDynamicScheduler.invokeAdminService(request, response); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/annotation/PermessionLimit.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller.annotation; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 权限限制 11 | * @author xuxueli 2015-12-12 18:29:02 12 | */ 13 | @Target(ElementType.METHOD) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface PermessionLimit { 16 | 17 | /** 18 | * 登录拦截 (默认拦截) 19 | */ 20 | boolean limit() default true; 21 | 22 | } -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/CookieInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller.interceptor; 2 | 3 | import com.xxl.job.admin.core.util.FtlUtil; 4 | import com.xxl.job.admin.core.util.I18nUtil; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.servlet.ModelAndView; 7 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 8 | 9 | import javax.servlet.http.Cookie; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.util.HashMap; 13 | 14 | /** 15 | * push cookies to model as cookieMap 16 | * 17 | * @author xuxueli 2015-12-12 18:09:04 18 | */ 19 | @Component 20 | public class CookieInterceptor extends HandlerInterceptorAdapter { 21 | 22 | @Override 23 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 24 | ModelAndView modelAndView) throws Exception { 25 | 26 | // cookie 27 | if (modelAndView!=null && request.getCookies()!=null && request.getCookies().length>0) { 28 | HashMap cookieMap = new HashMap(); 29 | for (Cookie ck : request.getCookies()) { 30 | cookieMap.put(ck.getName(), ck); 31 | } 32 | modelAndView.addObject("cookieMap", cookieMap); 33 | } 34 | 35 | // static method 36 | if (modelAndView != null) { 37 | modelAndView.addObject("I18nUtil", FtlUtil.generateStaticModel(I18nUtil.class.getName())); 38 | } 39 | 40 | super.postHandle(request, response, handler, modelAndView); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller.interceptor; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 6 | 7 | import javax.annotation.Resource; 8 | 9 | /** 10 | * web mvc config 11 | * 12 | * @author xuxueli 2018-04-02 20:48:20 13 | */ 14 | @Configuration 15 | public class WebMvcConfig extends WebMvcConfigurerAdapter { 16 | 17 | @Resource 18 | private PermissionInterceptor permissionInterceptor; 19 | @Resource 20 | private CookieInterceptor cookieInterceptor; 21 | 22 | @Override 23 | public void addInterceptors(InterceptorRegistry registry) { 24 | registry.addInterceptor(permissionInterceptor).addPathPatterns("/**"); 25 | registry.addInterceptor(cookieInterceptor).addPathPatterns("/**"); 26 | super.addInterceptors(registry); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/controller/resolver/WebExceptionResolver.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.controller.resolver; 2 | 3 | import com.xxl.job.admin.core.util.JacksonUtil; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | import org.springframework.web.method.HandlerMethod; 10 | import org.springframework.web.servlet.HandlerExceptionResolver; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.io.IOException; 16 | 17 | /** 18 | * common exception resolver 19 | * 20 | * @author xuxueli 2016-1-6 19:22:18 21 | */ 22 | @Component 23 | public class WebExceptionResolver implements HandlerExceptionResolver { 24 | private static transient Logger logger = LoggerFactory.getLogger(WebExceptionResolver.class); 25 | 26 | @Override 27 | public ModelAndView resolveException(HttpServletRequest request, 28 | HttpServletResponse response, Object handler, Exception ex) { 29 | logger.error("WebExceptionResolver:{}", ex); 30 | 31 | // if json 32 | boolean isJson = false; 33 | HandlerMethod method = (HandlerMethod)handler; 34 | ResponseBody responseBody = method.getMethodAnnotation(ResponseBody.class); 35 | if (responseBody != null) { 36 | isJson = true; 37 | } 38 | 39 | // error result 40 | ReturnT errorResult = new ReturnT(ReturnT.FAIL_CODE, ex.toString().replaceAll("\n", "
")); 41 | 42 | // response 43 | ModelAndView mv = new ModelAndView(); 44 | if (isJson) { 45 | try { 46 | response.setContentType("application/json;charset=utf-8"); 47 | response.getWriter().print(JacksonUtil.writeValueAsString(errorResult)); 48 | } catch (IOException e) { 49 | logger.error(e.getMessage(), e); 50 | } 51 | return mv; 52 | } else { 53 | 54 | mv.addObject("exceptionMsg", errorResult.getMsg()); 55 | mv.setViewName("/common/common.exception"); 56 | return mv; 57 | } 58 | } 59 | 60 | } -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/conf/XxlJobDynamicSchedulerConfig.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.conf; 2 | 3 | import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler; 4 | import org.quartz.Scheduler; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.core.io.ClassPathResource; 8 | import org.springframework.scheduling.quartz.SchedulerFactoryBean; 9 | 10 | import javax.sql.DataSource; 11 | 12 | /** 13 | * @author xuxueli 2018-10-28 00:18:17 14 | */ 15 | @Configuration 16 | public class XxlJobDynamicSchedulerConfig { 17 | 18 | @Bean 19 | public SchedulerFactoryBean getSchedulerFactoryBean(DataSource dataSource){ 20 | 21 | SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean(); 22 | schedulerFactory.setDataSource(dataSource); 23 | schedulerFactory.setAutoStartup(true); // 自动启动 24 | schedulerFactory.setStartupDelay(20); // 延时启动,应用启动成功后在启动 25 | schedulerFactory.setOverwriteExistingJobs(true); // 覆盖DB中JOB:true、以数据库中已经存在的为准:false 26 | schedulerFactory.setApplicationContextSchedulerContextKey("applicationContext"); 27 | schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties")); 28 | 29 | return schedulerFactory; 30 | } 31 | 32 | @Bean(initMethod = "start", destroyMethod = "destroy") 33 | public XxlJobDynamicScheduler getXxlJobDynamicScheduler(SchedulerFactoryBean schedulerFactory){ 34 | 35 | Scheduler scheduler = schedulerFactory.getScheduler(); 36 | 37 | XxlJobDynamicScheduler xxlJobDynamicScheduler = new XxlJobDynamicScheduler(); 38 | xxlJobDynamicScheduler.setScheduler(scheduler); 39 | 40 | return xxlJobDynamicScheduler; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/jobbean/RemoteHttpJobBean.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.jobbean; 2 | 3 | import com.xxl.job.admin.core.thread.JobTriggerPoolHelper; 4 | import com.xxl.job.admin.core.trigger.TriggerTypeEnum; 5 | import org.quartz.JobExecutionContext; 6 | import org.quartz.JobExecutionException; 7 | import org.quartz.JobKey; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.scheduling.quartz.QuartzJobBean; 11 | 12 | /** 13 | * http job bean 14 | * “@DisallowConcurrentExecution” diable concurrent, thread size can not be only one, better given more 15 | * @author xuxueli 2015-12-17 18:20:34 16 | */ 17 | //@DisallowConcurrentExecution 18 | public class RemoteHttpJobBean extends QuartzJobBean { 19 | private static Logger logger = LoggerFactory.getLogger(RemoteHttpJobBean.class); 20 | 21 | @Override 22 | protected void executeInternal(JobExecutionContext context) 23 | throws JobExecutionException { 24 | 25 | // load jobId 26 | JobKey jobKey = context.getTrigger().getJobKey(); 27 | Integer jobId = Integer.valueOf(jobKey.getName()); 28 | 29 | // trigger 30 | JobTriggerPoolHelper.trigger(jobId, TriggerTypeEnum.CRON, -1, null, null); 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobGroup.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by xuxueli on 16/9/30. 9 | */ 10 | public class XxlJobGroup { 11 | 12 | private int id; 13 | private String appName; 14 | private String title; 15 | private int order; 16 | private int addressType; // 执行器地址类型:0=自动注册、1=手动录入 17 | private String addressList; // 执行器地址列表,多地址逗号分隔(手动录入) 18 | 19 | // registry list 20 | private List registryList; // 执行器地址列表(系统注册) 21 | public List getRegistryList() { 22 | if (addressList!=null && addressList.trim().length()>0) { 23 | registryList = new ArrayList(Arrays.asList(addressList.split(","))); 24 | } 25 | return registryList; 26 | } 27 | 28 | public int getId() { 29 | return id; 30 | } 31 | 32 | public void setId(int id) { 33 | this.id = id; 34 | } 35 | 36 | public String getAppName() { 37 | return appName; 38 | } 39 | 40 | public void setAppName(String appName) { 41 | this.appName = appName; 42 | } 43 | 44 | public String getTitle() { 45 | return title; 46 | } 47 | 48 | public void setTitle(String title) { 49 | this.title = title; 50 | } 51 | 52 | public int getOrder() { 53 | return order; 54 | } 55 | 56 | public void setOrder(int order) { 57 | this.order = order; 58 | } 59 | 60 | public int getAddressType() { 61 | return addressType; 62 | } 63 | 64 | public void setAddressType(int addressType) { 65 | this.addressType = addressType; 66 | } 67 | 68 | public String getAddressList() { 69 | return addressList; 70 | } 71 | 72 | public void setAddressList(String addressList) { 73 | this.addressList = addressList; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobLogGlue.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.model; 2 | 3 | /** 4 | * xxl-job log for glue, used to track job code process 5 | * @author xuxueli 2016-5-19 17:57:46 6 | */ 7 | public class XxlJobLogGlue { 8 | 9 | private int id; 10 | private int jobId; // 任务主键ID 11 | private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum 12 | private String glueSource; 13 | private String glueRemark; 14 | private String addTime; 15 | private String updateTime; 16 | 17 | public int getId() { 18 | return id; 19 | } 20 | 21 | public void setId(int id) { 22 | this.id = id; 23 | } 24 | 25 | public int getJobId() { 26 | return jobId; 27 | } 28 | 29 | public void setJobId(int jobId) { 30 | this.jobId = jobId; 31 | } 32 | 33 | public String getGlueType() { 34 | return glueType; 35 | } 36 | 37 | public void setGlueType(String glueType) { 38 | this.glueType = glueType; 39 | } 40 | 41 | public String getGlueSource() { 42 | return glueSource; 43 | } 44 | 45 | public void setGlueSource(String glueSource) { 46 | this.glueSource = glueSource; 47 | } 48 | 49 | public String getGlueRemark() { 50 | return glueRemark; 51 | } 52 | 53 | public void setGlueRemark(String glueRemark) { 54 | this.glueRemark = glueRemark; 55 | } 56 | 57 | public String getAddTime() { 58 | return addTime; 59 | } 60 | 61 | public void setAddTime(String addTime) { 62 | this.addTime = addTime; 63 | } 64 | 65 | public String getUpdateTime() { 66 | return updateTime; 67 | } 68 | 69 | public void setUpdateTime(String updateTime) { 70 | this.updateTime = updateTime; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobRegistry.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.model; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * Created by xuxueli on 16/9/30. 7 | */ 8 | public class XxlJobRegistry { 9 | 10 | private int id; 11 | private String registryGroup; 12 | private String registryKey; 13 | private String registryValue; 14 | private Date updateTime; 15 | 16 | public int getId() { 17 | return id; 18 | } 19 | 20 | public void setId(int id) { 21 | this.id = id; 22 | } 23 | 24 | public String getRegistryGroup() { 25 | return registryGroup; 26 | } 27 | 28 | public void setRegistryGroup(String registryGroup) { 29 | this.registryGroup = registryGroup; 30 | } 31 | 32 | public String getRegistryKey() { 33 | return registryKey; 34 | } 35 | 36 | public void setRegistryKey(String registryKey) { 37 | this.registryKey = registryKey; 38 | } 39 | 40 | public String getRegistryValue() { 41 | return registryValue; 42 | } 43 | 44 | public void setRegistryValue(String registryValue) { 45 | this.registryValue = registryValue; 46 | } 47 | 48 | public Date getUpdateTime() { 49 | return updateTime; 50 | } 51 | 52 | public void setUpdateTime(Date updateTime) { 53 | this.updateTime = updateTime; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/quartz/XxlJobThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.quartz; 2 | 3 | import org.quartz.SchedulerConfigException; 4 | import org.quartz.spi.ThreadPool; 5 | 6 | /** 7 | * single thread pool, for async trigger 8 | * 9 | * @author xuxueli 2019-03-06 10 | */ 11 | public class XxlJobThreadPool implements ThreadPool { 12 | 13 | @Override 14 | public boolean runInThread(Runnable runnable) { 15 | 16 | // async run 17 | runnable.run(); 18 | return true; 19 | 20 | //return false; 21 | } 22 | 23 | @Override 24 | public int blockForAvailableThreads() { 25 | return 1; 26 | } 27 | 28 | @Override 29 | public void initialize() throws SchedulerConfigException { 30 | 31 | } 32 | 33 | @Override 34 | public void shutdown(boolean waitForJobsToComplete) { 35 | 36 | } 37 | 38 | @Override 39 | public int getPoolSize() { 40 | return 1; 41 | } 42 | 43 | @Override 44 | public void setInstanceId(String schedInstId) { 45 | 46 | } 47 | 48 | @Override 49 | public void setInstanceName(String schedName) { 50 | 51 | } 52 | 53 | // support 54 | public void setThreadCount(int count) { 55 | // 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouteStrategyEnum.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route; 2 | 3 | import com.xxl.job.admin.core.route.strategy.*; 4 | import com.xxl.job.admin.core.util.I18nUtil; 5 | 6 | /** 7 | * Created by xuxueli on 17/3/10. 8 | */ 9 | public enum ExecutorRouteStrategyEnum { 10 | 11 | FIRST(I18nUtil.getString("jobconf_route_first"), new ExecutorRouteFirst()), 12 | LAST(I18nUtil.getString("jobconf_route_last"), new ExecutorRouteLast()), 13 | ROUND(I18nUtil.getString("jobconf_route_round"), new ExecutorRouteRound()), 14 | RANDOM(I18nUtil.getString("jobconf_route_random"), new ExecutorRouteRandom()), 15 | CONSISTENT_HASH(I18nUtil.getString("jobconf_route_consistenthash"), new ExecutorRouteConsistentHash()), 16 | LEAST_FREQUENTLY_USED(I18nUtil.getString("jobconf_route_lfu"), new ExecutorRouteLFU()), 17 | LEAST_RECENTLY_USED(I18nUtil.getString("jobconf_route_lru"), new ExecutorRouteLRU()), 18 | FAILOVER(I18nUtil.getString("jobconf_route_failover"), new ExecutorRouteFailover()), 19 | BUSYOVER(I18nUtil.getString("jobconf_route_busyover"), new ExecutorRouteBusyover()), 20 | SHARDING_BROADCAST(I18nUtil.getString("jobconf_route_shard"), null); 21 | 22 | ExecutorRouteStrategyEnum(String title, ExecutorRouter router) { 23 | this.title = title; 24 | this.router = router; 25 | } 26 | 27 | private String title; 28 | private ExecutorRouter router; 29 | 30 | public String getTitle() { 31 | return title; 32 | } 33 | public ExecutorRouter getRouter() { 34 | return router; 35 | } 36 | 37 | public static ExecutorRouteStrategyEnum match(String name, ExecutorRouteStrategyEnum defaultItem){ 38 | if (name != null) { 39 | for (ExecutorRouteStrategyEnum item: ExecutorRouteStrategyEnum.values()) { 40 | if (item.name().equals(name)) { 41 | return item; 42 | } 43 | } 44 | } 45 | return defaultItem; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/ExecutorRouter.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route; 2 | 3 | import com.xxl.job.core.biz.model.ReturnT; 4 | import com.xxl.job.core.biz.model.TriggerParam; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by xuxueli on 17/3/10. 12 | */ 13 | public abstract class ExecutorRouter { 14 | protected static Logger logger = LoggerFactory.getLogger(ExecutorRouter.class); 15 | 16 | /** 17 | * route address 18 | * 19 | * @param addressList 20 | * @return ReturnT.content=address 21 | */ 22 | public abstract ReturnT route(TriggerParam triggerParam, List addressList); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteBusyover.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler; 5 | import com.xxl.job.admin.core.util.I18nUtil; 6 | import com.xxl.job.core.biz.ExecutorBiz; 7 | import com.xxl.job.core.biz.model.ReturnT; 8 | import com.xxl.job.core.biz.model.TriggerParam; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by xuxueli on 17/3/10. 14 | */ 15 | public class ExecutorRouteBusyover extends ExecutorRouter { 16 | 17 | @Override 18 | public ReturnT route(TriggerParam triggerParam, List addressList) { 19 | StringBuffer idleBeatResultSB = new StringBuffer(); 20 | for (String address : addressList) { 21 | // beat 22 | ReturnT idleBeatResult = null; 23 | try { 24 | ExecutorBiz executorBiz = XxlJobDynamicScheduler.getExecutorBiz(address); 25 | idleBeatResult = executorBiz.idleBeat(triggerParam.getJobId()); 26 | } catch (Exception e) { 27 | logger.error(e.getMessage(), e); 28 | idleBeatResult = new ReturnT(ReturnT.FAIL_CODE, ""+e ); 29 | } 30 | idleBeatResultSB.append( (idleBeatResultSB.length()>0)?"

":"") 31 | .append(I18nUtil.getString("jobconf_idleBeat") + ":") 32 | .append("
address:").append(address) 33 | .append("
code:").append(idleBeatResult.getCode()) 34 | .append("
msg:").append(idleBeatResult.getMsg()); 35 | 36 | // beat success 37 | if (idleBeatResult.getCode() == ReturnT.SUCCESS_CODE) { 38 | idleBeatResult.setMsg(idleBeatResultSB.toString()); 39 | idleBeatResult.setContent(address); 40 | return idleBeatResult; 41 | } 42 | } 43 | 44 | return new ReturnT(ReturnT.FAIL_CODE, idleBeatResultSB.toString()); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteFailover.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler; 5 | import com.xxl.job.admin.core.util.I18nUtil; 6 | import com.xxl.job.core.biz.ExecutorBiz; 7 | import com.xxl.job.core.biz.model.ReturnT; 8 | import com.xxl.job.core.biz.model.TriggerParam; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by xuxueli on 17/3/10. 14 | */ 15 | public class ExecutorRouteFailover extends ExecutorRouter { 16 | 17 | @Override 18 | public ReturnT route(TriggerParam triggerParam, List addressList) { 19 | 20 | StringBuffer beatResultSB = new StringBuffer(); 21 | for (String address : addressList) { 22 | // beat 23 | ReturnT beatResult = null; 24 | try { 25 | ExecutorBiz executorBiz = XxlJobDynamicScheduler.getExecutorBiz(address); 26 | beatResult = executorBiz.beat(); 27 | } catch (Exception e) { 28 | logger.error(e.getMessage(), e); 29 | beatResult = new ReturnT(ReturnT.FAIL_CODE, ""+e ); 30 | } 31 | beatResultSB.append( (beatResultSB.length()>0)?"

":"") 32 | .append(I18nUtil.getString("jobconf_beat") + ":") 33 | .append("
address:").append(address) 34 | .append("
code:").append(beatResult.getCode()) 35 | .append("
msg:").append(beatResult.getMsg()); 36 | 37 | // beat success 38 | if (beatResult.getCode() == ReturnT.SUCCESS_CODE) { 39 | 40 | beatResult.setMsg(beatResultSB.toString()); 41 | beatResult.setContent(address); 42 | return beatResult; 43 | } 44 | } 45 | return new ReturnT(ReturnT.FAIL_CODE, beatResultSB.toString()); 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteFirst.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by xuxueli on 17/3/10. 11 | */ 12 | public class ExecutorRouteFirst extends ExecutorRouter { 13 | 14 | @Override 15 | public ReturnT route(TriggerParam triggerParam, List addressList){ 16 | return new ReturnT(addressList.get(0)); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteLast.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by xuxueli on 17/3/10. 11 | */ 12 | public class ExecutorRouteLast extends ExecutorRouter { 13 | 14 | @Override 15 | public ReturnT route(TriggerParam triggerParam, List addressList) { 16 | return new ReturnT(addressList.get(addressList.size()-1)); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteRandom.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.List; 8 | import java.util.Random; 9 | 10 | /** 11 | * Created by xuxueli on 17/3/10. 12 | */ 13 | public class ExecutorRouteRandom extends ExecutorRouter { 14 | 15 | private static Random localRandom = new Random(); 16 | 17 | @Override 18 | public ReturnT route(TriggerParam triggerParam, List addressList) { 19 | String address = addressList.get(localRandom.nextInt(addressList.size())); 20 | return new ReturnT(address); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/route/strategy/ExecutorRouteRound.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.route.strategy; 2 | 3 | import com.xxl.job.admin.core.route.ExecutorRouter; 4 | import com.xxl.job.core.biz.model.ReturnT; 5 | import com.xxl.job.core.biz.model.TriggerParam; 6 | 7 | import java.util.List; 8 | import java.util.Random; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | /** 12 | * Created by xuxueli on 17/3/10. 13 | */ 14 | public class ExecutorRouteRound extends ExecutorRouter { 15 | 16 | private static ConcurrentHashMap routeCountEachJob = new ConcurrentHashMap(); 17 | private static long CACHE_VALID_TIME = 0; 18 | private static int count(int jobId) { 19 | // cache clear 20 | if (System.currentTimeMillis() > CACHE_VALID_TIME) { 21 | routeCountEachJob.clear(); 22 | CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24; 23 | } 24 | 25 | // count++ 26 | Integer count = routeCountEachJob.get(jobId); 27 | count = (count==null || count>1000000)?(new Random().nextInt(100)):++count; // 初始化时主动Random一次,缓解首次压力 28 | routeCountEachJob.put(jobId, count); 29 | return count; 30 | } 31 | 32 | @Override 33 | public ReturnT route(TriggerParam triggerParam, List addressList) { 34 | String address = addressList.get(count(triggerParam.getJobId())%addressList.size()); 35 | return new ReturnT(address); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/trigger/TriggerTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.trigger; 2 | 3 | import com.xxl.job.admin.core.util.I18nUtil; 4 | 5 | /** 6 | * trigger type enum 7 | * 8 | * @author xuxueli 2018-09-16 04:56:41 9 | */ 10 | public enum TriggerTypeEnum { 11 | 12 | MANUAL(I18nUtil.getString("jobconf_trigger_type_manual")), 13 | CRON(I18nUtil.getString("jobconf_trigger_type_cron")), 14 | RETRY(I18nUtil.getString("jobconf_trigger_type_retry")), 15 | PARENT(I18nUtil.getString("jobconf_trigger_type_parent")), 16 | API(I18nUtil.getString("jobconf_trigger_type_api")); 17 | 18 | private TriggerTypeEnum(String title){ 19 | this.title = title; 20 | } 21 | private String title; 22 | public String getTitle() { 23 | return title; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/FtlUtil.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.core.util; 2 | 3 | import freemarker.ext.beans.BeansWrapper; 4 | import freemarker.ext.beans.BeansWrapperBuilder; 5 | import freemarker.template.Configuration; 6 | import freemarker.template.TemplateHashModel; 7 | 8 | /** 9 | * ftl util 10 | * 11 | * @author xuxueli 2018-01-17 20:37:48 12 | */ 13 | public class FtlUtil { 14 | 15 | private static BeansWrapper wrapper = new BeansWrapperBuilder(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS).build(); //BeansWrapper.getDefaultInstance(); 16 | 17 | public static TemplateHashModel generateStaticModel(String packageName) { 18 | try { 19 | TemplateHashModel staticModels = wrapper.getStaticModels(); 20 | TemplateHashModel fileStatics = (TemplateHashModel) staticModels.get(packageName); 21 | return fileStatics; 22 | } catch (Exception e) { 23 | e.printStackTrace(); 24 | } 25 | return null; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobGroupDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobGroup; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by xuxueli on 16/9/30. 11 | */ 12 | @Mapper 13 | public interface XxlJobGroupDao { 14 | 15 | public List findAll(); 16 | 17 | public List findByAddressType(@Param("addressType") int addressType); 18 | 19 | public int save(XxlJobGroup xxlJobGroup); 20 | 21 | public int update(XxlJobGroup xxlJobGroup); 22 | 23 | public int remove(@Param("id") int id); 24 | 25 | public XxlJobGroup load(@Param("id") int id); 26 | } 27 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobInfoDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobInfo; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | 10 | /** 11 | * job info 12 | * @author xuxueli 2016-1-12 18:03:45 13 | */ 14 | @Mapper 15 | public interface XxlJobInfoDao { 16 | 17 | public List pageList(@Param("offset") int offset, 18 | @Param("pagesize") int pagesize, 19 | @Param("jobGroup") int jobGroup, 20 | @Param("jobDesc") String jobDesc, 21 | @Param("executorHandler") String executorHandler); 22 | public int pageListCount(@Param("offset") int offset, 23 | @Param("pagesize") int pagesize, 24 | @Param("jobGroup") int jobGroup, 25 | @Param("jobDesc") String jobDesc, 26 | @Param("executorHandler") String executorHandler); 27 | 28 | public int save(XxlJobInfo info); 29 | 30 | public XxlJobInfo loadById(@Param("id") int id); 31 | 32 | public int update(XxlJobInfo item); 33 | 34 | public int delete(@Param("id") int id); 35 | 36 | public List getJobsByGroup(@Param("jobGroup") int jobGroup); 37 | 38 | public int findAllCount(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobLogGlueDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobLogGlue; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * job log for glue 11 | * @author xuxueli 2016-5-19 18:04:56 12 | */ 13 | @Mapper 14 | public interface XxlJobLogGlueDao { 15 | 16 | public int save(XxlJobLogGlue xxlJobLogGlue); 17 | 18 | public List findByJobId(@Param("jobId") int jobId); 19 | 20 | public int removeOld(@Param("jobId") int jobId, @Param("limit") int limit); 21 | 22 | public int deleteByJobId(@Param("jobId") int jobId); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/dao/XxlJobRegistryDao.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.dao; 2 | 3 | import com.xxl.job.admin.core.model.XxlJobRegistry; 4 | import org.apache.ibatis.annotations.Mapper; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by xuxueli on 16/9/30. 11 | */ 12 | @Mapper 13 | public interface XxlJobRegistryDao { 14 | 15 | public int removeDead(@Param("timeout") int timeout); 16 | 17 | public List findAll(@Param("timeout") int timeout); 18 | 19 | public int registryUpdate(@Param("registryGroup") String registryGroup, 20 | @Param("registryKey") String registryKey, 21 | @Param("registryValue") String registryValue); 22 | 23 | public int registrySave(@Param("registryGroup") String registryGroup, 24 | @Param("registryKey") String registryKey, 25 | @Param("registryValue") String registryValue); 26 | 27 | public int registryDelete(@Param("registryGroup") String registGroup, 28 | @Param("registryKey") String registryKey, 29 | @Param("registryValue") String registryValue); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/java/com/xxl/job/admin/service/XxlJobService.java: -------------------------------------------------------------------------------- 1 | package com.xxl.job.admin.service; 2 | 3 | 4 | import com.xxl.job.admin.core.model.XxlJobInfo; 5 | import com.xxl.job.core.biz.model.ReturnT; 6 | 7 | import java.util.Date; 8 | import java.util.Map; 9 | 10 | /** 11 | * core job action for xxl-job 12 | * 13 | * @author xuxueli 2016-5-28 15:30:33 14 | */ 15 | public interface XxlJobService { 16 | 17 | /** 18 | * page list 19 | * 20 | * @param start 21 | * @param length 22 | * @param jobGroup 23 | * @param jobDesc 24 | * @param executorHandler 25 | * @param filterTime 26 | * @return 27 | */ 28 | public Map pageList(int start, int length, int jobGroup, String jobDesc, String executorHandler, String filterTime); 29 | 30 | /** 31 | * add job, default quartz stop 32 | * 33 | * @param jobInfo 34 | * @return 35 | */ 36 | public ReturnT add(XxlJobInfo jobInfo); 37 | 38 | /** 39 | * update job, update quartz-cron if started 40 | * 41 | * @param jobInfo 42 | * @return 43 | */ 44 | public ReturnT update(XxlJobInfo jobInfo); 45 | 46 | /** 47 | * remove job, unbind quartz 48 | * 49 | * @param id 50 | * @return 51 | */ 52 | public ReturnT remove(int id); 53 | 54 | /** 55 | * start job, bind quartz 56 | * 57 | * @param id 58 | * @return 59 | */ 60 | public ReturnT start(int id); 61 | 62 | /** 63 | * stop job, unbind quartz 64 | * 65 | * @param id 66 | * @return 67 | */ 68 | public ReturnT stop(int id); 69 | 70 | /** 71 | * dashboard info 72 | * 73 | * @return 74 | */ 75 | public Map dashboardInfo(); 76 | 77 | /** 78 | * chart info 79 | * 80 | * @param startDate 81 | * @param endDate 82 | * @return 83 | */ 84 | public ReturnT> chartInfo(Date startDate, Date endDate); 85 | 86 | } 87 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | ### web 2 | server.port=8080 3 | server.context-path=/xxl-job-admin 4 | 5 | ### resources 6 | spring.mvc.static-path-pattern=/static/** 7 | spring.resources.static-locations=classpath:/static/ 8 | 9 | ### freemarker 10 | spring.freemarker.templateLoaderPath=classpath:/templates/ 11 | spring.freemarker.suffix=.ftl 12 | spring.freemarker.charset=UTF-8 13 | spring.freemarker.request-context-attribute=request 14 | spring.freemarker.settings.number_format=0.########## 15 | 16 | ### mybatis 17 | mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml 18 | 19 | ### xxl-job, datasource 20 | spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl-job?Unicode=true&characterEncoding=UTF-8 21 | spring.datasource.username=root 22 | spring.datasource.password=root 23 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 24 | 25 | spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource 26 | spring.datasource.tomcat.max-wait=10000 27 | spring.datasource.tomcat.max-active=30 28 | spring.datasource.tomcat.test-on-borrow=true 29 | spring.datasource.tomcat.validation-query=SELECT 1 30 | spring.datasource.tomcat.validation-interval=30000 31 | 32 | ### xxl-job email 33 | spring.mail.host=smtp.qq.com 34 | spring.mail.port=25 35 | spring.mail.username=xxx@qq.com 36 | spring.mail.password=xxx 37 | spring.mail.properties.mail.smtp.auth=true 38 | spring.mail.properties.mail.smtp.starttls.enable=true 39 | spring.mail.properties.mail.smtp.starttls.required=true 40 | 41 | 42 | ### xxl-job login 43 | xxl.job.login.username=admin 44 | xxl.job.login.password=123456 45 | 46 | ### xxl-job, access token 47 | xxl.job.accessToken= 48 | 49 | ### xxl-job, i18n (default empty as chinese, "en" as english) 50 | xxl.job.i18n= 51 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logback 5 | 6 | 7 | 8 | 9 | %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n 10 | 11 | 12 | 13 | 14 | ${log.path} 15 | 16 | ${log.path}.%d{yyyy-MM-dd}.zip 17 | 18 | 19 | %date %level [%thread] %logger{36} [%file : %line] %msg%n 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobGroupMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | t.id, 17 | t.app_name, 18 | t.title, 19 | t.`order`, 20 | t.address_type, 21 | t.address_list 22 | 23 | 24 | 29 | 30 | 36 | 37 | 38 | INSERT INTO XXL_JOB_QRTZ_TRIGGER_GROUP ( `app_name`, `title`, `order`, `address_type`, `address_list`) 39 | values ( #{appName}, #{title}, #{order}, #{addressType}, #{addressList}); 40 | 41 | 42 | 43 | UPDATE XXL_JOB_QRTZ_TRIGGER_GROUP 44 | SET `app_name` = #{appName}, 45 | `title` = #{title}, 46 | `order` = #{order}, 47 | `address_type` = #{addressType}, 48 | `address_list` = #{addressList} 49 | WHERE id = #{id} 50 | 51 | 52 | 53 | DELETE FROM XXL_JOB_QRTZ_TRIGGER_GROUP 54 | WHERE id = #{id} 55 | 56 | 57 | 62 | 63 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogGlueMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | t.id, 18 | t.job_id, 19 | t.glue_type, 20 | t.glue_source, 21 | t.glue_remark, 22 | t.add_time, 23 | t.update_time 24 | 25 | 26 | 27 | INSERT INTO XXL_JOB_QRTZ_TRIGGER_LOGGLUE ( 28 | `job_id`, 29 | `glue_type`, 30 | `glue_source`, 31 | `glue_remark`, 32 | `add_time`, 33 | `update_time` 34 | ) VALUES ( 35 | #{jobId}, 36 | #{glueType}, 37 | #{glueSource}, 38 | #{glueRemark}, 39 | now(), 40 | now() 41 | ); 42 | 45 | 46 | 47 | 53 | 54 | 55 | DELETE FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE 56 | WHERE id NOT in( 57 | SELECT id FROM( 58 | SELECT id FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE 59 | WHERE `job_id` = #{jobId} 60 | ORDER BY update_time desc 61 | LIMIT 0, #{limit} 62 | ) t1 63 | ) AND `job_id` = #{jobId} 64 | 65 | 66 | 67 | DELETE FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE 68 | WHERE `job_id` = #{jobId} 69 | 70 | 71 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobRegistryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | t.id, 16 | t.registry_group, 17 | t.registry_key, 18 | t.registry_value, 19 | t.update_time 20 | 21 | 22 | 23 | DELETE FROM XXL_JOB_QRTZ_TRIGGER_REGISTRY 24 | WHERE update_time DATE_ADD(NOW(),INTERVAL -#{timeout} SECOND) 25 | 26 | 27 | 32 | 33 | 34 | UPDATE XXL_JOB_QRTZ_TRIGGER_REGISTRY 35 | SET `update_time` = NOW() 36 | WHERE `registry_group` = #{registryGroup} 37 | AND `registry_key` = #{registryKey} 38 | AND `registry_value` = #{registryValue} 39 | 40 | 41 | 42 | INSERT INTO XXL_JOB_QRTZ_TRIGGER_REGISTRY( `registry_group` , `registry_key` , `registry_value`, `update_time`) 43 | VALUES( #{registryGroup} , #{registryKey} , #{registryValue}, NOW()) 44 | 45 | 46 | 47 | DELETE FROM XXL_JOB_QRTZ_TRIGGER_REGISTRY 48 | WHERE registry_group = #{registryGroup} 49 | AND registry_key = #{registryKey} 50 | AND registry_value = #{registryValue} 51 | 52 | 53 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/quartz.properties: -------------------------------------------------------------------------------- 1 | # Default Properties file for use by StdSchedulerFactory 2 | # to create a Quartz Scheduler Instance, if a different 3 | # properties file is not explicitly specified. 4 | # 5 | 6 | org.quartz.scheduler.instanceName: DefaultQuartzScheduler 7 | org.quartz.scheduler.instanceId: AUTO 8 | org.quartz.scheduler.rmi.export: false 9 | org.quartz.scheduler.rmi.proxy: false 10 | org.quartz.scheduler.wrapJobExecutionInUserTransaction: false 11 | 12 | #org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool 13 | #org.quartz.threadPool.threadCount: 5 14 | #org.quartz.threadPool.threadPriority: 5 15 | #org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true 16 | 17 | org.quartz.jobStore.misfireThreshold: 60000 18 | org.quartz.jobStore.maxMisfiresToHandleAtATime: 1 19 | 20 | #org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore 21 | 22 | # for async trigger 23 | org.quartz.threadPool.class: com.xxl.job.admin.core.quartz.XxlJobThreadPool 24 | 25 | # for cluster 26 | org.quartz.jobStore.tablePrefix: XXL_JOB_QRTZ_ 27 | org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX 28 | org.quartz.jobStore.isClustered: true 29 | org.quartz.jobStore.clusterCheckinInterval: 5000 30 | -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.eot -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.ttf -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/Ionicons/fonts/ionicons.woff -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdh7732/spring-boot/5430767dafee84e6f0b68e7bc5873cb43d92562d/xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /xxl-job/xxl-job-admin/src/main/resources/static/adminlte/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | DataTables Bootstrap 3 integration 3 | ©2011-2015 SpryMedia Ltd - datatables.net/license 4 | */ 5 | (function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,d){a||(a=window);if(!d||!d.fn.dataTable)d=require("datatables.net")(a,d).$;return b(d,a,a.document)}:b(jQuery,window,document)})(function(b,a,d,m){var f=b.fn.dataTable;b.extend(!0,f.defaults,{dom:"<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'p>>",renderer:"bootstrap"});b.extend(f.ext.classes, 6 | {sWrapper:"dataTables_wrapper form-inline dt-bootstrap",sFilterInput:"form-control input-sm",sLengthSelect:"form-control input-sm",sProcessing:"dataTables_processing panel panel-default"});f.ext.renderer.pageButton.bootstrap=function(a,h,r,s,j,n){var o=new f.Api(a),t=a.oClasses,k=a.oLanguage.oPaginate,u=a.oLanguage.oAria.paginate||{},e,g,p=0,q=function(d,f){var l,h,i,c,m=function(a){a.preventDefault();!b(a.currentTarget).hasClass("disabled")&&o.page()!=a.data.action&&o.page(a.data.action).draw("page")}; 7 | l=0;for(h=f.length;l",{"class":t.sPageButton+" "+g,id:0===r&&"string"===typeof c?a.sTableId+"_"+c:null}).append(b("",{href:"#", 8 | "aria-controls":a.sTableId,"aria-label":u[c],"data-dt-idx":p,tabindex:a.iTabIndex}).html(e)).appendTo(d),a.oApi._fnBindAction(i,{action:c},m),p++)}},i;try{i=b(h).find(d.activeElement).data("dt-idx")}catch(v){}q(b(h).empty().html('