├── .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