首页 文章 精选 留言 我的

精选列表

搜索[热搜算法],共10004篇文章
优秀的个人博客,低调大师

mybatis mapper.xml 热部署

package com.guangeryi.mall.core.utils.mybatis; import com.guangeryi.mall.common.CommonConstant; import com.guangeryi.mall.core.utils.StringUtils; import org.apache.ibatis.binding.MapperProxyFactory; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.logging.log4j.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.stereotype.Component; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Component public class MyBatisMapperRefresher implements DisposableBean, InitializingBean, ApplicationContextAware { private final Logger logger = LoggerFactory.getLogger(getClass()); /** * 扫描周期,单位秒 */ private int periodSeconds = 5; /** * 初始化完成,延迟扫描时间,单位秒 */ private int initialDelay = 5; /** * 是否启用 */ @Value("${mapper.auto.load}") private boolean enabled; private ConfigurableApplicationContext context = null; private transient Resource[] basePackage = null; private HashMap<String, String> fileMapping = new HashMap<>(); private Set<String> isChangedMapper = new HashSet<>(); private Scanner scanner = null; private ScheduledExecutorService service = null; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = (ConfigurableApplicationContext) applicationContext; } @Override public void afterPropertiesSet() throws Exception { if (!enabled) { logger.info("MyBatisMapperRefresher is Disabled"); return; } try { service = Executors.newScheduledThreadPool(1); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); basePackage = resolver.getResources("classpath*:xx.xml");// 加载配置xml文件 logger.info("监控以下" + basePackage.length + "个xml文件:"); // 触发文件监听事件 scanner = new Scanner(); scanner.scan(); service.scheduleAtFixedRate(new Task(), MyBatisMapperRefresher.this.initialDelay, MyBatisMapperRefresher.this.periodSeconds, TimeUnit.SECONDS); } catch (Exception e1) { logger.error("can not starter Mybatis xml refresher,exception:{}", e1); } } class Task implements Runnable { @Override public void run() { try { if (scanner.isChanged()) { scanner.reloadXML(); } } catch (Exception ex) { logger.error("MyBatisMapperRefresher,exception:{}", ex); } } } @Override public void destroy() throws Exception { if (service != null) { service.shutdownNow(); } } class Scanner { private Resource[] mapperXmlFiles; public Scanner() { mapperXmlFiles = MyBatisMapperRefresher.this.basePackage; } public void reloadXML() throws Exception { SqlSessionFactory factory = context.getBean(SqlSessionFactory.class); Configuration configuration = factory.getConfiguration(); Set<Class<?>> knownMapperKeys = new HashSet<>(); Field field = configuration.getMapperRegistry().getClass().getDeclaredField("knownMappers"); field.setAccessible(true); Map<Class<?>, MapperProxyFactory<?>> knownMappers = (Map<Class<?>, MapperProxyFactory<?>>) field.get(configuration.getMapperRegistry()); knownMapperKeys.addAll(knownMappers.keySet()); // 移除加载项 removeConfig(configuration, isChangedMapper); Set<String> isChangedMapperTemp = isChangedMapper.stream().map(item -> StringUtils.split(item, CommonConstant.CHAR_SPOT)[0]).collect(Collectors.toSet()); Iterator<Class<?>> classIterator = knownMapperKeys.iterator(); while (classIterator.hasNext()) { Class clazz = classIterator.next(); if (clazz == null || Strings.isEmpty(clazz.getName())) continue; String[] clazzNames = StringUtils.split(clazz.getName(), CommonConstant.CHAR_SPOT); if (isChangedMapperTemp.contains(clazzNames[clazzNames.length - 1])) { knownMappers.remove(clazz); configuration.addMapper(clazz); } } isChangedMapper.clear(); } private void removeConfig(Configuration configuration, Set<String> isChangedMapper) throws Exception { Class<?> classConfig = configuration.getClass(); clearMap(classConfig, configuration, "mappedStatements", isChangedMapper); clearMap(classConfig, configuration, "caches", isChangedMapper); clearMap(classConfig, configuration, "resultMaps", isChangedMapper); clearMap(classConfig, configuration, "parameterMaps", isChangedMapper); clearMap(classConfig, configuration, "keyGenerators", isChangedMapper); clearMap(classConfig, configuration, "sqlFragments", isChangedMapper); clearSet(classConfig, configuration, "loadedResources", isChangedMapper); } private void clearMap(Class<?> classConfig, Configuration configuration, String fieldName, Set<String> isChangedMapper) throws Exception { Set<String> isChangedMapperTemp = isChangedMapper.stream().map(item -> "repository." + StringUtils.split(item, CommonConstant.CHAR_SPOT)[0]).collect(Collectors.toSet()); Field field = classConfig.getDeclaredField(fieldName); field.setAccessible(true); Map mapConfig = (Map) field.get(configuration); Map tempMap = new HashMap(); tempMap.putAll(mapConfig); tempMap.forEach((key, value) -> { if (StringUtils.StringContains((String) key, isChangedMapperTemp)) mapConfig.remove(key); }); } private void clearSet(Class<?> classConfig, Configuration configuration, String fieldName, Set<String> isChangedMapper) throws Exception { Set<String> isChangedMapperTemp = isChangedMapper.stream().map(item -> "repository/" + StringUtils.split(item, CommonConstant.CHAR_SPOT)[0]).collect(Collectors.toSet()); isChangedMapperTemp.addAll(isChangedMapper.stream().map(item -> "repository." + StringUtils.split(item, CommonConstant.CHAR_SPOT)[0]).collect(Collectors.toSet())); Field field = classConfig.getDeclaredField(fieldName); field.setAccessible(true); Set setConfig = (Set) field.get(configuration); Set tempMap = new HashSet<>(); tempMap.addAll(setConfig); tempMap.forEach(item -> { if (StringUtils.StringContains((String) item, isChangedMapperTemp)) setConfig.remove(item); }); } public void scan() throws IOException { if (!fileMapping.isEmpty()) { return; } Resource[] resources = mapperXmlFiles; if (resources != null) { for (int i = 0; i < resources.length; i++) { String multi_key = getValue(resources[i]); String fileName = resources[i].getFilename(); fileMapping.put(fileName, multi_key); logger.info("monitor Mybatis mapper file:{}", resources[i].getFile().getAbsolutePath()); } } } private String getValue(Resource resource) throws IOException { String contentLength = String.valueOf((resource.contentLength())); String lastModified = String.valueOf((resource.lastModified())); return new StringBuilder(contentLength).append(lastModified).toString(); } public boolean isChanged() throws IOException { boolean isChanged = false; Resource[] resources = mapperXmlFiles; if (resources != null) { for (int i = 0; i < resources.length; i++) { String name = resources[i].getFilename(); String value = fileMapping.get(name); String multi_key = getValue(resources[i]); if (!multi_key.equals(value)) { isChanged = true; fileMapping.put(name, multi_key); isChangedMapper.add(name); logger.info("reload Mybatis mapper file:{}", resources[i].getFile().getAbsolutePath()); } } } return isChanged; } } } 希望园友多多提意见...

优秀的个人博客,低调大师

智能投影的“淘金热”

往年不温不火的投影产品,在今年格外热闹。 一家名为极米的创业公司发布基于“投影+Android盒子”的智能投影后,同类产品如同冰山解冻般纷纷浮出水面。 这里用“浮出”,是因为智能投影产品的起源纷纷杂杂难以确定。极米是智能硬件圈内第一家发布投影产品的,但据说在此时深圳已有一票Android投影方案。在极米之前,投影领域有类似“投影+播放系统”的家庭影院产品;极米发布后,几个月内相继出现十余个同类项目。 智能投影领域忽然就变得炙手可热,几股推动力量开始穿插在其中。 1、以极米、威泡为代表的创业选手,它们通常选择众筹作为产品第一站; 2、神画、坚果等深圳系厂商,有ODM、投影外包设计等强硬件背景; 3、类似百度、土豆与第三方合作OEM的互联网选手; 4、海尔这类家电巨擘。 几个分类不是特别精确,其中有几家身份交叉,既做众筹,供应链以及研发力量也放

优秀的个人博客,低调大师

deepin 25 实现“秒搜”自由

“这个报告到底存在哪里?”“只记得文档里有‘预算调整’,文件名却死活想不起来......”与海量文件打交道,类似的抓狂瞬间几乎天天上演。 别担心,deepin 25 带着“全文检索”黑科技来了,哪怕只记得只言片语,也能瞬间定位目标,彻底终结文件查找难题。 内容级深度搜索,告别“记文件名”焦虑 全文检索功能能够直接穿透文件名,深入文档内部文本内容进行搜索。 不记得文件名没关系,只需输入你所记得的部分关键词,系统就自动匹配出所有包含该内容的文档,瞬间锁定目标。无论是合同条款、会议纪要还是数据报表,哪怕搜索内容藏在图片中,都能被精准捕捉。 关键词高亮显示:一眼锁定核心信息 找到文件只是第一步,快速定位关键内容才是提升效率的核心。 在 deepin 25 的全文检索结果列表中,所有包含关键词的文件名和文件内容都会用醒目的颜色标记,无需逐字阅读就能一眼锁定重点,让信息获取效率提升数倍。 多关键词组合搜索:精准过滤无关信息 在查找文件时,常常会遇到这样的情况:需要的文档涉及多个关键信息,只靠单个关键词搜索,结果往往混入大量无关文件。 deepin 25 的多关键词组合搜索功能,可完美解决这个问题。就像常用的搜索引擎,支持输入多个关键词,用空格分隔,系统便会精准识别并匹配同时包含所有关键词的文件,大大提高搜索的命中率。这种类似搜索引擎的操作逻辑,上手零难度,却能让搜索命中率大幅提升。 deepin 25 的全文检索功能,用内容级搜索打破文件名限制,用高亮显示简化信息定位,用多关键词组合提升精准度,三者协同发力,让文件查找从“耗时任务”变成 “秒级操作”! 欢迎尝试体验并在评论区分享您的使用心得。同时也诚邀您前往社区论坛参与更深入的交流与探讨,共同助力 deepin 的成长。

优秀的个人博客,低调大师

搜“apple”不返回“Apple”?你需要了解 Elasticsearch Normalizer

作者介绍 魏彬,普翔科技 CTO,开源软件爱好者,中国第一位 Elastic 认证工程师,《Elastic日报》和 《ElasticTalk》社区项目发起人,被 elastic 中国公司授予 2019 年度合作伙伴架构师特别贡献奖。对 Elasticsearch、Kibana、Beats、Logstash、Grafana 等开源软件有丰富的实践经验,为零售、金融、保险、证券、科技等众多行业的客户提供过咨询和培训服务,帮助客户在实际业务中找准开源软件的定位,实现从 0 到 1 的落地、从 1 到 N 的拓展,产生实际的业务价值。 在 Elasticsearch 中处理字符串类型的数据时,如果我们想把整个字符串作为一个完整的 term 存储,我们通常会将其类型 type 设定为 keyword。但有时这种设定又会给我们带来麻烦,比如同一个数据再写入时由于没有做好清洗,导致大小写不一致,比如 apple、Apple两个实际都是 apple,但当我们去搜索 apple 时却无法返回 Apple 的文档。要解决这个问题,就需要 Normalizer 出场了。废话不多说,直接上手看! 一、上手 我们先来重现一下开篇的问题。 PUT test_normalizer { "mappings": { "doc":{ "properties": { "type":{ "type":"keyword" } } } } } PUT test_normalizer/doc/1 { "type":"apple" } PUT test_normalizer/doc/2 { "type":"Apple" } # 查询一 GET test_normalizer/_search { "query": { "match":{ "type":"apple" } } } # 查询二 GET test_normalizer/_search { "query": { "match":{ "type":"aPple" } } } 大家执行后会发现 查询一返回了文档1,而 查询二没有文档返回,原因如下图所示: 1、Docs写入 Elasticsearch时由于 type 是 keyword,分词结果为原始字符串2、查询 Query 时分词默认是采用和字段写时相同的配置,因此这里也是 keyword,因此分词结果也是原始字符3、两边的分词进行匹对,便得出了我们上面的结果 二、Normalizer Normalizer 是 keyword 的一个属性,可以对 keyword 生成的单一 Term 再做进一步的处理,比如 lowercase,即做小写变换。使用方法和自定义分词器有些类似,需要自定义,如下所示: DELETE test_normalizer # 自定义 normalizer PUT test_normalizer { "settings": { "analysis": { "normalizer": { "lowercase": { "type": "custom", "filter": [ "lowercase" ] } } } }, "mappings": { "doc": { "properties": { "type": { "type": "keyword" }, "type_normalizer": { "type": "keyword", "normalizer": "lowercase" } } } } } PUT test_normalizer/doc/1 { "type": "apple", "type_normalizer": "apple" } PUT test_normalizer/doc/2 { "type": "Apple", "type_normalizer": "Apple" } # 查询三 GET test_normalizer/_search { "query": { "term":{ "type":"aPple" } } } # 查询四 GET test_normalizer/_search { "query": { "term":{ "type_normalizer":"aPple" } } } 我们第一步是自定义了名为 lowercase 的 normalizer,其中 filter 类似自定义分词器中的 filter ,但是可用的种类很少,详情大家可以查看官方文档。然后通过 normalizer属性设定到字段 type_normalizer 中,然后插入相同的 2 条文档。执行发现,查询三无结果返回,查询四返回 2 条文档。 问题解决了!我们来看下是如何解决的 1、文档写入时由于加入了 normalizer,所有的 term 都会被做小写处理2、查询时搜索词同样采用有 normalizer 的配置,因此处理后的 term 也是小写的3、两边分词匹对,就得到了我们上面的结果 三、总结 本文通过一个实例来给大家讲解了 Normalizer 的实际使用场景,希望对大家有所帮助! 声明:本文由原文《听说你还没掌握 Normalizer 的使用方法?》作者“魏彬”授权转载,对未经许可擅自使用者,保留追究其法律责任的权利。 【阿里云Elastic Stack】100%兼容开源ES,独有9大能力,提供免费X-pack服务(单节点价值$6000) 相关活动 更多折扣活动,请访问阿里云 Elasticsearch 官网 阿里云 Elasticsearch 商业通用版,1核2G ,SSD 20G首月免费阿里云 Logstash 2核4G首月免费

优秀的个人博客,低调大师

jSearch(聚搜)v1.3.0 发布!带来站点分组功能

jSearch 发布到现在马上要满一年了,今天迎来了1.3版本。要只是满足我自己的需求的话其实很多更新都不是很必要了,因为我还挺能凑合的😂😂,所以能持续更新到现在真的是多亏了一批一直在用的用户和github上的issues。感谢大家! v1.3.0更新说明 1.新增搜索站点分组 支持快捷键Ctrl+1...9 切换分组; 支持非插件页面Ctrl+1...9 进行单组搜索; 2.新增地址栏搜索开关快捷键:Shift+D 本次更新图示: 更新历史: https://github.com/dubox/jSearch/releases

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册