├── .gitignore ├── LICENSE ├── README.md ├── docker-compose.yml ├── im-ai ├── .gitignore ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── xy │ │ │ └── ai │ │ │ ├── ImAiApplication.java │ │ │ ├── config │ │ │ └── ChatConfig.java │ │ │ ├── controller │ │ │ └── ChatbotController.java │ │ │ └── utils │ │ │ └── TikaUtil.java │ └── resources │ │ ├── application-undertow.yml │ │ ├── application.yml │ │ ├── banner.txt │ │ ├── bootstrap.yml │ │ └── logback-plus.xml │ └── test │ └── java │ └── com │ └── xy │ └── ai │ └── ImAiApplicationTests.java ├── im-analysis ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── xy │ │ │ └── alysis │ │ │ ├── ImAnalysisApplication.java │ │ │ ├── controller │ │ │ └── HanLPController.java │ │ │ ├── service │ │ │ └── HanLPService.java │ │ │ └── utils │ │ │ ├── HanLPConversion.java │ │ │ ├── HanLPDependencyParser.java │ │ │ ├── HanLPKeyWord.java │ │ │ └── HanLPSegmenter.java │ └── resources │ │ ├── application-undertow.yml │ │ ├── application.yml │ │ ├── banner.txt │ │ ├── bootstrap.yml │ │ ├── hanlp.properties │ │ └── logback-plus.xml │ └── test │ └── java │ └── com │ ├── hankcs │ ├── book │ │ ├── ch01 │ │ │ └── HelloWord.java │ │ ├── ch02 │ │ │ ├── AhoCorasickDoubleArrayTrieSegmentation.java │ │ │ ├── AhoCorasickSegmentation.java │ │ │ ├── BinTrieBasedSegmentation.java │ │ │ ├── DemoAhoCorasickDoubleArrayTrieSegment.java │ │ │ ├── DemoDoubleArrayTrieSegment.java │ │ │ ├── DemoStopwords.java │ │ │ ├── DoubleArrayTrieBasedSegmentation.java │ │ │ ├── EvaluateCWS.java │ │ │ └── NaiveDictionaryBasedSegmentation.java │ │ ├── ch03 │ │ │ ├── DemoAdjustModel.java │ │ │ ├── DemoCorpusLoader.java │ │ │ ├── DemoCustomDictionary.java │ │ │ ├── DemoJapaneseSegment.java │ │ │ ├── DemoNgramSegment.java │ │ │ └── EvaluateBigram.java │ │ ├── ch04 │ │ │ └── CWS_HMM.java │ │ ├── ch05 │ │ │ ├── CheapFeatureClassifier.java │ │ │ ├── DemoPerceptronCWS.java │ │ │ ├── EvaluatePerceptronCWS.java │ │ │ ├── FeatureEngineering.java │ │ │ ├── NameGenderClassification.java │ │ │ ├── OnlineLearning.java │ │ │ └── RichFeatureClassifier.java │ │ ├── ch06 │ │ │ ├── CrfppTrainHanLPLoad.java │ │ │ └── EvaluateCRFCWS.java │ │ ├── ch07 │ │ │ ├── CustomCorpusPOS.java │ │ │ ├── CustomPOS.java │ │ │ └── EvaluatePOS.java │ │ ├── ch08 │ │ │ ├── DemoCRFNER.java │ │ │ ├── DemoCRFNERPlane.java │ │ │ ├── DemoHMMNER.java │ │ │ ├── DemoNRF.java │ │ │ ├── DemoNumEng.java │ │ │ ├── DemoPlane.java │ │ │ ├── DemoRoleTagNR.java │ │ │ ├── DemoRoleTagNS.java │ │ │ ├── DemoRoleTagNT.java │ │ │ └── DemoSPNER.java │ │ ├── ch09 │ │ │ ├── DemoExtractNewWord.java │ │ │ ├── DemoTFIDF.java │ │ │ └── DemoTermFrequency.java │ │ ├── ch10 │ │ │ ├── DemoTextClustering.java │ │ │ └── DemoTextClusteringFMeasure.java │ │ ├── ch11 │ │ │ ├── DemoLoadTextClassificationCorpus.java │ │ │ ├── DemoTextClassification.java │ │ │ └── DemoTextClassificationFMeasure.java │ │ ├── ch12 │ │ │ ├── DebugKBeamArcEagerDependencyParser.java │ │ │ ├── DemoTrainParser.java │ │ │ └── OpinionMining.java │ │ ├── ch13 │ │ │ ├── DemoNeuralParser.java │ │ │ └── DemoTrainWord2Vec.java │ │ └── package-info.java │ ├── demo │ │ ├── DemoAtFirstSight.java │ │ ├── DemoBasicTokenizer.java │ │ ├── DemoCRFLexicalAnalyzer.java │ │ ├── DemoChineseNameRecognition.java │ │ ├── DemoCustomDictionary.java │ │ ├── DemoCustomNature.java │ │ ├── DemoDependencyParser.java │ │ ├── DemoEvaluateCWS.java │ │ ├── DemoHighSpeedSegment.java │ │ ├── DemoIndexSegment.java │ │ ├── DemoJapaneseNameRecognition.java │ │ ├── DemoKeyword.java │ │ ├── DemoMultithreadingSegment.java │ │ ├── DemoNLPSegment.java │ │ ├── DemoNShortSegment.java │ │ ├── DemoNewWordDiscover.java │ │ ├── DemoNormalization.java │ │ ├── DemoNotionalTokenizer.java │ │ ├── DemoNumberAndQuantifierRecognition.java │ │ ├── DemoOccurrence.java │ │ ├── DemoOrganizationRecognition.java │ │ ├── DemoPerceptronLexicalAnalyzer.java │ │ ├── DemoPhraseExtractor.java │ │ ├── DemoPinyin.java │ │ ├── DemoPinyinToChinese.java │ │ ├── DemoPipeline.java │ │ ├── DemoPlaceRecognition.java │ │ ├── DemoPosTagging.java │ │ ├── DemoRewriteText.java │ │ ├── DemoSegment.java │ │ ├── DemoSentimentAnalysis.java │ │ ├── DemoStopWord.java │ │ ├── DemoSuggester.java │ │ ├── DemoSummary.java │ │ ├── DemoTextClassification.java │ │ ├── DemoTextClassificationFMeasure.java │ │ ├── DemoTextClustering.java │ │ ├── DemoTextClusteringFMeasure.java │ │ ├── DemoTokenizerConfig.java │ │ ├── DemoTraditionalChinese2SimplifiedChinese.java │ │ ├── DemoTraditionalChineseSegment.java │ │ ├── DemoTranslatedNameRecognition.java │ │ ├── DemoURLRecognition.java │ │ ├── DemoUseAhoCorasickDoubleArrayTrieSegment.java │ │ ├── DemoWord2Vec.java │ │ └── DemoWordDistance.java │ └── hanlp │ │ ├── HanLPTest.java │ │ ├── algorithm │ │ ├── EditDistanceTest.java │ │ ├── LongestCommonSubsequenceTest.java │ │ ├── LongestCommonSubstringTest.java │ │ ├── MaxHeapTest.java │ │ ├── ViterbiTest.java │ │ └── ahocorasick │ │ │ └── trie │ │ │ └── TrieTest.java │ │ ├── classification │ │ └── classifiers │ │ │ └── NaiveBayesClassifierTest.java │ │ ├── collection │ │ ├── AhoCorasick │ │ │ └── AhoCorasickDoubleArrayTrieTest.java │ │ ├── MDAG │ │ │ ├── MDAGMapTest.java │ │ │ └── MDAGSetTest.java │ │ ├── dartsclone │ │ │ └── DartMapTest.java │ │ └── trie │ │ │ ├── DoubleArrayTrieTest.java │ │ │ ├── bintrie │ │ │ ├── BinTrieParseTextTest.java │ │ │ └── BinTrieTest.java │ │ │ └── datrie │ │ │ ├── IntArrayListTest.java │ │ │ ├── MutableDoubleArrayTrieIntegerTest.java │ │ │ └── Utf8CharacterMappingTest.java │ │ ├── corpus │ │ ├── MSR.java │ │ ├── PKU.java │ │ ├── TestAdjustCoreDictionary.java │ │ ├── TestICWB.java │ │ ├── TestJianFanDictionaryMaker.java │ │ ├── TestMakeCompanyCorpus.java │ │ ├── TestMakePinYinDictionary.java │ │ ├── TestMakeTranslateName.java │ │ ├── TestNRDcitionaryMaker.java │ │ ├── TestNSDictionaryMaker.java │ │ ├── TestNTDcitionaryMaker.java │ │ ├── TestNatureDictionaryMaker.java │ │ ├── TestPinyinGuesser.java │ │ ├── ZZGenerateNR.java │ │ ├── ZZGenerateNature.java │ │ ├── dependency │ │ │ └── CoNll │ │ │ │ └── CoNLLLoaderTest.java │ │ ├── dictionary │ │ │ ├── DictionaryMakerTest.java │ │ │ ├── TMDictionaryMakerTest.java │ │ │ └── item │ │ │ │ └── ItemTest.java │ │ ├── document │ │ │ ├── CorpusLoaderTest.java │ │ │ ├── DocumentTest.java │ │ │ └── sentence │ │ │ │ ├── SentenceTest.java │ │ │ │ └── word │ │ │ │ └── WordTest.java │ │ ├── io │ │ │ ├── ByteArrayTest.java │ │ │ ├── IIOAdapterTest.java │ │ │ └── IOUtilTest.java │ │ ├── synonym │ │ │ └── SynonymTest.java │ │ └── tag │ │ │ └── NatureTest.java │ │ ├── dependency │ │ ├── MaxEntDependencyParserTest.java │ │ └── perceptron │ │ │ └── parser │ │ │ └── KBeamArcEagerDependencyParserTest.java │ │ ├── dictionary │ │ ├── CoreBiGramTableDictionaryTest.java │ │ ├── CustomDictionaryTest.java │ │ ├── SimplifyNGramDictionary.java │ │ ├── SuffixDictionaryTest.java │ │ ├── other │ │ │ ├── CharTableTest.java │ │ │ ├── CharTypeTest.java │ │ │ └── PartOfSpeechTagDictionaryTest.java │ │ ├── py │ │ │ └── PinyinDictionaryTest.java │ │ ├── stopword │ │ │ └── CoreStopWordDictionaryTest.java │ │ └── ts │ │ │ └── TraditionalChineseDictionaryTest.java │ │ ├── mining │ │ ├── cluster │ │ │ └── ClusterAnalyzerTest.java │ │ ├── word │ │ │ ├── TermFrequencyCounterTest.java │ │ │ └── TfIdfCounterTest.java │ │ └── word2vec │ │ │ └── VectorsReaderTest.java │ │ ├── model │ │ ├── bigram │ │ │ └── BigramDependencyModelTest.java │ │ ├── crf │ │ │ ├── CRFLexicalAnalyzerTest.java │ │ │ ├── CRFModelTest.java │ │ │ ├── CRFNERecognizerTest.java │ │ │ ├── CRFPOSTaggerTest.java │ │ │ ├── CRFSegmenterTest.java │ │ │ └── LogLinearModelTest.java │ │ ├── hmm │ │ │ ├── FirstOrderHiddenMarkovModelTest.java │ │ │ ├── HMMLexicalAnalyzerTest.java │ │ │ ├── HMMPOSTaggerTest.java │ │ │ ├── HMMSegmenterTest.java │ │ │ └── SecondOrderHiddenMarkovModelTest.java │ │ ├── perceptron │ │ │ ├── CWSTrainerTest.java │ │ │ ├── Config.java │ │ │ ├── DemoTrainCWS.java │ │ │ ├── DemoTrainNER.java │ │ │ ├── DemoTrainPOS.java │ │ │ ├── NERTrainerTest.java │ │ │ ├── POSTrainerTest.java │ │ │ ├── PerceptronLexicalAnalyzerTest.java │ │ │ ├── PerceptronNERecognizerTest.java │ │ │ ├── PerceptronNameGenderClassifierTest.java │ │ │ ├── PerceptronPOSTaggerTest.java │ │ │ ├── PerceptronSegmenterTest.java │ │ │ ├── PerceptronTaggerTest.java │ │ │ ├── corpus │ │ │ │ └── ConvertPKU.java │ │ │ ├── feature │ │ │ │ └── ImmutableFeatureMDatMapTest.java │ │ │ ├── model │ │ │ │ └── LinearModelTest.java │ │ │ └── utility │ │ │ │ ├── IOUtilityTest.java │ │ │ │ └── UtilityTest.java │ │ └── trigram │ │ │ └── CharacterBasedGenerativeModelTest.java │ │ ├── recognition │ │ ├── ns │ │ │ └── PlaceRecognitionTest.java │ │ └── nt │ │ │ └── OrganizationRecognitionTest.java │ │ ├── seg │ │ ├── Dijkstra │ │ │ └── DijkstraSegmentTest.java │ │ ├── NShort │ │ │ └── NShortSegmentTest.java │ │ ├── Other │ │ │ ├── AhoCorasickDoubleArrayTrieSegmentTest.java │ │ │ └── DoubleArrayTrieSegmentTest.java │ │ ├── SegmentTest.java │ │ ├── SegmentTestCase.java │ │ └── common │ │ │ └── CWSEvaluatorTest.java │ │ ├── suggest │ │ ├── ISuggesterTest.java │ │ └── scorer │ │ │ └── pinyin │ │ │ └── PinyinKeyTest.java │ │ ├── summary │ │ └── TextRankSentenceTest.java │ │ ├── tokenizer │ │ ├── URLTokenizerTest.java │ │ ├── lexical │ │ │ └── AbstractLexicalAnalyzerTest.java │ │ └── pipe │ │ │ └── SegmentPipelineTest.java │ │ └── utility │ │ ├── MathUtilityTest.java │ │ ├── SentencesUtilTest.java │ │ ├── TestUtility.java │ │ └── TextUtilityTest.java │ └── xy │ └── alysis │ └── ImAnalysisApplicationTests.java ├── im-auth ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── xy │ │ │ └── auth │ │ │ ├── ImAuthApplication.java │ │ │ ├── annotations │ │ │ └── count │ │ │ │ ├── TakeCount.java │ │ │ │ └── TakeCountAspect.java │ │ │ ├── config │ │ │ ├── CorsConfig.java │ │ │ ├── Knife4jConfig.java │ │ │ ├── QRConfig.java │ │ │ ├── RedisConfig.java │ │ │ ├── ThreadPoolConfig.java │ │ │ └── WebConfig.java │ │ │ ├── constant │ │ │ └── QrcodeConstant.java │ │ │ ├── controller │ │ │ └── AuthController.java │ │ │ ├── domain │ │ │ ├── LoginRequest.java │ │ │ ├── dto │ │ │ │ ├── ImUserDataDto.java │ │ │ │ └── ImUserDto.java │ │ │ └── vo │ │ │ │ └── UserVo.java │ │ │ ├── mapper │ │ │ ├── ImUserDataMapper.java │ │ │ └── ImUserMapper.java │ │ │ ├── response │ │ │ ├── IResult.java │ │ │ ├── ResponseNotIntercept.java │ │ │ ├── Result.java │ │ │ ├── ResultCode.java │ │ │ ├── ResultEnum.java │ │ │ └── handler │ │ │ │ └── GlobalHandler.java │ │ │ ├── security │ │ │ ├── CustomAuthenticationEntryPoint.java │ │ │ ├── RSAKeyProperties.java │ │ │ ├── SecurityProperties.java │ │ │ ├── config │ │ │ │ ├── PasswordEncoderConfig.java │ │ │ │ └── WebSecurityConfig.java │ │ │ ├── exception │ │ │ │ └── AuthenticationFailException.java │ │ │ ├── filter │ │ │ │ └── TokenAuthenticationFilter.java │ │ │ ├── handle │ │ │ │ ├── LoginAccessDefineHandler.java │ │ │ │ └── LoginAuthenticationHandler.java │ │ │ ├── provider │ │ │ │ ├── MobileAuthenticationProvider.java │ │ │ │ ├── QrScanAuthenticationProvider.java │ │ │ │ └── UsernamePasswordAuthenticationProvider.java │ │ │ └── token │ │ │ │ ├── MobileAuthenticationToken.java │ │ │ │ ├── QrScanAuthenticationToken.java │ │ │ │ └── UserAuthenticationToken.java │ │ │ ├── service │ │ │ ├── ImUserService.java │ │ │ ├── QrCodeService.java │ │ │ ├── SmsService.java │ │ │ └── impl │ │ │ │ ├── ImUserServiceImpl.java │ │ │ │ ├── QrCodeServiceImpl.java │ │ │ │ └── SmsServiceImpl.java │ │ │ └── utils │ │ │ ├── JsonUtil.java │ │ │ ├── RSAUtil.java │ │ │ ├── RedisUtil.java │ │ │ └── ResponseUtils.java │ └── resources │ │ ├── application-swagger.yml │ │ ├── application-undertow.yml │ │ ├── application.yml │ │ ├── banner.txt │ │ ├── bootstrap.yml │ │ ├── logback-plus.xml │ │ └── mapper │ │ ├── ImUserDataMapper.xml │ │ └── ImUserMapper.xml │ └── test │ └── java │ └── com │ └── xy │ └── auth │ └── ImAuthApplicationTests.java ├── im-common ├── im-core │ ├── .gitignore │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── xy │ │ └── imcore │ │ ├── constants │ │ └── Constant.java │ │ ├── enums │ │ ├── IMStatus.java │ │ ├── IMemberStatus.java │ │ ├── IMessageContentType.java │ │ ├── IMessageReadStatus.java │ │ ├── IMessageSendStatus.java │ │ └── IMessageType.java │ │ ├── model │ │ ├── IMGroupMessageDto.java │ │ ├── IMRegisterUserDto.java │ │ ├── IMSingleMessageDto.java │ │ ├── IMVideoMessageDto.java │ │ ├── IMWsConnMessage.java │ │ ├── IMessageDto.java │ │ └── IMessageWrap.java │ │ └── utils │ │ ├── JwtUtil.java │ │ └── StringUtils.java └── pom.xml ├── im-connect ├── pom.xml ├── src │ └── main │ │ ├── java │ │ └── com │ │ │ └── xy │ │ │ └── connect │ │ │ ├── ApplicationBootstrap.java │ │ │ ├── ImConnectApplication.java │ │ │ ├── config │ │ │ ├── ConfigCenter.java │ │ │ ├── IMNacosConfig.java │ │ │ ├── IMNettyConfig.java │ │ │ ├── IMRabbitMQConfig.java │ │ │ ├── IMRedisConfig.java │ │ │ ├── LogConstant.java │ │ │ └── loader │ │ │ │ └── YamlConfigLoader.java │ │ │ ├── message │ │ │ ├── MessageHandler.java │ │ │ ├── channels │ │ │ │ └── UserChannelCtxMap.java │ │ │ └── process │ │ │ │ ├── MessageHandlerFactory.java │ │ │ │ ├── MessageProcess.java │ │ │ │ └── impl │ │ │ │ ├── GroupMessageProcess.java │ │ │ │ ├── SingleMessageProcess.java │ │ │ │ └── VideoMessageProcess.java │ │ │ ├── mq │ │ │ └── RabbitMQHandler.java │ │ │ ├── netty │ │ │ ├── HttpRequestHandler.java │ │ │ ├── IMChannelHandler.java │ │ │ ├── factory │ │ │ │ ├── NettyEventLoopFactory.java │ │ │ │ └── NettyVirtualThreadFactory.java │ │ │ ├── process │ │ │ │ ├── HeartBeatProcess.java │ │ │ │ ├── LoginProcess.java │ │ │ │ └── WsProcess.java │ │ │ └── service │ │ │ │ ├── AbstractRemoteServer.java │ │ │ │ ├── tcp │ │ │ │ ├── TcpSocketServer.java │ │ │ │ └── codec │ │ │ │ │ ├── MessageDecoder.java │ │ │ │ │ └── MessageEncoder.java │ │ │ │ └── websocket │ │ │ │ ├── WebSocketServer.java │ │ │ │ └── codec │ │ │ │ ├── MessageDecoder.java │ │ │ │ └── MessageEncoder.java │ │ │ └── utils │ │ │ ├── IPAddressUtil.java │ │ │ ├── JedisUtil.java │ │ │ ├── JsonUtil.java │ │ │ ├── MachineCodeUtils.java │ │ │ └── MessageUtils.java │ │ └── resources │ │ ├── logback.xml │ │ ├── mq.yml │ │ ├── nacos.yml │ │ ├── netty.yml │ │ └── redis.yml └── target │ └── classes │ ├── logback.xml │ ├── mq.yml │ ├── nacos.yml │ ├── netty.yml │ └── redis.yml ├── im-file ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── xy │ │ │ └── file │ │ │ ├── ImFileApplication.java │ │ │ ├── client │ │ │ ├── MinioAutoConfiguration.java │ │ │ ├── MinioProperties.java │ │ │ └── PearlMinioClient.java │ │ │ ├── config │ │ │ └── ExecutorConfig.java │ │ │ ├── controller │ │ │ ├── FileMinioController.java │ │ │ └── MediaMinioController.java │ │ │ ├── entity │ │ │ ├── OssFile.java │ │ │ ├── OssFileDownloadRange.java │ │ │ ├── OssFileImage.java │ │ │ ├── OssFileMediaInfo.java │ │ │ ├── OssFileUploadProgress.java │ │ │ └── OssFileUploadResponse.java │ │ │ ├── enums │ │ │ ├── BoolEnum.java │ │ │ └── StorageBucketEnum.java │ │ │ ├── handler │ │ │ ├── ImageProcessingStrategy.java │ │ │ └── impl │ │ │ │ ├── CompressStrategy.java │ │ │ │ ├── ThumbnailStrategy.java │ │ │ │ └── WatermarkStrategy.java │ │ │ ├── service │ │ │ ├── OssFileImageService.java │ │ │ ├── OssFileService.java │ │ │ └── impl │ │ │ │ ├── OssFileImageServiceImpl.java │ │ │ │ └── OssFileServiceImpl.java │ │ │ └── util │ │ │ ├── MinioUtils.java │ │ │ ├── RedisRepo.java │ │ │ ├── ResponseResult.java │ │ │ ├── ResultCode.java │ │ │ └── WatermarkUtil.java │ └── resources │ │ ├── application-undertow.yml │ │ ├── application.yml │ │ ├── banner.txt │ │ ├── bootstrap.yml │ │ └── logback-plus.xml │ └── test │ └── java │ └── com │ └── xy │ └── imfile │ └── ImFileApplicationTests.java ├── im-gateway ├── .gitignore ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── xy │ │ └── im │ │ ├── ImGatewayApplication.java │ │ ├── config │ │ └── RedisConfig.java │ │ ├── filter │ │ ├── BlackListFilter.java │ │ ├── CustomFilter.java │ │ └── DynamicFallbackFilter.java │ │ ├── lb │ │ └── NacosWebsocketClusterChooseRule.java │ │ ├── log │ │ ├── RequestLogFilter.java │ │ └── ResponseLogFilter.java │ │ └── utils │ │ ├── IPAddressUtil.java │ │ ├── JsonUtil.java │ │ └── RedisUtil.java │ └── resources │ ├── application.yml │ ├── banner.txt │ ├── bootstrap.yml │ └── logback-plus.xml ├── im-meet ├── .gitignore ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── xy │ │ └── meet │ │ ├── ImMeetApplication.java │ │ ├── StartCenter.java │ │ ├── config │ │ ├── ConfigCenter.java │ │ ├── IMNacosConfig.java │ │ ├── IMNettyConfig.java │ │ ├── LogConstant.java │ │ └── loader │ │ │ └── YamlConfigLoader.java │ │ ├── entity │ │ ├── Message.java │ │ ├── Room.java │ │ └── User.java │ │ ├── netty │ │ ├── IMeetChatServerHandler.java │ │ └── service │ │ │ ├── IMeetChatServer.java │ │ │ └── codec │ │ │ ├── MessageDecoder.java │ │ │ └── MessageEncoder.java │ │ └── utils │ │ ├── IPAddressUtil.java │ │ └── JsonUtil.java │ └── resources │ ├── logback.xml │ ├── nacos.yml │ └── netty.yml ├── im-server ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── xy │ │ │ │ └── server │ │ │ │ ├── ImServerApplication.java │ │ │ │ ├── annotations │ │ │ │ └── lock │ │ │ │ │ ├── LockTransactional.java │ │ │ │ │ └── LockTransactionalAspect.java │ │ │ │ ├── config │ │ │ │ ├── Knife4jConfig.java │ │ │ │ ├── MybatisPlusConfig.java │ │ │ │ ├── RabbitTemplateFactory.java │ │ │ │ ├── RedisConfig.java │ │ │ │ ├── ResponseInterceptorConfig.java │ │ │ │ └── ThreadPoolConfig.java │ │ │ │ ├── controller │ │ │ │ ├── ChatController.java │ │ │ │ ├── FileController.java │ │ │ │ ├── FriendController.java │ │ │ │ ├── GroupChatController.java │ │ │ │ ├── MessageController.java │ │ │ │ ├── SingleChatController.java │ │ │ │ └── VideoChatController.java │ │ │ │ ├── domain │ │ │ │ ├── dto │ │ │ │ │ ├── ChatDto.java │ │ │ │ │ ├── FriendDto.java │ │ │ │ │ ├── FriendRequestDto.java │ │ │ │ │ ├── FriendshipRequestDto.java │ │ │ │ │ ├── GroupDto.java │ │ │ │ │ ├── GroupInviteDto.java │ │ │ │ │ ├── LoginDto.java │ │ │ │ │ └── UserDto.java │ │ │ │ ├── po │ │ │ │ │ ├── ImChatPo.java │ │ │ │ │ ├── ImFriendshipGroupMemberPo.java │ │ │ │ │ ├── ImFriendshipGroupPo.java │ │ │ │ │ ├── ImFriendshipPo.java │ │ │ │ │ ├── ImFriendshipRequestPo.java │ │ │ │ │ ├── ImGroupMemberPo.java │ │ │ │ │ ├── ImGroupMessagePo.java │ │ │ │ │ ├── ImGroupMessageStatusPo.java │ │ │ │ │ ├── ImGroupPo.java │ │ │ │ │ ├── ImPrivateMessagePo.java │ │ │ │ │ ├── ImUserDataPo.java │ │ │ │ │ └── ImUserPo.java │ │ │ │ └── vo │ │ │ │ │ ├── ChatVo.java │ │ │ │ │ ├── FriendVo.java │ │ │ │ │ ├── FriendshipRequestVo.java │ │ │ │ │ ├── GroupMemberVo.java │ │ │ │ │ ├── LoginVo.java │ │ │ │ │ └── UserVo.java │ │ │ │ ├── exception │ │ │ │ ├── BusinessException.java │ │ │ │ ├── ForbiddenException.java │ │ │ │ ├── GlobalException.java │ │ │ │ └── handler │ │ │ │ │ └── CommonExceptionHandler.java │ │ │ │ ├── mapper │ │ │ │ ├── ImChatMapper.java │ │ │ │ ├── ImFriendshipGroupMapper.java │ │ │ │ ├── ImFriendshipGroupMemberMapper.java │ │ │ │ ├── ImFriendshipMapper.java │ │ │ │ ├── ImFriendshipRequestMapper.java │ │ │ │ ├── ImGroupMapper.java │ │ │ │ ├── ImGroupMemberMapper.java │ │ │ │ ├── ImGroupMessageMapper.java │ │ │ │ ├── ImGroupMessageStatusMapper.java │ │ │ │ ├── ImPrivateMessageMapper.java │ │ │ │ ├── ImUserDataMapper.java │ │ │ │ └── ImUserMapper.java │ │ │ │ ├── response │ │ │ │ ├── IResult.java │ │ │ │ ├── ResponseNotIntercept.java │ │ │ │ ├── Result.java │ │ │ │ ├── ResultEnum.java │ │ │ │ ├── common │ │ │ │ │ └── ResponseResult.java │ │ │ │ └── handler │ │ │ │ │ └── GlobalHandler.java │ │ │ │ ├── service │ │ │ │ ├── FileService.java │ │ │ │ ├── FriendService.java │ │ │ │ ├── GroupChatService.java │ │ │ │ ├── ImChatService.java │ │ │ │ ├── ImFriendshipGroupMemberService.java │ │ │ │ ├── ImFriendshipGroupService.java │ │ │ │ ├── ImFriendshipRequestService.java │ │ │ │ ├── ImFriendshipService.java │ │ │ │ ├── ImGroupMemberService.java │ │ │ │ ├── ImGroupMessageService.java │ │ │ │ ├── ImGroupMessageStatusService.java │ │ │ │ ├── ImGroupService.java │ │ │ │ ├── ImPrivateMessageService.java │ │ │ │ ├── ImUserService.java │ │ │ │ ├── MessageService.java │ │ │ │ ├── SingleChatService.java │ │ │ │ ├── VideoChatService.java │ │ │ │ └── impl │ │ │ │ │ ├── FileServiceImpl.java │ │ │ │ │ ├── FriendServiceImpl.java │ │ │ │ │ ├── GroupChatServiceImpl.java │ │ │ │ │ ├── ImChatServiceImpl.java │ │ │ │ │ ├── ImFriendshipGroupMemberServiceImpl.java │ │ │ │ │ ├── ImFriendshipGroupServiceImpl.java │ │ │ │ │ ├── ImFriendshipRequestServiceImpl.java │ │ │ │ │ ├── ImFriendshipServiceImpl.java │ │ │ │ │ ├── ImGroupMemberServiceImpl.java │ │ │ │ │ ├── ImGroupMessageServiceImpl.java │ │ │ │ │ ├── ImGroupMessageStatusServiceImpl.java │ │ │ │ │ ├── ImGroupServiceImpl.java │ │ │ │ │ ├── ImPrivateMessageServiceImpl.java │ │ │ │ │ ├── ImUserServiceImpl.java │ │ │ │ │ ├── MessageServiceImpl.java │ │ │ │ │ ├── SingleChatServiceImpl.java │ │ │ │ │ └── VideoChatServiceImpl.java │ │ │ │ └── utils │ │ │ │ ├── DateTimeUtils.java │ │ │ │ ├── GroupHeadImageUtil.java │ │ │ │ ├── JsonUtil.java │ │ │ │ ├── MinioUtil.java │ │ │ │ ├── MockMultipartFile.java │ │ │ │ └── RedisUtil.java │ │ └── resources │ │ │ ├── application-swagger.yml │ │ │ ├── application-undertow.yml │ │ │ ├── application.yml │ │ │ ├── banner.txt │ │ │ ├── bootstrap.yml │ │ │ ├── logback-plus.xml │ │ │ └── mapper │ │ │ ├── ImChatMapper.xml │ │ │ ├── ImFriendshipGroupMapper.xml │ │ │ ├── ImFriendshipGroupMemberMapper.xml │ │ │ ├── ImFriendshipMapper.xml │ │ │ ├── ImFriendshipRequestMapper.xml │ │ │ ├── ImGroupMapper.xml │ │ │ ├── ImGroupMemberMapper.xml │ │ │ ├── ImGroupMessageMapper.xml │ │ │ ├── ImGroupMessageStatusMapper.xml │ │ │ ├── ImPrivateMessageMapper.xml │ │ │ ├── ImUserDataMapper.xml │ │ │ └── ImUserMapper.xml │ └── test │ │ └── java │ │ └── com │ │ └── xy │ │ └── data │ │ └── ImServerApplicationTests.java └── target │ └── classes │ ├── application-swagger.yml │ ├── application-undertow.yml │ ├── application.yml │ ├── bootstrap.yml │ ├── logback-plus.xml │ └── mapper │ ├── ImChatMapper.xml │ ├── ImFriendshipGroupMapper.xml │ ├── ImFriendshipGroupMemberMapper.xml │ ├── ImFriendshipMapper.xml │ ├── ImFriendshipRequestMapper.xml │ ├── ImGroupMapper.xml │ ├── ImGroupMemberMapper.xml │ ├── ImGroupMessageMapper.xml │ ├── ImGroupMessageStatusMapper.xml │ ├── ImPrivateMessageMapper.xml │ ├── ImUserDataMapper.xml │ └── ImUserMapper.xml ├── pom.xml ├── rsa ├── privateKey.pem └── publicKey.pem └── sql └── im-core.sql /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | .idea 22 | /target 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | im-auth/src/main/resources/application.yml 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 dennis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /im-ai/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /im-ai/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 20 | -------------------------------------------------------------------------------- /im-ai/src/main/java/com/xy/ai/ImAiApplication.java: -------------------------------------------------------------------------------- 1 | package com.xy.ai; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ImAiApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(ImAiApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-ai/src/main/java/com/xy/ai/config/ChatConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.ai.config; 2 | 3 | import org.springframework.ai.chat.client.ChatClient; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | class ChatConfig { 9 | 10 | @Bean 11 | ChatClient chatClient(ChatClient.Builder builder) { 12 | return builder.defaultSystem("你是一个智能机器人,你的名字叫 Spring AI智能机器人").build(); 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /im-ai/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 # 配置启动端口号 3 | compression: 4 | enabled: true # 开启gzip压缩 5 | mime-types: application/json,application/xml,text/html,text/xml,text/plain 6 | min-response-size: 1024 7 | 8 | spring: 9 | banner: 10 | location: classpath:banner.txt 11 | profiles: 12 | include: undertow # 引用其他的yml文件 13 | threads: 14 | virtual: 15 | enabled: true # 开启虚拟线程 16 | ai: 17 | openai: 18 | api-key: "sk-0b48339cb3bd49f58bab98d972e180ee" # 安全起见,从系统环境变量读取 19 | base-url: https://api.deepseek.com 20 | chat: 21 | options: 22 | model: deepseek-chat 23 | temperature: 0.5 24 | -------------------------------------------------------------------------------- /im-ai/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Spring 2 | spring: 3 | application: 4 | # 应用名称 5 | name: im-ai 6 | profiles: 7 | # 环境配置 8 | active: dev 9 | cloud: 10 | sentinel: 11 | # 取消控制台懒加载 12 | eager: true 13 | transport: 14 | # sentinel控制台地址 15 | dashboard: localhost:8858 16 | nacos: 17 | discovery: 18 | # 服务注册地址 19 | server-addr: localhost:8848 20 | username: nacos 21 | password: nacos 22 | config: 23 | # 配置中心地址 24 | server-addr: localhost:8848 25 | # 配置文件格式 26 | file-extension: yml 27 | # 共享配置 28 | shared-configs: 29 | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} -------------------------------------------------------------------------------- /im-ai/src/test/java/com/xy/ai/ImAiApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.xy.ai; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ImAiApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-analysis/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /im-analysis/src/main/java/com/xy/alysis/ImAnalysisApplication.java: -------------------------------------------------------------------------------- 1 | package com.xy.alysis; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | 7 | @EnableAsync 8 | @SpringBootApplication 9 | public class ImAnalysisApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ImAnalysisApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /im-analysis/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8082 # 配置启动端口号 3 | compression: 4 | enabled: true # 开启gzip压缩 5 | mime-types: application/json,application/xml,text/html,text/xml,text/plain 6 | min-response-size: 1024 7 | 8 | 9 | 10 | spring: #springboot的配置 11 | banner: 12 | location: classpath:banner.txt 13 | profiles: 14 | include: undertow # 引用其他的yml文件 15 | threads: 16 | virtual: 17 | enabled: true # 开启虚拟线程 18 | 19 | # TODO: knife4j相关配置 可以不用改 20 | knife4j: 21 | enable: true # 开启增强配置 22 | production: false # 开启生产环境屏蔽 23 | setting: 24 | language: zh_cn # 默认中文 25 | swagger-model-name: 实体类 -------------------------------------------------------------------------------- /im-analysis/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Spring 2 | spring: 3 | application: 4 | # 应用名称 5 | name: im-analysis 6 | profiles: 7 | # 环境配置 8 | active: dev 9 | cloud: 10 | sentinel: 11 | # 取消控制台懒加载 12 | eager: true 13 | transport: 14 | # sentinel控制台地址 15 | dashboard: localhost:8858 16 | nacos: 17 | discovery: 18 | # 服务注册地址 19 | server-addr: localhost:8848 20 | username: nacos 21 | password: nacos 22 | config: 23 | # 配置中心地址 24 | server-addr: localhost:8848 25 | # 配置文件格式 26 | file-extension: yml 27 | # 共享配置 28 | shared-configs: 29 | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/book/ch01/HelloWord.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Han He 3 | * me@hankcs.com 4 | * 2018-05-18 下午5:38 5 | * 6 | * 7 | * Copyright (c) 2018, Han He. All Rights Reserved, http://www.hankcs.com/ 8 | * This source is subject to Han He. Please contact Han He for more information. 9 | * 10 | */ 11 | package com.hankcs.book.ch01; 12 | 13 | import com.hankcs.hanlp.HanLP; 14 | 15 | /** 16 | * 《自然语言处理入门》1.6 开源工具 17 | * 配套书籍:http://nlp.hankcs.com/book.php 18 | * 讨论答疑:https://bbs.hankcs.com/ 19 | * 20 | * @author hankcs 21 | * @see 《自然语言处理入门》 22 | * @see 讨论答疑 23 | */ 24 | public class HelloWord 25 | { 26 | public static void main(String[] args) 27 | { 28 | HanLP.Config.enableDebug(); // 首次运行会自动建立模型缓存,为了避免你等得无聊,开启调试模式说点什么:-) 29 | System.out.println(HanLP.segment("王国维和服务员")); 30 | } 31 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/book/ch02/DemoAhoCorasickDoubleArrayTrieSegment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Han He 3 | * me@hankcs.com 4 | * 2018-05-29 下午12:19 5 | * 6 | * 7 | * Copyright (c) 2018, Han He. All Rights Reserved, http://www.hankcs.com/ 8 | * This source is subject to Han He. Please contact Han He for more information. 9 | * 10 | */ 11 | package com.hankcs.book.ch02; 12 | 13 | import com.hankcs.hanlp.HanLP; 14 | import com.hankcs.hanlp.seg.Other.AhoCorasickDoubleArrayTrieSegment; 15 | 16 | import java.io.IOException; 17 | 18 | /** 19 | * 《自然语言处理入门》2.8 HanLP的词典分词实现 20 | * 配套书籍:http://nlp.hankcs.com/book.php 21 | * 讨论答疑:https://bbs.hankcs.com/ 22 | * 23 | * @author hankcs 24 | * @see 《自然语言处理入门》 25 | * @see 讨论答疑 26 | */ 27 | public class DemoAhoCorasickDoubleArrayTrieSegment 28 | { 29 | public static void main(String[] args) throws IOException 30 | { 31 | HanLP.Config.ShowTermNature = false; 32 | AhoCorasickDoubleArrayTrieSegment segment = new AhoCorasickDoubleArrayTrieSegment(); 33 | System.out.println(segment.seg("江西鄱阳湖干枯,中国最大淡水湖变成大草原")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/book/ch10/DemoTextClustering.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Han He 3 | * me@hankcs.com 4 | * 2019-01-03 6:54 PM 5 | * 6 | * 7 | * Copyright (c) 2019, Han He. All Rights Reserved, http://www.hankcs.com/ 8 | * See LICENSE file in the project root for full license information. 9 | * 10 | */ 11 | package com.hankcs.book.ch10; 12 | 13 | /** 14 | * 《自然语言处理入门》10 文本聚类 15 | * 配套书籍:http://nlp.hankcs.com/book.php 16 | * 讨论答疑:https://bbs.hankcs.com/ 17 | * 请参考{@link com.hankcs.demo.DemoTextClustering} 18 | * 19 | * @author hankcs 20 | * @see 《自然语言处理入门》 21 | * @see 讨论答疑 22 | */ 23 | public class DemoTextClustering extends com.hankcs.demo.DemoTextClustering 24 | { 25 | } 26 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/book/ch10/DemoTextClusteringFMeasure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Han He 3 | * me@hankcs.com 4 | * 2019-01-03 6:53 PM 5 | * 6 | * 7 | * Copyright (c) 2019, Han He. All Rights Reserved, http://www.hankcs.com/ 8 | * See LICENSE file in the project root for full license information. 9 | * 10 | */ 11 | package com.hankcs.book.ch10; 12 | 13 | /** 14 | * 《自然语言处理入门》10 文本聚类 15 | * 配套书籍:http://nlp.hankcs.com/book.php 16 | * 讨论答疑:https://bbs.hankcs.com/ 17 | * 请参考{@link com.hankcs.demo.DemoTextClusteringFMeasure} 18 | * 19 | * @author hankcs 20 | * @see 《自然语言处理入门》 21 | * @see 讨论答疑 22 | */ 23 | public class DemoTextClusteringFMeasure extends com.hankcs.demo.DemoTextClusteringFMeasure 24 | { 25 | } 26 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/book/ch11/DemoTextClassification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Han He 3 | * me@hankcs.com 4 | * 2019-01-04 8:22 PM 5 | * 6 | * 7 | * Copyright (c) 2019, Han He. All Rights Reserved, http://www.hankcs.com/ 8 | * See LICENSE file in the project root for full license information. 9 | * 10 | */ 11 | package com.hankcs.book.ch11; 12 | 13 | /** 14 | * 《自然语言处理入门》11.4 朴素贝叶斯分类器 15 | * 配套书籍:http://nlp.hankcs.com/book.php 16 | * 讨论答疑:https://bbs.hankcs.com/ 17 | * 请参考 {@link com.hankcs.demo.DemoTextClassification} 18 | * 19 | * @author hankcs 20 | * @see 《自然语言处理入门》 21 | * @see 讨论答疑 22 | */ 23 | public class DemoTextClassification extends com.hankcs.demo.DemoTextClassification 24 | { 25 | } 26 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/book/ch13/DemoTrainWord2Vec.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Han He 3 | * me@hankcs.com 4 | * 2019-02-26 12:29 5 | * 6 | * 7 | * Copyright (c) 2019, Han He. All Rights Reserved, http://www.hankcs.com/ 8 | * See LICENSE file in the project root for full license information. 9 | * 10 | */ 11 | package com.hankcs.book.ch13; 12 | 13 | import com.hankcs.demo.DemoWord2Vec; 14 | 15 | /** 16 | * 《自然语言处理入门》13.3 word2vec 17 | * 配套书籍:http://nlp.hankcs.com/book.php 18 | * 讨论答疑:https://bbs.hankcs.com/ 19 | * 请参考 {@link DemoWord2Vec} 20 | * 21 | * @author hankcs 22 | * @see 《自然语言处理入门》 23 | * @see 讨论答疑 24 | */ 25 | public class DemoTrainWord2Vec extends DemoWord2Vec 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/book/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 这个包是《自然语言处理入门》的配套代码,与HanLP1.x同步更新,保持兼容。 3 | * 配套书籍:http://nlp.hankcs.com/book.php 4 | * 讨论答疑:https://bbs.hankcs.com/ 5 | * 6 | * @see 《自然语言处理入门》 7 | * @see 讨论答疑 8 | */ 9 | package com.hankcs.book; -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoAtFirstSight.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * He Han 4 | * hankcs.cn@gmail.com 5 | * 2014/12/7 21:13 6 | * 7 | * 8 | * Copyright (c) 2003-2014, 上海林原信息科技有限公司. All Right Reserved, http://www.linrunsoft.com/ 9 | * This source is subject to the LinrunSpace License. Please contact 上海林原信息科技有限公司 to get more information. 10 | * 11 | */ 12 | package com.hankcs.demo; 13 | 14 | import com.hankcs.hanlp.HanLP; 15 | 16 | /** 17 | * 第一个Demo,惊鸿一瞥 18 | * 19 | * @author hankcs 20 | */ 21 | public class DemoAtFirstSight 22 | { 23 | public static void main(String[] args) 24 | { 25 | System.out.println("首次编译运行时,HanLP会自动构建词典缓存,请稍候……"); 26 | HanLP.Config.enableDebug(); // 为了避免你等得无聊,开启调试模式说点什么:-) 27 | System.out.println(HanLP.segment("你好,欢迎使用HanLP汉语处理包!接下来请从其他Demo中体验HanLP丰富的功能~")); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoBasicTokenizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * hankcs 4 | * me@hankcs.com 5 | * 2015/5/4 23:38 6 | * 7 | * 8 | * Copyright (c) 2003-2015, hankcs. All Right Reserved, http://www.hankcs.com/ 9 | * 10 | */ 11 | package com.hankcs.demo; 12 | 13 | import com.hankcs.hanlp.tokenizer.BasicTokenizer; 14 | 15 | /** 16 | * 演示基础分词,基础分词只进行基本NGram分词,不识别命名实体,不使用用户词典 17 | * 18 | * @author hankcs 19 | */ 20 | public class DemoBasicTokenizer 21 | { 22 | public static void main(String[] args) 23 | { 24 | String text = "举办纪念活动铭记二战历史,不忘战争带给人类的深重灾难,是为了防止悲剧重演,确保和平永驻;" + 25 | "铭记二战历史,更是为了提醒国际社会,需要共同捍卫二战胜利成果和国际公平正义," + 26 | "必须警惕和抵制在历史认知和维护战后国际秩序问题上的倒行逆施。"; 27 | System.out.println(BasicTokenizer.segment(text)); 28 | // 测试分词速度,让大家对HanLP的性能有一个直观的认识 29 | long start = System.currentTimeMillis(); 30 | int pressure = 100000; 31 | for (int i = 0; i < pressure; ++i) 32 | { 33 | BasicTokenizer.segment(text); 34 | } 35 | double costTime = (System.currentTimeMillis() - start) / (double) 1000; 36 | System.out.printf("BasicTokenizer分词速度:%.2f字每秒\n", text.length() * pressure / costTime); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoJapaneseNameRecognition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * He Han 4 | * hankcs.cn@gmail.com 5 | * 2014/12/7 19:38 6 | * 7 | * 8 | * Copyright (c) 2003-2014, 上海林原信息科技有限公司. All Right Reserved, http://www.linrunsoft.com/ 9 | * This source is subject to the LinrunSpace License. Please contact 上海林原信息科技有限公司 to get more information. 10 | * 11 | */ 12 | package com.hankcs.demo; 13 | 14 | import com.hankcs.hanlp.HanLP; 15 | import com.hankcs.hanlp.seg.Segment; 16 | import com.hankcs.hanlp.seg.common.Term; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * 日本人名识别 22 | * @author hankcs 23 | */ 24 | public class DemoJapaneseNameRecognition 25 | { 26 | public static void main(String[] args) 27 | { 28 | String[] testCase = new String[]{ 29 | "北川景子参演了林诣彬导演的《速度与激情3》", 30 | "林志玲亮相网友:确定不是波多野结衣?", 31 | "龟山千广和近藤公园在龟山公园里喝酒赏花", 32 | }; 33 | Segment segment = HanLP.newSegment().enableJapaneseNameRecognize(true); 34 | for (String sentence : testCase) 35 | { 36 | List termList = segment.seg(sentence); 37 | System.out.println(termList); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoKeyword.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * He Han 4 | * hankcs.cn@gmail.com 5 | * 2014/12/7 19:25 6 | * 7 | * 8 | * Copyright (c) 2003-2014+ 上海林原信息科技有限公司. All Right Reserved+ http://www.linrunsoft.com/ 9 | * This source is subject to the LinrunSpace License. Please contact 上海林原信息科技有限公司 to get more information. 10 | * 11 | */ 12 | package com.hankcs.demo; 13 | 14 | import com.hankcs.hanlp.HanLP; 15 | import com.hankcs.hanlp.summary.TextRankKeyword; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * 关键词提取 21 | * @author hankcs 22 | */ 23 | public class DemoKeyword 24 | { 25 | public static void main(String[] args) 26 | { 27 | String content = "程序员(英文Programmer)是从事程序开发、维护的专业人员。" + 28 | "一般将程序员分为程序设计人员和程序编码人员," + 29 | "但两者的界限并不非常清楚,特别是在中国。" + 30 | "软件从业人员分为初级程序员、高级程序员、系统" + 31 | "分析员和项目经理四大类。"; 32 | List keywordList = HanLP.extractKeyword(content, 5); 33 | System.out.println(keywordList); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoNewWordDiscover.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Hankcs 3 | * me@hankcs.com 4 | * 2017-11-02 11:21 5 | * 6 | * 7 | * Copyright (c) 2017, 码农场. All Right Reserved, http://www.hankcs.com/ 8 | * This source is subject to Hankcs. Please contact Hankcs to get more information. 9 | * 10 | */ 11 | package com.hankcs.demo; 12 | 13 | import com.hankcs.hanlp.HanLP; 14 | import com.hankcs.hanlp.corpus.io.IOUtil; 15 | import com.hankcs.hanlp.mining.word.WordInfo; 16 | import com.hankcs.hanlp.utility.TestUtility; 17 | 18 | import java.io.IOException; 19 | import java.util.List; 20 | 21 | /** 22 | * 词语提取、新词发现 23 | * 24 | * @author hankcs 25 | */ 26 | public class DemoNewWordDiscover 27 | { 28 | static final String CORPUS_PATH = TestUtility.ensureTestData("红楼梦.txt", "http://file.hankcs.com/corpus/红楼梦.zip"); 29 | 30 | public static void main(String[] args) throws IOException 31 | { 32 | // 文本长度越大越好,试试红楼梦? 33 | List wordInfoList = HanLP.extractWords(IOUtil.newBufferedReader(CORPUS_PATH), 100); 34 | System.out.println(wordInfoList); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoNormalization.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * hankcs 4 | * me@hankcs.com 5 | * 2015/5/18 16:08 6 | * 7 | * 8 | * Copyright (c) 2003-2015, hankcs. All Right Reserved, http://www.hankcs.com/ 9 | * 10 | */ 11 | package com.hankcs.demo; 12 | 13 | import com.hankcs.hanlp.HanLP; 14 | import com.hankcs.hanlp.dictionary.CustomDictionary; 15 | 16 | /** 17 | * 演示正规化字符配置项的效果(繁体->简体,全角->半角,大写->小写)。 18 | * 该配置项位于hanlp.properties中,通过Normalization=true来开启 19 | * 切换配置后必须删除CustomDictionary.txt.bin缓存,否则只影响动态插入的新词。 20 | * 21 | * @author hankcs 22 | */ 23 | public class DemoNormalization 24 | { 25 | public static void main(String[] args) 26 | { 27 | HanLP.Config.Normalization = true; 28 | CustomDictionary.insert("爱听4G", "nz 1000"); 29 | System.out.println(HanLP.segment("爱听4g")); 30 | System.out.println(HanLP.segment("爱听4G")); 31 | System.out.println(HanLP.segment("爱听4G")); 32 | System.out.println(HanLP.segment("爱听4G")); 33 | System.out.println(HanLP.segment("愛聽4G")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoNotionalTokenizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * He Han 4 | * hankcs.cn@gmail.com 5 | * 2015/4/6 23:20 6 | * 7 | * 8 | * Copyright (c) 2003-2014, 上海林原信息科技有限公司. All Right Reserved, http://www.linrunsoft.com/ 9 | * This source is subject to the LinrunSpace License. Please contact 上海林原信息科技有限公司 to get more information. 10 | * 11 | */ 12 | package com.hankcs.demo; 13 | 14 | import com.hankcs.hanlp.seg.common.Term; 15 | import com.hankcs.hanlp.tokenizer.NotionalTokenizer; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * 演示自动去除停用词、自动断句的分词器 21 | * @author hankcs 22 | */ 23 | public class DemoNotionalTokenizer 24 | { 25 | public static void main(String[] args) 26 | { 27 | String text = "小区居民有的反对喂养流浪猫,而有的居民却赞成喂养这些小宝贝"; 28 | // 自动去除停用词 29 | System.out.println(NotionalTokenizer.segment(text)); // 停用词典位于data/dictionary/stopwords.txt,可以自行修改 30 | // 自动断句+去除停用词 31 | for (List sentence : NotionalTokenizer.seg2sentence(text)) 32 | { 33 | System.out.println(sentence); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoNumberAndQuantifierRecognition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * hankcs 4 | * me@hankcs.com 5 | * 2015/5/6 18:44 6 | * 7 | * 8 | * Copyright (c) 2003-2015, hankcs. All Right Reserved, http://www.hankcs.com/ 9 | * 10 | */ 11 | package com.hankcs.demo; 12 | 13 | import com.hankcs.hanlp.tokenizer.StandardTokenizer; 14 | 15 | /** 16 | * 演示数词和数量词识别 17 | * 18 | * @author hankcs 19 | */ 20 | public class DemoNumberAndQuantifierRecognition 21 | { 22 | public static void main(String[] args) 23 | { 24 | StandardTokenizer.SEGMENT.enableNumberQuantifierRecognize(true); 25 | String[] testCase = new String[] 26 | { 27 | "十九元套餐包括什么", 28 | "九千九百九十九朵玫瑰", 29 | "壹佰块都不给我", 30 | "9012345678只蚂蚁", 31 | "牛奶三〇〇克*2", 32 | "ChinaJoy“扫黄”细则露胸超2厘米罚款", 33 | }; 34 | for (String sentence : testCase) 35 | { 36 | System.out.println(StandardTokenizer.segment(sentence)); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoPlaceRecognition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * He Han 4 | * hankcs.cn@gmail.com 5 | * 2014/12/7 19:25 6 | * 7 | * 8 | * Copyright (c) 2003-2014+ 上海林原信息科技有限公司. All Right Reserved+ http://www.linrunsoft.com/ 9 | * This source is subject to the LinrunSpace License. Please contact 上海林原信息科技有限公司 to get more information. 10 | * 11 | */ 12 | package com.hankcs.demo; 13 | 14 | import com.hankcs.hanlp.HanLP; 15 | import com.hankcs.hanlp.seg.Segment; 16 | import com.hankcs.hanlp.seg.common.Term; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * 地名识别 22 | * @author hankcs 23 | */ 24 | public class DemoPlaceRecognition 25 | { 26 | public static void main(String[] args) 27 | { 28 | String[] testCase = new String[]{ 29 | "蓝翔给宁夏固原市彭阳县红河镇黑牛沟村捐赠了挖掘机", 30 | }; 31 | Segment segment = HanLP.newSegment().enablePlaceRecognize(true); 32 | for (String sentence : testCase) 33 | { 34 | List termList = segment.seg(sentence); 35 | System.out.println(termList); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoPosTagging.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * He Han 4 | * hankcs.cn@gmail.com 5 | * 2014/12/7 20:14 6 | * 7 | * 8 | * Copyright (c) 2003-2014, 上海林原信息科技有限公司. All Right Reserved, http://www.linrunsoft.com/ 9 | * This source is subject to the LinrunSpace License. Please contact 上海林原信息科技有限公司 to get more information. 10 | * 11 | */ 12 | package com.hankcs.demo; 13 | 14 | import com.hankcs.hanlp.HanLP; 15 | import com.hankcs.hanlp.seg.Segment; 16 | 17 | /** 18 | * 词性标注 19 | * @author hankcs 20 | */ 21 | public class DemoPosTagging 22 | { 23 | public static void main(String[] args) 24 | { 25 | String text = "教授正在教授自然语言处理课程"; 26 | Segment segment = HanLP.newSegment(); 27 | 28 | System.out.println("未标注:" + segment.seg(text)); 29 | segment.enablePartOfSpeechTagging(true); 30 | System.out.println("标注后:" + segment.seg(text)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoRewriteText.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * hankcs 4 | * me@hankcs.com 5 | * 2015/11/13 18:36 6 | * 7 | * 8 | * Copyright (c) 2003-2015, hankcs. All Right Reserved, http://www.hankcs.com/ 9 | * 10 | */ 11 | package com.hankcs.demo; 12 | 13 | import com.hankcs.hanlp.dictionary.CoreSynonymDictionary; 14 | 15 | /** 16 | * @author hankcs 17 | */ 18 | public class DemoRewriteText 19 | { 20 | public static void main(String[] args) 21 | { 22 | String text = "这个方法可以利用同义词词典将一段文本改写成意思相似的另一段文本,而且差不多符合语法"; 23 | System.out.println(CoreSynonymDictionary.rewrite(text)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoSummary.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * He Han 4 | * hankcs.cn@gmail.com 5 | * 2014/12/7 19:25 6 | * 7 | * 8 | * Copyright (c) 2003-2014+ 上海林原信息科技有限公司. All Right Reserved+ http://www.linrunsoft.com/ 9 | * This source is subject to the LinrunSpace License. Please contact 上海林原信息科技有限公司 to get more information. 10 | * 11 | */ 12 | package com.hankcs.demo; 13 | 14 | import com.hankcs.hanlp.HanLP; 15 | import com.hankcs.hanlp.summary.TextRankSentence; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * 自动摘要 21 | * @author hankcs 22 | */ 23 | public class DemoSummary 24 | { 25 | public static void main(String[] args) 26 | { 27 | String document = "水利部水资源司司长陈明忠9月29日在国务院新闻办举行的新闻发布会上透露," + 28 | "根据刚刚完成了水资源管理制度的考核,有部分省接近了红线的指标," + 29 | "有部分省超过红线的指标。对一些超过红线的地方,陈明忠表示,对一些取用水项目进行区域的限批," + 30 | "严格地进行水资源论证和取水许可的批准。"; 31 | List sentenceList = HanLP.extractSummary(document, 3); 32 | System.out.println(sentenceList); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoTextClusteringFMeasure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Han He 3 | * me@hankcs.com 4 | * 2018-08-18 11:11 PM 5 | * 6 | * 7 | * Copyright (c) 2018, Han He. All Rights Reserved, http://www.hankcs.com/ 8 | * This source is subject to Han He. Please contact Han He for more information. 9 | * 10 | */ 11 | package com.hankcs.demo; 12 | 13 | import com.hankcs.hanlp.mining.cluster.ClusterAnalyzer; 14 | 15 | import static com.hankcs.demo.DemoTextClassification.CORPUS_FOLDER; 16 | 17 | /** 18 | * @author hankcs 19 | */ 20 | public class DemoTextClusteringFMeasure 21 | { 22 | public static void main(String[] args) 23 | { 24 | for (String algorithm : new String[]{"kmeans", "repeated bisection"}) 25 | { 26 | System.out.printf("%s F1=%.2f\n", algorithm, ClusterAnalyzer.evaluate(CORPUS_FOLDER, algorithm) * 100); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoTokenizerConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * He Han 4 | * hankcs.cn@gmail.com 5 | * 2014/12/16 17:47 6 | * 7 | * 8 | * Copyright (c) 2003-2014, 上海林原信息科技有限公司. All Right Reserved, http://www.linrunsoft.com/ 9 | * This source is subject to the LinrunSpace License. Please contact 上海林原信息科技有限公司 to get more information. 10 | * 11 | */ 12 | package com.hankcs.demo; 13 | 14 | import com.hankcs.hanlp.HanLP; 15 | import com.hankcs.hanlp.tokenizer.StandardTokenizer; 16 | 17 | /** 18 | * 演示动态设置预置分词器,这里的设置是全局的 19 | * @author hankcs 20 | */ 21 | public class DemoTokenizerConfig 22 | { 23 | public static void main(String[] args) 24 | { 25 | String text = "泽田依子是上外日本文化经济学院的外教"; 26 | System.out.println(StandardTokenizer.segment(text)); 27 | StandardTokenizer.SEGMENT.enableAllNamedEntityRecognize(true); 28 | System.out.println(StandardTokenizer.segment(text)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/demo/DemoUseAhoCorasickDoubleArrayTrieSegment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * He Han 4 | * me@hankcs.com 5 | * 2015/12/7 19:17 6 | * 7 | * 8 | * Copyright (c) 2008-2015, 码农场. All Right Reserved, http://www.hankcs.com/ 9 | * This source is subject to Hankcs. Please contact Hankcs to get more information. 10 | * 11 | */ 12 | package com.hankcs.demo; 13 | 14 | import com.hankcs.hanlp.HanLP; 15 | import com.hankcs.hanlp.seg.Other.AhoCorasickDoubleArrayTrieSegment; 16 | 17 | import java.io.IOException; 18 | 19 | /** 20 | * 基于AhoCorasickDoubleArrayTrie的分词器,该分词器允许用户跳过核心词典,直接使用自己的词典。 21 | * 需要注意的是,自己的词典必须遵守HanLP词典格式。 22 | * 23 | * @author hankcs 24 | */ 25 | public class DemoUseAhoCorasickDoubleArrayTrieSegment 26 | { 27 | public static void main(String[] args) throws IOException 28 | { 29 | // AhoCorasickDoubleArrayTrieSegment要求用户必须提供自己的词典路径 30 | AhoCorasickDoubleArrayTrieSegment segment = new AhoCorasickDoubleArrayTrieSegment(HanLP.Config.CustomDictionaryPath[0]); 31 | System.out.println(segment.seg("微观经济学继续教育循环经济")); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/HanLPTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp; 2 | 3 | import com.hankcs.hanlp.model.perceptron.PerceptronLexicalAnalyzer; 4 | import com.hankcs.hanlp.seg.Viterbi.ViterbiSegment; 5 | import junit.framework.TestCase; 6 | 7 | public class HanLPTest extends TestCase 8 | { 9 | public void testNewSegment() throws Exception 10 | { 11 | assertTrue(HanLP.newSegment("维特比") instanceof ViterbiSegment); 12 | assertTrue(HanLP.newSegment("感知机") instanceof PerceptronLexicalAnalyzer); 13 | } 14 | 15 | public void testDicUpdate() 16 | { 17 | System.out.println(HanLP.segment("大数据是一个新词汇!")); 18 | } 19 | 20 | public void testConvertToPinyinList() 21 | { 22 | System.out.println(HanLP.convertToPinyinString("你好", " ", false)); 23 | } 24 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/algorithm/LongestCommonSubsequenceTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.algorithm; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class LongestCommonSubsequenceTest extends TestCase 6 | { 7 | String a = "Tom Hanks"; 8 | String b = "Hankcs"; 9 | public void testCompute() throws Exception 10 | { 11 | assertEquals(5, LongestCommonSubsequence.compute(a, b)); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/algorithm/LongestCommonSubstringTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.algorithm; 2 | 3 | import com.hankcs.hanlp.algorithm.LongestCommonSubstring; 4 | import junit.framework.TestCase; 5 | 6 | public class LongestCommonSubstringTest extends TestCase 7 | { 8 | String a = "www.hankcs.com"; 9 | String b = "hankcs"; 10 | public void testCompute() throws Exception 11 | { 12 | // System.out.println(LongestCommonSubstring.compute(a.toCharArray(), b.toCharArray())); 13 | assertEquals(6, LongestCommonSubstring.compute(a.toCharArray(), b.toCharArray())); 14 | } 15 | 16 | public void testLongestCommonSubstring() throws Exception 17 | { 18 | // System.out.println(LongestCommonSubstring.compute(a, b)); 19 | assertEquals(6, LongestCommonSubstring.compute(a, b)); 20 | } 21 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/algorithm/MaxHeapTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.algorithm; 2 | 3 | import com.hankcs.hanlp.algorithm.MaxHeap; 4 | import junit.framework.TestCase; 5 | 6 | import java.util.Comparator; 7 | 8 | public class MaxHeapTest extends TestCase 9 | { 10 | final MaxHeap heap = new MaxHeap(5, new Comparator() 11 | { 12 | @Override 13 | public int compare(Integer o1, Integer o2) 14 | { 15 | return o1.compareTo(o2); 16 | } 17 | }); 18 | 19 | @Override 20 | public void setUp() throws Exception 21 | { 22 | heap.add(1); 23 | heap.add(3); 24 | heap.add(5); 25 | heap.add(7); 26 | heap.add(9); 27 | heap.add(8); 28 | heap.add(6); 29 | heap.add(4); 30 | heap.add(2); 31 | heap.add(0); 32 | } 33 | 34 | public void testToList() throws Exception 35 | { 36 | assertEquals("[9, 8, 7, 6, 5]", heap.toList().toString()); 37 | } 38 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/collection/trie/datrie/IntArrayListTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.collection.trie.datrie; 2 | 3 | import com.hankcs.hanlp.corpus.io.ByteArray; 4 | import junit.framework.TestCase; 5 | 6 | import java.io.DataOutputStream; 7 | import java.io.File; 8 | import java.io.FileOutputStream; 9 | 10 | public class IntArrayListTest extends TestCase 11 | { 12 | IntArrayList array = new IntArrayList(); 13 | 14 | @Override 15 | public void setUp() throws Exception 16 | { 17 | for (int i = 0; i < 64; ++i) 18 | { 19 | array.append(i); 20 | } 21 | } 22 | 23 | public void testSaveLoad() throws Exception 24 | { 25 | File tempFile = File.createTempFile("hanlp", ".intarray"); 26 | array.save(new DataOutputStream(new FileOutputStream(tempFile.getAbsolutePath()))); 27 | array.load(ByteArray.createByteArray(tempFile.getAbsolutePath())); 28 | for (int i = 0; i < 64; ++i) 29 | { 30 | assertEquals(i, array.get(i)); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/corpus/TestNSDictionaryMaker.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.corpus; 2 | 3 | import com.hankcs.hanlp.corpus.dictionary.EasyDictionary; 4 | import com.hankcs.hanlp.corpus.dictionary.NSDictionaryMaker; 5 | import com.hankcs.hanlp.corpus.document.CorpusLoader; 6 | import com.hankcs.hanlp.corpus.document.Document; 7 | 8 | public class TestNSDictionaryMaker { 9 | 10 | public static void main(String[] args) 11 | { 12 | EasyDictionary dictionary = EasyDictionary.create("data/dictionary/2014_dictionary.txt"); 13 | final NSDictionaryMaker nsDictionaryMaker = new NSDictionaryMaker(dictionary); 14 | CorpusLoader.walk("D:\\JavaProjects\\CorpusToolBox\\data\\2014\\", new CorpusLoader.Handler() 15 | { 16 | @Override 17 | public void handle(Document document) 18 | { 19 | nsDictionaryMaker.compute(document.getComplexSentenceList()); 20 | } 21 | }); 22 | nsDictionaryMaker.saveTxtTo("D:\\JavaProjects\\HanLP\\data\\test\\place\\ns"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/corpus/TestNTDcitionaryMaker.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.corpus; 2 | 3 | import com.hankcs.hanlp.corpus.dictionary.EasyDictionary; 4 | import com.hankcs.hanlp.corpus.dictionary.NTDictionaryMaker; 5 | import com.hankcs.hanlp.corpus.document.CorpusLoader; 6 | import com.hankcs.hanlp.corpus.document.Document; 7 | 8 | public class TestNTDcitionaryMaker 9 | { 10 | 11 | public static void main(String[] args) 12 | { 13 | EasyDictionary dictionary = EasyDictionary.create("data/dictionary/2014_dictionary.txt"); 14 | final NTDictionaryMaker ntDictionaryMaker = new NTDictionaryMaker(dictionary); 15 | // CorpusLoader.walk("D:\\JavaProjects\\CorpusToolBox\\data\\2014\\", new CorpusLoader.Handler() 16 | CorpusLoader.walk("data/test/nt/test/", new CorpusLoader.Handler() 17 | { 18 | @Override 19 | public void handle(Document document) 20 | { 21 | ntDictionaryMaker.compute(document.getComplexSentenceList()); 22 | } 23 | }); 24 | ntDictionaryMaker.saveTxtTo("D:\\JavaProjects\\HanLP\\data\\test\\organization\\nt"); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/corpus/TestNatureDictionaryMaker.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.corpus; 2 | 3 | import com.hankcs.hanlp.corpus.dictionary.NatureDictionaryMaker; 4 | import com.hankcs.hanlp.corpus.document.CorpusLoader; 5 | import com.hankcs.hanlp.corpus.document.Document; 6 | import com.hankcs.hanlp.corpus.util.CorpusUtil; 7 | 8 | public class TestNatureDictionaryMaker 9 | { 10 | 11 | public static void main(String[] args) 12 | { 13 | // makeCoreDictionary("D:\\JavaProjects\\CorpusToolBox\\data\\2014", "data/dictionary/CoreNatureDictionary.txt"); 14 | // EasyDictionary dictionary = EasyDictionary.create("data/dictionary/CoreNatureDictionary.txt"); 15 | final NatureDictionaryMaker dictionaryMaker = new NatureDictionaryMaker(); 16 | CorpusLoader.walk("D:\\JavaProjects\\CorpusToolBox\\data\\2014", new CorpusLoader.Handler() 17 | { 18 | @Override 19 | public void handle(Document document) 20 | { 21 | dictionaryMaker.compute(CorpusUtil.convert2CompatibleList(document.getSimpleSentenceList(false))); // 再打一遍不拆分的 22 | dictionaryMaker.compute(CorpusUtil.convert2CompatibleList(document.getSimpleSentenceList(true))); // 先打一遍拆分的 23 | } 24 | }); 25 | dictionaryMaker.saveTxtTo("data/test/CoreNatureDictionary"); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/corpus/dictionary/TMDictionaryMakerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.corpus.dictionary; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class TMDictionaryMakerTest extends TestCase 6 | { 7 | public void testCreate() throws Exception 8 | { 9 | TMDictionaryMaker tmDictionaryMaker = new TMDictionaryMaker(); 10 | tmDictionaryMaker.addPair("ab", "cd"); 11 | tmDictionaryMaker.addPair("ab", "cd"); 12 | tmDictionaryMaker.addPair("ab", "Y"); 13 | tmDictionaryMaker.addPair("ef", "gh"); 14 | tmDictionaryMaker.addPair("ij", "kl"); 15 | tmDictionaryMaker.addPair("ij", "kl"); 16 | tmDictionaryMaker.addPair("ij", "kl"); 17 | tmDictionaryMaker.addPair("X", "Y"); 18 | // System.out.println(tmDictionaryMaker); 19 | } 20 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/corpus/dictionary/item/ItemTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.corpus.dictionary.item; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class ItemTest extends TestCase 6 | { 7 | public void testCreate() throws Exception 8 | { 9 | assertEquals("希望 v 7685 vn 616", Item.create("希望 v 7685 vn 616").toString()); 10 | } 11 | 12 | public void testCombine() throws Exception 13 | { 14 | SimpleItem itemA = SimpleItem.create("A 1 B 2"); 15 | SimpleItem itemB = SimpleItem.create("B 1 C 2 D 3"); 16 | itemA.combine(itemB); 17 | assertEquals("B 3 D 3 C 2 A 1 ", itemA.toString()); 18 | } 19 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/corpus/document/DocumentTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.corpus.document; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class DocumentTest extends TestCase 6 | { 7 | public void testCreate() throws Exception 8 | { 9 | Document document = Document.create("[上海/ns 华安/nz 工业/n (/w 集团/n )/w 公司/n]/nt 董事长/n 谭旭光/nr 和/c 秘书/n 胡花蕊/nr 来到/v [美国/ns 纽约/ns 现代/t 艺术/n 博物馆/n]/ns 参观/v"); 10 | assertNotNull(document); 11 | } 12 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/corpus/document/sentence/word/WordTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.corpus.document.sentence.word; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class WordTest extends TestCase 6 | { 7 | public void testCreate() throws Exception 8 | { 9 | assertEquals("人民网/nz", Word.create("人民网/nz").toString()); 10 | assertEquals("[纽约/nsf 时报/n]/nz", CompoundWord.create("[纽约/nsf 时报/n]/nz").toString()); 11 | assertEquals("[中央/n 人民/n 广播/vn 电台/n]/nt", CompoundWord.create("[中央/n 人民/n 广播/vn 电台/n]nt").toString()); 12 | } 13 | 14 | public void testSpace() throws Exception 15 | { 16 | CompoundWord compoundWord = CompoundWord.create("[9/m 11/m 后/f]/mq"); 17 | assertEquals(3, compoundWord.innerList.size()); 18 | } 19 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/corpus/tag/NatureTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.corpus.tag; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class NatureTest extends TestCase 6 | { 7 | public void testFromString() throws Exception 8 | { 9 | Nature one = Nature.create("新词性1"); 10 | Nature two = Nature.create("新词性2"); 11 | 12 | assertEquals(one, Nature.fromString("新词性1")); 13 | assertEquals(two, Nature.fromString("新词性2")); 14 | } 15 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/dependency/perceptron/parser/KBeamArcEagerDependencyParserTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.dependency.perceptron.parser; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.io.IOException; 6 | 7 | public class KBeamArcEagerDependencyParserTest extends TestCase 8 | { 9 | public void testLoad() throws IOException, ClassNotFoundException 10 | { 11 | KBeamArcEagerDependencyParser parser = new KBeamArcEagerDependencyParser(); 12 | } 13 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/dictionary/CoreBiGramTableDictionaryTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.dictionary; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class CoreBiGramTableDictionaryTest extends TestCase 6 | { 7 | public void testReload() throws Exception 8 | { 9 | int biFrequency = CoreBiGramTableDictionary.getBiFrequency("高性能", "计算"); 10 | CoreBiGramTableDictionary.reload(); 11 | assertEquals(biFrequency, CoreBiGramTableDictionary.getBiFrequency("高性能", "计算")); 12 | } 13 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/dictionary/other/PartOfSpeechTagDictionaryTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.dictionary.other; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class PartOfSpeechTagDictionaryTest extends TestCase 6 | { 7 | public void testTranslate() throws Exception 8 | { 9 | assertEquals("名词", PartOfSpeechTagDictionary.translate("n")); 10 | } 11 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/dictionary/py/PinyinDictionaryTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.dictionary.py; 2 | 3 | import com.hankcs.hanlp.HanLP; 4 | import junit.framework.TestCase; 5 | 6 | import java.util.Arrays; 7 | 8 | public class PinyinDictionaryTest extends TestCase 9 | { 10 | 11 | public void testGet() 12 | { 13 | System.out.println(Arrays.toString(PinyinDictionary.get("鼖"))); 14 | System.out.println(PinyinDictionary.convertToPinyin("\uD867\uDF7E\uD867\uDF8C")); 15 | System.out.println(HanLP.convertToPinyinList("\uD867\uDF7E\uD867\uDF8C")); 16 | } 17 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/mining/word/TermFrequencyCounterTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.mining.word; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class TermFrequencyCounterTest extends TestCase 6 | { 7 | public void testGetKeywords() throws Exception 8 | { 9 | TermFrequencyCounter counter = new TermFrequencyCounter(); 10 | counter.add("加油加油中国队!"); 11 | System.out.println(counter); 12 | System.out.println(counter.getKeywords("女排夺冠,观众欢呼女排女排女排!")); 13 | } 14 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/mining/word/TfIdfCounterTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.mining.word; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class TfIdfCounterTest extends TestCase 6 | { 7 | public void testGetKeywords() throws Exception 8 | { 9 | TfIdfCounter counter = new TfIdfCounter(); 10 | counter.add("《女排夺冠》", "女排北京奥运会夺冠"); 11 | counter.add("《羽毛球男单》", "北京奥运会的羽毛球男单决赛"); 12 | counter.add("《女排》", "中国队女排夺北京奥运会金牌重返巅峰,观众欢呼女排女排女排!"); 13 | counter.compute(); 14 | 15 | for (Object id : counter.documents()) 16 | { 17 | System.out.println(id + " : " + counter.getKeywordsOf(id, 3)); 18 | } 19 | 20 | System.out.println(counter.getKeywords("奥运会反兴奋剂", 2)); 21 | } 22 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/mining/word2vec/VectorsReaderTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.mining.word2vec; 2 | 3 | import com.hankcs.hanlp.corpus.io.IOUtil; 4 | import junit.framework.TestCase; 5 | 6 | import java.io.BufferedWriter; 7 | import java.io.File; 8 | 9 | public class VectorsReaderTest extends TestCase 10 | { 11 | public void testReadVectorFile() throws Exception 12 | { 13 | File tempFile = File.createTempFile("hanlp-vector", ".txt"); 14 | tempFile.deleteOnExit(); 15 | BufferedWriter bw = IOUtil.newBufferedWriter(tempFile.getAbsolutePath()); 16 | bw.write("3 1\n" + 17 | "cat 1.1\n" + 18 | " 2.2\n" + 19 | "dog 3.3\n" 20 | ); 21 | bw.close(); 22 | 23 | VectorsReader reader = new VectorsReader(tempFile.getAbsolutePath()); 24 | reader.readVectorFile(); 25 | assertEquals(2, reader.words); 26 | assertEquals(2, reader.vocab.length); 27 | assertEquals(2, reader.matrix.length); 28 | assertEquals(1f, reader.matrix[1][0]); 29 | } 30 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/bigram/BigramDependencyModelTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.bigram; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class BigramDependencyModelTest extends TestCase 6 | { 7 | public void testLoad() throws Exception 8 | { 9 | assertEquals("限定", BigramDependencyModel.get("传", "v", "角落", "n")); 10 | } 11 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/crf/CRFLexicalAnalyzerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.crf; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.io.IOException; 6 | 7 | public class CRFLexicalAnalyzerTest extends TestCase 8 | { 9 | public void testLoad() throws Exception 10 | { 11 | CRFLexicalAnalyzer analyzer = new CRFLexicalAnalyzer(); 12 | String[] tests = new String[]{ 13 | "商品和服务", 14 | "总统普京与特朗普通电话讨论太空探索技术公司", 15 | "微软公司於1975年由比爾·蓋茲和保羅·艾倫創立,18年啟動以智慧雲端、前端為導向的大改組。" 16 | }; 17 | // for (String sentence : tests) 18 | // { 19 | // System.out.println(analyzer.analyze(sentence)); 20 | // System.out.println(analyzer.seg(sentence)); 21 | // } 22 | } 23 | 24 | public void testIssue1221() throws IOException 25 | { 26 | CRFLexicalAnalyzer analyzer = new CRFLexicalAnalyzer(); 27 | analyzer.enableCustomDictionaryForcing(true); 28 | System.out.println(analyzer.seg("商品和服务")); 29 | } 30 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/crf/CRFNERecognizerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.crf; 2 | 3 | import com.hankcs.hanlp.HanLP; 4 | import junit.framework.TestCase; 5 | 6 | public class CRFNERecognizerTest extends TestCase 7 | { 8 | public static final String CORPUS = "data/test/pku98/199801.txt"; 9 | public static String NER_MODEL_PATH = "data/model/crf/pku199801/ner.txt"; 10 | public void testTrain() throws Exception 11 | { 12 | CRFTagger tagger = new CRFNERecognizer(null); 13 | tagger.train(CORPUS, NER_MODEL_PATH); 14 | } 15 | 16 | public void testLoad() throws Exception 17 | { 18 | CRFTagger tagger = new CRFNERecognizer(NER_MODEL_PATH); 19 | } 20 | 21 | public void testConvert() throws Exception 22 | { 23 | CRFTagger tagger = new CRFNERecognizer(null); 24 | tagger.convertCorpus(CORPUS, "data/test/crf/ner-corpus.tsv"); 25 | } 26 | 27 | public void testDumpTemplate() throws Exception 28 | { 29 | CRFTagger tagger = new CRFNERecognizer(null); 30 | tagger.dumpTemplate("data/test/crf/ner-template.txt"); 31 | } 32 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/crf/LogLinearModelTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.crf; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class LogLinearModelTest extends TestCase 6 | { 7 | public void testLoad() throws Exception 8 | { 9 | LogLinearModel model = new LogLinearModel("/Users/hankcs/Downloads/crfpp-msr-cws-model.txt"); 10 | } 11 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/hmm/HMMLexicalAnalyzerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.hmm; 2 | 3 | import com.hankcs.hanlp.corpus.PKU; 4 | import junit.framework.TestCase; 5 | 6 | public class HMMLexicalAnalyzerTest extends TestCase 7 | { 8 | 9 | public static final String CORPUS_PATH = PKU.PKU199801_TRAIN; 10 | 11 | public void testTrain() throws Exception 12 | { 13 | HMMSegmenter segmenter = new HMMSegmenter(); 14 | segmenter.train(CORPUS_PATH); 15 | HMMPOSTagger tagger = new HMMPOSTagger(); 16 | tagger.train(CORPUS_PATH); 17 | HMMNERecognizer recognizer = new HMMNERecognizer(); 18 | recognizer.train(CORPUS_PATH); 19 | HMMLexicalAnalyzer analyzer = new HMMLexicalAnalyzer(segmenter, tagger, recognizer); 20 | System.out.println(analyzer.analyze("我的希望是希望人们幸福")); 21 | } 22 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/hmm/HMMPOSTaggerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.hmm; 2 | 3 | import com.hankcs.hanlp.corpus.PKU; 4 | import com.hankcs.hanlp.model.perceptron.PerceptronSegmenter; 5 | import com.hankcs.hanlp.tokenizer.lexical.AbstractLexicalAnalyzer; 6 | import com.hankcs.hanlp.utility.TestUtility; 7 | import junit.framework.TestCase; 8 | 9 | import java.util.Arrays; 10 | 11 | public class HMMPOSTaggerTest extends TestCase 12 | { 13 | public void testTrain() throws Exception 14 | { 15 | HMMPOSTagger tagger = new HMMPOSTagger(); // 创建词性标注器 16 | // HMMPOSTagger tagger = new HMMPOSTagger(new SecondOrderHiddenMarkovModel()); // 或二阶隐马 17 | tagger.train(PKU.PKU199801); // 训练 18 | System.out.println(Arrays.toString(tagger.tag("他", "的", "希望", "是", "希望", "上学"))); // 预测 19 | AbstractLexicalAnalyzer analyzer = new AbstractLexicalAnalyzer(new PerceptronSegmenter(), tagger); // 构造词法分析器 20 | System.out.println(analyzer.analyze("他的希望是希望上学").translateLabels()); // 分词+词性标注 21 | } 22 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/hmm/HMMSegmenterTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.hmm; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class HMMSegmenterTest extends TestCase 6 | { 7 | public void testTrain() throws Exception 8 | { 9 | HMMSegmenter segmenter = new HMMSegmenter(); 10 | segmenter.train("data/test/my_cws_corpus.txt"); 11 | System.out.println(segmenter.segment("商品和服务")); 12 | } 13 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/hmm/SecondOrderHiddenMarkovModelTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.hmm; 2 | 3 | 4 | public class SecondOrderHiddenMarkovModelTest extends FirstOrderHiddenMarkovModelTest 5 | { 6 | static float[][][] transition_probability2 = new float[][][]{ 7 | {{0.7f, 0.3f}, {0.4f, 0.6f}}, 8 | {{0.7f, 0.3f}, {0.4f, 0.6f}}, 9 | }; 10 | 11 | public void testPredict() throws Exception 12 | { 13 | SecondOrderHiddenMarkovModel hmm2 = new SecondOrderHiddenMarkovModel(start_probability, transition_probability, emission_probability, transition_probability2); 14 | SecondOrderHiddenMarkovModel trainedModel = new SecondOrderHiddenMarkovModel(); 15 | trainedModel.train(hmm2.generate(3, 10, 100000)); 16 | hmm2.unLog(); 17 | trainedModel.unLog(); 18 | assertTrue(hmm2.similar(trainedModel)); 19 | } 20 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Hankcs 3 | * me@hankcs.com 4 | * 2017-10-27 下午5:46 5 | * 6 | * 7 | * Copyright (c) 2017, 码农场. All Right Reserved, http://www.hankcs.com/ 8 | * This source is subject to Hankcs. Please contact Hankcs to get more information. 9 | * 10 | */ 11 | package com.hankcs.hanlp.model.perceptron; 12 | 13 | import com.hankcs.hanlp.HanLP; 14 | 15 | /** 16 | * @author hankcs 17 | */ 18 | public class Config 19 | { 20 | public static final String CWS_MODEL_FILE = HanLP.Config.PerceptronCWSModelPath; 21 | public static final String POS_MODEL_FILE = HanLP.Config.PerceptronPOSModelPath; 22 | public static final String NER_MODEL_FILE = HanLP.Config.PerceptronNERModelPath; 23 | } 24 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/DemoTrainCWS.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.perceptron; 2 | 3 | import java.io.IOException; 4 | 5 | public class DemoTrainCWS 6 | { 7 | public static void main(String[] args) throws IOException 8 | { 9 | PerceptronTrainer trainer = new CWSTrainer(); 10 | PerceptronTrainer.Result result = trainer.train( 11 | "data/test/pku98/199801.txt", 12 | Config.CWS_MODEL_FILE 13 | ); 14 | System.out.printf("准确率F1:%.2f\n", result.getAccuracy()); 15 | PerceptronSegmenter segment = new PerceptronSegmenter(result.getModel()); 16 | // 也可以用 17 | // Segment segment = new AveragedPerceptronSegment(POS_MODEL_FILE); 18 | System.out.println(segment.segment("商品与服务")); 19 | } 20 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/DemoTrainPOS.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Hankcs 3 | * me@hankcs.com 4 | * 2017-10-27 下午4:28 5 | * 6 | * 7 | * Copyright (c) 2017, 码农场. All Right Reserved, http://www.hankcs.com/ 8 | * This source is subject to Hankcs. Please contact Hankcs to get more information. 9 | * 10 | */ 11 | package com.hankcs.hanlp.model.perceptron; 12 | 13 | import java.io.IOException; 14 | 15 | /** 16 | * @author hankcs 17 | */ 18 | public class DemoTrainPOS 19 | { 20 | public static void main(String[] args) throws IOException 21 | { 22 | PerceptronTrainer trainer = new POSTrainer(); 23 | trainer.train("data/test/pku98/199801.txt", Config.POS_MODEL_FILE); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/NERTrainerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.perceptron; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.util.Arrays; 6 | 7 | public class NERTrainerTest extends TestCase 8 | { 9 | public void testTrain() throws Exception 10 | { 11 | PerceptronTrainer trainer = new NERTrainer(); 12 | trainer.train("data/test/pku98/199801.txt", Config.NER_MODEL_FILE); 13 | } 14 | 15 | public void testTag() throws Exception 16 | { 17 | PerceptronNERecognizer recognizer = new PerceptronNERecognizer(Config.NER_MODEL_FILE); 18 | System.out.println(Arrays.toString(recognizer.recognize("吴忠市 乳制品 公司 谭利华 来到 布达拉宫 广场".split(" "), "ns n n nr p ns n".split(" ")))); 19 | } 20 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/POSTrainerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.perceptron; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.util.Arrays; 6 | 7 | public class POSTrainerTest extends TestCase 8 | { 9 | 10 | public void testTrain() throws Exception 11 | { 12 | PerceptronTrainer trainer = new POSTrainer(); 13 | trainer.train("data/test/pku98/199801.txt", Config.POS_MODEL_FILE); 14 | } 15 | 16 | public void testLoad() throws Exception 17 | { 18 | PerceptronPOSTagger tagger = new PerceptronPOSTagger(Config.POS_MODEL_FILE); 19 | System.out.println(Arrays.toString(tagger.tag("中国 交响乐团 谭利华 在 布达拉宫 广场 演出".split(" ")))); 20 | } 21 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/PerceptronNERecognizerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.perceptron; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class PerceptronNERecognizerTest extends TestCase 6 | { 7 | public void testEmptyInput() throws Exception 8 | { 9 | PerceptronNERecognizer recognizer = new PerceptronNERecognizer(); 10 | recognizer.recognize(new String[0], new String[0]); 11 | } 12 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/PerceptronPOSTaggerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.perceptron; 2 | 3 | import com.hankcs.hanlp.HanLP; 4 | import com.hankcs.hanlp.corpus.PKU; 5 | import com.hankcs.hanlp.tokenizer.lexical.AbstractLexicalAnalyzer; 6 | import junit.framework.TestCase; 7 | 8 | import java.util.Arrays; 9 | 10 | public class PerceptronPOSTaggerTest extends TestCase 11 | { 12 | public void testTrain() throws Exception 13 | { 14 | PerceptronTrainer trainer = new POSTrainer(); 15 | trainer.train(PKU.PKU199801_TRAIN, PKU.POS_MODEL); // 训练 16 | PerceptronPOSTagger tagger = new PerceptronPOSTagger(PKU.POS_MODEL); // 加载 17 | System.out.println(Arrays.toString(tagger.tag("他", "的", "希望", "是", "希望", "上学"))); // 预测 18 | AbstractLexicalAnalyzer analyzer = new AbstractLexicalAnalyzer(new PerceptronSegmenter(), tagger); // 构造词法分析器 19 | System.out.println(analyzer.analyze("李狗蛋的希望是希望上学")); // 分词+词性标注 20 | } 21 | 22 | public void testCompress() throws Exception 23 | { 24 | PerceptronPOSTagger tagger = new PerceptronPOSTagger(); 25 | tagger.getModel().compress(0.01); 26 | double[] scores = tagger.evaluate("data/test/pku98/199801.txt"); 27 | System.out.println(scores[0]); 28 | tagger.getModel().save(HanLP.Config.PerceptronPOSModelPath + ".small"); 29 | } 30 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/PerceptronTaggerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.perceptron; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class PerceptronTaggerTest extends TestCase 8 | { 9 | public void testEmptyInput() throws Exception 10 | { 11 | PerceptronPOSTagger tagger = new PerceptronPOSTagger(); 12 | tagger.tag(new ArrayList()); 13 | } 14 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/corpus/ConvertPKU.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Hankcs 3 | * me@hankcs.com 4 | * 2017-09-18 上午10:43 5 | * 6 | * 7 | * Copyright (c) 2017, 码农场. All Right Reserved, http://www.hankcs.com/ 8 | * This source is subject to Hankcs. Please contact Hankcs to get more information. 9 | * 10 | */ 11 | package com.hankcs.hanlp.model.perceptron.corpus; 12 | 13 | import com.hankcs.hanlp.HanLP; 14 | import com.hankcs.hanlp.corpus.document.CorpusLoader; 15 | import com.hankcs.hanlp.corpus.document.Document; 16 | import com.hankcs.hanlp.corpus.document.sentence.word.IWord; 17 | import com.hankcs.hanlp.corpus.io.IOUtil; 18 | import junit.framework.TestCase; 19 | 20 | import java.io.BufferedWriter; 21 | import java.io.File; 22 | import java.io.IOException; 23 | import java.util.List; 24 | 25 | /** 26 | * @author hankcs 27 | */ 28 | public class ConvertPKU extends TestCase 29 | { 30 | } 31 | -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/model/LinearModelTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.perceptron.model; 2 | 3 | import com.hankcs.hanlp.model.perceptron.CWSTrainer; 4 | import com.hankcs.hanlp.model.perceptron.PerceptronTrainer; 5 | import junit.framework.TestCase; 6 | 7 | import static java.lang.System.out; 8 | 9 | public class LinearModelTest extends TestCase 10 | { 11 | public static final String MODEL_FILE = "data/pku_mini.bin"; 12 | 13 | // public void testLoad() throws Exception 14 | // { 15 | // LinearModel model = new LinearModel(MODEL_FILE); 16 | // PerceptronTrainer trainer = new CWSTrainer(); 17 | // double[] prf = trainer.evaluate("icwb2-data/mini/pku_development.txt", 18 | // model 19 | // ); 20 | // out.printf("Performance - P:%.2f R:%.2f F:%.2f\n", prf[0], prf[1], prf[2]); 21 | // } 22 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/utility/IOUtilityTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.perceptron.utility; 2 | 3 | import junit.framework.TestCase; 4 | 5 | import java.util.Arrays; 6 | 7 | public class IOUtilityTest extends TestCase 8 | { 9 | public void testReadLineToArray() throws Exception 10 | { 11 | String line = " 你好 世界 ! "; 12 | String[] array = IOUtility.readLineToArray(line); 13 | System.out.println(Arrays.toString(array)); 14 | } 15 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/model/perceptron/utility/UtilityTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.model.perceptron.utility; 2 | 3 | import com.hankcs.hanlp.corpus.PKU; 4 | import com.hankcs.hanlp.corpus.document.sentence.Sentence; 5 | import com.hankcs.hanlp.model.hmm.HMMNERecognizer; 6 | import com.hankcs.hanlp.model.perceptron.PerceptronNERecognizer; 7 | import com.hankcs.hanlp.model.perceptron.tagset.NERTagSet; 8 | import junit.framework.TestCase; 9 | 10 | import java.util.Arrays; 11 | import java.util.Map; 12 | 13 | public class UtilityTest extends TestCase 14 | { 15 | public void testCombineNER() throws Exception 16 | { 17 | NERTagSet nerTagSet = new HMMNERecognizer().getNERTagSet(); 18 | String[] nerArray = Utility.reshapeNER(Utility.convertSentenceToNER(Sentence.create("萨哈夫/nr 说/v ,/w 伊拉克/ns 将/d 同/p [联合国/nt 销毁/v 伊拉克/ns 大规模/b 杀伤性/n 武器/n 特别/a 委员会/n]/nt 继续/v 保持/v 合作/v 。/w"), nerTagSet))[2]; 19 | System.out.println(Arrays.toString(nerArray)); 20 | System.out.println(Utility.combineNER(nerArray, nerTagSet)); 21 | } 22 | 23 | public void testEvaluateNER() throws Exception 24 | { 25 | Map scores = Utility.evaluateNER(new PerceptronNERecognizer(), PKU.PKU199801_TEST); 26 | Utility.printNERScore(scores); 27 | } 28 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/recognition/ns/PlaceRecognitionTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.recognition.ns; 2 | 3 | import com.hankcs.hanlp.seg.Dijkstra.DijkstraSegment; 4 | import junit.framework.TestCase; 5 | 6 | public class PlaceRecognitionTest extends TestCase 7 | { 8 | public void testSeg() throws Exception 9 | { 10 | // HanLP.Config.enableDebug(); 11 | DijkstraSegment segment = new DijkstraSegment(); 12 | segment.enableJapaneseNameRecognize(false); 13 | segment.enableTranslatedNameRecognize(false); 14 | segment.enableNameRecognize(false); 15 | segment.enableCustomDictionary(false); 16 | 17 | segment.enablePlaceRecognize(true); 18 | // System.out.println(segment.seg("南翔向宁夏固原市彭阳县红河镇黑牛沟村捐赠了挖掘机")); 19 | } 20 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/seg/Dijkstra/DijkstraSegmentTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.seg.Dijkstra; 2 | 3 | import com.hankcs.hanlp.seg.SegmentTestCase; 4 | import com.hankcs.hanlp.corpus.tag.Nature; 5 | import com.hankcs.hanlp.seg.Segment; 6 | import com.hankcs.hanlp.seg.common.Term; 7 | 8 | import java.util.List; 9 | 10 | public class DijkstraSegmentTest extends SegmentTestCase 11 | { 12 | public void testWrongName() throws Exception 13 | { 14 | Segment segment = new DijkstraSegment(); 15 | List termList = segment.seg("好像向你借钱的人跑了"); 16 | assertNoNature(termList, Nature.nr); 17 | // System.out.println(termList); 18 | } 19 | 20 | public void testIssue770() throws Exception 21 | { 22 | // HanLP.Config.enableDebug(); 23 | Segment segment = new DijkstraSegment(); 24 | List termList = segment.seg("为什么我扔出的瓶子没有人回复?"); 25 | // System.out.println(termList); 26 | assertSegmentationHas(termList, "瓶子 没有"); 27 | } 28 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/seg/Other/AhoCorasickDoubleArrayTrieSegmentTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.seg.Other; 2 | 3 | import com.hankcs.hanlp.HanLP; 4 | import junit.framework.TestCase; 5 | 6 | public class AhoCorasickDoubleArrayTrieSegmentTest extends TestCase 7 | { 8 | public void testLoadMyDictionary() throws Exception 9 | { 10 | AhoCorasickDoubleArrayTrieSegment segment 11 | = new AhoCorasickDoubleArrayTrieSegment("data/dictionary/CoreNatureDictionary.mini.txt"); 12 | HanLP.Config.ShowTermNature = false; 13 | assertEquals("[江西, 鄱阳湖, 干枯]", segment.seg("江西鄱阳湖干枯").toString()); 14 | } 15 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/seg/Other/DoubleArrayTrieSegmentTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.seg.Other; 2 | 3 | import com.hankcs.hanlp.HanLP; 4 | import junit.framework.TestCase; 5 | 6 | public class DoubleArrayTrieSegmentTest extends TestCase 7 | { 8 | public void testLoadMyDictionary() throws Exception 9 | { 10 | DoubleArrayTrieSegment segment = new DoubleArrayTrieSegment("data/dictionary/CoreNatureDictionary.mini.txt"); 11 | HanLP.Config.ShowTermNature = false; 12 | assertEquals("[江西, 鄱阳湖, 干枯]", segment.seg("江西鄱阳湖干枯").toString()); 13 | } 14 | 15 | public void testLoadMyDictionaryWithNature() throws Exception 16 | { 17 | DoubleArrayTrieSegment segment = new DoubleArrayTrieSegment("data/dictionary/CoreNatureDictionary.mini.txt", 18 | "data/dictionary/custom/上海地名.txt ns"); 19 | segment.enablePartOfSpeechTagging(true); 20 | assertEquals("[上海市/ns, 虹口区/ns, 大连西路/ns, 550/m, 号/q]", segment.seg("上海市虹口区大连西路550号").toString()); 21 | } 22 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/seg/common/CWSEvaluatorTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.seg.common; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class CWSEvaluatorTest extends TestCase 6 | { 7 | public void testGetPRF() throws Exception 8 | { 9 | CWSEvaluator evaluator = new CWSEvaluator(); 10 | evaluator.compare("结婚 的 和 尚未 结婚 的", "结婚 的 和尚 未结婚 的"); 11 | CWSEvaluator.Result prf = evaluator.getResult(false); 12 | assertEquals(0.6f, prf.P); 13 | assertEquals(0.5f, prf.R); 14 | } 15 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/suggest/ISuggesterTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.suggest; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class ISuggesterTest extends TestCase 6 | { 7 | public void testRemoveAllSentences() throws Exception 8 | { 9 | ISuggester suggester = new Suggester(); 10 | String[] titleArray = 11 | ( 12 | "威廉王子发表演说 呼吁保护野生动物\n" + 13 | "《时代》年度人物最终入围名单出炉 普京马云入选\n" + 14 | "“黑格比”横扫菲:菲吸取“海燕”经验及早疏散\n" + 15 | "日本保密法将正式生效 日媒指其损害国民知情权\n" + 16 | "英报告说空气污染带来“公共健康危机”" 17 | ).split("\\n"); 18 | for (String title : titleArray) 19 | { 20 | suggester.addSentence(title); 21 | } 22 | 23 | assertEquals(true, suggester.suggest("mayun", 1).size() > 0); 24 | 25 | suggester.removeAllSentences(); 26 | 27 | assertEquals(0, suggester.suggest("mayun", 1).size()); 28 | } 29 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/suggest/scorer/pinyin/PinyinKeyTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.suggest.scorer.pinyin; 2 | 3 | import com.hankcs.hanlp.algorithm.LongestCommonSubstring; 4 | import junit.framework.TestCase; 5 | 6 | public class PinyinKeyTest extends TestCase 7 | { 8 | public void testConstruct() throws Exception 9 | { 10 | PinyinKey pinyinKeyA = new PinyinKey("专题分析"); 11 | PinyinKey pinyinKeyB = new PinyinKey("教室资格"); 12 | // System.out.println(pinyinKeyA); 13 | // System.out.println(pinyinKeyB); 14 | assertEquals(1, LongestCommonSubstring.compute(pinyinKeyA.getFirstCharArray(), pinyinKeyB.getFirstCharArray())); 15 | } 16 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/tokenizer/URLTokenizerTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.tokenizer; 2 | 3 | import com.hankcs.hanlp.seg.common.Term; 4 | import junit.framework.TestCase; 5 | 6 | import java.util.List; 7 | 8 | public class URLTokenizerTest extends TestCase 9 | { 10 | public void testSegment() 11 | { 12 | String text = "随便写点啥吧?abNfxbGRIAUQfGGgvesskbrhEfvCdOHyxfWBq"; 13 | List terms = URLTokenizer.segment(text); 14 | System.out.println(terms); 15 | } 16 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/hankcs/hanlp/utility/SentencesUtilTest.java: -------------------------------------------------------------------------------- 1 | package com.hankcs.hanlp.utility; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class SentencesUtilTest extends TestCase 6 | { 7 | public void testToSentenceList() throws Exception 8 | { 9 | // for (String sentence : SentencesUtil.toSentenceList("逗号把句子切分为意群,表示小于分号大于顿号的停顿。", false)) 10 | // { 11 | // System.out.println(sentence); 12 | // } 13 | assertEquals(1, SentencesUtil.toSentenceList("逗号把句子切分为意群,表示小于分号大于顿号的停顿。", false).size()); 14 | assertEquals(2, SentencesUtil.toSentenceList("逗号把句子切分为意群,表示小于分号大于顿号的停顿。", true).size()); 15 | } 16 | 17 | public void testSplitSentence() throws Exception 18 | { 19 | String content = "我白天是一名语言学习者,晚上是一名初级码农。空的时候喜欢看算法和应用数学书,也喜欢悬疑推理小说,ACG方面喜欢型月、轨迹。喜欢有思想深度的事物,讨厌急躁、拜金与安逸的人\r\n目前在魔都某女校学习,这是我的个人博客。闻道有先后,术业有专攻,请多多关照。"; 20 | assertEquals(12, SentencesUtil.toSentenceList(content).size()); 21 | } 22 | } -------------------------------------------------------------------------------- /im-analysis/src/test/java/com/xy/alysis/ImAnalysisApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.xy.alysis; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ImAnalysisApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-auth/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/ImAuthApplication.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth; 2 | 3 | import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; 4 | import com.xy.auth.security.RSAKeyProperties; 5 | import com.xy.auth.security.SecurityProperties; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 9 | import org.springframework.scheduling.annotation.EnableAsync; 10 | 11 | 12 | 13 | @EnableAsync 14 | @EnableKnife4j 15 | @SpringBootApplication 16 | @EnableConfigurationProperties(value = {SecurityProperties.class, RSAKeyProperties.class}) 17 | public class ImAuthApplication { 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(ImAuthApplication.class, args); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/annotations/count/TakeCount.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.annotations.count; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface TakeCount { 11 | } 12 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/annotations/count/TakeCountAspect.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.annotations.count; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.aspectj.lang.JoinPoint; 5 | import org.aspectj.lang.annotation.After; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Before; 8 | import org.springframework.stereotype.Component; 9 | 10 | 11 | /** 12 | * 记录接口耗时 13 | */ 14 | @Slf4j 15 | @Aspect 16 | @Component 17 | public class TakeCountAspect { 18 | 19 | //用threadlocal记录当前线程的开始访问时间 20 | private final ThreadLocal startTime = new ThreadLocal<>(); 21 | 22 | @Before("@annotation(takeCount)") 23 | public void doBefore(TakeCount takeCount) { 24 | //记录开始时间 25 | startTime.set(System.currentTimeMillis()); 26 | } 27 | 28 | @After("@annotation(TakeCount)") 29 | public void doAfter(JoinPoint point) { 30 | log.info("{}访问耗时为:{}ms", point.getSignature().getName(), (System.currentTimeMillis() - startTime.get())); 31 | } 32 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | @Configuration 9 | public class CorsConfig { 10 | 11 | @Bean 12 | public WebMvcConfigurer corsConfigurer() { 13 | return new WebMvcConfigurer() { 14 | @Override 15 | public void addCorsMappings(CorsRegistry registry) { 16 | registry.addMapping("/**") 17 | .allowedOrigins("*") 18 | .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") 19 | .allowedHeaders("*") 20 | .maxAge(3600); 21 | } 22 | }; 23 | } 24 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/config/Knife4jConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.config; 2 | 3 | import io.swagger.v3.oas.models.OpenAPI; 4 | import io.swagger.v3.oas.models.info.Info; 5 | import io.swagger.v3.oas.models.info.License; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | @Configuration 10 | public class Knife4jConfig { 11 | @Bean 12 | public OpenAPI springShopOpenAPI() { 13 | return new OpenAPI() 14 | .info(new Info().title("im-auth") 15 | .description("im-auth接口文档") 16 | .version("v1.0") 17 | .license(new License().name("Apache 2.0").url("http://springdoc.org"))); 18 | } 19 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/config/QRConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.config; 2 | 3 | import cn.hutool.extra.qrcode.QrConfig; 4 | import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | import java.awt.*; 10 | 11 | @Configuration 12 | @ConfigurationProperties(prefix = "qrcode") 13 | public class QRConfig { 14 | 15 | private int width = 300; // 默认宽度 16 | private int height = 300; // 默认高度 17 | private String errorCorrectionLevel = "L"; // 容错级别 18 | 19 | @Bean 20 | public QrConfig qrConfig() { 21 | //初始宽度和高度 22 | QrConfig qrConfig = new QrConfig(width, height); 23 | 24 | //设置边距,即二维码和边框的距离 25 | qrConfig.setMargin(2); 26 | //设置二维码的纠错级别 27 | qrConfig.setErrorCorrection(ErrorCorrectionLevel.valueOf(errorCorrectionLevel)); 28 | //设置前景色 29 | qrConfig.setForeColor(Color.BLACK); 30 | //设置背景色 31 | qrConfig.setBackColor(Color.WHITE); 32 | 33 | return qrConfig; 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.http.converter.HttpMessageConverter; 5 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author dense 12 | */ 13 | @Configuration 14 | public class WebConfig implements WebMvcConfigurer { 15 | 16 | @Override 17 | public void configureMessageConverters(List> converters) { 18 | converters.addFirst(new MappingJackson2HttpMessageConverter()); 19 | } 20 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/constant/QrcodeConstant.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.constant; 2 | 3 | public class QrcodeConstant { 4 | 5 | // 登录二维码前缀 6 | public static final String QRCODE_PREFIX = "IM-LOGIN-QRCODE-"; 7 | 8 | // 待扫描 9 | public static final String QRCODE_PENDING = "PENDING"; 10 | // 已扫描待授权 11 | public static final String QRCODE_SCANNED = "SCANNED"; 12 | // 已过期 13 | public static final String QRCODE_EXPIRED = "EXPIRED"; 14 | // 无效二维码 15 | public static final String QRCODE_INVALID = "INVALID"; 16 | // 已授权 17 | public static final String QRCODE_AUTHORIZED = "AUTHORIZED"; 18 | // 错误状态 19 | public static final String QRCODE_ERROR = "ERROR"; 20 | 21 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/domain/LoginRequest.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.domain; 2 | 3 | import lombok.*; 4 | 5 | @Data 6 | @Setter 7 | @Getter 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class LoginRequest { 11 | 12 | // 用户名、手机号或二维码字符串 13 | private String principal; 14 | 15 | // 加密后的密码、验证码或二维码登录密码 16 | private String credentials; 17 | 18 | // 认证类型,例如 "form", "sms", "scan" 19 | private String authType; 20 | } 21 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/domain/dto/ImUserDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.domain.dto; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * @TableName im_user 12 | */ 13 | @TableName(value = "im_user") 14 | @Data 15 | public class ImUserDto implements Serializable { 16 | 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId 23 | @TableField(value = "user_id") 24 | private String userId; 25 | /** 26 | * 27 | */ 28 | @TableField(value = "user_name") 29 | private String username; 30 | /** 31 | * 32 | */ 33 | @TableField(value = "password") 34 | private String password; 35 | /** 36 | * 37 | */ 38 | @TableField(value = "mobile") 39 | private String mobile; 40 | /** 41 | * 42 | */ 43 | @TableField(value = "create_time") 44 | private Long createTime; 45 | /** 46 | * 47 | */ 48 | @TableField(value = "update_time") 49 | private Long updateTime; 50 | 51 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/domain/vo/UserVo.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.domain.vo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @TableName im_user_data 7 | */ 8 | @Data 9 | public class UserVo { 10 | 11 | 12 | private String userId; 13 | 14 | private String name; 15 | 16 | private String avatar; 17 | 18 | private Integer userSex; 19 | 20 | private String birthDay; 21 | 22 | private String location; 23 | 24 | private String selfSignature; 25 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/mapper/ImUserDataMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.auth.domain.dto.ImUserDataDto; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_user_data】的数据库操作Mapper 10 | */ 11 | @Mapper 12 | public interface ImUserDataMapper extends BaseMapper { 13 | 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/mapper/ImUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.auth.domain.dto.ImUserDto; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_user】的数据库操作Mapper 10 | * @createDate 2024-03-17 01:34:00 11 | * @Entity generator.domain.ImUser 12 | */ 13 | @Mapper 14 | public interface ImUserMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/response/IResult.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.response; 2 | 3 | 4 | public interface IResult { 5 | /** 6 | * 获取状态码 7 | * 8 | * @return 状态码 9 | */ 10 | Integer getCode(); 11 | 12 | /** 13 | * 获取消息体 14 | * 15 | * @return 消息体 16 | */ 17 | String getMessage(); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/response/ResponseNotIntercept.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.response; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 返回放行注解 7 | * 在类和方法上使用此注解表示不会在ResponseResult类中进一步封装返回值,直接返回原生值 8 | */ 9 | @Target({ElementType.METHOD, ElementType.TYPE}) //可以在字段、方法 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface ResponseNotIntercept { 13 | String value() default ""; 14 | } 15 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/response/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.response; 2 | 3 | /** 4 | * 常用结果的枚举 5 | */ 6 | public enum ResultEnum implements IResult { 7 | 8 | ERROR(100, "失败"), 9 | 10 | SUCCESS(200, "成功"), 11 | 12 | VALIDATE_FAILED(400, "参数错误"), 13 | 14 | COMMON_FAILED(500, "系统错误"), 15 | 16 | FORBIDDEN(2004, "没有权限访问资源"), 17 | 18 | PASSWD_ERROR(1000, "用户名或密码错误"), 19 | 20 | USER_EMPTY(1000, "用户不存在"); 21 | 22 | private Integer code; 23 | private String message; 24 | 25 | //省略get、set方法和构造方法 26 | 27 | ResultEnum(Integer code, String message) { 28 | this.code = code; 29 | this.message = message; 30 | } 31 | 32 | @Override 33 | public Integer getCode() { 34 | return code; 35 | } 36 | 37 | public void setCode(Integer code) { 38 | this.code = code; 39 | } 40 | 41 | @Override 42 | public String getMessage() { 43 | return message; 44 | } 45 | 46 | public void setMessage(String message) { 47 | this.message = message; 48 | } 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/security/SecurityProperties.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.security; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.cloud.context.config.annotation.RefreshScope; 6 | 7 | 8 | /** 9 | * Security框架配置信息 10 | */ 11 | 12 | @Data 13 | @RefreshScope 14 | @ConfigurationProperties( 15 | prefix = "security" 16 | ) 17 | public class SecurityProperties { 18 | 19 | /** 20 | * 过滤器忽略地址 21 | */ 22 | private String[] ignoreUrl; 23 | 24 | /** 25 | * jwt 盐值 26 | */ 27 | private String secret; 28 | 29 | /** 30 | * jwt token 过期时间 单位:min 31 | */ 32 | private Integer expiration; 33 | 34 | 35 | private RSAKeyProperties RSAKeyProperties; 36 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/security/exception/AuthenticationFailException.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.security.exception; 2 | 3 | import com.xy.auth.response.ResultCode; 4 | import org.springframework.security.core.AuthenticationException; 5 | 6 | public class AuthenticationFailException extends AuthenticationException { 7 | 8 | private ResultCode resultCode; 9 | 10 | public AuthenticationFailException(String msg, Throwable cause) { 11 | super(msg, cause); 12 | } 13 | 14 | public AuthenticationFailException(String msg) { 15 | super(msg); 16 | } 17 | 18 | public AuthenticationFailException(ResultCode resultCode) { 19 | super(resultCode.getEn()); 20 | this.resultCode = resultCode; 21 | } 22 | 23 | public ResultCode getResultCode() { 24 | return resultCode; 25 | } 26 | 27 | public void setResultCode(ResultCode resultCode) { 28 | this.resultCode = resultCode; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/security/handle/LoginAccessDefineHandler.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.security.handle; 2 | 3 | import com.xy.auth.utils.ResponseUtils; 4 | import com.xy.imcore.model.IMessageWrap; 5 | import jakarta.servlet.ServletException; 6 | import jakarta.servlet.http.HttpServletRequest; 7 | import jakarta.servlet.http.HttpServletResponse; 8 | import org.springframework.security.access.AccessDeniedException; 9 | import org.springframework.security.web.access.AccessDeniedHandler; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.io.IOException; 13 | 14 | /** 15 | * 权限不足处理器 16 | */ 17 | @Component 18 | public class LoginAccessDefineHandler implements AccessDeniedHandler { 19 | 20 | 21 | @Override 22 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { 23 | 24 | IMessageWrap wrap = new IMessageWrap(700, "您没有开通对应的权限,请联系管理员!"); 25 | 26 | ResponseUtils.out(response, wrap); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/security/handle/LoginAuthenticationHandler.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.security.handle; 2 | 3 | import com.xy.auth.utils.ResponseUtils; 4 | import com.xy.imcore.model.IMessageWrap; 5 | import jakarta.servlet.ServletException; 6 | import jakarta.servlet.http.HttpServletRequest; 7 | import jakarta.servlet.http.HttpServletResponse; 8 | import org.springframework.security.core.AuthenticationException; 9 | import org.springframework.security.web.AuthenticationEntryPoint; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.io.IOException; 13 | 14 | /** 15 | * 匿名用户访问资源处理器 16 | */ 17 | @Component 18 | public class LoginAuthenticationHandler implements AuthenticationEntryPoint { 19 | 20 | @Override 21 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { 22 | 23 | IMessageWrap wrap = new IMessageWrap(600, "匿名用户没有权限进行访问!"); 24 | 25 | ResponseUtils.out(response, wrap); 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/security/token/UserAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.security.token; 2 | 3 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 4 | 5 | /** 6 | * 账号密码登录 7 | */ 8 | public class UserAuthenticationToken extends UsernamePasswordAuthenticationToken { 9 | 10 | 11 | public UserAuthenticationToken(Object principal, Object credentials) { 12 | super(principal, credentials); 13 | } 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/service/ImUserService.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.auth.domain.dto.ImUserDto; 5 | import com.xy.auth.domain.vo.UserVo; 6 | 7 | 8 | /** 9 | * @author dense 10 | * @description 针对表【im_user】的数据库操作Service 11 | * @createDate 2024-03-17 01:34:00 12 | */ 13 | public interface ImUserService extends IService { 14 | 15 | UserVo info(String userId); 16 | 17 | boolean isOnline(String userId); 18 | } 19 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/service/QrCodeService.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.service; 2 | 3 | import jakarta.servlet.http.HttpServletResponse; 4 | 5 | 6 | public interface QrCodeService { 7 | 8 | public String createCodeToBase64(String content); 9 | 10 | public void createCodeToStream(String content, HttpServletResponse response); 11 | } -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/service/SmsService.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.service; 2 | 3 | public interface SmsService { 4 | 5 | String sendMessage(String phoneNum) throws Exception; 6 | } 7 | -------------------------------------------------------------------------------- /im-auth/src/main/java/com/xy/auth/service/impl/QrCodeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth.service.impl; 2 | 3 | import cn.hutool.extra.qrcode.QrCodeException; 4 | import cn.hutool.extra.qrcode.QrCodeUtil; 5 | import cn.hutool.extra.qrcode.QrConfig; 6 | import com.xy.auth.service.QrCodeService; 7 | import jakarta.annotation.Resource; 8 | import jakarta.servlet.http.HttpServletResponse; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.io.IOException; 13 | 14 | 15 | @Slf4j 16 | @Service 17 | public class QrCodeServiceImpl implements QrCodeService { 18 | 19 | @Resource 20 | private QrConfig config; 21 | 22 | //生成到文件 23 | public String createCodeToBase64(String content) { 24 | try { 25 | // 生成 Base64 二维码 26 | return QrCodeUtil.generateAsBase64(content, config, QrCodeUtil.QR_TYPE_SVG); 27 | } catch (QrCodeException e) { 28 | e.printStackTrace(); 29 | } 30 | return null; 31 | } 32 | 33 | //生成到流 34 | public void createCodeToStream(String content, HttpServletResponse response) { 35 | try { 36 | QrCodeUtil.generate(content, config, "png", response.getOutputStream()); 37 | } catch (QrCodeException | IOException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /im-auth/src/main/resources/application-swagger.yml: -------------------------------------------------------------------------------- 1 | #springdoc相关配置 2 | springdoc: 3 | swagger-ui: 4 | path: /swagger-ui.html 5 | tags-sorter: alpha 6 | operations-sorter: alpha 7 | api-docs: 8 | enabled: true 9 | path: /v3/api-docs 10 | group-configs: 11 | - group: 'auth' 12 | paths-to-match: '/**' 13 | packages-to-scan: com.xy.server #改成你自己的包名,一般到启动类的包名 14 | 15 | 16 | 17 | # TODO: knife4j相关配置 可以不用改 18 | knife4j: 19 | enable: true # 开启增强配置 20 | production: false # 开启生产环境屏蔽 21 | setting: 22 | language: zh_cn # 默认中文 23 | swagger-model-name: 实体类 24 | -------------------------------------------------------------------------------- /im-auth/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Tomcat 2 | server: 3 | port: 4800 4 | 5 | # Spring 6 | spring: 7 | application: 8 | # 应用名称 9 | name: im-auth 10 | profiles: 11 | # 环境配置 12 | active: dev 13 | cloud: 14 | sentinel: 15 | # 取消控制台懒加载 16 | eager: true 17 | transport: 18 | # sentinel控制台地址 19 | dashboard: localhost:8858 20 | nacos: 21 | discovery: 22 | # 服务注册地址 23 | server-addr: localhost:8848 24 | username: nacos 25 | password: nacos 26 | config: 27 | # 配置中心地址 28 | server-addr: localhost:8848 29 | # 配置文件格式 30 | file-extension: yml 31 | # 共享配置 32 | shared-configs: 33 | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} 34 | -------------------------------------------------------------------------------- /im-auth/src/main/resources/mapper/ImUserDataMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-auth/src/main/resources/mapper/ImUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-auth/src/test/java/com/xy/auth/ImAuthApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.xy.auth; 2 | 3 | import org.junit.jupiter.api.Test; 4 | //import org.springframework.boot.test.context.SpringBootTest; 5 | // 6 | //@SpringBootTest 7 | class ImAuthApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-common/im-core/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/constants/Constant.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.constants; 2 | 3 | public class Constant { 4 | 5 | // 声明交换机和绑定队列 6 | public static final String EXCHANGENAME = "IM-SERVER"; 7 | 8 | 9 | public static final String ROUTERKEYPREFIX = "IM-"; 10 | 11 | 12 | public static final String IMUSERPREFIX = "IM-USER-"; 13 | 14 | public static final String IMUSER = "userId"; 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/enums/IMStatus.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.enums; 2 | 3 | 4 | /** 5 | * 好友关系的状态:1表示正常,0表示删除。可以为空,表示状态未知或未记录。 6 | * 拉黑标志: 1表示正常,0表示拉黑。可以为空,表示拉黑状态未知或未记录。 7 | * 阅读状态: 1表示已读,0表示未读。可以为空,表示阅读状态未知或未记录。 8 | * 审批状态: 1表示同意,0表示拒绝 9 | * 群组类型: 1表示私有群(类似微信),0表示公开群(类似QQ) 10 | * 全员禁言: 1表示不禁言,0表示全员禁言 11 | * 群组状态: 1表示正常,0表示解散 12 | */ 13 | 14 | public enum IMStatus { 15 | YES(1, "yes"), 16 | NO(0, "no"); 17 | 18 | 19 | private int code; 20 | 21 | private String status; 22 | 23 | IMStatus(int code, String status) { 24 | this.code = code; 25 | this.status = status; 26 | } 27 | 28 | public int getCode() { 29 | return code; 30 | } 31 | 32 | public void setCode(int code) { 33 | this.code = code; 34 | } 35 | 36 | public String getStatus() { 37 | return status; 38 | } 39 | 40 | public void setStatus(String status) { 41 | this.status = status; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/enums/IMemberStatus.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.enums; 2 | 3 | /** 4 | * 群成员角色枚举 5 | */ 6 | public enum IMemberStatus { 7 | 8 | NORMAL(0, "普通成员"), 9 | ADMIN(1, "管理员"), 10 | GROUP_OWNER(2, "群主"), 11 | MUTED(3, "禁言成员"), 12 | REMOVED(4, "已移除成员"); 13 | 14 | private final Integer code; 15 | private final String desc; 16 | 17 | IMemberStatus(Integer status, String desc) { 18 | this.desc = desc; 19 | this.code = status; 20 | } 21 | 22 | public static IMemberStatus getByCode(Integer code) { 23 | for (IMemberStatus v : values()) { 24 | if (v.code.equals(code)) { 25 | return v; 26 | } 27 | } 28 | return null; 29 | } 30 | 31 | 32 | public String getDesc() { 33 | return desc; 34 | } 35 | 36 | public Integer getCode() { 37 | return code; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/enums/IMessageContentType.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.enums; 2 | 3 | public enum IMessageContentType { 4 | 5 | TEXT(1, "文字"), 6 | IMAGE(2, "图片"), 7 | VIDEO(3, "视频"), 8 | AUDIO(4, "语音"), 9 | FILE(5, "文件"), 10 | LOCAL(6, "位置"), 11 | TIP(10, "系统提示"), 12 | 13 | RTC_CALL(101, "呼叫"), 14 | RTC_ACCEPT(102, "接受"), 15 | RTC_REJECT(103, "拒绝"), 16 | RTC_CANCEL(104, "取消呼叫"), 17 | RTC_FAILED(105, "呼叫失败"), 18 | RTC_HANDUP(106, "挂断"), 19 | RTC_CANDIDATE(107, "同步candidate"); 20 | 21 | 22 | private Integer code; 23 | 24 | private String type; 25 | 26 | IMessageContentType(int code, String type) { 27 | this.code = code; 28 | this.type = type; 29 | } 30 | 31 | public static IMessageContentType getByCode(Integer code) { 32 | for (IMessageContentType v : values()) { 33 | if (v.code.equals(code)) { 34 | return v; 35 | } 36 | } 37 | return null; 38 | } 39 | 40 | public Integer getCode() { 41 | return code; 42 | } 43 | 44 | public void setCode(Integer code) { 45 | this.code = code; 46 | } 47 | 48 | public String getType() { 49 | return type; 50 | } 51 | 52 | public void setType(String type) { 53 | this.type = type; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/enums/IMessageReadStatus.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.enums; 2 | 3 | public enum IMessageReadStatus { 4 | 5 | UNREAD(0, "未读"), 6 | ALREADY_READ(1, "已读"), 7 | RECALL(2, "已撤回"); 8 | 9 | private Integer code; 10 | 11 | private String desc; 12 | 13 | IMessageReadStatus(Integer index, String desc) { 14 | this.code = index; 15 | this.desc = desc; 16 | } 17 | 18 | public static IMessageReadStatus fromCode(Integer code) { 19 | for (IMessageReadStatus typeEnum : values()) { 20 | if (typeEnum.code.equals(code)) { 21 | return typeEnum; 22 | } 23 | } 24 | return null; 25 | } 26 | 27 | public String description() { 28 | return desc; 29 | } 30 | 31 | public Integer code() { 32 | return this.code; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/enums/IMessageSendStatus.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.enums; 2 | 3 | public enum IMessageSendStatus { 4 | 5 | SUCCESS(0, "成功"), 6 | FAILED(1, "失败"), 7 | SENDING(2, "发送中"), 8 | OTHER(3, "其它异常"); 9 | 10 | private Integer code; 11 | 12 | private String status; 13 | 14 | IMessageSendStatus(Integer index, String status) { 15 | this.code = index; 16 | this.status = status; 17 | } 18 | 19 | public Integer getCode() { 20 | return code; 21 | } 22 | 23 | public void setCode(Integer code) { 24 | this.code = code; 25 | } 26 | 27 | public String getStatus() { 28 | return status; 29 | } 30 | 31 | public void setStatus(String status) { 32 | this.status = status; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/enums/IMessageType.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.enums; 2 | 3 | public enum IMessageType { 4 | 5 | ERROR(-1, "信息异常"), 6 | LOGIN_OVER(900, "登录过期"), 7 | LOGIN(1000, "登录"), 8 | HEART_BEAT(1001, "心跳"), 9 | FORCE_LOGOUT(1002, "强制下线"), 10 | SINGLE_MESSAGE(1003, "私聊消息"), 11 | GROUP_MESSAGE(1004, "群发消息"), 12 | VIDEO_MESSAGE(1005, "视频通话"), 13 | 14 | ROBOT(1006, "机器人"), 15 | 16 | PUBLIC(1007, "公众号"); 17 | 18 | private Integer code; 19 | 20 | private String type; 21 | 22 | IMessageType(Integer code, String type) { 23 | this.code = code; 24 | this.type = type; 25 | } 26 | 27 | public static IMessageType getByCode(Integer code) { 28 | for (IMessageType v : values()) { 29 | if (v.code.equals(code)) { 30 | return v; 31 | } 32 | } 33 | return null; 34 | } 35 | 36 | public Integer getCode() { 37 | return code; 38 | } 39 | 40 | public void setCode(Integer code) { 41 | this.code = code; 42 | } 43 | 44 | public String getType() { 45 | return type; 46 | } 47 | 48 | public void setType(String type) { 49 | this.type = type; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/model/IMGroupMessageDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.model; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.xy.imcore.enums.IMessageType; 6 | import jakarta.validation.constraints.NotBlank; 7 | import jakarta.validation.constraints.Size; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | import lombok.experimental.Accessors; 12 | 13 | import java.io.Serial; 14 | import java.io.Serializable; 15 | import java.util.List; 16 | 17 | /** 18 | * group of chat messages 19 | */ 20 | @Data 21 | @Accessors(chain = true) 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | public class IMGroupMessageDto extends IMessageDto implements Serializable { 25 | 26 | @Serial 27 | private static final long serialVersionUID = 1L; 28 | /** 29 | * group id 30 | */ 31 | @NotBlank(message = "群聊id不能为空") 32 | private String groupId; 33 | 34 | /** 35 | * group members 36 | */ 37 | @JsonInclude(JsonInclude.Include.NON_NULL) 38 | private List to_List; 39 | 40 | /** 41 | * message type 42 | */ 43 | private Integer messageType = IMessageType.GROUP_MESSAGE.getCode(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/model/IMRegisterUserDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.model; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.io.Serial; 10 | import java.io.Serializable; 11 | 12 | @Data 13 | @Accessors(chain = true) 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class IMRegisterUserDto implements Serializable { 17 | 18 | @Serial 19 | private static final long serialVersionUID = 1L; 20 | 21 | private String userId; 22 | 23 | private String token; 24 | 25 | private String brokerId; 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/model/IMSingleMessageDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.model; 2 | 3 | 4 | import com.xy.imcore.enums.IMessageType; 5 | import jakarta.validation.constraints.NotBlank; 6 | import jakarta.validation.constraints.Size; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | import lombok.experimental.Accessors; 11 | 12 | import java.io.Serial; 13 | import java.io.Serializable; 14 | 15 | /** 16 | * single of chat messages 17 | * @author dense 18 | */ 19 | @Data 20 | @Accessors(chain = true) 21 | @NoArgsConstructor 22 | @AllArgsConstructor 23 | public class IMSingleMessageDto extends IMessageDto implements Serializable { 24 | 25 | @Serial 26 | private static final long serialVersionUID = 1L; 27 | 28 | /** 29 | * send to somebody 30 | */ 31 | @NotBlank(message = "接收人id不能为空") 32 | private String toId; 33 | 34 | /** 35 | * message type 36 | */ 37 | private Integer messageType = IMessageType.SINGLE_MESSAGE.getCode(); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/model/IMVideoMessageDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serial; 9 | import java.io.Serializable; 10 | 11 | @Data 12 | @Accessors(chain = true) 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class IMVideoMessageDto implements Serializable { 16 | 17 | @Serial 18 | private static final long serialVersionUID = 1L; 19 | 20 | private String fromId; 21 | 22 | private String toId; 23 | 24 | private String url; 25 | 26 | private Integer type; 27 | 28 | public String getFromId() { 29 | return fromId; 30 | } 31 | 32 | public void setFromId(String fromId) { 33 | this.fromId = fromId; 34 | } 35 | 36 | public String getToId() { 37 | return toId; 38 | } 39 | 40 | public void setToId(String toId) { 41 | this.toId = toId; 42 | } 43 | 44 | public String getUrl() { 45 | return url; 46 | } 47 | 48 | public void setUrl(String url) { 49 | this.url = url; 50 | } 51 | 52 | public Integer getType() { 53 | return type; 54 | } 55 | 56 | public void setType(Integer type) { 57 | this.type = type; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/model/IMWsConnMessage.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.model; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonSubTypes; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.experimental.Accessors; 10 | 11 | import java.io.Serial; 12 | import java.io.Serializable; 13 | 14 | 15 | /** 16 | * websocket connection info 17 | * 18 | * @param 19 | */ 20 | @Data 21 | @Accessors(chain = true) 22 | @Builder 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | @JsonSubTypes({ 26 | @JsonSubTypes.Type(value = String.class), 27 | // 你可以根据需要添加更多的子类型 28 | // @JsonSubTypes.Type(value = AnotherClass.class, name = "anotherClass") 29 | }) 30 | public class IMWsConnMessage implements Serializable { 31 | 32 | @Serial 33 | private static final long serialVersionUID = 1L; 34 | 35 | /** 36 | * connection type 37 | */ 38 | private Integer code; 39 | 40 | /** 41 | * connection user's token 42 | */ 43 | private String token; 44 | 45 | /** 46 | * connection information 47 | */ 48 | private T data; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /im-common/im-core/src/main/java/com/xy/imcore/model/IMessageWrap.java: -------------------------------------------------------------------------------- 1 | package com.xy.imcore.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serial; 9 | import java.io.Serializable; 10 | 11 | @Data 12 | @Accessors(chain = true) 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class IMessageWrap implements Serializable { 16 | 17 | @Serial 18 | private static final long serialVersionUID = 1L; 19 | 20 | private Integer code; 21 | 22 | private T data; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/ImConnectApplication.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect; 2 | 3 | 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | @Slf4j 7 | public class ImConnectApplication { 8 | 9 | 10 | public static void main(String[] args) { 11 | new ApplicationBootstrap().start(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/config/IMRedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.config; 2 | 3 | /** 4 | * redis配置 5 | */ 6 | public class IMRedisConfig { 7 | 8 | private RedisConfig redis; 9 | 10 | public RedisConfig getRedis() { 11 | return redis; 12 | } 13 | 14 | public void setRedis(RedisConfig redis) { 15 | this.redis = redis; 16 | } 17 | 18 | public static class RedisConfig { 19 | 20 | private String host; 21 | private int port; 22 | private String password; 23 | private int timeout; 24 | private int database; 25 | 26 | public String getHost() { 27 | return host; 28 | } 29 | 30 | public void setHost(String host) { 31 | this.host = host; 32 | } 33 | 34 | public int getPort() { 35 | return port; 36 | } 37 | 38 | public void setPort(int port) { 39 | this.port = port; 40 | } 41 | 42 | public String getPassword() { 43 | return password; 44 | } 45 | 46 | public void setPassword(String password) { 47 | this.password = password; 48 | } 49 | 50 | public int getTimeout() { 51 | return timeout; 52 | } 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/config/LogConstant.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.config; 2 | 3 | 4 | /** 5 | * 业务名称 日志配置 6 | * 对应日志文件 logback.xml 7 | */ 8 | public class LogConstant { 9 | 10 | public final static String MAIN = "IM-Connect"; 11 | 12 | public final static String CONFIG = "IM-ConfigCenter"; 13 | 14 | public final static String NETTY = "NettyServer"; 15 | 16 | public final static String RABBITMQ = "RabbitMQServer"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/config/loader/YamlConfigLoader.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.config.loader; 2 | 3 | import org.yaml.snakeyaml.Yaml; 4 | 5 | import java.io.InputStream; 6 | 7 | public class YamlConfigLoader { 8 | 9 | public static T loadConfig(String filePath, Class clazz) { 10 | Yaml yaml = new Yaml(); 11 | try (InputStream in = YamlConfigLoader.class 12 | .getClassLoader() 13 | .getResourceAsStream(filePath)) { 14 | if (in == null) { 15 | throw new IllegalArgumentException("File not found: " + filePath); 16 | } 17 | return yaml.loadAs(in, clazz); 18 | } catch (Exception e) { 19 | throw new RuntimeException("Failed to load config", e); 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/message/process/MessageProcess.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.message.process; 2 | 3 | import com.xy.imcore.model.IMessageWrap; 4 | 5 | /** 6 | * 消息处理接口 7 | */ 8 | public interface MessageProcess { 9 | 10 | void dispose(IMessageWrap IMessageWrap); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/netty/factory/NettyVirtualThreadFactory.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.netty.factory; 2 | 3 | import io.netty.util.concurrent.DefaultThreadFactory; 4 | 5 | /** 6 | * 线程工厂 7 | */ 8 | public class NettyVirtualThreadFactory extends DefaultThreadFactory { 9 | 10 | /** 11 | * 线程工厂构造函数 12 | * 13 | * @param poolType 线程池类型 14 | * @param priority 线程数量 15 | */ 16 | public NettyVirtualThreadFactory(Class poolType, int priority) { 17 | super(poolType, priority); 18 | } 19 | 20 | /** 21 | * 创建虚拟线程 22 | * 23 | * @param r 线程 24 | * @param name 线程名称 25 | * @return 线程 26 | */ 27 | @Override 28 | protected Thread newThread(Runnable r, String name) { 29 | // 直接使用 JDK 提供的虚拟线程创建 API 30 | return Thread.ofVirtual() 31 | .name("Virtual-Thread-" + name, 0) 32 | .unstarted(r); 33 | } 34 | } -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/netty/process/HeartBeatProcess.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.netty.process; 2 | 3 | import com.xy.connect.config.ConfigCenter; 4 | import com.xy.connect.config.LogConstant; 5 | import com.xy.connect.utils.JedisUtil; 6 | import com.xy.connect.utils.JsonUtil; 7 | import com.xy.connect.utils.MessageUtils; 8 | import com.xy.imcore.enums.IMessageType; 9 | import com.xy.imcore.model.IMWsConnMessage; 10 | import io.netty.channel.ChannelHandlerContext; 11 | import io.netty.util.AttributeKey; 12 | import lombok.extern.slf4j.Slf4j; 13 | 14 | import static com.xy.imcore.constants.Constant.IMUSERPREFIX; 15 | 16 | @Slf4j(topic = LogConstant.NETTY) 17 | public class HeartBeatProcess implements WsProcess { 18 | 19 | @Override 20 | public void process(ChannelHandlerContext ctx, IMWsConnMessage sendInfo) { 21 | 22 | String token = sendInfo.getToken(); 23 | 24 | String userId = parseUsername(ctx, token); 25 | 26 | // 响应ws 27 | MessageUtils.send(ctx, sendInfo.setCode(IMessageType.HEART_BEAT.getCode())); 28 | 29 | // 设置心跳时间 用于 用户 redis 信息续期 30 | JedisUtil.getInstance().expire(IMUSERPREFIX + userId, ConfigCenter.nettyConfig.getNettyConfig().getHeartBeatTime() * 2); 31 | 32 | log.info("用户:{} 心跳中...... ", userId); 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/netty/service/tcp/codec/MessageEncoder.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.netty.service.tcp.codec; 2 | 3 | 4 | import com.xy.connect.utils.JsonUtil; 5 | import com.xy.imcore.model.IMWsConnMessage; 6 | import io.netty.buffer.ByteBuf; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.handler.codec.MessageToByteEncoder; 9 | 10 | 11 | public class MessageEncoder extends MessageToByteEncoder { 12 | 13 | @Override 14 | protected void encode(ChannelHandlerContext channelHandlerContext, IMWsConnMessage message, 15 | ByteBuf byteBuf) throws Exception { 16 | String text = JsonUtil.toJSONString(message); 17 | 18 | byte[] bytes = text.getBytes("UTF-8"); 19 | // 写入长度 20 | byteBuf.writeLong(bytes.length); 21 | // 写入命令体 22 | byteBuf.writeBytes(bytes); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/netty/service/websocket/codec/MessageDecoder.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.netty.service.websocket.codec; 2 | 3 | 4 | import com.xy.connect.utils.JsonUtil; 5 | import com.xy.imcore.model.IMWsConnMessage; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.MessageToMessageDecoder; 8 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; 9 | 10 | import java.util.List; 11 | 12 | public class MessageDecoder extends MessageToMessageDecoder { 13 | 14 | @Override 15 | protected void decode(ChannelHandlerContext channelHandlerContext, 16 | TextWebSocketFrame textWebSocketFrame, 17 | List list) throws Exception { 18 | list.add(JsonUtil.parseObject(textWebSocketFrame.text(), IMWsConnMessage.class)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/netty/service/websocket/codec/MessageEncoder.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.netty.service.websocket.codec; 2 | 3 | 4 | import com.xy.connect.utils.JsonUtil; 5 | import com.xy.imcore.model.IMWsConnMessage; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.MessageToMessageEncoder; 8 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; 9 | 10 | import java.util.List; 11 | 12 | public class MessageEncoder extends MessageToMessageEncoder { 13 | 14 | @Override 15 | protected void encode(ChannelHandlerContext channelHandlerContext, IMWsConnMessage message, 16 | List list) throws Exception { 17 | list.add(new TextWebSocketFrame(JsonUtil.toJSONString(message))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /im-connect/src/main/java/com/xy/connect/utils/MessageUtils.java: -------------------------------------------------------------------------------- 1 | package com.xy.connect.utils; 2 | 3 | import com.xy.imcore.model.IMWsConnMessage; 4 | import io.netty.channel.ChannelHandlerContext; 5 | 6 | public class MessageUtils { 7 | 8 | public static boolean sendError(ChannelHandlerContext ctx, Integer code, String errorInfo) { 9 | return send(ctx, IMWsConnMessage.builder().code(code).data(errorInfo).build()); 10 | } 11 | 12 | public static boolean send(ChannelHandlerContext ctx, IMWsConnMessage msg) { 13 | if (ctx == null || msg == null || !ctx.channel().isOpen()) { 14 | return false; 15 | } 16 | ctx.channel().writeAndFlush(msg); 17 | return true; 18 | } 19 | 20 | public static void close(ChannelHandlerContext ctx) { 21 | ctx.close(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /im-connect/src/main/resources/mq.yml: -------------------------------------------------------------------------------- 1 | rabbitMQ: 2 | address: localhost 3 | port: 5672 4 | username: guest 5 | password: guest 6 | virtual: / -------------------------------------------------------------------------------- /im-connect/src/main/resources/nacos.yml: -------------------------------------------------------------------------------- 1 | nacosConfig: 2 | name: im-connect 3 | address: localhost 4 | group: DEFAULT_GROUP 5 | port: 8848 6 | username: nacos 7 | password: nacos 8 | version: 1.0.0 -------------------------------------------------------------------------------- /im-connect/src/main/resources/netty.yml: -------------------------------------------------------------------------------- 1 | nettyConfig: 2 | heartBeatTime: 30000 3 | bossThreadSize: 4 4 | workThreadSize: 16 5 | tcpConfig: 6 | enable: false 7 | port: 8 | - 9000 9 | - 9001 10 | - 9002 11 | webSocketConfig: 12 | enable: true 13 | port: 14 | - 19000 15 | - 19001 16 | - 19002 -------------------------------------------------------------------------------- /im-connect/src/main/resources/redis.yml: -------------------------------------------------------------------------------- 1 | redis: 2 | host: localhost 3 | port: 6379 4 | password: 5 | -------------------------------------------------------------------------------- /im-connect/target/classes/mq.yml: -------------------------------------------------------------------------------- 1 | rabbitMQ: 2 | address: localhost 3 | port: 5672 4 | username: guest 5 | password: guest 6 | virtual: / -------------------------------------------------------------------------------- /im-connect/target/classes/nacos.yml: -------------------------------------------------------------------------------- 1 | nacosConfig: 2 | name: im-connect 3 | address: localhost 4 | group: DEFAULT_GROUP 5 | port: 8848 6 | username: nacos 7 | password: nacos 8 | version: 1.0.0 -------------------------------------------------------------------------------- /im-connect/target/classes/netty.yml: -------------------------------------------------------------------------------- 1 | nettyConfig: 2 | heartBeatTime: 30000 3 | bossThreadSize: 4 4 | workThreadSize: 16 5 | tcpConfig: 6 | enable: false 7 | port: 8 | - 9000 9 | - 9001 10 | - 9002 11 | webSocketConfig: 12 | enable: true 13 | port: 14 | - 19000 15 | - 19001 16 | - 19002 -------------------------------------------------------------------------------- /im-connect/target/classes/redis.yml: -------------------------------------------------------------------------------- 1 | redis: 2 | host: localhost 3 | port: 6379 4 | password: 5 | -------------------------------------------------------------------------------- /im-file/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/ImFileApplication.java: -------------------------------------------------------------------------------- 1 | package com.xy.file; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.web.client.RestTemplate; 7 | 8 | @SpringBootApplication 9 | public class ImFileApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ImFileApplication.class, args); 13 | } 14 | 15 | @Bean 16 | public RestTemplate restTemplate(){ 17 | return new RestTemplate(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/controller/MediaMinioController.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.controller; 2 | 3 | import com.xy.file.service.OssFileImageService; 4 | import jakarta.annotation.Resource; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestParam; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import org.springframework.web.multipart.MultipartFile; 12 | 13 | @Slf4j 14 | @RestController 15 | @RequestMapping("/api/media") 16 | public class MediaMinioController { 17 | 18 | 19 | @Resource 20 | private OssFileImageService ossImageFileService; 21 | 22 | /** 23 | * 上传接口 24 | * 25 | * @param file 文件 26 | * @return 上传结果 27 | */ 28 | @PostMapping("/image") 29 | public ResponseEntity uploadImage(@RequestParam MultipartFile file) { 30 | log.info("[文件上传] 图片文件处理"); 31 | return ossImageFileService.uploadImage(file); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/entity/OssFile.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.entity; 2 | 3 | import lombok.*; 4 | 5 | /** 6 | * 上传文件 7 | */ 8 | @Data 9 | @Builder 10 | @Getter 11 | @Setter 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class OssFile { 15 | 16 | /** 17 | * 主键 18 | */ 19 | private String id; 20 | /** 21 | * 分片上传的uploadId 22 | */ 23 | private String uploadId; 24 | /** 25 | * 桶名称 26 | */ 27 | private String bucketName; 28 | /** 29 | * 文件唯一标识(md5) 30 | */ 31 | private String identifier; 32 | /** 33 | * 文件名 34 | */ 35 | private String fileName; 36 | /** 37 | * 文件类型 38 | */ 39 | private String fileType; 40 | /** 41 | * 文件的key 42 | */ 43 | private String objectKey; 44 | 45 | 46 | private String contentType; 47 | 48 | /** 49 | * 文件大小(byte) 50 | */ 51 | private Long fileSize; 52 | /** 53 | * 每个分片大小(byte) 54 | */ 55 | private Long partSize; 56 | /** 57 | * 分片数量 58 | */ 59 | private Integer partNum; 60 | /** 61 | * 是否已完成上传(完成合并),1是0否 62 | */ 63 | private Integer isFinish; 64 | 65 | /** 66 | * 文件地址 67 | */ 68 | private String path; 69 | 70 | } -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/entity/OssFileImage.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.entity; 2 | 3 | import lombok.*; 4 | 5 | @Data 6 | @Builder 7 | @Getter 8 | @Setter 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class OssFileImage { 12 | 13 | /** 14 | * 主键 15 | */ 16 | private String id; 17 | /** 18 | * 分片上传的uploadId 19 | */ 20 | private String uploadId; 21 | /** 22 | * 桶名称 23 | */ 24 | private String bucketName; 25 | /** 26 | * 文件唯一标识(md5) 27 | */ 28 | private String identifier; 29 | /** 30 | * 文件名 31 | */ 32 | private String fileName; 33 | /** 34 | * 文件类型 35 | */ 36 | private String fileType; 37 | /** 38 | * 文件的key 39 | */ 40 | private String objectKey; 41 | 42 | private String contentType; 43 | /** 44 | * 文件大小(byte) 45 | */ 46 | private Long fileSize; 47 | /** 48 | * 文件地址 49 | */ 50 | private String path; 51 | /** 52 | * 缩略图文件地址 53 | */ 54 | private String thumbnailPath; 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/entity/OssFileMediaInfo.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.entity; 2 | 3 | 4 | import lombok.*; 5 | import net.coobird.thumbnailator.geometry.Positions; 6 | 7 | @Data 8 | @Builder 9 | @Getter 10 | @Setter 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class OssFileMediaInfo { 14 | 15 | /** 16 | * 宽 高 17 | */ 18 | private Integer width, height; 19 | 20 | /** 21 | * 水印地址 22 | */ 23 | private String watermarkPath = "C:/Users/dense/Desktop/截图/通话请求窗口.jpg"; 24 | 25 | /** 26 | * 水印位置 27 | */ 28 | private Positions watermarkPosition = Positions.BOTTOM_RIGHT; 29 | /** 30 | * 透明度 31 | */ 32 | private Float opacity = 0.5f; 33 | /** 34 | * 放大倍数 35 | */ 36 | private Double scale = 0.5; 37 | 38 | /** 39 | * 比例 40 | */ 41 | private Double ratio = 0.3; 42 | 43 | /** 44 | * 格式 45 | */ 46 | private String format = "png"; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/entity/OssFileUploadProgress.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.entity; 2 | 3 | import lombok.*; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * 文件上传进度响应对象 9 | */ 10 | @Data 11 | @Builder 12 | @Getter 13 | @Setter 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class OssFileUploadProgress { 17 | 18 | /** 19 | * 是否为新文件(从未上传过的文件),1是0否 20 | */ 21 | private Integer isNew; 22 | 23 | /** 24 | * 是否已完成上传(是否已经合并分片),1是0否 25 | */ 26 | private Integer isFinish; 27 | 28 | /** 29 | * 文件地址 30 | */ 31 | private String path; 32 | 33 | /** 34 | * 上传id 35 | */ 36 | private String uploadId; 37 | 38 | /** 39 | * 未完全上传时,还未上传的(分片、上传链接)Map 40 | */ 41 | private Map undoneChunkMap; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/entity/OssFileUploadResponse.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.entity; 2 | 3 | import lombok.*; 4 | 5 | @Data 6 | @Builder 7 | @Getter 8 | @Setter 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class OssFileUploadResponse { 12 | 13 | private String minIoUrl; 14 | 15 | private String nginxUrl; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/enums/BoolEnum.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.enums; 2 | 3 | public class BoolEnum { 4 | 5 | public static final Integer YES = 1; 6 | 7 | public static final Integer NO = 0; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/handler/ImageProcessingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.handler; 2 | 3 | 4 | import com.xy.file.entity.OssFileMediaInfo; 5 | 6 | import java.io.InputStream; 7 | 8 | /** 9 | * 策略接口 10 | */ 11 | public interface ImageProcessingStrategy { 12 | 13 | InputStream process(InputStream inputStream, OssFileMediaInfo ossMediaFileInfo) throws Exception; 14 | } 15 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/handler/impl/WatermarkStrategy.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.handler.impl; 2 | 3 | import com.xy.file.entity.OssFileMediaInfo; 4 | import com.xy.file.handler.ImageProcessingStrategy; 5 | import com.xy.file.util.WatermarkUtil; 6 | import net.coobird.thumbnailator.geometry.Positions; 7 | 8 | import java.awt.*; 9 | import java.io.InputStream; 10 | 11 | /** 12 | * 图片水印策略实现 13 | */ 14 | public class WatermarkStrategy implements ImageProcessingStrategy { 15 | 16 | 17 | @Override 18 | public InputStream process(InputStream inputStream, OssFileMediaInfo ossMediaFileInfo) throws Exception { 19 | 20 | // String watermarkPath = ossMediaFileInfo.getWatermarkPath(); 21 | // Float opacity = ossMediaFileInfo.getOpacity(); 22 | // Double scale = ossMediaFileInfo.getScale(); 23 | 24 | String format = ossMediaFileInfo.getFormat(); 25 | 26 | return WatermarkUtil.addTextWatermarkToStream( 27 | inputStream, 28 | "Lynk", 29 | new Font("Arial", Font.BOLD, 30), 30 | Color.lightGray, 31 | Positions.BOTTOM_RIGHT, 32 | format, 33 | 0.5f 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/service/OssFileImageService.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.service; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.multipart.MultipartFile; 5 | 6 | public interface OssFileImageService { 7 | 8 | /** 9 | * 上传图片 10 | */ 11 | ResponseEntity uploadImage(MultipartFile file); 12 | } 13 | -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/service/OssFileService.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.service; 2 | 3 | 4 | import com.xy.file.entity.OssFile; 5 | import com.xy.file.util.ResponseResult; 6 | import org.springframework.http.ResponseEntity; 7 | 8 | public interface OssFileService { 9 | 10 | /** 11 | * 获取文件上传进度 12 | */ 13 | ResponseResult getMultipartUploadProgress(String identifier); 14 | 15 | 16 | /** 17 | * 发起分片上传 18 | */ 19 | ResponseResult initMultiPartUpload(OssFile ossFile); 20 | 21 | 22 | /** 23 | * 合并分片文件 24 | */ 25 | ResponseResult mergeMultipartUpload(String identifier); 26 | 27 | 28 | /** 29 | * 检查文件是否存在 30 | */ 31 | ResponseResult isExits(String identifier); 32 | 33 | /** 34 | * 下载文件 35 | */ 36 | ResponseEntity downloadFile(String identifier, String range); 37 | 38 | } -------------------------------------------------------------------------------- /im-file/src/main/java/com/xy/file/util/RedisRepo.java: -------------------------------------------------------------------------------- 1 | package com.xy.file.util; 2 | 3 | 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.data.redis.core.BoundValueOperations; 6 | import org.springframework.data.redis.core.StringRedisTemplate; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.concurrent.TimeUnit; 10 | 11 | 12 | @Component 13 | public class RedisRepo { 14 | 15 | @Autowired 16 | private StringRedisTemplate redisTemplate; 17 | 18 | public String get(String key) { 19 | BoundValueOperations ops = redisTemplate.boundValueOps(key); 20 | return ops.get(); 21 | } 22 | 23 | public void save(String key, String str) { 24 | BoundValueOperations ops = redisTemplate.boundValueOps(key); 25 | ops.set(str); 26 | } 27 | 28 | public void saveTimeout(String key, String value, long timeout, TimeUnit unit) { 29 | delete(key); 30 | redisTemplate.boundValueOps(key).setIfAbsent(value, timeout, unit); 31 | } 32 | 33 | public void delete(String key) { 34 | redisTemplate.delete(key); 35 | } 36 | 37 | public long expire(String key) { 38 | return redisTemplate.opsForValue().getOperations().getExpire(key); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /im-file/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8083 # 配置启动端口号 3 | compression: 4 | enabled: true # 开启gzip压缩 5 | mime-types: application/json,application/xml,text/html,text/xml,text/plain 6 | min-response-size: 1024 7 | 8 | 9 | 10 | spring: #springboot的配置 11 | banner: 12 | location: classpath:banner.txt 13 | profiles: 14 | include: undertow # 引用其他的yml文件 15 | threads: 16 | virtual: 17 | enabled: true # 开启虚拟线程 18 | 19 | data: 20 | redis: 21 | host: localhost 22 | port: 6379 23 | password: 24 | username: 25 | 26 | minio: 27 | endpoint: http://localhost:9000 28 | accessKey: minioadmin 29 | secretKey: minioadmin 30 | 31 | 32 | # TODO: log settings 33 | logging: 34 | config: classpath:logback-plus.xml #日志配置文件,会在当前项目下去找日志配置文件 35 | level: 36 | com.xy.*.mapper: debug 37 | com.xy.*: debug 38 | org.springframework: warn -------------------------------------------------------------------------------- /im-file/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Spring 2 | spring: 3 | application: 4 | # 应用名称 5 | name: im-file 6 | profiles: 7 | # 环境配置 8 | active: dev 9 | cloud: 10 | sentinel: 11 | # 取消控制台懒加载 12 | eager: true 13 | transport: 14 | # sentinel控制台地址 15 | dashboard: localhost:8858 16 | nacos: 17 | discovery: 18 | # 服务注册地址 19 | server-addr: localhost:8848 20 | username: nacos 21 | password: nacos 22 | config: 23 | # 配置中心地址 24 | server-addr: localhost:8848 25 | # 配置文件格式 26 | file-extension: yml 27 | # 共享配置 28 | shared-configs: 29 | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} -------------------------------------------------------------------------------- /im-file/src/test/java/com/xy/imfile/ImFileApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.xy.imfile; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ImFileApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-gateway/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /im-gateway/src/main/java/com/xy/im/ImGatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.xy.im; 2 | 3 | 4 | import com.xy.im.lb.NacosWebsocketClusterChooseRule; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 8 | import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient; 9 | import org.springframework.web.reactive.config.EnableWebFlux; 10 | 11 | @SpringBootApplication 12 | // nacos 13 | @EnableDiscoveryClient 14 | // 自定义负载均衡处理类,只针对转发地址为im-connect的请求生效 15 | @LoadBalancerClient(value = "im-connect", configuration = {NacosWebsocketClusterChooseRule.class}) 16 | public class ImGatewayApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(ImGatewayApplication.class, args); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /im-gateway/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Tomcat 2 | server: 3 | port: 1100 4 | 5 | # Spring 6 | spring: 7 | application: 8 | # 应用名称 9 | name: im-gateway 10 | profiles: 11 | # 环境配置 12 | active: dev 13 | cloud: 14 | sentinel: 15 | # 取消控制台懒加载 16 | eager: true 17 | transport: 18 | # sentinel控制台地址 19 | dashboard: localhost:8858 20 | nacos: 21 | discovery: 22 | # 服务注册地址 23 | server-addr: localhost:8848 24 | username: nacos 25 | password: nacos 26 | config: 27 | # 配置中心地址 28 | server-addr: localhost:8848 29 | # 配置文件格式 30 | file-extension: yml 31 | # 共享配置 32 | shared-configs: 33 | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} -------------------------------------------------------------------------------- /im-meet/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /im-meet/src/main/java/com/xy/meet/ImMeetApplication.java: -------------------------------------------------------------------------------- 1 | package com.xy.meet; 2 | 3 | 4 | public class ImMeetApplication { 5 | 6 | public static void main(String[] args) { 7 | StartCenter.start(); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /im-meet/src/main/java/com/xy/meet/StartCenter.java: -------------------------------------------------------------------------------- 1 | package com.xy.meet; 2 | 3 | 4 | import com.xy.meet.config.ConfigCenter; 5 | import com.xy.meet.config.LogConstant; 6 | import com.xy.meet.netty.service.IMeetChatServer; 7 | import lombok.extern.slf4j.Slf4j; 8 | 9 | 10 | @Slf4j(topic = LogConstant.MAIN) 11 | public class StartCenter { 12 | 13 | public static void start() { 14 | 15 | log.info("IM服务启动中...."); 16 | 17 | // 获取配置 18 | ConfigCenter.load(); 19 | 20 | // 启动netty服务 21 | startNetty(); 22 | 23 | log.info("IM meet服务启动成功...."); 24 | } 25 | 26 | 27 | private static void startNetty() { 28 | new IMeetChatServer().start(); 29 | // new AbstractRemoteServer().start(); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /im-meet/src/main/java/com/xy/meet/config/ConfigCenter.java: -------------------------------------------------------------------------------- 1 | package com.xy.meet.config; 2 | 3 | 4 | import com.xy.meet.config.loader.YamlConfigLoader; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | /** 8 | * 加载resource目录下的配置文件 9 | */ 10 | @Slf4j(topic = LogConstant.CONFIG) 11 | public class ConfigCenter { 12 | 13 | public static IMNettyConfig nettyConfig; 14 | 15 | public static IMNacosConfig nacosConfig; 16 | 17 | public static void load() { 18 | 19 | nettyConfig = YamlConfigLoader.loadConfig("netty.yml", IMNettyConfig.class); 20 | 21 | nacosConfig = YamlConfigLoader.loadConfig("nacos.yml", IMNacosConfig.class); 22 | 23 | log.info("加载配置成功"); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /im-meet/src/main/java/com/xy/meet/config/LogConstant.java: -------------------------------------------------------------------------------- 1 | package com.xy.meet.config; 2 | 3 | 4 | /** 5 | * 业务名称 日志配置 6 | * 对应日志文件 logback.xml 7 | */ 8 | public class LogConstant { 9 | 10 | public final static String MAIN = "IM-Connect"; 11 | 12 | public final static String CONFIG = "IM-ConfigCenter"; 13 | 14 | public final static String NETTY = "NettyServer"; 15 | 16 | public final static String RABBITMQ = "RabbitMQServer"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /im-meet/src/main/java/com/xy/meet/config/loader/YamlConfigLoader.java: -------------------------------------------------------------------------------- 1 | package com.xy.meet.config.loader; 2 | 3 | import org.yaml.snakeyaml.Yaml; 4 | 5 | import java.io.InputStream; 6 | 7 | public class YamlConfigLoader { 8 | 9 | public static T loadConfig(String filePath, Class clazz) { 10 | Yaml yaml = new Yaml(); 11 | try (InputStream in = YamlConfigLoader.class 12 | .getClassLoader() 13 | .getResourceAsStream(filePath)) { 14 | if (in == null) { 15 | throw new IllegalArgumentException("File not found: " + filePath); 16 | } 17 | return yaml.loadAs(in, clazz); 18 | } catch (Exception e) { 19 | throw new RuntimeException("Failed to load config", e); 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /im-meet/src/main/java/com/xy/meet/entity/Room.java: -------------------------------------------------------------------------------- 1 | package com.xy.meet.entity; 2 | 3 | import java.util.Set; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | public class Room { 7 | 8 | // 房间ID 9 | private String roomId; 10 | // 房间用户 11 | private Set users; 12 | 13 | public Room(String roomId) { 14 | this.roomId = roomId; 15 | this.users = ConcurrentHashMap.newKeySet(); 16 | } 17 | 18 | public String getRoomId() { 19 | return roomId; 20 | } 21 | 22 | public Set getUsers() { 23 | return users; 24 | } 25 | 26 | public void addUser(User user) { 27 | users.add(user); 28 | } 29 | 30 | public User getUser(String userId) { 31 | return users.stream().filter(user -> user.getUserId().equals(userId)).findFirst().orElse(null); 32 | } 33 | 34 | public void removeUser(String userId) { 35 | User user = getUser(userId); 36 | if (user != null) { 37 | users.remove(user); 38 | } 39 | } 40 | 41 | public boolean isEmpty() { 42 | return users.isEmpty(); 43 | } 44 | } -------------------------------------------------------------------------------- /im-meet/src/main/java/com/xy/meet/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.xy.meet.entity; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | public class User { 6 | 7 | private String userId; 8 | 9 | private Channel channel; // 用户对应的Netty Channel 10 | 11 | public User(String userId, Channel channel) { 12 | this.userId = userId; 13 | this.channel = channel; 14 | } 15 | 16 | public String getUserId() { 17 | return userId; 18 | } 19 | 20 | public Channel getChannel() { 21 | return channel; 22 | } 23 | } -------------------------------------------------------------------------------- /im-meet/src/main/java/com/xy/meet/netty/service/codec/MessageDecoder.java: -------------------------------------------------------------------------------- 1 | package com.xy.meet.netty.service.codec; 2 | 3 | 4 | import com.xy.meet.entity.Message; 5 | import com.xy.meet.utils.JsonUtil; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.MessageToMessageDecoder; 8 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; 9 | 10 | import java.util.List; 11 | 12 | public class MessageDecoder extends MessageToMessageDecoder { 13 | 14 | @Override 15 | protected void decode(ChannelHandlerContext channelHandlerContext, 16 | TextWebSocketFrame textWebSocketFrame, 17 | List list) throws Exception { 18 | list.add(JsonUtil.parseObject(textWebSocketFrame.text(), Message.class)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /im-meet/src/main/java/com/xy/meet/netty/service/codec/MessageEncoder.java: -------------------------------------------------------------------------------- 1 | package com.xy.meet.netty.service.codec; 2 | 3 | 4 | import com.xy.meet.entity.Message; 5 | import com.xy.meet.utils.JsonUtil; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.handler.codec.MessageToMessageEncoder; 8 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; 9 | 10 | import java.util.List; 11 | 12 | public class MessageEncoder extends MessageToMessageEncoder { 13 | 14 | @Override 15 | protected void encode(ChannelHandlerContext channelHandlerContext, Message message, 16 | List list) throws Exception { 17 | list.add(new TextWebSocketFrame(JsonUtil.toJSONString(message))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /im-meet/src/main/resources/nacos.yml: -------------------------------------------------------------------------------- 1 | nacosConfig: 2 | name: im-meet 3 | address: localhost 4 | port: 8848 5 | username: nacos 6 | password: qsczse111 7 | version: 1.0.0 -------------------------------------------------------------------------------- /im-meet/src/main/resources/netty.yml: -------------------------------------------------------------------------------- 1 | nettyConfig: 2 | heartBeatTime: 8000 3 | bossThreadSize: 8 4 | workThreadSize: 16 5 | tcpConfig: 6 | enable: false 7 | port: 8 | - 9000 9 | webSocketConfig: 10 | enable: true 11 | port: 12 | - 19100 -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/ImServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.xy.server; 2 | 3 | import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.scheduling.annotation.EnableAsync; 7 | import org.springframework.transaction.annotation.EnableTransactionManagement; 8 | 9 | 10 | @EnableKnife4j 11 | @EnableAsync 12 | @EnableTransactionManagement //开启事务管理 13 | @SpringBootApplication 14 | public class ImServerApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(ImServerApplication.class, args); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/config/Knife4jConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.config; 2 | 3 | import io.swagger.v3.oas.models.OpenAPI; 4 | import io.swagger.v3.oas.models.info.Info; 5 | import io.swagger.v3.oas.models.info.License; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | @Configuration 10 | public class Knife4jConfig { 11 | @Bean 12 | public OpenAPI springShopOpenAPI() { 13 | return new OpenAPI() 14 | .info(new Info().title("im-server") 15 | .description("im-server接口文档") 16 | .version("v1.0") 17 | .license(new License().name("Apache 2.0").url("http://springdoc.org"))); 18 | } 19 | } -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/config/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.config; 2 | 3 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; 4 | import com.xy.imcore.enums.IMStatus; 5 | import com.xy.server.utils.DateTimeUtils; 6 | import org.apache.ibatis.reflection.MetaObject; 7 | import org.mybatis.spring.annotation.MapperScan; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @Configuration 11 | @MapperScan("com.xy.server.mapper") 12 | public class MybatisPlusConfig implements MetaObjectHandler { 13 | 14 | 15 | @Override 16 | public void insertFill(MetaObject metaObject) { 17 | setFieldValByName("createTime", DateTimeUtils.getUTCDateTime(), metaObject); 18 | setFieldValByName("updateTime", DateTimeUtils.getUTCDateTime(), metaObject); 19 | setFieldValByName("delFlag", IMStatus.NO.getCode(), metaObject); 20 | } 21 | 22 | @Override 23 | public void updateFill(MetaObject metaObject) { 24 | setFieldValByName("updateTime", DateTimeUtils.getUTCDateTime(), metaObject); 25 | } 26 | } -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/config/RabbitTemplateFactory.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.config; 2 | 3 | import org.springframework.amqp.rabbit.connection.ConnectionFactory; 4 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 5 | import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback; 6 | import org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnsCallback; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | public class RabbitTemplateFactory { 11 | 12 | private final ConnectionFactory connectionFactory; 13 | 14 | public RabbitTemplateFactory(ConnectionFactory connectionFactory) { 15 | this.connectionFactory = connectionFactory; 16 | } 17 | 18 | public RabbitTemplate createRabbitTemplate(ConfirmCallback confirmCallback, ReturnsCallback returnsCallback) { 19 | RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); 20 | rabbitTemplate.setConfirmCallback(confirmCallback); 21 | rabbitTemplate.setReturnsCallback(returnsCallback); 22 | //Mandatory为true时,消息通过交换器无法匹配到队列会返回给生产者,为false时匹配不到会直接被丢弃 23 | rabbitTemplate.setMandatory(true); 24 | return rabbitTemplate; 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/config/ResponseInterceptorConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Component 10 | @ConfigurationProperties(prefix = "response.interceptor") 11 | public class ResponseInterceptorConfig { 12 | private List ignoredUrls = new ArrayList<>(); 13 | 14 | public List getIgnoredUrls() { 15 | return ignoredUrls; 16 | } 17 | 18 | public void setIgnoredUrls(List ignoredUrls) { 19 | this.ignoredUrls = ignoredUrls; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/config/ThreadPoolConfig.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.config; 2 | 3 | import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.context.annotation.Primary; 7 | import org.springframework.scheduling.annotation.EnableAsync; 8 | 9 | import java.util.concurrent.Executor; 10 | import java.util.concurrent.Executors; 11 | 12 | /** 13 | * 虚拟线程池 14 | * @author dense 15 | */ 16 | @Configuration 17 | @EnableAsync 18 | public class ThreadPoolConfig { 19 | 20 | @Bean 21 | @Primary // 将我们设置的虚拟线程池作为主线程池 22 | public Executor virtualThreadExecutor() { 23 | return Executors.newThreadPerTaskExecutor(Thread.ofVirtual().name("im-server-virtual-thread-", 1).factory()); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/dto/ChatDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.dto; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | import jakarta.validation.constraints.NotNull; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | 12 | @Data 13 | @Accessors(chain = true) 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Schema(description = "会话对象") 17 | public class ChatDto implements Serializable { 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | @NotNull(message = "会话id不能为空") 22 | @Schema(description = "会话id") 23 | private String chatId; 24 | 25 | @Schema(description = "会话类型") 26 | private Integer chatType; 27 | 28 | @Schema(description = "发送人") 29 | private String fromId; 30 | 31 | @Schema(description = "接收人") 32 | private String toId; 33 | 34 | @Schema(description = "是否屏蔽") 35 | private Integer isMute; 36 | 37 | @Schema(description = "是否置顶") 38 | private Integer isTop; 39 | 40 | @Schema(description = "时序") 41 | private Long sequence; 42 | 43 | } -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/dto/FriendDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.dto; 2 | 3 | 4 | import io.swagger.v3.oas.annotations.media.Schema; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | 12 | 13 | @Data 14 | @Accessors(chain = true) 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | @Schema(description = "好友对象") 18 | public class FriendDto implements Serializable { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | @Schema(description = "自己id") 23 | private String fromId; 24 | 25 | @Schema(description = "好友id") 26 | private String toId; 27 | } 28 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/dto/FriendRequestDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.dto; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.experimental.Accessors; 8 | 9 | 10 | @Data 11 | @Accessors(chain = true) 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | 15 | public class FriendRequestDto { 16 | 17 | private String fromId; 18 | 19 | private String toId; 20 | 21 | private String remark; 22 | 23 | private String message; 24 | } 25 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/dto/FriendshipRequestDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serializable; 9 | 10 | 11 | @Data 12 | @Accessors(chain = true) 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class FriendshipRequestDto implements Serializable { 16 | 17 | private String id; 18 | 19 | private String fromId; 20 | 21 | private String toId; 22 | 23 | private String remark; 24 | 25 | private Integer approveStatus; 26 | 27 | } -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/dto/GroupDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.dto; 2 | 3 | 4 | import io.swagger.v3.oas.annotations.media.Schema; 5 | import jakarta.validation.constraints.NotNull; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.experimental.Accessors; 10 | 11 | import java.io.Serializable; 12 | 13 | @Data 14 | @Accessors(chain = true) 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | @Schema(description = "群聊对象") 18 | public class GroupDto implements Serializable { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | @NotNull(message = "群id不能为空") 23 | @Schema(description = "群聊id") 24 | private String groupId; 25 | 26 | @Schema(description = "用户id") 27 | private String userId; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/dto/GroupInviteDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.dto; 2 | 3 | import io.swagger.v3.oas.annotations.media.Schema; 4 | import jakarta.validation.constraints.NotNull; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | import java.util.List; 12 | 13 | 14 | @Data 15 | @Accessors(chain = true) 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Schema(description = "群聊邀请") 19 | public class GroupInviteDto implements Serializable { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | @NotNull(message = "群id不能为空") 24 | @Schema(description = "群聊id") 25 | private String groupId; 26 | 27 | @NotNull(message = "用户id不能为空") 28 | @Schema(description = "用户id") 29 | private String userId; 30 | 31 | @NotNull(message = "被邀请用户id不能为空") 32 | @Schema(description = "被邀请用户id") 33 | private List memberIds; 34 | 35 | @Schema(description = "邀请类型") 36 | private Integer type; 37 | } 38 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/dto/LoginDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.dto; 2 | 3 | 4 | import io.swagger.v3.oas.annotations.media.Schema; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | 12 | @Data 13 | @Accessors(chain = true) 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Schema(description = "登录") 17 | public class LoginDto implements Serializable { 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | @Schema(description = "用户id") 22 | private String userId; 23 | 24 | @Schema(description = "密码") 25 | private String password; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.dto; 2 | 3 | 4 | import io.swagger.v3.oas.annotations.media.Schema; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.experimental.Accessors; 9 | 10 | @Data 11 | @Accessors(chain = true) 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Schema(description = "用户对象") 15 | public class UserDto { 16 | 17 | @Schema(description = "用户id") 18 | private String userId; 19 | } 20 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/vo/ChatVo.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serializable; 9 | 10 | @Data 11 | @Accessors(chain = true) 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class ChatVo implements Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | private String chatId; 19 | 20 | private Integer chatType; 21 | 22 | private String ownerId; 23 | 24 | private String toId; 25 | 26 | private Integer isMute; 27 | 28 | private Integer isTop; 29 | 30 | private Long sequence; 31 | 32 | private String name; 33 | 34 | private String avatar; 35 | 36 | private Integer unread; 37 | 38 | // groupId or userId 39 | private String id; 40 | 41 | private Object message; 42 | 43 | private Integer messageContentType; 44 | 45 | private Long messageTime; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/vo/FriendVo.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.vo; 2 | 3 | 4 | import lombok.Data; 5 | 6 | 7 | @Data 8 | public class FriendVo { 9 | 10 | private String userId; 11 | 12 | private String friendId; 13 | 14 | private String name; 15 | 16 | // 别名 17 | private String alias; 18 | 19 | private String avatar; 20 | 21 | private Integer gender; 22 | 23 | private String location; 24 | 25 | // 是否拉黑 1正常 2拉黑 26 | private Integer black; 27 | 28 | private Integer flag; 29 | 30 | private String birthDay; 31 | 32 | private String selfSignature; 33 | 34 | private Long sequence; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/vo/FriendshipRequestVo.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.vo; 2 | 3 | import lombok.Data; 4 | import lombok.experimental.Accessors; 5 | 6 | import java.io.Serializable; 7 | 8 | 9 | @Data 10 | @Accessors(chain = true) 11 | public class FriendshipRequestVo implements Serializable { 12 | 13 | private String id; 14 | 15 | private String fromId; 16 | 17 | private String toId; 18 | 19 | private String name; 20 | 21 | private String avatar; 22 | 23 | private String message; 24 | 25 | private Integer approveStatus; 26 | 27 | } -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/vo/GroupMemberVo.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.vo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.experimental.Accessors; 8 | 9 | @Data 10 | @Accessors(chain = true) 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class GroupMemberVo { 14 | 15 | private String userId; 16 | 17 | private String name; 18 | 19 | private String avatar; 20 | 21 | private Integer gender; 22 | 23 | private String birthDay; 24 | 25 | private String location; 26 | 27 | private String selfSignature; 28 | 29 | private Integer mute; 30 | 31 | private String alias; 32 | 33 | private Integer role; 34 | 35 | private String joinType; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/vo/LoginVo.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.vo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.io.Serializable; 10 | 11 | @Data 12 | @Accessors(chain = true) 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class LoginVo implements Serializable { 16 | 17 | private static final long serialVersionUID = 1L; 18 | private String userId; 19 | private String token; 20 | } 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/domain/vo/UserVo.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.domain.vo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @TableName im_user_data 7 | */ 8 | @Data 9 | public class UserVo { 10 | 11 | private String userId; 12 | 13 | private String name; 14 | 15 | private String avatar; 16 | 17 | private Integer gender; 18 | 19 | private String birthDay; 20 | 21 | private String location; 22 | 23 | private String selfSignature; 24 | } -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/exception/BusinessException.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.exception; 2 | 3 | import com.xy.server.response.ResultEnum; 4 | 5 | public class BusinessException extends RuntimeException { 6 | 7 | private int code; 8 | 9 | private String message; 10 | 11 | public BusinessException(ResultEnum resultEnum) { 12 | this.code = resultEnum.getCode(); 13 | this.message = resultEnum.getMessage(); 14 | } 15 | 16 | public Integer getCode() { 17 | return code; 18 | } 19 | 20 | public void setCode(Integer code) { 21 | this.code = code; 22 | } 23 | 24 | @Override 25 | public String getMessage() { 26 | return message; 27 | } 28 | 29 | public void setMessage(String message) { 30 | this.message = message; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/exception/ForbiddenException.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.exception; 2 | 3 | import com.xy.server.response.ResultEnum; 4 | 5 | public class ForbiddenException extends RuntimeException { 6 | 7 | private int code; 8 | 9 | private String message; 10 | 11 | public ForbiddenException(ResultEnum resultEnum) { 12 | this.code = resultEnum.getCode(); 13 | this.message = resultEnum.getMessage(); 14 | } 15 | 16 | public Integer getCode() { 17 | return code; 18 | } 19 | 20 | public void setCode(Integer code) { 21 | this.code = code; 22 | } 23 | 24 | @Override 25 | public String getMessage() { 26 | return message; 27 | } 28 | 29 | public void setMessage(String message) { 30 | this.message = message; 31 | } 32 | } -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/exception/GlobalException.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.exception; 2 | 3 | import com.xy.server.response.ResultEnum; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | @Data 9 | public class GlobalException extends RuntimeException implements Serializable { 10 | 11 | private static final long serialVersionUID = 8134030011662574394L; 12 | private Integer code; 13 | private String message; 14 | 15 | public GlobalException(Integer code, String message) { 16 | this.code = code; 17 | this.message = message; 18 | } 19 | 20 | public GlobalException(ResultEnum resultEnum) { 21 | this.code = resultEnum.getCode(); 22 | this.message = resultEnum.getMessage(); 23 | } 24 | 25 | 26 | public GlobalException(ResultEnum resultEnum, String message) { 27 | this.code = resultEnum.getCode(); 28 | this.message = message; 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImChatMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImChatPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_chat】的数据库操作Mapper 10 | * @createDate 2024-03-17 01:33:59 11 | * @Entity generator.domain.ImChatSet 12 | */ 13 | @Mapper 14 | public interface ImChatMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImFriendshipGroupMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImFriendshipGroupPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_friendship_group】的数据库操作Mapper 10 | * @createDate 2024-03-17 01:33:59 11 | * @Entity generator.domain.ImFriendshipGroup 12 | */ 13 | @Mapper 14 | public interface ImFriendshipGroupMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImFriendshipGroupMemberMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImFriendshipGroupMemberPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_friendship_group_member】的数据库操作Mapper 10 | * @createDate 2024-03-17 01:33:59 11 | * @Entity generator.domain.ImFriendshipGroupMember 12 | */ 13 | @Mapper 14 | public interface ImFriendshipGroupMemberMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImFriendshipMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImFriendshipPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_friendship】的数据库操作Mapper 10 | * @createDate 2024-03-17 01:33:59 11 | * @Entity generator.domain.ImFriendship 12 | */ 13 | @Mapper 14 | public interface ImFriendshipMapper extends BaseMapper { 15 | 16 | // List selectFriendList(@Param("userId") String userId); 17 | } 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImFriendshipRequestMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImFriendshipRequestPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_friendship_request】的数据库操作Mapper 10 | * @createDate 2024-03-17 01:34:00 11 | * @Entity generator.domain.ImFriendshipRequest 12 | */ 13 | @Mapper 14 | public interface ImFriendshipRequestMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImGroupMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImGroupPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author dense 12 | * @description 针对表【im_group】的数据库操作Mapper 13 | * @createDate 2024-03-17 01:34:00 14 | * @Entity generator.domain.ImGroup 15 | */ 16 | @Mapper 17 | public interface ImGroupMapper extends BaseMapper { 18 | 19 | List selectNinePeople(@Param("groupId") String groupId); 20 | } 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImGroupMemberMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImGroupMemberPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_group_member】的数据库操作Mapper 10 | * @createDate 2024-03-17 01:34:00 11 | * @Entity generator.domain.ImGroupMember 12 | */ 13 | @Mapper 14 | public interface ImGroupMemberMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImGroupMessageMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImGroupMessagePo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author dense 12 | * @description 针对表【im_group_message】的数据库操作Mapper 13 | * @createDate 2024-03-28 23:00:15 14 | * @Entity com.xy.server.model.ImGroupMessage 15 | */ 16 | @Mapper 17 | public interface ImGroupMessageMapper extends BaseMapper { 18 | 19 | List selectGroupMessageByGroupId(@Param("userId") String userId, @Param("groupId") String groupId, @Param("sequence") Long sequence); 20 | 21 | List selectGroupMessage(@Param("userId") String userId, @Param("sequence") Long sequence); 22 | 23 | ImGroupMessagePo selectLastGroupMessage(@Param("userId") String userId, @Param("groupId") String groupId); 24 | 25 | } 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImGroupMessageStatusMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImGroupMessageStatusPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_group_message_status】的数据库操作Mapper 10 | * @createDate 2024-03-28 23:00:15 11 | * @Entity com.xy.server.model.ImGroupMessageStatus 12 | */ 13 | @Mapper 14 | public interface ImGroupMessageStatusMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImPrivateMessageMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImPrivateMessagePo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author dense 12 | * @description 针对表【im_private_message】的数据库操作Mapper 13 | * @createDate 2024-03-28 23:00:15 14 | * @Entity com.xy.server.model.ImPrivateMessage 15 | */ 16 | @Mapper 17 | public interface ImPrivateMessageMapper extends BaseMapper { 18 | 19 | List selectSingleMessageByToId(@Param("fromId") String fromId, @Param("toId") String toId, @Param("messageTime") Long messageTime); 20 | 21 | List selectSingleMessage(@Param("userId") String userId, @Param("messageTime") Long messageTime); 22 | 23 | ImPrivateMessagePo selectLastSingleMessage(@Param("fromId") String fromId, @Param("toId") String toId); 24 | 25 | Integer selectReadStatus(@Param("fromId") String fromId, @Param("toId") String toId, @Param("status") Integer code); 26 | } 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImUserDataMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImUserDataPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_user_data】的数据库操作Mapper 10 | * @createDate 2024-03-17 01:34:00 11 | * @Entity generator.domain.ImUserData 12 | */ 13 | @Mapper 14 | public interface ImUserDataMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/mapper/ImUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.xy.server.domain.po.ImUserPo; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author dense 9 | * @description 针对表【im_user】的数据库操作Mapper 10 | * @createDate 2024-03-17 01:34:00 11 | * @Entity generator.domain.ImUser 12 | */ 13 | @Mapper 14 | public interface ImUserMapper extends BaseMapper { 15 | 16 | } 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/response/IResult.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.response; 2 | 3 | 4 | public interface IResult { 5 | /** 6 | * 获取状态码 7 | * 8 | * @return 状态码 9 | */ 10 | Integer getCode(); 11 | 12 | /** 13 | * 获取消息体 14 | * 15 | * @return 消息体 16 | */ 17 | String getMessage(); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/response/ResponseNotIntercept.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.response; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 返回放行注解 7 | * 在类和方法上使用此注解表示不会在ResponseResult类中进一步封装返回值,直接返回原生值 8 | */ 9 | @Target({ElementType.METHOD, ElementType.TYPE}) //可以在字段、方法 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface ResponseNotIntercept { 13 | String value() default ""; 14 | } 15 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/response/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.response; 2 | 3 | /** 4 | * 常用结果的枚举 5 | */ 6 | public enum ResultEnum implements IResult { 7 | 8 | ERROR(100, "失败"), 9 | 10 | SUCCESS(200, "成功"), 11 | 12 | VALIDATE_FAILED(400, "参数错误"), 13 | 14 | COMMON_FAILED(500, "系统错误"), 15 | 16 | FORBIDDEN(2004, "没有权限访问资源"), 17 | 18 | PASSWD_ERROR(1000, "用户名或密码错误"), 19 | 20 | USER_EMPTY(1000, "用户不存在"); 21 | 22 | private Integer code; 23 | private String message; 24 | 25 | //省略get、set方法和构造方法 26 | 27 | ResultEnum(Integer code, String message) { 28 | this.code = code; 29 | this.message = message; 30 | } 31 | 32 | @Override 33 | public Integer getCode() { 34 | return code; 35 | } 36 | 37 | public void setCode(Integer code) { 38 | this.code = code; 39 | } 40 | 41 | @Override 42 | public String getMessage() { 43 | return message; 44 | } 45 | 46 | public void setMessage(String message) { 47 | this.message = message; 48 | } 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/FileService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import org.springframework.web.multipart.MultipartFile; 4 | 5 | import java.io.File; 6 | 7 | public interface FileService { 8 | 9 | String uploadFile(MultipartFile file); 10 | 11 | MultipartFile fileToMultipartFile(File file); 12 | 13 | MultipartFile fileToImageMultipartFile(File file); 14 | } 15 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/FriendService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.xy.server.domain.dto.FriendDto; 4 | import com.xy.server.domain.dto.FriendRequestDto; 5 | import com.xy.server.domain.dto.FriendshipRequestDto; 6 | import com.xy.server.domain.vo.FriendVo; 7 | import com.xy.server.domain.vo.FriendshipRequestVo; 8 | 9 | import java.util.List; 10 | 11 | 12 | public interface FriendService { 13 | 14 | List list(String userId, String sequence); 15 | 16 | FriendVo findFriend(FriendDto friendDto); 17 | 18 | void addFriend(FriendRequestDto friendRequestDto); 19 | 20 | void approveFriend(FriendshipRequestDto friendshipRequestDto); 21 | 22 | List request(String userId); 23 | 24 | void delFriend(FriendDto friendDto); 25 | } 26 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/GroupChatService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | 4 | import com.xy.imcore.model.IMGroupMessageDto; 5 | import com.xy.server.domain.dto.GroupDto; 6 | import com.xy.server.domain.dto.GroupInviteDto; 7 | import com.xy.server.response.Result; 8 | 9 | /** 10 | * 单聊 11 | */ 12 | 13 | public interface GroupChatService { 14 | 15 | Result send(IMGroupMessageDto IMGroupMessageDto); 16 | 17 | Result getMembers(GroupDto groupDto); 18 | 19 | void quitGroup(GroupDto groupDto); 20 | 21 | Result inviteGroup(GroupInviteDto groupInviteDto); 22 | 23 | Result groupInfo(GroupDto groupDto); 24 | } 25 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImChatService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.dto.ChatDto; 5 | import com.xy.server.domain.po.ImChatPo; 6 | import com.xy.server.domain.vo.ChatVo; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author dense 12 | * @description 针对表【im_chat_set】的数据库操作Service 13 | * @createDate 2024-03-17 01:33:59 14 | */ 15 | public interface ImChatService extends IService { 16 | 17 | List list(ChatDto chatDto); 18 | 19 | void read(ChatDto chatDto); 20 | 21 | ChatVo create(ChatDto ChatDto); 22 | 23 | ChatVo one(String fromId, String toId); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImFriendshipGroupMemberService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.po.ImFriendshipGroupMemberPo; 5 | 6 | /** 7 | * @author dense 8 | * @description 针对表【im_friendship_group_member】的数据库操作Service 9 | * @createDate 2024-03-17 01:33:59 10 | */ 11 | public interface ImFriendshipGroupMemberService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImFriendshipGroupService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.po.ImFriendshipGroupPo; 5 | 6 | /** 7 | * @author dense 8 | * @description 针对表【im_friendship_group】的数据库操作Service 9 | * @createDate 2024-03-17 01:33:59 10 | */ 11 | public interface ImFriendshipGroupService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImFriendshipRequestService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.po.ImFriendshipRequestPo; 5 | 6 | /** 7 | * @author dense 8 | * @description 针对表【im_friendship_request】的数据库操作Service 9 | * @createDate 2024-03-17 01:34:00 10 | */ 11 | public interface ImFriendshipRequestService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImFriendshipService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.po.ImFriendshipPo; 5 | 6 | /** 7 | * @author dense 8 | * @description 针对表【im_friendship】的数据库操作Service 9 | * @createDate 2024-03-17 01:33:59 10 | */ 11 | public interface ImFriendshipService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImGroupMemberService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.po.ImGroupMemberPo; 5 | 6 | /** 7 | * @author dense 8 | * @description 针对表【im_group_member】的数据库操作Service 9 | * @createDate 2024-03-17 01:34:00 10 | */ 11 | public interface ImGroupMemberService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImGroupMessageService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.po.ImGroupMessagePo; 5 | 6 | /** 7 | * @author dense 8 | * @description 针对表【im_group_message】的数据库操作Service 9 | * @createDate 2024-03-28 23:00:15 10 | */ 11 | public interface ImGroupMessageService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImGroupMessageStatusService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.po.ImGroupMessageStatusPo; 5 | 6 | /** 7 | * @author dense 8 | * @description 针对表【im_group_message_status】的数据库操作Service 9 | * @createDate 2024-03-28 23:00:15 10 | */ 11 | public interface ImGroupMessageStatusService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImGroupService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.po.ImGroupPo; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author dense 10 | * @description 针对表【im_group】的数据库操作Service 11 | * @createDate 2024-03-17 01:34:00 12 | */ 13 | public interface ImGroupService extends IService { 14 | 15 | 16 | List selectNinePeople(String groupId); 17 | } 18 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImPrivateMessageService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.server.domain.po.ImPrivateMessagePo; 5 | 6 | /** 7 | * @author dense 8 | * @description 针对表【im_private_message】的数据库操作Service 9 | * @createDate 2024-03-28 23:00:15 10 | */ 11 | public interface ImPrivateMessageService extends IService { 12 | } 13 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/ImUserService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.xy.imcore.model.IMRegisterUserDto; 5 | import com.xy.server.domain.dto.LoginDto; 6 | import com.xy.server.domain.po.ImUserPo; 7 | import com.xy.server.domain.vo.LoginVo; 8 | import com.xy.server.domain.vo.UserVo; 9 | 10 | /** 11 | * @author dense 12 | * @description 针对表【im_user】的数据库操作Service 13 | * @createDate 2024-03-17 01:34:00 14 | */ 15 | public interface ImUserService extends IService { 16 | 17 | LoginVo login(LoginDto loginDto); 18 | 19 | UserVo info(String userId); 20 | 21 | LoginVo refreshToken(String token); 22 | 23 | void register(IMRegisterUserDto IMRegisterUserDto); 24 | } 25 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/MessageService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.xy.server.domain.dto.ChatDto; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | 9 | public interface MessageService { 10 | 11 | List singleCheck(ChatDto chatDto); 12 | 13 | Map list(ChatDto chatDto); 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/SingleChatService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | 4 | import com.xy.imcore.model.IMSingleMessageDto; 5 | import com.xy.server.response.Result; 6 | 7 | /** 8 | * 单聊 9 | */ 10 | 11 | public interface SingleChatService { 12 | 13 | Result send(IMSingleMessageDto IMSingleMessageDto); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/VideoChatService.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service; 2 | 3 | import com.xy.imcore.model.IMVideoMessageDto; 4 | 5 | public interface VideoChatService { 6 | 7 | void send(IMVideoMessageDto IMVideoMessageDto); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/impl/ImFriendshipGroupMemberServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.xy.server.domain.po.ImFriendshipGroupMemberPo; 5 | import com.xy.server.mapper.ImFriendshipGroupMemberMapper; 6 | import com.xy.server.service.ImFriendshipGroupMemberService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author dense 11 | * @description 针对表【im_friendship_group_member】的数据库操作Service实现 12 | * @createDate 2024-03-17 01:33:59 13 | */ 14 | @Service 15 | public class ImFriendshipGroupMemberServiceImpl extends ServiceImpl 16 | implements ImFriendshipGroupMemberService { 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/impl/ImFriendshipGroupServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.xy.server.domain.po.ImFriendshipGroupPo; 5 | import com.xy.server.mapper.ImFriendshipGroupMapper; 6 | import com.xy.server.service.ImFriendshipGroupService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author dense 11 | * @description 针对表【im_friendship_group】的数据库操作Service实现 12 | * @createDate 2024-03-17 01:33:59 13 | */ 14 | @Service 15 | public class ImFriendshipGroupServiceImpl extends ServiceImpl 16 | implements ImFriendshipGroupService { 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/impl/ImFriendshipRequestServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.xy.server.domain.po.ImFriendshipRequestPo; 5 | import com.xy.server.mapper.ImFriendshipRequestMapper; 6 | import com.xy.server.service.ImFriendshipRequestService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author dense 11 | * @description 针对表【im_friendship_request】的数据库操作Service实现 12 | * @createDate 2024-03-17 01:34:00 13 | */ 14 | @Service 15 | public class ImFriendshipRequestServiceImpl extends ServiceImpl 16 | implements ImFriendshipRequestService { 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/impl/ImFriendshipServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.xy.server.domain.po.ImFriendshipPo; 5 | import com.xy.server.mapper.ImFriendshipMapper; 6 | import com.xy.server.service.ImFriendshipService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author dense 11 | * @description 针对表【im_friendship】的数据库操作Service实现 12 | * @createDate 2024-03-17 01:33:59 13 | */ 14 | @Service 15 | public class ImFriendshipServiceImpl extends ServiceImpl 16 | implements ImFriendshipService { 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/impl/ImGroupMemberServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.xy.server.domain.po.ImGroupMemberPo; 5 | import com.xy.server.mapper.ImGroupMemberMapper; 6 | import com.xy.server.service.ImGroupMemberService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author dense 11 | * @description 针对表【im_group_member】的数据库操作Service实现 12 | * @createDate 2024-03-17 01:34:00 13 | */ 14 | @Service 15 | public class ImGroupMemberServiceImpl extends ServiceImpl 16 | implements ImGroupMemberService { 17 | } 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/impl/ImGroupMessageServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.xy.server.domain.po.ImGroupMessagePo; 5 | import com.xy.server.mapper.ImGroupMessageMapper; 6 | import com.xy.server.service.ImGroupMessageService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author dense 11 | * @description 针对表【im_group_message】的数据库操作Service实现 12 | * @createDate 2024-03-28 23:00:15 13 | */ 14 | @Service 15 | public class ImGroupMessageServiceImpl extends ServiceImpl 16 | implements ImGroupMessageService { 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/impl/ImGroupMessageStatusServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.xy.server.domain.po.ImGroupMessageStatusPo; 5 | import com.xy.server.mapper.ImGroupMessageStatusMapper; 6 | import com.xy.server.service.ImGroupMessageStatusService; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author dense 11 | * @description 针对表【im_group_message_status】的数据库操作Service实现 12 | * @createDate 2024-03-28 23:00:15 13 | */ 14 | @Service 15 | public class ImGroupMessageStatusServiceImpl extends ServiceImpl 16 | implements ImGroupMessageStatusService { 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/impl/ImGroupServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.xy.server.domain.po.ImGroupPo; 5 | import com.xy.server.mapper.ImGroupMapper; 6 | import com.xy.server.service.ImGroupService; 7 | import jakarta.annotation.Resource; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author dense 14 | * @description 针对表【im_group】的数据库操作Service实现 15 | * @createDate 2024-03-17 01:34:00 16 | */ 17 | @Service 18 | public class ImGroupServiceImpl extends ServiceImpl 19 | implements ImGroupService { 20 | 21 | @Resource 22 | private ImGroupMapper imGroupMapper; 23 | 24 | 25 | @Override 26 | public List selectNinePeople(String groupId) { 27 | return imGroupMapper.selectNinePeople(groupId); 28 | } 29 | } 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /im-server/src/main/java/com/xy/server/service/impl/ImPrivateMessageServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xy.server.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.xy.server.domain.po.ImPrivateMessagePo; 5 | import com.xy.server.mapper.ImPrivateMessageMapper; 6 | import com.xy.server.service.ImPrivateMessageService; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * @author dense 12 | * @description 针对表【im_private_message】的数据库操作Service实现 13 | * @createDate 2024-03-28 23:00:15 14 | */ 15 | @Slf4j(topic = "single") 16 | @Service 17 | public class ImPrivateMessageServiceImpl extends ServiceImpl 18 | implements ImPrivateMessageService { 19 | 20 | } 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /im-server/src/main/resources/application-swagger.yml: -------------------------------------------------------------------------------- 1 | #springdoc相关配置 2 | springdoc: 3 | swagger-ui: 4 | path: /swagger-ui.html 5 | tags-sorter: alpha 6 | operations-sorter: alpha 7 | api-docs: 8 | enabled: true 9 | path: /v3/api-docs 10 | group-configs: 11 | - group: 'server' 12 | paths-to-match: '/**' 13 | packages-to-scan: com.xy.server #改成你自己的包名,一般到启动类的包名 14 | 15 | 16 | 17 | # TODO: knife4j相关配置 可以不用改 18 | knife4j: 19 | enable: true # 开启增强配置 20 | production: false # 开启生产环境屏蔽 21 | setting: 22 | language: zh_cn # 默认中文 23 | swagger-model-name: 实体类 24 | -------------------------------------------------------------------------------- /im-server/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Spring 2 | spring: 3 | application: 4 | # 应用名称 5 | name: im-service 6 | profiles: 7 | # 环境配置 8 | active: dev 9 | cloud: 10 | sentinel: 11 | # 取消控制台懒加载 12 | eager: true 13 | transport: 14 | # sentinel控制台地址 15 | dashboard: localhost:8858 16 | nacos: 17 | discovery: 18 | # 服务注册地址 19 | server-addr: localhost:8848 20 | username: nacos 21 | password: nacos 22 | config: 23 | # 配置中心地址 24 | server-addr: localhost:8848 25 | # 配置文件格式 26 | file-extension: yml 27 | # 共享配置 28 | shared-configs: 29 | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImChatMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImFriendshipGroupMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImFriendshipGroupMemberMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImFriendshipMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImFriendshipRequestMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImGroupMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 14 | 15 | -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImGroupMemberMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImGroupMessageStatusMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImUserDataMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/src/main/resources/mapper/ImUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/src/test/java/com/xy/data/ImServerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.xy.data; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ImServerApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /im-server/target/classes/application-swagger.yml: -------------------------------------------------------------------------------- 1 | #springdoc相关配置 2 | springdoc: 3 | swagger-ui: 4 | path: /swagger-ui.html 5 | tags-sorter: alpha 6 | operations-sorter: alpha 7 | api-docs: 8 | enabled: true 9 | path: /v3/api-docs 10 | group-configs: 11 | - group: 'server' 12 | paths-to-match: '/**' 13 | packages-to-scan: com.xy.server #改成你自己的包名,一般到启动类的包名 14 | 15 | 16 | 17 | # TODO: knife4j相关配置 可以不用改 18 | knife4j: 19 | enable: true # 开启增强配置 20 | production: false # 开启生产环境屏蔽 21 | setting: 22 | language: zh_cn # 默认中文 23 | swagger-model-name: 实体类 24 | -------------------------------------------------------------------------------- /im-server/target/classes/bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Spring 2 | spring: 3 | application: 4 | # 应用名称 5 | name: im-service 6 | profiles: 7 | # 环境配置 8 | active: dev 9 | cloud: 10 | sentinel: 11 | # 取消控制台懒加载 12 | eager: true 13 | transport: 14 | # sentinel控制台地址 15 | dashboard: localhost:8858 16 | nacos: 17 | discovery: 18 | # 服务注册地址 19 | server-addr: localhost:8848 20 | username: nacos 21 | password: nacos 22 | config: 23 | # 配置中心地址 24 | server-addr: localhost:8848 25 | # 配置文件格式 26 | file-extension: yml 27 | # 共享配置 28 | shared-configs: 29 | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImChatMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImFriendshipGroupMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImFriendshipGroupMemberMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImFriendshipMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImFriendshipRequestMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImGroupMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 14 | 15 | -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImGroupMemberMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImGroupMessageStatusMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImUserDataMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /im-server/target/classes/mapper/ImUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rsa/publicKey.pem: -------------------------------------------------------------------------------- 1 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0lvuzVF/rtMMxkufrEC3p185fdcQBm2Q66AfOdrKe2Uj9vt+v1wC9LuZjX8nkZLjXYvjCxyneo6BDjbT4hjAGjtNMmyE3xZHV4W52XPhWpTrlMTIavyE0HG5Ch5/8jRhTifo0ROiYTYobkURXLcQNTT6rxm/4JPMWWdUa22p5T2udFyWy60T9gEvN+OqkQHQv3zkcIozeVbMuO8aYskag/6Xt7CaI0g6/zhRTBBFXzl8brEGYlkEEc6Y6+D61QPaja36XIBSgQwQz2U/hGRYumwdp9M+Uu2d9PVgX/s9rh5NNmuzxd7xGKHHY4yLPCBUp61VF82wOE9D0j3KgcBoTQIDAQAB --------------------------------------------------------------------------------