-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.json
1 lines (1 loc) · 506 KB
/
content.json
1
{"meta":{"title":"Bejond IO","subtitle":"Don't be afraid of output. Most of things you write or do might be no readers, but they mean a lot to yourself.","description":"自律然后自由","author":"Bejond Shao","url":"http://bejondshao.github.io"},"pages":[{"title":"","date":"2023-03-04T16:14:56.509Z","updated":"2023-03-04T16:14:56.509Z","comments":true,"path":"Bejond Shao-DLUT-Software-Engineer-Java-20200429.html","permalink":"http://bejondshao.github.io/Bejond%20Shao-DLUT-Software-Engineer-Java-20200429.html","excerpt":"","keywords":null,"text":"Bejond Shao • Male • 1990-10 • Dalian, Liaoning • [email protected] • +86 18640902787 6 years Java development experience of backend service. Research on security, identity authentication and authorization. Have a systematic study of Keycloak. Use spare time for single sign-on and LDAP integration. Use Spring Security for OpenId Connect authentication and authorization. Have complete product design and implementation experience for remote call of message middleware. Familiar with mainstream Java frameworks. Research and tuning experience on JVM tuning and memory leak. Embrace and have a deep interest in technology. Can quickly become familiar with new ideas and technical solutions and use them. Able to learn technology systematically, and good at recording and summarizing. Like to help others with what I have learned. Education 2009 - 2013: Dalian University of Technology,Software engineering,bachelor degree. Work Experiences Beijing Shiji Kunlun Software Co., Ltd.(2016/05 - by now) I work on intelligent hotel service management system for five-star hotels, not only to solve hotel front office staff’s problems, but also to make guests have a better experiences on their trip. I’m responsible for Mobile PMS and Kiosk self-help system. Participate in the compnay and become a full member in advance in 2 months. Become the leader of the projects I worked on. Responsible for technology leadership, such as Springboot, camel, keycloak, rabbitmq etc. As a leader, I always do the resarch and make a demo for my workmates. Always tring to make the product better, besides developing modules, doing reconstruction about the products, performance tuning, code review. Responsible for Java developer interviews. Liferay Inc.(2014/06 - 2016/04) I worked in Liferay as technical support engineer for Liferay portal, worked together with Asia-Pacific and occident coworkers. Help customer support engineers to solve technical problems, such as bug fixing, hotfix making, complex environmental construction, issue reproduction, customer issue analysing, etc. Catch thread dump and heap dump to analyse system performance issues, JVM performance turning. Product Experiences Name: Kiosk self-help system (Kiosk) Introduction: Kiosk locates in local hotel, communicate with hotel Property Management System (PMS), usually Opera or Cambridge. And Kiosk can help guests do check in processes by themselves, in case of front desk is busy or the guest doesn’t want to contact with staff directly. Kiosk can search reservation, find rooms, and assign room, upload document to Public Security Bureau (PSB), make payment or pre-authorization and check in or check out. Roles and resposibilities: Person in charge. Analyse customer requirement, make design for Rest APIs, technical difficulties resolution. Achieve progress control and product quality control. Related technologies: Java EE, EJB, CDI, AOP, Mybatis, JPA, JWT,RabbitMQ, Postgresql, Oracle, Maven, SVN. Name: Guest Journey Engine(GJE) Introduction: GJE is an interface for online hotel business for third-party internet channels such as Feizhu and Ctrip. The interfaces about GJE is similar to Kiosk, but GJE is a load-balanced cloud architecture gateway. It can serve multiple channels and also connect to multiple hotels. GJE called the hotel intranet Kiosk interface and encountered network limitations. By applying RabbitMQ’s RPC mode, intranet penetration was achieved. Roles and resposibilities: The same as Kiosk. Related technologies: Java EE, EJB, CDI, AOP, Mybatis, JPA, JWT,Postgresql, RabbitMQ. Name: Kunlun 360 Introduction: Kunlun 360 is a comprehensive system independently developed by Shiji Kunlun, which is a full-service hotel business. Including reservation processing, room, guest, billing management. And intellijent functions such as electronic signature, document uploading, scan code payment, invoice printing and other modules. The mobile PMS function is implemented, which is convenient for the service staff to serve the guests specifically. It does not have to be confined to the front desk or self-help equipment to allow guests to have a better experience. Roles and resposibilities: I am responsible for reservation, room, guest, billing management and other modules. Responsible for requirements analysis, function investigation, interface design, function implementation, and coordination client testing. Related technologies: Springboot, Rest API, Mybatis, JPA, Postgresql. Name: Liferay Portal Introduction: Liferay Portal is an open source enterprise content management system that provides commercial support to multiple companies. Its portlet-based development model makes it easy for users to dynamically manage page layout and content. Pluggable multi-function plugins flexibly complete the expected functions. Roles and resposibilities: Product maintenance, responsible for the system and LDAP module. Maintain liferay-portal and liferay-ee systems and submit for repair. Related technologies: Liferay, portlet, Struts, Spring, Hibernate, JSP, LDAP, Bootstrap, freemarker, Git, JIRA. Open Source: Grape Introduction: Use python to obtain basic information of A-share stocks, daily trading information, calculate K-line and other technical indicators, and screen through certain stock selection strategies. In the process of stock investment, I was unable to have too many stocks and had no time to observe all the K-lines and stock infomations, so I developed this system to screen by itself. Screened stocks can be adjusted according to different strategies, and non-relational database MongoDB is used for local persistence, and the screening results are automatically uploaded to personal blog. Related technologies: Python, MongoDB, Tushare, pandas, unit testing. Personal Skills 2011, Obtained English CET-6 certificate, fluent in listening, speaking, reading and writing. 2012, Obtained Financial English Certificate. 2012, Obtained IBM Certificate (SOA and Service Computing). Linux server maintenance experience. 6 years of Linux desktop experience. Familiar with common Linux commands. Familiar with Intellij / eclipse debugging, quickly locate problems. Automate testing with Junit. Hobbies Personal technical blog Stackoverflow Github","raw":null,"content":null},{"title":"Oops...","date":"2023-03-04T13:39:50.064Z","updated":"2023-03-02T03:26:34.063Z","comments":true,"path":"/404.html","permalink":"http://bejondshao.github.io/404.html","excerpt":"","keywords":null,"text":"It’s time to have a rest😊.","raw":null,"content":null},{"title":"","date":"2023-03-04T16:14:08.099Z","updated":"2023-03-04T16:14:08.099Z","comments":true,"path":"邵帅-大连理工大学-软件工程-Java-20200429.html","permalink":"http://bejondshao.github.io/%E9%82%B5%E5%B8%85-%E5%A4%A7%E8%BF%9E%E7%90%86%E5%B7%A5%E5%A4%A7%E5%AD%A6-%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B-Java-20200429.html","excerpt":"","keywords":null,"text":"邵帅 • 男 • 1990-10 • 辽宁 大连 • [email protected] • +86 18640902787 六年Java后台研发经验,曾就职于Liferay,服务于开源框架Liferay(CMS)的维护和支持,服务于亚太,欧美客户。 现从事酒店智能化管理,主要负责在线入住,在线选房,在线离店等一整套智能化酒店业务流程,提供移动PMS解决方案并实现。带领两个人做产品研发和维护。 对安全,身份认证、授权颇有研究。对Keycloak有过系统的学习。利用业余时间做单点登录,LDAP集成。使用Spring Security做OpenId Connect身份认证与授权。 对消息中间件远程调用有完整的产品设计和实现经验。熟悉主流Java框架。对JVM调优,内存泄露有研究和调优经验。 拥抱技术,对技术有钻研的兴趣。能很快的熟悉新的思想和技术方案并使用。能系统的学习技术,并善于做记录和总结,喜欢用自己所学帮助他人。 教育经历 2009-2013 : 大连理工大学,软件工程,本科。 工作经历 北京石基昆仑软件有限公司(2016/05-至今) 工作内容为智能化酒店服务管理。主要负责酒店自助入住相关业务,负责Kiosk自助机产品研发,云端GJE在线入住产品研发,移动端PMS的服务开发。包括创建订单,在线选房分房,预授权,付款,离店等功能。 入职两个月提前转正,并承担Kiosk自助机产品和GJE产品开发。后由于人员变动,成为项目负责人。 负责新技术调研,如SpringBoot, Camel, Keycloak。技术攻关,比如消息中间件RPC模式应用,新PMS接口对接,产品设计和代码规范。 优化代码结构,性能调优,代码审核。 负责Java开发人员招聘和面试。 Liferay(2014/06-2016/04) 工作内容为开源项目Liferay维护。为美国,日本,印度,澳大利亚,欧洲客户提供技术支持。 与客户支持人员沟通(英语),为客户分析Liferay的bug,其中包括搭建环境,分析客户数据,分析问题日志,重现问题,调试并解决问题,制作补丁,向低版本移植修复,解决不同修复之间代码冲突。问题涉及前台,后台API,系统业务模块,权限管理,Liferay升级兼容等问题。 Thread Dump,Heap Dump分析,JVM调优。 项目经历 产品名称:Kiosk自助机服务系统 产品简介:Kiosk自助机服务系统是部署在酒店,通过与酒店PMS进行交互完成客人自助查询分配房间,刷预授权,人脸识别,上传证件到公安局,办理入住以及离店的多功能智能化系统。Kiosk提供两套接口,一套接口(SOAP协议)供酒店自助机使用。解决客人排队,自主选房的问题,同时减轻酒店前台压力。另一套接口(REST API)供GJE使用,完成在线选房,入住,离店等功能。 角色及职能:产品负责人,对客户需求分析,设计,接口定义,并做技术难点实现。实现进度把控,产品质量把关。 相关技术:Java EE, EJB, CDI, AOP, Mybatis, JPA, JWT,RabbitMQ, Postgresql, Oracle, Maven, SVN。 产品名称:Guest Journey Engine(GJE) 产品简介:GJE是供第三方互联网厂商如飞猪,携程等使用的在线办理酒店业务的接口。服务于国内五星级酒店如香格里拉,红树林,万豪等。对接PMS有Opera(国内四星级五星级酒店行业通用酒店管理系统),Cambridge(石基信息自主研发云PMS)。主要功能包括创建订单,在线选房分房,刷预授权,在线入住,抛账,自助离店等。其中GJE调用酒店内网Kiosk接口遇到网络限制,通过应用RabbitMQ的RPC模式,实现了跨域调用。 角色及职能:产品负责人,对客户需求分析,设计,接口定义,并做技术难点实现。实现进度把控,产品质量把关。编写自动化并发测试代码。 相关技术:Java EE, EJB, CDI, AOP, Mybatis, JPA, JWT,Postgresql, RabbitMQ。 产品名称:Kunlun 360 产品介绍:Kunlun 360是石基昆仑自主研发的,全方位服务酒店业务的综合性系统。包含订单处理,客房管理,客人管理,账目管理,证件上传公安局,扫码支付,电子签名,发票打印等多个模块。实现移动PMS功能,方便服务人员专项服务客人,不必局限于前台或自助设备,让客人获得更优质的体验。 角色及职能:本人负责订单,客房,客人,账目管理等模块。负责需求分析,功能调研,接口设计,功能实现,协调客户端测试。 相关技术:SpringBoot, Mybatis, JPA, Postgresql。 产品名称:Liferay Portal 产品简介:Liferay Portal是一个开源企业级的内容管理系统,为多家企业提供商业支持。其基于portlet的开发模式使其便于用户动态管理页面布局和内容。可插拔的多功能插件灵活完成预期功能。技术体系是基于SSH的多功能的portlet容器。官方标准版本的功能包括内容管理,日历,用户导入(LDAP,SAML,AD等),动态可配置的角色和权限的管理,内容搜索(基于Elasticsearch)等。 角色及职能:产品维护,负责系统与LDAP对接模块。维护liferay(开源)和liferay-ee(private)系统,提交修复。 相关技术: Liferay, portlet, Struts, Spring, Hibernate, JSP, LDAP, Bootstrap, freemarker, Git, JIRA等 个人项目:Grape 项目简介:使用python获取A股股票基本信息,每日交易信息,计算K线等其他技术指标,通过一定的选股策略进行筛选。本人在股票投资过程中,迫于股票数量太多,无暇观察所有K线,所以开发此系统以自行筛选。筛选的股票可根据不同的策略调整,并使用非关系型数据库MongoDB本地持久化,同时自动上传筛选结果到个人博客中。 相关技术:Python, MongoDB, Tushare, pandas。 个人技能 2011年,获英语CET-6证书,听说读写流利。 2012年,获金融英语证书。 2012年,获IBM证书(SOA与服务计算)。 Linux服务器(CentOS)维护经验。六年Linux使用经验。熟悉Linux常用命令。 熟练使用git以及Intellij/eclipse调试,快速定位问题。使用Junit自动化测试。 兴趣爱好 技术博客 Stackoverflow Github","raw":null,"content":null},{"title":"Who This Shining Guy Is?","date":"2015-12-18T07:42:48.000Z","updated":"2023-03-02T04:46:15.801Z","comments":true,"path":"about/index.html","permalink":"http://bejondshao.github.io/about/index.html","excerpt":"","keywords":null,"text":"I am so unfamous that no one comes to me to talk about business. I thought this is so wasteful so I keep on working… keep on working… keep on… If you want to reach me, please contact [email protected] (Please don’t mail to this address). Attaching a gmail address just to pretend international. I rarely check that email. [email protected] is more offen, well, not so offen. Because the 163 email is full of junk ADs. How did they get my email? Why am I so famous? That doesn’t make sense. 2017-08-23","raw":null,"content":null},{"title":"wechat","date":"2015-12-18T07:42:48.000Z","updated":"2023-03-02T03:26:34.292Z","comments":true,"path":"about/wechat.html","permalink":"http://bejondshao.github.io/about/wechat.html","excerpt":"","keywords":null,"text":"Here is my wechat: slbxts Or you can saomiao the picture.","raw":null,"content":null},{"title":"categories","date":"2019-12-29T13:21:08.000Z","updated":"2023-03-02T03:26:34.292Z","comments":true,"path":"categories/index.html","permalink":"http://bejondshao.github.io/categories/index.html","excerpt":"","keywords":null,"text":"","raw":null,"content":null},{"title":"tags","date":"2019-12-29T13:23:57.000Z","updated":"2023-03-02T03:26:34.311Z","comments":true,"path":"tags/index-1.html","permalink":"http://bejondshao.github.io/tags/index-1.html","excerpt":"","keywords":null,"text":"","raw":null,"content":null},{"title":"tags","date":"2019-12-29T13:21:57.000Z","updated":"2023-03-02T03:26:34.311Z","comments":true,"path":"tags/index.html","permalink":"http://bejondshao.github.io/tags/index.html","excerpt":"","keywords":null,"text":"","raw":null,"content":null}],"posts":[{"title":"How to make mac run shell on startup","slug":"How-to-make-mac-run-shell-on-startup","date":"2020-05-05T14:21:00.000Z","updated":"2023-03-02T03:26:34.083Z","comments":true,"path":"2020/05/05/How-to-make-mac-run-shell-on-startup/","link":"","permalink":"http://bejondshao.github.io/2020/05/05/How-to-make-mac-run-shell-on-startup/","excerpt":"","keywords":null,"text":"Write a simple shell, like: 123456789101112#!/bin/bashHOME=/rootLOGNAME=rootPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/binLANG=en_US.UTF-8SHELL=/bin/bashPWD=/rootcd /Users/bejond/tools/mongodb-osx-x86_64-4.0.9/bin./mongod --dbpath /Users/bejond/data/dbecho "Mongod Server Started" Save it as a .sh file, like /Users/bejond/startmongodb.sh. Then make the shell runnable. sudo chmod a+x /Users/bejond/startmongodb.sh Create a .plisth file in /Library/LaunchAgents/, like com.startup.mongodb.plist, in order to run the script or command. Edit the file, like: 1234567891011121314151617181920212223242526272829303132<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"> <dict> <key>EnvironmentVariables</key> <dict> <key>PATH</key> <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:</string> </dict> <key>Label</key> <string>com.startup.mongodb</string> <key>ProgramArguments</key> <array> <string>/Users/bejond/startmongodb.sh</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <false/> <key>LaunchOnlyOnce</key> <true/> <key>StandardErrorPath</key> <string>/tmp/startup.mongodb.stderr</string> <key>UserName</key> <string>bejond</string> <key>GroupName</key> <string>admin</string> <key>InitGroups</key> <true/> </dict></plist> Seeing ProgramArguments, this means we can pass a command and arguments. You can also change ProgramArguments to Program, but without <array> element. Add the com.startup.mongodb.plist to launchd: $ sudo launchctl load /Library/LaunchAgents/com.startup.mongodb.plist Remove the com.startup.mongodb.plist from launchd: $ sudo launchctl unload /Library/LaunchAgents/com.startup.mongdb.plist Then /Users/bejond/startmongodb.sh would be executed just now. And it would also run on next startup. [1] Running script upon login mac - answered by trisweb [2] Adding Startup Scripts to Launch Daemon on Mac OS X Sierra 10.12.6, by seeing the .plist file [3] Run command on startup / login (Mac OS X) - answered by Scott","raw":null,"content":null,"categories":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/categories/Linux/"},{"name":"Mac","slug":"Linux/Mac","permalink":"http://bejondshao.github.io/categories/Linux/Mac/"}],"tags":[{"name":"mac","slug":"mac","permalink":"http://bejondshao.github.io/tags/mac/"}]},{"title":"日内交易策略 ","slug":"日内交易策略","date":"2020-03-21T18:44:00.000Z","updated":"2023-03-02T03:26:34.240Z","comments":true,"path":"2020/03/22/日内交易策略/","link":"","permalink":"http://bejondshao.github.io/2020/03/22/%E6%97%A5%E5%86%85%E4%BA%A4%E6%98%93%E7%AD%96%E7%95%A5/","excerpt":"","keywords":null,"text":"注:该策略未经过详细回测和实操,仅提供思路,不作为投资依据。 另外,这个策略收益不稳定,可能造成得了芝麻,丢了西瓜的情况。在没有自动化交易条件下,不建议使用。 再注:投机是迷途,投资才是最终归宿。 根据具有适量流动性和适当波动性的证券的价格规律,做日内的高抛低吸,在保证扣除手续费后实现盈利。在未发生急跌或急升的情况下,每完成一个交易回合(高抛低吸)即可实现盈利。 名词介绍: 起始价格: 日内交易策略的证券基准价格,理想情况下,证券价格围绕这个价格上下浮动。起始价格一般情况下日内是不会变的,特殊情况除外。 价位间隔:日内交易策略的价格浮动计量单位,一般在1%以内,比如可转债,价位间隔可以是0.25元,可以是0.5元,0.7元,1元等都可以。 委托价格:由起始价格加上或减去一个或多个价位间隔的价格,用于委托买单和卖单,实现套利。 成交量:在资金少的情况下,可以以股为单位,如100股,1000股等。资金多的情况下,可以以仓位为计量单位,比如1/4仓位,1/2仓位。 手续费比例:每次成交的手续费,比如十万分之5,百万分之5,万分之2.5等。这个手续费其实相对于套利来说微乎其微,目的是说价位间隔不可设置过小,否则获利太少意义不大。 交易回合:完成一次低价买入,高价卖出即是一个交易回合。有时候行情变化大,无法自动完成交易回合,那么在收盘时需要平衡仓位,在不受较大损失情况下,控制仓位。 成本分析: 假设交易起始价格为a元,价位间隔为i元,成交量为n股,手续费比例为x。则一个交易回合(低吸高抛)的收益为 (a + i)n - (a - i)n - (a - i)nx - (a + i)nx = 2in - 2anx。若要满足 2in - 2anx > 0,需要满足 i > ax。以可转债为例,a往往为100左右,这里设为100元,x则是交易手续费比例,一般为十万分之五或百万分之五,这里取十万分之五,即0.00005。代入得 i > 0.005,即委托差值在0.005以上就可以实现盈利,盈利为 2(i - 0.005)n,其中n越大,即资金越多,盈利越多。 盈利分析: 在上述成本分析可看出,一个成功的交易回合的盈利为 2(i - 0.005)n,可见i和n越大,一个交易回合的收益就越大。当然n大到一定程度时会影响交易价格,会让其他人误认为是压单或托单,所以挂单时要分批次挂单,这个在后面最大化利润再分析。i不应过小,仅比成本多一点虽然能成交,但是收益太小,二是证券价格容易超出价格区间,就使得后续交易很被动,要么不继续参与交割,要么放弃之前的利润而向时价靠拢。 最大利润: 想要获得最大利润,不能单看某个交易回合的利润,要看整个交易日的收益,即每个交易回合的利润*交易回合数量的值达到最大。交易是否能成交取决于价格波动是否达到了交易回合设定的交易价格。倘若一支证券当日处在连续上升或持续下跌的过程,那么日内交易就基本不会进行,因为价格满足不了交易区间设定的价格,就会要么卖飞,买不到筹码;要么收集了很多筹码,但没机会出手。这种情况就是非理想状态,这种情况发生得比较少,尤其是对于前期沉寂的可转债来说,很难遇见,可能几个月都是横盘,日波动范围在一到两元之间,术语叫振幅,在3%以内,这个振幅不是稳定不变的,有时候可能一下子变大,只要收盘价和基础价格差距不大,都没什么问题。就怕收盘价与基础价相差两个以上的价位间隔。我们需要做的就是在可控范围内的振幅内反复摩擦,实现套利。 起始价格a,价位间隔i,成交仓位的设定 这三个变量就构成了日内交易模型最基本的要素,设置得合理与否直接关系模型的收益率(注:资金量不同,不方便描述,因此最大利润模型以成交仓位和收益率来计算收益,不以资金量为标准)。 a. 1/2仓位2i委托 假设证券是如下图波动(横轴坐标11:30和1:00应该是一起的,中间不应该有半小时,请忽略这个错误😂): 这是较为理想的情况,股票整日波动像波浪一样,并且上下趋势明显,波动幅度不大,且高位和低位与起始价格差距相近。这种情况就可以以开盘价为起始价a,以股票以往日内高点和低点作为高点和低点来计算价位间隔i。价位间隔的计算需要根据高点和低点的差值除以2。如果不是量化交易,人工设定买卖点,则可以直接以昨日高点和低点来设定,不过设定的差距最好相同,比如0.5元。 开盘前如果没有证券,则开盘可以买入1/2仓位,在有证券的前提下,在开盘后,观察证券走势,委托卖出所有的持有证券,价格为 a + i,并用剩余1/2的资金设定买入,价格为 a - i。这样能在价格高点时完成一半交易,在价格低点时,完成另一半交易。完成一个交易回合后,即实现了上述的盈利。同时继续操作。 在收盘时可以根据手中证券和证券价格来判断是否进行收盘前交易。一般可保持1/2仓位,1/2资金。倘若今天价格走高,证券都出手了,可以在价格不高,且未超过a + i的情况下适当补仓,不一定局限于1/2仓位。同理,倘若今天价格走低,接盘满仓了,尾盘可考虑在不亏损的情况下清部分仓位。这个是应该做的,可以空仓,但是尽量不要满仓。因为对于第二日的日内交易,满仓会很被动,会影响后续的日内交易。 开盘前的建仓和收盘前的控制仓位可适当放宽原则,即不考虑昨日和今日的起始价格,保证有部分筹码且未满仓,才能具有灵活性。 b. 1/4仓位3i委托或1/4仓位2i委托 如果证券是如下图波动: 这种情况是比第1种更普遍的情况,即日内波动不太明显,绝大多数是处在微小的波动中,高位低位出现的次数少。这种情况就很考验投机者的交易素养,倘若设定价位间隔i过大,就可能出现没有交易,或空仓或满仓的情况,这样就容易在尾盘不得不控制仓位而吐出今日的收益,导致没有收益。这种情况就需要缩小价位间隔i,比如0.25。这种价格的波动是可以根据以往证券价格来预判的,比如有的证券较不活跃,出现俗称织布机行情,这种情况在普通投资者看来是没有行情,但是在日内交易模式来看,是再理想不过了,只不过每次交易收益不高,需要多次操作罢了。 这种行情的交易模式可如下配置:开盘保证有1/4的仓位,然后设定较小的i值,委托卖出所有证券,卖出价格为a + i。如果开盘有1/2的仓位,如果委托卖出所有证券,且价格较低,一旦出现放量拉升,那么就会出现踏空的情形,从而不便再接回筹码,就会很被动,很可能丧失当日甚至以后的交易机会。这种较小波动的行情,可以委托卖出已持有的1/2仓位中的一半,即1/4仓位,价格为a + i,然后再委托剩下的1/4仓位,价格为a + 2i。同时委托买单,分别为1/4的仓位,价格为a - i和 a - 2i。不难看出,当i较小时,我们的交易价格区间就变成了3i,即以a + 2i的价格卖出,以a - i价格买入;以a + i价格卖出,以a - 2i价格买入。这样就能减少踏空和较高位(a - i)接盘的风险。 倘若上述委托a + i成交,我们就可以按照程序委托买入1/4仓位,价格为a - 2i,所以就有了1/2仓位的a - 2i的买单尚未成交;同理倘若a - i成交,则接着委托卖出,价格为 a + 2i,所以就有了1/2仓位的a + 2i的卖单尚未成交。这样形成了堆积,会有不成交的情况,导致空仓或满仓。所以为了保险起见,可以在成交后的委托仍然以2i原则来委托:即不以i的大小为依据,成交后的委托价格差固定为2i,而不是3i。那么当1/4的a + i卖单成交后,立即委托1/4的a - i买单,保证仓位和资金的平衡。这种1/4仓位2i委托模式优点是不易踏空或接盘,缺点是收益较少。这种收益较多较少没有定论,完全是看日内波动的情况的。 c. 动态起始价格1/2仓位2i委托 如果证券是如下图波动: 这种情况即是证券有启动的现象,在1/4或1/2仓位成交后无明显回调,资金进入趋势明显的情况,就说明日内交易失灵了,不能再按照以往的2i或3i区间模式来下买单了,这时候就要考虑调高起始价格a,重新设定交易规则,其实规则大致是不变的,只不过a在原有基础上上调到a + i。所以在空仓且买单a - i长时间未成交的情况下,就要委托a + i买入1/4仓位的买单,注意这个a + i的价格要和当前价格有一定差距,不能是立即成交的那种,否则就成了追高了。读者可能会疑问a + i卖出,再a + i买入,岂不是亏了两笔手续费?别忘了,还有一笔a + 2i已经成交了,所以当出现空仓未成交的情况下,说明已经有2i的盈利了,这时候那点手续费是可以忽略不计的。成大事者不拘小节,就放心的委托a + i买单吧。剩下的操作和前两种一样,只不过起始价格a都变为a + i而已。 同理,如果证券价格出现大幅下跌,导致满仓,这时就要考虑降低起始价格,降低委托卖出的价格,保证1/4或者1/2资金。 不论这两种情况发生了哪一种,收盘前最好保证有部分证券和部分现金,以应对第二天高开或低开的情况。 至于收益率,还是那句话,在i比较大时,交易次数越多,收益率就越高。这里就不计算了,因为理想总是很丰满,现实往往不尽如人意😂。这个策略就是赚个辛苦钱,别期望太高,因为每次设定都是1/4或1/2仓位,并且价格区间在价格的1%左右,所以收益不会太高。当日能有0.5%收益就不错,有1%收益就很好了。超过1%那就是运气好,晚饭可以加鸡腿了😂。当然,没有收益也很正常,甚至亏损(价格偏离预计区域了,收盘前买回或卖出)都很正常,有赚就有亏嘛。 补充:如果你觉得计算委托价格麻烦,有简化版本:将资金分为4,6或者8份,选择起始价格a(弱化a),将a设定为当前交易价格,设定固定的价位间隔i(牢记i),然后以a + i价格委托卖出1/6仓位,以a + 2i价格委托卖出1/6仓位,以a - i价格委托买入1/6仓位,以a - 2i价格委托买入1/6仓位,这样就剩下1/3资金(这1/3资金是应对趋势上涨或趋势下跌设定买单用的,希望用不到)。如果某一个委托成交,比如a + i卖出成交,获得资金,则起始价格变为当前价格,即a + i,反向委托,立即以a价格委托买入1/6仓位。如果a - i买入成交,获得证券,则起始价格变为当前价格,即a - i,反向委托,立即以a价格委托卖出1/6仓位。每一次新的委托都是以最近一次成交的反向操作。只要价格不大幅下跌,那么这个无脑委托方式会吃到每一次波动的收益。我们丝毫不需要关注目前持仓的市值是多少,盈亏多少。我们只需要在成交后做下一次委托。 举个例子:资金4万,两百股可转债,当前价格100元,价格区间0.5元。则预先委托卖单100.998元(这个小数稍后解释),100股;卖单100.498元,100股;委托买单99.501元,100股;委托买单99.001元,100股。如果价格升到100.5元,100股卖出,换回10050元,立即委托买单,100.001元,100股。如果价格降低到100元,则买入委托成交,获得100股。则立即委托卖单,100.498元,100股。以此类推。我曾用这种无脑委托薅羊毛的方式成功在虚拟币套牢的情况下解套,并且小赚。由于资金不大,所以完全是无脑委托,毫不关注价格走势,成交就获得收益,最终解套。 你可能注意到我委托卖单为比整数少一点100.998,委托买单比整数多一点99.501。这是因为人们都喜欢取整,所以在卖单101元会形成排队,同理在买单99.5会形成排队,我们可以用少许的价格差,轻松排在前面,预先成交。一来节省时间,二来有可能真的因为排队而没能成交,错失收益。 这种委托方式简单无脑,弱化a,a总是变为成交的价格,牢记i,反向操作委托即可。丝毫不需要思考,只要成交,且有波动,就注定有收益。 再啰嗦一些:一、该日内交易策略比较适合T + 0的交易品种,因为证券和资金可日内多次使用,且满仓也容易调仓。T + 1品种慎用。二、该策略适用于交易量一般,不能太少,也不能太多的个股,价格波动较不明显,最近一段时间处于横盘阶段,没有大量资金进入流出的个股。对于右侧的个股建议拿住不动,对于左侧的个股建议清仓。 聊聊投资和投机 正常来说,投资应该是多学习,多调研,少交易。即将大多精力用于研究公司,研究对象,研究市场,预期未来数年的情况。比如股票,就是看好一个公司未来几年的发展预期。倘若我们总是盯着短期(这个短期可能是几分钟,几天,几个月,甚至一两年)股价,低买高卖,那就是投机。也就是说只要你将眼光放在股价上,进行低买高卖,不论时间长短,那就是投机。利弗莫尔就是这么区别投资和投机的,他自始至终都自认为是投机客。简单来说,投资关注的是价值,投机关注的是价格。 对于投机客来说,交易时间会容易盯盘,这有很大弊端,比如无法专心工作,享受生活,做本应该做的事,做需要专注的事,比如学习等。另外盯盘过分关注每笔交易和价格波动,未持有时希望其下跌,看到上涨则有踏空焦虑;持仓时希望其上涨,下跌则有亏损焦虑。所以盯盘肯定会造成焦虑,无法集中注意力,对什么事都无法投入,提不起兴致。而实际上,这些波动和你关系真的不大,这些价格都是数以万计的参与者委托形成的,到底是涨是跌,是由他们决定的,和你看不看盘,没有一点关系。你不看盘,它按照这个趋势波动,你看盘,它还是按照这个趋势波动。你看盘这件事是没有任何收益的事,那么你为什么还要看盘,给自己徒增烦恼呢? 你可能会反问,那么日内波动策略,不就是根据短期价格波动来买卖的吗?那不看盘如何操作? 其实,我是推崇自动化交易的,也叫量化交易。但是目前,我关注的可转债并没有交易接口,所以无法量化交易。当然可以后来丰富日内价格波动规律,统计可转债信息,发现可投机个股。 日内交易策略,应该是佛系的,无情绪的。什么意思?假设我不使用日内交易策略,那我完全不需要知道日内价格波动,交易期都不需要看盘。倘若使用日内交易策略,那么只需要根据上一交易日的高低点,收盘价,大致设定起始价格,价位间隔,双向委托价格,成交仓位而已,然后就顺其自然吧。成交了就赚个零花钱,没成交也没损失什么,不是么?设定好成交提醒,成交了,然后设定反向委托,关了手机继续工作。打开交易软件只是设定反向操作,不需要也不要关注其价格波动,不要做任何分析,不要做任何多余的调整。因为除了委托,其他的行为和思考都是多余的。倘若有交易接口,整个过程都不需要人做任何操作。这也是程序比人优秀之处,没有情感,没有思想,只按照策略规则执行。","raw":null,"content":null,"categories":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/"},{"name":"策略","slug":"股票/策略","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/%E7%AD%96%E7%95%A5/"}],"tags":[{"name":"交易","slug":"交易","permalink":"http://bejondshao.github.io/tags/%E4%BA%A4%E6%98%93/"}]},{"title":"股票交易所思","slug":"股票交易所思","date":"2020-02-25T14:52:00.000Z","updated":"2023-03-02T03:26:34.257Z","comments":true,"path":"2020/02/25/股票交易所思/","link":"","permalink":"http://bejondshao.github.io/2020/02/25/%E8%82%A1%E7%A5%A8%E4%BA%A4%E6%98%93%E6%89%80%E6%80%9D/","excerpt":"","keywords":null,"text":"买入时机很重要,同样一直股票,甲买后浮盈20个点,乙买后套8个点。假设今天股票跌5个点。甲和乙看这个股票的观点很可能截然不同,甚至操作完全相反。而股票却是同一支股票。2020-02-07 上面是我今年年初对自己的频繁操作所形成的交易总结,我觉得这个道理很简单,但是又没有参悟透。十分有必要再详细讨论。这篇文章是对自己混沌思想的理顺,不作为投资依据。 一支股票上市后,二级市场就可以自由交易,价格也会随着交易而变化。股票的数量不变,价格却升高或降低。我曾仔细思考过价格变化的原因,那就是有相当的资金进入或流出。虽然一支股票会无交易骤升,但是只要有人想要套现,就必然需要场外资金接手,否则会出现无量骤跌的情形。反之无量骤降同理,如果想要抄底,尤其是涉及量比较大的抄底,必然是持票者割肉的结果,否则就会随着买盘的增多而拉高股价。具体原理我就不在此详细解释了。也就是说,假设你想通过二级市场的买卖来获得利润(暂不考虑股息),那么买入和卖出时机很重要,更极端来讲,买入时机至关重要。 只要一支股票不是有突发不可弥补的事件,股价都是在市场交易中以肉眼可见的速度变化的。从日线,周线来看,也是平滑的。一支股票,不论股性如何,基本面如何,未来期望如何,它的股价都会变化。我们都知道股票应该低买高卖,但是别忘了,每一次价格变化,都是由成交决定的。也就是说,在这个价格,持票者和持币者的意见是截然相反的:持票者可能是后市看跌,持币者后市看涨。当然,持票者卖出不一定是后市看跌,他可能是想做个日T或者阶段T。但是持币者买入一定是后市看涨,我相信没有人会认为某支股票未来几天会跌而现在买入,他们都是恨不得此刻买完就涨,再不济明天应该是涨,起码未来几天应该涨。实际上,买入就涨,那是神仙才能做到的事。我们买入股票涨或者跌都是正常的。 可以积累预测未来几天的股价走势的经验,但没必要根据时分交易推断下一秒钟股价是涨还是跌。一个人的格局要大,才能做大事。局限于蝇头小利会显得很拘谨,因一点小波动而喜怒无常,不会有大作为。那多大的格局算大呢?因人而异,不同资产或不同评判标准自然不同。若用相对百分比来判断的话,我觉得一天仓位的百分之十以内都是可以接受的,也就是说上午当日浮盈5个点,结果下午收盘亏5个点,都能坦然接受,而不至于悔恨:我上午卖了就好了。十个点的波动还是比较抽象,也许有的人持仓少,十个点波动也没多少,那么怎么判断。经历过风雨,才能见到更鲜艳的彩虹。能坦然接受一日损失一个月的工资,日收益超过一个月工资也不沾沾自喜,才算小有所成。说的是什么意思,就是不要为了三五个点而担惊受怕,十分没必要。也没必要每天为了这三五个点做T,首先日内波动无法预测,其次日内持续走高或持续走低,都会让做T损失更多。看日内波动而脑补做T的收入就是给自己画饼,这是完全不切实际的想法。并且会造成右侧T飞的情况,要么高位接回(这时高位接回很可能会吃一波回撤,更加难受),要么就一直看着它带着本属于你的收益越走越高。 说到右侧,就是在我几年交易经验的总结。我曾想抄底实现收益最大化,我犯了事后诸葛亮的看盘定策略的幼稚错误。我曾看着K线,想象自己在低点买,在高点卖,这就是一倍的收益啊,我的亏损就可以挽回了,并且还能大赚一笔,简直太天真了😂。那时的我并不明白,我并没有看底的能力,我也没遇到谁有看底的能力,连投机天才利弗莫尔都告诫我们不要抄底,因为没人知道底在哪里。而这种事情却在左侧时时刻刻在发生,上文已说过,每次交易都是持票者卖出,持币者买入的。认为自己是在抄底而买入股票,这件事动机就有问题,他想着收益最大化,很可能会栽跟头。为什么?首先,没人知道底在哪里。其次,即便此时是底,但是股票不是海浪,不是说到了底部就会上升。以我观察的经验来看,股价到底了,也会有一段时间,短则几天,多则几个月的时间横盘,即小幅波动。有的股票甚至一直在底部横盘,就再也没启动过。甚至赶上行情不好,继续领跌。一旦左侧交易买入,会有三种结果:一、继续下跌,即套牢。这是最差的情况。二、小幅上升,这种情况很少碰到。三、未知时长的横盘。不论这三种情况出现哪一种,都不是好的交易模式。即便是第二种,它的上升也是很少的,十到二十个点就是上限了,继而又下跌。而横盘也是不值当的,尤其是那些幻想买入就拉升的人来说,这种焦灼等待的时期会让他丧失耐性,即便后来拉升了,也会在有少许盈利后就卖掉。对于第一种套牢的情况,则更是糟糕。谁都不喜欢亏损,看到账户上”-“后面的数值越来越大,心理肯定会不好受。这时候好多人会调动资金补仓,我就曾犯过这样的错误,结果只是让”-“后面的数值越来越大,甚至补到最后,”-”的数值比我建仓时的资金还多。抄底抄成股东,说的就是我🌚。倘若情况并没有这么糟,只是小套,但是此时你对这支股票的评价可能和你买入时的看法截然不同了,即便没有割肉,当股票涨上来时,你很可能会立即卖出,庆幸自己没有亏损,还小赚(可能只赚了个盒饭钱😂),但是后面的上涨就永远跟你没关系了。因为你陪着它度过了不受待见的低谷,但是你没有和它一起成长,这个时候会加深你对它的不屑而羞于买回,内心一直在看空,也就永远的失去它了。 倘若我们买在右侧启动(后续补充) 不要做T,更不要做日内T。对于右侧的股票,做T是对它的不尊重。你不尊重它,它就给你颜色瞧瞧。还有一点我不赞成做T的理由:精力白白消耗在盯盘上,收益却远远小于自己的其他收获。一个人的时间和精力都是有限的,股市开盘的时间都是一天中最好的时候。这个时间段,不论是在工作中,或个人生活中,都是十分宝贵的。我们本应该拿这段时间做该做的事,学该学的习。倘若频繁看盘,会涣散精力,而无法输入输出,造成焦虑,甚至狂躁。相信很多盘中看盘尤其是盯盘的人深有体会。这件事是彻彻底底的亏损。而盯盘期间,如果行情没有做T的机会,那么这段时间的盯盘就是完全的浪费掉了。即便有做T机会,操作完后,还会继续盯盘,精神更紧张。卖出了会考虑买入,买入了会考虑卖出,最终精疲力竭。甚至卖飞了,买了又深套了,都会造成懊悔,真是赔了夫人又折兵,十分的愚蠢。所以应该限制自己看盘,尤其是克制自己不在开盘期间看盘。开盘时间看盘会受日内波动影响个人判断,影响对股票的评价,一支股票怎么会因为日内的波动而改变趋势呢,哪只右侧股票不是经历过大幅日内波动呢。只有看日线,甚至周线,才能看到一倍甚至十倍的收益。只有置身事外,才能看清庐山真面目。当你重新回到没有参与炒股之前的生活状态,你会找回原来的自己,你会发现,原来没有股市的生活是这么的美好😂。你可能会担心一旦这支股票在日内改变了趋势呢?还是上面的理论,要坦然接受日内十个点的波动[3]。几倍收益的股票在上升过程中,日内波动不值一提,数天甚至几周的回调都是必须经历的过程。但是,日内看盘对自己的投资思维的负面影响以及生活影响,要远远超过十几个点的收益的。 如果你看好一支股票,认为它处在右侧,那么可以少量买入,比如一成。如果它回撤了,不要买入,要有耐心等待,反正一成仓,损失又没多少,这样你就会有耐心等待它回升。当它继续走高时,再买入,这样表面上看是降低了收益,但实际上,如果它是真正的右侧,这种交易模式是最稳妥的。我为什么说如果它是真正的右侧,和左侧一个道理,没有人知道底在哪里,也没有人确定这支股票是在右侧,只能根据经验来判断这支股票可能是右侧。分步骤建仓是减少损失的保守方式,虽然收益不如一次性操作来得多,但是这种方式对心理的考验是最小的,最能使你平静的度过套牢时期。 [3] 一般高位高开六个点以上的股票有可能在当天跳水,但几率无法确定,其他情况的跳水有待慢慢总结。","raw":null,"content":null,"categories":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/"},{"name":"思考","slug":"股票/思考","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/%E6%80%9D%E8%80%83/"}],"tags":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/tags/%E8%82%A1%E7%A5%A8/"}]},{"title":"SVN Issues","slug":"SVN-Issues","date":"2020-02-12T09:08:00.000Z","updated":"2023-03-02T03:26:34.196Z","comments":true,"path":"2020/02/12/SVN-Issues/","link":"","permalink":"http://bejondshao.github.io/2020/02/12/SVN-Issues/","excerpt":"","keywords":null,"text":"14:14 Commit failed with error 0 files committed, 42 files failed to commit: xxx 移植xxx相关的部分业务 svn: E200009: Commit failed (details follow): svn: E200009: Cannot commit ‘/Users/abc/xxx/Lastname.java’ because it was moved to ‘/Users/abc/xxx/bizmodel/Lastname.java’ which is not part of the commit; both sides of the move must be committed together The reason is you are moving the file to another folder while also editing the file. So it means they can’t be done together. You need to revert the changes(or make a copy about the changes.) do move action and commit. Then do edit and commit.","raw":null,"content":null,"categories":[{"name":"Tools","slug":"Tools","permalink":"http://bejondshao.github.io/categories/Tools/"}],"tags":[]},{"title":"关于股市的思考","slug":"关于股市的思考","date":"2020-02-04T02:46:00.000Z","updated":"2023-03-02T03:26:34.224Z","comments":true,"path":"2020/02/04/关于股市的思考/","link":"","permalink":"http://bejondshao.github.io/2020/02/04/%E5%85%B3%E4%BA%8E%E8%82%A1%E5%B8%82%E7%9A%84%E6%80%9D%E8%80%83/","excerpt":"","keywords":null,"text":"人们看股票容易犯一个错误,总是构思股票后市会涨,所以容易盲目买入。而走势往往不是我们所想的那样。2020-02-04 买入时机很重要,同样一直股票,甲买后浮盈20个点,乙买后套8个点。假设今天股票跌5个点。甲和乙看这个股票的观点很可能截然不同,甚至操作完全相反。而股票却是同一只股票。2020-02-07 好多人喜欢拿基础面,技术面,甚至国家政治层面考虑股票。其实,投机市场,所有的面都是为了股价服务的,都是想不花钱操纵股价。而实际上,股价的波动只有一个因素:资金流向。对于投机者,绝不要听信消息,更不要听信基本面好转,年报涨幅大就买入,利空消息一出就卖,这是迷信,连投机都算不上。2020-03-05 每天守着三五个点的人肯定吃不到大肉,很可能吃到大亏。2020-03-05 股市从来都不缺机会,缺的是发现机会的眼睛。想不劳而获,看到只股票买入就赚钱就是在守株待兔。好的股票不会直接蹦到你面前让你买。直接蹦到你面前的股票是别人有意让你看到的,这样的股票不一定是兔子,很可能是鳄鱼。2020-03-08 你真的热爱交易吗?你绝大多数的交易属于手痒,有钱不花,有股不卖难受。实际上是交易会刺激大脑分泌多巴胺,会兴奋,感觉很刺激。但是这种感觉会很快消失,所以就驱使自己继续交易。2020-03-22 投资不是生活的全部,但投资是一辈子的事情。工作不是生活的全部,但工作不是一辈子必须要做的。理想的生活是不限定在固定的场所办公,在哪里都可以,这样,生活就会更丰富多彩,走遍天下,见识更多的人文地理。当然,全职投资就是实现的一种方式。这种自由需要本金,目前来看1000万吧😂。2020-03-22","raw":null,"content":null,"categories":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/"},{"name":"思考","slug":"股票/思考","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/%E6%80%9D%E8%80%83/"}],"tags":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/tags/%E8%82%A1%E7%A5%A8/"}]},{"title":"grape股票列表-2020","slug":"grape股票列表-2020","date":"2020-01-05T05:46:54.000Z","updated":"2023-03-02T03:26:34.214Z","comments":false,"path":"2020/01/05/grape股票列表-2020/","link":"","permalink":"http://bejondshao.github.io/2020/01/05/grape%E8%82%A1%E7%A5%A8%E5%88%97%E8%A1%A8-2020/","excerpt":"","keywords":null,"text":"grape本地运行的结果。 声明:grape选股策略在不断调整和丰富,股票列表仅记录用,不作为任何投资建议。依据列表选股投资导致亏损本人概不负责。 code name date industry area close 601211 国泰君安 2019-12-30 证券 上海 18.68 601368 绿城水务 2019-12-30 水务 广西 5.86 600827 百联股份 2019-12-30 超市连锁 上海 8.97 600269 赣粤高速 2019-12-30 路桥 江西 4.12 600803 新奥股份 2019-12-30 农药化肥 河北 10.63 002561 徐家汇 2019-12-30 百货 上海 8.15 601699 潞安环能 2019-12-30 煤炭开采 山西 7.24 600021 上海电力 2019-12-30 火力发电 上海 7.95 601199 江南水务 2019-12-30 水务 江苏 3.79 600533 栖霞建设 2019-12-30 区域地产 江苏 3.35 600886 国投电力 2019-12-30 水力发电 北京 9.15 600998 九州通 2019-12-31 医药商业 湖北 14.15 002004 华邦健康 2019-12-31 化学制药 重庆 4.94 000582 北部湾港 2019-12-31 港口 广西 8.95 600033 福建高速 2019-12-31 路桥 福建 3.07 000899 赣能股份 2019-12-31 火力发电 江西 4.87 600785 新华百货 2019-12-31 百货 宁夏 15.02 601607 上海医药 2019-12-31 医药商业 上海 18.37 600332 白云山 2019-12-31 中成药 广东 35.61 600039 四川路桥 2019-12-31 建筑工程 四川 3.36 600598 北大荒 2020-01-02 种植业 黑龙江 9.96 600419 天润乳业 2020-01-02 乳制品 新疆 14.15 002763 汇洁股份 2020-01-02 服饰 深圳 8.8 600229 城市传媒 2020-01-02 出版业 山东 7.43 000718 苏宁环球 2020-01-02 区域地产 吉林 3.95 601333 广深铁路 2020-01-02 铁路 深圳 3.09 002444 巨星科技 2020-01-02 轻工机械 浙江 11.0 002539 云图控股 2020-01-02 农药化肥 四川 4.98 300154 瑞凌股份 2020-01-02 元器件 深圳 5.72 002097 山河智能 2020-01-02 工程机械 湖南 5.96 002789 建艺集团 2020-01-02 装修装饰 深圳 16.8 600461 洪城水业 2020-01-02 水务 江西 6.07 000719 中原传媒 2020-01-02 出版业 河南 7.26 600835 上海机电 2020-01-02 运输设备 上海 16.92 600373 中文传媒 2020-01-03 出版业 江西 14.55 000997 新 大 陆 2020-01-03 软件服务 福建 16.92 600697 欧亚集团 2020-01-03 百货 吉林 18.25 603588 高能环境 2020-01-03 环境保护 北京 9.66 600886 国投电力 2020-01-02 水力发电 北京 9.14 002345 潮宏基 2020-01-06 服饰 广东 4.41 002085 万丰奥威 2020-01-06 汽车配件 浙江 7.29 601098 中南传媒 2020-01-06 出版业 湖南 12.23 300388 国祯环保 2020-01-06 环境保护 安徽 10.43 600757 长江传媒 2020-01-07 出版业 湖北 6.52 600998 九州通 2020-01-07 医药商业 湖北 14.39 002004 华邦健康 2020-01-07 化学制药 重庆 5.04 000573 粤宏远A 2020-01-07 区域地产 广东 3.17 600612 老凤祥 2020-01-07 服饰 上海 49.7 600879 航天电子 2020-01-03 航空 湖北 6.13 002254 泰和新材 2020-01-03 化纤 山东 10.69 600389 江山股份 2020-01-03 农药化肥 江苏 22.14 600498 烽火通信 2020-01-03 通信设备 湖北 27.91 000519 中兵红箭 2020-01-06 矿物制品 湖南 8.51 601857 中国石油 2020-01-06 石油开采 北京 6.23 000875 吉电股份 2020-01-06 火力发电 吉林 3.39 603192 汇得科技 2020-01-06 化工原料 上海 28.35 002636 金安国纪 2020-01-06 元器件 上海 9.18 002298 中电兴发 2020-01-06 软件服务 安徽 7.88 002401 中远海科 2020-01-06 软件服务 上海 11.72 300505 川金诺 2020-01-06 化工原料 云南 23.42 002516 旷达科技 2020-01-07 纺织 江苏 3.05 002582 好想你 2020-01-07 食品 河南 9.2 300683 海特生物 2020-01-07 生物制药 湖北 30.78 603609 禾丰牧业 2020-01-07 饲料 辽宁 12.58 000401 冀东水泥 2020-01-07 水泥 河北 16.96 600469 风神股份 2020-01-08 汽车配件 河南 5.61 002598 山东章鼓 2020-01-08 机械基件 山东 6.94 300258 精锻科技 2020-01-08 汽车配件 江苏 11.91 002595 豪迈科技 2020-01-08 专用机械 山东 19.55 002520 日发精机 2020-01-08 机床制造 浙江 7.49 300117 嘉寓股份 2020-01-08 装修装饰 北京 4.1 002455 百川股份 2020-01-08 化工原料 江苏 6.19 600655 豫园股份 2020-01-08 百货 上海 8.3 600326 西藏天路 2020-01-08 水泥 西藏 7.44 300580 贝斯特 2020-01-08 汽车配件 江苏 16.77 600765 中航重机 2020-01-08 机械基件 贵州 10.5 000976 华铁股份 2020-01-08 运输设备 广东 5.61 002738 中矿资源 2020-01-08 小金属 北京 16.52 002224 三 力 士 2020-01-08 橡胶 浙江 6.27 002335 科华恒盛 2020-01-09 电气设备 福建 19.0 600104 上汽集团 2020-01-09 汽车整车 上海 24.95 300619 金银河 2020-01-09 专用机械 广东 24.51 002882 金龙羽 2020-01-09 电气设备 深圳 11.2 300517 海波重科 2020-01-09 建筑工程 湖北 15.91 600886 国投电力 2020-01-09 水力发电 北京 8.97 000099 中信海直 2020-01-09 空运 深圳 7.62 601579 会稽山 2020-01-09 红黄酒 浙江 8.83 002202 金风科技 2020-01-09 电气设备 新疆 12.8 600827 百联股份 2020-01-09 超市连锁 上海 9.0 300690 双一科技 2020-01-09 电气设备 山东 26.07 601828 美凯龙 2020-01-09 其他商业 上海 11.42 603199 九华旅游 2020-01-09 旅游景点 安徽 24.22 601021 春秋航空 2020-01-09 空运 上海 44.32 002444 巨星科技 2020-01-09 轻工机械 浙江 11.22 002026 山东威达 2020-01-09 机械基件 山东 5.81 601000 唐山港 2020-01-09 港口 河北 2.62 600919 江苏银行 2020-01-09 银行 江苏 7.16 600098 广州发展 2020-01-09 火力发电 广东 6.6 601169 北京银行 2020-01-09 银行 北京 5.67 600023 浙能电力 2020-01-09 火力发电 浙江 3.95 600336 澳柯玛 2020-01-09 家用电器 山东 4.57 600085 同仁堂 2020-01-09 中成药 北京 27.43 300396 迪瑞医疗 2020-01-09 医疗保健 吉林 17.55 000899 赣能股份 2020-01-09 火力发电 江西 4.91 600785 新华百货 2020-01-09 百货 宁夏 15.23 601010 文峰股份 2020-01-09 超市连锁 江苏 3.41 000582 北部湾港 2020-01-09 港口 广西 8.89 600035 楚天高速 2020-01-09 路桥 湖北 3.45 002839 张家港行 2020-01-09 银行 江苏 5.81 603139 康惠制药 2020-01-09 中成药 陕西 17.37 002462 嘉事堂 2020-01-09 医药商业 北京 16.59 300016 北陆药业 2020-01-09 中成药 北京 9.12 300599 雄塑科技 2020-01-09 塑料 广东 10.75 002873 新天药业 2020-01-09 中成药 贵州 17.19 300075 数字政通 2020-01-09 软件服务 北京 12.25 002331 皖通科技 2020-01-09 软件服务 安徽 10.29 603607 京华激光 2020-01-09 造纸 浙江 22.2 000543 皖能电力 2020-01-09 火力发电 安徽 4.67 601886 江河集团 2020-01-10 装修装饰 北京 7.98 600057 厦门象屿 2020-01-10 仓储物流 福建 4.41 600755 厦门国贸 2020-01-10 商贸代理 福建 7.7 600033 福建高速 2020-01-10 路桥 福建 3.16 002561 徐家汇 2020-01-10 百货 上海 8.34 600015 华夏银行 2020-01-10 银行 北京 7.66 601199 江南水务 2020-01-10 水务 江苏 3.85 603856 东宏股份 2020-01-09 塑料 山东 10.5 600835 上海机电 2020-01-13 运输设备 上海 17.12 002478 常宝股份 2020-01-13 钢加工 江苏 6.1 600697 欧亚集团 2020-01-13 百货 吉林 18.22 002394 联发股份 2020-01-13 纺织 江苏 9.62 601188 龙江交通 2020-01-13 路桥 黑龙江 3.06 000524 岭南控股 2020-01-13 酒店餐饮 广东 7.55 601336 新华保险 2020-01-13 保险 北京 51.25 601328 交通银行 2020-01-13 银行 上海 5.65 600908 无锡银行 2020-01-13 银行 江苏 5.52 600269 赣粤高速 2020-01-13 路桥 江西 4.16 600350 山东高速 2020-01-13 路桥 山东 4.87 603689 皖天然气 2020-01-13 供气供热 安徽 11.5 600533 栖霞建设 2020-01-13 区域地产 江苏 3.41 000402 金 融 街 2020-01-13 全国地产 北京 7.98 601607 上海医药 2020-01-13 医药商业 上海 18.53 601005 重庆钢铁 2020-01-13 普钢 重庆 1.84 600021 上海电力 2020-01-13 火力发电 上海 8.11 601088 中国神华 2020-01-13 煤炭开采 北京 18.19 601677 明泰铝业 2020-01-13 铝 河南 11.48 000718 苏宁环球 2020-01-13 区域地产 吉林 3.78 002015 协鑫能科 2020-01-13 新型电力 江苏 6.22 000987 越秀金控 2020-01-14 多元金融 广东 9.99 000617 中油资本 2020-01-14 多元金融 新疆 12.18 000967 盈峰环境 2020-01-14 环境保护 浙江 6.6 002011 盾安环境 2020-01-14 工程机械 浙江 5.17 000828 东莞控股 2020-01-14 路桥 广东 8.4 601390 中国中铁 2020-01-14 建筑工程 北京 5.96 601699 潞安环能 2020-01-14 煤炭开采 山西 7.2 600475 华光股份 2020-01-14 专用机械 江苏 10.27 600168 武汉控股 2020-01-14 水务 湖北 6.9 000726 鲁 泰A 2020-01-14 纺织 山东 9.26 002443 金洲管道 2020-01-14 钢加工 浙江 6.84 000703 恒逸石化 2020-01-15 化纤 广西 14.22 600790 轻纺城 2020-01-16 商品城 浙江 3.62 002101 广东鸿图 2020-01-16 汽车配件 广东 8.2 603937 丽岛新材 2020-01-13 铝 江苏 11.33 000960 锡业股份 2020-01-13 小金属 云南 10.56 000869 张 裕A 2020-01-13 红黄酒 山东 29.28 300218 安利股份 2020-01-13 塑料 安徽 8.1 601518 吉林高速 2020-01-13 路桥 吉林 2.7 600639 浦东金桥 2020-01-13 园区开发 上海 14.13 002574 明牌珠宝 2020-01-14 服饰 浙江 5.26 002448 中原内配 2020-01-14 汽车配件 河南 6.02 002743 富煌钢构 2020-01-14 钢加工 安徽 6.53 300148 天舟文化 2020-01-16 出版业 湖南 4.47 000541 佛山照明 2020-01-17 家用电器 广东 5.09 002102 ST冠福 2020-01-17 化学制药 福建 2.2 600865 百大集团 2020-01-20 百货 浙江 6.72 600056 中国医药 2020-01-20 医药商业 北京 13.35 600979 广安爱众 2020-01-20 水力发电 四川 4.18 002392 北京利尔 2020-01-20 其他建材 北京 3.89 000950 重药控股 2020-01-21 医药商业 重庆 6.23 600587 新华医疗 2020-01-21 医疗保健 山东 15.99 600603 广汇物流 2020-01-21 仓储物流 四川 5.4 603955 大千生态 2020-01-22 环境保护 江苏 16.28 601369 陕鼓动力 2020-01-22 机械基件 陕西 6.65 600153 建发股份 2020-01-22 商贸代理 福建 8.87 603161 科华控股 2020-01-22 汽车配件 江苏 13.71 600037 歌华有线 2020-01-22 影视音像 北京 9.59 002144 宏达高科 2020-01-22 纺织 浙江 10.18 002612 朗姿股份 2020-01-22 服饰 北京 9.04 000153 丰原药业 2020-01-23 化学制药 安徽 6.87 600328 兰太实业 2020-02-04 化工原料 内蒙 8.47 002589 瑞康医药 2020-02-05 医药商业 山东 7.72 600863 内蒙华电 2020-02-05 火力发电 内蒙 2.7 000919 金陵药业 2020-02-05 化学制药 江苏 7.8 000411 英特集团 2020-02-05 医药商业 浙江 12.37 600479 千金药业 2020-02-05 中成药 湖南 9.61 000623 吉林敖东 2020-02-05 化学制药 吉林 17.07 002217 合力泰 2020-02-06 元器件 福建 5.42 603599 广信股份 2020-02-06 农药化肥 安徽 14.7 600308 华泰股份 2020-02-06 造纸 山东 4.47 002734 利民股份 2020-02-06 农药化肥 江苏 13.38 601928 凤凰传媒 2020-02-06 出版业 江苏 7.54 603365 水星家纺 2020-02-06 纺织 上海 16.51 600589 广东榕泰 2020-02-07 塑料 广东 5.24 601200 上海环境 2020-02-07 环境保护 上海 12.31 600510 黑牡丹 2020-02-07 全国地产 江苏 6.77 002425 凯撒文化 2020-02-07 互联网 广东 6.1 600873 梅花生物 2020-02-05 食品 西藏 4.29 002672 东江环保 2020-02-07 环境保护 深圳 10.24 002083 孚日股份 2020-02-10 纺织 山东 6.42 002154 报 喜 鸟 2020-02-10 服饰 浙江 3.12 601952 苏垦农发 2020-02-10 种植业 江苏 7.13 000517 荣安地产 2020-02-11 区域地产 浙江 2.65 000591 太阳能 2020-02-12 新型电力 重庆 3.69 600704 物产中大 2020-02-14 商贸代理 浙江 5.54 600727 鲁北化工 2020-02-14 农药化肥 山东 7.61 000553 安道麦A 2020-02-14 农药化肥 湖北 10.09 002498 汉缆股份 2020-02-11 电气设备 山东 3.01 600586 金晶科技 2020-02-14 玻璃 山东 2.99 600811 东方集团 2020-02-17 综合类 黑龙江 3.41 600837 海通证券 2020-02-17 证券 上海 14.8 002736 国信证券 2020-02-17 证券 深圳 12.09 002381 双箭股份 2020-02-17 橡胶 浙江 8.13 600284 浦东建设 2020-02-17 建筑工程 上海 6.34 002560 通达股份 2020-02-18 电气设备 河南 5.64 002403 爱仕达 2020-02-18 家用电器 浙江 8.65 603556 海兴电力 2020-02-18 电器仪表 浙江 16.46 300233 金城医药 2020-02-18 化学制药 山东 20.06 603928 兴业股份 2020-02-19 化工原料 江苏 11.62 600522 中天科技 2020-02-19 通信设备 江苏 8.27 002423 中粮资本 2020-02-19 多元金融 河南 9.61 603968 醋化股份 2020-02-19 化工原料 江苏 14.72 603639 海利尔 2020-02-14 农药化肥 山东 26.65 600329 中新药业 2020-02-17 中成药 天津 13.7 601216 君正集团 2020-02-19 化工原料 内蒙 2.99 000729 燕京啤酒 2020-02-20 啤酒 北京 6.29 601988 中国银行 2020-02-20 银行 北京 3.63 000415 渤海租赁 2020-02-20 多元金融 新疆 3.58 000166 申万宏源 2020-02-20 证券 新疆 4.94 600814 杭州解百 2020-02-20 百货 浙江 5.05 603298 杭叉集团 2020-02-20 专用机械 浙江 13.27 601238 广汽集团 2020-02-21 汽车整车 广东 11.7 000598 兴蓉环境 2020-02-21 水务 四川 4.65 600582 天地科技 2020-02-21 工程机械 北京 3.1 601016 节能风电 2020-02-21 新型电力 北京 2.36 603020 爱普股份 2020-02-21 食品 上海 8.13 000913 钱江摩托 2020-02-21 摩托车 浙江 11.41 002302 西部建设 2020-02-24 水泥 新疆 11.18 601633 长城汽车 2020-02-25 汽车整车 河北 9.56 600162 香江控股 2020-02-26 全国地产 深圳 2.27 601618 中国中冶 2020-02-26 建筑工程 北京 2.73 000498 山东路桥 2020-02-26 建筑工程 山东 4.7 600068 葛洲坝 2020-02-26 建筑工程 湖北 6.53 601669 中国电建 2020-02-26 建筑工程 北京 4.25 000065 北方国际 2020-02-26 建筑工程 北京 8.24 600502 安徽建工 2020-02-27 建筑工程 安徽 4.04 002526 山东矿机 2020-02-27 工程机械 山东 2.29 600724 宁波富达 2020-02-27 区域地产 浙江 3.61 002457 青龙管业 2020-02-27 塑料 宁夏 7.99 002852 道道全 2020-02-27 食品 湖南 13.44 000528 柳 工 2020-02-27 工程机械 广西 6.66 002034 旺能环境 2020-02-27 环境保护 浙江 14.98 002521 齐峰新材 2020-02-24 造纸 山东 5.97 002611 东方精工 2020-02-28 轻工机械 广东 4.63 002322 理工环科 2020-03-02 软件服务 浙江 11.63 601666 平煤股份 2020-03-02 煤炭开采 河南 4.06 002061 浙江交科 2020-03-02 建筑工程 浙江 5.6 002097 山河智能 2020-03-02 工程机械 湖南 6.04 601186 中国铁建 2020-03-02 建筑工程 北京 10.45 600970 中材国际 2020-03-02 建筑工程 江苏 6.67 600742 一汽富维 2020-03-02 汽车配件 吉林 12.6 002809 红墙股份 2020-03-02 化工原料 广东 17.32 600528 中铁工业 2020-03-02 运输设备 北京 10.71 600170 上海建工 2020-03-02 建筑工程 上海 3.6 600820 隧道股份 2020-03-02 建筑工程 上海 6.01 600089 特变电工 2020-03-02 电气设备 新疆 6.65 600106 重庆路桥 2020-03-02 路桥 重庆 2.94 000755 山西路桥 2020-03-02 公路 山西 3.9 600688 上海石化 2020-03-02 石油加工 上海 4.16 601019 山东出版 2020-03-02 出版业 山东 6.81 600335 国机汽车 2020-03-02 汽车配件 天津 5.72 603766 隆鑫通用 2020-03-03 摩托车 重庆 3.74 603017 中衡设计 2020-03-03 建筑工程 江苏 10.83 600581 八一钢铁 2020-03-03 普钢 新疆 3.38 002010 传化智联 2020-03-04 仓储物流 浙江 6.96 601611 中国核建 2020-03-04 建筑工程 上海 7.07 000042 中洲控股 2020-03-04 全国地产 深圳 10.3 002440 闰土股份 2020-03-04 染料涂料 浙江 11.82 601996 丰林集团 2020-03-04 家居用品 广西 2.81 000882 华联股份 2020-03-04 其他商业 北京 2.23 600997 开滦股份 2020-03-04 煤炭开采 河北 5.25 002133 广宇集团 2020-03-04 全国地产 浙江 3.38 600097 开创国际 2020-03-04 渔业 上海 9.6 000631 顺发恒业 2020-03-04 区域地产 吉林 2.84 601158 重庆水务 2020-03-04 水务 重庆 5.51 600657 信达地产 2020-03-04 全国地产 北京 3.95 600073 上海梅林 2020-03-04 食品 上海 8.45 600939 重庆建工 2020-03-04 建筑工程 重庆 4.66 002539 云图控股 2020-03-04 农药化肥 四川 4.7 600408 ST安泰 2020-03-04 焦炭加工 山西 2.29 002344 海宁皮城 2020-03-04 商品城 浙江 4.16 000537 广宇发展 2020-03-04 区域地产 天津 7.23 002375 亚厦股份 2020-03-04 装修装饰 浙江 5.57 600185 格力地产 2020-03-04 区域地产 广东 4.84 600578 京能电力 2020-03-05 火力发电 北京 3.09 000531 穗恒运A 2020-03-05 火力发电 广东 6.64 600705 中航资本 2020-03-05 多元金融 黑龙江 4.66 002948 青岛银行 2020-03-05 银行 山东 5.67 600743 华远地产 2020-03-05 区域地产 北京 2.49 000407 胜利股份 2020-03-05 供气供热 山东 3.45 603225 新凤鸣 2020-03-05 化纤 浙江 11.75 600012 皖通高速 2020-03-05 路桥 安徽 5.66 002053 云南能投 2020-03-05 食品 云南 7.36 600022 山东钢铁 2020-03-05 普钢 山东 1.39 600113 浙江东日 2020-03-06 区域地产 浙江 6.95 601339 百隆东方 2020-03-06 纺织 浙江 3.97 600982 宁波热电 2020-03-06 供气供热 浙江 2.93 600569 安阳钢铁 2020-03-06 普钢 河南 2.43 601800 中国交建 2020-03-06 建筑工程 北京 9.49 002438 江苏神通 2020-03-04 机械基件 江苏 8.22 002462 嘉事堂 2020-03-05 医药商业 北京 16.1 000582 北部湾港 2020-03-05 港口 广西 8.62 002839 张家港行 2020-03-05 银行 江苏 6.09 603969 银龙股份 2020-03-06 其他建材 天津 4.15 600798 宁波海运 2020-03-09 水运 浙江 3.46 600755 厦门国贸 2020-03-05 商贸代理 福建 7.07 600035 楚天高速 2020-03-10 路桥 湖北 3.48 600104 上汽集团 2020-03-10 汽车整车 上海 23.3 002244 滨江集团 2020-03-10 区域地产 浙江 4.62 002620 瑞和股份 2020-03-10 装修装饰 深圳 6.04 000573 粤宏远A 2020-03-10 区域地产 广东 3.0 002811 亚泰国际 2020-03-13 装修装饰 深圳 15.35 002807 江阴银行 2020-03-13 银行 江苏 4.54 600995 文山电力 2020-03-13 水力发电 云南 7.73 601390 中国中铁 2020-03-10 建筑工程 北京 5.79 002357 富临运业 2020-03-16 公路 四川 5.96 300154 瑞凌股份 2020-03-17 元器件 深圳 5.87 002687 乔治白 2020-03-17 服饰 浙江 5.87 600051 宁波联合 2020-03-17 综合类 浙江 6.15 000419 通程控股 2020-03-19 百货 湖南 4.56 600693 东百集团 2020-03-19 百货 福建 5.35 601607 上海医药 2020-03-20 医药商业 上海 19.07 002448 中原内配 2020-03-20 汽车配件 河南 5.43 600963 岳阳林纸 2020-03-20 造纸 湖南 4.4 002283 天润曲轴 2020-03-20 汽车配件 山东 3.68 002033 丽江旅游 2020-03-23 旅游景点 云南 6.43 002790 瑞尔特 2020-03-20 家居用品 福建 6.66 002377 国创高新 2020-03-24 房产服务 湖北 4.19 600874 创业环保 2020-03-24 环境保护 天津 7.4 002360 同德化工 2020-03-24 化工原料 山西 5.33 601010 文峰股份 2020-03-24 超市连锁 江苏 3.2 603897 长城科技 2020-03-24 电气设备 浙江 18.92 002102 ST冠福 2020-03-24 化学制药 福建 2.19 000581 威孚高科 2020-03-25 汽车配件 江苏 19.58 600665 天地源 2020-03-25 全国地产 陕西 3.56 600969 郴电国际 2020-03-25 水力发电 湖南 6.49 600533 栖霞建设 2020-03-25 区域地产 江苏 3.29 600865 百大集团 2020-03-25 百货 浙江 6.3 600778 友好集团 2020-03-25 百货 新疆 5.29 001896 豫能控股 2020-03-25 火力发电 河南 3.54 002574 明牌珠宝 2020-03-26 服饰 浙江 5.14 600337 美克家居 2020-03-27 家居用品 新疆 4.5 600252 中恒集团 2020-03-27 中成药 广西 3.31 002060 粤 水 电 2020-03-27 建筑工程 广东 3.12 000530 冰山冷热 2020-03-25 机械基件 辽宁 3.92 603038 华立股份 2020-03-30 装修装饰 广东 14.37 002538 司尔特 2020-03-31 农药化肥 安徽 5.0 603609 禾丰牧业 2020-03-26 饲料 辽宁 11.63 603001 奥康国际 2020-03-27 服饰 浙江 8.91 002109 兴化股份 2020-03-30 化工原料 陕西 3.46 000417 合肥百货 2020-03-31 百货 安徽 4.99 600491 龙元建设 2020-04-02 建筑工程 浙江 7.65 600873 梅花生物 2020-04-02 食品 西藏 4.47 000850 华茂股份 2020-04-07 纺织 安徽 4.27 600577 精达股份 2020-04-07 电气设备 安徽 2.85 002327 富安娜 2020-04-08 纺织 深圳 7.0 601200 上海环境 2020-04-08 环境保护 上海 12.0 601199 江南水务 2020-04-10 水务 江苏 3.97 600785 新华百货 2020-04-10 百货 宁夏 15.4 002004 华邦健康 2020-04-10 化学制药 重庆 5.11 000488 晨鸣纸业 2020-04-10 造纸 山东 5.25 000877 天山股份 2020-04-10 水泥 新疆 11.61 600109 国金证券 2020-04-10 证券 四川 9.56 600159 大龙地产 2020-04-08 区域地产 北京 2.6 603878 武进不锈 2020-04-10 钢加工 江苏 11.2 603599 广信股份 2020-04-13 农药化肥 安徽 16.37 603937 丽岛新材 2020-04-14 铝 江苏 11.25 603858 步长制药 2020-04-15 中成药 山东 21.44 000090 天健集团 2020-04-15 建筑工程 深圳 5.41 000757 浩物股份 2020-04-14 汽车配件 四川 4.84 002546 新联电子 2020-04-16 电气设备 江苏 4.31 002208 合肥城建 2020-04-16 区域地产 安徽 6.9 603458 勘设股份 2020-04-17 建筑工程 贵州 20.04 603928 兴业股份 2020-04-20 化工原料 江苏 12.42 300500 启迪设计 2020-04-20 建筑工程 江苏 15.36 600894 广日股份 2020-04-20 运输设备 广东 7.77 600751 海航科技 2020-04-20 水运 天津 2.98 603067 振华股份 2020-04-20 化工原料 湖北 6.16 002293 罗莱生活 2020-04-20 纺织 江苏 9.09 603020 爱普股份 2020-04-17 食品 上海 8.84 603585 苏利股份 2020-04-21 化工原料 江苏 20.95 600780 通宝能源 2020-04-22 火力发电 山西 3.63 000011 深物业A 2020-04-22 区域地产 深圳 9.28 300660 江苏雷利 2020-04-22 电气设备 江苏 16.66 000731 四川美丰 2020-04-23 农药化肥 四川 5.23 300443 金雷股份 2020-04-23 专用机械 山东 15.36 600248 延长化建 2020-04-23 建筑工程 陕西 4.35 600048 保利地产 2020-04-23 全国地产 广东 15.89 603979 金诚信 2020-04-24 建筑工程 北京 9.29 600326 西藏天路 2020-04-24 水泥 西藏 7.19 300732 设研院 2020-04-24 建筑工程 河南 17.56 603858 步长制药 2020-04-27 中成药 山东 21.27 002788 鹭燕医药 2020-04-27 医药商业 福建 8.52 000011 深物业A 2020-04-27 区域地产 深圳 9.03 002406 远东传动 2020-04-27 汽车配件 河南 5.64 001696 宗申动力 2020-04-27 摩托车 重庆 5.72 600027 华电国际 2020-04-27 火力发电 山东 3.6 002392 北京利尔 2020-04-27 其他建材 北京 3.92 600873 梅花生物 2020-04-27 食品 西藏 4.55 002327 富安娜 2020-04-27 纺织 深圳 7.02 000528 柳 工 2020-04-27 工程机械 广西 6.87 600329 中新药业 2020-04-27 中成药 天津 14.25 600048 保利地产 2020-04-27 全国地产 广东 15.91 600639 浦东金桥 2020-04-28 园区开发 上海 13.19 600077 宋都股份 2020-04-28 全国地产 浙江 2.96 000157 中联重科 2020-04-28 工程机械 湖南 6.19 300660 江苏雷利 2020-04-28 电气设备 江苏 15.26 600153 建发股份 2020-04-28 商贸代理 福建 8.03 002128 露天煤业 2020-04-28 煤炭开采 内蒙 7.61 601216 君正集团 2020-04-28 化工原料 内蒙 2.75 600820 隧道股份 2020-04-28 建筑工程 上海 5.66 600008 首创股份 2020-04-28 环境保护 北京 3.23 603298 杭叉集团 2020-04-28 专用机械 浙江 12.86 600999 招商证券 2020-04-28 证券 深圳 18.2 000718 苏宁环球 2020-04-28 区域地产 吉林 3.22 601369 陕鼓动力 2020-04-28 机械基件 陕西 5.95 600578 京能电力 2020-04-28 火力发电 北京 2.86 600125 铁龙物流 2020-04-28 铁路 辽宁 5.14 000006 深振业A 2020-04-28 区域地产 深圳 4.89 002039 黔源电力 2020-04-28 水力发电 贵州 13.99 603535 嘉诚国际 2020-04-28 仓储物流 广东 16.51 603277 银都股份 2020-04-28 专用机械 浙江 9.78 600731 湖南海利 2020-04-28 农药化肥 湖南 6.84 600170 上海建工 2020-04-28 建筑工程 上海 3.3 002443 金洲管道 2020-04-28 钢加工 浙江 6.09 600729 重庆百货 2020-04-28 百货 重庆 27.24 601727 上海电气 2020-04-28 电气设备 上海 4.84 600387 海越能源 2020-04-28 石油贸易 浙江 7.56 000869 张 裕A 2020-04-28 红黄酒 山东 25.43 601107 四川成渝 2020-04-28 路桥 四川 3.64 600828 XD茂业商 2020-04-28 百货 四川 4.16 603693 江苏新能 2020-04-29 新型电力 江苏 10.18 000767 漳泽电力 2020-04-29 火力发电 山西 2.24 600269 赣粤高速 2020-04-29 路桥 江西 3.64 000989 九 芝 堂 2020-04-29 中成药 湖南 9.28 000036 华联控股 2020-04-30 全国地产 深圳 3.97 600064 南京高科 2020-04-30 园区开发 江苏 8.88 000965 天保基建 2020-04-30 区域地产 天津 3.26 000828 东莞控股 2020-04-30 路桥 广东 7.31 002142 宁波银行 2020-04-30 银行 浙江 26.05 601001 大同煤业 2020-05-06 煤炭开采 山西 3.81 600901 江苏租赁 2020-05-06 多元金融 江苏 5.37 002381 双箭股份 2020-05-07 橡胶 浙江 8.06 600308 华泰股份 2020-05-08 造纸 山东 4.53 600252 中恒集团 2020-05-08 中成药 广西 3.42 000932 华菱钢铁 2020-05-11 普钢 湖南 4.23 600846 同济科技 2020-05-11 建筑工程 上海 8.78 600790 轻纺城 2020-05-11 商品城 浙江 3.18 600594 益佰制药 2020-05-12 中成药 贵州 5.65 002573 清新环境 2020-05-12 环境保护 北京 6.09 603817 海峡环保 2020-05-13 环境保护 福建 6.16 601336 新华保险 2020-05-13 保险 北京 45.54 600629 华建集团 2020-05-18 建筑工程 上海 8.13 603599 广信股份 2020-05-18 农药化肥 安徽 16.32 002053 云南能投 2020-05-18 食品 云南 6.9 000612 焦作万方 2020-05-19 铝 河南 3.96 002531 天顺风能 2020-05-19 电气设备 江苏 6.09 000753 漳州发展 2020-05-19 汽车服务 福建 2.78 603766 隆鑫通用 2020-05-19 摩托车 重庆 3.61 000417 合肥百货 2020-05-19 百货 安徽 4.64 603303 得邦照明 2020-05-20 家用电器 浙江 9.8 300214 日科化学 2020-05-21 化工原料 山东 8.41 600163 中闽能源 2020-05-22 新型电力 福建 3.39 603917 合力科技 2020-05-25 汽车配件 浙江 10.14 002267 陕天然气 2020-05-25 供气供热 陕西 6.39 600426 华鲁恒升 2020-05-25 农药化肥 山东 17.78 601003 柳钢股份 2020-05-25 普钢 广西 5.09 600023 浙能电力 2020-05-25 火力发电 浙江 3.53 600985 淮北矿业 2020-05-25 煤炭开采 安徽 8.59 000552 靖远煤电 2020-05-26 煤炭开采 甘肃 2.36 600551 时代出版 2020-05-27 出版业 安徽 7.96 601088 中国神华 2020-05-27 煤炭开采 北京 16.45 600926 杭州银行 2020-05-27 银行 浙江 8.9 603113 金能科技 2020-05-27 化工原料 山东 10.11 600888 新疆众和 2020-05-28 铝 新疆 4.84 600348 阳泉煤业 2020-05-28 煤炭开采 山西 4.67 601818 光大银行 2020-05-28 银行 北京 3.81 000906 浙商中拓 2020-05-28 批发业 浙江 5.52 000959 首钢股份 2020-05-28 普钢 北京 3.0 601009 南京银行 2020-05-28 银行 江苏 7.92 600971 恒源煤电 2020-05-28 煤炭开采 安徽 4.94 000055 方大集团 2020-05-28 其他建材 深圳 4.28 601288 农业银行 2020-05-28 银行 北京 3.43 600642 申能股份 2020-05-28 火力发电 上海 5.36 600016 民生银行 2020-05-28 银行 北京 5.76 002441 众业达 2020-05-28 批发业 广东 8.54 600036 招商银行 2020-05-28 银行 深圳 34.22 000722 湖南发展 2020-05-28 水力发电 湖南 6.01 600382 广东明珠 2020-05-28 商贸代理 广东 6.27 600291 西水股份 2020-05-28 保险 内蒙 8.07 601388 怡球资源 2020-05-28 铝 江苏 1.8 600750 江中药业 2020-05-29 中成药 江西 12.74 600415 小商品城 2020-06-01 商品城 浙江 3.8 002344 海宁皮城 2020-06-01 商品城 浙江 4.08 002818 富森美 2020-06-01 其他商业 四川 12.05 600644 乐山电力 2020-06-01 水力发电 四川 5.11 601200 上海环境 2020-06-01 环境保护 上海 12.27 600886 国投电力 2020-06-02 水力发电 北京 7.75 600665 天地源 2020-06-04 全国地产 陕西 3.54 603878 武进不锈 2020-06-04 钢加工 江苏 11.4 600657 信达地产 2020-06-04 全国地产 北京 3.94 601018 宁波港 2020-06-05 港口 浙江 3.45 000488 晨鸣纸业 2020-06-05 造纸 山东 4.91 000600 建投能源 2020-06-05 火力发电 河北 4.92 600633 浙数文化 2020-06-05 互联网 浙江 9.5 603968 醋化股份 2020-06-05 化工原料 江苏 14.37 600325 华发股份 2020-06-05 区域地产 广东 6.88 000923 河钢资源 2020-06-08 普钢 河北 13.95 000028 国药一致 2020-06-08 医药商业 深圳 43.62 601801 皖新传媒 2020-06-08 出版业 安徽 5.35 002448 中原内配 2020-06-09 汽车配件 河南 5.47 600229 城市传媒 2020-06-10 出版业 山东 8.05 603368 柳药股份 2020-06-10 医药商业 广西 33.18 600535 天士力 2020-06-10 中成药 天津 14.86 600674 川投能源 2020-06-10 水力发电 四川 9.14 002444 巨星科技 2020-06-10 轻工机械 浙江 11.44 300610 晨化股份 2020-06-09 化工原料 江苏 11.84 601628 中国人寿 2020-06-10 保险 北京 28.92 603889 新澳股份 2020-06-11 纺织 浙江 5.52 601398 工商银行 2020-06-11 银行 北京 5.27 002543 万和电气 2020-06-11 家用电器 广东 8.66 002408 齐翔腾达 2020-06-12 化工原料 山东 6.37 600875 东方电气 2020-06-12 电气设备 四川 9.27 600757 长江传媒 2020-06-12 出版业 湖北 5.4 002526 山东矿机 2020-06-12 工程机械 山东 2.34 601838 成都银行 2020-06-12 银行 四川 7.89 000719 中原传媒 2020-06-12 出版业 河南 6.91 000537 广宇发展 2020-06-12 区域地产 天津 7.4 002026 山东威达 2020-06-12 机械基件 山东 4.99 600000 浦发银行 2020-06-12 银行 上海 10.55 601229 上海银行 2020-06-12 银行 上海 8.28 300423 鲁亿通 2020-06-12 电气设备 山东 12.86 002438 江苏神通 2020-06-12 机械基件 江苏 7.62 601318 中国平安 2020-06-12 保险 深圳 74.15 600352 浙江龙盛 2020-06-12 染料涂料 浙江 12.68 000543 皖能电力 2020-06-12 火力发电 安徽 3.95 601688 华泰证券 2020-06-12 证券 江苏 17.82 600755 厦门国贸 2020-06-15 商贸代理 福建 6.64 601163 三角轮胎 2020-06-15 汽车配件 山东 13.22 002394 联发股份 2020-06-15 纺织 江苏 8.99 600173 卧龙地产 2020-06-15 全国地产 浙江 4.58 300196 长海股份 2020-06-15 玻璃 江苏 10.58 600282 南钢股份 2020-06-16 普钢 江苏 3.25 002078 太阳纸业 2020-06-16 造纸 山东 9.48 600997 开滦股份 2020-06-16 煤炭开采 河北 4.75 600808 马钢股份 2020-06-16 普钢 安徽 2.7 600782 新钢股份 2020-06-16 普钢 江西 4.22 600643 爱建集团 2020-06-16 多元金融 上海 7.95 002146 荣盛发展 2020-06-16 全国地产 河北 7.9 600622 光大嘉宝 2020-06-16 区域地产 上海 3.94 600287 江苏舜天 2020-06-16 商贸代理 江苏 5.56 601128 常熟银行 2020-06-16 银行 江苏 7.33 000685 中山公用 2020-06-16 水务 广东 7.69 600751 海航科技 2020-06-16 水运 天津 3.08 000926 福星股份 2020-06-16 区域地产 湖北 5.27 601169 北京银行 2020-06-16 银行 北京 4.89 603926 铁流股份 2020-06-16 汽车配件 浙江 11.5 601006 大秦铁路 2020-06-16 铁路 山西 6.99 000623 吉林敖东 2020-06-16 化学制药 吉林 15.61 000783 长江证券 2020-06-16 证券 湖北 6.6 600420 现代制药 2020-06-17 化学制药 上海 10.01 600056 中国医药 2020-06-17 医药商业 北京 14.67 000717 韶钢松山 2020-06-17 普钢 广东 4.05 000411 英特集团 2020-06-17 医药商业 浙江 11.45 000983 西山煤电 2020-06-17 煤炭开采 山西 4.87 600508 上海能源 2020-06-17 煤炭开采 上海 8.25 000807 云铝股份 2020-06-17 铝 云南 4.32 601577 长沙银行 2020-06-17 银行 湖南 7.93 000937 冀中能源 2020-06-18 煤炭开采 河北 3.12 000778 新兴铸管 2020-06-18 钢加工 河北 3.5 600219 南山铝业 2020-06-18 铝 山东 2.1 600395 盘江股份 2020-06-18 煤炭开采 贵州 5.45 000961 中南建设 2020-06-18 建筑工程 江苏 8.58 002736 国信证券 2020-06-19 证券 深圳 11.22 601228 广州港 2020-06-19 港口 广东 3.2 002926 华西证券 2020-06-19 证券 四川 10.89 000166 申万宏源 2020-06-19 证券 新疆 4.6 000686 东北证券 2020-06-19 证券 吉林 8.45 000776 广发证券 2020-06-19 证券 广东 13.91 600958 东方证券 2020-06-19 证券 上海 9.38 601233 桐昆股份 2020-06-19 化纤 浙江 12.83 002067 景兴纸业 2020-06-19 造纸 浙江 3.11 600995 文山电力 2020-06-19 水力发电 云南 7.8 000591 太阳能 2020-06-19 新型电力 重庆 3.32 600533 栖霞建设 2020-06-19 区域地产 江苏 3.56 600061 国投资本 2020-06-23 证券 上海 13.17 600837 海通证券 2020-06-24 证券 上海 12.87 000563 陕国投A 2020-06-24 多元金融 陕西 3.64 002244 滨江集团 2020-06-24 区域地产 浙江 4.29 002839 张家港行 2020-06-24 银行 江苏 5.79 601222 林洋能源 2020-06-29 电器仪表 江苏 5.3 000875 吉电股份 2020-06-29 火力发电 吉林 3.73 000671 阳 光 城 2020-07-01 区域地产 福建 6.97 600048 保利地产 2020-07-01 全国地产 广东 15.9 000069 华侨城A 2020-07-01 旅游景点 深圳 6.5 600422 昆药集团 2020-07-01 中成药 云南 10.03 601166 兴业银行 2020-07-01 银行 福建 16.15 000750 国海证券 2020-07-01 证券 广西 4.42 601328 交通银行 2020-07-01 银行 上海 5.16 601319 中国人保 2020-07-02 保险 北京 7.35 002081 金 螳 螂 2020-07-02 装修装饰 江苏 8.25 601555 东吴证券 2020-07-02 证券 江苏 9.03 601618 中国中冶 2020-07-02 建筑工程 北京 2.63 601225 陕西煤业 2020-07-02 煤炭开采 陕西 7.74 600908 无锡银行 2020-07-02 银行 江苏 5.16 601339 百隆东方 2020-07-02 纺织 浙江 3.62 600705 中航资本 2020-07-02 多元金融 黑龙江 4.23 600864 哈投股份 2020-07-02 证券 黑龙江 6.62 601000 唐山港 2020-07-02 港口 河北 2.28 600713 南京医药 2020-07-02 医药商业 江苏 4.4 603323 苏农银行 2020-06-30 银行 江苏 4.44 600017 日照港 2020-06-30 港口 山东 2.49 603928 兴业股份 2020-06-30 化工原料 江苏 10.82 601939 建设银行 2020-07-01 银行 北京 6.36 603558 健盛集团 2020-07-01 纺织 浙江 9.33 601998 中信银行 2020-07-01 银行 北京 5.31 601988 中国银行 2020-07-01 银行 北京 3.5 603357 设计总院 2020-07-02 建筑工程 安徽 10.24 601666 平煤股份 2020-07-03 煤炭开采 河南 4.26 601699 潞安环能 2020-07-03 煤炭开采 山西 6.45 600284 浦东建设 2020-07-03 建筑工程 上海 6.67 600390 五矿资本 2020-07-03 多元金融 湖南 7.89 601898 中煤能源 2020-07-03 煤炭开采 北京 4.13 002807 江阴银行 2020-07-03 银行 江苏 4.2 600919 江苏银行 2020-07-03 银行 江苏 6.06 601607 上海医药 2020-07-03 医药商业 上海 19.01 601866 中远海发 2020-07-06 水运 上海 2.16 601058 赛轮轮胎 2020-07-06 汽车配件 山东 4.04 002948 青岛银行 2020-07-06 银行 山东 5.78 601326 秦港股份 2020-07-06 港口 河北 2.85 600928 西安银行 2020-07-06 银行 陕西 6.5 002088 鲁阳节能 2020-07-06 矿物制品 山东 9.74 002936 郑州银行 2020-07-06 银行 河南 4.02 601985 中国核电 2020-07-06 新型电力 北京 4.53 002608 江苏国信 2020-07-06 火力发电 江苏 7.07 600704 物产中大 2020-07-06 商贸代理 浙江 4.76 600295 鄂尔多斯 2020-07-06 小金属 内蒙 7.79 600015 华夏银行 2020-07-06 银行 北京 7.14 600019 宝钢股份 2020-07-06 普钢 上海 5.15 601800 中国交建 2020-07-06 建筑工程 北京 8.75 601298 青岛港 2020-07-06 港口 山东 6.28 601668 中国建筑 2020-07-06 建筑工程 北京 5.48 000898 鞍钢股份 2020-07-06 普钢 辽宁 2.85 601669 中国电建 2020-07-06 建筑工程 北京 4.15 601997 贵阳银行 2020-07-06 银行 贵州 8.45 600177 雅戈尔 2020-07-06 服饰 浙江 6.77 601390 中国中铁 2020-07-06 建筑工程 北京 5.75 000761 本钢板材 2020-07-06 普钢 辽宁 3.51 000598 兴蓉环境 2020-07-06 水务 四川 4.94 600874 创业环保 2020-07-06 环境保护 天津 7.14 600970 中材国际 2020-07-06 建筑工程 江苏 5.9 300067 安诺其 2020-07-06 染料涂料 上海 3.86 600567 山鹰纸业 2020-07-06 造纸 安徽 3.19 600987 航民股份 2020-07-06 纺织 浙江 5.72 002478 常宝股份 2020-07-06 钢加工 江苏 5.19 000899 赣能股份 2020-07-06 火力发电 江西 4.47 601117 中国化学 2020-07-06 建筑工程 北京 6.18 002206 海 利 得 2020-07-06 化纤 浙江 3.52 600466 蓝光发展 2020-07-06 区域地产 四川 6.08 002318 久立特材 2020-07-06 特种钢 浙江 7.92 603689 皖天然气 2020-07-06 供气供热 安徽 10.76 600007 中国国贸 2020-07-06 园区开发 北京 14.6 600528 中铁工业 2020-07-06 运输设备 北京 9.89 002016 世荣兆业 2020-07-06 区域地产 广东 7.37 000627 天茂集团 2020-07-07 保险 湖北 6.09 600252 中恒集团 2020-07-17 中成药 广西 3.49 600461 洪城水业 2020-07-20 水务 江西 7.12 600351 亚宝药业 2020-07-20 中成药 山西 5.3 000767 漳泽电力 2020-07-20 火力发电 山西 2.5 002889 东方嘉盛 2020-07-20 仓储物流 深圳 24.84 000631 顺发恒业 2020-07-21 区域地产 吉林 3.12 603567 珍宝岛 2020-07-21 中成药 黑龙江 13.16 600603 广汇物流 2020-07-22 仓储物流 四川 5.33 601088 中国神华 2020-07-20 煤炭开采 北京 16.26 601003 柳钢股份 2020-07-20 普钢 广西 5.24 600780 通宝能源 2020-07-23 火力发电 山西 3.52 600398 海澜之家 2020-07-23 服饰 江苏 6.37 000999 华润三九 2020-07-23 中成药 深圳 30.8 603585 苏利股份 2020-07-24 化工原料 江苏 18.66 300158 振东制药 2020-07-27 化学制药 山西 5.77 600068 葛洲坝 2020-07-28 建筑工程 湖北 6.52 300179 四方达 2020-07-28 矿物制品 河南 6.08 300194 福安药业 2020-07-29 化学制药 重庆 6.06 002462 嘉事堂 2020-07-29 医药商业 北京 14.9 601158 重庆水务 2020-07-29 水务 重庆 5.34 603359 东珠生态 2020-07-28 环境保护 江苏 18.21 601975 招商南油 2020-07-31 水运 江苏 2.67 600846 同济科技 2020-08-03 建筑工程 上海 8.92 601601 中国太保 2020-08-04 保险 上海 30.84 000001 平安银行 2020-08-04 银行 深圳 14.04 600963 岳阳林纸 2020-08-07 造纸 湖南 4.39 601098 中南传媒 2020-08-07 出版业 湖南 11.01 000922 佳电股份 2020-08-07 电气设备 黑龙江 7.49 601567 三星医疗 2020-08-10 电器仪表 浙江 7.53 002015 协鑫能科 2020-08-10 新型电力 江苏 6.01 002215 诺 普 信 2020-08-10 农药化肥 深圳 6.56 000726 鲁 泰A 2020-08-11 纺织 山东 7.88 002102 ST冠福 2020-08-12 化学制药 福建 1.92 600027 华电国际 2020-08-12 火力发电 山东 3.68 600729 重庆百货 2020-08-13 百货 重庆 31.75 600644 乐山电力 2020-08-14 水力发电 四川 5.68 601186 中国铁建 2020-08-17 建筑工程 北京 9.27 002327 富安娜 2020-08-18 纺织 深圳 7.52 002290 ST中科创 2020-08-18 家用电器 江苏 5.29 603900 莱绅通灵 2020-08-19 服饰 江苏 8.66 601992 金隅集团 2020-08-17 水泥 北京 3.3 601311 骆驼股份 2020-08-21 电气设备 湖北 9.06 002737 葵花药业 2020-08-24 中成药 黑龙江 14.95 600982 宁波热电 2020-08-27 供气供热 浙江 3.0 600743 华远地产 2020-08-27 区域地产 北京 2.23 600170 上海建工 2020-08-27 建筑工程 上海 3.37 600820 隧道股份 2020-08-28 建筑工程 上海 6.07 601566 九牧王 2020-08-31 服饰 福建 9.95 601166 兴业银行 2020-09-01 银行 福建 16.35 002911 佛燃能源 2020-09-01 供气供热 广东 16.41 600790 轻纺城 2020-09-01 商品城 浙江 3.41 300732 设研院 2020-09-02 建筑工程 河南 16.85 600113 浙江东日 2020-09-02 区域地产 浙江 6.98 600106 重庆路桥 2020-09-02 路桥 重庆 2.7 600565 迪马股份 2020-09-02 全国地产 重庆 3.12 600865 百大集团 2020-09-03 百货 浙江 7.2 002936 郑州银行 2020-09-01 银行 河南 3.85 002344 海宁皮城 2020-09-04 商品城 浙江 4.64 002543 万和电气 2020-09-08 家用电器 广东 8.65 603878 武进不锈 2020-09-16 钢加工 江苏 8.98 600094 大名城 2020-09-16 区域地产 上海 6.12 600742 一汽富维 2020-09-18 汽车配件 吉林 10.82 600266 城建发展 2020-09-21 区域地产 北京 5.98 600781 *ST辅仁 2020-09-22 中成药 河南 4.35 002757 南兴股份 2020-09-22 专用机械 广东 21.76 688009 中国通号 2020-09-23 运输设备 北京 6.48 603013 亚普股份 2020-09-25 汽车配件 江苏 16.59 600348 阳泉煤业 2020-09-29 煤炭开采 山西 4.94 000983 西山煤电 2020-09-29 煤炭开采 山西 4.45 601928 凤凰传媒 2020-09-29 出版业 江苏 7.33 600023 浙能电力 2020-09-29 火力发电 浙江 3.72 601555 东吴证券 2020-09-29 证券 江苏 10.77 600580 卧龙电驱 2020-10-09 电气设备 浙江 13.21 601619 嘉泽新能 2020-10-09 新型电力 宁夏 3.39 000552 靖远煤电 2020-10-09 煤炭开采 甘肃 2.7 000055 方大集团 2020-10-09 其他建材 深圳 4.97 600835 上海机电 2020-10-09 运输设备 上海 17.59 300066 三川智慧 2020-10-09 电器仪表 江西 5.62 000338 潍柴动力 2020-10-09 汽车配件 山东 15.79 000767 漳泽电力 2020-10-09 火力发电 山西 2.54 600335 国机汽车 2020-10-09 汽车配件 天津 5.42 600218 全柴动力 2020-10-09 农用机械 安徽 10.17 600104 上汽集团 2020-10-09 汽车整车 上海 19.8 002423 中粮资本 2020-10-09 多元金融 河南 10.31 600177 雅戈尔 2020-10-09 服饰 浙江 6.99 002593 日上集团 2020-10-12 汽车配件 福建 4.14 601233 桐昆股份 2020-10-12 化纤 浙江 15.65 300130 新国都 2020-10-12 IT设备 深圳 16.17 603657 春光科技 2020-10-12 塑料 浙江 19.93 002736 国信证券 2020-10-12 证券 深圳 14.76 601886 江河集团 2020-10-12 装修装饰 北京 6.3 601598 中国外运 2020-10-12 仓储物流 北京 4.03 002889 东方嘉盛 2020-10-12 仓储物流 深圳 27.4 000968 蓝焰控股 2020-10-12 煤炭开采 山西 8.52 600256 广汇能源 2020-10-12 石油开采 新疆 3.03 300303 聚飞光电 2020-10-12 半导体 深圳 6.89 000001 平安银行 2020-10-12 银行 深圳 15.9 601128 常熟银行 2020-10-12 银行 江苏 8.18 002267 陕天然气 2020-10-12 供气供热 陕西 6.8 002381 双箭股份 2020-10-12 橡胶 浙江 10.15 600036 招商银行 2020-10-12 银行 深圳 37.56 600141 兴发集团 2020-10-12 化工原料 湖北 10.66 300780 德恩精工 2020-10-12 机械基件 四川 19.29 601601 中国太保 2020-10-12 保险 上海 33.17 600133 东湖高新 2020-10-12 园区开发 湖北 6.12 603035 常熟汽饰 2020-10-12 汽车配件 江苏 14.18 002441 众业达 2020-10-12 批发业 广东 8.81 600308 华泰股份 2020-10-12 造纸 山东 5.24 600981 汇鸿集团 2020-10-12 商贸代理 江苏 3.58 000850 华茂股份 2020-10-12 纺织 安徽 3.97 601339 百隆东方 2020-10-12 纺织 浙江 3.83 600208 新湖中宝 2020-10-12 全国地产 浙江 3.53 600985 淮北矿业 2020-10-12 煤炭开采 安徽 10.13 002849 威星智能 2020-10-12 电器仪表 浙江 15.14 603277 银都股份 2020-10-12 专用机械 浙江 11.66 601577 长沙银行 2020-10-12 银行 湖南 9.13 002722 金轮股份 2020-10-12 纺织机械 江苏 13.38 600794 保税科技 2020-10-12 仓储物流 江苏 3.53 601985 中国核电 2020-10-12 新型电力 北京 4.55 600064 南京高科 2020-10-12 园区开发 江苏 11.38 000753 漳州发展 2020-10-12 汽车服务 福建 3.12 600376 首开股份 2020-10-12 区域地产 北京 6.93 601866 中远海发 2020-10-12 水运 上海 2.17 000630 铜陵有色 2020-10-12 铜 安徽 2.31 000719 中原传媒 2020-10-12 出版业 河南 7.85 600900 长江电力 2020-10-12 水力发电 北京 19.25 002738 中矿资源 2020-10-12 小金属 北京 19.95 600026 中远海能 2020-10-12 水运 上海 7.48 600188 兖州煤业 2020-10-12 煤炭开采 山东 9.71 603166 福达股份 2020-10-12 汽车配件 广西 7.15 600704 物产中大 2020-10-12 商贸代理 浙江 4.79 600757 长江传媒 2020-10-12 出版业 湖北 5.71 603156 养元饮品 2020-10-12 软饮料 河北 25.52 603098 森特股份 2020-10-12 装修装饰 北京 9.98 601088 中国神华 2020-10-12 煤炭开采 北京 16.74 000761 本钢板材 2020-10-12 普钢 辽宁 3.51 603300 华铁应急 2020-10-12 钢加工 浙江 6.95 002202 金风科技 2020-10-14 电气设备 新疆 12.0 002406 远东传动 2020-10-14 汽车配件 河南 7.14 300596 利安隆 2020-10-14 化工原料 天津 35.02 601318 中国平安 2020-10-14 保险 深圳 81.38 600395 盘江股份 2020-10-14 煤炭开采 贵州 6.15 600729 重庆百货 2020-10-14 百货 重庆 35.74 603928 兴业股份 2020-10-14 化工原料 江苏 12.41 603225 新凤鸣 2020-10-15 化纤 浙江 11.11 002394 联发股份 2020-10-15 纺织 江苏 10.83 603788 宁波高发 2020-10-15 汽车配件 浙江 19.18 600987 航民股份 2020-10-15 纺织 浙江 5.84 601818 光大银行 2020-10-15 银行 北京 3.98 002763 汇洁股份 2020-10-15 服饰 深圳 7.78 002440 闰土股份 2020-10-15 染料涂料 浙江 9.79 601139 深圳燃气 2020-10-15 供气供热 深圳 7.68 300387 富邦股份 2020-10-15 化工原料 湖北 10.12 300695 兆丰股份 2020-10-15 汽车配件 浙江 78.06 000988 华工科技 2020-10-15 电器仪表 湖北 25.28 603558 健盛集团 2020-10-16 纺织 浙江 9.8 002893 华通热力 2020-10-16 供气供热 北京 10.7 603706 东方环宇 2020-10-16 供气供热 新疆 19.3 300428 四通新材 2020-10-16 铝 河北 17.07 600123 兰花科创 2020-10-16 煤炭开采 山西 5.35 601699 潞安环能 2020-10-16 煤炭开采 山西 6.7 600997 开滦股份 2020-10-16 煤炭开采 河北 5.29 601918 新集能源 2020-10-16 煤炭开采 安徽 2.63 600508 上海能源 2020-10-16 煤炭开采 上海 9.33 601898 中煤能源 2020-10-16 煤炭开采 北京 4.18 000933 神火股份 2020-10-16 煤炭开采 河南 5.25 600785 新华百货 2020-10-16 百货 宁夏 16.72 601939 建设银行 2020-10-16 银行 北京 6.4 601997 贵阳银行 2020-10-16 银行 贵州 7.97 002224 三 力 士 2020-10-16 橡胶 浙江 6.88 601229 上海银行 2020-10-16 银行 上海 8.39 000651 格力电器 2020-10-16 家用电器 广东 57.7 603689 皖天然气 2020-10-16 供气供热 安徽 10.96 600332 白云山 2020-10-16 中成药 广东 34.18 000027 深圳能源 2020-10-16 火力发电 深圳 5.81 600019 宝钢股份 2020-10-16 普钢 上海 5.21 600919 江苏银行 2020-10-16 银行 江苏 6.3 300360 炬华科技 2020-10-16 电器仪表 浙江 10.77 600061 国投资本 2020-10-16 证券 上海 15.25 600030 中信证券 2020-10-16 证券 深圳 31.08 000776 广发证券 2020-10-16 证券 广东 16.33 002099 海翔药业 2020-10-16 化学制药 浙江 8.0 000685 中山公用 2020-10-16 水务 广东 8.65 000883 湖北能源 2020-10-16 火力发电 湖北 3.93 600837 海通证券 2020-10-16 证券 上海 14.79 000002 万 科A 2020-10-16 全国地产 深圳 27.86 600681 百川能源 2020-10-16 供气供热 湖北 5.57 000736 中交地产 2020-10-16 全国地产 重庆 7.47 000543 皖能电力 2020-10-16 火力发电 安徽 4.29 600846 同济科技 2020-10-16 建筑工程 上海 9.27 000623 吉林敖东 2020-10-16 化学制药 吉林 17.47 600582 天地科技 2020-10-16 工程机械 北京 3.18 600120 浙江东方 2020-10-16 多元金融 浙江 7.85 603567 珍宝岛 2020-10-16 中成药 黑龙江 12.92 600863 内蒙华电 2020-10-16 火力发电 内蒙 2.69 601098 中南传媒 2020-10-16 出版业 湖南 11.06 603279 景津环保 2020-10-16 环境保护 山东 21.82 603917 合力科技 2020-10-16 汽车配件 浙江 12.1 002644 佛慈制药 2020-10-16 中成药 甘肃 8.63 000650 仁和药业 2020-10-16 中成药 江西 6.57 300259 新天科技 2020-10-16 电器仪表 河南 5.62 002327 富安娜 2020-10-14 纺织 深圳 8.11 603920 世运电路 2020-10-16 元器件 广东 24.38 600488 天药股份 2020-10-19 化学制药 天津 5.35 600848 上海临港 2020-10-19 园区开发 上海 23.78 603006 联明股份 2020-10-19 汽车配件 上海 11.48 002948 青岛银行 2020-10-19 银行 山东 5.25 600998 九州通 2020-10-19 医药商业 湖北 17.88 601998 中信银行 2020-10-19 银行 北京 5.25 002673 西部证券 2020-10-19 证券 陕西 9.9 601688 华泰证券 2020-10-19 证券 江苏 21.22 000750 国海证券 2020-10-19 证券 广西 5.72 600167 联美控股 2020-10-20 供气供热 辽宁 13.87 000906 浙商中拓 2020-10-22 批发业 浙江 6.81 002085 万丰奥威 2020-10-23 汽车配件 浙江 7.1 002244 滨江集团 2020-10-23 区域地产 浙江 4.9 600999 招商证券 2020-10-23 证券 深圳 22.18 600048 保利地产 2020-10-23 全国地产 广东 16.4 300038 数知科技 2020-10-23 互联网 北京 8.72 601398 工商银行 2020-10-23 银行 北京 5.06 002290 ST中科创 2020-10-23 家用电器 江苏 5.39 000036 华联控股 2020-10-23 全国地产 深圳 4.43 600908 无锡银行 2020-10-23 银行 江苏 6.13 000898 鞍钢股份 2020-10-26 普钢 辽宁 2.7 002039 黔源电力 2020-10-26 水力发电 贵州 16.13 002111 威海广泰 2020-10-26 航空 山东 16.48 002236 大华股份 2020-10-26 电器仪表 浙江 21.85 002448 中原内配 2020-10-26 汽车配件 河南 5.86 002479 富春环保 2020-10-26 火力发电 浙江 6.97 002518 科士达 2020-10-26 电气设备 深圳 15.55 600648 外高桥 2020-10-26 园区开发 上海 16.2 600710 苏美达 2020-10-26 工程机械 江苏 5.22 601288 农业银行 2020-10-26 银行 北京 3.23 601567 三星医疗 2020-10-26 电器仪表 浙江 7.28 601668 中国建筑 2020-10-26 建筑工程 北京 5.22 603041 美思德 2020-10-26 化工原料 江苏 15.88 603992 松霖科技 2020-10-26 家居用品 福建 18.4 000155 川能动力 2020-10-27 新型电力 四川 5.18 603776 永安行 2020-10-27 公共交通 江苏 22.18 600284 浦东建设 2020-10-27 建筑工程 上海 6.64 002756 永兴材料 2020-10-27 特种钢 浙江 18.2 000899 赣能股份 2020-10-28 火力发电 江西 4.84 600461 洪城水业 2020-10-28 水务 江西 6.81 600406 国电南瑞 2020-10-28 电气设备 江苏 21.33 002045 国光电器 2020-10-28 元器件 广东 9.66 000600 建投能源 2020-10-28 火力发电 河北 5.45 002823 凯中精密 2020-10-27 机械基件 深圳 11.77 002384 东山精密 2020-10-27 元器件 江苏 27.2 600068 葛洲坝 2020-10-29 建筑工程 湖北 7.37 000407 胜利股份 2020-10-29 供气供热 山东 4.15 002911 佛燃能源 2020-10-26 供气供热 广东 16.44 603908 牧高笛 2020-10-26 纺织 浙江 26.05 603699 纽威股份 2020-10-27 专用机械 江苏 15.88 002162 悦心健康 2020-10-28 医疗保健 上海 3.52 603900 莱绅通灵 2020-10-30 服饰 江苏 8.59 600039 四川路桥 2020-10-30 建筑工程 四川 4.46 600012 皖通高速 2020-10-30 路桥 安徽 5.31 603897 长城科技 2020-10-30 电气设备 浙江 19.96 600740 山西焦化 2020-10-30 焦炭加工 山西 5.04 600408 ST安泰 2020-10-30 焦炭加工 山西 1.83 002276 万马股份 2020-11-02 电气设备 浙江 8.35 002718 友邦吊顶 2020-11-02 家居用品 浙江 16.98 002249 大洋电机 2020-11-02 电气设备 广东 4.03 600366 宁波韵升 2020-11-02 矿物制品 浙江 6.36 600368 五洲交通 2020-11-02 路桥 广西 3.6 002478 常宝股份 2020-11-03 钢加工 江苏 5.58 603002 宏昌电子 2020-11-03 化工原料 广东 5.49 300194 福安药业 2020-11-03 化学制药 重庆 6.5 300158 振东制药 2020-11-03 化学制药 山西 6.34 002775 文科园林 2020-11-03 建筑工程 深圳 5.51 603329 上海雅仕 2020-11-04 仓储物流 上海 14.35 000791 甘肃电投 2020-11-04 水力发电 甘肃 3.63 000821 京山轻机 2020-11-04 轻工机械 湖北 6.85 600219 南山铝业 2020-11-05 铝 山东 2.44 601901 方正证券 2020-11-05 证券 湖南 9.1 002377 国创高新 2020-11-05 房产服务 湖北 4.42 000900 现代投资 2020-11-05 路桥 湖南 3.89 600535 天士力 2020-11-05 中成药 天津 17.84 002446 盛路通信 2020-11-05 通信设备 广东 7.7 600469 风神股份 2020-11-05 汽车配件 河南 5.11 601155 新城控股 2020-11-05 区域地产 江苏 34.91 000402 金 融 街 2020-11-05 全国地产 北京 6.91 600783 鲁信创投 2020-11-05 多元金融 山东 16.8 600875 东方电气 2020-11-05 电气设备 四川 10.66 002380 科远智慧 2020-11-05 电气设备 江苏 16.42 603677 奇精机械 2020-11-05 机械基件 浙江 12.75 600798 宁波海运 2020-11-06 水运 浙江 3.23 601877 正泰电器 2020-11-06 电气设备 浙江 32.2 002131 利欧股份 2020-11-06 互联网 浙江 3.35 000488 晨鸣纸业 2020-11-06 造纸 山东 5.55 600512 腾达建设 2020-11-06 建筑工程 浙江 3.04 002404 嘉欣丝绸 2020-11-06 纺织 浙江 7.04 600458 时代新材 2020-11-06 塑料 湖南 7.44 000544 中原环保 2020-11-06 环境保护 河南 7.46 603556 海兴电力 2020-11-06 电器仪表 浙江 15.09 002221 东华能源 2020-11-06 石油贸易 江苏 10.06 601113 ST华鼎 2020-11-06 化纤 浙江 3.35 603335 迪生力 2020-11-06 汽车配件 广东 5.07 002408 齐翔腾达 2020-11-06 化工原料 山东 8.21 603128 华贸物流 2020-11-06 仓储物流 上海 7.13 600273 嘉化能源 2020-11-10 化工原料 浙江 10.68 600362 江西铜业 2020-11-10 铜 江西 16.12 600339 中油工程 2020-11-11 石油加工 新疆 3.02 002001 新 和 成 2020-11-11 化学制药 浙江 30.92 600565 迪马股份 2020-11-11 全国地产 重庆 2.98 600782 新钢股份 2020-11-11 普钢 江西 4.53 600067 冠城大通 2020-11-11 全国地产 福建 3.88 000528 柳 工 2020-11-11 工程机械 广西 7.4 601006 大秦铁路 2020-11-11 铁路 山西 6.52 601003 柳钢股份 2020-11-11 普钢 广西 4.95 002546 新联电子 2020-11-11 电气设备 江苏 4.29 002121 *ST科陆 2020-11-11 电器仪表 深圳 3.65 002110 三钢闽光 2020-11-11 普钢 福建 7.01 600282 南钢股份 2020-11-11 普钢 江苏 3.26 601158 重庆水务 2020-11-11 水务 重庆 5.32 000671 阳 光 城 2020-11-11 区域地产 福建 7.43 601005 重庆钢铁 2020-11-11 普钢 重庆 1.52 000717 韶钢松山 2020-11-11 普钢 广东 4.88 601117 中国化学 2020-11-11 建筑工程 北京 5.82 002091 江苏国泰 2020-11-11 商贸代理 江苏 6.7 601390 中国中铁 2020-11-11 建筑工程 北京 5.68 601996 丰林集团 2020-11-11 家居用品 广西 2.95 002543 万和电气 2020-11-12 家用电器 广东 9.32 002004 华邦健康 2020-11-12 化学制药 重庆 5.46 600317 营口港 2020-11-12 港口 辽宁 2.65 000557 西部创业 2020-11-12 铁路 宁夏 3.58 601880 大连港 2020-11-12 港口 辽宁 2.05 601228 广州港 2020-11-12 港口 广东 3.44 603968 醋化股份 2020-11-12 化工原料 江苏 17.43 002882 金龙羽 2020-11-12 电气设备 深圳 10.11 603867 新化股份 2020-11-12 化工原料 浙江 27.27 600717 天津港 2020-11-12 港口 天津 4.84 603681 永冠新材 2020-11-12 化工原料 上海 19.16 603266 天龙股份 2020-11-12 塑料 浙江 12.17 600210 紫江企业 2020-11-12 广告包装 上海 4.46 600231 凌钢股份 2020-11-12 普钢 辽宁 2.3 000960 锡业股份 2020-11-12 小金属 云南 9.84 000751 锌业股份 2020-11-12 铅锌 辽宁 3.0 688101 三达膜 2020-11-12 环境保护 陕西 21.41 600497 驰宏锌锗 2020-11-12 铅锌 云南 4.2 000811 冰轮环境 2020-11-13 工程机械 山东 7.77 000783 长江证券 2020-11-13 证券 湖北 8.37 000028 国药一致 2020-11-13 医药商业 深圳 50.94 603227 雪峰科技 2020-11-13 化工原料 新疆 4.37 300384 三联虹普 2020-11-13 纺织机械 北京 18.62 600081 东风科技 2020-11-13 汽车配件 上海 11.66 000060 中金岭南 2020-11-13 铅锌 深圳 4.46 002206 海 利 得 2020-11-13 化纤 浙江 4.0 002109 兴化股份 2020-11-13 化工原料 陕西 3.74 000756 新华制药 2020-11-13 化学制药 山东 10.89 000708 中信特钢 2020-11-16 特种钢 湖北 20.15 603967 中创物流 2020-11-16 仓储物流 山东 15.59 300440 运达科技 2020-11-16 软件服务 四川 9.75 600581 八一钢铁 2020-11-16 普钢 新疆 3.69 002101 广东鸿图 2020-11-16 汽车配件 广东 7.77 600058 五矿发展 2020-11-16 商贸代理 北京 7.06 600278 东方创业 2020-11-16 商贸代理 上海 10.18 300462 华铭智能 2020-11-16 专用机械 上海 25.95 600575 淮河能源 2020-11-16 水运 安徽 2.24 000598 兴蓉环境 2020-11-16 水务 四川 5.16 600018 上港集团 2020-11-16 港口 上海 4.52 600971 恒源煤电 2020-11-16 煤炭开采 安徽 5.3 600795 国电电力 2020-11-16 火力发电 辽宁 2.11 000927 *ST夏利 2020-11-16 汽车整车 天津 4.05 000709 河钢股份 2020-11-16 普钢 河北 2.23 600295 鄂尔多斯 2020-11-16 小金属 内蒙 9.89 600755 厦门国贸 2020-11-16 商贸代理 福建 7.07 603648 畅联股份 2020-11-16 仓储物流 上海 9.96 601101 昊华能源 2020-11-16 煤炭开采 北京 4.01 603339 四方科技 2020-11-16 专用机械 江苏 10.86 002015 协鑫能科 2020-11-16 新型电力 江苏 6.12 601018 宁波港 2020-11-17 港口 浙江 4.12 002040 南 京 港 2020-11-18 港口 江苏 7.41 000905 厦门港务 2020-11-18 港口 福建 8.02 600063 皖维高新 2020-11-18 化纤 安徽 4.18 000657 中钨高新 2020-11-18 小金属 海南 7.07 002724 海洋王 2020-11-18 半导体 深圳 8.15 000961 中南建设 2020-11-19 建筑工程 江苏 10.17 002462 嘉事堂 2020-11-19 医药商业 北京 15.88 603037 凯众股份 2020-11-19 汽车配件 上海 17.46 603323 苏农银行 2020-11-19 银行 江苏 4.97 002620 瑞和股份 2020-11-19 装修装饰 深圳 6.77 600420 现代制药 2020-11-19 化学制药 上海 10.68 000419 通程控股 2020-11-19 百货 湖南 4.87 600727 鲁北化工 2020-11-19 农药化肥 山东 7.62 601949 中国出版 2020-11-19 出版业 北京 5.91 000601 韶能股份 2020-11-20 水力发电 广东 7.09 600173 卧龙地产 2020-11-20 全国地产 浙江 5.21 002002 鸿达兴业 2020-11-20 化工原料 江苏 4.04 600886 国投电力 2020-11-20 水力发电 北京 9.35 002182 云海金属 2020-11-20 小金属 江苏 11.69 000885 城发环境 2020-11-20 公路 河南 12.2 300422 博世科 2020-11-20 环境保护 广西 12.13 002130 沃尔核材 2020-11-20 电气设备 深圳 5.65 002155 湖南黄金 2020-11-20 黄金 湖南 9.05 002753 永东股份 2020-11-20 化工原料 山西 8.7 600742 一汽富维 2020-11-20 汽车配件 吉林 11.89 600352 浙江龙盛 2020-11-20 染料涂料 浙江 14.76 002871 伟隆股份 2020-11-20 机械基件 山东 18.26 002540 亚太科技 2020-11-20 铝 江苏 5.23","raw":null,"content":null,"categories":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/"},{"name":"选股","slug":"股票/选股","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/%E9%80%89%E8%82%A1/"}],"tags":[{"name":"grape","slug":"grape","permalink":"http://bejondshao.github.io/tags/grape/"},{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/tags/%E8%82%A1%E7%A5%A8/"}]},{"title":"验证股票之股东人数","slug":"验证股票之股东人数","date":"2019-11-24T06:10:00.000Z","updated":"2023-03-02T03:26:34.266Z","comments":true,"path":"2019/11/24/验证股票之股东人数/","link":"","permalink":"http://bejondshao.github.io/2019/11/24/%E9%AA%8C%E8%AF%81%E8%82%A1%E7%A5%A8%E4%B9%8B%E8%82%A1%E4%B8%9C%E4%BA%BA%E6%95%B0/","excerpt":"","keywords":null,"text":"写文章最好的方式是立即下笔写提纲,逐渐丰富调整。没有人能在脑中构思完整的内容并一气呵成。 股价和股性没有决定性关系,没有人能百分百断定一家公司是优质的,正如我们无法百分百确定一个人是优秀的人一样。其所形成的投资理由无非是比较规律化的基本面,未来预期,财务报表,近期新闻公告,笼统的市场分析等,即便实地考察也容易被蒙蔽双眼,因为公司都尽可能的向股东展示其好的一面。所以股价和股民分析的结果往往大相径庭,股民眼中的优质公司,股价却连连走低,于是利空消息就被人所知了。而普通甚至账面一塌糊涂的公司股价却节节攀升,进而概念和利好就出来了。发现规律没?利好利空理论上会影响股价,但是这些消息往往是根据股价来产生的,这就很有趣,有点本末倒置的感觉。 那么股价是受什么影响的呢?归根结底就一个因素:资金。 股票就像锅里的石子,资金就像外部加热的柴火,外部加热,则每个石子温度都上升;倘若抽走柴火,那么所有的石子都会很快冷却。锅里的石子总量没有变化(即使石子数量变多也只是大石子分裂,石子总量没变),只是温度降低了。倘若没有外部加热,石子也会缓慢冷却,这是因为散热消耗,即交易手续费和印花税。分红则是将每个石子切下小部分拿走分给股东,与主题无关,这里不再赘述。 既然决定股价上升的因素是涌入资金,那么这个资金势必是要从某些人的口袋里掏出来的。起带头作用的,往往是拥有大量资金的机构,散户则是根据股价的走势也好,根据财报或新闻也好,为已经拉升的股票投入更多的资金,借公司未来发展为由,期以股价攀升。投机就是如此,但凡以某个价格买入,都是认为当前价格是最便宜的,看好后市。倘若有人说,他看好一个公司是以投资的心态来买入股票的,股价越跌越买。你要远离这样的人,起码也要远离他的思想。这是在别人抽离柴火时他往上续火,与市场作对的人没有好下场,即便若干年后他等来的新的柴火,但是这段时间的资金时间损失和内心的煎熬所带来的的影响是无法用金钱衡量的。永远不要尝试抄底,永远不要左侧交易。 尝试抄底无疑和单纯女孩遇到渣男,天真的认为她会是他最后一个女人一样愚蠢。 如果在交易中因追高而导致亏损,这时就需要判断是调整还是已经进入左侧。这个并没有明确的准则,只能靠个人的经验和分析来判断(这是另外一个话题,在此不方便详细论述,但是一个十分重要的话题)。但有一点可以肯定:一旦判断为左侧,不论收益或亏损多少,都要立刻出局。 这里同样有个准则:永远不要看到股票在高位下跌一些甚至下跌很多而买入。因为你不清楚是回调还是别人在出局。 现在我们把精力放在找资金上。如何判断该股票现在有正在流入的资金,这不是每日在手机APP上查看某个股票当日资金流入还是流出来判断的,一是这种方式不准确;二是某一天的资金方向,甚至某一大段时间的资金方向并不能说明总体趋势(这种资金趋势是机构之间的博弈结果,到底谁输谁赢还真无法断定);三是股票太多,每天统计太耗费精力,即便是程序量化统计,结果大概猜测也不会有什么用处。我的意思是,资金的动向,不能简单的靠量化来分析,而是通过建模,拆分为不同的特征来分析。 注意:特征表明是可明确观察的表象。这里我使用特征一词,着重强调可观察。而到底我们观察的指标是资金流入的结果还是资金流入的原因,详细分辨还是可以得到答案的,但是指标定性并没有我们关注的资金方向重要,因此统一使用特征代替。 那么有哪些特征表明资金正处在流入方向呢? 理性人股东人数变化(指标偏滞后) 受到《理性人-股东人数的变化与股价走势》一文的启发,从机构和散户的角度思考股价规律。 参考我截取的部分股东和股价规律截图: 东方雨虹002271 可以看到股东人数和股价呈横着的数字8的样式,∞,即股东人数多了,股价就下降。股价上升,股东人数就少。可以理解为在股价由低位到高位的过程中,机构不断吸筹,这其中出手的散户包括之前被套牢解套,包括小赚而离场的。因此股东数量变少,股价攀升。当股价到达高位时,散户从各个渠道(论坛,公众号,股吧评论,各大群,各大v推荐)发现强势股票进而介入,此时机构慢慢出货,股价进一步拉升。在出货过程中,不同机构也有不同的策略,毕竟机构人员的投机观念也不同,因此往往会形成对冲。所以就存在股价呈波浪形上扬。到达最高位,各大机构开始出货,没有那么多散户接手,因此股价暴跌。聪明的机构会通过拉高出货的方式,使股价缓慢回落。在回落过程中,总有散户看股价较最高点回落好多,以为捡到便宜而买入,这就是套牢的开始。在回落的过程中,越来越多的散户发现股票。左侧交易的人,判断股票是否值得买入一是根据最高点判断,二是根据估值判断。不论哪种判断他们都忽略了重要一点:谁也不知道股票的底在哪里,即便股票到底部也要盘整好长一段时间才会有下一次牛市。因此但凡没有启动牛市的股票,都是不值得投机的。 要知道,股价的推动是随着机构收集筹码而抬高股价的,这是自然规律,其实机构倒是希望以最少的价钱买最多的股票。这个时候随着机构不断收集筹码,散户不断卖出筹码,导致股票集中,甚至后来机构高度控盘,市场上已经没有多少卖出力量了,那么根据杰西 · 利弗莫尔的”阻力最小方向运动规律”,股票自然就很容易拉升了,甚至到后来没有筹码卖出,就以涨停开盘或收盘。往往到后期拉升时,会有很多散户看到股票价格稳步攀升而预测后市,不惜冒被套牢的风险追高。他们并不是投机,这是在赌博,赌自己不是最后一棒。 再列出其他具有代表性的股东人数和股价的关系图: 双汇发展000895 这个票更是完美诠释了股东人数与股价变化的规律。 东旭蓝天000040 众泰汽车000980 为什么股价连创新低,并且市净率已经远小于1了,股价还不拉升呢?哈哈,看到右上角股东人数了吗?有6万散户也是像你这么想的。都想不劳而获,那么谁出资金拉升呢?机构吗?机构在释放筹码,当然不会拉升。所以这只股票的下一个牛市,难以预料。 供销大集000564 海航基础600515 石基信息002153 贵州茅台600519 这个股东人数指标比较落后于股价,因此需要将股票提前放到关注池里,在是否值得买入时作为一个重要参考条件,甚至可以算作必要条件。因为机构在没有足够筹码时会缓慢吸筹,而缓慢吸筹的过程走势就很不明朗,也有可能底部吸筹然后埋伏而不拉升。因为在拉升的过程中,如果散户过多,解套的人过多,阻力太大。股价下跌也很常见,并不是说机构就是很厉害,他们大多是分散投机,有的甚至也深套割肉。没有哪个机构敢保证买了股票就能赚钱。 注意:这个指标只能用作验证买入条件是否达到,而不能用作买入的充分条件,我可以举出好多不符合这个关系的股票,甚至好多股票已经集中但是仍在在底部,这都是很常见的。 投机的唯一准则就是:找到右侧股票,用多个验证标准来确定该股票是右侧,再买入。否则,就继续等待。 要有空仓的定力,在机会未到时,一定要沉住气。当买入亏损时,一定要及时止损,保存实力。 需要注意的是,机构持股占有量与股价没有关系。我们很容易以为机构持有量增加,股价就会上扬,这只是形成记忆效应而已。机构也是人,他们的思维也只是在投机,只不过策略因人而异。因此机构买入股票并不能代表什么,股票价格是由资金方向决定的。机构有多种方式通过打压股价来吸筹。因此机构持有量增加可以作为投机的一个标的,但权重不宜过大。机构的资金量大,可以买入埋伏。而我们跟进的话就是漫长的盘整,对于投机客来说,这就是在犯错误。 次新股的第二牛 次新股指的是最近半年到一年半上市的股票。我们知道新股上市后往往会涨停数天,拉升很高,然后打开涨停板。股价慢慢回落,这个过程就是不断有散户进入,以为捡到便宜。的确有部分股票在打开涨停板后,盘整几天又继续拉升。但是这第二次拉升,在我看来是火中取栗,完全是在赌。新股大部分股票由机构认购,散户只是一小部分。因此打开涨停板,全国各大机构首要任务就是清仓套现,收益都在一倍以上,甚至三四倍。所以不论股价如何跌,收益率都是相当高的。处在这个时期的股票一旦下跌,少则5个点,多则数个跌停才能打开跌停板,风险实在太大。因此这几天后的拉升在我看来不是牛市,而是搏傻。一切这个时期进入的股民都是接盘侠,等待他们的将是无尽的深套。 我所指的第二牛,是次新股经过数个月甚至一年的缓慢下跌,盘整,进而拉升的情形。如果开盘连连涨停算第一次牛市的话,那么这次就是第二次牛市。这第二牛是有规律可循且好掌握的。有如下几个特点: 股票经过几个月下跌,市值比较小,通常在百亿以下,股价较发行价差距不大。 刚上市股票限售股占比极大,流通股占比少。比例在5:1到9:1之间。市场流通股少,机构收集筹码就容易,可操作性更高。 持股机构较少,前十股东占比大,拉升意向统一,更容易稳定进入牛市。 一般一个股票牛市周期两到三年,次新股由于机构持股多,周期较短。 选取几个样例: 江苏新能603693 现在处在历史最低点,十大流通股东控盘近50%,只需要加入观察池等待拉升。 天风证券601162 该股票在19年1月份到19年3月份进行了第二牛。目前在最低位置,等待拉升。 密尔克卫603713 该股票在上市后6个月开启第二牛。目前位置一般,看似有第三牛的样子,但获利空间不大。 捷佳伟创300724 该股上市后四个月就开启第二牛。涨幅超过100%。目前局势不明朗。 明德生物002932 历史低位,流通股3000万,中度控盘,值得关注。 江苏新能603693 历史低位,中度控盘,值得关注。 长飞光纤601869 历史低位,注意前十大股东,武汉瑞图,武汉瑞腾,武汉瑞鸿,明显的分散持股,拉升意图明显,重点关注。 以上总结两种关于股东人数与股价的关系的案例,目的是验证股票的右侧真伪。投机就要右侧交易,我们应该借着机构抬轿子的机会,坐轿子。不应过早介入,也不要贪图最后的收益,我认为最好的卖出时机在高位的拉高出货,换手率尤其高的时候。为了保险起见,确定买入时,先拿一小部分资金试水(由于A股T+1机制,不要一天两次买入,因为买入无法当天割肉,更不要第一次就全仓买入。)。当股价上涨后,第二天再小部分资金买入。买入的手续费很少,因为不舍得浪费那5元手续费而大笔买入,是相当愚蠢的行为。 保住本金,机会遍地都是,缺的是发现机会的眼睛。不要碰到只股票就以为是机会,很有可能是陷阱。 本文编辑于2019年11月24日","raw":null,"content":null,"categories":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/"},{"name":"理论","slug":"股票/理论","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/%E7%90%86%E8%AE%BA/"}],"tags":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/tags/%E8%82%A1%E7%A5%A8/"},{"name":"选股","slug":"选股","permalink":"http://bejondshao.github.io/tags/%E9%80%89%E8%82%A1/"}]},{"title":"股票基本概念","slug":"股票基本概念","date":"2019-11-17T13:21:00.000Z","updated":"2023-03-02T03:26:34.258Z","comments":true,"path":"2019/11/17/股票基本概念/","link":"","permalink":"http://bejondshao.github.io/2019/11/17/%E8%82%A1%E7%A5%A8%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/","excerpt":"","keywords":null,"text":"每个概念都有标准详细的定义,括号加粗为个人为方便理解和复习的简要概括,不保证精确性。 股票 股票是一种由股份制有限公司签发的用以证明股东所持股份的凭证,它表明股票的持有者对股份公司的部分资本拥有所有权。由于股票包含有经济利益,且可以上市流通转让,股票也是一种有价证券。我国上市公司的股票是在上海证券交易所和深圳证券交易所发行,投资者一般在证券经纪公司开户交易。(公司用部分权益做担保,向社会借钱,并给出钱的人一些股票,股票算是对公司有一定的参与权的凭证,股票可以转卖。) 股票发行以后卖出股票所得的收入就归公司所有他不像债券那样,到一定时候偿还,除非公司宣布破产彻底清算。否则你就永远不能用股票向公司要回你所持有的那份财产。(公司靠发行股票借的钱不会还给你) 全责性。全责性是说你买了公司的股票,就成为公司的股东,就对公司的经营管理有权过问。向参加股东大会,了解公司的经营状况等,并且有权分享公司的利益。也就是参加配股分红。如果你持有的股票。占了公司股票的大多数。自然,你就取得了公司的领导权。在国外,股份制公司的产权转让,就常常是通过股票的转让来完成的。(有了股票就是公司股东,可以分股,可以分红,可以参与公司未来决定。) 三,流通性。流通性是说你买了股票以后,虽然不能退回去,但是可以转让给他人。可以在市场上买卖。(如果你不想要股票,想换成钱,可以把股票卖了,至于能卖多少以实际价格为准)","raw":null,"content":null,"categories":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/"},{"name":"知识","slug":"股票/知识","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/%E7%9F%A5%E8%AF%86/"}],"tags":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/tags/%E8%82%A1%E7%A5%A8/"}]},{"title":"股票进阶概念","slug":"股票进阶概念","date":"2019-11-17T13:14:00.000Z","updated":"2023-03-02T03:26:34.258Z","comments":true,"path":"2019/11/17/股票进阶概念/","link":"","permalink":"http://bejondshao.github.io/2019/11/17/%E8%82%A1%E7%A5%A8%E8%BF%9B%E9%98%B6%E6%A6%82%E5%BF%B5/","excerpt":"","keywords":null,"text":"每个概念都有标准详细的定义,括号加粗为个人为方便理解和复习的简要概括,不保证精确性。 股市互联互通 ”互联互通机制“的定义是:内地与香港股票市场交易互联互通机制(简称“互联互通机制”),是指上海证券交易所、深圳证券交易所分别和香港联合交易所有限公司建立技术连接,使内地和香港投资者可以通过当地证券公司或经纪商买卖规定范围内的对方交易所上市的股票。 简单来说,即内地和香港投资者可以互相买卖在对方交易所上市的符合一定条件的部分股票。(你可以用沪深的账号买卖港股,同样港股账号也可以买卖沪深的股票。以前是沪深两市互通,后来是沪深港互通,方便交易。但是有条件,目前是沪深市值需要50万以上才能开通沪港通,深港通。) * 北向资金:国外或香港资金经中央结算购买沪深股票。 * 南下资金:沪深两市资金经中央结算购买港股。 * 沪股通:北向资金可买沪市股票。 * 深股通:北向资金可买深市股票。 * 港股通:南下资金买港股。 股市互联互通机制有一个特点,就是股票卖出之后,资金会自动回流到投资者所在地,所以可以说南下资金并没有完全流出境外。这也减缓了跨境资金流动压力。但是,互联互通机制作为一个比较透明的窗口,能起到较资金大得多的影响力。在过去两年,沪港通已经成为反映两地投资者情绪的重要指标。 融资融券余额 * 融资是指投资者以资金或证券作为质押向券商借入资金用于买入股票,并在约定的期限内偿还借款本金和利息。融资余额指融资买入股票与偿还融资额的差额。(用账户中的保证金或证券做抵押,使用杠杆交易。) * 融券是指投资者以资金或证券作为质押向券商借入股票卖出,并在约定的期限内买入相同数量的和品种股票归还券商并支付相应的费用。融券余额指融券卖出股票数量与偿还融券数量的差额。(用账户中的额保证金或证券做抵押,向券商借股票操作(卖),待股票价格回落后,再用资金买回来,还给券商,用于做空。) 市场常以融资余额与融券余额换算金额(融券余额乘以股价)的差额衡量多空力量变化。","raw":null,"content":null,"categories":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/"},{"name":"知识","slug":"股票/知识","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/%E7%9F%A5%E8%AF%86/"}],"tags":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/tags/%E8%82%A1%E7%A5%A8/"}]},{"title":"grape股票列表-2019","slug":"grape股票列表-2019","date":"2019-11-05T15:13:00.000Z","updated":"2023-03-02T03:26:34.212Z","comments":false,"path":"2019/11/05/grape股票列表-2019/","link":"","permalink":"http://bejondshao.github.io/2019/11/05/grape%E8%82%A1%E7%A5%A8%E5%88%97%E8%A1%A8-2019/","excerpt":"","keywords":null,"text":"我的grape本地运行的结果,选股策略描述后续补充吧。先做个记录。 声明:grape选股策略在不断调整和丰富,股票列表仅记录用,不作为任何投资建议。依据列表选股投资导致亏损本人概不负责。 2019-11-05 find_head_up(filter_time=1.3) 600295 鄂尔多斯 小金属 内蒙: 2019-11-01 收盘价: 8.32 600814 杭州解百 百货 浙江: 2019-10-31 收盘价: 5.16 601186 中国铁建 建筑工程 北京: 2019-11-04 收盘价: 9.73 000419 通程控股 百货 湖南: 2019-11-04 收盘价: 4.42 601169 北京银行 银行 北京: 2019-11-01 收盘价: 5.63 000926 福星股份 区域地产 湖北: 2019-11-04 收盘价: 6.5 000623 吉林敖东 化学制药 吉林: 2019-11-04 收盘价: 16.0 600660 福耀玻璃 汽车配件 福建: 2019-11-04 收盘价: 22.21 600713 南京医药 医药商业 江苏: 2019-10-31 收盘价: 4.36 601006 大秦铁路 铁路 山西: 2019-11-04 收盘价: 7.84 600035 楚天高速 路桥 湖北: 2019-11-04 收盘价: 3.41 600317 营口港 港口 辽宁: 2019-11-05 收盘价: 2.66 601717 郑煤机 汽车配件 河南: 2019-11-05 收盘价: 6.23 603298 杭叉集团 专用机械 浙江: 2019-11-01 收盘价: 12.52 600015 华夏银行 银行 北京: 2019-11-01 收盘价: 7.56 601328 交通银行 银行 上海: 2019-11-05 收盘价: 5.73 600642 申能股份 火力发电 上海: 2019-11-01 收盘价: 5.84 601877 正泰电器 电气设备 浙江: 2019-11-05 收盘价: 23.94 000883 湖北能源 火力发电 湖北: 2019-11-05 收盘价: 4.15 600252 中恒集团 中成药 广西: 2019-11-04 收盘价: 3.0 300439 美康生物 医疗保健 浙江: 2019-11-05 收盘价: 14.75 600724 宁波富达 区域地产 浙江: 2019-11-04 收盘价: 3.56 600012 皖通高速 路桥 安徽: 2019-11-04 收盘价: 5.67 603167 渤海轮渡 水运 山东: 2019-11-05 收盘价: 9.29 600348 阳泉煤业 煤炭开采 山西: 2019-11-05 收盘价: 5.24 600328 兰太实业 化工原料 内蒙: 2019-11-04 收盘价: 8.16 603979 金诚信 建筑工程 北京: 2019-11-05 收盘价: 8.62 601939 建设银行 银行 北京: 2019-11-04 收盘价: 7.34 600377 宁沪高速 路桥 江苏: 2019-10-30 收盘价: 10.45 600056 中国医药 医药商业 北京: 2019-11-05 收盘价: 13.39 601988 中国银行 银行 北京: 2019-11-01 收盘价: 3.7 002033 丽江旅游 旅游景点 云南: 2019-11-04 收盘价: 5.94 600395 盘江股份 煤炭开采 贵州: 2019-11-04 收盘价: 5.3 600350 山东高速 路桥 山东: 2019-11-04 收盘价: 4.77 300026 红日药业 中成药 天津: 2019-10-31 收盘价: 3.43 601918 新集能源 煤炭开采 安徽: 2019-10-31 收盘价: 3.25 600827 百联股份 超市连锁 上海: 2019-11-04 收盘价: 8.92 600126 杭钢股份 普钢 浙江: 2019-11-05 收盘价: 4.64 38 2019-11-06 find_head_up(filter_time=1.3) 600508 上海能源 煤炭开采 上海: 2019-11-06 收盘价: 9.21 1 2019-11-09 find_head_up(filter_time=1.3) 600995 文山电力 水力发电 云南: 2019-11-08 收盘价: 7.56 1 2019-11-13 find_head_up(filter_time=1.3) 600827 百联股份 超市连锁 上海: 2019-11-07 收盘价: 8.93 1 2019-11-19 find_head_up(filter_time=1.3) 002043 兔 宝 宝 其他建材 浙江: 2019-11-18 收盘价: 6.11 1 2019-11-21 find_head_up(filter_time=1.3) 600252 中恒集团 中成药 广西: 2019-11-21 收盘价: 2.93 002085 万丰奥威 汽车配件 浙江: 2019-11-20 收盘价: 7.29 2 2019-11-25 find_head_up(filter_time=1.3) 002187 广百股份 百货 广东: 2019-11-25 收盘价: 8.5 000959 首钢股份 普钢 北京: 2019-11-25 收盘价: 3.71 600307 酒钢宏兴 普钢 甘肃: 2019-11-25 收盘价: 2.03 600348 阳泉煤业 煤炭开采 山西: 2019-11-25 收盘价: 5.37 601899 紫金矿业 黄金 福建: 2019-11-25 收盘价: 3.77 601666 平煤股份 煤炭开采 河南: 2019-11-25 收盘价: 3.96 600508 上海能源 煤炭开采 上海: 2019-11-25 收盘价: 9.25 600660 福耀玻璃 汽车配件 福建: 2019-11-25 收盘价: 22.29 002039 黔源电力 水力发电 贵州: 2019-11-22 收盘价: 14.61 9 补充一点:上周五石油开采和煤炭能源板块有启动迹象 2019-11-26 find_head_up(filter_time=1.3) 000002 万 科A 全国地产 深圳: 2019-11-26 收盘价: 28.35 600012 皖通高速 路桥 安徽: 2019-11-26 收盘价: 5.67 600236 桂冠电力 水力发电 广西: 2019-11-26 收盘价: 4.83 3 2019-11-28 find_head_up(filter_time=1.3) 002375 亚厦股份 装修装饰 浙江: 2019-11-28 收盘价: 5.56 300026 红日药业 中成药 天津: 2019-11-28 收盘价: 3.43 2 2019-11-29 find_head_up(filter_time=1.3) 002789 建艺集团 装修装饰 深圳: 2019-11-29 收盘价: 17.37 601717 郑煤机 汽车配件 河南: 2019-11-29 收盘价: 6.18 600713 南京医药 医药商业 江苏: 2019-11-29 收盘价: 4.36 000883 湖北能源 火力发电 湖北: 2019-11-29 收盘价: 4.13 4 2019-12-02 find_head_up(filter_time=1.3) 603203 快克股份 专用机械 江苏: 2019-12-02 收盘价: 22.5 603979 金诚信 建筑工程 北京: 2019-12-02 收盘价: 8.65 600236 桂冠电力 水力发电 广西: 2019-12-02 收盘价: 4.86 000543 皖能电力 火力发电 安徽: 2019-12-02 收盘价: 4.69 4 2019-12-04 find_head_up(filter_time=1.3) 600578 京能电力 火力发电 北京: 2019-12-04 收盘价: 3.09 1 2019-12-05 find_head_up(filter_time=1.3) 600674 川投能源 水力发电 四川: 2019-12-05 收盘价: 9.94 300026 红日药业 中成药 天津: 2019x-12-05 收盘价: 3.44 2 2019-12-06 find_head_up(filter_time=1.3) 000417 合肥百货 百货 安徽: 2019-12-06 收盘价: 4.92 002004 华邦健康 化学制药 重庆: 2019-12-06 收盘价: 4.93 000419 通程控股 百货 湖南: 2019-12-06 收盘价: 4.39 600693 东百集团 百货 福建: 2019-12-06 收盘价: 5.17 4 2019-12-09 find_head_up(filter_time=1.3) 600068 葛洲坝 建筑工程 湖北: 2019-12-09 收盘价: 6.23 600508 上海能源 煤炭开采 上海: 2019-12-09 收盘价: 9.2 000027 深圳能源 火力发电 深圳: 2019-12-09 收盘价: 6.09 3 2019-12-10 find_head_up(filter_time=1.3) 600362 江西铜业 铜 江西: 2019-12-10 收盘价: 15.09 1 2019-12-11 find_head_up(filter_time=1.3) 002654 万润科技 互联网 深圳: 2019-12-11 收盘价: 4.66 603798 康普顿 石油加工 山东: 2019-12-11 收盘价: 11.77 000069 华侨城A 旅游景点 深圳: 2019-12-11 收盘价: 7.2 601877 正泰电器 电气设备 浙江: 2019-12-11 收盘价: 24.22 601900 南方传媒 出版业 广东: 2019-12-11 收盘价: 9.14 601006 大秦铁路 铁路 山西: 2019-12-11 收盘价: 7.8 002039 黔源电力 水力发电 贵州: 2019-12-11 收盘价: 14.56 7 2019-12-12 find_head_up(filter_time=1.3) 300031 宝通科技 互联网 江苏: 2019-12-12 收盘价: 13.4 300196 长海股份 玻璃 江苏: 2019-12-12 收盘价: 9.66 002033 丽江旅游 旅游景点 云南: 2019-12-12 收盘价: 6.23 603979 金诚信 建筑工程 北京: 2019-12-12 收盘价: 8.74 600897 厦门空港 机场 福建: 2019-12-12 收盘价: 22.0 5 2019-12-13 find_head_up(filter_time=1.3) 000419 通程控股 百货 湖南: 2019-12-13 收盘价: 4.45 601939 建设银行 银行 北京: 2019-12-13 收盘价: 7.2 2 2019-12-16 find_head_up(filter_time=1.3) 600252 中恒集团 中成药 广西: 2019-12-16 收盘价: 3.07 600233 圆通速递 仓储物流 辽宁: 2019-12-16 收盘价: 12.44 600660 福耀玻璃 汽车配件 福建: 2019-12-16 收盘价: 23.17 000027 深圳能源 火力发电 深圳: 2019-12-16 收盘价: 6.14 600693 东百集团 百货 福建: 2019-12-16 收盘价: 5.23 5 2019-12-17 find_head_up(filter_time=1.3) 000987 越秀金控 多元金融 广东: 2019-12-17 收盘价: 9.72 600483 福能股份 火力发电 福建: 2019-12-17 收盘价: 9.24 000776 广发证券 证券 广东: 2019-12-17 收盘价: 14.64 603020 爱普股份 食品 上海: 2019-12-17 收盘价: 8.05 300026 红日药业 中成药 天津: 2019-12-17 收盘价: 3.45 601186 中国铁建 建筑工程 北京: 2019-12-17 收盘价: 10.07 600713 南京医药 医药商业 江苏: 2019-12-17 收盘价: 4.43 002375 亚厦股份 装修装饰 浙江: 2019-12-17 收盘价: 5.72 300039 上海凯宝 中成药 上海: 2019-12-17 收盘价: 4.59 601369 陕鼓动力 机械基件 陕西: 2019-12-17 收盘价: 6.56 600827 百联股份 超市连锁 上海: 2019-12-17 收盘价: 9.01 000623 吉林敖东 化学制药 吉林: 2019-12-17 收盘价: 16.39 600035 楚天高速 路桥 湖北: 2019-12-17 收盘价: 3.42 600814 杭州解百 百货 浙江: 2019-12-17 收盘价: 5.14 600170 上海建工 建筑工程 上海: 2019-12-17 收盘价: 3.55 600340 华夏幸福 区域地产 河北: 2019-12-17 收盘价: 28.13 000166 申万宏源 证券 新疆: 2019-12-17 收盘价: 5.06 600995 文山电力 水力发电 云南: 2019-12-17 收盘价: 7.71 002187 广百股份 百货 广东: 2019-12-17 收盘价: 8.41 000685 中山公用 水务 广东: 2019-12-17 收盘价: 8.27 600508 上海能源 煤炭开采 上海: 2019-12-17 收盘价: 9.31 601988 中国银行 银行 北京: 2019-12-17 收盘价: 3.68 600567 山鹰纸业 造纸 安徽: 2019-12-17 收盘价: 3.48 600015 华夏银行 银行 北京: 2019-12-17 收盘价: 7.65 601328 交通银行 银行 上海: 2019-12-17 收盘价: 5.6 601566 九牧王 服饰 福建: 2019-12-17 收盘价: 11.51 000718 苏宁环球 区域地产 吉林: 2019-12-17 收盘价: 3.8 600674 川投能源 水力发电 四川: 2019-12-17 收盘价: 9.81 28 2019-12-18 find_head_up(filter_time=1.3) 600028 中国石化 石油加工 北京: 2019-12-18 收盘价: 5.07 002392 北京利尔 其他建材 北京: 2019-12-18 收盘价: 3.76 600512 腾达建设 建筑工程 浙江: 2019-12-18 收盘价: 2.76 002004 华邦健康 化学制药 重庆: 2019-12-18 收盘价: 4.96 600328 兰太实业 化工原料 内蒙: 2019-12-18 收盘价: 8.04 600727 鲁北化工 农药化肥 山东: 2019-12-18 收盘价: 6.93 7 2019-12-19 find_head_up(filter_time=1.3) 000155 川能动力 新型电力 四川: 2019-12-19 收盘价: 4.3 000012 南 玻A 玻璃 深圳: 2019-12-19 收盘价: 4.87 000543 皖能电力 火力发电 安徽: 2019-12-19 收盘价: 4.75 603355 莱克电气 家用电器 江苏: 2019-12-19 收盘价: 23.5 601000 唐山港 港口 河北: 2019-12-19 收盘价: 2.61 603800 道森股份 专用机械 江苏: 2019-12-19 收盘价: 12.63 6 2019-12-23 find_head_up(filter_time=1.3) 002612 朗姿股份 服饰 北京: 2019-12-23 收盘价: 8.83 600897 厦门空港 机场 福建: 2019-12-23 收盘价: 21.87 000402 金 融 街 全国地产 北京: 2019-12-23 收盘价: 7.96 3 2019-12-24 find_head_up(filter_time=1.3) 002406 远东传动 汽车配件 河南: 2019-12-24 收盘价: 5.98 600780 通宝能源 火力发电 山西: 2019-12-24 收盘价: 3.57 601168 西部矿业 铜 青海: 2019-12-24 收盘价: 5.8 002375 亚厦股份 装修装饰 浙江: 2019-12-24 收盘价: 5.77 600508 上海能源 煤炭开采 上海: 2019-12-24 收盘价: 9.21 002033 丽江旅游 旅游景点 云南: 2019-12-24 收盘价: 6.07 600694 大商股份 百货 辽宁: 2019-12-24 收盘价: 26.56 300026 红日药业 中成药 天津: 2019-12-24 收盘价: 3.42 8 2019-12-26 find_head_up(filter_time=1.3) 002126 银轮股份 汽车配件 浙江: 2019-12-25 收盘价: 7.79 603800 道森股份 专用机械 江苏: 2019-12-25 收盘价: 12.85 600742 一汽富维 汽车配件 吉林: 2019-12-26 收盘价: 12.29 002603 以岭药业 中成药 河北: 2019-12-25 收盘价: 11.4 600021 上海电力 火力发电 上海: 2019-12-26 收盘价: 8.01 300154 瑞凌股份 元器件 深圳: 2019-12-26 收盘价: 5.62 603885 吉祥航空 空运 上海: 2019-12-26 收盘价: 14.4 601965 中国汽研 汽车服务 重庆: 2019-12-25 收盘价: 7.71 600803 新奥股份 农药化肥 河北: 2019-12-26 收盘价: 10.6 600062 华润双鹤 化学制药 北京: 2019-12-25 收盘价: 12.72 603020 爱普股份 食品 上海: 2019-12-25 收盘价: 8.05 300422 博世科 环境保护 广西: 2019-12-26 收盘价: 10.29 002595 豪迈科技 专用机械 山东: 2019-12-25 收盘价: 18.85 600814 杭州解百 百货 浙江: 2019-12-25 收盘价: 5.07 601668 中国建筑 建筑工程 北京: 2019-12-26 收盘价: 5.5 600723 首商股份 百货 北京: 2019-12-26 收盘价: 6.07 002187 广百股份 百货 广东: 2019-12-26 收盘价: 8.5 002144 宏达高科 纺织 浙江: 2019-12-26 收盘价: 9.92 600578 京能电力 火力发电 北京: 2019-12-25 收盘价: 3.08 000685 中山公用 水务 广东: 2019-12-25 收盘价: 8.07 600028 中国石化 石油加工 北京: 2019-12-25 收盘价: 5.01 002394 联发股份 纺织 江苏: 2019-12-26 收盘价: 9.34 600328 兰太实业 化工原料 内蒙: 2019-12-26 收盘价: 8.22 601199 江南水务 水务 江苏: 2019-12-26 收盘价: 3.76 600483 福能股份 火力发电 福建: 2019-12-25 收盘价: 8.93 000926 福星股份 区域地产 湖北: 2019-12-26 收盘价: 6.44 601666 平煤股份 煤炭开采 河南: 2019-12-26 收盘价: 3.86 600153 建发股份 商贸代理 福建: 2019-12-26 收盘价: 8.73 600785 新华百货 百货 宁夏: 2019-12-26 收盘价: 15.0 601717 郑煤机 汽车配件 河南: 2019-12-26 收盘价: 6.31 000028 国药一致 医药商业 深圳: 2019-12-25 收盘价: 45.45 002539 云图控股 农药化肥 四川: 2019-12-26 收盘价: 4.81 32 2019-12-27 find_head_up(filter_time=1.3) 002441 众业达 批发业 广东: 2019-12-27 收盘价: 7.38 601225 陕西煤业 煤炭开采 陕西: 2019-12-27 收盘价: 8.9 002128 露天煤业 煤炭开采 内蒙: 2019-12-27 收盘价: 8.41 600104 上汽集团 汽车整车 上海: 2019-12-27 收盘价: 23.88 000983 西山煤电 煤炭开采 山西: 2019-12-27 收盘价: 5.91 000718 苏宁环球 区域地产 吉林: 2019-12-27 收盘价: 3.73 600023 浙能电力 火力发电 浙江: 2019-12-27 收盘价: 3.94 000883 湖北能源 火力发电 湖北: 2019-12-27 收盘价: 4.14 8 2019-12-30 find_head_up(filter_time=1.3) 002833 弘亚数控 专用机械 广东: 2019-12-30 收盘价: 38.6 600886 国投电力 水力发电 北京: 2019-12-30 收盘价: 9.15 601699 潞安环能 煤炭开采 山西: 2019-12-30 收盘价: 7.24 601368 绿城水务 水务 广西: 2019-12-30 收盘价: 5.86 600827 百联股份 超市连锁 上海: 2019-12-30 收盘价: 8.97 600269 赣粤高速 路桥 江西: 2019-12-30 收盘价: 4.12 002561 徐家汇 百货 上海: 2019-12-30 收盘价: 8.15 002620 瑞和股份 装修装饰 深圳: 2019-12-30 收盘价: 6.1 601992 金隅集团 水泥 北京: 2019-12-30 收盘价: 3.61 600533 栖霞建设 区域地产 江苏: 2019-12-30 收盘价: 3.35 601211 国泰君安 证券 上海: 2019-12-30 收盘价: 18.68 000987 越秀金控 多元金融 广东: 2019-12-30 收盘价: 9.68 12 2019-12-31 find_head_up(filter_time=1.3) 600332 白云山 中成药 广东: 2019-12-31 收盘价: 35.61 600998 九州通 医药商业 湖北: 2019-12-31 收盘价: 14.15 000582 北部湾港 港口 广西: 2019-12-31 收盘价: 8.95 601607 上海医药 医药商业 上海: 2019-12-31 收盘价: 18.37 600039 四川路桥 建筑工程 四川: 2019-12-31 收盘价: 3.36 600076 康欣新材 其他建材 山东: 2019-12-31 收盘价: 4.39 002004 华邦健康 化学制药 重庆: 2019-12-31 收盘价: 4.94 000899 赣能股份 火力发电 江西: 2019-12-31 收盘价: 4.87 8 2020-01-02 find_head_up(filter_time=1.3) 600419 天润乳业 乳制品 新疆: 2020-01-02 收盘价: 14.15 300154 瑞凌股份 元器件 深圳: 2020-01-02 收盘价: 5.72 002763 汇洁股份 服饰 深圳: 2020-01-02 收盘价: 8.8 002444 巨星科技 轻工机械 浙江: 2020-01-02 收盘价: 11.0 002539 云图控股 农药化肥 四川: 2020-01-02 收盘价: 4.98 600820 隧道股份 建筑工程 上海: 2020-01-02 收盘价: 6.16 600598 北大荒 种植业 黑龙江: 2020-01-02 收盘价: 9.96 600461 洪城水业 水务 江西: 2020-01-02 收盘价: 6.07 600229 城市传媒 出版业 山东: 2020-01-02 收盘价: 7.43 002789 建艺集团 装修装饰 深圳: 2020-01-02 收盘价: 16.8 000719 中原传媒 出版业 河南: 2020-01-02 收盘价: 7.26 600835 上海机电 运输设备 上海: 2020-01-02 收盘价: 16.92 002097 山河智能 工程机械 湖南: 2020-01-02 收盘价: 5.96 601333 广深铁路 铁路 深圳: 2020-01-02 收盘价: 3.09 14 code date 300315 2020-01-03","raw":null,"content":null,"categories":[{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/"},{"name":"选股","slug":"股票/选股","permalink":"http://bejondshao.github.io/categories/%E8%82%A1%E7%A5%A8/%E9%80%89%E8%82%A1/"}],"tags":[{"name":"grape","slug":"grape","permalink":"http://bejondshao.github.io/tags/grape/"},{"name":"股票","slug":"股票","permalink":"http://bejondshao.github.io/tags/%E8%82%A1%E7%A5%A8/"}]},{"title":"Markdown语法笔记","slug":"Markdown语法笔记","date":"2019-10-05T16:51:00.000Z","updated":"2023-03-02T03:26:34.185Z","comments":true,"path":"2019/10/06/Markdown语法笔记/","link":"","permalink":"http://bejondshao.github.io/2019/10/06/Markdown%E8%AF%AD%E6%B3%95%E7%AC%94%E8%AE%B0/","excerpt":"","keywords":null,"text":"注:该笔记为本人记录,并未系统记录markdown语法。具体教程可参考这里 所有Markdown语法 开始标签前 和 结束标签后 都建议加空格,防止加载时出现前后标签并未成对加载出错,并且也方便阅读。 markdown复选框为: 12* [ ] 这是未选中的复选框格式* [x] 这是选中的复选框格式 [ ] 这是未选中的复选框格式 [x] 这是选中的复选框格式 部分编辑器好像没有复选框效果,无所谓了,自己看明白就好😂。 文字上标或下标: 12这是 <sup>上标</sup> ,这是 <sub>下标</sub> 。 这是 上标 ,这是 下标 。","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"Markdown","slug":"Markdown","permalink":"http://bejondshao.github.io/tags/Markdown/"}]},{"title":"How to parse markdown file with images to hexo asset_img format","slug":"How-to-parse-markdown-file-with-images-to-hexo-asset-img-format","date":"2018-11-10T07:24:00.000Z","updated":"2023-03-02T03:26:34.084Z","comments":true,"path":"2018/11/10/How-to-parse-markdown-file-with-images-to-hexo-asset-img-format/","link":"","permalink":"http://bejondshao.github.io/2018/11/10/How-to-parse-markdown-file-with-images-to-hexo-asset-img-format/","excerpt":"","keywords":null,"text":"In Hexo doc about asset folders, it shows two ways to insert image. One way is put images into one foler, like images and use them through ![This is title](/images/image.jpg). Another way is seperate images in each folder for each post. I think this is better for management and update, and we don’t need to pay much attention on image file names. In short words, when we enable post_asset_folder: true, then when we create post, there’s also created the same name folder to save images. We can use like {% asset_img image.jpg This is title %}. What if I edit the markdown out of Hexo scope, we can only use ![This is title](/images/image.jpg) to show to others. But when I want to post my article on Hexo site, I have edit the content of each image format, which is tedious. So the thing becomes clear. I need to change 1231. This is some content![](directory/regist.png)2. This is some other content ![This is title](directory (contains bracket)/user_registered.png) into 1231. This is some content{% asset_img regist.png %}2. This is some other content {% asset_img user_registered.png This is title %} First, I don’t want to use advanced programing language. I just need a simple command to finish it. So sed can search and replace content in file. Second, I need to get file name in ![This is title](directory (contains bracket)/image.jpg), ignore directory name and parse file name into {% asset_img image.jpg %}. Let’s seperate ![This is title](directory (contains bracket)/image.jpg) into parts: There’s a ! in front, and append[], and we need content in [] to be as title, then goes (), and always a / in (). It’s like ![](a/b), besides, a might contain bracket, because post title might contain bracket. ! matches the character ! literally \\[ matches the character [ literally We need content inside [], which is , we need content in front of ]. So it should be: ([^]]*). (Explaination: () in regex means group, we can use the content in the group with \\1, \\2 etc. [abc] means single character a, b, c. [^abc] means a character except a, b, c. * means matches 0 or more times.) So ([^]]*) means we want the content as group 1, which the content should not contain ]. So right now, !\\[([^]]*), we have matched ![This is title. Let’s continue. ] matches the character ] literally \\( matches the character ( literally We want to skip content before /, vice versa, we accept the characters which are not /, so it should be: [^\\/]*. \\/ matches the character / literally So right now, !\\[([^]]*)]\\([^\\/]*\\/, we have matched ![This is title](directory (contains bracket)/. Let’s continue. We want to keep file name, the content after /, in front of ), which means the content should not contain ). So we need ([^)]*), the content is kept as group 2. In the end, we add \\), matches the character ). So the regex is : !\\[([^]]*)]\\([^\\/]*\\/([^)]*)\\). But sed uses Basic Regular Expressions (BRE) by default, which uses \\( and \\) for group capturing, not just ( and ) as used in Extended Regular Expressions (ERE). So you should be careful when treating ( and ). If you want to match ( literally in sed, just use (. If you need group, use \\(. This is not good as we need to change the regex we created, it might cause mistakes. Good news is sed has a parameter -E to use Extended Regular Expressions. The syntax is: 1sed -E -i.bak 's/!\\[([^]]*)]\\([^\\/]*\\/([^)]*)\\)/{% asset_img \\2 \\1 %}/g' file or 1sed -i.bak 's/!\\[\\([^]]*\\)]([^\\/]*\\/\\([^)]*\\))/{% asset_img \\2 \\1 %}/g' file -i.bak will backup original file into file.bak. 's/old-text/new-text/g', s is the substitute command of set for find and replace. group 1 is ([^]]*), group 2 is ([^)]*) So above command means find old-text and replace file content with new-text, also backup fileinto file.bak. And here is online expression with example. [1]nixCraft - How to use sed to find and replace text in files in Linux / Unix shell [2]Stackoverflow - How to extract string in file and replace specific pattern text [3]Stackoverflow - Sed error “\\1 not defined in the RE” on MacOSX 10.9.5 [4]Stackoverflow - .bash_profile sed: \\1 not defined in the RE","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"},{"name":"Hexo","slug":"Others/Hexo","permalink":"http://bejondshao.github.io/categories/Others/Hexo/"}],"tags":[{"name":"Hexo","slug":"Hexo","permalink":"http://bejondshao.github.io/tags/Hexo/"}]},{"title":"Keycloak配置LDAP(Active Directory)","slug":"Keycloak配置LDAP-Active-Directory","date":"2018-07-18T14:40:00.000Z","updated":"2023-03-02T03:26:34.143Z","comments":true,"path":"2018/07/18/Keycloak配置LDAP-Active-Directory/","link":"","permalink":"http://bejondshao.github.io/2018/07/18/Keycloak%E9%85%8D%E7%BD%AELDAP-Active-Directory/","excerpt":"","keywords":null,"text":"@ Keycloak后台配置如下图,相关内容根据实际情况修改 其中Connection URL中的ip修改一下。 Users DN:根据AD的域定义,能指定到Users目录 Bind DN:填写管理员的mapping。比如这里keycloak1在AD里属于管理员组。 Bind Credential是keycloak1的密码 @ Active Directory创建管理员账户: 在AD中创建用户keycloak1,组设置为Administrators, Domain Admins, Domain Users。如图所示 @ 由于Keycloak要更新AD用户密码,AD要求使用SSL安全连接,所以要配置AD SSL连接。 @ AD配置证书服务 开始菜单->管理工具->服务器管理 角色->添加角色 点击“下一步”,在“服务器角色”,选择“Active Directory 证书服务”,点击“下一步” 点击“下一步”,默认,选择“证书授权” 点击“下一步”,默认,选择“企业”证书 点击“下一步”,默认,选择“根证书” 下一步,默认,选择“创建新的私有秘钥” 下一步,默认内容即可 下一步,证书有效期,5年到99年都可以 下一步,证书数据地址,默认即可 下一步,确认信息,安装 重启Windows Server 2008 @ 安装完证书,将证书导出,供客户端(Keycloak所在的机器)使用 打开一个cmd,执行命令certutil -ca.cert ad-client.crt,到"C:\\Users\\Administrator"文件夹,将ad-client.crt拷贝到Keycloak主机。 @ 开启”对安全通道数据进行数字加密或数字签名“ 开始->管理工具->组策略管理器。然后依次打开”林:bejond.org"->域->bejond.org->Domain Controller->Default Domain Controllers Policy,右键,编辑。 在“组策略管理编辑器”中,依次打开,计算机配置->策略->Windows 设置->本地策略->安全选项,找到”域成员:对安全通道数据进行数字加密或数字签名(始终)“,双击,选择”已启用“。确定。 打开cmd,执行gpupdate,更新域控制器的策略。 @ 在Keycloak主机,打开cmd,执行命令keytool -importcert -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file ad-client.crt。其中%JAVA_HOME%是Java环境变量,如果没有配置或找不到变量,到Java安装目录,定位到cacerts文件,将路径拷贝到命令里就行,比如keytool -importcert -keystore C:\\jdk1.8\\jre\\lib\\security\\cacerts -file ad-client.crt。然后会提示输入证书密码,输入"changeit"。然后会询问是否添加证书,输入"y"即可。 此时,已经配置完成。重启Keycloak。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/tags/DevOps/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"Keycloak配置邮箱和忘记密码功能","slug":"Keycloak配置邮箱和忘记密码功能","date":"2018-07-18T14:17:00.000Z","updated":"2023-03-02T03:26:34.164Z","comments":true,"path":"2018/07/18/Keycloak配置邮箱和忘记密码功能/","link":"","permalink":"http://bejondshao.github.io/2018/07/18/Keycloak%E9%85%8D%E7%BD%AE%E9%82%AE%E7%AE%B1%E5%92%8C%E5%BF%98%E8%AE%B0%E5%AF%86%E7%A0%81%E5%8A%9F%E8%83%BD/","excerpt":"","keywords":null,"text":"服务系统中的发送邮件功能都是依靠某个邮件服务器来发邮件的。一般是用第三方的smtp邮件服务器,比如smtp.gmail.com, smtp.163.com。本文以163邮箱为例。 一、首先,要注册一个163邮箱。Keycloak发送邮件其实是借用这个邮箱发送的。 二、进入Keycloak后台,进入相关realm,Realm Settings -> Email。按照如下图配置: @ Host就是发送邮件服务器,填smtp.163.com。 @ 端口默认是25,如果是ssl则是465 @ From Display Name,发件人姓名 @ From,显示的发件人地址。这个地址会显示在发件人地址,可以是别的邮箱,也可以是不存在的邮箱地址。 @ Reply To,当收件人想要回复邮件时,收件人的名字。 @ Envelop From,表示邮件是由谁发的。这个邮件地址必须和Username一样。 @ Username,真实邮件的发件人,填第一步注册的邮箱。 @ Password,这个密码,有的邮件服务商要求填写邮件密码。而163服务器要求填写授权码。获取授权码见步骤三 三、设定授权码。进入163邮箱,点击右上角设置 -> POP3/SMTP/IMAP。 然后在新页面选中IMAP/SMTP服务 选中后会弹窗,接着下一步,验证身份,设定授权码。授权码会以短信发送给你。这里我认为163设计得很不合理,授权码这类敏感信息应该加密保存,程序不应该能获取到明文,更不应该通过第三方服务(短信服务器)发送,这说明授权码已经暴露了。所以记得把短信删除。 四、将获取的授权码填入步骤二中的Password中。 五、到 http://localhost:8080/auth/realms/test1/login-actions/authenticate?execution=28375a24-caf5-478d-b3af-e665db7956c7&client_id=security-admin-console&tab_id=epQ00ae34Go 点击Forgot Password,会跳转到页面,输入用户邮箱。页面跳转到登录页,说明邮件发送成功。登录刚才用户的邮箱,就可以找到验证邮件。点击其中链接,就跳转到重置密码页。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"},{"name":"Security","slug":"Security","permalink":"http://bejondshao.github.io/tags/Security/"}]},{"title":"Use Maven Profile to Change Configuring during Packaging","slug":"Use-Maven-Profile-to-Change-Configuring-during-Packaging","date":"2018-07-18T10:06:00.000Z","updated":"2023-03-02T03:26:34.203Z","comments":true,"path":"2018/07/18/Use-Maven-Profile-to-Change-Configuring-during-Packaging/","link":"","permalink":"http://bejondshao.github.io/2018/07/18/Use-Maven-Profile-to-Change-Configuring-during-Packaging/","excerpt":"","keywords":null,"text":"We are going to deploy our application to wildfly to cloud server, while we need to set test environment and production environment. It’s complecated to set up double server with different ports, because it means doing the same deployment things twice. One simple way is to deploy the same app in the same wildfly, but with different app names. To achieve this, you can simply rename app.war to newname.war. So the context becomes to newname. You can visit web application through http://localhost:8080/newname. You need to do this each time you do deploy. There’s another elegant way to achieve this. Add jboss-web.xml to WEB-INF and package it to the war. jboss-web.xml looks like this: 123456789<?xml version="1.0" encoding="UTF-8"?><jboss-web xmlns="http://www.jboss.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_5_1.xsd"> <context-root>appname</context-root></jboss-web> And if the war contains resource connecting like database, file system. You probably need to connect to different databases, for databases, we usually put data source in META-INF/persistence.xml, like this: 1<jta-data-source>java:jboss/datasources/DS</jta-data-source> I can’t change it each time do deploy. It’ll be good if the context-root and jta-data-source can be changed during packaging. Maven profile works like a charm. I have to attach document because it explains more details and more complemental. When we looking for solutions we usually google it instead of reading docs, because if we find the right place, it will solve our issue directly, but we might be blind for why and how or some other usages. Reading docs might take much more time and probably you lost in it. It depends on situations. It’s up to you. Back to maven profile, it’s like “pom.xml settings”, during packing, you can choose which profile to use. And packaging the application for you. In this case, we use profile to set property with different values. Remember this, profile can do more than set property values, it can use different jdks to compile, copy different resource files, package for different hosts, etc. I make example for data source. First, create a property in <properties> element. 1234<properties> <base-jta-data-source>java:jboss/datasources/DS</base-jta-data-source></properties> Then create profiles 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263<profiles> <profile> <id>default</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <jta-data-source>${base-jta-data-source}</jta-data-source> <final-artifactId>${project.artifactId}</final-artifactId> </properties> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skip>false</skip> <argLine>-Dfile.encoding=UTF-8</argLine> </configuration> </plugin> <plugin> <groupId>org.jboss.as.plugins</groupId> <artifactId>jboss-as-maven-plugin</artifactId> <inherited>true</inherited> <configuration> <skip>false</skip> </configuration> </plugin> </plugins> <finalName>${project.artifactId}-${project.version}</finalName> </build> </profile> <profile> <!-- To use this profile run command: [mvn clean package -P dev] --> <id>dev</id> <properties> <jta-data-source>${base-jta-data-source}-DEV</jta-data-source> <final-artifactId>${project.artifactId}-dev</final-artifactId> </properties> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skip>false</skip> <argLine>-Dfile.encoding=UTF-8</argLine> </configuration> </plugin> <plugin> <groupId>org.jboss.as.plugins</groupId> <artifactId>jboss-as-maven-plugin</artifactId> <inherited>true</inherited> <configuration> <skip>false</skip> </configuration> </plugin> </plugins> <finalName>${final-artifactId}-${project.version}</finalName> </build> </profile></profiles> Notice <jta-data-source>, <final-artifactId>, they are defined in <profile> element, belongs to each profile, so they can be different values. And in <finalName>, we use final-artifactId and project.version to generate package name. It will be like “mvn-profile-1.0-SNAPSHOT”, “mvn-profile-dev-1.0-SNAPSHOT”. All properties can be used by ${propertyname}. Properties can be used out side of pom.xml. When packaing, maven can filter files and replace ${propertyname} with real value. For example, if we want to change context-root of jboss-web.xml. We can change it like: 1<context-root>${final-artifactId}</context-root> Besides, we need to set filter in pom.xml in <build><plugins><plugin> element: 123456789101112131415161718192021222324252627282930313233<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> <archive> <manifest> <addClasspath>false</addClasspath> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> </manifest> </archive> <webResources> <resource> <directory>${project.build.directory}/generated-web</directory> </resource> <resource> <directory>src/main/web/WEB-INF</directory> <filtering>true</filtering> <targetPath>WEB-INF</targetPath> <includes> <include>jboss-web.xml</include> </includes> </resource> <resource> <directory>src/main/web/WEB-INF</directory> <filtering>false</filtering> <targetPath>WEB-INF</targetPath> </resource> </webResources> </configuration></plugin> maven-war-plugin will collect dependencies, resources and packing the files. Noticing element <filtering>, default is false. It will filter the files and replacing properties. But you should be responsible for files to be filtered. You just include the files that need to be filtered. Other files should be copy no filtering. Because image, certification would be broken after filtering. All codes can be found here. After downloading the module, you can verify this by runningmvn clean package and mvn clean package -P dev to see the differences. Or you can download the packages here.","raw":null,"content":null,"categories":[{"name":"Tools","slug":"Tools","permalink":"http://bejondshao.github.io/categories/Tools/"}],"tags":[{"name":"maven","slug":"maven","permalink":"http://bejondshao.github.io/tags/maven/"}]},{"title":"SCIM(System for Cross-domain Identity Management)","slug":"SCIM-System-for-Cross-domain-Identity-Management","date":"2018-07-06T07:51:00.000Z","updated":"2023-03-02T03:26:34.194Z","comments":true,"path":"2018/07/06/SCIM-System-for-Cross-domain-Identity-Management/","link":"","permalink":"http://bejondshao.github.io/2018/07/06/SCIM-System-for-Cross-domain-Identity-Management/","excerpt":"","keywords":null,"text":"@ SCIM(System for Cross-domain Identity Management) 2是一套开放式API,用于管理身份信息。 @ SCIM意在更方便的管理用户身份和web服务,尤其是云服务。其意在减少构建用户管理模块的开销,减少工作量。 @ Model SCIM 2.0是以Resource为基础设计的一套模型。Resource有id, externalId和meta属性(meta属性存储记录的基本信息,比如resourceType, created, lastModified, location, version等)。根据RFC7643定义的User, Group继承Resource,具有额外的属性,EnterpriseUser继承User。 @ User举例 1234567891011121314151617181920212223242526272829303132333435{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "id":"2819c223-7f76-453a-919d-413861904646", "externalId":"bjensen", "meta":{ "resourceType": "User", "created":"2011-08-01T18:29:49.793Z", "lastModified":"2011-08-01T18:29:49.793Z", "location":"https://example.com/v2/Users/2819c223...", "version":"W\\/\\"f250dd84f0671c3\\"" }, "name":{ "formatted": "Ms. Barbara J Jensen, III", "familyName": "Jensen", "givenName": "Barbara", "middleName": "Jane", "honorificPrefix": "Ms.", "honorificSuffix": "III" }, "userName":"bjensen", "phoneNumbers":[ { "value":"555-555-8377", "type":"work" } ], "emails":[ { "value":"[email protected]", "type":"work", "primary": true } ]} @ Group表示user的集合,group也可以包含其他group。 12345678910111213141516171819202122232425{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"], "id":"e9e30dba-f08f-4109-8486-d5c6a331660a", "displayName": "Tour Guides", "members":[ { "value": "2819c223-7f76-453a-919d-413861904646", "$ref": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646", "display": "Babs Jensen" }, { "value": "902c246b-6245-4190-8e05-00816be7344a", "$ref": "https://example.com/v2/Users/902c246b-6245-4190-8e05-00816be7344a", "display": "Mandy Pepperidge" } ], "meta": { "resourceType": "Group", "created": "2010-01-23T04:56:22Z", "lastModified": "2011-05-13T04:42:34Z", "version": "W\\/\\"3694e05e9dff592\\"", "location": "https://example.com/v2/Groups/e9e30dba-f08f-4109-8486-d5c6a331660a" }} @ Operations SCIM提供几个简单的REST API,用于管理资源 Create: POST https://example.com/{v}/{resource} Read: GET https://example.com/{v}/{resource}/{id} Replace: PUT https://example.com/{v}/{resource}/{id} Delete: DELETE https://example.com/{v}/{resource}/{id} Update: PATCH https://example.com/{v}/{resource}/{id} Search: GET https://example.com/{v}/{resource}?filter={attribute}{op}{value}&sortBy={attributeName}&sortOrder={ascending|descending} Bulk(批量): POST https://example.com/{v}/Bulk @ 为了简化沟通流程,SCIM提供三个端点接口,支持特定的属性和特性。 GET /ServiceProviderConfig 验证数据合法性,指定验证信息,数据类型。 GET /ResourceTypes 发现可用的资源。 GET /Schemas 读取资源和扩展的属性。 @ Create Request 创建一个User。下面例子请求URL包含version,可以看出SCIM API支持多个版本的服务,可以通过ServiceProviderConfig查找可用的服务。 1234567891011121314151617POST /v2/Users HTTP/1.1Accept: application/jsonAuthorization: Bearer h480djs93hd8Host: example.comContent-Length: ...Content-Type: application/json{ "schemas":["urn:ietf:params:scim:schemas:core:2.0:User"], "externalId":"bjensen", "userName":"bjensen", "name":{ "familyName":"Jensen", "givenName":"Barbara" }} @ Create Response 预定的响应内容和HTTP 201表明Resource创建成功。id和meta数据也同时返回,location表示可以在那里获取到用户。 1234567891011121314151617181920212223HTTP/1.1 201 CreatedContent-Type: application/scim+jsonLocation: https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646ETag: W/"e180ee84f0671b1"{ "schemas":["urn:ietf:params:scim:schemas:core:2.0:User"], "id":"2819c223-7f76-453a-919d-413861904646", "externalId":"bjensen", "meta":{ "resourceType":"User", "created":"2011-08-01T21:32:44.882Z", "lastModified":"2011-08-01T21:32:44.882Z", "location": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646", "version":"W\\/\\"e180ee84f0671b1\\"" }, "name":{ "familyName":"Jensen", "givenName":"Barbara" }, "userName":"bjensen"} @ Get Request 使用HTTP GET发送到端点,查询资源 12345GET /v2/Users/2819c223-7f76-453a-919d-413861904646 HTTP/1.1Host: example.comAccept: application/scim+jsonAuthorization: Bearer h480djs93hd8 @ Create Response 返回GET获取的资源。Etag头用于阻止并发修改资源。 12345678910111213141516171819202122232425262728293031323334353637383940HTTP/1.1 201 Created HTTP/1.1Content-Type: application/scim+jsonLocation: https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646ETag: W/"e180ee84f0671b1"{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "id":"2819c223-7f76-453a-919d-413861904646", "externalId":"bjensen", "meta":{ "resourceType": "User", "created":"2011-08-01T18:29:49.793Z", "lastModified":"2011-08-01T18:29:49.793Z", "location":"https://example.com/v2/Users/2819c223...", "version":"W\\/\\"f250dd84f0671c3\\"" }, "name":{ "formatted": "Ms. Barbara J Jensen, III", "familyName": "Jensen", "givenName": "Barbara", "middleName": "Jane", "honorificPrefix": "Ms.", "honorificSuffix": "III" }, "userName":"bjensen", "phoneNumbers":[ { "value":"555-555-8377", "type":"work" } ], "emails":[ { "value":"[email protected]", "type":"work", "primary": true } ]} @ Filter Request 通过加查询条件,查询资源列表。SCIM支持equals, contains, starts with等等。对查询结果还可以排序,可以返回特定的属性以及返回指定数量的资源。 https://example.com/{resource}?filter={attribute} {op} {value} & sortBy={attributeName}&sortOrder={ascending|descending}&attributes={attributes} https://example.com/Users?filter=title pr and userType eq “Employee”&sortBy=title&sortOrder=ascending&attributes=title,username @ Filter Response 1234567891011121314151617{ "schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"], "totalResults":2, "Resources":[ { "id":"c3a26dd3-27a0-4dec-a2ac-ce211e105f97", "title":"Assistant VP", "userName":"bjensen" }, { "id":"a4a25dd3-17a0-4dac-a2ac-ce211e125f57", "title":"VP", "userName":"jsmith" } ]} @ SCIM不涉及验证(Authentication)和授权(Authorization),想要实现验证和授权功能,参考RFC 7644 2. Authentication and Authorization. [1] simplecloud SCIM [2] RFC 7644","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"SCIM","slug":"SCIM","permalink":"http://bejondshao.github.io/tags/SCIM/"},{"name":"Identity Management","slug":"Identity-Management","permalink":"http://bejondshao.github.io/tags/Identity-Management/"}]},{"title":"NoClassDefFoundError: Failed to link org/jboss/resteasy/plugins/providers/yaml/i18n/LogMessages","slug":"NoClassDefFoundError-Failed-to-link-org-jboss-resteasy-plugins-providers-yaml-i18n-LogMessages","date":"2018-06-22T06:48:00.000Z","updated":"2023-03-02T03:26:34.189Z","comments":true,"path":"2018/06/22/NoClassDefFoundError-Failed-to-link-org-jboss-resteasy-plugins-providers-yaml-i18n-LogMessages/","link":"","permalink":"http://bejondshao.github.io/2018/06/22/NoClassDefFoundError-Failed-to-link-org-jboss-resteasy-plugins-providers-yaml-i18n-LogMessages/","excerpt":"","keywords":null,"text":"I’m using wildfly10.1.0.Final and try to passing byte[] to REST API. It throws error. 10:38:57,445 ERROR [io.undertow.request] (default task-11) UT005023: Exception handling request to /app/rest/searchUser: java.lang.NoClassDefFoundError: Failed to link org/jboss/resteasy/plugins/providers/yaml/i18n/LogMessages (Module “org.jboss.resteasy.resteasy-yaml-provider:main” from local module loader @2f490758 (finder: local module finder @101df177 (roots: /home/bejond/code/server/wildfly-10.1.0.Final/modules,/home/bejond/code/server/wildfly-10.1.0.Final/modules/system/layers/base/.overlays/layer-base-wildfly-10-weld-2.4,/home/bejond/code/server/wildfly-10.1.0.Final/modules/system/layers/base))): org/jboss/logging/BasicLogger at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.jboss.modules.ModuleClassLoader.defineClass(ModuleClassLoader.java:446) at org.jboss.modules.ModuleClassLoader.loadClassLocal(ModuleClassLoader.java:274) at org.jboss.modules.ModuleClassLoader1.loadClassLocal(ModuleClassLoader.java:78)atorg.jboss.modules.Module.loadModuleClass(Module.java:606)atorg.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)atorg.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363)atorg.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351)atorg.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:93)atorg.jboss.resteasy.plugins.providers.YamlProvider.readFrom(YamlProvider.java:60)atorg.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.readFrom(AbstractReaderInterceptorContext.java:61)atorg.jboss.resteasy.core.interception.ServerReaderInterceptorContext.readFrom(ServerReaderInterceptorContext.java:60)atorg.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:53)atorg.jboss.resteasy.security.doseta.DigitalVerificationInterceptor.aroundReadFrom(DigitalVerificationInterceptor.java:34)atorg.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:55)atorg.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor.aroundReadFrom(GZIPDecodingInterceptor.java:59)atorg.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:55)atorg.jboss.resteasy.core.MessageBodyParameterInjector.inject(MessageBodyParameterInjector.java:151)atorg.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:91)atorg.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:114)atorg.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:295)atorg.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:249)atorg.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:236)atorg.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:402)atorg.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:209)atorg.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221)atorg.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)atorg.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)atjavax.servlet.http.HttpServlet.service(HttpServlet.java:790)atio.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)atio.undertow.servlet.handlers.FilterHandler1.loadClassLocal(ModuleClassLoader.java:78) at org.jboss.modules.Module.loadModuleClass(Module.java:606) at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190) at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363) at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351) at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:93) at org.jboss.resteasy.plugins.providers.YamlProvider.readFrom(YamlProvider.java:60) at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.readFrom(AbstractReaderInterceptorContext.java:61) at org.jboss.resteasy.core.interception.ServerReaderInterceptorContext.readFrom(ServerReaderInterceptorContext.java:60) at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:53) at org.jboss.resteasy.security.doseta.DigitalVerificationInterceptor.aroundReadFrom(DigitalVerificationInterceptor.java:34) at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:55) at org.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor.aroundReadFrom(GZIPDecodingInterceptor.java:59) at org.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:55) at org.jboss.resteasy.core.MessageBodyParameterInjector.inject(MessageBodyParameterInjector.java:151) at org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:91) at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:114) at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:295) at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:249) at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:236) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:402) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:209) at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221) at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) at io.undertow.servlet.handlers.FilterHandler1.loadClassLocal(ModuleClassLoader.java:78)atorg.jboss.modules.Module.loadModuleClass(Module.java:606)atorg.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)atorg.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363)atorg.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351)atorg.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:93)atorg.jboss.resteasy.plugins.providers.YamlProvider.readFrom(YamlProvider.java:60)atorg.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.readFrom(AbstractReaderInterceptorContext.java:61)atorg.jboss.resteasy.core.interception.ServerReaderInterceptorContext.readFrom(ServerReaderInterceptorContext.java:60)atorg.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:53)atorg.jboss.resteasy.security.doseta.DigitalVerificationInterceptor.aroundReadFrom(DigitalVerificationInterceptor.java:34)atorg.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:55)atorg.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor.aroundReadFrom(GZIPDecodingInterceptor.java:59)atorg.jboss.resteasy.core.interception.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:55)atorg.jboss.resteasy.core.MessageBodyParameterInjector.inject(MessageBodyParameterInjector.java:151)atorg.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:91)atorg.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:114)atorg.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:295)atorg.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:249)atorg.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:236)atorg.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:402)atorg.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:209)atorg.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:221)atorg.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)atorg.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)atjavax.servlet.http.HttpServlet.service(HttpServlet.java:790)atio.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)atio.undertow.servlet.handlers.FilterHandlerFilterChainImpl.doFilter(FilterHandler.java:129) at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:226) at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) at io.undertow.servlet.handlers.FilterHandlerFilterChainImpl.doFilter(FilterHandler.java:131)atorg.omnifaces.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:124)atorg.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:108)atio.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)atio.undertow.servlet.handlers.FilterHandlerFilterChainImpl.doFilter(FilterHandler.java:131) at org.omnifaces.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:124) at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:108) at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) at io.undertow.servlet.handlers.FilterHandlerFilterChainImpl.doFilter(FilterHandler.java:131)atorg.omnifaces.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:124)atorg.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:108)atio.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)atio.undertow.servlet.handlers.FilterHandlerFilterChainImpl.doFilter(FilterHandler.java:131) at org.picketlink.http.internal.SecurityFilter.processRequest(SecurityFilter.java:356) at org.picketlink.http.internal.SecurityFilter.performOutboundProcessing(SecurityFilter.java:241) at org.picketlink.http.internal.SecurityFilter.doFilter(SecurityFilter.java:196) at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50) at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292) at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81) at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138) at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135) at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272) at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104) at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202) at io.undertow.server.HttpServerExchange1.run(HttpServerExchange.java:805)atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)atjava.util.concurrent.ThreadPoolExecutor1.run(HttpServerExchange.java:805) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor1.run(HttpServerExchange.java:805)atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)atjava.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) This error is not related with parsing or unmarshalling. I find that LogMessage is located in wildfly-10.1.0.Final/modules/system/layers/base/org/jboss/resteasy/resteasy-jaxrs/main/resteasy-client-3.0.19.Final.jar/org/jboss/resteasy/client/jaxrs/i18n. It should be found during wildfly startup. I look up google and find little about it. And here seems related with the issue. I stop trying and unzip a wildfly11.0.0.Final and the NoClassDefFoundError is gone, shows the real error info, which is what I need. What I’m saying is that if you met this kind of issue. Stop searching, you can: Upgrade to latest wildfly. If you can’t upgrade. You can try to reach wildfly developer, it probably takes long time to get fixed, cause if you have worked on open source software, you will konw how much work to do before fixing the new issue:joy:. Go deep into wildfly classpath and classloader, write a classloader to load the package you need. This is still not a good solution cause you probably need to add module on wildfly, which is beyond of your application.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"服务器","slug":"Java/服务器","permalink":"http://bejondshao.github.io/categories/Java/%E6%9C%8D%E5%8A%A1%E5%99%A8/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Wildfly","slug":"Wildfly","permalink":"http://bejondshao.github.io/tags/Wildfly/"}]},{"title":"Wildfly10.1.0.Final报ResteasyClientBuilder.execuetSrevice NoSuchMethodError问题","slug":"Wildfly10-1-0-Final报ResteasyClientBuilder-executeService-NoSuchMethodError问题","date":"2018-06-15T06:31:00.000Z","updated":"2023-03-02T03:26:34.206Z","comments":true,"path":"2018/06/15/Wildfly10-1-0-Final报ResteasyClientBuilder-executeService-NoSuchMethodError问题/","link":"","permalink":"http://bejondshao.github.io/2018/06/15/Wildfly10-1-0-Final%E6%8A%A5ResteasyClientBuilder-executeService-NoSuchMethodError%E9%97%AE%E9%A2%98/","excerpt":"","keywords":null,"text":"ResteasyClientBuilder是一个支持Client pool,SSL context,异步执行的HttpClient Builder。在使用时遇到了奇怪的事情。我在test包下使用 1new ResteasyClientBuilder().executorService(Executors.newCachedThreadPool()); 就没问题,但是在main包下使用上述代码,就出现: Caused by: org.jboss.resteasy.spi.UnhandledException: java.lang.NoSuchMethodError: org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder.executorService(Ljava/util/concurrent/ExecutorService;)Ljavax/ws/rs/client/ClientBuilder; at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:78) at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:222) at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:179) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:422) NoSuchMethodError。我怀疑是项目包依赖的问题,去pom.xml发现依赖是 12345<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> <scope>provided</scope></dependency> 之所以用<scope>provided</scope>是因为resteasy-client是Wildfly自带的组件,所以打包项目时不包含resteasy-client,带了反而会出错。 之所以报NoSuchMethodError是因为Wildfly自带的resteasy-client在/home/bejond/codewildfly-10.1.0.Final/modules/system/layers/base/org/jboss/resteasy/resteasy-jaxrs/main/resteasy-client-3.0.19.Final.jar,版本比较旧,是3.0.19.Final。 这个版本里并没有executorService(ExecutorService executorService)。实际上是ResteasyClientBuilder的父类ClientBuilder并没有定义executorService(ExecutorService executorService)。 而test下能正常测试是因为使用的新版本的resteasy-client,我使用的是resteasy-client-3.5.0.Final。而自动化测试是不依赖Web服务器的,所以能正常运行。 pom.xml依赖没写<version>是依赖了父pom。子pom如果要使用别的版本的依赖,加上<version>即可: 1234567<dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-client</artifactId> <!-- wildfly 10.1.0.Final使用的resteasy-jarx里面的resteasy-client是3.0.19.Final --> <version>3.0.19.Final</version> <scope>provided</scope></dependency> Stackoverflow RESTEasy Client + NoSuchMethodError建议下载最新resteasy-jaxrx包,替换wildfly-10.1.0.Final/modules/system/layers/base/org/jboss/resteasy/resteasy-jaxrs所有的组件。我并没有这么做,一来不确定是否有兼容性问题(Java向下兼容做得很好,一般不会有这个问题。但就怕遇到,排查起来很麻烦),二来加大实施成本。所以我使用降级的方式来做,其实也不算降级,就是使用Wildfly10.1.0.Final自带的包。 这样调整后进入ResteasyClientBuilder就找不到executorService(ExecutorService executorService)了。但是打开ResteasyClientBuilder的源码,发现提示编译错误。 点击ClientBuilder跳到源码发现版本是2.1 2.1版本里的ClientBuilder定义新的抽象方法executorService(ExecutorService executorService),所以提示未实现抽象方法或者将ResteasyClientBuilder改为抽象类错误。 是因为Intellij项目library依赖配置问题,到项目.idea/library下,把Maven__org_jboss_spec_javax_ws_rs_jboss_jaxrs_api_2_1_spec_1_0_0_Final.xml删掉即可。 然后Intellij会自动根据maven依赖增加Maven__org_jboss_spec_javax_ws_rs_jboss_jaxrs_api_2_0_spec_1_0_1_Final.xml文件。 调整好依赖后,test里的测试代码就会对executorService(ExecutorService executorService)标红了。需要将项目代码和test的代码修改为 1new ResteasyClientBuilder().asyncExecutor(Executors.newCachedThreadPool()); 需要注意,asyncExecutor(ExecutorService asyncExecutor)在新版本的resteasy-client包里已经过期,用executorService(ExecutorService executorService)代替。从这个例子也能看出程序设计的问题,低版本方法名定义得随意,到了后期调整为新的名字。实际上executorService直接调用的asyncExecutor,又将asyncExecutor标记为Deprecated。 补充: 在这个例子里如果不使用executorService(ExecutorService executorService),ResteasyClient.build()就会创建10线程固定大小的线程池。那么设定connectionPoolSize(int size)就不会起作用。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"服务器","slug":"Java/服务器","permalink":"http://bejondshao.github.io/categories/Java/%E6%9C%8D%E5%8A%A1%E5%99%A8/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Wildfly","slug":"Wildfly","permalink":"http://bejondshao.github.io/tags/Wildfly/"},{"name":"resteasy-jaxrs","slug":"resteasy-jaxrs","permalink":"http://bejondshao.github.io/tags/resteasy-jaxrs/"}]},{"title":"Intellij debug模式启动很慢调整","slug":"Intellij-debug模式启动很慢调整","date":"2018-05-30T12:02:00.000Z","updated":"2023-03-02T03:26:34.088Z","comments":true,"path":"2018/05/30/Intellij-debug模式启动很慢调整/","link":"","permalink":"http://bejondshao.github.io/2018/05/30/Intellij-debug%E6%A8%A1%E5%BC%8F%E5%90%AF%E5%8A%A8%E5%BE%88%E6%85%A2%E8%B0%83%E6%95%B4/","excerpt":"","keywords":null,"text":"移除不需要的断点,在debug窗口,点击在Stop按钮下有个View breakpoints按钮,可以移除断点。也可以编辑当前project的.idea/workspace.xml文件,找到method_breakpoints节点,移除不需要的节点。可以先mute breakpoints启动,速度提升很多。 检查debug窗口,settings,“Show values inline”(在代码后面动态显示变量内容),“Show method return values”(显示方法返回的值),酌情关闭。开启这两个选项会有性能消耗。 Settings -> Debugger -> Data Views -> Java,“Enable alternative view for Collections classes”(对集合有额外的展示界面)和"Enable ‘toString()’ object view"(展示object的toString()方法)酌情关闭。这两个也会有性能消耗。 最小化Memory小窗。这个Memory小窗是用来监测运行时变量所占内存的,一般不必开启,默认是最小化的。 获取hostname,然后在/etc/hosts里添加 12127.0.0.1 your_host_name.local::1 your_host_name.local 参考 [1] Intellij Support: Java: slow performance or hangups when starting debugger and stepping [2] Stackoverflow: IntelliJ IDEA debugger is too slow to start on macOS","raw":null,"content":null,"categories":[{"name":"Tools","slug":"Tools","permalink":"http://bejondshao.github.io/categories/Tools/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Intellij","slug":"Intellij","permalink":"http://bejondshao.github.io/tags/Intellij/"}]},{"title":"Prometheus metric names定义规则","slug":"Prometheus-metric-names定义规则","date":"2018-05-16T10:13:00.000Z","updated":"2023-03-02T03:26:34.190Z","comments":true,"path":"2018/05/16/Prometheus-metric-names定义规则/","link":"","permalink":"http://bejondshao.github.io/2018/05/16/Prometheus-metric-names%E5%AE%9A%E4%B9%89%E8%A7%84%E5%88%99/","excerpt":"","keywords":null,"text":"Metrics定义规则 Metrics名字以应用名为命名空间,即该metric是从哪个应用来的,比如: pms_reservations_total crs_failed_requests_total Metrics必须有确定的单位,并且是基本单位,比如seconds, bytes, meters。而不是milliseconds, megabytes, kilometers。 每个单位都应该用复数,并且可以加描述性的后缀,比如total: http_request_duration_seconds node_memory_usage_bytes http_requests_total(针对累加性质的计数集体) Metrics应该代表一个整体性的描述,比如: 请求时长 数据bytes大小 瞬时资源使用百分比 sum()或者avg()之类的指标用于创建metric是很好的方式。Metric应该是有特定意义的词汇。如果一个metric无法描述清数据类型,那就分成几个metrics。 Labels 使用labels区分metric不同的特点,比如: apt_http_requests_total - 区别不同的请求类型:type="create|update|delete" api_request_duration_seconds - 区别请求的阶段:stage="extract|transform|load" 不要把label放到metric name中,这会造成冗余和混乱。 注意:每一个独立的lable键值对组合都代表一个新的time series,这很有可能增加数据量。不要用labels存储数据量大的指标,比如userId, email等。也就是说labels一般用作内容可能性比较少的指标。 基本单位 Prometheus使用部分基本单位列表: Time: seconds Temperature: celsius Length: meters Bytes: bytes Bits: bytes Percent: ratio() (值为0~1, ratio通常不用做后缀,但是A_per_B类型除外,比如disk_usage_ratio会这么使用) Voltage: volts Electric current: amperes Energy: joules Weight: grams","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"}],"tags":[{"name":"Prometheus","slug":"Prometheus","permalink":"http://bejondshao.github.io/tags/Prometheus/"},{"name":"Metric names","slug":"Metric-names","permalink":"http://bejondshao.github.io/tags/Metric-names/"}]},{"title":"Ubuntu 16.04 Takes Too Long to Boot","slug":"Ubuntu-16-04-Takes-Too-Long-to-Boot","date":"2018-05-10T02:40:00.000Z","updated":"2023-03-02T03:26:34.203Z","comments":true,"path":"2018/05/10/Ubuntu-16-04-Takes-Too-Long-to-Boot/","link":"","permalink":"http://bejondshao.github.io/2018/05/10/Ubuntu-16-04-Takes-Too-Long-to-Boot/","excerpt":"","keywords":null,"text":"This issue might happen to any ubuntu versions. It happends ubuntu 16.04 is widely used. It takes around 1 minute to boot. I’m afraid I’m using a fake ubuntu, especially a fake xubuntu😂. Here are some ways to speed up booting: Check out services that start up on booting. $ sudo systemd-analyze blame And the list: 123456789101112131415161718192021222325.661s apt-daily.service19.036s apt-daily-upgrade.service 8.411s vmware-USBArbitrator.service 8.395s gpu-manager.service 8.390s ModemManager.service 7.347s dev-sda9.device 6.647s NetworkManager-wait-online.service 6.459s grub-common.service 6.122s alsa-restore.service 5.664s NetworkManager.service 5.459s accounts-daemon.service 5.325s nmbd.service 4.398s snapd.service 4.384s teamviewerd.service 4.186s apport.service 4.180s systemd-logind.service 4.010s networking.service 3.958s lm-sensors.service 3.926s rsyslog.service 2.873s winbind.service 2.816s avahi-daemon.service 2.723s udisks2.service 2.549s thermald.service @ apt-daily.service This is Debian bug #844453. apt-daily.service shouldn’t be run during boot, but only some time afterward. One workaround is edit apt-daily.timer $ sudo systemctl edit apt-daily.timer and paste the following text into the editor window: 123456# apt-daily timer configuration override[Timer]OnBootSec=15minOnUnitActiveSec=1dAccuracySec=1hRandomizedDelaySec=30min This changes the “timer” that triggers apt-daily.service to run at a random time between 15 min and 45 min after boot. Attention: My system failed to boot after doing below /etc/systemd/system.conf actions, please prepare a USB installation before doing this. If it fails, you can use live system to revert, good luck😂 And for others recommendations, I also change /etc/systemd/system.conf file. Uncomment 12#DefaultTimeoutStartSec=90s#DefaultTimeoutStopSec=90s and change to 12DefaultTimeoutStartSec=10sDefaultTimeoutStopSec=10s @ apt-daily-upgrade.service helps daily apt upgrade and clean. I don’t see I need to enable it. So I disable it by: $ sudo systemctl disable apt-daily-upgrade.service or you can also treat this service just like apt-daily.service by running: $ sudo systemctl edit apt-daily-upgrade.timer and paste settings above. @ For vmware-USBArbitrator.service I tried to disable it but failed. I disabled vmware.service and vmware-workstation-server.service If your booting is extremely slow, like several minutes. It probably has problem about disk alaising. Please refer here. References: [1] Stackoverflow [2] Stackoverflow [3] systemctl mask vs systemctl disable Extends: [1] systemctl 命令完全指南","raw":null,"content":null,"categories":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/categories/Linux/"},{"name":"Ubuntu","slug":"Linux/Ubuntu","permalink":"http://bejondshao.github.io/categories/Linux/Ubuntu/"}],"tags":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/tags/Linux/"},{"name":"Ubuntu","slug":"Ubuntu","permalink":"http://bejondshao.github.io/tags/Ubuntu/"}]},{"title":"CentOS报错: Could not resolve host: mirrorlist.centos.org; Unknown error","slug":"CentOS报错-Could-not-resolve-host-mirrorlist-centos-org-Unknown-error","date":"2018-05-09T02:40:00.000Z","updated":"2023-03-02T03:26:34.074Z","comments":true,"path":"2018/05/09/CentOS报错-Could-not-resolve-host-mirrorlist-centos-org-Unknown-error/","link":"","permalink":"http://bejondshao.github.io/2018/05/09/CentOS%E6%8A%A5%E9%94%99-Could-not-resolve-host-mirrorlist-centos-org-Unknown-error/","excerpt":"","keywords":null,"text":"由于其他错误,执行了 12$ sudo yum clean metadata$ sudo yum clean all 在更新资源时报 123456789101112131415161718192021222324252627Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=stock32 error was14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Unknown error" One of the configured repositories failed (Unknown),and yum doesn't have enough cached data to continue. At this point the onlysafe thing yum can do is fail. There are a few ways to work "fix" this: 1. Contact the upstream for the repository and get them to fix the problem. 2. Reconfigure the baseurl/etc. for the repository, to point to a working upstream. This is most often useful if you are using a newer distribution release than is supported by the repository (and the packages for the previous distribution release still work). 3. Disable the repository, so yum won't use it by default. Yum will then just ignore the repository until you permanently enable it again or use --enablerepo for temporary usage: yum-config-manager --disable <repoid> 4. Configure the failing repository to be skipped, if it is unavailable. Note that yum will try to contact the repo. when it runs most commands, so will have to try and fail each time (and thus. yum will be be much slower). If it is a very temporary problem though, this is often a nice compromise: yum-config-manager --save --setopt=<repoid>.skip_if_unavailable=true 配置下网络即可: 查看网卡配置文件: 12$ cd /etc/sysconfig/network-scripts$ ls 12345678910ifcfg-ens32 ifdown-post ifup-eth ifup-sitifcfg-ens32.bak ifdown-ppp ifup-ib ifup-Teamifcfg-lo ifdown-routes ifup-ippp ifup-TeamPortifdown ifdown-sit ifup-ipv6 ifup-tunnelifdown-bnep ifdown-Team ifup-isdn ifup-wirelessifdown-eth ifdown-TeamPort ifup-plip init.ipv6-globalifdown-ib ifdown-tunnel ifup-plusb network-functionsifdown-ippp ifup ifup-post network-functions-ipv6ifdown-ipv6 ifup-aliases ifup-pppifdown-isdn ifup-bnep ifup-routes 第一个ifcfg-ens32就是网卡配置文件,不同机器略有不同。 2. 备份: 1$ sudo cp /etc/sysconfig/network-scripts/ifcfg-ens32 /etc/sysconfig/network-scripts/ifcfg-ens32.bak 编辑,然后修改内容。(内容大致如下) 123456789101112131415161718192021TYPE=EthernetBOOTPROTO=staticIPADDR=192.168.1.74GATEWAY=192.168.1.1NETMASK=255.255.255.0DNS1=8.8.8.8DEFROUTE=yesPEERDNS=yesPEERROUTES=yesIPV4_FAILURE_FATAL=noIPV6INIT=yesIPV6_AUTOCONF=yesIPV6_DEFROUTE=yesIPV6_PEERDNS=yesIPV6_PEERROUTES=yesIPV6_FAILURE_FATAL=noIPV6_ADDR_GEN_MODE=stable-privacyNAME=ens32UUID=fbe7146b-693d-4047-b73c-fd685a76337bDEVICE=ens32ONBOOT=yes 针对动态配置,需要设置: 12BOOTPROTO=dhcpONBOOT=yes 针对静态配置,需要设置: 12BOOTPROTO=staticONBOOT=yes 静态配置设置固定IP,网关,DNS: 1234IPADDR=192.168.1.74GATEWAY=192.168.1.1NETMASK=255.255.255.0DNS1=8.8.8.8 重启网络服务并更新资源 12$ sudo systemctl restart network$ sudo yum update 参考文章: [1] CentOS报错","raw":null,"content":null,"categories":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/categories/Linux/"},{"name":"CentOS","slug":"Linux/CentOS","permalink":"http://bejondshao.github.io/categories/Linux/CentOS/"}],"tags":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/tags/Linux/"},{"name":"CentOS","slug":"CentOS","permalink":"http://bejondshao.github.io/tags/CentOS/"}]},{"title":"Keycloak和Kibana集成实现单点登录","slug":"Keycloak和Kibana集成实现单点登录","date":"2018-04-09T08:49:00.000Z","updated":"2023-03-02T03:26:34.128Z","comments":true,"path":"2018/04/09/Keycloak和Kibana集成实现单点登录/","link":"","permalink":"http://bejondshao.github.io/2018/04/09/Keycloak%E5%92%8CKibana%E9%9B%86%E6%88%90%E5%AE%9E%E7%8E%B0%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95/","excerpt":"","keywords":null,"text":"Elasticsearch Elasticsearch是一个分布式, 支持RESTful接口查询和分析的引擎, 用于解决不断增长的数据和用例。 作为Elastic Stack的核心存储数据。 Es提供多种查询方式, 聚合细化查询粒度。 可以自动检查结点健壮性。 Es可以做到应用查询, 安全分析, 记录日志, 监测, 警报, 生成报告等。 另外Es还可以和Hadoop结合使用。 安装Elasticsearch 到Elasticsearch下载页下载zip包,当前版本6.2.3。 下载zip包好处是解压到本地, 配置文件可以放在用户目录, 启动方便, 重做系统也不会丢失配置。 当然如果是服务器部署, 应该下载对应的安装包, 方便安装服务。 进入elasticsearch/bin目录, 命令行启动elasticsearch。 待启动完成, 访问http://localhost:9200 。 看到如下所示基本信息表明启动成功。 Kibana Kibana将Es的数据以友好的可视化方式展示, 比如脂肪图, 曲线图, 饼图, 地理图。 Kibana聚合了Es的功能, 并具备基于时间的分析功能。 安装 到Kibana下载页下载zip包, 当前版本6.2.3。 进入kibana/bin目录, 启动kibana。 待启动完成,访问http://localhost:5601即可。 Keycloak保护Kibana 工作流程 外部请求被keycloak proxy拦截。 keycloak proxy根据它的配置决定请求是否需要验证。 如果需要验证, keycloak proxy将请求重定向到keycloak的登录页面。 成功登录后, 将请求发送到kibana。 Keycloak配置client 在Keycloak后台创建client, 名为kibana。 Root URL填keycloak proxy监听的地址, 如http://localhost:8081 开启Authorization Enabled, 保存, 用于验证客户端。 安装keycloak proxy 下载keycloak proxy 3.4.3到本地, 解压。 在keycloak-proxy-3.4.3.Final/bin目录下创建proxy.json文件 123456789101112131415161718192021222324252627282930{ "target-url": "http://localhost:5601", "bind-address": "0.0.0.0", "http-port": "8081", "applications": [ { "base-path": "/", "error-page": "/error.html", "adapter-config": { "realm": "abc", "resource": "kibana", "auth-server-url": "http://localhost:8080/auth", "ssl-required" : "external", "principal-attribute": "name", "credentials": { "secret": "7aa8d667-2ae1-4ee9-b9b8-eb94b317b649" } } , "constraints": [ { "pattern": "/*", "roles-allowed": [ "user" ] } ] } ]} target-url: kibana后台的地址 bind-address: 绑定keycloak proxy的地址, 默认localhost http-port: keycloak proxy监听的端口 base-path: 要保护的应用的路径,必须以"/"开头 resource: keycloak创建的client id auth-server-url: keycloak验证地址 credentials: 客户端验证的方式, 如果是secret, secret的密钥从keycloak cline -> Credentials获得, 见下图 constrainsts: 过滤条件 pattern: 过滤不同路径下的内容 roles-allowed: 具有roles-allowed里的role的用户才有权限访问pattern下的资源 配置好proxy.json后, 在bin下执行 $ java -jar launcher.jar 验证登录 访问http://localhost:8081, keycloak proxy检测到当前用户未登录, 会跳转到keycloak登录界面。 输入用户名密码, 验证成功后即调回keycloak proxy。 keycloak proxy负责转发到kibana。 可以看到浏览器地址为localhost:8081, 而不是localhost:5601。 遗留问题 Kibana没有验证功能, 因此也没有登出功能。 只能在Keycloak中Users -> Someuser -> Sessions点击Logout all sessions尝试登出。 但是点击后在keycloak proxy console则报UT005071: Undertow request failed HttpServerExchange异常, 该问题在Keycloak-3311已经提及, 但是至今未修复。 Keycloak proxy暂时只能起到定向到keycloak登录的功能, 对于鉴权还做得不好, 任何一个在Realm里的用户, 即便没有roles_allowed里的role, 也能访问登录后的kibana界面, 详见Keycloak-7120","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"},{"name":"Kibana","slug":"Kibana","permalink":"http://bejondshao.github.io/tags/Kibana/"},{"name":"Elasticsearch","slug":"Elasticsearch","permalink":"http://bejondshao.github.io/tags/Elasticsearch/"},{"name":"Keycloak proxy","slug":"Keycloak-proxy","permalink":"http://bejondshao.github.io/tags/Keycloak-proxy/"}]},{"title":"Java 8 新特性","slug":"Java-8-新特性","date":"2018-04-09T06:27:00.000Z","updated":"2023-03-02T03:26:34.104Z","comments":true,"path":"2018/04/09/Java-8-新特性/","link":"","permalink":"http://bejondshao.github.io/2018/04/09/Java-8-%E6%96%B0%E7%89%B9%E6%80%A7/","excerpt":"","keywords":null,"text":"Lambda表达式和函数式接口 Lambda表达式(也叫闭包),最简单的形式可以用逗号分隔的参数列表, -> 符号和功能语句块来表示。 语法如下: 1234(parameters) -> expression或(parameters) -> {statements;} 例如: 1Arrays.asList("a", "b", "c").forEach((String e) -> System.out.println(e)); 其中参数类型可省,编译器根据上下文自动推测。 功能块复杂可以用大括号括起来,像方法体一样: 1234Arrays.asList("a", "b", "c").forEach(e -> { e += ","; System.out.println(e);}); Lambda表达式有返回值, 编译器会根据上下文推断返回值的类型。 如果Lambda的语句块只有一行, 不需要return关键字。 下面两个写法是等价的: 1Arrays.asList("a", "b", "d").sort((e1, e2) -> e1.compareTo(e2)); 12345Arrays.asList("a", "b", "d").sort((e1, e2) -> { int result = e1.compareTo(e2); return result;}); 总结下Lambda表达式的几个特性: 可选类型声明: 不需要声明参数类型, 编译器可以统一识别参数值。 可选的参数圆括号: 一个参数无需定义圆括号, 但多个参数需要定义圆括号。 可选的大括号: 如果主体包含了一个语句, 就不需要使用大括号。 可选的返回关键字: 如果主体只有一个表达式返回值则编译器会自动返回值, 大括号需要指定明表达式返回了一个数值。 Lambda表达式只能引用标记了final的外层局部变量, 这就是说不能在Lambda内部修改定义在域外的局部变量。 Lambda表达式主要用来定义行内执行的方法类型接口, 例如, 一个简单方法接口。 Lambda表达式免去了使用匿名方法的麻烦, 并且给予Java简单但是强大的函数化的编程能力。 注意, Lambda表达式当中不允许声明一个与局部变量同名的参数或者局部变量。 默认方法 Java 8引入default关键字修饰接口的方法, 该方法可以有方法体。 实现接口的类可以覆盖默认方法。 123456789101112131415161718private interface Defaulable { // Interfaces now allow default methods, the implementer may or // may not implement (override) them. default String notRequired() { return "Default implementation"; } default void defaultMethod() {}}private static class DefaultableImpl implements Defaulable {}private static class OverridableImpl implements Defaulable { @Override public String notRequired() { return "Overridden implementation"; }} 函数式接口 函数式接口是只有一个抽象方法的接口, 函数式接口可以隐性的转换成Lambda表达式。 Java 8提供@FunctionalInterface限定接口为函数式接口。 需要注意, default方法不算抽象方法, 带有@Override注解的继承自夫接口的方法也不算当前接口的方法。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java 8","slug":"Java-8","permalink":"http://bejondshao.github.io/tags/Java-8/"}]},{"title":"Simple String Null, Empty and Blank Issues","slug":"Simple-String-Null-Empty-and-Blank-Issues","date":"2018-04-08T12:40:00.000Z","updated":"2023-03-02T03:26:34.196Z","comments":true,"path":"2018/04/08/Simple-String-Null-Empty-and-Blank-Issues/","link":"","permalink":"http://bejondshao.github.io/2018/04/08/Simple-String-Null-Empty-and-Blank-Issues/","excerpt":"","keywords":null,"text":"@ Today I meet an interesting issue about String. First, let’s guess what’s the result of the code below: 1234567@Testpublic void testConcat() { String a = null; String b = null; String c = a + b; System.out.println("c = " + c);} The answer is: 1c = nullnull Yes, String c becomes “nullnull”, which is not our desired result. And how to avoid this? 1234a = a == null ? "" : a;b = b == null ? "" : b;String d = a + b;System.out.println("d = " + d); This time, String d is “”. It also happends to StringBuffer.append(String s) if s is null. We should be patient to String concat behavior. @ If we create a Restful API that accepts two parameters, String firstName and String lastName. But we need to make sure that they are not all empty. We can set default value to attribute when defining to the parameter to avoid “null” issue. Like: 12345678@XmlAttribute(name = "LastName")@JsonProperty("lastName")private String lastName = "";@XmlAttribute(name = "FirstName")@JsonProperty("firstName")private String firstName = ""; @ Another use case is that we usually want to check if a String is not null or “”. We usually use org.apache.commons.lang3.StringUtils.isNotEmpty(final CharSequence cs). But it just checks if cs is null or “”. It treats a whitespace string as not empty. We can trim cs before checking, but it’s not a good way because: The method points up “final”. We have to trim cs all the time if we don’t change cs at the first place. Good news is there’s a better method org.apache.commons.lang3.StringUtils.isNotBlank(final CharSequence cs). It treats whitespace string as empty too.🙂","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"}]},{"title":"Keycloak和Jenkins集成实现单点登录","slug":"Keycloak和Jenkins集成实现单点登录","date":"2018-03-26T09:06:00.000Z","updated":"2023-03-02T03:26:34.121Z","comments":true,"path":"2018/03/26/Keycloak和Jenkins集成实现单点登录/","link":"","permalink":"http://bejondshao.github.io/2018/03/26/Keycloak%E5%92%8CJenkins%E9%9B%86%E6%88%90%E5%AE%9E%E7%8E%B0%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95/","excerpt":"","keywords":null,"text":"安装Jenkins(参考) @ 将key添加到系统中 wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add - @ 将下面一行添加到/etc/apt/sources.list中: deb https://pkg.jenkins.io/debian-stable binary/ @ 安装 123sudo apt-get updatesudo apt-get install jenkins 配置Jenkins @ 修改Jenkins运行端口,编辑/etc/default/jenkins文件,将HTTP_PORT改为另外一个端口,比如8880 @ 启动Jenkins sudo service start jenkins @ 打开http://localhost:8880 ,就可以访问,刚开启,会询问admin初始密码,到/var/lib/jenkins/secrets/initialAdminPassword拷贝过来即可。 @ 下载keycloak-plugin到本地。 @ 打开http://localhost:8880/pluginManager/advanced ,使用Upload Plugin,上传keycloak-plugin,并安装。 @ 重启Jenkins sudo service restart jenkins 配置Keycloak @ 创建Client,名称jenkins,保存。 @ 打开jenkins client的Installation页签,选择Keycloak OIDC JSON,拷贝内容留作到Jenkins的配置 @ 在Realm中创建用于登录的用户。 @ 访问 http://localhost:8880/configure ,找到Keycloak JSON框,将Keycloak OIDC JSON内容拷贝到这里,保存。 @ 访问http://localhost:8880/configureSecurity/ , 勾选"Enable security",Security Realm选择"Keycloak Authentication Plugin",保存。 @ 登出管理员用户,点击log in。会跳转到Keycloak登录界面,验证Keycloak用户成功后,跳回Jenkins。至此完成单点登录。 @ 点击log out,即跳转到Keycloak登录页,说明可以实现Jenkins登出,同时使Keycloak的session失效。 遗留问题 在Keycloak主动使session失效,Jenkins用户仍可以访问Jenkins功能。 而如果在http://localhost:8880/configure 配置页选中"Validate Token on each request",并选中"Keep login session open until access token times out?“,其效果仍然和问题1一样。如果取消选中"Keep login session open until access token times out?”,则在Keycloak使session失效后,Jenkins请求页面会一直卡住,无法做其他操作。只能重启Jenkins服务。 不要在开启Keycloak验证后Authorization选"Legacy mode"。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"},{"name":"Jenkins","slug":"Jenkins","permalink":"http://bejondshao.github.io/tags/Jenkins/"}]},{"title":"什么是Docker","slug":"什么是Docker","date":"2018-03-26T06:24:53.000Z","updated":"2023-03-02T03:26:34.220Z","comments":true,"path":"2018/03/26/什么是Docker/","link":"","permalink":"http://bejondshao.github.io/2018/03/26/%E4%BB%80%E4%B9%88%E6%98%AFDocker/","excerpt":"","keywords":null,"text":"IT软件中,Docker指容器化技术,用于支持创建和使用Linux容器。Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。 虚拟机运行另一个操作系统,占用资源多,需要分配内存和硬盘,冗余,启动慢。而Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。具有启动快,占用资源少,体积小,便于迁移等优点。 Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。 它是目前最流行的 Linux 容器解决方案。 Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。 总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。 Docker用途 Docker 的主要用途,目前有三大类。 (1)**提供一次性的环境。**比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。 (2)**提供弹性的云服务。**因为 Docker 容器可以随开随关,很适合动态扩容和缩容。 (3)**组建微服务架构。**通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。 [1] Docker入门教程","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"}],"tags":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/tags/DevOps/"},{"name":"Docker","slug":"Docker","permalink":"http://bejondshao.github.io/tags/Docker/"}]},{"title":"Keycloak和Grafana集成实现单点登录","slug":"Keycloak和Grafana集成实现单点登录","date":"2018-03-26T03:26:12.000Z","updated":"2023-03-02T03:26:34.118Z","comments":true,"path":"2018/03/26/Keycloak和Grafana集成实现单点登录/","link":"","permalink":"http://bejondshao.github.io/2018/03/26/Keycloak%E5%92%8CGrafana%E9%9B%86%E6%88%90%E5%AE%9E%E7%8E%B0%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95/","excerpt":"","keywords":null,"text":"Keycloak配置 @ 登录Keycloak后台http://localhost:8080/auth/admin/master/console/#/realms/master @ Add Realm,Name为"abc" @ 创建Client,Name为"grafana",grafana默认端口是3000, 因此Root URL填写http://localhost:3000 @ 开启Authorization Enabled,保存。(该步骤非必须,建议开启,可以提供鉴权功能) @ 打开Credentials,留存Secret,用于稍后配置grafana.ini。 @ 到Users模块创建用户 @ 到用户的Credentials页签设定密码,关闭Temporary选项。 安装(参考) 123wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_5.0.3_amd64.debsudo apt-get install -y adduser libfontconfigsudo dpkg -i grafana_5.0.3_amd64.deb @ 启动服务 sudo service grafana-server start @ 访问http://localhost:3000即可看到登录界面 Grafana配置Oauth @ 编辑/etc/grafana/grafana.ini配置文件 12345678910111213141516[auth.generic_oauth]enabled = truename = abcallow_sign_up = trueclient_id = grafana# secret从keycloak的grafana client,Credentials页签的Secret获取。client_secret = 9a134c1a-e8f2-46b0-b351-d2ffeccaa289;scopes = user:email,read:orgscopes = openid email nameauth_url = http://localhost:8080/auth/realms/abc/protocol/openid-connect/authtoken_url = http://localhost:8080/auth/realms/abc/protocol/openid-connect/token;api_url = https://foo.bar/user;team_ids =;allowed_organizations = 同时修改[database]和[security]节点内容。 @ 重启服务 sudo service grafana-server restart @ 再次访问http://localhost:3000 ,登录界面能看到"Sign in with abc",点击即跳转到Keycloak登录界面,Realm为abc。使用bejond.shao登录,登录成功跳转回grafana,实现单点登录。同时grafana会创建同名用户,并存储基本信息,如邮箱。 存在的问题 @ Session无法同步 在keycloak登出用户的所有sessions,grafana并不知晓,session仍有效。 在grafana登出用户,再次登录,点击"Sign in with abc",没有登录界面,而是直接跳转回grafana。说明grafana登出功能未做到通知IdP。详见sign out url for generic oauth","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"}],"tags":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/tags/DevOps/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"},{"name":"Grafana","slug":"Grafana","permalink":"http://bejondshao.github.io/tags/Grafana/"}]},{"title":"Debian/Ubuntu安装Docker","slug":"Debian-Ubuntu安装Docker","date":"2018-03-21T06:00:18.000Z","updated":"2023-03-02T03:26:34.078Z","comments":true,"path":"2018/03/21/Debian-Ubuntu安装Docker/","link":"","permalink":"http://bejondshao.github.io/2018/03/21/Debian-Ubuntu%E5%AE%89%E8%A3%85Docker/","excerpt":"","keywords":null,"text":"@ 更新资源 $ sudo apt-get update @ 安装docker $ sudo apt-get install docker.io @ 启动docker服务 $ sudo service docker start @ 将当前用户添加到docker组(需要注销或重启) $ sudo usermod -aG docker $USER @ 更改docker image镜像为国内镜像 $ sudo vim /etc/default/docker 在文件底部加上 DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com" 重启docker服务 $ sudo service docker restart @ Hello world $ docker run hello-world","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"}],"tags":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/tags/DevOps/"},{"name":"Docker","slug":"Docker","permalink":"http://bejondshao.github.io/tags/Docker/"}]},{"title":"什么是容器","slug":"什么是容器","date":"2018-03-16T09:29:17.000Z","updated":"2023-03-02T03:26:34.222Z","comments":true,"path":"2018/03/16/什么是容器/","link":"","permalink":"http://bejondshao.github.io/2018/03/16/%E4%BB%80%E4%B9%88%E6%98%AF%E5%AE%B9%E5%99%A8/","excerpt":"","keywords":null,"text":"Linux® 容器是与系统其他部分隔离开的一系列进程,从另一个镜像运行,并由该镜像提供支持进程所需的全部文件。容器提供的镜像包含了应用的所有依赖项,因而在从开发到测试再到生产的整个过程中,它都具有可移植性和一致性。 容器,可以想象成一个箱子,这个箱子里有格子,有套网,有刷子等等工具,你可以往里放衣服,放鞋子,放你要用的东西。你的衣服,鞋子放在自己的旅行箱正合适,但是放在另一个箱子可能就会弄褶皱。这里衣服就好比应用程序,箱子就是容器。如果没有容器,直接将程序安装到电脑上(简单说就是操作系统中),很可能会出现不兼容,缺少依赖,某个功能莫名失效的问题。而如果把应用程序安装在容器中,再将容器复制到新的系统中,则完美运行。 更加详细地来说,假定你在开发一个应用。你使用的是一台笔记本电脑,而且你的开发环境具有特定的配置。其他开发人员身处的环境配置可能稍有不同。你正在开发的应用依赖于你当前的配置,还要依赖于某些特定文件。与此同时,你的企业还拥有标准化的测试和生产环境,且具有自身的配置和一系列支持文件。你希望尽可能多在本地模拟这些环境,而不产生重新创建服务器环境的开销。因此,你要如何确保应用能够在这些环境中运行和通过质量检测,并且在部署过程中不出现令人头疼的问题,也无需重新编写代码和进行故障修复?答案就是使用容器。容器可以确保你的应用拥有必需的配置和文件,使得这些应用能够在从开发到测试、再到生产的整个流程中顺利运行,而不出现任何不良问题。这样可以避免危机,做到皆大欢喜。 容器不就是虚拟化吗? 是,但不完全是。 虚拟化是让多个操作系统安装在一台机器上运行。容器则可以共享同一个操作系统,将应用进程与系统其他部分隔离开。虚拟化将注意力放在操作系统上,容器将注意力放在应用上,更轻量化。 cgroup(control groups) 控制组 (cgroups) 是一项内核功能,能够控制和限制一个进程或多组进程的资源使用。而 systemd 初始化系统可设置用户空间,并且管理它们的进程,cgroups 使用该系统来更严密地控制这些隔离进程。这两种技术在增加对 Linux 的整体控制的同时,也成为了保持环境隔离的重要框架。 systemd(system daemon,系统守护进程) systemd是Linux中的一套基础构建模块。提供一个system和服务管理器,服务管理器PID为1,然后启动剩下的服务。systemd提供了积极的并行机制,使用socket和D-Bus激活服务,提供按需启动的进程,通过cgroups,保持挂载和自动挂载来监控进程。 User namespaces progress 用户名称空间的改进推动了容器的进一步发展。用户名称空间“使得用户和组 ID 可以按名称空间进行映射。对于容器而言,这意味着用户和组可以在容器内部拥有执行某些操作的特权,而在容器外部则没有这种特权。” 这类似于 Jail 概念,但它实现了进一步的进程隔离,从而增加了安全性,而不再是 Jail 的修改环境的概念。 容器是操作系统层虚拟化特征的一种抽象 Linux 容器是我们开发、部署和管理应用方式的又一次飞跃。Linux 容器镜像提供了可移植性和版本控制,确保能够在开发人员的笔记本电脑上运行的应用,同样也能在生产环境中正常运行。 运行 Linux 容器消耗的资源少于虚拟机,但在很大程度上保持了应用隔离,而且它作为大型应用的一部分更加易于管理。 Linux 容器的价值在于它能加速开发并满足新出现的业务需求,而并非用于完成这些工作的软件。不要认为容器只限于运行单个应用:您可以使用容器来运行应用或服务的多个部分。而且,您可以使用其他技术(如 Kubernetes)让容器化应用实现自动化并对这些应用进行编排。由于容器托管了应用逻辑、运行时和依赖项,因此您的容器可以包括所有这一切,或者也可以构建一个应用,其中包含多个用作微服务的容器。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"}],"tags":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/tags/DevOps/"}]},{"title":"SVN常用命令","slug":"SVN常用命令","date":"2018-03-16T08:34:21.000Z","updated":"2023-03-02T03:26:34.196Z","comments":true,"path":"2018/03/16/SVN常用命令/","link":"","permalink":"http://bejondshao.github.io/2018/03/16/SVN%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/","excerpt":"","keywords":null,"text":"@ svn checkout http://url @ svn add filename/dir @ svn revert filename, 将修改恢复至原始状态 @ svn blame, 查看文件历史更改 @ svn copy filename, 拷贝文件 @ svn cleanup 清理工作副本。有时可能会出现“工作副本已锁定”错误。若要删除锁定,并递归清理工作副本,请使用 svn update @ svn delete filename @ svn diff @ svn export path1 path2 @ svn commit -m “asdf” @ svn import path svn import -m “asdf” URL @ svn info @ svn list @ svn log path @ svn merge 以指示 Subversion 将存储库中最新版本的文件合并到您的工作副本中。 @ svn merge -r 1994:1993 . 将r1994的所有改变回滚,只是回滚到本地,可以比较差异,需要做额外的commit操作才能提交到服务器。 @ svn mkdir path 若要在您的工作副本中创建新目录,请键入: svn mkdir PATH 若要在您的项目存储库中创建新目录,请键入: svn mkdir URL @ svn resolved 解决冲突后,键入 svn resolved PATH…,通知工作副本该冲突已“解决”。 @ svn revert 撤销更改 使用 Subversion 时,您会发现 svn revert PATH… 等效于 Windows 中的 Ctrl Z。您可以: 撤消本地工作副本中的任何本地更改,从而解决冲突状态。 撤消工作副本中的条目内容及属性更改。 取消任何进度安排操作,如添加文件、删除文件等。 注意,如不提供目标,会导致工作副本中的更改丢失。 @ svn status @ svn switch 可以使用 svn switch URL [PATH] 更新工作副本,以镜像新的 URL。您还可以将工作副本或部分工作副本移动到新的分支。您可以将此子命令用作分支的快捷方式。 @ svn update [path] @ 项目的主干通常用作开发主线,而分支通常用作主线的变更。分支是正在进行的开发线。在软件开发生命周期中,如果软件产品的发布版本已到期,经常会用 到分支,使测试者可以使用候选版本,使新的开发可以继续进行,不受测试的约束。分支还用于实验性工作,以及完成代码重写。标记是将一组文件修订版本标记为 整体的方式。虽然分支和标记都是使用 svn copy 子命令创建的,但它们是完全不同的。分支表示多个修订版本而标记只表示单个修订版本。 本站点上您项目的 Subversion 存储库支持对您的源文件进行分支和标记。对于 Subversion 来说,标记和分支属于简单实用的“复制”操作。 @ 若要创建分支或标记项目文件,请键入: svn copy SRC DST -m “在此处键入您的信息”","raw":null,"content":null,"categories":[{"name":"Tools","slug":"Tools","permalink":"http://bejondshao.github.io/categories/Tools/"}],"tags":[{"name":"SVN","slug":"SVN","permalink":"http://bejondshao.github.io/tags/SVN/"}]},{"title":"Istio介绍","slug":"Istio介绍","date":"2018-03-16T07:58:32.000Z","updated":"2023-03-02T03:26:34.104Z","comments":true,"path":"2018/03/16/Istio介绍/","link":"","permalink":"http://bejondshao.github.io/2018/03/16/Istio%E4%BB%8B%E7%BB%8D/","excerpt":"","keywords":null,"text":"Istio是用来连接,管理和保护微服务的平台。不改动应用代码,在环境中部署一个sidecar即可实现负载均衡,服务之间认证,监控等功能。Istio有控制面板,可以管理代理,拦截服务间通信。 Istio目前只支持在Kubernets(K8s)部署。 Istio可解决单体应用转型为分布式微服务架构时遇到的问题。Service mesh(服务网格)用于描述构成这些应用程序的微服务网络以及它们之间的交互。随着服务增多,服务越来越难管理,需要有服务发现,负载均衡,故障恢复,指标收集以及监控等需求。 Istio能监测并控制微服务 ,主要功能有: 流量管理。控制服务间流量和API调用流向,使得服务在网络恶劣情况下稳定。 可观察性。了解服务依赖关系,认清流量流向,快速识别问题。 策略执行。将组织策略应用与服务之间的互动,确保访问策略得以执行,确保资源在消费者间良好分配。策略的修改通过配置网格,而不是修改应用代码。 服务身份和安全。为网各种的服务提供可验证身份,提供保护服务流量的能力,使其可以在不同可信度的网络上流转。 集成和定制。策略执行组建可扩展和定制,以便与ACL,日志,监控,配额,审核等解决方案集成。 极大减少应用代码和策略的耦合,便于运维和迁移。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"}],"tags":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/tags/DevOps/"},{"name":"Istio","slug":"Istio","permalink":"http://bejondshao.github.io/tags/Istio/"}]},{"title":"Spring cloud介绍","slug":"Spring-cloud介绍","date":"2018-03-16T06:02:54.000Z","updated":"2023-03-02T03:26:34.197Z","comments":true,"path":"2018/03/16/Spring-cloud介绍/","link":"","permalink":"http://bejondshao.github.io/2018/03/16/Spring-cloud%E4%BB%8B%E7%BB%8D/","excerpt":"","keywords":null,"text":"Spring cloud为开发者提供便利的工具,在分布式系统快速构建常用的模式。(比如配置管理,服务发现,断路器,智能路由,微代理,总线控制,一次性token,全范围锁,自动任命leader,分布式session,云声明等)开发者可以快速构实现上述模式的建服务和应用。这些服务和应用可以在笔记本,数据中心,云主机运行。 Spring cloud是基于spring boot构建的,只不过提供了一些类库,这些类库在将应用放到classpath时附加了一些行为。在基础行为上可以快速配置或扩展应用。 特性 Spring cloud专注于提供现成的基本用例,支持扩展其他用例。 分布式/版本式的配置 服务注册与发现 路由 服务到服务之间调用 负载均衡 断路器 全应用锁 自动任命leader和云声明 分布式消息 pom.xml 123456789101112131415161718192021222324252627282930313233343536<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.M7</version></parent><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M7</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement><dependencies> <dependency> <groupId></groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency></dependencies><repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository></repositories>","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/tags/DevOps/"},{"name":"Spring cloud","slug":"Spring-cloud","permalink":"http://bejondshao.github.io/tags/Spring-cloud/"}]},{"title":"Consul介绍","slug":"Consul介绍","date":"2018-03-15T07:38:45.000Z","updated":"2023-03-02T03:26:34.078Z","comments":true,"path":"2018/03/15/Consul介绍/","link":"","permalink":"http://bejondshao.github.io/2018/03/15/Consul%E4%BB%8B%E7%BB%8D/","excerpt":"","keywords":null,"text":"Consul介绍 Consul包含多个组件,是为基础设施提供服务发现和服务配置的工具。特性有: 服务发现:Consul的客户端可以提供一个服务,比如api或者mysql服务。其他的客户端可以通过Consul发现已存在的服务(即api或mysql)。使用DNS或者HTTP,应用程序可以很方便的发现它们所依赖的服务。 健康度检测:Consul客户端可以提供多种健康度检测,比如和某个service关联(“web服务是否返回200 OK”),或者检查本地节点(“内存使用在90%以下”)。这些信息可以让运维人员监测集群健康,防止服务被不健康的主机使用。 Keyc/Value存储:支持层级式键值对存储数据,比如动态配置,功能开关,协作等的,并且有HTTP API方便设定。 多数据中心:Consul有现成的多数据中心,使用者不需要写抽象层来扩展业务。 Consul基本架构 Consul是一个分布式的高可用系统。这是详细介绍 每一个为Consul提供服务的节点都运行一个Consul agent(代理)。发现其他服务或读存键值对并不需要运行agent。Agent是用来做健康检测的,检测这个节点和节点提供的服务。 Agents和Consul服务器沟通,Consul服务器存储和复制数据。这些服务器选出一个leader(头儿)。虽然Consul可以运行在一台服务器上,但是建议用3到5台避免数据丢失。建议给每个数据中心建立一个集群环境。 你基础设施中需要发现其他服务的组件可以查询任何一个Consul 的server或者agent。Agent会自动转发请求到server。 每个数据中运行了一个Consul server集群。当一个跨数据中心的服务发现和配置请求创建时,本地Consul Server转发请求到远程的数据中心并返回结果。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"}],"tags":[{"name":"Consul","slug":"Consul","permalink":"http://bejondshao.github.io/tags/Consul/"},{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/tags/DevOps/"}]},{"title":"iPhone8(Plus)扬声器播放音乐噼啪噪声","slug":"iPhone8-Plus-扬声器播放音乐噼啪噪声","date":"2018-03-14T15:09:31.000Z","updated":"2023-03-02T03:26:34.215Z","comments":true,"path":"2018/03/14/iPhone8-Plus-扬声器播放音乐噼啪噪声/","link":"","permalink":"http://bejondshao.github.io/2018/03/14/iPhone8-Plus-%E6%89%AC%E5%A3%B0%E5%99%A8%E6%92%AD%E6%94%BE%E9%9F%B3%E4%B9%90%E5%99%BC%E5%95%AA%E5%99%AA%E5%A3%B0/","excerpt":"","keywords":null,"text":"iPhone8(Pluse)网上有人提到扬声器播放音乐时不时的有噼啪声。我买了手机,将旧备份还原到新手机后,也出现了这个问题。我怀疑是备份中保留了APP的数据,这些数据与新的APP不兼容,所以在读取时产生工作不稳定而导致的干扰。在我“抹掉所有内容和设置”后,发现噼啪声出现频率少很多,基本可以忍受。“抹掉所有内容和设置”,打开“设置”,“通用”,“还原”,“抹掉所有内容和设置”。 后来我又将旧备份还原,结果噪音出现频率有多了,所以基本是软件原因。于是只能重新设置,重新下载APP,然后备份。这次备份就和iPhone8,iOS11.2.6完全兼容了。另外如果不是急切想要新版本功能,不建议升级iOS和APP。","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"iPhone","slug":"iPhone","permalink":"http://bejondshao.github.io/tags/iPhone/"}]},{"title":"在应用启动前更新数据库遇到TransactionRequiredException","slug":"在应用启动前更新数据库遇到TransactionRequiredException","date":"2018-03-07T09:41:26.000Z","updated":"2023-03-02T03:26:34.224Z","comments":true,"path":"2018/03/07/在应用启动前更新数据库遇到TransactionRequiredException/","link":"","permalink":"http://bejondshao.github.io/2018/03/07/%E5%9C%A8%E5%BA%94%E7%94%A8%E5%90%AF%E5%8A%A8%E5%89%8D%E6%9B%B4%E6%96%B0%E6%95%B0%E6%8D%AE%E5%BA%93%E9%81%87%E5%88%B0TransactionRequiredException/","excerpt":"","keywords":null,"text":"在实现项目升级时,自动查找SQL文件并执行脚本,更新数据库表结构或内容时,遇到“javax.persistence.TransactionRequiredException: Executing an update/delete query"。 由于执行更新要在应用启动前执行,所以需要实现ServletContextListener,实现contextInitialized(ServletContextEvent sce)方法。 尝试过多种增加@Transactional注解都无效,最后在stackoverflow找到解决方法。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"wildfly","slug":"wildfly","permalink":"http://bejondshao.github.io/tags/wildfly/"}]},{"title":"Wildfly读取classpath文件","slug":"Wildfly读取classpath文件","date":"2018-03-01T07:58:00.000Z","updated":"2023-03-02T03:26:34.210Z","comments":true,"path":"2018/03/01/Wildfly读取classpath文件/","link":"","permalink":"http://bejondshao.github.io/2018/03/01/Wildfly%E8%AF%BB%E5%8F%96classpath%E6%96%87%E4%BB%B6/","excerpt":"","keywords":null,"text":"由于Wildfly使用Virtual File System 无法通过URL或InputStream直接转换为java.io.File。需要通过VirtualFile转换: 123URL url = getClass().getClassLoader().getResource("updatesql");VirtualFile virtualFile = (VirtualFile)url.openConnection().getContent();File[] folder = virtualFile.getPhysicalFile().listFiles(); pom.xml 123456<dependency> <groupId>org.jboss</groupId> <artifactId>jboss-vfs</artifactId> <version>3.2.12.Final</version></dependency> 参考:[1] stackoverflow","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Wildfly","slug":"Wildfly","permalink":"http://bejondshao.github.io/tags/Wildfly/"}]},{"title":"表和视图对比","slug":"表和视图对比","date":"2018-02-23T06:29:19.000Z","updated":"2023-03-02T03:26:34.258Z","comments":true,"path":"2018/02/23/表和视图对比/","link":"","permalink":"http://bejondshao.github.io/2018/02/23/%E8%A1%A8%E5%92%8C%E8%A7%86%E5%9B%BE%E5%AF%B9%E6%AF%94/","excerpt":"","keywords":null,"text":"@ 表是存储数据的数据库对象。 @ 视图是表的部分列或多个表的SELECT集合,即就是个SELECT语句。 @ 视图并不存储真实数据,不占用内存和空间,只是用于数据查询,展示。 @ 更新表的内容同样会更新视图。 @ 在Oracle数据库中,更新视图同样会更新表的内容,参考Oracle View @ 视图适用于多表连接查询重复使用,不适合增删改。存储过程适用于频繁操作的SQL语句,可以提高效率。 @ 可以限制用户访问表,允许用户访问视图,同时可以对视图做访问限定,比如只读视图。 @ 创建和删除视图对表无任何影响。","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"Database","slug":"Database","permalink":"http://bejondshao.github.io/tags/Database/"}]},{"title":"How to check if IP is in IP range","slug":"How-to-check-if-IP-is-in-IP-range","date":"2017-12-22T07:38:20.000Z","updated":"2023-03-02T03:26:34.083Z","comments":true,"path":"2017/12/22/How-to-check-if-IP-is-in-IP-range/","link":"","permalink":"http://bejondshao.github.io/2017/12/22/How-to-check-if-IP-is-in-IP-range/","excerpt":"","keywords":null,"text":"I work on writing services, the client validation contains IP checking. But the customer uses cluster base framework to invoke our services, there are multiple clients with different IPs obviously. First I change the configuration page and make it able to save multiple IPs with “,” seperated, like “192.168.1.12,192.168.1.25”. But there are hundreds of IPs. Some of them are in the same network segment, it’s not right to write out all the IPs. Right configuration is like “23.25.6.8,192.168.1.20,42.12.56.0/24,124.1.53.0/24”. As the validation needs to be able check multiple IPs and IP range. So I divide them into two parts: one part is real IPs, the other part is IP ranges. Real IPs checking is simple, just spilt it and check if the IP array contains client IP. Let’s move to IP range checking. Way one: I come up with an idea that analyze IP ranges and generate new regex patterns. I search regext about IP checking, it seems complex, even dynamic generating. By the way, regex does not play well with me😂. I believe even I make it, it probably gets me more troubles. It’ll be hard to maintain for others. Way two: Converting IP to int numbers and check if the IP is in the range. Here is a solution. It might take you a little time to understand the algorithm. 1234567891011public int intOfIpV4(String ip) { int result = 0; byte[] bytes = IPAddressUtil.textToNumericFormatV4(ip); // 1 if (bytes == null) { return result; } for (byte b : bytes) { result = result << 8 | (b & 0xFF); } return result; } bytes is 4 length array, each byte means a IP part, divided by “.”. Eg, IPAddressUtil.textToNumericFormatV4(“”)","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"IP","slug":"IP","permalink":"http://bejondshao.github.io/tags/IP/"}]},{"title":"Jboss6.x升级到Wildfly10所遇到的问题","slug":"Jboss6-x升级到Wildfly10所遇到的问题","date":"2017-12-18T09:46:59.000Z","updated":"2023-03-02T03:26:34.114Z","comments":true,"path":"2017/12/18/Jboss6-x升级到Wildfly10所遇到的问题/","link":"","permalink":"http://bejondshao.github.io/2017/12/18/Jboss6-x%E5%8D%87%E7%BA%A7%E5%88%B0Wildfly10%E6%89%80%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/","excerpt":"","keywords":null,"text":"1). Hibernate second level cache问题 17:02:43,041 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool – 61) MSC000001: Failed to start service jboss.persistenceunit.abc-weixin-showcase#primary.FIRST_PHASE: org.jboss.msc.service.StartException in service jboss.persistenceunit.abc-weixin-showcase#primary.FIRST_PHASE: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.RegionFactory] at org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl$1$1.run(PhaseOnePersistenceUnitServiceImpl.java:120) at org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl$1$1.run(PhaseOnePersistenceUnitServiceImpl.java:102) at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:667) at org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl1.run(PhaseOnePersistenceUnitServiceImpl.java:129)atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)atjava.util.concurrent.ThreadPoolExecutor1.run(PhaseOnePersistenceUnitServiceImpl.java:129) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor1.run(PhaseOnePersistenceUnitServiceImpl.java:129)atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)atjava.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) at org.jboss.threads.JBossThread.run(JBossThread.java:320) Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.RegionFactory] at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264) at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228) at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207) at org.hibernate.boot.internal.MetadataBuilderImpl$MetadataBuildingOptionsImpl.(MetadataBuilderImpl.java:663) at org.hibernate.boot.internal.MetadataBuilderImpl.(MetadataBuilderImpl.java:127) at org.hibernate.boot.MetadataSources.getMetadataBuilder(MetadataSources.java:135) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.(EntityManagerFactoryBuilderImpl.java:185) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.(EntityManagerFactoryBuilderImpl.java:149) at org.hibernate.jpa.boot.spi.Bootstrap.getEntityManagerFactoryBuilder(Bootstrap.java:28) at org.hibernate.jpa.boot.spi.Bootstrap.getEntityManagerFactoryBuilder(Bootstrap.java:40) at org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.(TwoPhaseBootstrapImpl.java:39) at org.jboss.as.jpa.hibernate5.HibernatePersistenceProviderAdaptor.getBootstrap(HibernatePersistenceProviderAdaptor.java:159) at org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl.createContainerEntityManagerFactoryBuilder(PhaseOnePersistenceUnitServiceImpl.java:242) at org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl.access$800(PhaseOnePersistenceUnitServiceImpl.java:59) at org.jboss.as.jpa.service.PhaseOnePersistenceUnitServiceImpl$1$1.run(PhaseOnePersistenceUnitServiceImpl.java:117) … 7 more Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.jboss.as.jpa.hibernate4.infinispan.InfinispanRegionFactory] as strategy [org.hibernate.cache.spi.RegionFactory] at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:113) at org.hibernate.cache.internal.RegionFactoryInitiator.resolveRegionFactory(RegionFactoryInitiator.java:99) at org.hibernate.cache.internal.RegionFactoryInitiator.initiateService(RegionFactoryInitiator.java:67) at org.hibernate.cache.internal.RegionFactoryInitiator.initiateService(RegionFactoryInitiator.java:28) at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88) at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254) … 21 more 解决方法: https://developer.jboss.org/thread/266936 Solved by moving second level cache from hibernate4 to hibernate5 in persistence.xml: 1<property name="hibernate.cache.region.factory_class" value="org.jboss.as.jpa.hibernate5.infinispan.InfinispanRegionFactory" /> 2). PSQLException: ERROR: column "user_id" contains null values" 由于hibernate4对表关联创建的列为users_id和roles_id,升级为hibernate5后,hibernate尝试将列名改为user_id,roles_id,而在进行alter table user_roles add column User_id int8 not null操作时,遇到非空检查失败了。解决方法是将原表备份,然后删除user_roles表,启动项目后会自动创建新的表和表结构。然后再自行更新表。 3). Hibernate infinispan statistics cache问题 [2017-12-15 05:14:40,464] Artifact abc-weixin-showcase:war exploded: Error during artifact deployment. See server log for details. [2017-12-15 05:14:40,468] Artifact abc-weixin-showcase:war exploded: java.lang.Exception: {“WFLYCTL0080: Failed services” => {“jboss.persistenceunit.abc-weixin-showcase#primary” => “org.jboss.msc.service.StartException in service jboss.persistenceunit.abc-weixin-showcase#primary: javax.persistence.PersistenceException: [PersistenceUnit: primary] Unable to build Hibernate SessionFactory Caused by: javax.persistence.PersistenceException: [PersistenceUnit: primary] Unable to build Hibernate SessionFactory Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.spi.CacheImplementor] Caused by: org.hibernate.cache.CacheException: Unable to start region factory Caused by: org.infinispan.commons.CacheConfigurationException: ISPN000372: Statistics are enabled while attribute ‘available’ is set to false.”},“WFLYCTL0412: Required services that are not installed:” => [“jboss.persistenceunit.abc-weixin-showcase#primary”],“WFLYCTL0180: Services with missing/unavailable dependencies” => undefined} 17:17:43,075 INFO [org.jboss.as.server] (management-handler-thread - 5) WFLYSRV0236: Suspending server with no timeout. [2017-12-15 05:23:17,962] Artifact abc-weixin-showcase:war exploded: Error during artifact deployment. See server log for details. [2017-12-15 05:23:17,962] Artifact abc-weixin-showcase:war exploded: java.lang.Exception: {“WFLYCTL0080: Failed services” => {“jboss.persistenceunit.abc-weixin-showcase#primary” => “org.jboss.msc.service.StartException in service jboss.persistenceunit.abc-weixin-showcase#primary: javax.persistence.PersistenceException: [PersistenceUnit: primary] Unable to build Hibernate SessionFactory Caused by: javax.persistence.PersistenceException: [PersistenceUnit: primary] Unable to build Hibernate SessionFactory Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.spi.CacheImplementor] Caused by: org.hibernate.cache.CacheException: Unable to start region factory Caused by: org.infinispan.commons.CacheConfigurationException: ISPN000372: Statistics are enabled while attribute ‘available’ is set to false.”},“WFLYCTL0412: Required services that are not installed:” => [“jboss.persistenceunit.abc-weixin-showcase#primary”],“WFLYCTL0180: Services with missing/unavailable dependencies” => undefined} Solution: https://stackoverflow.com/questions/43586016/infinispan-statistics-are-enabled-while-attribute-available-is-set-to-false Workaround: 將persistence.xml hibernate.cache.infinispan.statistics=true 改为false Note: 有可能在解决第2个问题后这个问题就不存在了。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Wildfly","slug":"Wildfly","permalink":"http://bejondshao.github.io/tags/Wildfly/"}]},{"title":"SunCertPathBuilderException: unable to find valid certification path to requested target","slug":"SunCertPathBuilderException-unable-to-find-valid-certification-path-to-requested-target","date":"2017-12-14T03:47:22.000Z","updated":"2023-03-02T03:26:34.198Z","comments":true,"path":"2017/12/14/SunCertPathBuilderException-unable-to-find-valid-certification-path-to-requested-target/","link":"","permalink":"http://bejondshao.github.io/2017/12/14/SunCertPathBuilderException-unable-to-find-valid-certification-path-to-requested-target/","excerpt":"","keywords":null,"text":"原文 产生SunCertPathBuilderException: unable to find valid certification path to requested target的原因是要以SSL方式连接目标,而目标的证书是自签名的,所以会导致这个问题。 通常异常如下: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:441) at javax.mail.Service.connect(Service.java:233) at javax.mail.Service.connect(Service.java:134) 当我们使用浏览器通过https访问自签名的站点时,也会提示安全信息: 产生原因 当客户端要通过SSL(比如:HTTPS, IMAPS, LDAPS)访问服务器时,只会连接受信任的应用。在Java领域里被称为keystore,通常存储在$JAVA_HOME/lib/security/cacerts。这个文件包含了一系列受信用的证书。 解决方法 获取证书 Linux $ openssl s_client -connect google.com:443 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt Windows(需要安装sed for Windows和OpenSSL) > openssl s_client -connect google.com:443 < NUL | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt 上面命令是从google.com的443端口获取证书,存储为public.crt。 导入证书到cacerts文件中 $JAVA_HOME/bin/keytool -import alias google.com -keystore $JAVA_HOME/jre/lib/security/cacerts -file public.crt","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"SSL","slug":"SSL","permalink":"http://bejondshao.github.io/tags/SSL/"}]},{"title":"Netty开发环境搭建","slug":"Netty开发环境搭建","date":"2017-12-14T03:39:07.000Z","updated":"2023-03-02T03:26:34.189Z","comments":true,"path":"2017/12/14/Netty开发环境搭建/","link":"","permalink":"http://bejondshao.github.io/2017/12/14/Netty%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/","excerpt":"","keywords":null,"text":"克隆Netty源码 $ git clone [email protected]:netty/netty.git Build dev-tools 12$ cd dev-tools$ mvn clean install Note: 此步骤必须,因为build整个项目需要使用dev-tools。感觉netty的build顺序不合理,应该自动build dev-tools。 3. Build整个项目 12$ cd ..$ mvn clean install -DskipTests=True Note: -DskipTests=True是必须的,因为本地环境没有运行test的能力,很多tests会报错导致build失败。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Netty","slug":"Netty","permalink":"http://bejondshao.github.io/tags/Netty/"}]},{"title":"如何查找哪个进程在占用端口","slug":"如何查找哪个进程在占用端口","date":"2017-12-13T11:11:22.000Z","updated":"2023-03-02T03:26:34.237Z","comments":true,"path":"2017/12/13/如何查找哪个进程在占用端口/","link":"","permalink":"http://bejondshao.github.io/2017/12/13/%E5%A6%82%E4%BD%95%E6%9F%A5%E6%89%BE%E5%93%AA%E4%B8%AA%E8%BF%9B%E7%A8%8B%E5%9C%A8%E5%8D%A0%E7%94%A8%E7%AB%AF%E5%8F%A3/","excerpt":"","keywords":null,"text":"原文 netstat: 展示网络连接,路由表,网络接口数据。 fuser: 标识占用文件或端口的进程。 lsof: 展示被打开的文件以及占用文件的进程。 /proc/$pid/: Note: 普通用户只能查询到当前用户运行的进程,建议以root用户执行。 netstat $ netstat -tulpn 部分结果: 1234567891011bejond@bejond-HP:~$ netstat -tulpn(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)Active Internet connections (only servers)Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:35421 0.0.0.0:* LISTEN 12779/java tcp 0 0 127.0.0.1:19645 0.0.0.0:* LISTEN 1277/python tcp 0 0 0.0.0.0:445 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:6942 0.0.0.0:* LISTEN 12779/java tcp 0 0 0.0.0.0:34303 0.0.0.0:* LISTEN 12779/java tcp 0 0 0.0.0.0:8643 0.0.0.0:* LISTEN 16031/java 可以使用grep过滤: $ netstat -tulpn | grep 8643 1234bejond@bejond-HP:~$ netstat -tulpn | grep 8643(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)tcp 0 0 0.0.0.0:8643 0.0.0.0:* LISTEN 16031/java TCP端口8643正在执行java程序,进程号为16031,可以通过$ ls -l /proc/16031/exe验证。 12bejond@bejond-HP:~$ ls -l /proc/16031/exelrwxrwxrwx 1 bejond bejond 0 12月 13 17:52 /proc/16031/exe -> /home/bejond/tools/java-tools/jdk1.8.0_121/bin/java 可以通过$ man java或$ whatis java了解java是什么程序。 fuser 查找哪个进程占用8643端口: $ fuser 8643/tcp 12bejond@bejond-HP:~$ fuser 8643/tcp8643/tcp: 16031 如果要查找哪里的程序创建进程16031及其工作组: $ ls -l /proc/16031/cwd 12bejond@bejond-HP:~$ ls -l /proc/16031/cwdlrwxrwxrwx 1 bejond bejond 0 12月 13 19:08 /proc/16031/cwd -> /home/bejond/code/server/wildfly-10.0.0.Final_v5/bin 或者直接输入$ pwdx 16031 12bejond@bejond-HP:~$ pwdx 1603116031: /home/bejond/code/server/wildfly-10.0.0.Final_v5/bin 如何查找进程的拥有者: $ ps aux 部分结果: 1234567891011121314bejond@bejond-HP:~$ ps auxUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.0 0.0 154936 6832 ? Ss 15:28 0:01 /sbin/init splashroot 2 0.0 0.0 0 0 ? S 15:28 0:00 [kthreadd]root 4 0.0 0.0 0 0 ? S< 15:28 0:00 [kworker/0:0H]root 6 0.0 0.0 0 0 ? S< 15:28 0:00 [mm_percpu_wq]root 7 0.0 0.0 0 0 ? S 15:28 0:01 [ksoftirqd/0]root 8 0.0 0.0 0 0 ? S 15:28 0:10 [rcu_sched]root 9 0.0 0.0 0 0 ? S 15:28 0:00 [rcu_bh]root 10 0.0 0.0 0 0 ? S 15:28 0:00 [migration/0]root 11 0.0 0.0 0 0 ? S 15:28 0:00 [watchdog/0]root 12 0.0 0.0 0 0 ? S 15:28 0:00 [cpuhp/0]root 13 0.0 0.0 0 0 ? S 15:28 0:00 [cpuhp/1]root 14 0.0 0.0 0 0 ? S 15:28 0:00 [watchdog/1] 使用grep过滤: $ ps aux | grep 16031 123bejond@bejond-HP:~$ ps aux | grep 16031bejond 16031 2.5 11.4 4537864 920976 pts/6 Sl+ 17:52 2:40 /home/bejond/tools/java-tools/jdk1.8.0_121/bin/java -D[Standalone] -server -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true -agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=n -Dorg.jboss.boot.log.file=/home/bejond/code/server/wildfly-10.0.0.Final_v5/standalone/log/server.log -Dlogging.configuration=file:/home/bejond/code/server/wildfly-10.0.0.Final_v5/standalone/configuration/logging.properties -jar /home/bejond/code/server/wildfly-10.0.0.Final_v5/jboss-modules.jar -mp /home/bejond/code/server/wildfly-10.0.0.Final_v5/modules org.jboss.as.standalone -Djboss.home.dir=/home/bejond/code/server/wildfly-10.0.0.Final_v5 -Djboss.server.base.dir=/home/bejond/code/server/wildfly-10.0.0.Final_v5/standalonebejond 17481 0.0 0.0 16112 1080 pts/7 S+ 19:36 0:00 grep --color=auto 16031 尝试执行如下命令: $ ps -eo pid,user,group,args,etime,lstart | grep '16031' 123bejond@bejond-HP:~$ ps -eo pid,user,group,args,etime,lstart | grep '16031'16031 bejond bejond /home/bejond/tools/java-too 01:47:04 Wed Dec 13 17:52:52 201717510 bejond bejond grep --color=auto 16031 00:00 Wed Dec 13 19:39:56 2017 想要看到更多信息?另一个方式是$ cat /proc/16031/environ: 12bejond@bejond-HP:~$ cat /proc/16031/environLESSOPEN=| /usr/bin/lesspipe %sUSER=bejondLANGUAGE=en_USLC_TIME=zh_CN.UTF-8XDG_SEAT=seat0SSH_AGENT_PID=1211XDG_SESSION_TYPE=x11SHLVL=1QT4_IM_MODULE=fcitxHOME=/home/bejondDESKTOP_SESSION=xubuntuJRE_HOME=/home/bejond/tools/java-tools/jdk1.8.0_45/jreSMARTGITHG_MAX_HEAP_SIZE=4096mXDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0LC_MONETARY=zh_CN.UTF-8DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/busANT_OPTS=-Xmx4g -XX:MaxPermSize=2gJBOSS_HOME=/home/bejond/code/server/wildfly-10.0.0.Final_v5COLORTERM=truecolorGLADE_MODULE_PATH=:MANDATORY_PATH=/usr/share/gconf/xubuntu.mandatory.pathQT_QPA_PLATFORMTHEME=gtk2LOGNAME=bejondGTK_IM_MODULE=fcitxWINDOWID=75510244_=./standalone.shDEFAULTS_PATH=/usr/share/gconf/xubuntu.default.pathGTK_OVERLAY_SCROLLING=0XDG_SESSION_ID=c1CLUTTER_BACKEND=x11TERM=xterm-256colorRBENV_SHELL=bashPATH=/home/bejond/anaconda3/bin:/home/bejond/anaconda2/bin:/home/bejond/.rbenv/plugins/ruby-build/bin:/home/bejond/.rbenv/shims:/home/bejond/.rbenv/bin:/home/bejond/bin:/home/bejond/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/bejond/tools/java-tools/jdk1.8.0_121/bin:/home/bejond/tools/java-tools/apache-ant-1.9.5/bin:/home/bejond/tools/rar:/home/bejond/tools:/home/bejond/tools/java-tools/jdk1.8.0_45/jre/bin:/home/bejond/tools/Sublime_Text_2:/home/bejond/tools/smartgithg-4_6_3/bin:/home/bejond/tools/eclipse:/home/bejond/tools/FileZilla3/bin:/home/bejond/tools/navicat110_mysql_en:/home/bejond/tools/git-tools:/home/bejond/tools/giteye:/home/bejond/tools/scripts:/home/bejond/tools/jd:/home/bejond/tools/idea-IU-139.659.2/bin:/home/bejond/tools/apache-cxf-3.1.11/bin:/home/bejond/tools/apache-maven-3.5.0/bin:/home/bejond/tools/java-tools/jdk1.8.0_121/bin:/home/bejond/tools/java-tools/jdk1.8.0_45/jre/binGDM_LANG=en_USGLADE_PIXMAP_PATH=:ANT_HOME=/home/bejond/tools/java-tools/apache-ant-1.9.5SESSION_MANAGER=local/bejond-HP:@/tmp/.ICE-unix/1236,unix/bejond-HP:/tmp/.ICE-unix/1236XDG_MENU_PREFIX=xfce-LC_ADDRESS=zh_CN.UTF-8XDG_RUNTIME_DIR=/run/user/1000XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0DISPLAY=:0.0LANG=en_US.UTF-8XDG_CURRENT_DESKTOP=XFCELC_TELEPHONE=zh_CN.UTF-8LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:XDG_SESSION_DESKTOP=xubuntuXMODIFIERS=@im=fcitxXAUTHORITY=/home/bejond/.XauthoritySSH_AUTH_SOCK=/run/user/1000/keyring/sshGLADE_CATALOG_PATH=:XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/bejondLC_NAME=zh_CN.UTF-8SHELL=/bin/bashQT_ACCESSIBILITY=1GDMSESSION=xubuntuLESSCLOSE=/usr/bin/lesspipe %s %sLC_MEASUREMENT=zh_CN.UTF-8CLASSPATH=.:/home/bejond/tools/java-tools/jdk1.8.0_121/lib:/home/bejond/tools/java-tools/jdk1.8.0_121/lib:.:/home/bejond/tools/java-tools/jdk1.8.0_121/lib:/home/bejond/tools/java-tools/jdk1.8.0_121/jre/libLC_IDENTIFICATION=zh_CN.UTF-8XDG_VTNR=7QT_IM_MODULE=fcitxJAVA_HOME=/home/bejond/tools/java-tools/jdk1.8.0_121PWD=/home/bejond/code/server/wildfly-10.0.0.Final_v5/binCLUTTER_IM_MODULE=ximXDG_DATA_DIRS=/usr/share/xubuntu:/usr/share/xfce4:/usr/local/share:/usr/share:/var/lib/snapd/desktop:/var/lib/snapd/desktop:/usr/shareXDG_CONFIG_DIRS=/etc/xdg/xdg-xubuntu:/etc/xdg:/etc/xdgLC_NUMERIC=zh_CN.UTF-8LC_PAPER=zh_CN.UTF-8VTE_VERSION=4804 lsof 可以用如下几种方式,第一种即可。 $ lsof -i :8643 $ lsof -i tcp:8643 $ lsof -i :8643 | grep LISTEN 结果: 123bejond@bejond-HP:~$ lsof -i :8643COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEjava 16031 bejond 382u IPv4 2396178 0t0 TCP *:8643 (LISTEN) 附: 如果知道占用端口进程是java进程,可以使用jps [-v]命令查看,但是没法通过端口查询。 如果想杀掉进程,可以使用$ kill -9 16031,当然还有根据程序名关闭$ killall java,可以关闭所有java进程,不推荐这么用,风险极大🌚。","raw":null,"content":null,"categories":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/categories/Linux/"}],"tags":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/tags/Linux/"},{"name":"Command","slug":"Command","permalink":"http://bejondshao.github.io/tags/Command/"}]},{"title":"Mybatis提示IO Error:Broken pipe或No more data to read from socket错误","slug":"Mybatis提示IO-Error:Broken-pipe或No-more-data-to-read-from-socket错误","date":"2017-12-12T10:32:58.000Z","updated":"2023-03-02T03:26:34.186Z","comments":true,"path":"2017/12/12/Mybatis提示IO-Error:Broken-pipe或No-more-data-to-read-from-socket错误/","link":"","permalink":"http://bejondshao.github.io/2017/12/12/Mybatis%E6%8F%90%E7%A4%BAIO-Error%EF%BC%9ABroken-pipe%E6%88%96No-more-data-to-read-from-socket%E9%94%99%E8%AF%AF/","excerpt":"","keywords":null,"text":"mybatis连接数据库查询报 18:07:25,819 ERROR [stderr] (default task-40) org.apache.ibatis.exceptions.PersistenceException: 18:07:25,819 ERROR [stderr] (default task-40) ### Error querying database. Cause: java.sql.SQLRecoverableException: IO Error: Broken pipe (Write failed) 18:07:25,819 ERROR [stderr] (default task-40) ### The error may exist in mybatis/xml/QueryInfoMapper.xml 18:07:25,819 ERROR [stderr] (default task-40) ### The error may involve mybatis.mapper.QueryInfoMapper.queryInfoFromOpera-Inline 18:07:25,819 ERROR [stderr] (default task-40) ### The error occurred while setting parameters 18:07:25,819 ERROR [stderr] (default task-40) ### SQL: SELECT UDFC08 FROM( SELECT UDFC08 FROM RESERVATION_NAME WHERE RESV_NAME_ID = ? ) WHERE ROWNUM = 1 18:07:25,819 ERROR [stderr] (default task-40) ### Cause: java.sql.SQLRecoverableException: IO Error: Broken pipe (Write failed) 18:07:25,821 ERROR [stderr] (default task-40) at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) 18:07:25,821 ERROR [stderr] (default task-40) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150) 18:07:25,821 ERROR [stderr] (default task-40) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141) 18:07:25,821 ERROR [stderr] (default task-40) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77) 18:07:25,822 ERROR [stderr] (default task-40) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:82) 18:07:25,822 ERROR [stderr] (default task-40) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59) 18:07:25,822 ERROR [stderr] (default task-40) at com.sun.proxy.$Proxy330.queryInfoFromOpera(Unknown Source) 18:07:25,822 ERROR [stderr] (default task-40) at mybatis.QueryInfo.queryInfoFromOpera(QueryInfo.java:42) 或者提示 2017-12-12 17:41:35,730 INFO [stdout] (default task-17) ==> Parameters: 15271(String) 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) org.apache.ibatis.exceptions.PersistenceException: 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) ### Error querying database. Cause: java.sql.SQLRecoverableException: No more data to read from socket 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) ### The error may exist in mybatis/xml/QueryInfoMapper.xml 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) ### The error may involve mybatis.mapper.QueryInfoMapper.queryInfoFromOpera-Inline 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) ### The error occurred while setting parameters 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) ### SQL: SELECT UDFC08 FROM( SELECT UDFC08 FROM RESERVATION_NAME WHERE RESV_NAME_ID = ? ) WHERE ROWNUM = 1 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) ### Cause: java.sql.SQLRecoverableException: No more data to read from socket 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150) 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141) 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77) 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:82) 2017-12-12 17:41:35,733 ERROR [stderr] (default task-17) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59) 原因是数据库重启,导致connection pool中的connections都失效了,而mybatis在开库查询数据库内容时使用的旧的数据库,重启应用即可解决。 或者每次都创建新的connection再关闭,不使用connection pool,这样会浪费一些时间。 更好的方式是使用connection pool,使用异常拦截,出现异常时通过connection pool的factory创建新的connection。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Mybatis","slug":"Mybatis","permalink":"http://bejondshao.github.io/tags/Mybatis/"}]},{"title":"如何减少firefox内存用量","slug":"如何减少firefox内存用量","date":"2017-12-12T09:51:32.000Z","updated":"2023-03-02T03:26:34.225Z","comments":true,"path":"2017/12/12/如何减少firefox内存用量/","link":"","permalink":"http://bejondshao.github.io/2017/12/12/%E5%A6%82%E4%BD%95%E5%87%8F%E5%B0%91firefox%E5%86%85%E5%AD%98%E7%94%A8%E9%87%8F/","excerpt":"","keywords":null,"text":"一. 在浏览器地址栏输入about:config browser.cache.memory.enable 默认值true 缓存图片内容到内存,我设置成false browser.sessionhistory.max_entries 默认值50 减少session历史记录,我设置成5 config.trim_on_minimize 添加属性,用于在最小化时释放内存,True 二. 打开设置,在Performance中取消选中“Use recommended performance settings” 然后Content process limit设置为1或2。 三. 禁用主题,禁用非必须插件 尤其是Adblock Plus,虽然这个插件很好用,但是如果你觉得浏览器很慢而又找不到原因时,很可能是这个插件导致的。电脑内存8G,下面是我测试插件的结果。 在浏览器关闭时,内存用量为66%: 开启浏览器,Content process limit为4,开启adblock plus,内存为72%: 开启浏览器,Content process limit为4,禁用adblock plus,内存为70%,差距还不是很明显: 测试如下10个页签,所有测试都设置Content process limit为2: https://stackoverflow.com/ http://www.163.com/ http://www.sina.com/ http://www.people.com.cn/ http://www.xinhuanet.com/ https://www.jd.com/ https://www.mozilla.org/en-US/ https://www.davidtan.org/tips-reduce-firefox-memory-cache-usage/ https://stackoverflow.com/questions/5227675/good-location-for-android-keystore https://security.stackexchange.com/questions/100584/where-should-a-keystore-jks-be-stored-in-a-repository 开启adblock plus内存使用为82%,关闭adblock plus内存使用为77%,可以推测页签越多影响越大,我一般会开启20到30个页签。 顺便,我又测试了一个线程关闭adb的情况,内存使用为76%,可见每个线程数对内存占用影响大约为1%,多线程会加快页签处理速度。","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"Firefox","slug":"Firefox","permalink":"http://bejondshao.github.io/tags/Firefox/"}]},{"title":"正向代理与反向代理的区别","slug":"正向代理与反向代理的区别","date":"2017-12-11T10:42:11.000Z","updated":"2023-03-02T03:26:34.255Z","comments":true,"path":"2017/12/11/正向代理与反向代理的区别/","link":"","permalink":"http://bejondshao.github.io/2017/12/11/%E6%AD%A3%E5%90%91%E4%BB%A3%E7%90%86%E4%B8%8E%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E7%9A%84%E5%8C%BA%E5%88%AB/","excerpt":"","keywords":null,"text":"原文 概念 正向代理是一个位于客户端和目标服务器之间的代理服务器(中间服务器)。为了从目标服务器取得内容,客户端向代理服务器发送一个请求,并且指定目标服务器,之后代理向目标服务器转交并且将获得的内容返回给客户端。正向代理的情况下客户端必须要进行一些特别的设置才能使用。 反向代理正好相反。对于客户端来说,反向代理就好像真实服务器。并且客户端不需要进行任何设置。客户端向反向代理发送请求,接着反向代理判断请求走向何处,并将请求转交给客户端,使得这些内容就好似他自己一样,因此客户端并不会感知到反向代理后面的服务,不需要客户端做任何设置,只需要访问反向代理服务器就好了。 区别 正向代理是代理客户端,为客户端收发请求,使真实客户端对服务器不可见。正向代理是为客户端服务的,代替客户端请求真实服务器。 而反向代理是代理服务器端,为服务器收发请求,使真实服务器对客户端不可见。反向代理是保护真实服务器的。代替真实服务器将服务发布出去。 从上面的描述也能看得出来正向代理和反向代理最关键的两点区别: 1. 是否指定目标服务器 2. 客户端是否要做设置 下面用一张图来表示两者的差异: 正向代理中,proxy和client同属一个LAN,对server透明; 反向代理中,proxy和server同属一个LAN,对client透明。 实际上proxy在两种代理中做的事都是代为收发请求和响应(client无法直接访问server),不过从结构上来看正好左右互换了下,所以把前者那种代理方式叫做正向代理,后者叫做反向代理。 从用途上来区分: 正向代理:正向代理用途是为了在防火墙内的局域网提供访问internet的途径。另外还可以使用缓冲特性减少网络使用率 反向代理:反向代理的用途是将防火墙后面的服务器提供给internet用户访问。同时还可以完成诸如负载均衡等功能 从安全性来讲: 正向代理:正向代理允许客户端通过它访问任意网站并且隐蔽客户端自身,因此你必须采取安全措施来确保仅为经过授权的客户端提供服务 反向代理:对外是透明的,访问者并不知道自己访问的是代理。对访问者而言,他以为访问的就是原始服务器 正向代理应用 从上面的介绍也就可以猜出来正向代理的至少一个功能,翻墙,顺便能隐藏客户端IP。 用户A(国内IP)无法访问 google.com,但是能访问服务器B(国外IP),而服务器B可以访问 google.com。于是用户A访问服务器B,通过服务器B去访问 google.com,服务器B收到请求后,去访问 google.com,google.com把响应信息返回给服务器B,服务器B再把响应信息返回给A。这样,通过代理服务器B,就实现了翻墙。 反向代理应用 从上面的介绍也可以猜出来反向代理的至少一个功能,负载均衡。 假设用户A访问http://www.somesite.com/something.html ,但http://www.somesite.com 上并不存在something.html页面,于是接收用户请求的该服务器就偷偷从另外一台服务器上取回来,然后返回给用户,而用户并不知道something.html页面究竟位于哪台机器上。 反向代理的作用就比较多了: 保护和隐藏原始资源服务器 加密和SSL加速 负载均衡 缓存静态内容 压缩 减速上传 安全 外网发布 简单介绍保护和隐藏原始资源服务器: 用户A始终认为它访问的是原始服务器B而不是代理服务器Z,但实用际上反向代理服务器接受用户A的应答,从原始资源服务器B中取得用户A的需求资源,然后发送给用户A。由于防火墙的作用,只允许代理服务器Z访问原始资源服务器B。尽管在这个虚拟的环境下,防火墙和反向代理的共同作用保护了原始资源服务器B,但用户A并不知情。 透明代理 透明代理比较类似正向代理的功能,差别在于客户端根本不知道代理的存在,它改变你的request,并会传送真实IP(使用场景就是公司限制网络的访问)。 比如为了工作效率或者安全,A公司屏蔽了QQ软件的使用。A公司的员工接上了网络,但发现无法使用qq。这就是透明代理捣的鬼。公司在内网和外网的中间插入一个透明代理,这个代理会根据规则抓取请求内容,遇到qq的请求我就把这个请求给屏蔽掉,这样就完成了透明屏蔽。当然了,如果你明白原理,就可以自己搞个正向代理来绕过公司的屏蔽。可以通过SSH访问云服务器,云服务器充当正向代理,即可访问QQ的服务器。","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"Proxy","slug":"Proxy","permalink":"http://bejondshao.github.io/tags/Proxy/"}]},{"title":"Keycloak应用所需工作","slug":"Keycloak应用所需工作","date":"2017-12-11T09:46:00.000Z","updated":"2023-03-02T03:26:34.142Z","comments":true,"path":"2017/12/11/Keycloak应用所需工作/","link":"","permalink":"http://bejondshao.github.io/2017/12/11/Keycloak%E5%BA%94%E7%94%A8%E6%89%80%E9%9C%80%E5%B7%A5%E4%BD%9C/","excerpt":"","keywords":null,"text":"一、学习并了解keycloak项目以及相关概念,验证流程等 二、部署配置keyclaok服务器 下载并解压最新keyclaok 配置keyclaok数据库和数据库驱动 配置项目服务器中的adapter 三、禁用现有项目中的权限模块,注释相关权限验证代码 pickedlink .Net相关权限模块 User,Role等model可暂时保留,待keycloak应用成功后移除。 四、在keycloak进行相关配置 配置realm, client, resource, scope, permission, policy, role, user, group等以满足项目实际需要。(user和group支持attribute扩展,以符合实际项目需要) 设置用户密码策略 配置keycloak admin后台管理角色和用户 五、更改项目代码,应用keycloak java项目: 在项目页面中调用keycloak相关API获取用户权限,进行权限验证 .Net项目: 通过解码RPT或rest API来验证用户权限 通过angularJS调用 (示例) 服务端项目: keycloak有针对其他项目rest接口的身份验证,应移除服务端接口验证 客户端项目: 增加获取token的拦截器(或将token保存在缓存中以便使用,token需要定时更新),在请求头中添加验证信息 六、自定义 keycloak方面: 制作keycloak主题,包括图标,界面显示语言(keycloak支持多语言,只需要增加新key以及相关显示信息)。 所需技术:ftl (示例) 项目方面: 创建相关类和工具类,用于与keycloak交互,并将所获取内容进行缓存,减少与keycloak的沟通频率。 七、附加功能 keycloak升级 keycloak支持realm和authorization导出,可以快速便捷移植项目配置。 clustering,多节点keycloak服务器,加快验证效率。 第三方授权登录,如果应用可以开方相关请求验证模块 https访问 DLAP,可以从active directory, Red Hat Directory等服务器获取用户信息 Admin REST API,支持远程管理keycloak服务器信息,可以开发客户端角色,权限管理模块。 CORS Client Template 八、注意 keycloak源码中的权限角色检查使用的是常量string验证,不便于以后更改角色名称。在开发过程中应避免使用string验证,应该使用常量。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"Keycloak基本功能","slug":"Keycloak基本功能","date":"2017-12-07T10:09:00.000Z","updated":"2023-03-02T03:26:34.135Z","comments":true,"path":"2017/12/07/Keycloak基本功能/","link":"","permalink":"http://bejondshao.github.io/2017/12/07/Keycloak%E5%9F%BA%E6%9C%AC%E5%8A%9F%E8%83%BD/","excerpt":"","keywords":null,"text":"Keycloak是一个致力于解决应用和服务身份验证与访问管理的开源工具。可以通过简单的配置达到保护应用和服务的目的。 用户管理 你的应用不需要开发登录模块,验证用户和保存用户。Keycloak开发了用户管理,登录,注册,密码策略,安全问题,二步验证,密码重置等功能。登录,注册界面所需字段都是可配置,可自定义的。 用户角色,权限管理功能,用户组功能。用户sessions管理。 单点登录/登出(Single-Sign On/Out) 用户通过Keycloak验证身份而非应用本身。当用户通过Keycloak的身份验证后,访问其他应用则不需要登录。 登出同样适用。Keycloak也提供单点登出。 Kerberos对接 如果用户验证是通过Kerberos(LDAP或Active Directory)的方式,在登录工作站后,也能自动的通过Keycloak验证,而不需要再次提供用户名密码。 身份代理和社交应用登录(Identity Brokering and Social Login) 在后台管理配置社交应用可以实现第三方应用授权。 Keycloak也能通过现成的OpenID Connect或SAML2.0 Identity Providers验证用户。只需要在后台配置即可。 用户联盟(User Federation) Keycloak有内置的连接LDAP或AD的功能。你也可以实现自己的IdP,比如用户存储在关系型数据库。 客户端适配器(Client Adapters) 适配器让保护应用和服务变得很简单。已经有很多平台和编程语言的适配器。如果没有与你的平台相适应的适配器,别担心,Keycloak是建立在标准的协议之上,你可以使用任何OpenID Connect Resource Library或SAML 2.0 Service Provider library来实现。 你可以使用代理服务器来保护你的应用,那就根本不需要修改应用了。 后台管理(Admin Console) 通过后台管理,管理员可以管理Keycloak所有方面的配置。可以开启关闭多种功能,配置身份代理和用户联盟。可以定义应用和服务,定义细粒的授权策略。管理用户,包括角色,权限,sessions等。 账户管理界面(Account Management Console) 用户可以通过账户管理界面管理自己的信息,更新,设定二次验证。用户也可以管理自己的sessions。 标准协议(Standard Protocols) Keycloak是基于标准协议开发的,支持OpenID Connect, OAuth 2.0和SAML。 授权服务(Authorization Services) 如果基于role的授权无法满足需求,Keycloak提供细粒的授权服务。允许你通过后台管理所有的服务,可以定义满足你的需求的策略。 Admin REST API Keycloak提供REST API用于后台管理,包括对Clients,Groups, Users, Roles等一系列资源的管理。这就为应用与Keycloak交互提供可能,应用可以在业务中实现对用户角色权限的增减。 自定义主题 Keycloak为web页面和email信息提供主题支持,更换符合公司产品风格的样式,可以自定义内容包括: 账户管理界面 后台管理界面 邮件 登录界面 欢迎界面 自定义用户字段(Custom User Attributes) 我们可以在用户属性页添加自定义属性,并在注册界面或用户信息页展示。 集群环境(Clustering) Keycloak支持集群环境,保障Keycloak的稳定运行,减小服务器压力。集群的搭建可以选择standalone模式或domain模式。domain模式经官方提供的文档使用软件负载均衡已经搭建成功。 服务器缓存(Server Cache) Keycloak有两种缓存,一种缓存数据库内容到内存,用以减少获取数据的时间,包括realm, client, role和用户元数据。这种缓存是本地缓存,本地缓存是不会在集群环境中复制的。如果数据被更新了,一个失效消息会发送给剩下所有的节点服务器,用于更新缓存。当然有的缓存可以支持集群,需要告诉集群服务器,将特定的条目从本地缓存中移除。 另一种缓存用于处理用户sessions,离线tokens以及跟踪登录失败次数,用于检测网络攻击。这种缓存是临时的,只在内存中保存,但是也可以复制到集群环境中。 HTTPS/SSL Keycloak支持HTTPS协议传输,这也是官方推荐的方式。不过实际产品为了安全和负载均衡,可以考虑反响代理,对代理服务器做SSL,代理服务器与Keycloak交互仍使用HTTP协议。 服务提供者接口(Service Provider Interfaces) Keycloak设计为包括大多数使用场景,但也支持定制化。Keycloak设计了SPI来允许开发者实现自己的服务提供者。Keycloak可用的SPI有Connections JPA,Email Sender,Email Listener,Login Protocol,Realm等。 扩展服务器(Extending Server) Keycloak SPI框架提供实现或覆盖已有的providers。Keycloak也提供扩展核心功能的方式,包括: 增加自定义REST服务 增加自定义SPI 增加自定义JPA实体到Keycloak数据模型中 验证身份SPI(AUthentication SPI) Keycloak自带不同的验证机制:kerberos, 密码和一次性密码。这些机制可能无法满足你的需求,你可能会增加自己的验证机制。Keycloak提供一个验证身份SPI供创建新的插件时使用。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"如何将hexo与theme代码分开提交","slug":"如何将hexo与theme代码分开提交","date":"2017-11-30T14:29:00.000Z","updated":"2023-03-04T12:23:00.707Z","comments":true,"path":"2017/11/30/如何将hexo与theme代码分开提交/","link":"","permalink":"http://bejondshao.github.io/2017/11/30/%E5%A6%82%E4%BD%95%E5%B0%86hexo%E4%B8%8Etheme%E4%BB%A3%E7%A0%81%E5%88%86%E5%BC%80%E6%8F%90%E4%BA%A4/","excerpt":"","keywords":null,"text":"说在前面 Hexo博客静态页面是用hexo-deployer-git插件自动提交到bejondshao.github.io库中的master分支的。为了保存文章和自定义内容,我将Hexo框架,文章和自定义内容保存在source分支下。平时编辑提交都在source分支做,执行hexo deploy时hexo-deployer-git自动将静态内容提交到master,不必手动切换分支,很方便。 言归正传,之前有介绍过升级Hexo主题。里面手动下载源码,手动自定义,随着自定义内容越来越多,每次升级主题会很麻烦。所以有必要将主题也提交到代码库中。但是将主题提交到Hexo与文章中显然不合适,并且想和hexo-theme-hueman(This repository is archived. I don’t recommend you use it any more.)保持同步会很麻烦。所以有必要将主题单独提交到另一个资源中。 将本地bejondshao.github.io/themes/hueman/文件夹备份。 将hueman主题从源码移出 $ git rm -r themes/hueman(将themes/hueman文件夹以及内容递归移除资源库) 编辑bejondshao.github.io/.gitignore文件,在末尾添加themes/hueman/ 将更改提交到github的source分支: 1234$ git add . (将之前的操作的所有文件添加为待提交内容)$ git status (查看是否添加正确)$ git commit -m "source remove hueman" (提交,引号为提交信息,建议提交信息以branch+message格式提交,message尽量写得清晰。)$ git push origin source(将内容提交到远端。如果提交与远端有冲突,有个解决方法是加-f参数,这会覆盖远端的内容,谨慎使用,因为覆盖不可恢复。) 经过以上四步,hueman已经从bejondshao.github.io中完全移出了。以后在hueman中的修改都不会被bejondshao.github.io的git检测到。 5. 将hexo-theme-hueman fork到自己的账号中。 6. 克隆资源库到本地。 $ git clone [email protected]:ppoffice/hexo-theme-hueman.git 会在本地创建hexo-theme-human文件夹,里面包含主题源码。将hexo-theme-human重命名为hueman。 7. 将第一步备份的文件拷贝,覆盖第六步的文件夹。这样所有自定义修改都还在。将hueman文件夹拷贝到bejondshao.github.io/themes/下。 8. 编辑hueman/.git/config如下: 12345678910111213141516[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true[remote "upstream"] url = [email protected]:ppoffice/hexo-theme-hueman.git fetch = +refs/heads/*:refs/remotes/upstream/*[remote "origin"] url = [email protected]:bejondshao/hexo-theme-hueman.git fetch = +refs/heads/*:refs/remotes/origin/*[branch "master"] remote = origin merge = refs/heads/master 编辑hueman/.gitignore,将_config.yml那一行移出,因为我们应该把_config.yml自定义的内容也提交到资源库中。 将内容提交到远端库中。我建议切一个新的分支来存储带自定义的内容。 1234$ git checkout -b bejondshao (切创建一个新分支,并切换到那个分支)$ git add .$ git commit -m "bejondshao customization"$ git push origin bejondshao:bejondshao (将本地分支bejondshao的修改提交到远端,并在远端创建bejondshao这个分支) 这样,以后更改主题,在hueman资源库中提交,不会影响hexo主体内容。 11. 以后升级主题,只需要执行: 123$ git checkout bejondshao (确保在分支bejondshao操作,正常也是在这个分支,因为基本不会用到master分支)$ git pull --rebase upstream master (将upstream那个资源的内容获取到本地,并以upstream的master分支作为当前分支的base,即实现了应用upstream的更新。)$ git push origin bejondshao (将新的内容提交到个人账户的资源库中。) 做完以上操作,已经完成处理好hexo文章和主题的分离了,执行 123$ hexo clean$ hexo g$ hexo s 或 hexo d 查看下结果吧🍺! Update: Since","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"},{"name":"Hexo","slug":"Others/Hexo","permalink":"http://bejondshao.github.io/categories/Others/Hexo/"}],"tags":[{"name":"Hexo","slug":"Hexo","permalink":"http://bejondshao.github.io/tags/Hexo/"},{"name":"Theme","slug":"Theme","permalink":"http://bejondshao.github.io/tags/Theme/"}]},{"title":"Centos7中搭建wildfly","slug":"Centos7中搭建wildfly","date":"2017-11-30T12:00:55.000Z","updated":"2023-03-02T03:26:34.074Z","comments":true,"path":"2017/11/30/Centos7中搭建wildfly/","link":"","permalink":"http://bejondshao.github.io/2017/11/30/Centos7%E4%B8%AD%E6%90%AD%E5%BB%BAwildfly/","excerpt":"","keywords":null,"text":"(一)wildfly配置 1 将wildfly文件移至/opt目录 $ sudo mv /tmp/wildfly /opt 2 创建用户。创建名为wildfly的group,创建名为wildfly的不可登录的用户,将用户加入组中。 $ sudo groupadd -r wildfly useradd -r -g wildfly -d /opt/wildfly -s /sbin/nologin wildfly 3 以下都在systemd目录下执行 12345678$ cd /opt/wildfly$ sudo mkdir -p /etc/wildfly$ sudo cp wildfly.conf /etc/wildfly/$ sudo cp wildfly.service /etc/systemd/system/$ sudo cp launch.sh /opt/wildfly/bin/$ sudo chmod +x /opt/wildfly/bin/launch.sh$ sudo chmod +x /opt/wildfly/bin/standalone.sh$ sudo chown -R wildfly:wildfly /opt/wildfly 4 启动/自启 创建服务 $ sudo systemctl enable wildfly 启动服务 $ sudo systemctl start wildfly 停止服务 $ sudo systemctl stop wildfly 查看服务状态 $ sudo systemctl status wildfly (二)防火墙相关配置 查看防火墙状态 $ sudo firewall-cmd --state 开启http $ sudo firewall-cmd --zone=public --permanent --add-service=http 开启https $ sudo firewall-cmd --zone=public --permanent --add-service=https 开放8080端口 $ sudo firewall-cmd --zone=public --permanent --add-port=8080/tcp 开放8443端口 $ sudo firewall-cmd --zone=public --permanent --add-port=8443/tcp 开启防火墙 $ sudo systemctl start firewalld.service 查看防火墙开放的端口 $ sudo firewall-cmd --zone=public --permanent --list-ports 重新加载防火墙配置 $ sudo firewall-cmd --reload Note: 如果重新加载防火墙配置没有应用配置,重启防火墙: 1234$ sudo systemctl stop firewalld.service$ sudo systemctl status firewalld.service$ sudo systemctl start firewalld.service (三)nginx安装及网站应用配置 1 安装nginx前,安装前需先安装nginx依赖PCRE 安装在usr/local/src目录下下载pcre(版本自行选择稳定版)。执行: $ sudo wget http://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.40.tar.gz 解压 tar zxvf pcre-8.40.tar.gz 进入安装目录 `$ cd pcre-8.40 编译 $ sudo ./configure 安装 $ sudo make && make install 查看版本 $ pcre-config --version 2 安装nginx 1234567$ sudo wget http://nginx.org/download/nginx-1.6.2.tar.gz$ sudo tar zxvf nginx-1.6.2.tar.gz$ cd nginx-1.6.2$ sudo ./configure --prefix=/usr/local/webserver/nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre=/usr/local/src/pcre-8.40$ sudo make && make install$ /usr/local/webserver/nginx/sbin/nginx -v 3 配置nginx 进入目录/usr/local/webserver/nginx/conf 相关配置nginx.conf检查配置是否正确 启动Nginx /usr/local/webserver/nginx/sbin/nginx -t 修改配置后重新加载生效 /usr/local/webserver/nginx/sbin/nginxnginx -s reload 重新打开日志文件 nginx -s reopen 测试nginx配置文件是否正确 nginx -t -c /path/to/nginx.conf 4 访问站点配置nginx.conf 12345678location /application {proxy_pass http://127.0.0.1:8080/application;proxy_set_header Host $host;$proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto "https";proxy_set_header X-Forwarded-Port "443";proxy_set_header X-SSL-Client-Cert $ssl_client_cert;} 5 设置nginx服务为自启动 参考CentOS设置Nginx开机自启动","raw":null,"content":null,"categories":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/categories/Linux/"}],"tags":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/tags/Linux/"},{"name":"Centos","slug":"Centos","permalink":"http://bejondshao.github.io/tags/Centos/"},{"name":"Wildfly","slug":"Wildfly","permalink":"http://bejondshao.github.io/tags/Wildfly/"}]},{"title":"Netty4.x用户指南","slug":"Netty4-x用户指南","date":"2017-11-28T07:27:24.000Z","updated":"2023-03-02T03:26:34.188Z","comments":true,"path":"2017/11/28/Netty4-x用户指南/","link":"","permalink":"http://bejondshao.github.io/2017/11/28/Netty4-x%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97/","excerpt":"","keywords":null,"text":"原文 完整翻译可参考 序言 难题 如今我们通常使用应用或类库与不同的系统交互。比如,我们通常使用HTTP客户端类库来获取web服务器的信息,通过web service调用远程服务。但是普通的协议实现通常无法完成诸如大文件,邮件信息,即时通讯比如金融信息,多玩家网络游戏等功能。这些需求都对信息处理有很高的性能要求。你可能想实现一个HTTP服务器,比如基于AJAX的聊天系统,影音媒体库,或网盘。你甚至想实现一个符合你特殊需求的协议。还有个不可避免的情况,当你需要处理一个有专利权的协议,使得它能和一个旧系统进行交互。问题是我们多久能实现这个协议,并且要保证稳定性和高性能。 解决方案 Netty就是一个致力于提供异步消息驱动的网络应用框架,用来快速开发可维护可扩展的高效的服务器与客户端协议的工具。 Netty是一个能简单快速的开发网络应用协议的NIO客户端服务器框架。它使网络编程比如TCP和UDP变得简单化,流程化。 “快速且简单”并不意味着不容易维护或性能损失。Netty借鉴于以往的FTP,SMTP,HTTP,多种二进制和基于文本的协议等的实现经验,在设计时就格外小心。所以,Netty具有易用,高性能,高可靠,稳定,灵活的特点。 有人会发现其他网络应用框架也声称有这些优点,你可能会想知道Netty与其他框架有什么不同。答案就是Netty被设计的哲学。Netty在被设计的第一天起就致力于在实现和API文档给用户最好的体验。这并不那么直观,但这种哲学会让你意识到,在你读这篇指南和使用Netty时,它让你的生活更简单。 动手试试 这章意在构建简单的Netty例子来让你快速开始。读完这章,你能基于Netty快速的写出一个客户端和服务端。 如果你想彻底的学习Netty,你应该从第二章:Architectural Overview学习。 写一个Discard服务器 DISCARD协议接收消息然后忽略。 12345678910111213141516171819202122232425package io.netty.example.discard;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;/** * Handles a server-side channel. */public class DiscardServerHandler extends ChannelInboundHandlerAdapter { // (1) @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2) // 直接忽略收到的信息。 ((ByteBuf) msg).release(); // (3) } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4) // 异常时关闭连接。 cause.printStackTrace(); ctx.close(); }} DiscardServerHandler继承ChannelInboundHandlerAdapter。ChannelInboundHandlerAdapter实现了ChannelInboundHandler。ChannelInboundHandler提供了多种事件处理方法的定义。有了ChannelInboundHandlerAdapter,只需要继承它就可以了,而不用实现ChannelInboundHandler。 在这重写channelRead()事件处理方法。当接收客户端的消息时,就会调用channelRead()。本例中,消息类型是ByteBuf ByteBuf是一个引用计数对象,需要显式调用release()释放。需要注意,通常由handler释放传给handler的引用计数的对象。通常channelRead()像这样实现: 12345678@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) { try { // 对msg的操作 } finally { ReferenceCountUtil.release(msg); }} exceptionCaught()方法在Netty产生I/O异常时被调用。通常产生异常要记录并关闭通道。当然你也可能在关闭前发送响应code和message。 现在创建一个Server和main()方法来启动服务器。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061package io.netty.example.discard;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;/** * Discards any incoming data. */public class DiscardServer { private int port; public DiscardServer(int port) { this.port = port; } public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1) EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); // (2) b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // (3) .childHandler(new ChannelInitializer<SocketChannel>() { // (4) @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new DiscardServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) // (5) .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) // 绑定开启接收接入的连接。 ChannelFuture f = b.bind(port).sync(); // (7) // 等待直到服务器socket关闭。 // 这个例子里不会发生,但是你可以平滑的关闭服务器。 f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new DiscardServer(port).run(); }} NioEventLoopGroup是一个多线程循环事件处理器。Netty提供多种EventLoopGroup实现适应不同传输协议。在服务端,通常有两个NioEventLoopGroup,第一个为boss,接收接入的连接。第二个为worker,处理boss注册的连接。至于有多少线程可以处理Channels,取决于EventLoopGroup的实现,一般可以在构造器指定。如果不指定thread数,默认是用于Netty的处理器数的两倍。 ServerBootstrap是创建Server的工具类。可以用Channel直接创建Server。但直接用Channel构建比较繁琐,还是ServerBootstrap简单。 用NioServerSocketChannel初始化Channel,接收接入的连接。 这里的handler会赋一个新的被接收的Channel。ChannelInitializer是一个特殊的handler,用来替用户配置一个新的Channel。通常你会配置新Channel的ChannelPipeline,添加些handlers比如DiscardServerHandler,来实现你的网络应用。 你可以对Channel实现设定参数。这里我们在写TCP/IP服务器,所以我们可以设定tcpNoDelay,keepAlive等参数。具体参数请参考ChannelOption和ChannelConfig option()是针对boosGroup接收的channels,也就是NioServerSocketChannel。childOption()是针对父ServerChannel所接收的channels,在这里也是NioServerSocketChannel。 绑定端口,启动服务器。这里绑定8080端口到所有的NICs(network interface cards,网卡)。你可以随意调用bind(),但需要绑定不同的端口。 看下接收的数据 测试服务器最简单的方式是在命令行输入$ telnet localhost 8080,然后输入内容。 但没法确定这个服务器好用,我们需要在服务器输出点什么来体现它好用。 我们知道,channelRead()会在接收数据时被调用,所以我们可以在DiscardServerHandler里面加打印内容: 123456789101112@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) { ByteBuf in = (ByteBuf) msg; try { while (in.isReadable()) { // (1) System.out.print((char) in.readByte()); System.out.flush(); } } finally { ReferenceCountUtil.release(msg); // (2) }} 这个循环很低效,可以被替换为: System.out.println(in.toString(io.netty.util.CharsetUtil.US_ASCII)) 这里可以替换为: in.release() 如果再telnet,就会在服务器console看到打印内容。 Discard示例源码 Echo示例 服务器一般要给客户端返回信息,我们来实现ECHO协议。其实很简单,在DiscardServerHandler里,将channelRead()改为: 12345@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) { ctx.write(msg); // (1) ctx.flush(); // (2)} ChannelHandlerContext提供多种操作,让你触发多种I/O事件和操作。这里调用write(Object)将接收的信息逐字的输出。注意这里我们没release消息。因为Netty在将消息写出去时会自动释放。 ctx.write(Object)并没有将消息写出去。消息在内部缓存了,写是由ctx.flush()做的。你可以简单的用ctx.writeAndFlush(msg)来实现。 如果你再telnet,输入内容,就会发现有消息返回给客户端。 Echo示例源码 Time服务器 实现TIME协议。这和前面不同的是,这次发送一个保护32位二进制数字的消息,不接受任何请求,并且在发送消息后关闭连接。 由于我们要忽略所接收的消息,并在连接建立时发送信息,这次不用channelRead()方法,而用channelActive()方法。 12345678910111213141516171819202122232425package io.netty.example.time;public class TimeServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(final ChannelHandlerContext ctx) { // (1) final ByteBuf time = ctx.alloc().buffer(4); // (2) time.writeInt((int) (System.currentTimeMillis() / 1000L + 2208988800L)); final ChannelFuture f = ctx.writeAndFlush(time); // (3) f.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) { assert f == future; ctx.close(); } }); // (4) } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); }} channelAction()韩剧i在连接建立时被调用。这里我们随意写一个32位数据作为当前时间。 要发送消息,需要分配新的缓冲区。由于数据是32位的,所以ByteBuf需要至少4个字节。通过ChannelHandlerContext.alloc()获取当前的ByteBufAllocator,并分配缓冲区。 记录初始化的信息。ByteBuf发送消息时不需要调用java.nio.ByteBuffer.flip()。ByteBuf没有这样的方法,因为它有两个指针,一个用于读,一个用于写。在你向ByteBuf写内容时,写指针索引会增加,读指针索引不会变。读指针索引和写指针索引代表消息的开始和结束。 相反,NIO buffer不调用flip()是没法清晰的体现消息的开始和结束的。如果你忘记调用flip(),会很糟糕,很可能消息没有发送,也可能发送错误的消息。 ChannelHandlerContext.write()和writeAndFlush()方法返回ChannelFuture。ChannelFuture代表还没发生的I/O操作。任何已请求的操作可能还没执行,因为Netty中所有的操作都是异步的。比如,下面的代码可能在消息发送前就关闭了连接: 123Channel ch = ...;ch.writeAndFlush(message);ch.close(); 所以,你需要注意,要在ChannelFuture完成后再调用close()方法。当写操作完成后,它会通知它的监听器。另外注意,close()可能不会直接关闭连接,这个方法返回的是ChannelFuture。 4. 在写请求完成后,我们怎么知道它完成了?在ChannelFuture添加一个ChannelFutureListener就行了。这里,我们添加一个匿名ChannelFutureListener用来在操作完成时关闭channel。 你可以简单的用预定义的listener: f.addListener(ChannelFutureListener.CLOSE); 测试time服务器,需要在命令行输入: $ rdate -o <port> -p <host> Time客户端 这节研究如何用Netty创建客户端。和服务端区别是Bootstrap和Channel的实现不同。 123456789101112131415161718192021222324252627282930package io.netty.example.time;public class TimeClient { public static void main(String[] args) throws Exception { String host = args[0]; int port = Integer.parseInt(args[1]); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); // (1) b.group(workerGroup); // (2) b.channel(NioSocketChannel.class); // (3) b.option(ChannelOption.SO_KEEPALIVE, true); // (4) b.handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new TimeClientHandler()); } }); // Start the client. ChannelFuture f = b.connect(host, port).sync(); // (5) // Wait until the connection is closed. f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); } }} Bootstrap和ServerBootstrap类似,不同的是Bootstrap用于非服务端,比如客户端,无连接channel。 如果你只指定一个EventLoopGroup,它将会担当boss和worker组。这里并没用到boss组。 这里用NioSocketChannel而不是NioServerSocketChannel。 这里没有childOption()因为客户端SocketChannel没有父Channel。 用connect()而非bind()。 客户端代码和服务端代码没多少差别。ChannelHandler实现要接收32位数据,转换成Date,打印出来,最后关闭连接: 1234567891011121314151617181920212223package io.netty.example.time;import java.util.Date;public class TimeClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { ByteBuf m = (ByteBuf) msg; // (1) try { long currentTimeMillis = (m.readUnsignedInt() - 2208988800L) * 1000L; System.out.println(new Date(currentTimeMillis)); ctx.close(); } finally { m.release(); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); }} 在TCP/IP中,Netty读取数据,然后存到ByteBuf里。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Netty","slug":"Netty","permalink":"http://bejondshao.github.io/tags/Netty/"}]},{"title":"ChannelHandlerContext","slug":"ChannelHandlerContext","date":"2017-11-22T11:20:32.000Z","updated":"2023-03-02T03:26:34.076Z","comments":true,"path":"2017/11/22/ChannelHandlerContext/","link":"","permalink":"http://bejondshao.github.io/2017/11/22/ChannelHandlerContext/","excerpt":"","keywords":null,"text":"io.netty.channel.ChannelHandlerContext Interface ChannelHandlerContext 12public interface ChannelHandlerContextextends AttributeMap 使得ChannelHandler可以和它所在的ChannelPipeline以及其他handlers交互。一个handler可以在ChannelPipeline中通知下一个ChannelHandler,动态更改它所属的ChannelPipeline。 通知 你可以通过调用ChannelHandlerContext的多种方法通知同一个ChannelPipeline中最近的handler。请通过ChannelPipeline了解事件是如何传递的。 修改pipeline 可以通过调用ChannelHandlerContext.pipeline()获取handler所属的ChannelPipeline。你可以在pipeline中动态的增加,移除,替换handlers。 获取ChannelHandlerContext为了以后使用 比如在handler方法外触发一个事件,甚至是在另一个线程触发事件。 12345678910111213public class MyHandler extends ChannelDuplexHandler { private ChannelHandlerContext ctx; public void beforeAdd(ChannelHandlerContext ctx) { this.ctx = ctx; } public void login(String username, password) { ctx.write(new LoginMessage(username, password)); } ...} 存储有状态的信息 AttributeMap.attr(AttributeKey)允许你存储,访问handler和context有状态的信息。请通过ChannelHandlerContext获取多种存储信息的方式。 一个handler可以属于多个contexts 不难理解,一个ChannelHandler可以被添加到多个ChannelPipeline中。也就是说一个ChannelHandler实例可以有多个ChannelHandlerContext,因此如果一个ChannelHandler实例被多次添加到一个或多个ChannelPipelines中,那么它就可以被不同的ChannelHandlerContext调用。 下面例子handler将有多个独立的AttributeKeys,其数量和它被添加到pipelines的次数是一样的。不管它是被添加到同一个pipeline多次,还是添加到不同的pipelines。 123456789101112131415161718192021222324252627282930313233public class FactorialHandler extends ChannelInboundHandlerAdapter<Integer> { private final AttributeKey<Integer> counter = new AttributeKey<Integer>("counter"); // This handler will receive a sequence of increasing integers starting // from 1. @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { Integer a = ctx.attr(counter).get(); if (a == null) { a = 1; attr.set(a); } else { attr.set(new Integer(a.intValue() + 1)); } } } // 不同的context对象都给了"f1","f2"不同的名字,即使他们都指向同一个handler实例。 // 因为FactorialHandler在context中存储了它的状态(使用AttributeKey)。 // 当p1和p2开启时,实际上这个对象被计算了4次。 FactorialHandler fh = new FactorialHandler(); ChannelPipeline p1 = Channels.pipeline(); p1.addLast("f1", fh); p1.addLast("f2", fh); ChannelPipeline p2 = Channels.pipeline(); p2.addLast("f3", fh); p2.addLast("f4", fh); 更多资源 可以参考ChannelHandler和ChannelPipeline查阅更多关于inbound和outbound操作的信息,它们有什么不同的功能,它们在pipeline中是如何流通的,它们是如何在应用中处理操作的。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Netty","slug":"Netty","permalink":"http://bejondshao.github.io/tags/Netty/"}]},{"title":"ChannelPipeline","slug":"ChannelPipeline","date":"2017-11-22T11:19:28.000Z","updated":"2023-03-02T03:26:34.076Z","comments":true,"path":"2017/11/22/ChannelPipeline/","link":"","permalink":"http://bejondshao.github.io/2017/11/22/ChannelPipeline/","excerpt":"","keywords":null,"text":"io.netty.channel.ChannelPipeline Interface ChannelPipeline 12public interface ChannelPipeline extends java.lang.Iterable<java.util.Map.Entry<java.lang.String,ChannelHandler>> ChannelPipeline是个ChannelHandler的集合,用来处理拦截Channel中的inbound事件和outbound操作。ChannelPipeline实现了一个高级的拦截过滤模式,给用户全面的控制一个事件是如何被处理的,以及多个ChannelHandlers在一个管道里是如何交互的。 创建一个pipeline 每个channel都有自己的pipeline,在创建channel时就自动创建pipeline。 事件在pipeline中是怎么流通的 I/O事件由ChannelInboundHandler或ChannelOutboundHandler处理的,并调用ChannelHandlerContext的事件传播方法(比如ChannelHandlerContext.fireChannelRead(Object), ChannelHandlerContext.write(Object))传到最近的handler。 一个inbound事件由inbound handlers(图中左边自下而上的方式)处理。一个inbound handler通常处理由图表底部的I/O线程生成的inbound数据。inbound数据通常由远程端点读取,通常是一个实际的输入操作,例如SocketChannel.read(ByteBuffer)。如果inbound事件继续向上超过了顶部界限,就会被忽略掉,或者日志记录下来。 一个outbound事件由outbound handler(图中右边自上而下的方式) 处理。一个outbound handler通常生成或转换outbound信息,比如写请求。如果outbound事件继续向下超过了底部的界限,就会被与Channel相关的I/O线程处理。I/O线程通常执行实际的操作,比如SocketChannel.write(ByteBuffer)。 举个例子,我们创建如下的pipeline: 123456ChannelPipeline p = ...;p.addLast("1", new InboundHandlerA());p.addLast("2", new InboundHandlerB());p.addLast("3", new OutboundHandlerA());p.addLast("4", new OutboundHandlerB());p.addLast("5", new InboundOutboundHandlerX()); 上面的例子中,Inbound意味着是inbound handler,outbound意味着是outbound handler。当事件为inbound时,执行流程是1,2,3,4,5。当事件是outbound时,执行流程是5,4,3,2,1。在此基础上,ChannelPipeline自动跳过不相干的handlers来简化过程: 3和4没有实现ChannelInboundHandler,因此inbound事件只会执行1,2,5。 1和2没有实现ChannelOutboundHandler,因此outbound事件只会执行5,4,3。 如果5实现了ChannelInboundHandler和ChannelOutboundHandler,那么inbound和outbound事件都会包括5。 将一个事件传递到下一个handler 一个handler需要调用ChannelHandlerContext中的事件传递方法来将事件传给下一个handler。这些方法包括: Inbound事件传递方法: ChannelHandlerContext.fireChannelRegistered() ChannelHandlerContext.fireChannelActive() ChannelHandlerContext.fireChannelRead(Object) ChannelHandlerContext.fireChannelReadComplete() ChannelHandlerContext.fireExceptionCaught(Throwable) ChannelHandlerContext.fireUserEventTriggered(Object) ChannelHandlerContext.fireChannelWritabilityChanged() ChannelHandlerContext.fireChannelInactive() ChannelHandlerContext.fireChannelUnregistered() Outbound事件传递方法: ChannelHandlerContext.bind(SocketAddress, ChannelPromise) ChannelHandlerContext.connect(SocketAddress, SocketAddress, ChannelPromise) ChannelHandlerContext.write(Object, ChannelPromise) ChannelHandlerContext.flush() ChannelHandlerContext.read() ChannelHandlerContext.disconnect(ChannelPromise) ChannelHandlerContext.close(ChannelPromise) ChannelHandlerContext.deregister(ChannelPromise) 例如: 123456789101112131415public class MyInboundHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) { System.out.println("Connected!"); ctx.fireChannelActive(); }}public class MyOutboundHandler extends ChannelOutboundHandlerAdapter { @Override public void close(ChannelHandlerContext ctx, ChannelPromise promise) { System.out.println("Closing .."); ctx.close(promise); }} 创建一个pipeline 用户在一个pipeline中可以有一个或多个ChannelHandlers来接收I/O事件(比如读)以及请求I/O操作(比如写和关闭)。例如一般的channel pipeline中通常有一下几个handlers: ProtocolDecoder - 将二进制数据(比如ByteBuf)转换成Java对象。 ProtocolEncoder - 将Java对象转换为二进制数据。 业务逻辑handler - 实际的业务相关的处理。 举个例子: 1234567891011static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);...ChannelPipeline pipeline = ch.pipeline();pipeline.addLast("decoder", new MyProtocolDecoder());pipeline.addLast("encoder", new MyProtocolEncoder());// 告知pipeline在另一个线程执行MyBusinessLogicHandler事件处理方法而不是一个I/O线程。防止线程// 被耗时间的任务阻塞。如果业务逻辑是完全异步的或很快完成,就不需要指定group。pipeline.addLast(group, "handler", new MyBusinessLogicHandler()); 线程安全 一个ChannelHandler可以在任何时候被添加或移除,因为ChannelPipeline是线程安全的。比如你可以在敏感信息需要加密时添加加密handler,在转换完成后移除这个handler。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Netty","slug":"Netty","permalink":"http://bejondshao.github.io/tags/Netty/"}]},{"title":"ChannelHandler","slug":"ChannelHandler","date":"2017-11-22T11:18:02.000Z","updated":"2023-03-02T03:26:34.075Z","comments":true,"path":"2017/11/22/ChannelHandler/","link":"","permalink":"http://bejondshao.github.io/2017/11/22/ChannelHandler/","excerpt":"","keywords":null,"text":"io.netty.channel.ChannelHandler Interface ChannelHandler 1public interface ChannelHandler 处理I/O事件,或者拦截I/O操作,并传到它的ChannelPipeline中的下一个handler。 Sub-types ChannelHandler本身并没提供很多方法。要处理ChannelInboundInvoker或者ChannelOutboundInvoker操作,你需要实现ChannelHandler的子接口。最常用的是: @ ChannelInboundHandlerAdapter,处理并拦截inbound操作。 @ ChannelOutboundHandlerAdapter,处理并拦截outbound操作。 Context object ChannelHandler由一个ChannelHandlerContext对象提供。通过context对象,ChannelHandler可以和ChannelPipeline沟通。ChannelHandler可以通过context上行,下行传递事件,动态更改pipeline,或者将信息(使用AttributeKeys)存储到handler中。 State management ChannelHandler一般需要存储状态信息。最简单的方式是使用成员变量。 123456789101112131415161718192021222324public interface Message { // your methods here } public class DataServerHandler extends SimpleChannelInboundHandler<Message> { private boolean loggedIn; @Override public void channelRead0(ChannelHandlerContext ctx, Message message) { Channel ch = e.getChannel(); if (message instanceof LoginMessage) { authenticate((LoginMessage) message); loggedIn = true; } else (message instanceof GetDataMessage) { if (loggedIn) { ch.write(fetchSecret((GetDataMessage) message)); } else { fail(); } } } ... } 由于handler实例有一个状态变量,和每个connection相关联,你必须对每个新的channel创建新的handler实例,防止未授权的客户端获取机密信息: 12345678// Create a new handler instance per channel.// See ChannelInitializer.initChannel(Channel).public class DataServerInitializer extends ChannelInitializer<Channel> { @Override public void initChannel(Channel channel) { channel.pipeline().addLast("handler", new DataServerHandler()); }} 使用AttributeKey 建议使用成员变量存储handler的数据,有时候你可能不想创建很多的handler实例,这时你可以使用ChannelHandlerContext提供的AttributeKeys 1234567891011121314151617181920212223242526public interface Message { // your methods here } @Sharable public class DataServerHandler extends SimpleChannelInboundHandler<Message> { private final AttributeKey<Boolean> auth = AttributeKey.valueOf("auth"); @Override public void channelRead(ChannelHandlerContext ctx, Message message) { Attribute<Boolean> attr = ctx.attr(auth); Channel ch = ctx.channel(); if (message instanceof LoginMessage) { authenticate((LoginMessage) o); attr.set(true); } else (message instanceof GetDataMessage) { if (Boolean.TRUE.equals(attr.get())) { ch.write(fetchSecret((GetDataMessage) o)); } else { fail(); } } } ... } 既然heandler的state已经和ChannelHandlerContext绑定,就可以给不同的pipelines添加相同的handler实例: 123456789public class DataServerInitializer extends ChannelInitializer<Channel> { private static final DataServerHandler SHARED = new DataServerHandler(); @Override public void initChannel(Channel channel) { channel.pipeline().addLast("handler", SHARED); }} @Sharable注解 如果一个ChannelHandler声明为Sharable,就可以创建一个handler实例,把它加到不同的ChannelPipelines。如果不加这个注解,在向pipeline加handler时,需要创建新的handler实例,因为它可能有不能共享的数据,比如成员变量。 更多资料 请参考ChannelPipeline有关inbound和outbound操作的信息,它们的功能有什么区别,它们在pipeline是如何运作的,如何处理操作。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Netty","slug":"Netty","permalink":"http://bejondshao.github.io/tags/Netty/"}]},{"title":"Channel","slug":"Channel","date":"2017-11-22T11:16:23.000Z","updated":"2023-03-02T03:26:34.075Z","comments":true,"path":"2017/11/22/Channel/","link":"","permalink":"http://bejondshao.github.io/2017/11/22/Channel/","excerpt":"","keywords":null,"text":"io.netty.channel.Channel Interface Channel 12public interface Channelextends AttributeMap, java.lang.Comparable<Channel> Channel是一个网络socket的连接,一个组件,可以处理一些I/O操作,比如读,写,连接,绑定。 Channel会给一个user提供: 当前channel的状态(open? connected?) channel的配置参数(ChannelConfig,接收数据的尺寸) channel所支持的I/O操作 和当前chennel绑定的ChannelPipeline,用于处理所有的I/O事件和请求 所有I/O操作都是异步的 Netty中所有I/O操作都是异步的。也就是说所有I/O调用都会直接的返回,不能保证I/O请求在返回的时候已经完成,返回的结果有个ChannelFuture实例,这个ChannelFuture实例提醒你所请求的操作是否成功,失败或者取消。 Channels都是阶级分明的 一个Channel可以有一个parent,表示它是如何创建的。比如一个ServerSocketChannel创建一个SocketChannel,socketChannel.parent()就会返回ServerSocketChannel。 等级结构的意义取决于传输实现。比如你可以写一个新的Channel实现,创建sub-channels共享一个socket连接,比如BEEP和SSH。 向下转换,来访问特定的操作 一些传输暴露额外传输相关的操作。将Channel向下转换成子类型来调用相关操作。比如旧的I/O数据报传输,多播加入、离开操作是由DatagramChannel提供的。 释放资源 调用close()或close(ChannelPromise)是重要的,当Channel工作完成时,释放所有资源,保证所有资源都恰当的被释放。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Netty","slug":"Netty","permalink":"http://bejondshao.github.io/tags/Netty/"}]},{"title":"Hueman主题升级","slug":"Hueman主题升级","date":"2017-11-13T12:38:22.000Z","updated":"2023-03-02T03:26:34.085Z","comments":true,"path":"2017/11/13/Hueman主题升级/","link":"","permalink":"http://bejondshao.github.io/2017/11/13/Hueman%E4%B8%BB%E9%A2%98%E5%8D%87%E7%BA%A7/","excerpt":"","keywords":null,"text":"下载hueman源码,将hueman源码包复制到themes文件夹下 移植_config.yml 由于我使用的hueman主题版本比较旧,之前hueman配置文件是和hexo的_config.yml是一个文件。升级后在themes/hueman/下有新的_config.yml.example,把这个文件重命名为_config.yml,根据自己需要更改。 增加不蒜子统计 增加站点统计 编辑themes/hueman/layout/common/footer.ejs,将 1<p>Powered by <a href="//hexo.io/" target="_blank">Hexo</a>. Theme by <a href="//github.com/ppoffice" target="_blank">PPOffice</a></p> 更改为 12345678<p>Powered by <a href="//hexo.io/" target="_blank">Hexo</a>. Theme by <a href="//github.com/ppoffice" target="_blank">PPOffice</a> <span id="busuanzi_container_site_pv"> 本站总访问量<span id="busuanzi_value_site_pv"></span>次 </span> <span id="busuanzi_container_site_uv"> 你是本站第<span id="busuanzi_value_site_uv"></span>个访客 </span></p> 增加文章统计 编辑themes/hueman/layout/common/article.ejs,将 123<div class="article-entry" itemprop="articleBody"> <%- post.content %></div> 更改为 123456<div class="article-entry" itemprop="articleBody"> <%- post.content %></div><div class="article-entry" id="busuanzi_container_page_pv"> 本文总阅读<span id="busuanzi_value_page_pv"></span>次</div>","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"Hexo","slug":"Hexo","permalink":"http://bejondshao.github.io/tags/Hexo/"},{"name":"Hueman","slug":"Hueman","permalink":"http://bejondshao.github.io/tags/Hueman/"}]},{"title":"How to Install Wildfly as System Service","slug":"How-to-Install-Wildfly-as-System-Service","date":"2017-11-07T08:49:15.000Z","updated":"2023-03-02T03:26:34.082Z","comments":true,"path":"2017/11/07/How-to-Install-Wildfly-as-System-Service/","link":"","permalink":"http://bejondshao.github.io/2017/11/07/How-to-Install-Wildfly-as-System-Service/","excerpt":"","keywords":null,"text":"The latest wildfly is wildfly-11.0.0.Final. Acutally the tutorial is located in jboss.home.dir/docs/contrib/scripts. There are init.d way and systemd way. There’s also a service way which used for Windows system. As I just tried the systemd way, so I just introduce it. Open systemd/README file, it says clearly: == How to configure WildFly as a systemd service == Create a wildfly user # groupadd -r wildfly # useradd -r -g wildfly -d /opt/wildfly -s /sbin/nologin wildfly == Install WildFly # tar xvzf wildfly-11.0.0.Final.tar.gz -C /opt # ln -s /opt/wildfly-11.0.0.Final /opt/wildfly # chown -R wildfly:wildfly /opt/wildfly == Configure systemd # mkdir /etc/wildfly # cp wildfly.conf /etc/wildfly/ # cp wildfly.service /etc/systemd/system/ # cp launch.sh /opt/wildfly/bin/ # chmod +x /opt/wildfly/bin/launch.sh == Start and enable # systemctl start wildfly.service # systemctl enable wildfly.service After you execute the commands above, you would probably get some error: Failed to execute operation: Access denied when executing “systemctl start wildfly” I can’t come up with the solution with google, I just reboot and it is gone. service started failed, and log file says java.lang.RuntimeException: java.net.UnknownHostException: centostest: centostest: Name or service not known. This error is just because of the host name is not added to hosts file. I came up with a workaround with add 127.0.0.1 centostest to /etc/hosts file. The application can be visited by http://127.0.0.1:8080/app but can’t be visit by local network PCs. You need to modify jboss.home.dir/standalone/configuration/standalone.xml, search the interfaces element, edit like this: 12345678<interfaces> <interface name="management"> <inet-address value="${jboss.bind.address.management:127.0.0.1}"/> </interface> <interface name="public"> <!--<inet-address value="${jboss.bind.address:127.0.0.1}"/>--> <any-address/> </interface> And restart service by: # systemctl restart wildfly 4. If you still can’t visit the application, it might be firewall issue. You can disable firewall to check if it works: # systemctl stop firewalld.service (for redhat/centos) # ufw disable (for debain/ubuntu) If it works, you just need to add port 8080 and 8443 to firewall(Below is just for redhat/centos). a. enable firewall sudo systemctl start firewalld.service b. enable http $ sudo firewall-cmd —zone=public —permanent —add-service=http c. enable https sudo firewall-cmd —zone=public —permanent —add-service=https d. open port 8080 sudo firewall-cmd —zone=public —permanent —add-port=8080/tcp e. open port 8443 sudo firewall-cmd —zone=public —permanent —add-port=8443/tcp f. reload firewall configuration sudo firewall-cmd —reload For debain/ubuntu: a. enable firewall sudo ufw enable b. enable http sudo ufw allow http c. enable https sudo ufw allow https d. open port 8080 and 8443 sudo ufw allow 8080/tcp sudo ufw allow 8442/tcp e. reload configuration sudo rfw reload","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Wildfly","slug":"Wildfly","permalink":"http://bejondshao.github.io/tags/Wildfly/"}]},{"title":"Keycloak开发环境搭建","slug":"Keycloak开发环境搭建","date":"2017-11-01T01:55:00.000Z","updated":"2023-03-02T03:26:34.143Z","comments":true,"path":"2017/11/01/Keycloak开发环境搭建/","link":"","permalink":"http://bejondshao.github.io/2017/11/01/Keycloak%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/","excerpt":"","keywords":null,"text":"克隆Keycloak源码 git clone [email protected]:keycloak/keycloak.git Build项目 mvn clean install -Pdistribution -DskipTests=True Keycloak包会编译到distribution中,在server-dist/target/keycloak-会找到一个wildfly结构的keycloak server。 Build出的包直接启动会报moudule keycloak-server-subsystem not found,需要在/keycloak-xxx/modules/目录下创建layers.conf文件,文件内容为: layers=keycloak 修改Keycloak数据库,以Postgresql为例: a. 在keycloak-/modules/system/layers/base/org/下创建文件夹postgresql,在postgresql下创建文件夹main。 b. 到maven库下载postgresql对应版本的驱动,比如https://mvnrepository.com/artifact/org.postgresql/postgresql/9.4.1212 ,放到main目录下。 c. 在main目录下创建module.xml文件,内容为: 1234567891011<?xml version="1.0" encoding="UTF-8"?><module xmlns="urn:jboss:module:1.3" name="org.postgresql"> <resources> <resource-root path="postgresql-9.4-1212.jar"/> <!-- Insert resources here --> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> </dependencies></module> d. 编辑keycloak-/standalone/configuration/standalone.xml文件,更改数据库: 找到<subsystem xmlns="urn:jboss:domain:datasources:5.0">,将datasources替换为: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true"> <connection-url>jdbc:postgresql://127.0.0.1:5432/keycloak_ExampleDS</connection-url> <driver>postgresql</driver> <pool> <min-pool-size>10</min-pool-size> <max-pool-size>20</max-pool-size> <prefill>false</prefill> <use-strict-min>false</use-strict-min> <flush-strategy>FailingConnectionOnly</flush-strategy> </pool> <security> <user-name>postgres</user-name> <password>369</password> </security> <validation> <check-valid-connection-sql>SELECT 1</check-valid-connection-sql> <validate-on-match>false</validate-on-match> <background-validation>false</background-validation> <use-fast-fail>false</use-fast-fail> </validation> </datasource> <datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true"> <connection-url>jdbc:postgresql://127.0.0.1:5432/keycloak</connection-url> <driver>postgresql</driver> <pool> <min-pool-size>10</min-pool-size> <max-pool-size>20</max-pool-size> <prefill>false</prefill> <use-strict-min>false</use-strict-min> <flush-strategy>FailingConnectionOnly</flush-strategy> </pool> <security> <user-name>postgres</user-name> <password>369</password> </security> <validation> <check-valid-connection-sql>SELECT 1</check-valid-connection-sql> <validate-on-match>false</validate-on-match> <background-validation>false</background-validation> <use-fast-fail>false</use-fast-fail> </validation> </datasource> <drivers> <driver name="h2" module="com.h2database.h2"> <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class> </driver> <driver name="postgresql" module="org.postgresql"> <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class> </driver> </drivers></datasources> 其中connection-url改为相应的server和数据库。 5. 至此,配置完成,进入keycloak-/bin/,启动 standalone.sh(.bat)即可访问http://localhost:8080/auth 。 如果在启动时出现 123456Caused by: org.jboss.modules.ModuleNotFoundException: org.keycloak.keycloak-server-subsystem at org.jboss.modules.ModuleLoader.loadModule(ModuleLoader.java:294) at org.jboss.modules.ModuleLoader.loadModule(ModuleLoader.java:280) at org.jboss.as.controller.parsing.DeferredExtensionContext.loadModule(DeferredExtensionContext.java:111) ... 10 more 问题,参考Stackoverflow解答,需要在keycloak-/modules/目录下创建文件layers.conf,内容如下: 1layers=keycloak 下面有人解释说:这样做是在wildfly中开启keycloak subsystem模块。否则所有的keycloak类都无法被加载。这个文件在编译时没有被拷贝,很是奇怪。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"Hexo使用经验","slug":"Hexo使用经验","date":"2017-10-27T11:38:00.000Z","updated":"2023-03-04T12:21:05.303Z","comments":true,"path":"2017/10/27/Hexo使用经验/","link":"","permalink":"http://bejondshao.github.io/2017/10/27/Hexo%E4%BD%BF%E7%94%A8%E7%BB%8F%E9%AA%8C/","excerpt":"","keywords":null,"text":"本文仅做使用Hexo时遇到的问题汇总,如果对你有帮助,那就有吧😅。 Hexo官方安装方式 $ npm install hexo-cli -g 注意是是普通用户,如果安装时遇到权限问题,请想尽办法解决。不要用root安装,会出各种奇怪的问题。 安装后,写好文章,在执行 hexo deploy 后,出现 error deployer not found:git 的错误。 $ npm install hexo-deployer-git --save 如果hexo deploy后,输入网站域名,显示404了,但是通过url访问页面还能访问到。 123$ hexo clean$ hexo g$ hexo d 再访问试试 在不同系统下,比如OS X和Linux,package-lock.json是不一样的。我建议把package-lock.json加入.gitignore中。 在package-lock.json所在目录执行一下命令: 1234$ cp package-lock.json ~/package-lock.json$ git checkout package-lock.json$ git reset package-lock.json$ git rm --cached package-lock.json 编辑 .gitignore,在末尾填入package-lock.json 12345$ cp ~/package-lock.json .$ rm -f ~/package-lock.json$ git add .$ git commit -m "source the text you want to add"$ git push origin -f source 不同系统下,比如OS X和Linux,package.json不同,一定要保证两个环境都是用相同版本的Hexo和插件。建议都升到最新版,以后定时统一升级。 增加Emoji支持 使用hexo-renderer-markdown-it-plus 12npm un hexo-renderer-marked --savenpm i hexo-renderer-markdown-it-plus --save 编辑_config.yml,添加 12345678910markdown_it_plus: highlight: true html: true xhtmlOut: true breaks: true langPrefix: linkify: true typographer: quotes: “”‘’ pre_class: highlight 然后到这里或这里 查找emoji code,粘贴到文章即可。 我一开始使用hexo-renderer-markdown-it插件会有两个问题,一个问题是段落之间如果不加空行,会合并成一段,也就是整篇文章都成了一段,导致以前的文章都需要作调整。二个问题是无法使用粗体标志,相信其他标志也无法完美使用,需要在**前加空格,很是麻烦,后来使用hexo-renderer-markdown-it-plus就没有这些问题。 But there’s another issue you might meet LaTeX-incompatible input and strict mode is set to 'warn': Unicode text character "符" used in math mode [unicodeTextInMathMode]. It is due to Unicode text between double $, e.g. $xxx,符xxx$. You might not input it intendedly. So try to add `` before and after $ to make it not rendered. Hexo使用站内链接 1{% post_link hello-world Hello World %} hello-world是你的文章名称。如果文章不存在,这段代码将会被直接忽略。 Hello World是要展示的文字,如果不填,默认取引用文章标题。 示例:Hello World Hexo文章插入图片 详见如何在Hexo文章中插入图片 hexo-admin插件,可以本地可视化编辑文章。 hexo-admin可配置文章自定义参数,在博客_config.yml里添加 123metadata: categories: 杂记 comments: true 即可,需要重启hexo生效。 categories配置创建文章的默认类别,该属性是数组,如果想配置文章到默认的二级类别则为categories: [杂记,生活]。comments为是否开启文章评论功能,添加后即可在hexo-admin后台设定属性(comments即便不设定,如果博客开启评论功能,也是所有文章默认都开启的,这样配置则方便在hexo-admin设置某篇文章不开启comment,就不需要手动修改文章markdown文件了)。这些默认值需要通过hexo-admin方式创建文章才会设定默认值。如果是通过hexo new abc来创建文章,则打开hexo-admin文章这些配置默认值不生效,需要手动设定。另外使用hexo-admin创建文章还有个好处,会自动在draft里创建文章同名文件夹,可以放图片资源,在文章就可以引用了。如果文件夹里没有放图片资源,那么publish时就不会拷贝这个空文件夹到public目录下,稍微有点小遗憾😔。 Metadata功能,可以在_config.yml里添加诸如默认category的功能(因为hexo的默认category功能好像不好用) 12metadata: categories: Others 发现原来一个文章可以添加多个categories,比如: 123categories:- Others- SubCategory 其中SubCategory就是Others菜单的二级菜单。 hexo升级 12$ npm update hexo$ npm install -g --save hexo 会安装hexo的依赖,如果有warn提示其他包过期,需要使用npm update xxx方法更新包,不一定需要安装。另外需要注意package.json中使用的插件是否与当前hexo版本兼容。我一般不升级,因为升级都往往有些意料不到的问题,尤其用开源工具以及其他开源插件。不过还是要感谢做这些工具的开发者,他们是技术发展的推动者和贡献者。 hexo主题升级 参考如何将hexo与theme代码分开提交。 一键提交更新网站脚本 123456789101112131415#!/bin/bash# bejondshao.github.ioHOME=/rootLOGNAME=rootPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/binLANG=en_US.UTF-8SHELL=/bin/bashPWD=/rootcd /absolute_path/to/bejondshao.github.iogit statusgit add .git commit -m "source post"git pull --rebase origin sourcegit push origin sourcehexo g && hexo d 存为abc.sh将文件赋予执行权限 $ sudo chmod +x abc.sh 每日定时执行脚本 $ sudo crontab -e 然后编辑,设定 10 3 * * * /absolute_path/to/script 每天早晨三点执行上面更新脚本。参考博客和博客。为了防止某次提交出现网络问题,可以设置每隔10分钟执行。本地测试举例: 1*/10 * * * * /bin/bash /Users/alpha/abc/abc.sh 2>LOG_FILE > /Users/alpha/abc/abc.txt /bin/bash是使用bash执行脚本。crontab默认使用/bin/sh执行脚本。如果使用默认的shell,可以这样配置: 1*/10 * * * * /Users/alpha/abc/abc.sh 2>LOG_FILE > /Users/alpha/abc/abc.txt 2>LOG_FILE > /Users/alpha/abc/abc.txt是记录脚本执行输出内容,方便查看脚本是否执行,执行的情况。 注意: 脚本路径需要是绝对路径,脚本内的路径可以设定PATH,但是如无必要,建议使用绝对路径。 脚本里的HOME, LOGNAME, PATH, LANG, SHELL, PWD需要设定。不设定的话,后面的hexo相关的命令不会执行,即只能将源码推到资源库,但是没法更新网站。 执行计划任务时电脑不可以是sleep或关机。 脚本可能会有时不时无法将源码推到资源库的情况,有可能是执行git pull时出错,检查网络或者.git/config。也可能是执行git push出错,检查当前git用户是否有权限向资源库推送,必要时在github资源库上添加Collaborator。 Hexo server可以启动多个服务 指定另外一个端口即可,使用命令: hexo s -p 4001 hexo-admin插件可以设置登录账号密码 在Settings里,输入值后可以贴到_config.yml里,每次访问就需要登录。在家用不着,如果你想把hexo server部署到服务器,可以发布出去,在任意浏览器访问后台发布内容,这个功能就很有必要。 还可以使用路由器申请DDNS,申请一个二级域名,如果有个人域名可以指向该域名。然后再开启虚拟服务器,就可以访问域名加端口,访问本机的应用,当然也可以访问到hexo-admin。省去租服务器的钱了。但是要注意,偶尔用用可以,如果做涉及到广告商业或者其他用途,被宽带商监测到会发函警告的,我见网上有人被发函了,理由就是私自架设Web服务。 Comment 评论功能我以前没开启,后来想开启,大概看了有几种方式: 第三方评论服务(Disqus,有言,多说等,优点是可注册授权,缺点是服务不稳定。) Staticman(以pull request的方式在github的资源库创建issues,好处是不需要注册登录,可手动审核评论,坏处是没法注册登录。本想使用这种方式,但是配置时官方服务失效,作罢。) git issues(有gitment, ghpages-ghcomments等,在github的资源库创建issues。其他人评论则以comment的形式出现,没有验证博主是否有权利删除他人评论。需要注册登录github。) Valine(使用LeanCloud作为数据库存储。好处是不需要注册,绝大多数Hexo主题都已支持,可以直接启动配置项即可。另外建议结合Valine-Admin一起使用,可视化管理评论。) 禁用某个文章评论功能,在文章头部添加comments: false即可。","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"},{"name":"Hexo","slug":"Others/Hexo","permalink":"http://bejondshao.github.io/categories/Others/Hexo/"}],"tags":[{"name":"Hexo","slug":"Hexo","permalink":"http://bejondshao.github.io/tags/Hexo/"}]},{"title":"安装ubuntu后需要做的事","slug":"1安装ubuntu后需要做的事","date":"2017-10-27T10:45:10.000Z","updated":"2023-03-02T03:26:34.066Z","comments":true,"path":"2017/10/27/1安装ubuntu后需要做的事/","link":"","permalink":"http://bejondshao.github.io/2017/10/27/1%E5%AE%89%E8%A3%85ubuntu%E5%90%8E%E9%9C%80%E8%A6%81%E5%81%9A%E7%9A%84%E4%BA%8B/","excerpt":"","keywords":null,"text":"@ 安装linux前墙裂建议将/home单独分区,墙裂建议。 @ 修改root用户密码 $ sudo passwd root @ 安装软件需要依赖时可以执行,依赖和软件包就都安装好了 $ sudo apt-get -f install @ 安装过程需要找依赖包,也可以到https://packages.ubuntu.com/#search_contents 找。 @ 安装wineQQ(https://pan.baidu.com/s/1c2Mvxyo) $ sudo dpkg -i fonts-wqy-microhei_0.2.0-beta-2_all.deb ttf-wqy-microhei_0.2.0-beta-2_all.deb wine-qqintl_0.1.3-2_i386.deb 安装后在手机端取消设备锁才能登录 @ WizNote(比较好用的同步笔记) 1234$ sudo add-apt-repository ppa:wiznote-team$ sudo apt-get update$ sudo apt-get install wiznote$ WizNote @ clipman(记录粘贴板历史,墙裂推荐) $ sudo apt-get install xfce4-clipman @ haroopad(http://pad.haroopress.com/user.html 比较好用的本地markdown编辑器) @ geany(比较好用的编辑器,不geek。不过还是推荐学习vi/vim,否则关键时刻容易尴尬) $ sudo apt-get install geany @ ubuntu修改开机等待时间 编辑 /etc/default/grub文件 1234567GRUB_DEFAULT=0#GRUB_HIDDEN_TIMEOUT=0GRUB_HIDDEN_TIMEOUT_QUIET=trueGRUB_TIMEOUT=10GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"GRUB_CMDLINE_LINUX="" GRUB_DEFAULT=0,表示启动默认项是第一个系统 GRUB_TIMEOUT=10表示等待时间,改为你想要的数字 更新grub.cfg,执行 # update-grub 即可。 @ deadbeaf(DSD音乐播放器) @ git(文件版本管理工具) $ sudo apt-get install git @ gitk(git图形界面工具) $ sudo apt-get install gitk @ meld(diff比较工具) $ sudo apt install meld @ rdesktop(linux to windows远程桌面工具) $ sudo apt-get install rdesktop @ xrdp(windows to linux远程桌面工具) $ sudo apt-get install xrdp @ npm(你怕吗) $ sudo apt install npm @ 安装最新的node 12$ sudo npm install n -g$ sudo n stable @ 安装hexo(比较好用的git pages工具,npm最好不要用root执行) 123$ sudo chmod 777 /usr/local/lib/node_modules$ sudo chmod 777 /usr/local/lib$ npm install hexo-cli -g @ systemback(系统备份软件,有了它,下次装系统就不用看这篇文章了) 123$ sudo add-apt-repository ppa:nemh/systemback$ sudo apt-get update$ sudo apt-get install systemback @ docky(桌面panel工具) $ sudo apt-get install docky @ filezilla(ftp客户端) $ sudo apt-get install filezilla @ unar 解压中文名的windows下打包的zip文件无乱码 $ sudo apt-get install unar @ Nutstore(跨平台网盘) @ 搜狗输入法(原文连接:http://blog.topspeedsnail.com/archives/6955) Linux版的搜狗输入法和Fcitx有冲突,在安装前移除fcitx: 12345$ sudo apt remove fcitx*$ sudo apt purge fcitx*$ sudo apt autoremove$ rm -rf .sogouinput/ .config/fcitx .config/fcitx-qimpanel/ .config/sogou-qimpanel/ .config/SogouPY .config/SogouPY.users/$ reboot 官网下载安装包。 安装输入法 123$ sudo dpkg -i sogoupinyin*.deb$ sudo apt -f install$ reboot @ 谷歌拼音,如果上面搜狗输入法安装总是不起作用,无法输入中文或者输入后选项是乱码,只能使用谷歌输入法了。 $ sudo apt-get install fcitx-googlepinyin 安装后重启fcitx,在Configure里配置谷歌拼音。 @ cmake(C/C++编译打包工具) sudo apt install cmake @ fcitx-cloudpinyin(fcitx云拼音插件,非必须) 源码编译方式安装 下载源码 git clone [email protected]:fcitx/fcitx-cloudpinyin.git 编译 1234cd fcitx-cloudpinyinmkdir _buildcd _buildcmake .. 如果执行cmake … 报下面错: CMake Error at CMakeLists.txt:5 (find_package): By not providing “FindFcitx.cmake” in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by “Fcitx”, but CMake did not find one. Could not find a package configuration file provided by “Fcitx” (requested version 4.2.8) with any of the following names: FcitxConfig.cmake fcitx-config.cmake Add the installation prefix of “Fcitx” to CMAKE_PREFIX_PATH or set “Fcitx_DIR” to a directory containing one of the above files. If “Fcitx” provides a separate development package or SDK, be sure it has been installed. 需要安装fcitx-libs-dev sudo apt-get install fcitx-libs-dev 再执行cmake ..遇到 – Checking for module ‘libcurl’ – No package ‘libcurl’ found 安装libcurl4-gnutls-dev sudo apt-get install libcurl4-gnutls-dev 再执行cmake ..成功 安装 12makesudo make install 命令行安装 sudo apt-get install fcitx-module-cloudpinyin(我是安装好之后才找到这个方法的😂) 安装成功后可以在add-on找到。 双击cloud-pinyin,修改search engine,使用Baidu,尤其是国内地名,百度比谷歌好用。","raw":null,"content":null,"categories":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/categories/Linux/"}],"tags":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/tags/Linux/"}]},{"title":"通过VPS+SSH科学上网(翻墙)","slug":"通过VPS-SSH科学上网-翻墙","date":"2017-10-23T09:21:22.000Z","updated":"2023-03-02T03:26:34.259Z","comments":true,"path":"2017/10/23/通过VPS-SSH科学上网-翻墙/","link":"","permalink":"http://bejondshao.github.io/2017/10/23/%E9%80%9A%E8%BF%87VPS-SSH%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91-%E7%BF%BB%E5%A2%99/","excerpt":"","keywords":null,"text":"之前一直用的蓝灯,免费的一个终端每月500M流量。的确很好用,可以"管理系统代理",即电脑内的软件都可以畅通无阻,也可以设定https或socks代理,这样浏览器配置后就可以访问了,系统其他软件不受影响。蓝灯另外个优点是"代理部分流量",就是只在访问被封的资源时走蓝灯,其他走默认网络,这样访问国内资源快,且不会被限制使用国内服务。免费的使用谷歌速度尚可,看视频是不可能的。 后来,蓝灯不好用了,也不知道哪天能好用。 有好多VPN服务商,也有好多山寨VPN,好多就是试用前期嗷嗷快,付费后就要么登不上,要么总掉线,要么很卡,甚至多一段时间停止服务跑路了。当然也有靠谱的VPN,一个月100左右,用不起。所以只能自己租个VPS来用了。 VPS的选择 我只有一条建议:不要过分相信推荐,更不要选排名靠前的服务商。排名靠前的弊端是用户扎堆,服务器超额销售,网络带宽不足,流量明显,可能整个ip段被加入TGW中。 我举个反面教材,vultr,有Japan的主机,但是压根ping不通,所以不得不用美国的ip。 最简单的科学上网,通过SSH连接 1.选个服务商,组个主机,安装个linux系统。 2.如果你使用的是linux,执行 1$ ssh -D 7701 [email protected] -D是dynamic的意思,7701是SSH访问的端口(任意),root改成vps里的用户名,@后面的ip改成vps的固定ip。 输入后,会提示你输入密码(使用ssh证书就不需要输入密码了),登录成功,就连接到了远端vps。 3.打开firefox, 安装foxyproxy standard插件。 4.打开foxyproxy settings, 编辑Default proxy,在Proxy Details页签中,选中"Direct internet connection(no proxy)",点击OK 5.创建新的proxy,“Add new proxy”, 名为"proxy",打开Proxy Details页签, 选中"Manual Proxy Configuration", Server or IP Address填入127.0.0.1,port填入7701。选中SOCKS proxy, 选择SOCKS v5,点击OK 6.添加Pattern Subscriptions,这一步通过增加订阅pattern,用于过滤国内ip不使用ssh访问。 点击"Add New Pattern Subscription",选中Enable, Subscription URL填入"https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt “。在Proxies一栏中,点击"Add Porxies”,选中上一步创建的proxy。Refresh Rate填1440。Format选择FoxyProxy。Obfuscation选择Base64,点击OK。 7.编辑proxy pattern, 打开URL Patterns, Add New Pattern。选中Enable, Pattern name随意,URL pattern填入"https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt ",URL Inclusion/Exclusion选中Whitelist。点击OK。 8.右键foxyproxy,选中"Use proxies based on their pre-defined patterns and priorities" 至此,就可以访问谷歌了。","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"Google","slug":"Google","permalink":"http://bejondshao.github.io/tags/Google/"}]},{"title":"Thunder bird配置263邮箱收发邮件","slug":"Thunder-bird配置263邮箱收发邮件","date":"2017-08-23T14:54:42.000Z","updated":"2023-03-02T03:26:34.198Z","comments":true,"path":"2017/08/23/Thunder-bird配置263邮箱收发邮件/","link":"","permalink":"http://bejondshao.github.io/2017/08/23/Thunder-bird%E9%85%8D%E7%BD%AE263%E9%82%AE%E7%AE%B1%E6%94%B6%E5%8F%91%E9%82%AE%E4%BB%B6/","excerpt":"","keywords":null,"text":"好久没写博客了,最近看xubuntu自带的thunder bird邮件工具不用有点浪费,所以就研究了下。其实之前有研究过,只是只能收邮件,没法发,就放弃了。今天成功了,网上也没找到相关教程,记录下。 Account Settings Account Name,随便写 Your Name,就是发邮件时显示的名字 Signature text,选中“Use HTML”即可插入html的签名。如果签名有图片,使用相对路径是不好用的,需要到263网页邮箱中,inspect element,找到图片网络路径,拷贝替换相对路径。 或者根据这篇文章,将图片以base64的方式保存到html文件中,然后Signature选择file。 Server Settings Server Name,填写邮件收发的服务器,端口默认993 Connection security,连接服务器的方式,选SSL/TLS Authentication method,Normal password,第一次连接服务器会询问 Outgoing Server(SMTP) Server Name,发邮件使用的服务器,一般是smtp协议,端口默认465 User Name,发邮件时所使用的邮箱 Authentication method,Normal password Connection Security,选择STARTTLS,而不是SSL/TLS 至此,收发邮件功能都好用了,开机自启动,再也不用每次到网页输入账号密码了。 早点睡,别熬夜,我知道你体格好,但那也不是铁打的。","raw":null,"content":null,"categories":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/categories/Linux/"}],"tags":[]},{"title":"Issues met after installing xubuntu 16.04.2","slug":"Issues-met-after-installing-xubuntu-16-04-2","date":"2017-04-08T10:32:38.000Z","updated":"2023-03-02T03:26:34.101Z","comments":true,"path":"2017/04/08/Issues-met-after-installing-xubuntu-16-04-2/","link":"","permalink":"http://bejondshao.github.io/2017/04/08/Issues-met-after-installing-xubuntu-16-04-2/","excerpt":"","keywords":null,"text":"@ 安装无线网卡(Wireless network) http://jingyan.baidu.com/article/9989c7463cf43cf648ecfe21.html?st=5&os=1&bd_page_type=1&net_type=3 简短来说就是插入ubuntu安装U盘,打开/pool/main/d/dkms/安装dkms_xxx_all.deb文件 (In short, plug in the ubuntu installation disk, open /pool/main/d/dkms folder, install dkms_xxx_all.deb file) $ sudo dpkg -i xxx.deb 打开/pool/restricted/b/bcmwl/安装bcmwl-kernel-source_xxx.deb文件 ( go to /pool/restricted/b/bcmwl folder, install bcmwl_kernel-source_xxx.deb file) @ 安装为知笔记 (Wiznote) 123$ sudo add-apt-repository ppa:wiznote-team$ sudo apt-get update$ sudo apt-get install wiznote @ 关闭防火墙 (turn off firewall) $ sudo ufw disable @ 在/etc/下没有samba文件夹,需要安装samba (samba) $ sudo apt-get install samba samba-common system-config-samba winbind @ 安装smbtree (smbtree) $ sudo apt install smbclient @ sogoupinyin 重启后好用了 @ 安装软件时提示lock文件被锁住(You get the lock issue while installing packages) 123$ sudo rm /var/lib/dpkg/lock$ sudo dpkg --configure -a$ sudo apt-get -f install @ install git-man got error Depends: git-man (< 1:2.7.4-.) but 1:2.11.0-2ppa0ubuntu12.04.1 is to be installed e unable to correct problems you have held broken packages. debian try this: $ sudo apt-get install git-man got Err:1 http://ppa.launchpad.net/fcitx-team/nightly/ubuntu xenial/main i386 git-man all 1:2.11.0-2ppa0ubuntu12.04.1 404 Not Found disable fcitx-team,rerun $ sudo apt-get install git-man got Sub-process /usr/bin/dpkg returned an error code (1) 12$ sudo rm /etc/apt/sources.list$ sudo apt-get install git-man WARNING:root:could not open file ‘/etc/apt/sources.list’ $ software-properties-gtk check the repositories $ sudo apt-get update $ sudo apt-get install git 总结,归根结底是sources.list出问题了,移除后执行software-properties-gtk添加sources.list。在安装软件时切记不要着急,同时安装两个软件,或者在执行更新时安装软件。 (In conclude, there’s sth wrong with sources.list, after I remove it. I need to regenerate sources.list. Please be patient when installing packages, DO NOT install packages or do update in parallel.) @ 如果执行 $sudo dpkg -i xxx.deb 出现依赖问题,执行 $ sudo apt-get -f install 会安装依赖并重新安装deb包 (if you get dependencies issue while $ sudo dpkg -i xxx.deb, you need to do $sudo apt-get -f install. It’ll install all dependencies and the target package.)","raw":null,"content":null,"categories":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/categories/Linux/"}],"tags":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/tags/Linux/"}]},{"title":"Mybatis更新数据库示例","slug":"Mybatis更新数据库示例","date":"2017-03-30T09:56:20.000Z","updated":"2023-03-02T03:26:34.186Z","comments":true,"path":"2017/03/30/Mybatis更新数据库示例/","link":"","permalink":"http://bejondshao.github.io/2017/03/30/Mybatis%E6%9B%B4%E6%96%B0%E6%95%B0%E6%8D%AE%E5%BA%93%E7%A4%BA%E4%BE%8B/","excerpt":"","keywords":null,"text":"@ mybatis-config.xml 123 <mappers> <mapper resource="mybatis/xml/UserMapper.xml" /></mappers> @ 添加GuestInfoMapper接口 12 public interface UserMapper {void updateUserByUserNumber(UpdateUser updateUser); @ 编写model类,用于包装参数 123456package mybatis.model;public class UpdateUser { private String userNumber; private String firstName; private String docType; private String docTypeColumn; @ 添加Mapper.xml,编写sql UserMapper.xml 123456789<update id="updateUserByUserNumber" parameterType="mybatis.model.UpdateUser"> UPDATE NAME SET firstname = #{firstName}, sfirstname = #{firstName}, ${docTypeColumn} = #{docType} WHERE name_id = #{userNumber} </update> @ 调用接口方法,注意update时需要commit 1234SqlSession session = sqlSession.get(); UserMapper mapper = session.getMapper(UserMapper.class); mapper.updateUserByUserNumber(updateUser); session.commit();","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Mybatis","slug":"Mybatis","permalink":"http://bejondshao.github.io/tags/Mybatis/"}]},{"title":"Keycloak-配置服务器和客户端SSL","slug":"Keycloak-配置服务器和客户端SSL","date":"2017-02-15T09:16:00.000Z","updated":"2023-03-02T03:26:34.116Z","comments":true,"path":"2017/02/15/Keycloak-配置服务器和客户端SSL/","link":"","permalink":"http://bejondshao.github.io/2017/02/15/Keycloak-%E9%85%8D%E7%BD%AE%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%92%8C%E5%AE%A2%E6%88%B7%E7%AB%AFSSL/","excerpt":"","keywords":null,"text":"@ SSL配置原理参考 @ 在每个realm配置中,有HTTPS应用范围配置。 external request:在私有IP如localhost, 127.0.0.1, 10.0.x.x, 192.168.x.x以及172.16.x.x不会要求SSL。外部IP访问会要求HTTPS none:所有IP访问都不需要HTTPS all request:所有IP访问都需要HTTPS (在Master realm设置all request需要确保SSL已经搭建成功,否则会无法访问keycloak。解决方法是去keycloak数据库,更改realm表,“update realm set ssl_required = ‘EXTERNAL’ where name = ‘master’;”) @ 如果代理服务器(apache或nginx)不配置SSL,可以在keycloak配置SSL。总共分两步: 获取或生成keystore 在keycloak服务器配置keystore 以下介绍自生成keystore的方法,从认证机构申请的方法略过。 @ 在keycloak服务器主机keytool生成jks证书: keytool -genkeypair -alias aliasName -keyalg RSA -keystore keycloak.jks -validity 10950 注意:CN必须是主机名,也可以是ip但是ip容易变,必须是主机名或域名。因为在后续客户端配置auth server url中也要配置主机名,这两个地方的名称要相同。在httprequest中会验证。 口令是为保护证书,自定义。 validity有效时间,单位天 是否正确:y不是yes alias是给证书起别名,防止重复,证书存储在keycloak.jks中 @ 在keycloak服务器配置keystore 将keycloak.jks复制到configuration文件夹内,然后编辑standalone.xml,standalone-ha.xml或domain.xml文件: 1234567<security-realm name="UndertowRealm"> <server-identities> <ssl> <keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="changeit" /> </ssl> </server-identities></security-realm> Note: 如果是domain.xml,relative-to=“jboss.domain.config.dir” 然后找到 urn:jboss:domain:undertow关键字: 123456<subsystem xmlns="urn:jboss:domain:undertow:3.0"> <buffer-cache name="default"/> <server name="default-server"> <https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/> ...</subsystem> keycloak服务器已经配置完成,重启服务器即可访问 https://host:8443 下面介绍如何在客户端通过https访问keycloak: @ 用keycloak服务器配置的keystore导出证书,供客户端使用: keytool -export -alias abc -keystore keycloak.jks -rfc -file abc.crt alias建议和生成时的别名相同,根据keycloak.jks导出证书到abc.crt中,导出时会要求输入keycloak.jks的密码。 @ 将crt导入到客户端中: 参考 keytool -importcert -alias abc -file shij-server.crt -keystore truststore.jks 将crt证书导入到truststore.jks中,导入时会要求输入truststore.jks的密码 @ 在客户端的keycloak.json中配置 123456789101112{ "realm": "hello-world-authz", "auth-server-url": "https://abc:8443/auth", "ssl-required": "all", "resource": "hello-world-authz-service", "credentials": { "secret": "secret" }, "policy-enforcer": {}, "truststore": "E:/truststore.jks", "truststore-password": "changeit"} Note: truststore的配置项可以指定“classpath:/truststore.jks",例子使用的是系统文档位置,因为在我测试的时候classpath方式无法找到truststore。在研究配置时不断的测试,后来改成系统方式。在后来配置好SSL后debug发现,原因是Keycloak源码中的KeycloakUtil使用的classloader错误。参考Keycloak JIRA和github pull request。 Note: 如果导入后启动客户端出现 1Certificate for <192.168.1.8> doesn't match common name of the certificate subject: localhostCertificate for <192.168.1.8> doesn't match common name of the certificate subject: localhost 说明证书的CN是localhost,而远端主机是192.168.1.8。说明证书的common name起错了,应该是ip或者主机名,建议使用主机名","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"Keycloak升级","slug":"Keycloak升级","date":"2017-02-07T05:42:00.000Z","updated":"2023-03-02T03:26:34.117Z","comments":true,"path":"2017/02/07/Keycloak升级/","link":"","permalink":"http://bejondshao.github.io/2017/02/07/Keycloak%E5%8D%87%E7%BA%A7/","excerpt":"","keywords":null,"text":"@ 升级需要考虑database,keycloak-server.json, providers, themes,adapter,driver和applications。 @ 不建议从很旧的版本升到最新版。升级前要备份数据库。theme拷贝到新服务器中。 @ 不支持从candidate release升级到final。所以还是不要下载candidate release版本的吧。 @ 新适配器要拷贝到application服务器中 keycloak\\distribution\\adapters是生成的adapters,或者从官网下载对应版本的adapter。 以wildfly-adapter为例: adapter放在keycloak\\distribution\\adapters\\wildfly-adapter\\wildfly-adapter-zip\\target\\unpacked\\org\\keycloak\\下,将所有文件夹拷贝到 应用服务器wildfly-10.0.0.Final\\modules\\system\\add-ons\\keycloak\\org\\keycloak\\内。 @ 数据库jdbc驱动要拷贝到keycloak服务器中 postgresql驱动 创建文件夹modules\\system\\layers\\base\\org\\postgresql\\main 拷贝postgresql驱动 postgresql-9.4-1204.jdbc42.jar到main文件夹下 创建module.xml文件 1234567891011<?xml version="1.0" encoding="UTF-8"?><module xmlns="urn:jboss:module:1.3" name="org.postgresql"> <resources> <resource-root path="postgresql-9.4-1204.jdbc42.jar"/> <!-- Insert resources here --> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> </dependencies></module> Note:可以使用wildfly/bin/jboss-cli.sh脚本添加module。 @standalone.xml的数据库配置 12345678910111213141516171819202122232425262728 <subsystem xmlns="urn:jboss:domain:datasources:4.0"> <datasources><datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true"> <connection-url>jdbc:postgresql://localhost:5432/keycloak_ExampleDS</connection-url> <driver>postgresql</driver> <security> <user-name>postgres</user-name> <password>369</password> </security> </datasource><datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true"> <connection-url>jdbc:postgresql://localhost:5432/keycloak</connection-url> <driver>postgresql</driver> <security> <user-name>postgres</user-name> <password>369</password> </security> </datasource> <drivers> <driver name="h2" module="com.h2database.h2"> <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class> </driver> <driver name="postgresql" module="org.postgresql"> <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class> </driver> </drivers> </datasources> </subsystem> @ 转移keycloak-server.json文件 这个文件在2.2.0版还存在,在2.5.0时看不到了。暂时还好用,keycloak建议在standalone.xml,standalone-ha.xml或domain.xml配置。转换方式略。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"如何获取thread dump和heap dump","slug":"如何获取thread-dump和heap-dump","date":"2017-02-04T09:36:54.000Z","updated":"2023-03-02T03:26:34.237Z","comments":true,"path":"2017/02/04/如何获取thread-dump和heap-dump/","link":"","permalink":"http://bejondshao.github.io/2017/02/04/%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96thread-dump%E5%92%8Cheap-dump/","excerpt":"","keywords":null,"text":"@ 远程到主机上 12$ ssh [email protected]@192.168.1.95's password: 输入登录密码,即可远程。 @ 获取服务器进程号: Note: 执行jps(下面jstack, jmap等命令相同)时需要用运行java应用的用户来执行。这些用户往往被创建为nologin。比如创建wildfly用户来运行java程序。 12[bejond@centostest ~]$ sudo -u wildfly jps -l[sudo] password for bejond: 上面命令意思为bejond用户以wildfly用户的身份执行jps来查看wildfly用户所运行的程序。 输入bejond用户的登录密码即可。输入密码后输入结果: 14273 /opt/wildfly/jboss-modules.jar 14602 sun.tools.jps.Jps 这里看到进程号是14273。也可以使用$ sudo -u wildfly jps -lv,查看传递给JVM的参数。 14273 /opt/wildfly/jboss-modules.jar -D[Standalone] -Xms1024m -Xmx1024m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true -XX:-HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/wildfly/ -Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true -Dorg.jboss.boot.log.file=/opt/wildfly/standalone/log/server.log -Dlogging.configuration=file:/opt/wildfly/standalone/configuration/logging.properties 14584 sun.tools.jps.Jps -Dapplication.home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.151-1.b12.el7_4.x86_64 -Xms8m Note: 如果jps提示command not found。在centos下安装的java默认没有devel包,执行 $ sudo yum install java-1.8.0-openjdk-devel.x86_64即可。 @ 生成thread dump。Thread dump展示所有线程和stack traces。你可以查看在生成thread dump时服务器的工作状态。 Note: 采集thread dump需要每隔10秒至少采集三次。也可以每隔5秒至少采集6次。这能体现服务器在这段时间的变化,比如哪个线程悬挂,可能是死锁,可能是等待其他线程返回。使用jstack命令生成thread dump,并保存到目录里。 $ sudo -u wildfly jstack -l 14273 > /tmp/threaddump.txt Note: 保存文件位置要保存到/tmp中,因为/tmp文件夹允许任何用户进行读写,保存到其他文件夹会有可能保存失败。 Note: Windows系统下有个psexec软件,可以远程采集thread dump。但是需要在远程机器上配置客户端。 @ 分析thread dump。 将threaddump拷贝到本机(我使用Gigolo连接远程)。 使用 IBM Thread and Monitor Dump Analyzer for Java 工具分析,下载到本机,执行 $ java -jar jca_xxx.jar 如何分析thread dump这里暂不介绍了。 @ 获取Heap dump Heap dump是java堆的一个快照。在发生OutOfMemory问题时,heap dump是非常重要的根据。比如堆中最大的对象有泄露内存的嫌疑。 使用jmap命令获取heap dump。远程到主机,执行 $ sudo -u wildfly jmap -dump:format=b,file=/tmp/heapdump.hprof 14273 @ 使用Eclipse Memory Analyzer分析heap dump。 找最大的对象 找EMA建议的Leak Suspects,找的对象最好涉及到项目的类,而非第三方或JVM类。 在找问题前先浏览server.log和boot.log文件。 使用得手的工具,分析日志和dump会让你离找到问题根源更进一步。 @ heap dump可以设定jvm参数,在触发OOM时自动生成: -XX:-HeapDumpOnOutOfMemoryError 参数表示当JVM发生OOM时,自动生成DUMP文件。 -XX:HeapDumpPath=${目录}参数表示生成DUMP文件的路径,也可以指定文件名称,例如:XX:HeapDumpPath=/tmp/java_heapdump.hprof。如果不指定文件名,默认为:java__heapDump.hprof。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"JVM","slug":"JVM","permalink":"http://bejondshao.github.io/tags/JVM/"}]},{"title":"Keycloak客户端验证","slug":"Keycloak客户端验证","date":"2017-01-23T10:25:00.000Z","updated":"2023-03-02T03:26:34.142Z","comments":true,"path":"2017/01/23/Keycloak客户端验证/","link":"","permalink":"http://bejondshao.github.io/2017/01/23/Keycloak%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%AA%8C%E8%AF%81/","excerpt":"","keywords":null,"text":"@ 当机密的OIDC客户端需要向keycloak发送请求(比如请求token, refresh token),就需要被Keycloak验证。有两种方法: Clinet ID和Client Secret 这是传统的OAuth2方式 secret是从keycloak admin console生成的,放到adapter配置的credentials里 1234"credentials":{ "secret": "19666a4f-32dd-4049-b082-684c74115f28"} Client authentication with signed JWT 这是基于RFC7523,工作原理: 客户端需要有private key和certificate。这可以从keystore文件获取。 当客户度启动,它允许你从http://myhost/myapp/k_jwks 下载public key。 在验证过程中,客户端用private key签名,生成JWT token,用client_assertion参数发给keycloak keycloak必须有public key或客户端的certificate,用来验证JWT的签名。在keycloak admin console, client,Credentials页签,需要把验证方式改为Signed JWT。可以设置JWKS URLhttp://myhost/myapp/k_jwks 。这样keycloak会自动下载新的key。 也可以上传jks文件,也可以在admin console生成新文件,放到客户端里。 在keycloak.json文件里: 12345678910"credentials": {"j wt": {"client- keystore- file": "classpath: keystore- client. j ks","client- keystore- type": "JKS","client- keystore- password": "storepass","client- key- password": "keypass","client- key- alias": "clientkey","token- expiration": 10 }} 如果不用classpath:,可以指定任意路径的文件 @ 增加自己的客户端验证方式 需要实现客户端和服务端的providers在Server Developer Guide的Authentication SPI有详细介绍。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/tags/DevOps/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"Keycloak缩写列表","slug":"Keycloak缩写列表","date":"2017-01-23T10:21:00.000Z","updated":"2023-03-02T03:26:34.143Z","comments":true,"path":"2017/01/23/Keycloak缩写列表/","link":"","permalink":"http://bejondshao.github.io/2017/01/23/Keycloak%E7%BC%A9%E5%86%99%E5%88%97%E8%A1%A8/","excerpt":"","keywords":null,"text":"@ ABAC(Attribute-based access control) @ RBAC(Role-based access control) @ UBAC(User-based access control) @ CBAC(Context-based access control) @ TBAC(Time-based access control) @ ACMs(Access control mechanisms) @ SPI(Service Provider Interface) @ UMA(User-Managed Access)是OAuth 2.0的轮廓。UMA定义资源拥有者如何控制他的资源,允许其他客户端访问。即便资源分布在不同的服务器中,只需要一个授权中心允许访问即可。 User-Managed Access (UMA) is a profile of OAuth 2.0. UMA defines how resource owners can control protected-resource access by clients operated by arbitrary requesting parties, where the resources reside on any number of resource servers, and where a centralized authorization server governs access based on resource owner policies. 来源: User-Managed Access @ AAT(Authorization API Token) @ RPT(Request Party Token) @ CLI(Command Line Interface) @ JOSE(JSON Object Signing and Encryption) @ JWT(JSON Web Token) @ JWS(JSON Web Signature) @ JWE(JSON Web Encryption) @ JWA(JSON Web Algorithms) @ JWK(JSON Web Key)","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"Keycloak多realm控制","slug":"Keycloak多realm控制","date":"2017-01-22T10:05:00.000Z","updated":"2023-03-02T03:26:34.140Z","comments":true,"path":"2017/01/22/Keycloak多realm控制/","link":"","permalink":"http://bejondshao.github.io/2017/01/22/Keycloak%E5%A4%9Arealm%E6%8E%A7%E5%88%B6/","excerpt":"","keywords":null,"text":"@ 一个应用可以被多个realms保护,这些realms可以是一个keycloak server,也可以是多个。 也就需要多个keycloak.json,不同的名称。 @ 首先需要实现org.keycloak.adapters.KeycloakConfigResolver @ 然后在web.xml里配置新的Resolver 1234567<web-app>. . .<context-param><param-name>keycloak.config.resolver</param-name><param-value>example.PathBasedKeycloakConfigResolver</param-value></context-param></web-app>","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"Keycloak Clustering","slug":"Keycloak-Clustering","date":"2017-01-22T09:50:00.000Z","updated":"2023-03-04T12:14:12.067Z","comments":true,"path":"2017/01/22/Keycloak-Clustering/","link":"","permalink":"http://bejondshao.github.io/2017/01/22/Keycloak-Clustering/","excerpt":"","keywords":null,"text":"@ Standalone Clustered Configuration 打包好的包邮预定好的给云部署的服务器配置文件,/standalone/configuration/standalone-ha.xml。里面包括所有基本设置,包括网络,数据库,缓存和discovery。配置里有一点没配置。你要配置共享的数据库连接才能启动云架构。同时也需要在云之上部署负载均衡。 启动脚本 1\\bin\\standalone.bat --server-config=standalone-ha.xml @ Domain Clustered Mode Domain mode是集中管理和发布服务器配置的一种方式。 使用standalone方式配置云会慢慢随着节点增多而增加维护成本。每次更改配置文件都需要更改每个节点的内容。Domain mode就解决了这个问题,它提供一个管理中心。配置Domain mode一开始会很复杂,但是是一劳永逸的。这也是为什么Keycloak选择在wildfly上部署。 domain mode有几个概念需要了解一下。 domain controller 域控制器是存储,管理发布基本设置的进程。其他节点会从这里获取配置。 host controller 主机控制器用于在具体机器上管理节点。你会配置主机控制器运行一个或多个服务器节点。域控制器也和主机控制器交流。为了减少运行的进程,域管理器一般也当做主机管理器使用。 domain profile 域档案是有名字的固定配置,用于服务器启动。可以创建多个存档用于不同的服务器。 server group 服务器群是服务器的集合,被统一管理和配置。可以分配域档案给一个群,这样群里的服务器都用同样的域档案。 在域模型中,域控制器以主要节点的身份启动。然后主机控制器在每个机器上启动。每个主机控制器部署配置写明有多少个Keycloak服务器会在这个机器上运行。当主机控制器启动时,就会启动相应的keycloak服务器,然后从域控制器拉取配置。 @ Domain Configuration 配置文件是/domain/configuration/domain.xml。auth-server-standalone和auth-server-clustered的profile节点是应该配置的。同样也应该配置网络连接,缓存,数据库。 auth-server profile 1234567<profiles> <profile name="auth-server-standalone"> ... </profile> <profile name="auth-server-clustered"> ... </profile> auth-server-standalone是非云架构的,auth-server-clustered是云架构的。 另外还有许多socket-binding-groups 123456789101112<socket-binding-groups> <socket-binding-group name="standard-sockets" default-interface="public"> ... </socket-binding-group> <socket-binding-group name="ha-sockets" default-interface="public"> ... </socket-binding-group> <!-- load-balancer-sockets should be removed in production systems and replaced with a better softare or hardare based one --> <socket-binding-group name="load-balancer-sockets" default-interface="public"> ... </socket-binding-group></socket-binding-groups> 此配置定义与每个Keycloak服务器实例一起打开的各种连接器的默认端口映射。每个带${}符号的值都可以在命令行里用-D作为参数覆盖 $ domain.sh -Djboss.http.port=80 @ 给Keycloak定义的server group在server-groups节点里。它确定域档案是用"default",并且有一些默认的Java VM启动参数。绑定了一个socket-binding-group到服务器组里。 123456789101112131415<server-groups> <!-- load-balancer-group should be removed in production systems and replaced with a better softare or hardare based one --> <server-group name="load-balancer-group" profile="load-balancer"> <jvm name="default"> <heap size="64m" max-size="512m"/> </jvm> <socket-binding-group ref="load-balancer-sockets"/> </server-group> <server-group name="auth-server-group" profile="auth-server-clustered"> <jvm name="default"> <heap size="64m" max-size="512m"/> </jvm> <socket-binding-group ref="ha-sockets"/> </server-group></server-groups> @ 主机控制器配置 Keycloak有两个主机控制器文件/domain/configuration/host-master.xml和host-slave.xml。host-master.xml是配置域控制器,负载均衡,以及一个keycloak实例。host-slave.xml用于和域控制器交流,启动一个keycloak实例。 Note: 负载均衡不是必须的服务。使用负载均衡可以在开发机器上方便的测试云架构。在生产环境,你可以用其他负载均衡的软硬件代替它。 可以移除load-balancer项禁用负载均衡 12345<servers> <!-- remove or comment out next line --> <server name="load-balancer" group="loadbalancer-group"/> ...</servers> 另外一个需要注意的是声明验证服务器实例。有个属性叫port-offset。其他在socket-binding-group或server group里定义的端口都会加上port-offset,防止端口冲突。 123456<servers> ... <server name="server-one" group="auth-server-group" auto-start="true"> <socket-bindings port-offset="150"/> </server></servers> @ 服务器实例工作目录 每个在host files定义的keycloak服务器实例都在/domain/servers/创建一个server_name目录。额外的配置可以放在那里,临时数据,日志也会放在哪里。结构就像其他wlidfly服务器内容管理一样。 @ Domain Boot Script 12$ .../bin/domain.sh --host-config=host-master.xml> ...\\bin\\domain.bat --host-config=host-slave.xml @ Clustered Domain Example 你可以使用配置好的domain.xml,启动它会在一个机器上启动: 一个域控制器 一个HTTP负载均衡 两个Keycloak实例 如果想在两个机器启动实例,需要执行domain.sh两次,来启动两个独立的主机管理器。第一个作为主机会启动域控制器,HTTP负载均衡和一个keycloak服务器。第二个从属主机控制器会启动一个keycloak服务器。 @ 将从属与域控制器关联 在启动从属之前,要配置从属的主机控制器以便于安全的和域控制器通讯。如果不配置,从属主机就无法从域控制器获取配置。配置安全连接需要创建一个服务器管理员,在主机和从属机共享。通过/bin/add-user.sh脚本添加。 执行脚本,选择a,Management User,当它询问这个新用户是否是用于AS进程连接另一个,回复yes。然后会生成一个密码,将密码复制到…/domain/configuration/host-slave.xml里 1234567891011121314151617181920212223242526272829303132$ add-user.sh What type of user do you wish to add? a) Management User (mgmt-users.properties) b) Application User (application-users.properties) (a): a Enter the details of the new user to add. Using realm 'ManagementRealm' as discovered from the existing property files. Username : admin Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file. - The password should not be one of the following restricted values {root, admin, administrator} - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s) - The password should be different from the username Password : Re-enter Password : What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[ ]: About to add user 'admin' for realm 'ManagementRealm' Is this correct yes/no? yes Added user 'admin' to file '/.../standalone/configuration/mgmt-users.properties' Added user 'admin' to file '/.../domain/configuration/mgmt-users.properties' Added user 'admin' with groups to file '/.../standalone/configuration/mgmt-groups.properties' Added user 'admin' with groups to file '/.../domain/configuration/mgmt-groups.properties' Is this new user going to be used for one AS process to connect to another AS process? e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls. yes/no? yes To represent the user add the following to the server-identities definition <secret value="bWdtdDEyMyE=" /> <management> <security-realms> <security-realm name="ManagementRealm"> <server-identities> <secret value="bWdtdDEyMyE="/> </server-identities> Note: add-user.sh不是添加keycloak用户,是添加JBoss Enterprise Application Platform。 @ 由于我们在一个机器上运行两个节点,就需要启动两次脚本: 12$ domain.sh --host-config=host-master.xml$ domain.sh --host-config=host-slave.xml 然后尝试访问http://localhost:8080/auth","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"Keycloak Java Adapter Configuration","slug":"Keycloak-Java-Adapter-Configuration","date":"2017-01-05T03:43:00.000Z","updated":"2023-03-02T03:26:34.115Z","comments":true,"path":"2017/01/05/Keycloak-Java-Adapter-Configuration/","link":"","permalink":"http://bejondshao.github.io/2017/01/05/Keycloak-Java-Adapter-Configuration/","excerpt":"","keywords":null,"text":"@ keycloak adapter可以在war包里添加keycloak.json配置,也可以在standalone.xml里配置。 开发过程推荐使用keycloak.json,生产环境推荐使用standalone.xml。 下面是standalone的配置格式: <subsystem xmlns="urn:jboss:domain:keycloak:1.1"></subsystem> 以下是配置的属性 @ resource, 应用的client id。Required @ realm-public-key, PEM格式的realm public key。可以从console获取,不建议设置。如果不设置,Keycloak会每次下载新的public key。 @ auth-server-url,Keycloak服务器的url。所有Keycloak页面和REST服务都是从这个地址转发的。 http://host:port/auth。 Required @ ssl-required,确保所有沟通都通过HTTPS,在产品中应该设置为all。默认值external,意思HTTPS对外部请求是必须的。可用值all, external, none. @ use-resource-role-mappings,如果是true,adapter会在token里找application级别的role mappings。如果是false, 会看realm级别的role mappings。默认是false @ public-client, 如果是true,适配器不会为client向Keycloak发送证书。默认是false @ enable-cors,默认值false。如果是true,会处理CORS 前置请求,同时会从access token检查valid origins。 @ cors-max-age。如果CORS是enabled,这个值会被设置到Access-Control-Max-Age头中。如果没设置,这个头设定就不会在CORS响应里。 @ cors-allowed-methods, 如果cors开启,设定Access-Control-Allow-Methods @ bearer-only, 针对services,应该设为true。如果开启,adapter不会授权给用户,只会检查bearer tokens。默认是false @ autodetect-bearer-only, 如果应用服务器既是web应用,又是web服务(SOAP or REST),就应该设为true。这样会对未授权的用户跳转到登录页,对未授权的SOAP/REST客户端会返回401。Keycloak根据头X-Requested-With, SOAPAction或Accept来确定是SOAP还是REST客户端。默认值false @ enable-basic-auth, 告诉adapter支持basic验证。如果开启,必须提供secret。默认值false。 @ expose-token,如果是true,被授权的浏览器客户端(通过JS HTTP调用)可以通过root/k_query_bearer_token获取signed access token。默认是false @ credentials, 确定应用的凭证。这是个对象符合,key是credential类型,value是credential类型的值。现阶段支持password和jwt。对‘Confidential’访问方式来说是Required @ connection-pool-size, Adapter会创建额外的HTTP调用Keycloak Server来讲access code转为access token。这个配置多少个到Keycloak server的连接池装多少个连接,默认是20 @ disable-trust-manager, 如果Keycloak server要求HTTPS,并且这个属性设置为true。那么你就不需要配置truststore。这个设置只用在开发模式中,production环境应该设置成false。默认是false @ allow-any-hostname, 如果Keycloak server要求HTTPS,并且这个属性设置为true。那么Keycloak server的颁发证书就通过truststore,但是host name验证就去掉了。这个设置只用在开发模式中,production环境应该设置成false。默认是false @ truststore, 指向keystore文件的路径。如果在路径前加classpath:,那么truststore会从部署的classpath找文件。用于向外与Keycloak server做HTTPS沟通。客户端创建HTTPS请求需要一种验证服务器主机的方式,truststore就是做这个工作的。keystore包含一到多个受信主机证书或凭证管理中心。你可以解压Keycloak server的SSL keystore的public certificate来创建truststore。除非ssl-required是none或disable-trust-manager是true,那么这个属性就是Required。 @ truststore-password, truststore keystore的密码。如果设定了truststore,并且truststore需要密码,那么这个属性就是Required。 @ client-keystore, 指向keystore的路径。这个keystore包含客户端双向SSL验证,用于adapter创建对Keycloak server的HTTPS请求。 @ client-keystore-password, keystore的密码。如果client-keystore设定了,这个就是必须的。 @ client-key-password, 客户端key的密码,如果client-keystore设定了,这个就是必须的。 @ always-refresh-token,如果是true,适配器会在每次请求时都刷新token (这个在开发测试阶段很有必要) @ register-node-at-startup, 如果是ture,adapter会想Keycloak发送注册请求。这个属性默认是false。在cluster环境中起作用。 @ register-node-period, 定期在Keycloak重新注册adapter。cluster环境中使用。 @ token-store, 可以是session或cookie。默认是session,adapter将账户信息存储在HTTP session中。 @ principal-attribute, OpenID Connection ID Token attribute to populate the UserPrincipal name with. 如果token属性是null,默认值就是sub. 可能的值有sub, preferred_username, email, name, nickname, given_name, family_name. @ turn-off-change-session-id-on-login, 默认情况下,session id 会在登录成功后被改变,来插入一个安全攻击容器。设置成true,如果你想关闭这个功能。默认值是false @ token-minimum-time-to-live, 大多数情况下,会在access token失效前刷新。尤其是将access token发送给REST client,token可能会在验证它之前失效,所以刷新很有必要。这个值不应该大于realm’s access token寿命。默认是0(秒), 所以adapter会在它失效时刷新它。 @ min-time-between-jwks-request, 向Keycloak发送请求新的public key的间隔,单位秒。默认是10。当adapter不认识kid时,会下载尝试新的public key。10秒内不会重复请求,防止有DoS攻击,发送许多错误的kid。 @ public-key-cache-ttl, 向Keycloak发送请求新的public key的最大间隔,默认是86400秒(1天)。当adapter不认识kid时,会下载尝试新的public key。如果认识kid,会使用已存在的public key。超过这个期限,会下载新的key。","raw":null,"content":null,"categories":[{"name":"DevOps","slug":"DevOps","permalink":"http://bejondshao.github.io/categories/DevOps/"},{"name":"Keycloak","slug":"DevOps/Keycloak","permalink":"http://bejondshao.github.io/categories/DevOps/Keycloak/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Keycloak","slug":"Keycloak","permalink":"http://bejondshao.github.io/tags/Keycloak/"}]},{"title":"pandas - DataFrame","slug":"pandas-DataFrame","date":"2016-08-21T13:39:43.000Z","updated":"2023-03-02T03:26:34.217Z","comments":true,"path":"2016/08/21/pandas-DataFrame/","link":"","permalink":"http://bejondshao.github.io/2016/08/21/pandas-DataFrame/","excerpt":"","keywords":null,"text":"最近在研究股票,想通过股票API获取数据并分析。发现TuShare是个很好的工具。TuShare返回的绝大部分的数据格式都是pandas DataFrame类型。 DataFrame是二维的数据结构,其本质是Series的容器。可以把DataFrame类比成一个二维表格。在这里介绍下DataFrame的概念,记录常用方法。 @ Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。 @ DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。 @ 下标索引选取的是DataFrame的记录,与List相同DataFrame的下标也是从0开始,区间索引的话,为一个左闭右开的区间,即[0:3]选取的为1-3三条记录。 df[‘a’:‘b’] @ 数据切片 通过下标选取数据: df[‘one’] df.one 以上两个语句是等效的,都是返回df名称为one列的数据,返回的为一个Series。 df[0:3] df[0] 下标索引选取的是DataFrame的记录,与List相同DataFrame的下标也是从0开始,区间索引的话,为一个左闭右开的区间,即[0:3]选取的为1-3三条记录。与此等价,还可以用起始的索引名称和结束索引名称选取数据: df[‘a’:‘b’] 有一点需要注意的是使用起始索引名称和结束索引名称时,也会包含结束索引的数据。以上两种方式返回的都是DataFrame。 使用标签选取数据: df.loc[行标签,列标签] df.loc[‘a’:‘b’]#选取ab两行数据 df.loc[:,‘one’]#选取one列的数据 df.loc的第一个参数是行标签,第二个参数为列标签(可选参数,默认为所有列标签),两个参数既可以是列表也可以是单个字符,如果两个参数都为列表则返回的是DataFrame,否则,则为Series。 使用位置选取数据: df.iloc[行位置,列位置] df.iloc[1,1]#选取第二行,第二列的值,返回的为单个值 df.iloc[0,2],:]#选取第一行及第三行的数据 df.iloc[0:2,:]#选取第一行到第三行(不包含)的数据 df.iloc[:,1]#选取所有记录的第一列的值,返回的为一个Series df.iloc[1,:]#选取第一行数据,返回的为一个Series PS:loc为location的缩写,iloc则为integer & location的缩写 更广义的切片方式是使用.ix,它自动根据你给到的索引类型判断是使用位置还是标签进行切片 df.ix[1,1] df.ix[‘a’:‘b’] 通过逻辑指针进行数据切片: df[逻辑条件] df[df.one >= 2]#单个逻辑条件 df[(df.one >=1 ) & (df.one < 3) ]#多个逻辑条件组合 这种方式获得的数据切片都是DataFrame。","raw":null,"content":null,"categories":[{"name":"Python","slug":"Python","permalink":"http://bejondshao.github.io/categories/Python/"}],"tags":[{"name":"Python","slug":"Python","permalink":"http://bejondshao.github.io/tags/Python/"},{"name":"pandas","slug":"pandas","permalink":"http://bejondshao.github.io/tags/pandas/"}]},{"title":"How to return result with thread","slug":"How-to-return-result-with-thread","date":"2016-04-16T03:00:56.000Z","updated":"2023-03-02T03:26:34.085Z","comments":true,"path":"2016/04/16/How-to-return-result-with-thread/","link":"","permalink":"http://bejondshao.github.io/2016/04/16/How-to-return-result-with-thread/","excerpt":"","keywords":null,"text":"As we know that we can implements Runnable to create a thread. And invoke run() to run it. If we extends class Thread, we need to call method start(). But how can we get a value from a thread? Like the thread info, running result, logs etc. From 《Thinking of Java》, we can make a class implement Callable, and implement method call(). Method call() returns Object, which means we can get anything we want. Here is the code: https://github.com/bejondshao/personal/commit/e2855458790bf930d42e60acefa181b23bd4019e","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Threads","slug":"Threads","permalink":"http://bejondshao.github.io/tags/Threads/"}]},{"title":"用枚举类型设计省,市,区管理","slug":"用枚举类型设计省,市,区管理","date":"2016-04-09T10:23:44.000Z","updated":"2023-03-02T03:26:34.257Z","comments":true,"path":"2016/04/09/用枚举类型设计省,市,区管理/","link":"","permalink":"http://bejondshao.github.io/2016/04/09/%E7%94%A8%E6%9E%9A%E4%B8%BE%E7%B1%BB%E5%9E%8B%E8%AE%BE%E8%AE%A1%E7%9C%81%EF%BC%8C%E5%B8%82%EF%BC%8C%E5%8C%BA%E7%AE%A1%E7%90%86/","excerpt":"","keywords":null,"text":"@ 枚举类型可以将一组具有名称的值的优先级和创建为一种新的类型。我们可以像创建类一样创建枚举类型。比如 1234567public enum Food { APPLE, ORANGE, CHOCOLATE, GRAPE} @ 枚举类型有几个常用的方法。 values(),返回该枚举类型所有的常量数组。 ordinal(),返回某个常量所在枚举类型的位置,从0开始。Food.ORANGE.ordinal()的值是1 name(),返回当前常量的名字。 toString(),同name() equals(),比较两个枚举类型的值是否相同。由于枚举类型是单例并且是常量,所以枚举类型的比较可以直接用“==”。 static valueOf(Class enumType, String name),根据枚举类型和名称找到该枚举的值。 compareTo(),比较两个枚举值的顺序,通过ordinal()的值做差得出结果。 valueOf(String name),这个方法不是静态方法,所有需要一个枚举实例来调用。 @ 枚举还有静态引用的功能,由于省略了类型名,对后期维护容易造成困惑,不推荐使用。 @ 枚举类型是常量,不可以被继承,也不能继承其他类,但是可以让枚举类型实现接口。 @ 枚举类型可以添加描述,即每个常量可以赋值,可以是基本类型,可以是类。 ============ 前段时间想实现国内各个省,市,区的管理功能,这在购物网站填写地址时会用到。我想了几种实现方法,比如: 方法一:省,市,区均设定为model,在数据库里分别创建表,写实际的中文名称,比如“北京”,“大连”等等。这种表示方式好处是简洁明了,缺点是每个地址都需要存储汉字,导致数据库内容重复。 方法二:省,市,区均设定model,在数据库里创建表,用键值对的形式表示地点。比如省份使用两位int的值表示,“10” - 北京,“12” - “辽宁”;四位表示市,“1212” - (辽宁)大连,前两位表示省份,后两位是市;六位表示市区,“121210” - (辽宁大连)甘井子。这种表示方式的好处是可以只通过市区就定位该市区具体行政关系。缺点是省和市的内容重复。 方法三:省,市,区均用int表示,显示的写在java代码里,并用map关联。这种方式的好处是不占用数据库资源,在数据库里只需要给出三个列表示省市区即可。缺点是int值很容易重复,表明意义不清晰,如果使用“101112”的形式表示则增加了数据位数,也显得冗余。 方法四:使用枚举表示省,市,区。这种方式好处是不占用数据库,常量的值不会被更改,表达意义清晰。缺点是设计和实现稍微复杂。 我尝试的用枚举构思并实现了一下,仅供参考。1.0版本的代码可以参考https://github.com/bejondshao/personal/commit/ed3fe52f99e6bf0f7156befd9443eda12f275714 从区入手,设计District接口,这个接口里显示的声明多个以城市为组,将区分组。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758package com.bejond.enumregion;/** * Created by bejond on 4/9/16. * From https://zh.wikipedia.org/wiki/%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%E5%8E%BF%E7%BA%A7%E4%BB%A5%E4%B8%8A%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%88%97%E8%A1%A8 */public interface District { // 注意, 只有常量用汉字, 类型仍然用英文 enum Beijing implements District { 东城区, 西城区, 朝阳区, 丰台区, 石景山区, 海淀区, 门头沟区, 房山区, 通州区, 顺义区, 昌平区, 大兴区, 怀柔区, 平谷区, 密云区, 延庆区 } enum Tianjin implements District { 河西区, 河东区, 和平区, 南开区, 河北区, 红桥区, 东丽区, 西青区, 津南区, 北辰区, 武清区, 宝坻区, 宁河区, 静海区, 滨海新区, 蓟县 }; enum Shanghai implements District { 黄浦区, 徐汇区, 长宁区, 静安区, 普陀区, 虹口区, 杨浦区, 闵行区, 宝山区, 嘉定区, 浦东新区, 金山区, 松江区, 青浦区, 奉贤区崇明县 } enum Chongqing implements District { 渝中区, 大渡口区, 江北区, 南岸区, 北碚区, 渝北区, 巴南区, 长寿区, 沙坪坝区, 万州区, 涪陵区, 黔江区, 永川区, 合川区, 江津区, 九龙坡区, 南川区, 綦江区, 大足区, 璧山区, 铜梁区, 荣昌区, 潼南区, 梁平县, 开县, 忠县, 城口县, 垫江县, 武隆县, 丰都县, 奉节县, 云阳县, 巫溪县, 巫山县, 石柱土家族自治县, 秀山土家族苗族自治县, 酉阳土家族苗族自治县, 彭水苗族土家族自治县 } enum Shenyang implements District { 沈河区, 和平区, 大东区, 皇姑区, 铁西区, 苏家屯区, 浑南区, 沈北新区, 于洪区, 辽中区, 新民市, 康平县, 法库县 }; enum Dalian implements District { 西岗区, 中山区, 沙河口区, 甘井子区, 旅顺口区, 金州区, 普兰店区, 瓦房店市, 庄河市, 长海县 }; enum Shijiazhuang implements District { 长安区, 桥西区, 新华区, 裕华区, 井陉矿区, 藁城区, 鹿泉区, 栾城区, 晋州市, 新乐市, 井陉县, 正定县, 行唐县, 灵寿县, 高邑县, 深泽县, 赞皇县, 无极县, 平山县, 元氏县, 赵县 } enum Xiamen implements District { 思明区, 海沧区, 湖里区, 集美区, 同安区, 翔安区 } // 剩下的自己补吧, 特殊地区根据业务自行补充} 由于枚举可以实现接口,所以声明的"Beijing", "Dalian"都是接口,虽然是市名,但这个类型其实是表达这个市所包含的市区,所以类型是“区” 设计市。以辽宁省的市为例,将辽宁省所包含的市设为常量。 12345678910111213141516171819202122package com.bejond.enumregion.city;import com.bejond.enumregion.City;import com.bejond.enumregion.District;/** * Created by bejond on 4/9/16. */public enum LiaoningCity implements City { 沈阳市(District.Shenyang.class), 大连市(District.Dalian.class); private District[] districts; LiaoningCity(Class<? extends District> district) { districts = district.getEnumConstants(); } public District[] getDistricts() { return districts; }} 本来想声明市也是个接口,这样可以和区一样设计并管理,但是由于市和区要进行关联,关联的过程需要有构造函数,而接口不允许有构造函数。并且我们需要在市的层级上添加方法,获取该市的区,所以无法通过继承接口实现。 构造函数 1LiaoningCity(Class<? extends District> district) 有两个功能,一是将特定的市的区赋值给不同的市,二是初始化districts,这个变量可以返回某个市的所有区,而不是辽宁省的所有市的所有区。 设计省,设计方式和市一样,这个类型就是辽宁省,所以只有一个常量,将LiaoningCity赋给它。 12345678910111213141516171819202122package com.bejond.enumregion.province;import com.bejond.enumregion.Province;import com.bejond.enumregion.city.LiaoningCity;/** * Created by bejond on 4/9/16. */public enum LiaoningProvince implements Province { 辽宁省(LiaoningCity.class); private LiaoningCity[] liaoningCities; LiaoningProvince(Class<? extends LiaoningCity> liaoningCity) { liaoningCities = liaoningCity.getEnumConstants(); } public LiaoningCity[] getLiaoningCities() { return liaoningCities; }} 以上就是设计区,市,省的过程,测试方法 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091package com.bejond.enumregion.test;import com.bejond.enumregion.District;import com.bejond.enumregion.city.LiaoningCity;import com.bejond.enumregion.province.LiaoningProvince;import org.junit.Test;import java.util.HashMap;import java.util.Map;/** * Created by bejond on 4/9/16. */public class TestProvince { @Test public void testGetDistrictsByCityName() { /*Province province = Liaoning.大连市; for (Province city : province.getClass().getEnumConstants()) Province district = city.getClass().getEnumConstants();*/ String city = "dalian"; city = city.toLowerCase(); //city = (char)(city.charAt(0) - 32) + city.substring(1); System.out.println(city); /** * this cityMap should be done by other class or method. */ Map<String, String> cityMap = new HashMap<String, String>(); cityMap.put("dalian", "大连市"); cityMap.put("shenyang", "沈阳市"); String cityName = cityMap.get(city); LiaoningCity liaoningCity = LiaoningCity.valueOf(cityName); for (District district : liaoningCity.getDistricts()) { System.out.println(district); } } @Test public void getDistrictsByProvinceName() { String name = "liaoning"; name = name.toLowerCase(); /** * this provinceMap should be done by other class or method. */ Map<String, String> provinceMap = new HashMap<String, String>(); provinceMap.put("liaoning", "辽宁省"); provinceMap.put("hebei", "河北省"); String provinceName = provinceMap.get(name); String enumName = (char)(name.charAt(0) - 32) + name.substring(1) + "Province"; /** * this is stupid */ if (enumName.equals(LiaoningProvince.class.getSimpleName())) { for (LiaoningProvince liaoningProvince : LiaoningProvince.values()) { System.out.println(liaoningProvince.name()); for (LiaoningCity liaoningCity0 : liaoningProvince.getLiaoningCities()) { System.out.println(liaoningCity0.name() + "--"); } for (LiaoningCity liaoningCity : LiaoningCity.values()) { System.out.println(liaoningCity.name()); for (District district : liaoningCity.getDistricts()) { System.out.println(district); } System.out.println(); } } } /*Province province = Province.valueOf(provinceName); for (Enum city : province.getClass().getEnumConstants()) { // get cities System.out.println(city.name()); for (District district : ((LiaoningCity) city).getDistricts()) { System.out.println(district.toString()); } break; }*/ }} getDistrictsByCityName() 的运行结果: 1234567891011121314151617181920212223dalian西岗区中山区沙河口区甘井子区旅顺口区金州区普兰店区瓦房店市庄河市长海县 getDistrictsByProvinceName() 的运行结果: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859辽宁省沈阳市--大连市--沈阳市沈河区和平区大东区皇姑区铁西区苏家屯区浑南区沈北新区于洪区辽中区新民市康平县法库县大连市西岗区中山区沙河口区甘井子区旅顺口区金州区普兰店区瓦房店市庄河市长海县 所以我们可以根据“省份”下拉框来动态生成“市”的下拉框,接着“市区”下拉框。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"}]},{"title":"Google可用的域名","slug":"Google可用的域名","date":"2016-04-03T15:10:03.000Z","updated":"2023-03-02T03:26:34.079Z","comments":true,"path":"2016/04/03/Google可用的域名/","link":"","permalink":"http://bejondshao.github.io/2016/04/03/Google%E5%8F%AF%E7%94%A8%E7%9A%84%E5%9F%9F%E5%90%8D/","excerpt":"","keywords":null,"text":"在我的Google hosts更新(授之以渔)里,提供了通过更新hosts的方式来使用谷歌搜索。最近发现www.google.hk和www.google.com已经完全无法访问了。所以通过更改hosts的方式貌似已经无法满足需要了。 一次偶然的机会我发现https://www.google.co.jp 可以访问,我不确定这个网站能访问是因为我本地hosts的原因还是浏览器的原因,因为我用不同浏览器测试结果不一样,我用chrome和火狐都能访问,而safary和opera就无法访问。于是突发奇想我查找了谷歌搜索有哪些域名,在维基百科里找到List of Google domains. 我挨个打开测试,发现 https://www.google.ml https://www.google.md https://www.google.me https://www.google.mk https://www.google.bf https://www.google.st 这几个域名仍然能访问。 有趣的是,我发现https://www.google.co.jp 不依赖hosts可以访问,而上述几个域名需要我提供的更新hosts方法后才能访问。这是我测试的结果,也许你按照列表试验会有不同的域名,聊胜于无吧。","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"Google","slug":"Google","permalink":"http://bejondshao.github.io/tags/Google/"}]},{"title":"Java堆和栈的区别","slug":"Java堆和栈的区别","date":"2016-03-31T05:37:02.000Z","updated":"2023-03-02T03:26:34.112Z","comments":true,"path":"2016/03/31/Java堆和栈的区别/","link":"","permalink":"http://bejondshao.github.io/2016/03/31/Java%E5%A0%86%E5%92%8C%E6%A0%88%E7%9A%84%E5%8C%BA%E5%88%AB/","excerpt":"","keywords":null,"text":"Java Heap Memory(堆) 堆是用来存放java程序运行时的对象和jre的类的. 我们创建的对象总是存在堆里. GC就是清理堆中没有被引用的对象. 堆里的对象是全局可见可引用的. Java Stack Memory(栈) 栈用于线程运行时存放变量的, 包括临时变量, 指向存放在堆里的对象的引用等. 栈就像一个试管一样, 遵循后进先出(Last In First Out). 当程序调用一个方法时, 就会在栈里取一块区域, 用来分配临时变量和参数. 当方法执行完之后, 这块区域就释放了. 所以当有方法1调用方法2时, 会先申请一块区域存放方法1的内容, 然后再在栈里申请一块区域存放方法2的内容(Last In), 而方法2肯定会在方法1前结束, 因此先释放(First Out), 然后再释放方法1的区域. 栈相对于堆的存取速度快很多, 同时栈比堆小很多. 举个例子 12345678910111213package com.bejond.testheapandstack;public class Test{ public static void main(String[] args) { int a = 1; Object object = new Object(); Test test = new Test(); test.foo(test); } private void foo(Object obj) { String string = obj.toString(); }} 下图显示栈和堆的数据分配情况. 咱们一步一步来. Line 4, main()方法开始, 就会在栈申请一个空间. int a 是基本类型数据, 放在栈里. object是临时变量, 放在栈里, 创建的Object放在堆里, test也同object. Line 9, 调用方法foo, 所以在栈申请一块空间给foo() foo()的参数obj, 是一个对象的地址(Java方法参数均为值传递,obj代表对象所在地址的值,详细分析), 存在栈里. 由于传的是object, 所以obj指向object所引用的对象. string存在栈里, 它指向object.toString()返回的字符串, 字符串存在String Pool里. 当然, fool()方法调用toString(), toString()也会在栈里申请空间. 当toString()执行完成后, toString()的空间就释放了. 当foo()执行完成后, foo()的空间也释放了. 接着执行main(), Line 10, main()执行完成, 也会被释放. 堆和栈的区别 堆用来存储java程序所有创建的对象, 而栈针对某个线程存储临时变量和参数. 当我们new一个对象时, 它总是存储在堆里. 栈存放一个引用, 也就是个名字, 指向堆中的对象. 堆中的对象是全局可见的, 而栈中的内容只是当前线程可见. 当方法执行完, 临时变量就被销毁, 栈遵从FILO原则释放内容, 而堆里的对象仍然存在, 成为垃圾对象, 然后会随着GC被清理掉. (所以我们在方法中应尽可能少的创建对象) 我们可以使用-Xms和-Xmx设定启动时堆大小和堆的最大值, 用-Xss设定栈的大小. 当堆满了, 并且GC后仍然没法分配内存给新对象时, 会抛java.lang.OutOfMemoryError: Java Heap Space错误. 而栈满了会抛java.lang.StackOverFlowError错误. 栈相对于堆来讲很小, 由于使用FILO方式管理栈, 所以栈的存取速度比堆快很多.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"JVM","slug":"JVM","permalink":"http://bejondshao.github.io/tags/JVM/"}]},{"title":"触发Full GC的情况","slug":"触发Full-GC的情况","date":"2016-03-29T06:51:09.000Z","updated":"2023-03-02T03:26:34.259Z","comments":true,"path":"2016/03/29/触发Full-GC的情况/","link":"","permalink":"http://bejondshao.github.io/2016/03/29/%E8%A7%A6%E5%8F%91Full-GC%E7%9A%84%E6%83%85%E5%86%B5/","excerpt":"","keywords":null,"text":"原文地址: http://book.51cto.com/art/201011/235592.htm 除直接调用System.gc外,触发Full GC执行的情况有如下四种。 旧生代空间不足 旧生代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC后空间仍然不足,则抛出如下错误: java.lang.OutOfMemoryError: Java heap space 为避免以上两种状况引起的Full GC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。 Permanet Generation空间满 Permanet Generation中存放的为一些class的信息等,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出如下错误信息: java.lang.OutOfMemoryError: PermGen space 为避免Perm Gen占满造成Full GC现象,可采用的方法为增大Perm Gen空间或转为使用CMS GC。 CMS GC时出现promotion failed和concurrent mode failure 对于采用CMS进行旧生代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent mode failure两种状况,当这两种状况出现时可能会触发Full GC。 promotion failed是在进行Minor GC时,survivor space放不下、对象只能放入旧生代,而此时旧生代也放不下造成的;concurrent mode failure是在执行CMS GC的过程中同时有对象要放入旧生代,而此时旧生代空间不足造成的。 应对措施为:增大survivor space、旧生代空间或调低触发并发GC的比率,但在JDK 5.0+、6.0+的版本中有可能会由于JDK的bug29导致CMS在remark完毕后很久才触发sweeping动作。对于这种状况,可通过设置 -XX: CMSMaxAbortablePrecleanTime=5(单位为ms)来避免。 统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间 这是一个较为复杂的触发情况,Hotspot为了避免由于新生代对象晋升到旧生代导致旧生代空间不足的现象,在进行Minor GC时,做了一个判断,如果之前统计所得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间,那么就直接触发Full GC。 例如程序第一次触发Minor GC后,有6MB的对象晋升到旧生代,那么当下一次Minor GC发生时,首先检查旧生代的剩余空间是否大于6MB,如果小于6MB,则执行Full GC。 当新生代采用PS GC时,方式稍有不同,PS GC是在Minor GC后也会检查,例如上面的例子中第一次Minor GC后,PS GC会检查此时旧生代的剩余空间是否大于6MB,如小于,则触发对旧生代的回收。 除了以上4种状况外,对于使用RMI来进行RPC或管理的Sun JDK应用而言,默认情况下会一小时执行一次Full GC。可通过在启动时通过- java -Dsun.rmi.dgc.client.gcInterval=3600000来设置Full GC执行的间隔时间或通过-XX:+ DisableExplicitGC来禁止RMI调用System.gc。","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"JVM","slug":"JVM","permalink":"http://bejondshao.github.io/tags/JVM/"}]},{"title":"Java GC 监测","slug":"Java-GC-监测","date":"2016-03-29T05:37:18.000Z","updated":"2023-03-02T03:26:34.105Z","comments":true,"path":"2016/03/29/Java-GC-监测/","link":"","permalink":"http://bejondshao.github.io/2016/03/29/Java-GC-%E7%9B%91%E6%B5%8B/","excerpt":"","keywords":null,"text":"English Orignal Link: http://www.journaldev.com/2856/java-jvm-memory-model-and-garbage-collection-monitoring-tuning 我们可以通过命令行或者UI工具监测应用的内存使用情况. 这里我们用Java2Demo.jar作为测试应用. jstat 然后我们在Java2Demo.jar所在的目录打开一个命令行窗口, 命令行里启动这个程序: java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar Java2Demo.jar 启动后, 保持程序不要最小化. 我们需要知道正在运行的程序的端口号. ps -eaf | grep Java2Demo.jar 然后就可以看到 bejond 5002 4977 7 11:20 pts/3 00:11:01 java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar Java2Demo.jar bejond 10751 6230 0 13:52 pts/24 00:00:00 grep --color=auto Java2Demo.jar 端口是5002. 可以用jstat命令来观察JVM和内存使用情况: jstat -gc 5502 2000 这个命令是用来查看5002号端口的GC情况, 没2000毫秒刷新一次. 显示的结果类似如下: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 1024.0 1024.0 0.0 1.0 8192.0 4445.9 20480.0 10087.2 20480.0 16769.8 93 0.092 45 1.360 1.4521024.0 1024.0 0.0 1.0 8192.0 6749.7 20480.0 10087.2 20480.0 16769.8 93 0.092 45 1.360 1.4521024.0 1024.0 1.0 0.0 8192.0 1160.5 20480.0 10087.2 20480.0 16769.8 94 0.093 45 1.360 1.4531024.0 1024.0 1.0 0.0 8192.0 3475.4 20480.0 10087.2 20480.0 16769.8 94 0.093 45 1.360 1.4531024.0 1024.0 1.0 0.0 8192.0 5937.9 20480.0 10087.2 20480.0 16769.8 94 0.093 45 1.360 1.4531024.0 1024.0 1.0 0.0 8192.0 8192.0 20480.0 10087.2 20480.0 16769.8 94 0.093 45 1.360 1.4531024.0 1024.0 0.0 1.8 8192.0 2474.5 20480.0 10087.2 20480.0 16769.8 95 0.094 45 1.360 1.4541024.0 1024.0 0.0 1.8 8192.0 4775.0 20480.0 10087.2 20480.0 16769.8 95 0.094 45 1.360 1.4541024.0 1024.0 0.0 1.8 8192.0 7242.4 20480.0 10087.2 20480.0 16769.8 95 0.094 45 1.360 1.4541024.0 1024.0 1.0 0.0 8192.0 1490.7 20480.0 10087.3 20480.0 16769.8 96 0.095 45 1.360 1.4551024.0 1024.0 1.0 0.0 8192.0 3794.8 20480.0 10087.3 20480.0 16769.8 96 0.095 45 1.360 1.4551024.0 1024.0 1.0 0.0 8192.0 6262.4 20480.0 10087.3 20480.0 16769.8 96 0.095 45 1.360 1.4551024.0 1024.0 0.0 0.9 8192.0 494.5 20480.0 10087.3 20480.0 16769.8 97 0.095 45 1.360 1.4551024.0 1024.0 0.0 0.9 8192.0 2796.8 20480.0 10087.3 20480.0 16769.8 97 0.095 45 1.360 1.4551024.0 1024.0 0.0 0.9 8192.0 5100.1 20480.0 10087.3 20480.0 16769.8 97 0.095 45 1.360 1.4551024.0 1024.0 0.0 0.9 8192.0 7565.3 20480.0 10087.3 20480.0 16769.8 97 0.095 45 1.360 1.4551024.0 1024.0 1.1 0.0 8192.0 1809.8 20480.0 10087.3 20480.0 16769.8 98 0.096 45 1.360 1.4561024.0 1024.0 1.1 0.0 8192.0 4110.9 20480.0 10087.3 20480.0 16769.8 98 0.096 45 1.360 1.4561024.0 1024.0 1.1 0.0 8192.0 6415.6 20480.0 10087.3 20480.0 16769.8 98 0.096 45 1.360 1.4561024.0 1024.0 0.0 1.6 8192.0 662.7 20480.0 10087.3 20480.0 16769.8 99 0.096 45 1.360 1.4561024.0 1024.0 0.0 1.6 8192.0 3129.2 20480.0 10087.3 20480.0 16769.8 99 0.096 45 1.360 1.4561024.0 1024.0 0.0 1.6 8192.0 5431.5 20480.0 10087.3 20480.0 16769.8 99 0.096 45 1.360 1.4561024.0 1024.0 0.0 1.6 8192.0 7733.7 20480.0 10087.3 20480.0 16769.8 99 0.096 45 1.360 1.4561024.0 1024.0 1.0 0.0 8192.0 1984.4 20480.0 10087.3 20480.0 16769.8 100 0.097 45 1.360 1.4571024.0 1024.0 1.0 0.0 8192.0 4448.6 20480.0 10087.3 20480.0 16769.8 100 0.097 45 1.360 1.4571024.0 1024.0 1.0 0.0 8192.0 6753.0 20480.0 10087.3 20480.0 16769.8 100 0.097 45 1.360 1.4571024.0 1024.0 0.0 1.0 8192.0 994.0 20480.0 10087.3 20480.0 16769.8 101 0.097 45 1.360 1.4571024.0 1024.0 0.0 1.0 8192.0 3463.0 20480.0 10087.3 20480.0 16769.8 101 0.097 45 1.360 1.4571024.0 1024.0 0.0 1.0 8192.0 5766.2 20480.0 10087.3 20480.0 16769.8 101 0.097 45 1.360 1.4571024.0 1024.0 0.9 0.0 8192.0 0.0 20480.0 10087.3 20480.0 16769.8 102 0.099 45 1.360 1.4591024.0 1024.0 0.9 0.0 8192.0 2464.8 20480.0 10087.3 20480.0 16769.8 102 0.099 45 1.360 1.4591024.0 1024.0 0.9 0.0 8192.0 4768.3 20480.0 10087.3 20480.0 16769.8 102 0.099 45 1.360 1.4591024.0 1024.0 0.9 0.0 8192.0 7231.0 20480.0 10087.3 20480.0 16769.8 102 0.099 45 1.360 1.4591024.0 1024.0 0.0 7.2 8192.0 1317.7 20480.0 10087.3 20480.0 16769.8 103 0.099 45 1.360 1.4591024.0 1024.0 0.0 7.2 8192.0 3785.2 20480.0 10087.3 20480.0 16769.8 103 0.099 45 1.360 1.4591024.0 1024.0 0.0 7.2 8192.0 6086.6 20480.0 10087.3 20480.0 16769.8 103 0.099 45 1.360 1.4591024.0 1024.0 1.0 0.0 8192.0 336.4 20480.0 10087.3 20480.0 16769.8 104 0.100 45 1.360 1.4601024.0 1024.0 1.0 0.0 8192.0 2802.0 20480.0 10087.3 20480.0 16769.8 104 0.100 45 1.360 1.4601024.0 1024.0 1.0 0.0 8192.0 5105.4 20480.0 10087.3 20480.0 16769.8 104 0.100 45 1.360 1.4601024.0 1024.0 1.0 0.0 8192.0 7567.9 20480.0 10087.3 20480.0 16769.8 104 0.100 45 1.360 1.4601024.0 1024.0 0.0 1.6 8192.0 1811.9 20480.0 10087.3 20480.0 16769.8 105 0.101 45 1.360 1.4611024.0 1024.0 0.0 1.6 8192.0 4111.1 20480.0 10087.3 20480.0 16769.8 105 0.101 45 1.360 1.4611024.0 1024.0 0.0 1.6 8192.0 6573.7 20480.0 10087.3 20480.0 16769.8 105 0.101 45 1.360 1.4611024.0 1024.0 1.0 0.0 8192.0 828.8 20480.0 10087.3 20480.0 16769.8 106 0.101 45 1.360 1.4611024.0 1024.0 1.0 0.0 8192.0 3133.0 20480.0 10087.3 20480.0 16769.8 106 0.101 45 1.360 1.4611024.0 1024.0 1.0 0.0 8192.0 5597.5 20480.0 10087.3 20480.0 16769.8 106 0.101 45 1.360 1.4611024.0 1024.0 1.0 0.0 8192.0 7898.7 20480.0 10087.3 20480.0 16769.8 106 0.101 45 1.360 1.4611024.0 1024.0 0.0 1.0 8192.0 2305.3 20480.0 10087.3 20480.0 16769.8 107 0.102 45 1.360 1.462 上面的是我运行Java2Demo.jar很久后的到的结果. S0C和S1C: Survivor0和Survivor1区的大小(C就是count, 我猜的) S0U和S1U: S0和S1被使用的空间, 可以看到总有一个空间是0, 这是每次执行Minor GC后压缩的结果.(U就是used, 也是我猜的) EC和EU: Eden Count, Eden Used, 即Eden的大小和Eden被使用了多少. 可以看到Eden是S0的8倍. 可以看到EU慢慢增长, 当达到EC时会触发Minor GC而变小. 这时候S0U和S1U都会变化. OU也会变大. OC和OU: Old Gen Count, Old Gen Used, 即Old Gen的大小和Old Gen被使用的情况. PC和PU: Perm Gen Count, Perm Gen Used. 即Perm大小和Perm被使用的情况. YGC和YGCT: Young GC, Young GC Time. 就是在Young Gen里执行了多少次Minor GC和每次执行所用的时间. 你会发现YGCT会越来越大, 也就意味着程序运行会越来越慢. FGC和FGCT: Full GC, Full GC Time. 就是执行Full GC次数和Full GC所用的时间. 你会奇怪FGC怎么是47, 这是在启动Java2Demo时加载程序的资源, 所以会执行很多次Full GC. 这不必怀疑. 但是如果你的程序运行一段时间后频繁full GC那就一定有问题了. GCT: GC time. 表示GC所用的时间, 是YGC+FGC. jstat有一个优点是可以在远端的服务器启动这个监听. Java VisualVM和Visual GC jvisualvm是JDK自带的内存监听程序, 在命令行执行 jvisualvm 就会启动这个UI程序. 程序启动后, 在Tool -> Plugins -> Available Plugins, 找到Visual GC, 安装. 然后回到程序主页, 在左边导航栏里能看到Java2Demo{pid 5002}, 点击, 然后打开"Visual GC"页签, 就可以看到GC的信息了. Java GC 调优 Java GC调优应该是在你优化程序后提高性能的方案. 另外, 如果GC花费时间太长, 可以考虑调优. 如果你看到java.lang.OutOfMemoryError: PermGen space错误, 可以试着将-XX:PermGen和-XX:MaxPermGen调大. 也可以使用-XX:+CMSClassUnloadingEnabled来检查使用CMS GC时情况怎么样. 如果你看到很多Full GC操作, 可以试着提高Old Gen的大小. 但是注意, 不是说越大的内存空间就越好, 空间越大执行Major GC的时机就越晚, 而长时间不GC会导致JVM分配内存很慢, 应该是垃圾对象太多的缘故, 所以Old Gen太大反而会拖慢程序的速度. 只有熬到Old Gen满了, 执行Major GC后才会快. 而如果Old Gen很大, 迟迟不触发Major GC, 程序会越来越慢, 反而找不到问题. GC调优需要有很多的努力, 很多的经验去实践, 才能得到最好的适应你的应用的性能结果.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"JVM","slug":"JVM","permalink":"http://bejondshao.github.io/tags/JVM/"}]},{"title":"Java 垃圾回收机制","slug":"Java-垃圾回收机制","date":"2016-03-29T04:11:27.000Z","updated":"2023-03-02T03:26:34.111Z","comments":true,"path":"2016/03/29/Java-垃圾回收机制/","link":"","permalink":"http://bejondshao.github.io/2016/03/29/Java-%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6/","excerpt":"","keywords":null,"text":"English Original Link: http://www.journaldev.com/2856/java-jvm-memory-model-and-garbage-collection-monitoring-tuning Java Garbage Collection(GC) GC就是移除未被引用的对象(垃圾对象), 清理出内存来分配其他新对象. Java垃圾回收是自动的, 这基本不需要程序员管理, 区别于C C++等语言, 需要手动分配内存, 手动释放. 所以这使得Java程序员在内存使用时显得肆无忌惮, 对象回收也无法插手, 所以Java自动回收垃圾机制也成为Java项目的一大诟病. 项目到一定规模势必会有性能问题. 因此发现性能问题, 解决性能问题是一项有用的技能. GC在后台运行, 查找所有的对象, 找到垃圾对象, 然后删除它们. GC一般包括这三步: 标记: 将垃圾对象标记成可被回收状态. 删除: 就是删除啦. 压缩: 在删除垃圾对象后, 为了更好的性能, 会将存活的对象重新整理到一起, 这样会空出成块的内存空间. 上述GC过程有问题, 有什么问题? 很多刚创建的对象就是未被使用的. 在很多GC周期里的对象很可能被未来其他GC周期使用. 就是说很常用的对象可能在未来还会被使用, 如果删除了岂不可惜. 有什么好方法? Java回收机制利用Yong Gen的Minor GC和Old Gen的Major GC来处理这两个问题. Minor GC只会在Eden满了的时候执行, 所以可以避免问题1. Major GC会在Old Gen满了执行, 所以会避免问题2. Java GC 种类 GC一共有五种, 我们可以通过配置来使用不同的机制 Serial GC(-XX:+UseSerialGC): 串行GC使用标记-删除-压缩的模式来进行Minor GC和Major GC. 串行GC一般适用于客户端, 比如个人电脑, 非集群的服务器. 适用于CPU不太强悍的时候. Parallel GC(-XX:+UseParallelGC): 并行GC相对于串行GC, 是用N个线程执行Minor GC, N一般和CPU核心数相同, N可以通过-XX:ParallelGCThreads=n来控制. N并不是越大越好, 不要超过CPU核心数. Parallel Old GC (-XX:+UseParallelOldGC): 这种方式也是并行GC, 区别前者是, 这种方式在Young Gen和Old Gen都会使用并行机制. Concurrent Mark Sweep (CMS) Collector (-XX:+UseConcMarkSweepGC): CMS叫时实标记清理机制(我起的, 高大上吧, 哈哈哈). 就是在Old Gen里, 标记了垃圾对象, 不等Old Gen满, 就开始回收. 这有一个好处是每次回收的对象很少, stop-the-world的时间很短, 低延迟. 这在响应速度要求高的应用上使用, 比如购物网站, 如果网站暂停时间久了, 客户可能就关网页不买了, 去别家去买了, 这哪行. 但是, 这种方式, 想想就明白, 肯定需要强悍的硬件支持, 频繁的GC都会是很大的开销. CMS在Young Gen的方式和Parallel GC一样, 我们可以用-XX:ParallelCMSThreads=n来限制回收进程数. G1 Garbage Collector (-XX:+UseG1GC): 垃圾第一, 也叫G1, 这种模式在java 7以上的版本可用, 从长远来看, 它要替代CMS回收模式. G1回收也是并行的, 时实的, 并且是增量压缩的. 这种方式不考虑Young Gen还是Old Gen, 它将Heap分成几等份区域. 当JVM调用GC时, 它先清理存活对象少的区域, 也就是哪里垃圾多扫哪里. 更多信息Garbage-First Collector Oracle Documentation.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"JVM","slug":"JVM","permalink":"http://bejondshao.github.io/tags/JVM/"}]},{"title":"Java 内存管理机制","slug":"Java-内存管理机制","date":"2016-03-29T04:05:42.000Z","updated":"2023-03-02T03:26:34.110Z","comments":true,"path":"2016/03/29/Java-内存管理机制/","link":"","permalink":"http://bejondshao.github.io/2016/03/29/Java-%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E6%9C%BA%E5%88%B6/","excerpt":"","keywords":null,"text":"English Original Link: http://www.journaldev.com/2856/java-jvm-memory-model-and-garbage-collection-monitoring-tuning JVM Heap被分为两部分, Young Generation, Old Generation. Perm并不属于Heap Young Generation (Young Gen) 所有的new出来的对象都放在Young Gen, 当Young Gen满了, 就会执行Garbage Collection (GC), 此时的GC称为Minor GC. Young Gen被分成三部分: Eden Memory和两个Survivor Memory. 大多数新创建的对象都分配在Eden memory. Eden满了怎么办? JVM就会执行Minor GC. 被引用的对象都会存活下来, 它们将被移到Survivor Memory里, 图中的S0或S1. Eden满了就会执行Minor GC, 满了就执行. Minor GC执行时总会检查Survivor对象, 并且将其中一个Survivor区的对象移到另一个Survivor区里, 方便统计存活的对象大小. 也就是说, 总有一个Survivor区是空的. 在S0, S1轮回几次的存活对象都是比较坚挺的, 所以干脆就移到Old Memory了. 通常来讲, 对象移动到Old Memory是有标准的, 设定一个时间值来确定是否移动. 在Minor GC时, Old Gen可以被忽略. Old Gen对Young Gen的引用被认为是实际的GC Root。 Old Generation (Tenured Gen) Old Gen也叫Tenured Generation. 上面说了, Old Gen都保存比较坚挺的对象, 这些对象是时常被使用的, 起码也是使用频率很高的. 但是Old Memory满了怎么办? 会执行GC, 叫Major GC. Major GC只会清理Old Gen, 耗时比较长. 世界静止(Stop the world event) 所有的GC都会让世界静止, 垃圾回收的时候, 所有线程的工作都暂停, 请求和响应都暂停. Minor GC时数据量比较小, 所以Minor GC很快, 基本感觉不到. 但是Major GC由于要检查所有活着的对象, 花费时间比较长. 应该让Major GC的时间尽可能短(这是很难滴). 所以, 如果服务器短时间频繁做Major GC, 会导致time out问题. GC的耗时取决于使用什么策略进行GC, 所以JVM调优会比较影响性能. Permanent Generation (Perm Gen) Perm Gen保存应用的元数据, 包括该应用的类, 方法的定义和实现, 也包括java的类库和API. 注意, Perm Gen不属于Heap. Perm Gen的对象在full GC的时候会被回收. (Full GC又是什么鬼?) Full GC Full GC区别与Major GC, Major GC只会清理Old Gen. 而Full GC会清理整个jvm 内存的内容, 包括Young Gen, Old Gen, Perm.触发Full GC的情况 Method Area Method area是存储在Perm的一些类结构, 常量, 静态变量, 方法实现等. Memory Pool Memory Pool是由JVM内存管理创建的一个内存池, 用于存储固定不变的对象. String Pool就是一个栗子. Memory Pool可能在Heap, 也可能在Perm, 取决于JVM内存管理的实现方式. Runtime Constant Pool 运行期常量池存储常量, 静态变量程序块和静态方法. 运行期常量池属于Method Area Java Stack Memory 栈内存用来执行一个线程(Thread), 程序抛异常显示的内容就是从栈获取的. 包括方法特定的值, 比如临时变量, 对其他对象的引用(当然了, 对象存储在Heap里). 栈就像一个试管一样, 先进来的变量存在栈底, 因此遵循先进后出(Last In First Out, LIFO)的顺序. 与Heap的区别详见Difference between Stack and Heap Memory . Java Heap Memory Switches Java有很多变量可以设置,对jvm, heap的设置 VM 设置 描述 -XMs JVM启动时heap的初始大小 -XMx heap的最大值 -Xmn Young Gen的大小, 剩下的就是Old Gen的大小 -XX:PermGen Perm Gen初始大小 -XX:MaxPermGen Perm Gen最大值 -XX:SurvivorRatio Eden与单个Survivor的比率, 如果-XX:SurvivorRation=8(默认值), 那么就是Eden:S0=8:1, 所以Eden占Young Gen 8/10, S0和S1分别占Young Gen 1/10 -XX:NewRatio Old与Young的比率, 默认值2 更多配置 JVM Options Official Page 和 redcreen的专栏–JVM系列三:JVM参数设置、分析.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"JVM","slug":"JVM","permalink":"http://bejondshao.github.io/tags/JVM/"}]},{"title":"Liferay - Microsofe Active Directory Configuration","slug":"Liferay-Microsofe-Active-Directory-Configuration","date":"2016-03-24T06:18:00.000Z","updated":"2023-03-02T03:26:34.184Z","comments":true,"path":"2016/03/24/Liferay-Microsofe-Active-Directory-Configuration/","link":"","permalink":"http://bejondshao.github.io/2016/03/24/Liferay-Microsofe-Active-Directory-Configuration/","excerpt":"","keywords":null,"text":"Before config this, please view properties in AD. http://bejondshao.github.io/2016/03/23/Research-LDAP-Properties-for-the-User-Object/ There are so many traps on config Liferay with Active Directory. I’m gonna show you the right configuration. go to Control Panel -> Configuration -> Portal Settings -> Authentication, choose “LDAP” tab. Check Enabled. Import Enabled, Export Enabled can also be checked if you want. Click “Add” to add a LDAP server. On the new form, name it, choose “Apache Directory Server(Yes, click “Apache Directory Server”, not “Microsoft Active Directory Server”)” and click “Reset Values”, it will create default values of config. optmize values. Connection section @ Base Provider URL: change to ldap://ip_of_AD_server:389, the port is 389. @ Base DN: change to your own, eg: ou=org1,dc=bejond,dc=com. @ Principal: authentication for AD server. eg: cn=administrator,cn=users,dc=bejond,dc=com (it’s not case sensitive) or you can use user logon name eg: MYDOMAIN\\administrator @ Credentials: password of the user. Click “Test LDAP Connection” to test if you can logon AD via this user. Users section @ Authentication Search Filter: change it to (userprincipalname=@email_address@). @ Import Search Filter: leave it as default (objectClass=person) User Mapping section @ UUID: leave it blank. @ Screen Name: If you just import user to Liferay, just map any field in AD, eg “sAMAccountName”(“sAMAccountName” is User login name(pre-Windows 2000)), “cn”, please make sure the filed is unique in AD. But if you also want to export user to AD, just map screen name with cn, there’s no second choice. Because liferay would put screen name to add user, while cn is mandatory property. So unique screen name maps to cn suits for export user to AD. If you try other fields like “sAMAccountName”, you will get 1206:47:26,023 ERROR [http-bio-8690-exec-38][render_portlet_jsp:132] nulljavax.naming.InvalidNameException: sAMAccountName=ls15,ou=export,dc=mydomain,dc=com: [LDAP: error code 64 - 00002073: NameErr: DSID-03050AAB, problem 2005 (NAMING_VIOLATION), data 0, best match of:_ 'sAMAccountName=ls15,ou=export,dc=mydomain,dc=com'__]; remaining name 'sAMAccountName=ls15,ou=export,dc=mydomain,dc=com' [Sanitized] But take care that, cn in AD is for “First Name + Last Name” by default, it contains whitespace, so it can’t be imported to liferay as screen name. So you need to change it in AD. @ Email Address: change it to userprincipalname. It can be mapped with “mail” or “userprincipalname”. “mail” is email in AD, “userprincipalname” is User logon name. But if “Authentication Search Filter” is (userprincipalname=@email_address@), then Email Address should be userprincipalname. Portal login with email, so this should be unified. @ Password: leave it as default userPassword. @ First Name: leave it as default givenName. @ Middle Name: leave it blank. @ Last Name: leave it as default or blank sn. @ Full Name: leave it as blank, you can also set to other attributes. @ Job Title: leave it as default title. @ Status: You can map “status” with “useraccountcontrol” and try to export user to AD. You will get 1javax.naming.OperationNotSupportedException: [LDAP: error code 53 - 0000052D: SvcErr: DSID-031A0FC0, problem 5003 (WILL_NOT_PERFORM) Because a certificate must be installed on the domain controller and tied to AD, and then the client must support an SSL connection to AD for LDAP. The other attributes in the schema do not have this restriction and can be updated without a secure connection. So as far, let’s leave status blank. @ Group, Portrait, Custom User Mapping, Custom Contact Mapping: leave them blank Now click “Test LDAP Users”, you’ll see users from AD Groups section @ Import Search Filter: change it to (objectClass=group) Group Mapping section @ Group Name: leave it as default cn @ Descrption: leave it as default description @ User: leave it as default uniqueMember Now click “Test LDAP Groups”, you’ll see groups from AD Export section @ Users DN: change to the group or organization unit you want to export ou=export,dc=bejond,dc=com @ User Default Object Classes: leave it as default top,person,inetOrgPerson,organizationalPerson @ Groups DN: change it according to your domain, eg dc=bejond,dc=com @ Group Default Object Classes: leave it as default top,groupOfUniqueNames Then click “Save”, all settings are done. Let’s test export. Go to Users and Groups, create a user and save. If your config is right, you’ll see the user you created in AD. Liferay would export user when the user is added or updated. If you want to export existing users to LDAP, you can run a script on updating existing users with changing a non-important field.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"Liferay","slug":"Java/Liferay","permalink":"http://bejondshao.github.io/categories/Java/Liferay/"}],"tags":[{"name":"Liferay","slug":"Liferay","permalink":"http://bejondshao.github.io/tags/Liferay/"},{"name":"LDAP","slug":"LDAP","permalink":"http://bejondshao.github.io/tags/LDAP/"},{"name":"Active Directory","slug":"Active-Directory","permalink":"http://bejondshao.github.io/tags/Active-Directory/"}]},{"title":"如何在Hexo文章中插入图片","slug":"如何在Hexo文章中插入图片","date":"2016-03-23T09:09:00.000Z","updated":"2023-03-02T03:26:34.236Z","comments":true,"path":"2016/03/23/如何在Hexo文章中插入图片/","link":"","permalink":"http://bejondshao.github.io/2016/03/23/%E5%A6%82%E4%BD%95%E5%9C%A8Hexo%E6%96%87%E7%AB%A0%E4%B8%AD%E6%8F%92%E5%85%A5%E5%9B%BE%E7%89%87/","excerpt":"","keywords":null,"text":"如何插入的图片? https://hexo.io/docs/asset-folders.html 编辑_config.yml 1post_asset_folder: true 这样hexo会在每次使用hexo new title命令时在文章源文件目录下创建同名文件夹来存储资源. 在markdown文章里如何引用? 123{% asset_path slug %}{% asset_img slug [title] %}{% asset_link slug [title] %} 举个栗子: 本篇文章名叫what-is-LDAP, 创建它时,会创建同名文件夹,把LDAP.png放在那个文件夹下. 引用时写 1{% asset_img LDAP.png DLAP organization %} asset_img 表示要引用图片, LDAP.png是文件名, 后面的是图片显示的标题,可含空格。 asset_path会直接将连接显示在页面中。 asset_link可以用作内部连接, 可以用于连接文件, 下载使用。 然后执行hexo generate (或者hexo g) 就会将资源拷贝到和生成的文章相同的目录下,这样就可以了.在本地查看会显示不正常,但是部署到github上就显示正常了.","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"},{"name":"Hexo","slug":"Others/Hexo","permalink":"http://bejondshao.github.io/categories/Others/Hexo/"}],"tags":[{"name":"Hexo","slug":"Hexo","permalink":"http://bejondshao.github.io/tags/Hexo/"}]},{"title":"Research LDAP Properties for the User Object","slug":"Research-LDAP-Properties-for-the-User-Object","date":"2016-03-23T08:51:50.000Z","updated":"2023-03-02T03:26:34.191Z","comments":true,"path":"2016/03/23/Research-LDAP-Properties-for-the-User-Object/","link":"","permalink":"http://bejondshao.github.io/2016/03/23/Research-LDAP-Properties-for-the-User-Object/","excerpt":"","keywords":null,"text":"Original post: http://www.computerperformance.co.uk/Logon/LDAP_attributes_active_directory.htm Convert to Markdown tool: http://fuckyeahmarkdown.com/ LDAP Attributes. Properties Active Directory Users Computers Distinguished name Research LDAP Properties for the User Object This page explains the common LDAP attributes which are used in VBS scripts and PowerShell. Programs like VBScript (WSH), CSVDE and LDIFDE rely on these LDAP attributes to create or modify objects in Active Directory. For example, when you bulk import users you will include the LDAP attributes: dn and sAMAccountName. LDAP is the Lightweight Directory Access Protocol. Hall of Fame LDAP Attribute - DN Distinguished Name As the word ‘distinguished’ suggests, this is THE LDAP attribute that uniquely defines an object. Each DN must have a different name and location from all other objects in Active Directory. The other side of the coin is that DN provides a way of selecting any object in Active Directory. Once you have selected the object, then you can change its attributes. Time spent in getting to know the DN attribute will repay many fold. Observe the different components CN=common name, OU = organizational unit. DC often comes with two entries, DC=CP, DC=COM. Note that DC=CP.COM would be wrong. Incidentally in this situation, DC means domain content rather than domain controller. Another point with the syntax is to check the speech marks; when used with VBScript commands, DN is often enclosed in “speech marks”. Even the speech marks have to be of the right type, “double quotes are correct”, ‘single quotes may be ignored’, with unpredictable results. Finally, pay particular attention to commas in distinguished names. LDAP Attributes from Active Directory Users and Computers The diagram below is taken from Active Directory Users and Computers. It shows the commonest LDAP attributes for vbs scripts. When you write your scripts, check how the LDAP attributes map to the Active Directory boxes. Research Tip: One of my favourite techniques is to add values in the active directory property boxes, then export using CSVDE. Next, open the .csv file in Excel, search for the value, and read the LDAP field name from row 1. LDAP Attribute Example C Country: e.g GB for Great Britain. CN - Common Name CN=Guy Thomas. Actually, this LDAP attribute can be made up from givenName joined to SN. CN Maps to ‘Name’ in the LDAP provider. Remember CN is a mandatory property. See also sAMAccountName. description What you see in Active Directory Users and Computers. Not to be confused with displayName on the Users property sheet. displayName displayName = Guy Thomas. If you script this property, be sure you understand which field you are configuring. DisplayName can be confused with CN or description. Display name -v- Description Important LDAP Notes Di_s_play name and _D_escription are different Offi_c_e’s LDAP attribute is: physicalDeliveryOfficeName E-_m_ail is plain: mail LDAP Attribute Example DN - also distinguishedName DN is simply the most important LDAP attribute. CN=Jay Jamieson, OU= Newport,DC=cp,DC=com givenName Firstname also called Christian name homeDrive Home Folder : connect. Tricky to configure initials Useful in some cultures. name name = Guy Thomas. Exactly the same as CN. objectCategory Defines the Active Directory Schema category. For example, objectCategory = Person objectClass objectClass = User. Also used for Computer, organizationalUnit, even container. Important top level container. physicalDeliveryOfficeName Office! on the user’s General property sheet postOfficeBox P.O. box. profilePath Roaming profile path: connect. Trick to set up sAMAccountName This is a mandatory property, sAMAccountName = guyt. The old NT 4.0 logon name, must be unique in the domain. sAMAccountName If you are using an LDAP provider ‘Name’ automatically maps to sAMAcountName and CN. The default value is same as CN, but can be given a different value. SN SN = Thomas. This would be referred to as last name or surname. title Job title. For example Manager. userAccountControl Used to disable an account. A value of 514 disables the account, while 512 makes the account ready for logon. userPrincipalName userPrincipalName = [email protected] Often abbreviated to UPN, and looks like an email address. Very useful for logging on especially in a large Forest. Note UPN must be unique in the forest. wWWHomePage User’s home page. Examples of Exchange Specific LDAP attributes LDAP Attribute Example homeMDB Here is where you set the MailStore legacyExchangeDN Legacy distinguished name for creating Contacts. In the following example, Guy Thomas is a Contact in the first administrative group of GUYDOMAIN: /o=GUYDOMAIN/ou=first administrative group/cn=Recipients/cn=Guy Thomas mail An easy, but important attribute. A simple SMTP address is all that is required [email protected] mAPIRecipient - FALSE Indicates that a contact is not a domain user. mailNickname Normally this is the same value as the sAMAccountName, but could be different if you wished. Needed for mail enabled contacts. mDBUseDefaults Another straightforward field, just the value to:True msExchHomeServerName Exchange needs to know which server to deliver the mail. Example: /o=YourOrg/ou=First Administrative Group/cn=Configuration/cn=Servers/cn=MailSrv proxyAddresses As the name ‘proxy’ suggests, it is possible for one recipient to have more than one email address. Note the plural spelling of proxyAddresses. targetAddress SMTP:@ e-mail address. Note that SMTP is case sensitive. All capitals means the default address. showInAddressBook Displays the contact in the Global Address List. Other Useful LDAP Attributes / Propeties LDAP Attribute Example c Country or Region company Company or organization name department Useful category to fill in and use for filtering homephone Home Phone number, (Lots more phone LDAPs) l (Lower case L) L = Location. City ( Maybe Office location Important, particularly for printers and computers. manager Boss, manager mobile Mobile Phone number ObjectClass Usually, User, or Computer OU Organizational unit. See also DN pwdLastSet Force users to change their passwords at next logon postalCode Zip or post code st State, Province or County streetAddress First line of address telephoneNumber Office Phone userAccountControl Enable (512) / disable account (514) Examples of Obscure LDAP Attributes LDAP Attribute Example dNSHostname rID url uSNCreated, uSNChanged To discover more LDAP attributes, go to the command prompt, type: 1CSVDE -f Exportfile.csv Then open Exportfile.csv with Excel.exe. Alternatively, use ADSI Edit and right-click the container objects.","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"LDAP","slug":"LDAP","permalink":"http://bejondshao.github.io/tags/LDAP/"}]},{"title":"Google hosts 更新(授之以渔)","slug":"Google-hosts-更新-授之以渔","date":"2016-03-10T09:17:39.000Z","updated":"2023-03-02T03:26:34.079Z","comments":true,"path":"2016/03/10/Google-hosts-更新-授之以渔/","link":"","permalink":"http://bejondshao.github.io/2016/03/10/Google-hosts-%E6%9B%B4%E6%96%B0-%E6%8E%88%E4%B9%8B%E4%BB%A5%E6%B8%94/","excerpt":"","keywords":null,"text":"此文记录我获取hosts的几个途径. 一. racaljk 的host获取工具 https://github.com/racaljk/hosts 里面有详细的不同平台的获取和更改hosts的方法. 对于linux, 里面提到一个一条命令更新hosts的方法, 简直是福音啊! 1bash -c 'wget https://raw.githubusercontent.com/racaljk/hosts/master/hosts -qO /tmp/hosts && sudo mv /tmp/hosts /etc/hosts' @ bash -c 若用-c参数,则bash从字符串中读入命令,如果字符串后还有变量就被设定为从$0开始的位置参数 @ wget -qO -q, --quiet不显示输出信息 -O, --output-document=FILE 指定下载目录和文件名 这条命令就是从远端下载定期更新的文件hosts, 保存为/tmp/hosts文件, 并移动/tmp/hosts到/etc/hosts. 其实生效的是/etc/hosts文件. 这条语句需要root权限. 这条语句其实不算完美, 因为暴力的用/tmp/hosts替换了/etc/hosts. 其实在做任何配置的更改前, 最好备份原数据. 所以我对上条语句进行了优化. 1bash -c 'wget https://raw.githubusercontent.com/racaljk/hosts/master/hosts -O /tmp/hosts && cp /etc/hosts /etc/hosts.bak && sudo mv /tmp/hosts /etc/hosts && echo "127.0.0.1 yourhostname" >> /etc/hosts' 我把wget -q去掉了, 这样可以看到下载的信息, 心里有个底儿. 另外我在替换前备份了原hosts. 最后添加主机名到127.0.0.1, 详情见 http://bejondshao.github.io/2016/03/10/sudo-unable-to-solve-host-bejond/ 对于Mac OS,https://github.com/racaljk/hosts 推荐了手动更改,或者用Gas Mask。手动更改不推荐,因为mac下的hosts保存在/private/etc/hosts,这个位置无法通过Finder直接进入,需要用快捷键"Cmd Shift G",然后在弹出的窗口里输入"/private/etc",这样找到hosts,并且还要更改hosts文件的权限,很麻烦。另外,我也试了Gas Mask,这个工具很好,因为它直接获取了hosts,直接打开,我们编辑后保存就可以了。 Mac OS其实是like Unix的,所以Linux能运行的命令基本上在Mac上也能运行。所以我把上面的命令更改了下,大体上差不多,只不过需要注意:1. 运行命令时要确保Gas Mask处于关闭状态,因为Gas Mask监控hosts,会限制其他操作对hosts的修改。我在运行命令一开始总是无法更新hosts,后来关闭Gas Mask就能更新成功了。 1bash -c 'wget https://raw.githubusercontent.com/racaljk/hosts/master/hosts -O /tmp/hosts && mv /private/etc/hosts /private/etc/hosts.bak && cp /tmp/hosts /private/etc/hosts && echo "127.0.0.1 bejond" >> /private/etc/hosts' 一个命令,就完成了更新hosts的操作,很方便。至于Windows理论上也能做到,只不过 bash, wget, mv, cp, echo等命令需要更改为适合Windows的。 二. 盒子 整理发布的hosts http://www.360kb.com/kb/2_150.html 好处是直观简介, 复制下来贴到hosts里就行. 这个域名暂时还没有被和谐, 祝好运. 三. 老D http://laod.cn/hosts/2016-google-hosts.html 这个hosts更新也比较快, 但是更新hosts需要到百度盘,输入提取码,下载zip文件, 并且zip还带密码, 必须按照他说的做. 奇葩的是, 域名竟然是.cn的, 看来老D网站流量挺大, 祈福这个cn域名不会被和谐吧. 四. 百度google hosts 这些网站的hosts极不稳定, 很多网站为了流量而贴的过期hosts, 有点坑人. 所以要有未雨绸缪的精神, 在你当前hosts好用的情况下, 用google或者bing搜索好的hosts资源. 五. 付费VPN 这个也是最简单,最直接,比较方便的一条途径. 其实VPN也不算太贵, 一个月十到十五块的价格, 平均起来每天也不到一块. 我觉得每次看到google无限风火轮对精神的摧残是远远大于这几毛钱的花费的. 一般是包月, 我推荐你买服务前最好先到VPN测评网站看看VPN口碑, 还有要找准VPN正确的官方网站, 很多山寨网站冒充原主的名字, 等你交了钱却没有服务就傻眼了. 这里就不推荐了. 但是给点建议是买服务可以买三个月试试, 或者半年. 我一次性买了两年就有点后悔, 虽然一次买久了价格能便宜点, 但是速度慢也是比较令人惆怅的, 钱都交了, 你能咋地. 简单是付了钱, 就好像你在国外上网了, 所以所有的网站都畅通了. 但是访问国内网站会很慢, 甚至有的网站无法访问, 因为国外也会屏蔽中国的视频网站,比如土豆, 优酷等等. 还有很多在线音乐无法使用. 还有迅雷下载时很慢. 这样就导致你不得不时不时的切换VPN, 所以说比较方便. 还有很重要一点,除了Google,还有维基百科,很多国外的说不定什么时候会用到的网站,以及Youtube上的技术教程,sourceforge.net等等,尤其是第三方jar,maven库这类资源往往无法通过设定hosts来解决网络问题。这时候还必须使用VPN了。 还有一个方法是自己搭建VPS来实现VPN,亚马逊AWS有一年免费试用主机。我曾试过,速度挺好,比较稳定,也是一种实现翻墙的方式。这类实现的好处是自己使用服务,不会出现速度慢的情况,并且数据也不会被截取。 好了,以上的几种方式就是实现翻墙的,其实最终目的不是去看外面的世界,我并没有觉得墙外的风景更美,而是技术需求。在这里还是提醒下大家,不要为了翻墙而翻墙,要想想自己为什么这么做,目的是什么。","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"Hosts","slug":"Hosts","permalink":"http://bejondshao.github.io/tags/Hosts/"},{"name":"Google","slug":"Google","permalink":"http://bejondshao.github.io/tags/Google/"}]},{"title":"sudo: unable to solve host hostname","slug":"sudo-unable-to-solve-host-bejond","date":"2016-03-10T09:12:44.000Z","updated":"2023-03-02T03:26:34.218Z","comments":true,"path":"2016/03/10/sudo-unable-to-solve-host-bejond/","link":"","permalink":"http://bejondshao.github.io/2016/03/10/sudo-unable-to-solve-host-bejond/","excerpt":"","keywords":null,"text":"1.症状: 当你是使用sudo来执行命令时,总是在命令执行时,首先输出:“sudo:unable to resolve host Lily-desktop”(假设Lily-desktop 是你的当前主机的名字(host-name)), 但是怎样才能使使用sudo像以前一样不错误提示,正常工作呢。 when you’re running commands with sudo at beginning.It outputs “sudo:unable to resolve host Lily-desktop”(here assume current host-name is Lily-desktop),however the commands work as well as before. 2.产生该症状的原因: 这种症状经常发生在更改了hostname的情形下。在通过 编辑 /etc/hostname 改变了主机名字(hostname)之后, 我们还需要改变 /etc/hosts文件的相应部分的内容 This always happens after host-name changed.After change host-name by edit /etc/hostname,we also need to do a change in /etc/hosts file. 3.解决方案: Solve: Edit /etc/hosts: // 编辑 /etc/hosts 文件 gksudo gedit /etc/hosts make it looks like (change boldfaced words to current host-name): //使粗体字对应的词与当前的主机名即hostname 一致 127.0.0.1 localhost 127.0.1.1 Lily-desktop 以上信息来自 http://blog.csdn.net/wzb56_earl/article/details/6289988 http://nixcraft.com/ubuntu-debian/13543-ubuntu-sudo-unable-resolve-host.html // 对于解决方案可以直接用命令 echo “127.0.0.1 yourhostname” >> /etc/hosts 这样会直接将主机名对应127.0.0.1追加到hosts末尾 // echo “test” > a.txt 会清除a.txt的内容, 然后添加"test"","raw":null,"content":null,"categories":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/categories/Linux/"}],"tags":[{"name":"Linux","slug":"Linux","permalink":"http://bejondshao.github.io/tags/Linux/"},{"name":"Hosts","slug":"Hosts","permalink":"http://bejondshao.github.io/tags/Hosts/"}]},{"title":"Intellij和Maven管理项目依赖","slug":"Intellij和Maven管理项目依赖","date":"2016-03-07T04:41:44.000Z","updated":"2023-03-02T03:26:34.091Z","comments":true,"path":"2016/03/07/Intellij和Maven管理项目依赖/","link":"","permalink":"http://bejondshao.github.io/2016/03/07/Intellij%E5%92%8CMaven%E7%AE%A1%E7%90%86%E9%A1%B9%E7%9B%AE%E4%BE%9D%E8%B5%96/","excerpt":"","keywords":null,"text":"在了解maven以前, 我们的项目依赖都是放在WEB-INF/lib/下, 并且跟随项目打包, 这样有一个好处是移植性很好, 并且可以通过版本管理,比如git管理jar包. 产品下载下来就可以使用, 但是弊端在于占用了网络资源. 当lib大于100M的时候, 可以想象其他用户要下载要多花费很多时间. 而开发者下载时更是浪费了资源, 因为很多jar包开发者本来自己就具备了, 不必下载. 另外多个项目共同部署在一个服务器下时, jar包依赖会导致冲突, 这种问题算是莫名其妙的一类, 因为这种问题自己很难找到原因, 在网上搜索获得的答案几率比较小. 总的说来, maven管理项目依赖有利有弊, 但随着maven在开发者社区的普及, 会令项目移植更方便, 更快捷. 这几天在研究maven, 我们知道maven的项目依赖都记录在pom.xml, 这有一个好处是这个文件可以受git管理, 并且要更新更改jar包依赖只需要更改这个文件即可. 这个文件是手动编辑的, 编辑起来也不算费劲. 但是考虑到以前项目依赖都是放在一个目录里, 在Intellij或eclipse添加依赖就可以了, 而maven的依赖要手动写,未免有点不爽. 其实Intellij能自动生成依赖, 并且将依赖添加到module的依赖中. 这正是本文要说的. 在介绍Intellij与maven结合之前, 先介绍下Intellij自身对依赖的处理. 每当我们创建project或module时, 都会创建一个module-name.iml文件, 这个文件是Intellij对module的记录, 包括module类型,所包含的组件,以及依赖包的记录. 每当我们手动添加依赖后, 都会在iml文件中记录, 如图: 但是这个iml是属于Intellij的, 我们一般都是忽视这个文件的, 就是将其添加到.gitignore中. 因为如果这个文件被版本管理, 这个文件就会被其他开发者(或者你的另一个终端)下载, 而这个文件往往会导致冲突, 每次解决与项目无关的文件的冲突, 会不会有种想删了它的冲动, 对, 所以我们不管理这个文件. 所以接下来的操作, 我们不关注iml文件, 所有的项目依赖都由pom.xml管理. pom.xml这个文件的更改就涉及jar包的更新, 算是重大的更新, 所以每次更改都推荐将其单独提交. 用Intellij创建一个单独的maven module, 叫testmaven. 创建Hello.java 123456789package com.bejond.testmaven;/** * Created by bejond on 16-3-7. */public class Hello { public void main(String[] args) { System.out.println("Hello!"); }} 创建TestHello.java package com.bejond.testmaven; 1234567891011/** * Created by bejond on 16-3-7. */public class TestHello { @Test public void testHello() { Hello hello = new Hello(); hello.main(new String[] {}); }} 这时会发现@Test注解不存在, 我们需要配置pom.xml 1234567891011121314151617<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.bejond.testmaven</groupId> <artifactId>testmaven</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies></project> 每当pom.xml更改, Intellij就会检测到, 并且提示你导入更改, 以影响项目的依赖. 点击"Import Changes", 这时, 打开module settings (F4), 会发现项目依赖添加了Junit(以Maven开头), 说明pom起作用了. 然后到TestHello.java引入就可以了. (或者使用快捷键"Alt Enter") 1import org.junit.Test; ================================== Intellij更强大的在于, 它可以预测我们要导入的包, 也就是说pom.xml依赖可以由Intellij生成! 在第4步, 转到TestHello.java, 因为我们在这个文件要使用新的包. 点击"@Test", 等待三秒, 然后在弹出的小灯泡点击"Add Maven Dependency". (上述过程可以使用快捷键"Alt Enter"), 选择要使用的jar. 然后再执行第5,6,7就可以了. ================================== 所以现在我们回顾一下, 当我们利用maven管理包, 并且通过pom.xml记录依赖时, 我们不必手动下载对应的包(当中央资源库没有时, 也需要手动下载并指定), 然后在我们使用包时, 通过Intellij为我们生成pom依赖, 进而就可以正常使用了. 虽然想要达到的目的和以前一样, 但是新的依赖管理方式让项目依赖更方便, 更智能. 当然Maven还有其他的项目管理功能, 比如编译, 测试, 打包, 安装以供其他项目使用, 很方便.","raw":null,"content":null,"categories":[{"name":"Tools","slug":"Tools","permalink":"http://bejondshao.github.io/categories/Tools/"}],"tags":[{"name":"Intellij","slug":"Intellij","permalink":"http://bejondshao.github.io/tags/Intellij/"},{"name":"Maven","slug":"Maven","permalink":"http://bejondshao.github.io/tags/Maven/"}]},{"title":"Java中文乱码问题","slug":"Java中文乱码问题","date":"2016-03-01T09:03:00.000Z","updated":"2023-03-02T03:26:34.112Z","comments":true,"path":"2016/03/01/Java中文乱码问题/","link":"","permalink":"http://bejondshao.github.io/2016/03/01/Java%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/","excerpt":"","keywords":null,"text":"@ jsp页面乱码, 在jps中加 <%@ page contentType="text/html;charset=UTF-8" language="java" %> @ jsp传值到Action的乱码. struts.xml 不适用于struts2.1.6 (这个版本有这个bug, 其他版本可以通过这样配置), 可以用spring的filter <constant name="struts.i18n.encoding" value="UTF-8" /> @ 持久化到数据库内乱码, 配置数据库连接时, 后面参数加上编码, 并且数据库一开始创建时就应该指定编码格式. 12345jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8jdbc.username=rootjdbc.password= @ Tomcat中对于post方法提交的表单采用的默认编码为ISO-8859-1,而这种编码格式不支持中文字符。对于这个问题可以采用转换编码格式的方法来解决 在web.xml配置 12345678910111213141516<filter> <filter-name>Set Character Encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param></filter><filter-mapping> <filter-name>Set Character Encoding</filter-name> <url-pattern>/*</url-pattern></filter-mapping> ######注意, 这个filter应该在struts filter前, 并且不能和 <constant name="struts.i18n.encoding" value="UTF-8" /> ######冲突","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"}],"tags":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/tags/Java/"},{"name":"Encoding","slug":"Encoding","permalink":"http://bejondshao.github.io/tags/Encoding/"}]},{"title":"PortalException in moveFolders method will cause inconsistency issue between database and file system","slug":"PortalException-in-moveFolders-method-will-cause-inconsistency-issue-between-database-and-file-system","date":"2015-12-18T11:35:00.000Z","updated":"2023-03-02T03:26:34.189Z","comments":true,"path":"2015/12/18/PortalException-in-moveFolders-method-will-cause-inconsistency-issue-between-database-and-file-system/","link":"","permalink":"http://bejondshao.github.io/2015/12/18/PortalException-in-moveFolders-method-will-cause-inconsistency-issue-between-database-and-file-system/","excerpt":"","keywords":null,"text":"When we try to move folders from one repository to another one, if the source file is deleted in file system, the move process would be roll back due to transaction, while files before exception would be moved to new repository. This causes inconsistency. The detail https://issues.liferay.com/browse/LPS-61337 It depends on https://issues.liferay.com/browse/LPS-60884 Here is what I do: I delete a file in file system and try to move it to another folder. Then I debug that in FileSystemStore.getFileAsStream(companyId, repositoryId, fileName, versionLabel) 123456789101112131415161718192021public InputStream getFileAsStream( long companyId, long repositoryId, String fileName, String versionLabel) throws PortalException { if (Validator.isNull(versionLabel)) { versionLabel = getHeadVersionLabel( companyId, repositoryId, fileName); } File fileNameVersionFile = getFileNameVersionFile( companyId, repositoryId, fileName, versionLabel); try { return new FileInputStream(fileNameVersionFile); } catch (FileNotFoundException fnfe) { throw new NoSuchFileException(fileNameVersionFile.getPath(), fnfe); }} It throws FileNotFoundException. But the moving file action processed successfully. I continue debug about the exception, portal goes to DLFileEntryIndexer.doGetDocument(obj) // It’s about update index 1234567891011121314151617181920212223242526272829303132protected Document doGetDocument(Object obj) throws Exception { DLFileEntry dlFileEntry = (DLFileEntry)obj; if (_log.isDebugEnabled()) { _log.debug("Indexing document " + dlFileEntry); } boolean indexContent = true; InputStream is = null; try { String[] ignoreExtensions = PrefsPropsUtil.getStringArray( PropsKeys.DL_FILE_INDEXING_IGNORE_EXTENSIONS, StringPool.COMMA); if (ArrayUtil.contains( ignoreExtensions, StringPool.PERIOD + dlFileEntry.getExtension())) { indexContent = false; } if (indexContent) { is = dlFileEntry.getFileVersion().getContentStream(false); } } catch (Exception e) { } DLFileVersion dlFileVersion = dlFileEntry.getFileVersion(); You can see that it catch the exception, but does nothing. So the code continue doing the rest process. I come up with an idea about moveFolder, we can doing the same thing when the file is lost. But you know, we just hide the exception to make the process continue. Because in all, liferay doesn’t support transaction for file system. Here is my solution https://github.com/daledotshan/liferay-portal/pull/367 In my first commit, I catch the exception and print it out. I don’t throw exception in order to continue the moving process. In this way, we can avoid the inconsistency thing. In my second commit, I don’t delete the source folder if the source folder is not empty. Because if the files are all good, they will be moved to new folder. So the source folder would be empty and it can be deleted. So the left files are not found in file system.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"Liferay","slug":"Java/Liferay","permalink":"http://bejondshao.github.io/categories/Java/Liferay/"}],"tags":[{"name":"Liferay","slug":"Liferay","permalink":"http://bejondshao.github.io/tags/Liferay/"}]},{"title":"Liferay - ldap password policy - need specific error messages from AD on failed binds","slug":"Liferay-ldap-password-policy-need-specific-error-messages-from-AD-on-failed-binds","date":"2015-12-18T11:34:00.000Z","updated":"2023-03-02T03:26:34.184Z","comments":true,"path":"2015/12/18/Liferay-ldap-password-policy-need-specific-error-messages-from-AD-on-failed-binds/","link":"","permalink":"http://bejondshao.github.io/2015/12/18/Liferay-ldap-password-policy-need-specific-error-messages-from-AD-on-failed-binds/","excerpt":"","keywords":null,"text":"Customer has configured Liferay with Microsoft Active directory through LDAP and have below queries regarding LDAP password policies: How to display MS Active Directory password policy error message into liferay?(ex. if password expires in AD then password message expiry message should show in Liferay while login) If we have multiple directory servers (ADS,OpenDs…etc) in our environment, each directory servers having unique users and different password policies, how can we integrated this password polices in liferay & show corresponding Directory Server’s ( For Example ADS1, ADS2, OpenDs) error messages. How “Ldap password policies” works, specially in below Use Case(Ldap Required and Enable option checked): If we uncheck the LDAP password policies, now if user password got expired in AD and we try to login in Liferay with AD password it will show “Authentication failed”, which means it is still using LDAP password policy while we have unchecked it. CSE Research: I did some research and found, to display the LDAP (AD) error message into liferay as per the AD password policy, there are some property into Liferay portal.properties which need to map with AD. Below are the properties from portal.properties: Set these values to be a portion of the error message returned by the appropriate directory server to allow the portal to recognize messages from the LDAP server. The default values will work for Fedora DS. # ldap.error.password.age=age ldap.error.password.expired=expired ldap.error.password.history=history ldap.error.password.not.changeable=not allowed to change ldap.error.password.syntax=syntax ldap.error.password.trivial=trivial ldap.error.user.lockout=retry limit Request/Task: Please analyze the above property and let us know, what values need to be set in these properties to display the AD message at Liferay end. How “Ldap password policies” will work in the above point 3 use case? How to integrated the password polices in liferay & show corresponding Directory Server’s error messages( For Example ADS1, ADS2, OpenDs). ================================================================================================= 3) How "Ldap password policies" works, specially in below Use Case(Ldap Required and Enable option checked): If we uncheck the LDAP password policies, now if user password got expired in AD and we try to login in Liferay with AD password it will show "Authentication failed", which means it is still using LDAP password policy while we have unchecked it. If you check “Enabled” and “Required”, “Required” means check this box if LDAP authentication is required. Liferay will then not allow a user to log in unless he or she can successfully bind to the LDAP directory first. Uncheck this box if you want to allow users with Liferay accounts but no LDAP accounts to log in to the portal. There’s another setting “User LDAP Password Policy”, it is called in UserLocalServiceImpl.checkPasswordExpired(User), public void checkPasswordExpired(User user) throws PortalException, SystemException { if (LDAPSettingsUtil.isPasswordPolicyEnabled(user.getCompanyId())) { return; } PasswordPolicy passwordPolicy = user.getPasswordPolicy(); // Check if password has expired if (isPasswordExpired(user)) { int graceLoginCount = user.getGraceLoginCount(); if (graceLoginCount < passwordPolicy.getGraceLimit()) { user.setGraceLoginCount(++graceLoginCount); userPersistence.update(user); } else { user.setDigest(StringPool.BLANK); userPersistence.update(user); throw new PasswordExpiredException(); } } // Check if user should be forced to change password on first login if (passwordPolicy.isChangeable() && passwordPolicy.isChangeRequired()) { if (user.getLastLoginDate() == null) { user.setPasswordReset(true); userPersistence.update(user); } } } You can see if you check “User LDAP Password Policy”, portal would not check passwordPolicy. If you uncheck “User LDAP Password Policy”, portal would check the password policy of this user and check for him. That’s why customer uncheck “User LDAP Password Policy”, failed to login. It’s because the user doesn’t pass his password policy in Liferay. We can ask customer to check if there’s any other password policy in liferay. Why do this happen? Please see Available authenticators are: com.liferay.portal.security.auth.LDAPAuth # See the LDAP properties to configure the behavior of the LDAPAuth class. # auth.pipeline.pre=com.liferay.portal.security.auth.LDAPAuth #auth.pipeline.post= # Set this to true to enable password checking by the internal portal authentication. If set to false, you're essentially delegating password checking to the authenticators configured in "auth.pipeline.pre" and "auth.pipeline.post" settings. # auth.pipeline.enable.liferay.check=true Where does portal use LDAP to authenticate user? It locates in LDAPAuth.authenticateAgainstPreferredLDAPServer(long, String, String, long, String). result = authenticate( ldapServerId, companyId, emailAddress, screenName, userId, password); so in authenticate( ldapServerId, companyId, emailAddress, screenName, userId, password) , LDAP server will return validation result, or validation error message. Then portal would check error message with the key words Set these values to be a portion of the error message returned by the appropriate directory server to allow the portal to recognize messages from the LDAP server. The default values will work for Fedora DS. # ldap.error.password.age=age ldap.error.password.expired=expired ldap.error.password.history=history ldap.error.password.not.changeable=not allowed to change ldap.error.password.syntax=syntax ldap.error.password.trivial=trivial ldap.error.user.lockout=retry limit For the specific key words for the error message, I’m sorry I don’t know really. Customer can catch the error message that throwed from LDAP server, try to get the key words in different situagions and set the key words to the properties above. How to enable LDAP authentication? So in order to disable internal portal authentication, please set auth.pipeline.enable.liferay.check=false 2) If we have multiple directory servers (ADS,OpenDs..etc) in our environment, each directory servers having unique users and different password policies, how can we integrated this password polices in liferay & show corresponding Directory Server's ( For Example ADS1, ADS2, OpenDs) error messages. Portal allows adding multiple directory servers in control panel. If customer disables internal portal authentication, different users will do different authentication according to his LDAP server. So please try to help customer to enable LDAP server authentication first, then try to help customer to get error messages and set right key words.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"Liferay","slug":"Java/Liferay","permalink":"http://bejondshao.github.io/categories/Java/Liferay/"}],"tags":[{"name":"Liferay","slug":"Liferay","permalink":"http://bejondshao.github.io/tags/Liferay/"},{"name":"LDAP","slug":"LDAP","permalink":"http://bejondshao.github.io/tags/LDAP/"}]},{"title":"PortalException in moveFolders method will cause losing data","slug":"PortalException-in-moveFolders-method-will-cause-losing-data","date":"2015-12-18T11:31:00.000Z","updated":"2023-03-02T03:26:34.190Z","comments":true,"path":"2015/12/18/PortalException-in-moveFolders-method-will-cause-losing-data/","link":"","permalink":"http://bejondshao.github.io/2015/12/18/PortalException-in-moveFolders-method-will-cause-losing-data/","excerpt":"","keywords":null,"text":"Sample Issue Customer has a customer portlet to move folders from one site to another site. They use Liferfay’s DLAppServiceUtil.moveFolder API but encounter an issue. They have a folder which contains two sub folders. The first sub-folder contain normal files and the second sub-folder contain a file without extension and title contains a special character. After perform the move action, move is failed and first sub-folder and its files are deleted. The steps and sample portlets can be found in LPS-60884 At first we discuss about the issue, it probably connect with transaction. After looking into the code DLAppServiceImpl.java#L3405-L3436 In moveFolders(), there’s a for loop for file, folder or shortcut. For folder, there’s another recursion (递归). They are ok, but when the file or shortcut throws exception, DLAppServiceImpl.java#L3145-L3149 The copyFileEntry() will throw PortalException to its parent method, moveFolders(). While moveFolders() catches the exception, it will run “toRepository.deleteFolder(newFolder.getFolderId());”, which will delete the folder and file that already copied. But what’s worse, moveFolders() will throw exception to its parent method, moveFolders(), it will lead loop deletion, until the whole folder is deleted. This is why causing losing data. So I add bejondshao:LPS-60884, to check folder before delete it. Then I find that there are two same files in different repositories, the files are the same location as bad file. Because it calls copyFileEntry() then delete whole folder. This is not good. Because if the folder contains large or thouands of files, copyFileEntry() will take too much disk space. So I use moveFileEntry() instead. By the way, moveFileEntry() + deleteFolder() doing the same logic with copyFileEntry() + deleteFolder(). ==================================== Since the issue can’t be reproduced in trunk and clean bundle, so we use cqu-folder-move-portlet-6.2.10.1 (working).war to reproduce it. Besides, we use cqu-folder-move-portlet-6.2.10.1 (fix).war to test the fix.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"Liferay","slug":"Java/Liferay","permalink":"http://bejondshao.github.io/categories/Java/Liferay/"}],"tags":[{"name":"Liferay","slug":"Liferay","permalink":"http://bejondshao.github.io/tags/Liferay/"}]},{"title":"Last Name became required in Liferay 7.0","slug":"Last-Name-became-required-in-Liferay-7-0","date":"2015-12-18T10:39:00.000Z","updated":"2023-03-02T03:26:34.173Z","comments":true,"path":"2015/12/18/Last-Name-became-required-in-Liferay-7-0/","link":"","permalink":"http://bejondshao.github.io/2015/12/18/Last-Name-became-required-in-Liferay-7-0/","excerpt":"","keywords":null,"text":"Last name is not required in Liferay 6.2.10, while becomes required in Liferay 7.0. How to make this field required? I search for /liferay-portal/modules/apps/directory/directory-web/src/main/resources/META-INF/resources/user/details.jsp There are email-address, birthday, job-title, etc. But there’s no prefix, first-name, middle-name, last-name, suffix. I can’t find last-name in any jsp file. So I guess it’s setting in Java code, then generate it as jsp. Then I do a search for “last-name”. I find it is in Language.properties file in property “lang.user.name.field.names=prefix,first-name,middle-name,last-name,suffix”. Do another search for “lang.user.name.field.names”. It locates in FullNameDefinitionFactory 1 String[] fieldNames = StringUtil.split(LanguageUtil.get(locale, “lang.user.name.field.names”)); so these fields are splitted into a String array.Then I find 1 fullNameField.setRequired(fullNameDefinition.isFieldRequired(userNameField)); What’s fullNameField? It’s an object of FullNameDefinition, the FullNameDefinition has _requiredFields. Then I set a breakpoint, _requeiredFields contains two values “first-name” and “last-name”. But where did portal set this attribute?Let’s do a full search for “FullNameDefinitionFactory”, /liferay-portal/portal-web/docroot/html/taglib/ui/user_name_fields/page.jsp We can see that user name values are generated here, each field would be added “required” if it’s required.But when and why last name became required? We see there’s an exception in the page.jsp The message says “and-last-name”. Let’s blame this line and find the log.This line and the whole block of code were added in LPS-55591 Combine jsp fragments in page.jsp. The whole block of code is added in this commit. Besides, details_user_name.jspf contains this line before, but it’s removed in this commit. So we should blame this file. (We need smartgit or gitk to do this.) This line of code was changed in LPS-55364. Now we can go to trunk and search for the LPS.After search for the log, the diff of the line is The message says “and-last-name”. Let’s blame this line and find the log.This line and the whole block of code were added in LPS-55591 Combine jsp fragments in page.jsp. The whole block of code is added in this commit. Besides, details_user_name.jspf contains this line before, but it’s removed in this commit. So we should blame this file. (We need smartgit or gitk to do this.) This line of code was changed in LPS-55364. Now we can go to trunk and search for the LPS.After search for the log, the diff of the line is It means last name is added before LPS-55364. Well, let go deep, go deep. Finally, we find this commit LPS-16453 Make last name optionalgit-svn-id: svn://svn.liferay.com/repos/public/portal/trunk@81911 05bdf26c-840f-0410-9ced-eb539d925f36 So we go to source code, search for users.last.name.required in portal.properties, see if we can find it. Of course, it’s gone. Don’t worry. We just need to log for portal.properties to see when this property is deleted. It’s LPS-54956 (Implement the correct handling of defining required fields). But during research, required is set in LPS-55364 (Create ContactNameException and add appropriate exceptions as inner classes).Finally, we can find in Language.properties lang.user.name.required.field.names=last-name If you want to set last name not required, you can remove this property and to go portal-impl/ run “ant build-lang”. Then do “ant deploy” to apply the change. so, last-name is required, in LPS-51819 (Add multi-cultural support to user admin portlet) But all in all, if we find this line at the first, we would not need to search the whole things. Org.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"Liferay","slug":"Java/Liferay","permalink":"http://bejondshao.github.io/categories/Java/Liferay/"}],"tags":[{"name":"Liferay","slug":"Liferay","permalink":"http://bejondshao.github.io/tags/Liferay/"}]},{"title":"Liferay - LDAP configuration","slug":"Liferay-LDAP-configuration","date":"2015-12-18T10:05:00.000Z","updated":"2023-03-02T03:26:34.173Z","comments":true,"path":"2015/12/18/Liferay-LDAP-configuration/","link":"","permalink":"http://bejondshao.github.io/2015/12/18/Liferay-LDAP-configuration/","excerpt":"","keywords":null,"text":"Concept http://www.jianshu.com/p/a41b41977f95 Install LDAP. Download http://directory.apache.org/apacheds/downloads.html Install. My test is http://directory.apache.org/apacheds/download/download-linux-deb.html 64bit After install, start apacheds with sudo or root # /etc/init.d/apacheds-2.0.0-M20-default start # /etc/init.d/apacheds-2.0.0-M20-default status then check if it starts. My first starting failed. It’s because /var/lib/apacheds-2.0.0-M20/default/conf/wrapper-instance.conf # Path to java executable # Override the JRE used # wrapper.java.command= uncomment wrapper.java.command, set it to your java executable file wrapper.java.command=/home/bejond/tools/java-tools/jdk1.7.0_40/jre/bin/java then try another start, status. My second starting failed again. I look the log INFO | jvm 1 | 2015/11/18 17:43:30 | [17:43:30] WARN [org.apache.directory.server.config.ConfigPartitionInitializer] - Conflict in selecting configuration source, both config.ldif and ou=config exist delete either one of them and restart the server so just delete all folders and *.ldif files inside /var/lib/apacheds-2.0.0-M20/default/conf/ but log4j.properties and wrapper-instance.conf. Then start apacheds successfully. 3) Add test data in Apacheds. I use ApacheDirectoryStudio to do this. Download https://directory.apache.org/studio/downloads.html After unzip it, it needs jre to run it. I copy my jre into ApacheDirectoryStudio, just the same folder of ApacheDirectoryStudio.ini. a) After ApacheDirectoryStudio starts, new connection, leave authentication blank. Then new Entry behind dc=example,dc=com. b) After creating ou, let’s import users. i) Right click “Root DSE” -> Import -> LDIF import… Check the things like this ii) Import the data that saved in a.ldif file 1234567891011121314151617dn: cn=test1,ou=Users,dc=example,dc=com cn: test1 givenName: test1givenName objectClass: person objectClass: inetOrgPerson objectClass: organizationalPerson objectClass: top sn: test1lastName userPassword:: e1NTSEF9dVplNG13WkV2ZVNVT3RrZlh0aW5iK0cyM0g0RjZib0EzNDNOVWc9PQ== You can see I didn’t add emain for users. If you don’t want to add email for users, please add the properties in portal-ext.properties 123users.email.address.required=false [email protected] Add LDAP server in Liferay. Start Liferay 6.2.10 sp13 Go to control panel -> Portal Settings -> Authentication -> LDAP, check “Enabled”, “Import Enabled”, then click “Add” to add LDAP Servers. In the Edit LDAP Server, just click “Reset Values”, liferay would set all values in defaut values. You need other changing to adapt to LDAP server. After that, click “Test LDAP Connection”, “Liferay has successfully connected to the LDAP server.” would show. If it saids failed, please check if LDAP server starts, if liferay server can connect to LDAP server, if the settings are correct. After settings, we can try to search users in LDAP. Click “Test LDAP Users”. The blue info says missing the required attribtes, just ignore it, because we’ve set properties in portal-ext.properties file. Save the LDAP server, Save portal settings. Import LDAP users Go to control panel -> Configuration -> Server Administration -> Script, select language “Javascript”. Type the code in Script and Execute. Packages.com.liferay.portal.security.ldap.PortalLDAPImporterUtil.importFromLDAP(); // This is for ee6.2 In trunk, the PortalLDAPImporterUtil has been removed, so we need to import user with other API. In trunk, there's a bug that script only supports Groovy now (2015-12-04). Please change the code to com.liferay.portal.security.exportimport.UserImporterUtil.importUsers() Then we can see that users are imported into Liferay!","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"Liferay","slug":"Java/Liferay","permalink":"http://bejondshao.github.io/categories/Java/Liferay/"}],"tags":[{"name":"Liferay","slug":"Liferay","permalink":"http://bejondshao.github.io/tags/Liferay/"},{"name":"LDAP","slug":"LDAP","permalink":"http://bejondshao.github.io/tags/LDAP/"}]},{"title":"what is LDAP","slug":"what-is-LDAP","date":"2015-11-19T01:24:33.000Z","updated":"2023-03-02T03:26:34.218Z","comments":true,"path":"2015/11/19/what-is-LDAP/","link":"","permalink":"http://bejondshao.github.io/2015/11/19/what-is-LDAP/","excerpt":"","keywords":null,"text":"LDAP是轻量目录访问协议(Lightweight Directory Access Protocol)的缩写,LDAP是从X.500目录访问协议的基础上发展过来的. 特点: LDAP的结构用树来表示,而不是用表格。正因为这样,就不能用SQL语句了 LDAP可以很快地得到查询结果,不过在写方面,就慢得多 LDAP提供了静态数据的快速查询方式 Client/server模型,Server 用于存储数据,Client提供操作目录信息树的工具 这些工具可以将数据库的内容以文本格式(LDAP 数据交换格式,LDIF)呈现在您的面前 LDAP是一种开放Internet标准,LDAP协议是跨平台的Interent协议 http://stackoverflow.com/questions/18756688/what-are-cn-ou-dc-in-an-ldap-search CN = Common Name OU = Organizational Unit DC = Domain Component You read it from right to left, the right-most component is the root of the tree, and the left most component is the node (or leaf) you want to reach. https://en.wikipedia.org/wiki/LDAP_Data_Interchange_Format dn distinguished name This refers to the name that uniquely identifies an entry in the directory. dc domain component This refers to each component of the domain. For example www.google.com would be written as DC=www,DC=google,DC=com ou organizational unit This refers to the organizational unit (or sometimes the user group) that the user is part of. If the user is part of more than one group, you may specify as such, e.g., OU= Lawyer,OU= Judge. cn common name This refers to the individual object (person’s name; meeting room; recipe name; job title; etc.) for whom/which you are querying. dn: cn=The Postmaster,dc=example,dc=com objectClass: organizationalRole cn: The Postmaster","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"LDAP","slug":"LDAP","permalink":"http://bejondshao.github.io/tags/LDAP/"}]},{"title":"mysql start error","slug":"mysql-start-error","date":"2015-11-02T06:41:00.000Z","updated":"2023-03-02T03:26:34.217Z","comments":true,"path":"2015/11/02/mysql-start-error/","link":"","permalink":"http://bejondshao.github.io/2015/11/02/mysql-start-error/","excerpt":"","keywords":null,"text":"mysql start error ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysql.sock’ (2) When I type mysql, it shows "ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysql.sock’ (2)". Then I try to start mysql service: $ service mysql start But then I get error " No directory, logging in with HOME=/ … MySQL Community Server 5.6.27 did not start. Please check logs for more details. " Then I try to find the log file. It’s located in /var/lib/mysql/bejond.err Then I look at the log file and locate " InnoDB: No valid checkpoint found. InnoDB: If this error appears when you are creating an InnoDB database, InnoDB: the problem may be that during an earlier attempt you managed InnoDB: to create the InnoDB data files, but log file creation failed. InnoDB: If that is the case, please refer to InnoDB: http://dev.mysql.com/doc/refman/5.6/en/error-creating-innodb.html " Then I go to the link, find the note, if the error happends on start mysql, delete all files created by InnoDB: all ibdata files and all ib_logfile files. So I delete /var/lib/mysql/ibdata1, ib_logfile0, ib_logfile1. Then restart the service. It works!","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[{"name":"Mysql","slug":"Mysql","permalink":"http://bejondshao.github.io/tags/Mysql/"},{"name":"Database","slug":"Database","permalink":"http://bejondshao.github.io/tags/Database/"}]},{"title":"How to check bad fix","slug":"How-to-check-bad-fix","date":"2015-07-16T07:23:00.000Z","updated":"2023-03-02T03:26:34.082Z","comments":true,"path":"2015/07/16/How-to-check-bad-fix/","link":"","permalink":"http://bejondshao.github.io/2015/07/16/How-to-check-bad-fix/","excerpt":"","keywords":null,"text":"最近做了一个backport的票,backport就是别人以前修复了这个bug,我只需要将fix移植到客户的系统中。这是一个没有技术含量的票,遇到简单的票,三下五除二就解决了。但是遇到目标版本与master差别大时,也许backport后不好用。结果这次就遇到了,并且引起UI问题。 我先是查看所有commit的修复,发现没有关于UI的修复。找了好久也没有找出原因。后来我想到部分backport,只backport主要修复,但是这也需要对修复很了解才能做到合理取舍,只得放弃。 于是我采用最笨的方法,以文件为单位,单个测试。因为是UI问题,单个功能JSP文件错误就可能导致问题,我便找到可能的文件,将其还原到被修改前的状态,全部复制到backport后的版本上。这就相当于backport,但是唯独不backport这个文件。发现UI问题不见了!那就确定是这个文件引起。然后再找出此次修复的所有关于这个文件的commit,找到diff,每次应用一个commit,当应用到某个commit时,问题出现了,说明此次commit的fix导致了这个问题,然后仔细分析此次修改,最后找到问题。 ======================================================================== Recently I did a ticket about backport. Backport is just copy others fix to fix customer’s issue. This kind of tickets has little tech. If it’s simple, nothing progress. But if it’s not simple, that’s disgusting. But this time, it’s the latter. And it’s an UI issue. At first, I tried to look through the commits and found there’s no fix about UI. And then I tried to part backport it. But this needs me know the fix well, so that I can part backport it. So I give this solution up. At last, I use a stupid way, but it does make sence. I focus on each file. Since this is an UI issue, it relates js, css, jsp files. I found the JSP files which might be the reason. I took out one jsp, and find the original status that didn’t apply any fix. And I copied all the content to the backported file, which means I backported all the fix, but only left this JSP as “unfixed”. The result is, the UI issue was gone! That was clear enough. Then I applied the commits of the file one by one, until I can reproduce the issue. Then I located the commit that made bad fix. Then I took care of this fix and found out the cause.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"Liferay","slug":"Java/Liferay","permalink":"http://bejondshao.github.io/categories/Java/Liferay/"}],"tags":[{"name":"Liferay","slug":"Liferay","permalink":"http://bejondshao.github.io/tags/Liferay/"},{"name":"Backport","slug":"Backport","permalink":"http://bejondshao.github.io/tags/Backport/"}]},{"title":"After install liferay sp9(LPE-10066), web contents don't show to guest","slug":"After-install-liferay-sp9-LPE-10066-web-contents-don-t-show-to-guest","date":"2015-04-23T08:15:00.000Z","updated":"2023-03-02T03:26:34.068Z","comments":true,"path":"2015/04/23/After-install-liferay-sp9-LPE-10066-web-contents-don-t-show-to-guest/","link":"","permalink":"http://bejondshao.github.io/2015/04/23/After-install-liferay-sp9-LPE-10066-web-contents-don-t-show-to-guest/","excerpt":"","keywords":null,"text":"Recently, some customers met an issue that after installing sp9 or any conponent that contains LPE-10066 ( LPS-40597), web contents won’t show to guest or site member. The reproduction steps: Setting “journal.article.view.permission.check.enabled=true” in portal-ext.properties. Start a clean 6210-sp7 bundle and drag a web content portlet to page, add one web content. Visit site with guest, the web content shows. Setting “journal.article.view.permission.check.enabled=true” in portal-ext.properties. Start another 6210-sp9 bundle, connecting with the same database. Visit site with guest, there’s no web content. The root cause is this commit https://github.com/shinnlok/liferay-portal/commit/896de0dc6a21b19ff1bcc9223677ffc6013a1274. For journal.xml file, they add view permission to guest and site member role. And remove view permission under tag. We can find the differences between the screenshots. But journal.xml file only works when init the first web content in a site. So this file won’t work in customer’s old site. That’s the reason. Besides, the permission check mechanism is changed. Before LPS-40597, portal would check if guest (or site member) Doesn’t have view permission, if he doesn’t have, he won’t see web content; if undefined, he will see web content. After LPS-40597, portal would check if guest (or site member) Do have view permission, if he do have, he will see web content; if undefined, he won’t see web content. In sp7, there’s no view setting under “Resource Permissions”. In sp9, there’s view permission setting under “Resource Permissions”. We can see the view permission is unchecked. So with new permission checking mechanism, guest or site member doesn’t have view resource permission, so he can’t view web contents, even though we set each web content is viewable by guest, there’s no use. The solution is setting this view permission to guest and site member. The issue we talk about only happens in the site created before sp9, new site create after installing sp9 will work fine, because journal.xml file works later. I think this can make the issue clear.","raw":null,"content":null,"categories":[{"name":"Java","slug":"Java","permalink":"http://bejondshao.github.io/categories/Java/"},{"name":"Liferay","slug":"Java/Liferay","permalink":"http://bejondshao.github.io/categories/Java/Liferay/"}],"tags":[{"name":"Liferay","slug":"Liferay","permalink":"http://bejondshao.github.io/tags/Liferay/"}]},{"title":"Hello World","slug":"hello-world","date":"2015-04-10T01:05:15.000Z","updated":"2023-03-02T03:26:34.215Z","comments":true,"path":"2015/04/10/hello-world/","link":"","permalink":"http://bejondshao.github.io/2015/04/10/hello-world/","excerpt":"","keywords":null,"text":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick Start Create a new post 1$ hexo new "My New Post" More info: Writing Run server 1$ hexo server More info: Server Generate static files 1$ hexo generate More info: Generating Deploy to remote sites 1$ hexo deploy More info: Deployment","raw":null,"content":null,"categories":[{"name":"Others","slug":"Others","permalink":"http://bejondshao.github.io/categories/Others/"}],"tags":[]}]}