-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
153 lines (153 loc) · 51.2 KB
/
search.xml
File metadata and controls
153 lines (153 loc) · 51.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[SpringStatemachine学习笔记2——使用Papyrus构建简单的状态机]]></title>
<url>%2F2018%2F05%2F07%2FSpringStatemachine%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B02%E2%80%94%E2%80%94%E4%BD%BF%E7%94%A8Papyrus%E6%9E%84%E5%BB%BA%E7%AE%80%E5%8D%95%E7%9A%84%E7%8A%B6%E6%80%81%E6%9C%BA%2F</url>
<content type="text"><![CDATA[本篇介绍:使用SpringStatemachine和eclipse Papyrus搭建一个简单的状态机。开发工具:IntelliJ IDEA、eclipse Oxygen 1. 安装Papyrus插件下载eclipse,这里用的是Oxygen版本,依次选择Help->Install New Software…,点击插件地址栏后面的Manage按钮,添加以下地址:http://download.eclipse.org/modeling/mdt/papyrus/updates/releases/oxygen。安装搜索出来的Papyrus插件,这里面可以直接全选。 2. 创建Papyrus工程新建一个Papyrus工程,选择UML类型,这里新建一个名为order-state-diagram的工程。 初始化信息中选择State Machine Diagram。 3. 构建状态机图添加状态机的初始状态和定义两个状态State1和State2,连接三个状态。 新建Signal和SignalEvent,分别命名为E1和SignalEvent1,SignalEvent1的Signal中选择刚创建的E1。 在E1和E2的连接中添加触发器,触发器事件选择刚才创建的SignalEvent1。 4. 在工程中使用UML状态机图新建spring-statemachine-uml-demo工程,添加spring-statemachine-uml依赖。 123456789101112<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-uml</artifactId> <version>${spring-statemachine.version}</version> </dependency></dependencies> 把刚才创建的order-state-diagram.uml复制到resources中,定义StateMachineConfig类,根据uml状态图构建状态机。 1234567891011121314151617181920212223@Configuration@EnableStateMachinepublic class StateMachineConfig extends StateMachineConfigurerAdapter<String, String> { @Override public void configure(StateMachineModelConfigurer<String, String> model) throws Exception { model.withModel().factory(modelFactory()); } @Bean StateMachineModelFactory<String, String> modelFactory() { UmlStateMachineModelFactory factory = new UmlStateMachineModelFactory( "classpath:com/hyfblog/springstatemachineumldemo/order-state-diagram.uml"); factory.setStateMachineComponentResolver(stateMachineComponentResolver()); return factory; } @Bean public StateMachineComponentResolver<String, String> stateMachineComponentResolver() { return new DefaultStateMachineComponentResolver<>(); }} 在SpringStatemachineUmlDemoApplication注入StateMachine,通过在StateMachine中添加listener。 123456789101112131415161718192021222324252627282930@SpringBootApplicationpublic class SpringStatemachineUmlDemoApplication implements CommandLineRunner { private static final Logger logger = LoggerFactory.getLogger(SpringStatemachineUmlDemoApplication.class); @Autowired StateMachine<String, String> stateMachine; public static void main(String[] args) { SpringApplication.run(SpringStatemachineUmlDemoApplication.class, args); } @Override public void run(String... args) throws Exception { stateMachine.addStateListener(listeners()); stateMachine.start(); stateMachine.sendEvent("E1"); } @Bean StateMachineListener<String, String> listeners() { return new StateMachineListenerAdapter<String, String>() { @Override public void transition(Transition<String, String> transition) { logger.info(String.format("source:%s target:%s", String.valueOf(transition.getSource()), String.valueOf(transition.getTarget()))); } }; }} 启动SpringStatemachineUmlDemoApplication,在日志中就可以看到状态机事件转换日志打印了。 12342018-05-16 22:17:12.381 INFO 2172 --- [ main] h.s.SpringStatemachineUmlDemoApplication : source:null target:ObjectState [getIds()=[State1], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=1450712470, toString()=AbstractState [id=State1, pseudoState=org.springframework.statemachine.state.DefaultPseudoState@5173200b, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]]2018-05-16 22:17:12.384 INFO 2172 --- [ main] o.s.s.support.LifecycleObjectSupport : started org.springframework.statemachine.support.DefaultStateMachineExecutor@726a6b942018-05-16 22:17:12.384 INFO 2172 --- [ main] o.s.s.support.LifecycleObjectSupport : started State2 State1 / State1 / uuid=a2e65e59-ff73-4d27-b23e-074a64d8d61d / id=null2018-05-16 22:17:12.388 INFO 2172 --- [ main] h.s.SpringStatemachineUmlDemoApplication : source:ObjectState [getIds()=[State1], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=1450712470, toString()=AbstractState [id=State1, pseudoState=org.springframework.statemachine.state.DefaultPseudoState@5173200b, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]] target:ObjectState [getIds()=[State2], getClass()=class org.springframework.statemachine.state.ObjectState, hashCode()=1402333753, toString()=AbstractState [id=State2, pseudoState=null, deferred=[], entryActions=[], exitActions=[], stateActions=[], regions=[], submachine=null]] 5. 遗留问题 eclipse的Papyrus插件我也是刚开始学习,不怎么会用,具体的一些组件还需要细化理解。 业务逻辑代码耦合在Main方法中,不太优雅。 6. 更新日志2018-05-16 首次成文]]></content>
<categories>
<category>Java开发</category>
</categories>
<tags>
<tag>Spring Statemachine</tag>
</tags>
</entry>
<entry>
<title><![CDATA[SpringStatemachine学习笔记1——搭建一个简单的状态机]]></title>
<url>%2F2018%2F03%2F15%2FSpringStatemachine%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01%E2%80%94%E2%80%94%E6%90%AD%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E7%8A%B6%E6%80%81%E6%9C%BA%2F</url>
<content type="text"><![CDATA[本篇介绍:使用SpringStatemachine搭建一个简单的状态机。开发工具:IntelliJ IDEA 1. 状态流转图本篇尝试用SpringStatemachine来搭建一个简单的订单流程状态机。状态机有两个比较重要的概念,分别是状态和事件。这里,订单状态分为待支付、待发货、待收货、已签收、已关闭,事件包括支付、发货、签收、取消。状态图如下: 123456789101112131415161718## 2. 实现代码新建一个SpringBoot工程,在pom文件中引入SpringStatemachine相关的依赖。```xml<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.statemachine</groupId> <artifactId>spring-statemachine-core</artifactId> <version>${spring-statemachine.version}</version> </dependency></dependencies> 定义订单流的状态,新建OrderStates枚举类。 123456789101112131415161718192021222324252627public enum OrderStates { /** * 待支付 */ WAIT_PAY, /** * 待发货 */ WAIT_DELIVERY, /** * 待收货 */ WAIT_RECEIVE, /** * 已签收 */ SIGNED, /** * 已关闭 */ CLOSED} 定义订单事件,新建OrderEvents枚举类。 1234567891011121314151617181920212223public enum OrderEvents { /** * 支付 */ PAY, /** * 发货 */ DELIVERY, /** * 签收 */ SIGN, /** * 取消 */ CANCEL} 定义好上面两个东西后,就可以定义状态机模型了,新建OrderStateMachineConfig类,继承EnumStateMachineConfigurerAdapter类。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253@Configuration@EnableStateMachinepublic class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderStates, OrderEvents> { private static final Logger logger = LoggerFactory.getLogger(OrderStateMachineConfig.class); @Override public void configure(StateMachineStateConfigurer<OrderStates, OrderEvents> states) throws Exception { // 指定订单初始状态为待支付 states.withStates().initial(OrderStates.WAIT_PAY).states(EnumSet.allOf(OrderStates.class)); } @Override public void configure(StateMachineTransitionConfigurer<OrderStates, OrderEvents> transitions) throws Exception { // 指定订单流转状态和事件 transitions .withExternal().source(OrderStates.WAIT_PAY).target(OrderStates.WAIT_DELIVERY).event(OrderEvents.PAY) .and() .withExternal().source(OrderStates.WAIT_DELIVERY).target(OrderStates.WAIT_RECEIVE).event(OrderEvents.DELIVERY) .and() .withExternal().source(OrderStates.WAIT_RECEIVE).target(OrderStates.SIGNED).event(OrderEvents.SIGN) .and() .withExternal().source(OrderStates.WAIT_PAY).target(OrderStates.CLOSED).event(OrderEvents.CANCEL); } @Override public void configure(StateMachineConfigurationConfigurer<OrderStates, OrderEvents> config) throws Exception { config.withConfiguration().listener(createOrderListeners()); } @Bean StateMachineListener<OrderStates, OrderEvents> createOrderListeners() { // 模拟订单业务逻辑 return new StateMachineListenerAdapter<OrderStates, OrderEvents>() { @Override public void transition(Transition transition) { if (transition.getSource() == null && transition.getTarget().getId() == OrderStates.WAIT_PAY) { logger.info("创建订单,待支付"); } else if (transition.getSource().getId() == OrderStates.WAIT_PAY && transition.getTarget().getId() == OrderStates.WAIT_DELIVERY) { logger.info("订单已支付"); } else if (transition.getSource().getId() == OrderStates.WAIT_PAY && transition.getTarget().getId() == OrderStates.CLOSED) { logger.info("订单已取消"); } else if (transition.getTarget().getId() == OrderStates.WAIT_RECEIVE) { logger.info("订单已发货"); } else if (transition.getTarget().getId() == OrderStates.SIGNED) { logger.info("订单已签收"); } } }; }} 在启动类中添加以下代码,模拟订单状态转换事件发生。 12345678910111213141516171819@SpringBootApplicationpublic class SpringStatemachineDemoApplication implements CommandLineRunner { @Autowired StateMachine<OrderStates, OrderEvents> stateMachine; public static void main(String[] args) { SpringApplication.run(SpringStatemachineDemoApplication.class, args); } @Override public void run(String... args) { stateMachine.start(); stateMachine.sendEvent(OrderEvents.PAY); stateMachine.sendEvent(OrderEvents.DELIVERY); stateMachine.sendEvent(OrderEvents.SIGN); } } 启动SpringStatemachineDemoApplication,查看控制台打印的日志,可以看到每发送一个事件,状态机都会进入我们在OrderStateMachineConfig定义的处理逻辑中。 3. 待处理问题OrderStateMachineConfig中的业务逻辑代码混在一起,不够优雅。 4. 更新日志2018-05-07 首次成文```flow st=>start: 开始 e=>end: 结束 wait_pay=>condition: 支付成功 wait_delivery=>inputoutput: 待发货 wait_receive=>inputoutput: 待收货 signed=>inputoutput: 已签收 closed=>inputoutput: 已关闭 pay=>operation: 支付 delivery=>operation: 发货 sign=>operation: 签收 cancel=>operation: 取消订单 st->wait_pay wait_pay(yes)->pay->wait_delivery wait_pay(no)->cancel->closed wait_delivery->delivery->wait_receive wait_receive->sign->signed {"scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12} var code = document.getElementById("flowchart-0-code").value; var options = JSON.parse(decodeURIComponent(document.getElementById("flowchart-0-options").value)); var diagram = flowchart.parse(code); diagram.drawSVG("flowchart-0", options);]]></content>
<categories>
<category>Java开发</category>
</categories>
<tags>
<tag>Spring Statemachine</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Jenkins实现WebLogic自动化部署]]></title>
<url>%2F2018%2F02%2F11%2FJenkins%E5%AE%9E%E7%8E%B0WebLogic%E8%87%AA%E5%8A%A8%E5%8C%96%E9%83%A8%E7%BD%B2%2F</url>
<content type="text"><![CDATA[本篇介绍:使用Jenkins实现WebLogic的自动化部署。 现在公司是使用WebLogic做应用服务器,每次打包发布都要好几分钟,实在是不方便,只好尝试着用Jenkins做个自动化部署方案。 1. 安装Jenkins必要插件打开Jenkins的插件配置中心,安装Publish Over SSH插件和Subversion Plug-in。 安装Publish Over SSH插件后需要配置一下服务器地址,之后的构建中才能选择。在Jenkins全局配置中,找到Publish over SSH,这里可以增加服务器配置。可以选择SSH key,或者勾选下面这个选项,每个服务器自己输入用户名和密码,最后点一下Test Configuration,确认可以正常连接上服务器。 2. 配置Jenkins构建2.1 新建maven构建任务在Jenkins新建一个任务,输入任务名称,选择构建一个maven项目。 2.2 配置svn源码管理在源码管理的tab中选择Subversion,输入svn地址和用户名密码,如果Subversion可以选择的话,确认Subversion Plug-in插件是否安装成功。用Git的话也类似,安装Git插件,填入相关的Git代码库信息。 2.3 配置BuildRoot POM中选择代码项目中的父pom就行,Goals and options中可以输入对应的maven命令,例如clean package -Dmaven.test.skip=true这样,不填的话默认是install。 2.4 配载构建后操作构建后操作中点构建后操作步骤,选择Send build artifacts over SSH,name选择上面配置的服务器。 Sources files选择需要部署的war包路径,根据目录是maven构建后的target目录。 Remove prefix是上传到服务器中需要去掉的前缀路径,例如这里war包路径是demo-web\target\demo.war,Remove prefix就要是demo-web\target\,否则上传到服务器后,war包的路径也会是demo-web\target\demo.war这样。 Remote directory是指artifacts上传到服务器后的根目录,它的上层目录是我们之前配置服务器时配置根目录。 Exec command就是上传完artifacts后需要执行的服务器脚本了,一般这里就是部署重启的脚本。 3. 编写WebLogic重启脚本查了下WebLogic的官方文档,使用weblogic.Deployer部署主要有以下几个命令:start、stop、undeploy、deploy、update。使用weblogic.Deployer的话,必须要把weblogic的lib目录加到系统的PATH环境变量中,否则就要像下面这样每次都export一下,每个命令也要指定一下weblogic目录lib文件夹的位置,否则会报找不到类错误的问题。 因为公司部署WebLogic是每次都删除部署包然后重新部署的,所以这里的脚本就按这种方式来处理了,直接update部署也可以,换个命令就行了,参考脚本如下。 123456789101112131415161718192021222324252627282930313233343536#!/bin/bashcd /u01/wls/demo#设置weblogic命令行环境变量export wlslib=/u01/wls/middleware/wlserver/server/lib#查找正在运行的war包名称running_war_name=`ls -t *UAT.war | head -1`running_service_name=${running_war_name%%.*}echo "running war ${running_war_name}"#重命名demo.wardate_str=$(date +%Y%m%d%H%M%S)echo "rename demo.war to $demo_{date_str}_UAT.war "mv demo.war demo_${date_str}_UAT.war#查找需要部署的war包名称newest_war_name=`ls -t *.war | head -1`echo "deploy war ${newest_war_name}"newest_service_name=${newest_war_name%%.*}#停止当前服务echo "stop domain service ${running_service_name}"/u01/wls/jdk1.8.0_131/bin/java -cp $wlslib/weblogic.jar:$wlslib/wlepool.jar:$wlslib/wleorb.jar weblogic.Deployer -adminurl http://127.0.0.1:7001 -user weblogic -password admin -name ${running_service_name} -stop #删除当前部署echo "undeploy war ${running_war_name}"/u01/wls/jdk1.8.0_131/bin/java -cp $wlslib/weblogic.jar:$wlslib/wlepool.jar:$wlslib/wleorb.jar weblogic.Deployer -adminurl http://127.0.0.1:7001 -user weblogic -password admin -name ${running_service_name} -undeploy#安装新war包echo "deploy war ${newest_war_name}"/u01/wls/jdk1.8.0_131/bin/java -cp $wlslib/weblogic.jar:$wlslib/wlepool.jar:$wlslib/wleorb.jar weblogic.Deployer -adminurl http://127.0.0.1:7001 -user weblogic -password admin -deploy -name ${newest_service_name} -source /u01/wls/demo/${newest_war_name} -targets server0#重启服务echo "start service ${newest_service_name}"/u01/wls/jdk1.8.0_131/bin/java -cp $wlslib/weblogic.jar:$wlslib/wlepool.jar:$wlslib/wleorb.jar weblogic.Deployer -adminurl http://127.0.0.1:7001 -user weblogic -password admin -name ${newest_service_name} -start 4. 常见问题使用weblogic.Deployer命令的过程中,可能会报If using http protocol, tunneling must be enabled的错误,错误信息如下。 1Unable to connect to 'http://127.0.0.1:7001': No available router to destination.. Ensure the url represents a compatible running admin server and that the credentials are correct. If using http protocol, tunneling must be enabled on the admin server. 解决办法按提示所说,进入WebLogic控制台,依次选择环境->服务器->管理服务器,协议tab里面的HTTP,里面有个启用隧道的单选框,勾上就行了。 5. 更新日志2018-02-11 首次成文]]></content>
<categories>
<category>运维</category>
</categories>
<tags>
<tag>Jenkins</tag>
<tag>WebLogic</tag>
<tag>自动化部署</tag>
</tags>
</entry>
<entry>
<title><![CDATA[大型分布式网站架构设计与实践——读书笔记1]]></title>
<url>%2F2018%2F01%2F23%2F%E5%A4%A7%E5%9E%8B%E5%88%86%E5%B8%83%E5%BC%8F%E7%BD%91%E7%AB%99%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%AE%9E%E8%B7%B5%E2%80%94%E2%80%94%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B01%2F</url>
<content type="text"><![CDATA[本篇介绍:《大型分布式网站架构设计与实践》读书笔记1。 1. 思维导图1.1 分布式架构基础设施 1.2 互联网安全架构 2.相关附件下载百度网盘暂时上传不了,以后补充(⊙﹏⊙)b 3.更新日志2018-01-23 首次成文]]></content>
<categories>
<category>Java开发</category>
</categories>
<tags>
<tag>读书笔记</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Python使用cx_Oracle连接数据库]]></title>
<url>%2F2017%2F12%2F22%2FPython%E4%BD%BF%E7%94%A8cx-Oracle%E8%BF%9E%E6%8E%A5%E6%95%B0%E6%8D%AE%E5%BA%93%2F</url>
<content type="text"><![CDATA[本篇介绍:如何Python使用cx_Oracle连接Oracle数据库。开发工具:Python2.7+或Python3.4+ 1. 安装cx_Oracle使用pip安装cx_Oracle库,打开命令行,输入以下命令。 1python -m pip install cx_Oracle --upgrade 但是,cx_Oracle不像java的jdbc驱动一样,直接引入就可以使用了,还需要安装oracle客户端。 2. 安装Oracle客户端2.1 下载安装到oracle官网下载客户端,下载basic版本就可以了。oracle官网要注册才能下载,嫌麻烦的windows64位用户可以直接到这上面下载。百度网盘链接:https://pan.baidu.com/s/1eSlgFrc,密码:wpnz。 下载完成后解压到安装目录,如D:\instantclient_12_2_x64,在network\admin下面创建tnsnames.ora,文件我是直接从PLSQL拷过来的,我也没试过不创建能不能正常连接(⊙﹏⊙)。 2.2 配置环境变量因为cx_Oracle要通过环境变量来找到oracle客户端的,所以还要配置环境变量。windows用户打开环境变量,在系统变量的Path后面添加oracle客户端的路径,如这里是添加D:\instantclient_12_2_x64。 3. Oracle连接测试在PyCharm中新建脚本测试数据库是否能连通。 12345678910111213141516#!/usr/bin/env python# -*- coding: utf-8 -*-import cx_Oracleif __name__ == '__main__': connection = cx_Oracle.connect('test', 'test', '127.0.0.1:1521/test') print(connection.version) cursor = connection.cursor() cursor.execute(""" SELECT user_code, user_name FROM sys_user WHERE user_code = :userCode """, userCode='ADMIN') for user_code, user_name in cursor: print("rows:", user_code, user_name) 执行上面的脚本,控制台正常打印出oracle版本和查询情况,连接成功。 12345"C:\Program Files\Python36\python.exe" E:/PycharmProjects/PythonDemo/OracleDemo/link_oracle_demo.py11.2.0.3.0rows: ADMIN ADMINProcess finished with exit code 0 4. 兼容PL/SQL的情况系统在安装有PL/SQL的情况下,因为PL/SQL是不能用64位版本的oracle客户端的,所以要另外下载32位版的oracle客户端,在PL/SQL配置中指定使用32位版客户端的oci.dll。 5. 更新日志2017-12-29 首次成文]]></content>
<categories>
<category>Python</category>
</categories>
<tags>
<tag>Python</tag>
<tag>数据库</tag>
</tags>
</entry>
<entry>
<title><![CDATA[MongoDB-3.6安装问题]]></title>
<url>%2F2017%2F12%2F19%2FMongoDB-3-6%E5%AE%89%E8%A3%85%E9%97%AE%E9%A2%98%2F</url>
<content type="text"><![CDATA[本篇介绍:MongoDB-3.6安装过程中遇到的问题开发工具:MongoDB-3.6 1. 安装完成后无法访问今天给一台服务器重新安装MongoDB,从官网下载最新的3.6版本下载安装后,发现无法访问,本地telnet端口27017不通,但是通过查看服务器端口情况,发现MongoDB服务是正常启动的,端口也是用的27017,通过本地的Mongo客户端可以正常访问服务。一开始以为是服务器防火墙的问题,把27017端口添加到防火墙开放端口后依然不行,一直以为问题是在防火墙上,折腾了好久才想到,是不是新版的MongoDB做了访问限制。最后发现,3.6版本的MongoDB默认开启了访问白名单限制bind_ip=localhost(/(ㄒoㄒ)/~~估计是跟前段时间爆出的MongoDB漏洞有关)。解决办法有两种,要不就把访问限制全部放开,要不就把访问客户端IP添加到白名单中。 2. 放开全部访问限制放开全部限制适合测试环境中使用,这样方便开发人员测试访问,只需要在启动命令参数中添加–bind_ip_all即可。 1mongod -f /usr/local/mongodb/mongodb.conf --bind_ip_all 或者直接在mongodb.conf的配置文件中加入下面的配置命令。 1bind_ip_all = true 3. 指定访问白名单生产环境中建议还是开启MongoDB的白名单访问限制功能。在启动命令参数中添加bind_ip参数。 1mongod -f /usr/local/mongodb/mongodb.conf --bind_ip 127.0.0.1,192.168.1.xxx 另外一种方法,也是直接添加到配置文件中。 1bind_ip = 127.0.0.1,192.168.1.xxx ╰(°▽°)╯折腾了半天,终于搞完了。。]]></content>
<categories>
<category>MongoDB</category>
</categories>
<tags>
<tag>MongoDB</tag>
</tags>
</entry>
<entry>
<title><![CDATA[SpringCloud学习笔记4——Zuul服务网关]]></title>
<url>%2F2017%2F06%2F28%2FSpringCloud%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B04%E2%80%94%E2%80%94Zuul%E6%9C%8D%E5%8A%A1%E7%BD%91%E5%85%B3%2F</url>
<content type="text"><![CDATA[本篇介绍:如何使用Zuul作为微服务的服务网关。开发工具:IntelliJ IDEA 1. 搭建Zuul服务1.1 新建Zuul服务端项目新建一个module,选择Spring Initializr,输入项目名称,这里我命令为zuul-demo。选择需要添加的SpringBoot依赖,这里选择Zuul。新建项目后,打开pom.xml文件,确认是否添加以下依赖,没有添加的话需要添加一下。123456789<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId></dependency><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId></dependency> 1.2 配置zuul网关服务打开application.properties,添加以下内容,指定服务名称和端口,这个与之前的微服务项目一样。除此之外,还需要指定url的映射方式和地址,这里有两种映射方式可供选择,一种是通过url直接映射,一种是通过微服务的serviceId映射,推荐使用第二种方式。1234567891011spring.application.name=api-gatewayserver.port=5555#通过url直接映射,不推荐使用此方式,因为需要维护所有微服务的服务提供地址zuul.routes.api-a-url.path=/api-a-url/**zuul.routes.api-a-url.url=http://localhost:2222/#通过serviceId映射,推荐使用此方式zuul.routes.api-a.path=/api-a/**zuul.routes.api-a.serviceId=hello-serviceeureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/ 1.3 启动服务分别启动eureka-server-demo,eureka-service-demo和zuul-demo项目,访问http://localhost:5555/api-a-url/sayHello?name=Kroos或http://localhost:5555/api-a/sayHello?name=Kroos,可以看到已经可以通过zuul正常访问微服务了。 2. 服务过滤外网通过服务网关访问微服务,在zuul网关上实现访问权限控制等通用功能,可以避免在每个微服务上各自实现这些功能。在zuul上定义过滤器,需要继承ZuulFilter抽象类,实现相关的方法,具体的示例代码如下。123456789101112131415161718192021222324252627282930313233343536public class AccessFilter extends ZuulFilter { private static final Logger logger = LoggerFactory.getLogger(AccessFilter.class); @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); logger.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString())); Object accessToken = request.getParameter("accessToken"); if (accessToken == null) { logger.warn("access token is empty"); ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); return null; } logger.info("access token ok"); return null; }} 上面代码中的四个实现方法的作用如下: filterType:可以返回四种类型的值,定义过滤器在请求的什么时候执行。 pre:在请求被路由之前调用 routing:在请求被路由时调用 post:在routing和error过滤器之后被调用 error:请求发生错误时被调用 filterOrder:定义过滤的执行顺序,值越小优先级越高。 shouldFilter:根据返回值决定过滤器是否需要执行。 run:过滤器的具体实现逻辑。这里调用ctx.setSendZuulResponse(false)方法指定对请求不进行路由,也可以调用ctx.setResponseBody()来指定请求的返回内容。 定义好过滤器之后,还需要在启动类中注入过滤器的实例。1234567891011121314@EnableZuulProxy@SpringCloudApplicationpublic class ZuulDemoApplication { public static void main(String[] args) { SpringApplication.run(ZuulDemoApplication.class, args); } @Bean public AccessFilter accessFilter() { return new AccessFilter(); } } 再次启动服务,这时访问http://localhost:5555/api-a/sayHello?name=Kroos,会发现后台返回了401错误,需要带上token参数才可以访问成功了。]]></content>
<categories>
<category>Java开发</category>
</categories>
<tags>
<tag>SpringCloud</tag>
</tags>
</entry>
<entry>
<title><![CDATA[SpringCloud学习笔记3——服务配置中心]]></title>
<url>%2F2017%2F06%2F16%2FSpringCloud%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B03%E2%80%94%E2%80%94%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%2F</url>
<content type="text"><![CDATA[本篇介绍:如何基于SpringCloud搭建服务配置中心。开发工具:IntelliJ IDEA 1. 搭建配置中心服务1.1 新建项目新建项目config-server-demo,依赖选择Config Server。pom文件添加的依赖如下:123456789101112<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency></dependencies> 1.2 添加@EnableConfigServer注解在启动类ConfigServerDemoApplication中添加@EnableConfigServer注解。12345678@EnableConfigServer@SpringBootApplicationpublic class ConfigServerDemoApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerDemoApplication.class, args); }} 1.3 指定配置路径修改application.properties,指定配置文件检索目录。Spring Cloud Config支持从Git,本地文件,项目目录等多种途径获取配置文件信息,这里暂时以项目目录为例。12345spring.application.name=config-serverserver.port=7001#指定ConfigServer从src/main/resource目录下检索文件spring.profiles.active=native 然后在config-server-demo的src/main/resource目录下新建文件jdbc-dev.properties和jdbc-test.properties。 1.4 测试访问URL启动服务后,我们就可以通过以下的URL来测试是否可以获取配置成功了。 /{application}/{profile}[/{label}] /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties上面的URL会映射到文件{application}-{profile}.properties,例如application对应配置文件中的jdbc,profile对应dev和test,label是Git中不同的分支,默认为master。这时,例如我们访问http://localhost:7001/jdbc/dev,就可以查看到jdbc-dev.properties文件中的配置信息了。 2. 配置客户端2.1 添加依赖在client-demo项目的pom文件中添加以下依赖。12345<!--Spring Cloud Config依赖--><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId></dependency> 2.2 添加配置文件在src/main/resources目录下新建配置文件bootstrap.properties,添加以下内容。123spring.cloud.config.name=jdbcspring.cloud.config.profile=devspring.cloud.config.uri=http://localhost:7001/ spring.cloud.config.name对应上面配置中心配置文件的{application},spring.cloud.config.profile根据不同的环境不一样,也需要与配置中心的{profile}对应起来。spring.cloud.config.uri就是配置中心的访问地址了。 2.3 在类中注入配置值新建ConfigController类,注入从配置中心获取的值。1234567891011121314@RestController@RequestMapping(value = "/config")@RefreshScopepublic class ConfigController { @Value("${jdbcUrl}") private String jdbcUrl; @RequestMapping(value = "/getJdbcUrl", method = RequestMethod.GET) public String getJdbcUrl() { return this.jdbcUrl; }} 启动项目后,访问http://localhost:3333/config/getJdbcUrl,就可以看到,client-demo已经可以从配置中心获取配置值了。 3. 遗留问题 使用Git存放配置文件 配置文件分多层级存储 更新配置后,对应的配置值要实时刷新 如果配置是jdbc连接池配置,更新配置后是否有办法实时更新数据库连接池的URL 4. 更新日志2017-06-16 首次成文]]></content>
<categories>
<category>Java开发</category>
</categories>
<tags>
<tag>SpringCloud</tag>
</tags>
</entry>
<entry>
<title><![CDATA[SpringCloud学习笔记2——hystrix熔断器的使用]]></title>
<url>%2F2017%2F06%2F13%2FSpringCloud%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B02%E2%80%94%E2%80%94hystrix%E7%86%94%E6%96%AD%E5%99%A8%E7%9A%84%E4%BD%BF%E7%94%A8%2F</url>
<content type="text"><![CDATA[本篇介绍:在SpringCloud中使用hystrix熔断器。开发工具:IntelliJ IDEA 1. hystrix介绍关于hystrix的详细介绍,可以访问GitHub上Hystrix的项目,这里不再细说了。 2. 添加hystrix依赖在client-demo的pom.xml文件中添加以下依赖。12345<!--hystrix依赖--><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId></dependency> 3. 增加hystrix回调方法新增ConsumerService接口。12345public interface ConsumerService { String testSayHello(String name);} 新增ConsumerServiceImpl实现类。12345678910111213141516171819@Servicepublic class ConsumerServiceImpl implements ConsumerService { @Autowired private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "helloServiceFallback") public String testSayHello(String name) { return restTemplate.getForEntity("http://hello-service/sayHello?name=" + name, String.class).getBody(); } /** * hystrix回调方法,要注意回调方法的签名要跟@HystrixCommand注释的方法一致 */ public String helloServiceFallback(String name) { return "hello-service服务暂时不可用"; }} 修改原来的ConsumerController类,把调用方法移动到上面的ConsumerServiceImpl类中。123456789101112@RestControllerpublic class ConsumerController { @Autowired private ConsumerService consumerService; @RequestMapping(value = "/testSayHello", method = RequestMethod.GET) public String testSayHello(@RequestParam String name) { return consumerService.testSayHello(name); }} 最后,给启动类ClientDemoApplication添加注解@EnableCircuitBreaker。 4. 测试启动eureka-server-demo工程和client-demo工程,访问http://localhost:3333/testSayHello?name=Romas,可以看到页面已经返回helloServiceFallback的提示信息。 5. 更新日志2017-06-13 首次成文]]></content>
<categories>
<category>Java开发</category>
</categories>
<tags>
<tag>SpringCloud</tag>
<tag>SpringBoot</tag>
<tag>hystrix</tag>
</tags>
</entry>
<entry>
<title><![CDATA[SpringCloud学习笔记1——eureka服务注册与发现]]></title>
<url>%2F2017%2F06%2F13%2FSpringCloud%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B01%E2%80%94%E2%80%94eureka%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%8E%E5%8F%91%E7%8E%B0%2F</url>
<content type="text"><![CDATA[本篇介绍:如何基于SpringCloud搭建可调用的微服务。开发工具:IntelliJ IDEA 1. 搭建eureka服务端1.1 新建eureka服务端项目新建一个module,选择Spring Initializr,输入项目名称,这里我命令为eureka-server-demo。选择需要添加的SpringBoot依赖,这里选择Eureka Server。点击完成生成工程,生成项目后可以查看pom.xml文件,可以看到IntelliJ IDEA已经帮我们自动添加好了相关的依赖。123456789101112131415161718192021222324<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency></dependencies><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement> 1.2 修改server工程配置打开application.properties文件,添加以下内容。12345678#eureka服务端端口server.port=1111#eureka服务端本身就是服务注册中心,所以此工程要设置成不在服务注册中心注册eureka.client.register-with-eureka=falseeureka.client.fetch-registry=falseeureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/ 1.3 启动server执行EurekaServerDemoApplication类启动服务器,启动成功看,打开http://localhost:1111/,看到以下界面,就代表启动成功了。 2. 搭建eureka服务提供端2.1 新建eureka服务提供端项目跟新建server端一样新建一个module,这里命令为eureka-service-demo,选择依赖的时候选择Eureka Discovery。查看pom.xml的依赖是否添加正确。123456789101112131415161718192021222324<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency></dependencies><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement> 2.2 实现服务逻辑这里的服务逻辑简单地接收一个name作为入参,返回Hello+name的字符串。首先,新建一个SayHelloController类,实现方法基本上跟常用的SpringMVC一致,这里注入的DiscoveryClient和Registration是为了之后在分布式环境下可以更好地观察客户端调用情况而使用的。123456789101112131415161718192021222324@RestControllerpublic class SayHelloController { private static final Logger logger = LoggerFactory.getLogger(SayHelloController.class); @Autowired private DiscoveryClient discoveryClient; @Autowired private Registration registration; @RequestMapping(value = "/sayHello", method = RequestMethod.GET) @ResponseBody public String sayHello(@RequestParam String name) { List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances(registration.getServiceId()); if (serviceInstanceList != null) { for (ServiceInstance serviceInstance : serviceInstanceList) { logger.info("/sayHello,host:" + serviceInstance.getHost() + ",port:" + serviceInstance.getPort() + ",serviceId:" + serviceInstance.getServiceId()); } } return "Hello " + name + "!"; }} 2.3 修改服务提供端配置修改application.properties配置文件。123456#指定微服务的名称,此后调用就可以直接使用该名称调用spring.application.name=hello-serviceserver.port=2222#这里要跟刚才eureka服务端配置的一致eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/ 2.4 启动并注册服务运行EurekaServiceDemoApplication,再打开http://localhost:1111/eureka/,可以看到服务已经注册成功了。这里要启动多个服务实例的话,可以启动一个服务后,修改application.properties的端口配置,去除启动配置里面的Single instance only勾选,再启动就可以了。这时直接访问服务http://localhost:2222/sayHello?name=Kroos,是可以调用成功的。 3. 使用客户端调用服务这里使用Ribbon作为客户端的负载均衡的实现。 3.1 新建客户端项目新建module,依赖选择Ribbon,生成项目,这里命令为client-demo,生成成功后pom.xml的依赖如下。1234567891011121314151617181920212223242526272829303132<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency></dependencies><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement> 3.2 修改配置文件和注入RestTemplate修改application.properties,指定eureka的地址。1234spring.application.name=ribbon-consumerserver.port=3333eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/ 修改启动类ClientDemoApplication,注入RestTemplate和增加@EnableDiscoveryClient注解。1234567891011121314@EnableDiscoveryClient@SpringBootApplicationpublic class ClientDemoApplication { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(ClientDemoApplication.class, args); }} 3.3 新建服务端调用类新建ConsumerController,使用restTemplate调用服务端。123456789101112@RestControllerpublic class ConsumerController { @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/testSayHello", method = RequestMethod.GET) public String testSayHello(@RequestParam String name) { return restTemplate.getForEntity("http://hello-service/sayHello?name=" + name, String.class).getBody(); }} 注意这里的调用地址,直接使用http://hello-service/sayHello就行了,调用http://localhost:3333/testSayHello?name=xxx几次,可以看到服务被分发到两个service端分别执行。12342017-06-13 10:41:40.949 INFO 23620 --- [nio-2223-exec-1] c.h.s.controller.SayHelloController : /sayHello,host:huangyongfeng,port:2222,serviceId:HELLO-SERVICE2017-06-13 10:41:40.949 INFO 23620 --- [nio-2223-exec-1] c.h.s.controller.SayHelloController : /sayHello,host:huangyongfeng,port:2223,serviceId:HELLO-SERVICE2017-06-13 10:41:42.979 INFO 23620 --- [nio-2223-exec-2] c.h.s.controller.SayHelloController : /sayHello,host:huangyongfeng,port:2222,serviceId:HELLO-SERVICE2017-06-13 10:41:42.980 INFO 23620 --- [nio-2223-exec-2] c.h.s.controller.SayHelloController : /sayHello,host:huangyongfeng,port:2223,serviceId:HELLO-SERVICE 4. 更新日志2017-06-13 首次成文]]></content>
<categories>
<category>Java开发</category>
</categories>
<tags>
<tag>SpringCloud</tag>
<tag>eureka</tag>
<tag>SpringBoot</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Oracle执行计划说明]]></title>
<url>%2F2017%2F06%2F08%2FOracle%E6%89%A7%E8%A1%8C%E8%AE%A1%E5%88%92%E8%AF%B4%E6%98%8E%2F</url>
<content type="text"><![CDATA[本篇介绍:如何查看分析Oracle的执行计划 1. 查看执行计划1.1 使用SQL命令查看先使用explain plan for命令解析sql,再执行select * from TABLE(DBMS_XPLAN.DISPLAY);语句查看解析结果。123456789101112131415SQL> explain plan for 2 select * from cust_order;ExplainedSQL> select * from TABLE(DBMS_XPLAN.DISPLAY);PLAN_TABLE_OUTPUT--------------------------------------------------------------------------------Plan hash value: 922872969-------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 78778 | 75M| 3279 (1)| 00:00:40 || 1 | TABLE ACCESS FULL| CUST_ORDER | 78778 | 75M| 3279 (1)| 00:00:40 |-------------------------------------------------------------------------------8 rows selected 1.2 使用PLSQL或Toad等工具PLSQL下选择对应的sql按F5执行解析就可以了,需要显示更多的执行计划信息,可以在设置里面修改。 2. SQL执行顺序SQL的执行顺序按照下图执行计划从上到下,从右到左的顺序执行。从上到下,是指在同一层级下,上面的查询比下面的先执行,从右到左,是指层级右边的比左边的先执行,用户可以点击下一个操作的按钮逐步查看sql的执行顺序。 3. COST(耗费) The Oracle Optimizer is a cost-based optimizer. The execution plan selected for a SQL statement is just one of the many alternative execution plans considered by the Optimizer. The Optimizer selects the execution plan with the lowest cost, where cost represents the estimated resource usage for that plan. The lower the cost the more efficient the plan is expected to be. The optimizer’s cost model accounts for the IO, CPU, and network resources that will be used by the query. 上面的图中有COST这一列,Oracle现在主要使用的是基于代价的优化器,Oracle会自动选择COST最小的执行计划,COST并没有单位,是一个相对值,Oracle会根据COST的大小来评估CBO的执行成本,选择执行计划。COST的计算由磁盘IO、CPU、网络资源计算而成。 4. Cardinality(基数) The cardinality is the estimated number of rows that will be returned by each operation. The Optimizer determines the cardinality for each operation based on a complex set of formulas that use both table and column level statistics as input (or the statistics derived by dynamic sampling). One of the simplest formulas is used when there is a single equality predicate in a single table query (with no histogram). In this case the Optimizer assumes a uniform distribution and calculates the cardinality for the query by dividing the total number of rows in the table by the number of distinct values in the column used in the where clause predicate. Cardinality是Oracle执行sql每一步操作估算的记录行数,CBO优化器会根据查询的表、列级别的统计数据或者动态的数据采样统计作为输入数据,经过一系统复杂的计算得出Cardinality。 5. Access Method Full table scan-全表扫描,它会访问表中的所有记录,大数据量的表查询应该尽量避免这种操作。 Table access by ROWID-通过ROWID访问表记录。记录的ROWID指向了该行的数据文件,数据块以及数据块中的位置。这是查找行记录最快的方式,Oracle会优先使用这种方式。 Index unique scan-通过唯一索引扫描只会返回一条记录,Oracle通常会使用唯一索引或者主键去进去查找。 Index range scan-索引范围扫描,发生在对唯一索引进行范围操作的情况下,如(=, <, >,LIKE等)。 Index range scan descending-带排序的索引范围扫描,访问跟Index range scan一样,当索引满足ORDER BY .. DESCENDING这种排序语句的时候使用。 Index skip scan-组合索引键中非前导列索引检索。适用于查询条件中没有指定组合索引的前导列,只是指定了组合索引的其它列,这样Oracle就会使用Index skip scan的方式来访问数据。在前导列的数据唯一值越少,非前导列的数据唯一值越多的情况下,Index skip scan的性能越好。实际的搜索过程中,Oracle是会根据前导列的唯一值的个数划分多个查询入口,利用组合索引的其它列在各自的前导查询入口里面搜索数据,再合并结果集。例如有一个表user_info(user_id, sex, user_name),其中(sex, user_name)是组合索引,当查询条件为user_name=’ZhangSan’时,而sex这一列的唯一值只有0,1两种情况时,实际的查询应该是类似于123select * from user_info where sex = 0 and user_name='ZhangSan' union all select * from user_info where sex = 1 and user_name='ZhangSan' 因此可以看出,当索引前导列的唯一值过多,Index skip scan的性能应付受到影响。而Index skip scan的使用条件包括以下三个:(1)索引是一个复合索引,可以是唯一索引,也可以不唯一(2)索引中前导列的重复值很多,即唯一值少,其它列重复值很少,即唯一值很多(3)查询条件中没有使用前导列条件来过滤数据 Full Index scan-索引全扫描,就是指要扫描目标索引所有叶子块的所有索引行,但是并不需要扫描该索引的所有的分支块,在默认情况下,Oracle在做索引全扫描时只需要通过访问必要的分支块定位到位于该索引最左边的叶子块的第一行索引行,就可以利用该索引叶子块之间的双向指针链表,从左至右依次顺序扫描该索引所有叶子块的所有索引行了。Full Index scan在查询的条件列都有索引的情况下使用,它会比搜索Table更加高效。 参考资料https://docs.oracle.com/cd/B19306_01/server.102/b14211/ex_plan.htm#i25909http://blog.csdn.net/truelove12358/article/details/70282445http://blog.csdn.net/tianlesoftware/article/details/5826546http://www.iteye.com/topic/586256 更新日志]]></content>
<categories>
<category>数据库</category>
</categories>
<tags>
<tag>Oracle</tag>
</tags>
</entry>
<entry>
<title><![CDATA[IntelliJ IDEA常用设置和插件]]></title>
<url>%2F2017%2F05%2F31%2FIntelliJ%20IDEA%E5%B8%B8%E7%94%A8%E8%AE%BE%E7%BD%AE%E5%92%8C%E6%8F%92%E4%BB%B6%2F</url>
<content type="text"><![CDATA[本篇介绍:Intellij IDEA常用的设置和插件 1. 常用设置2. 常用插件2.1 CamelCase用于转换蛇形命名(snake_case)和驼峰命名(camelCase),安装后快捷键为SHIFT + ALT + U。 2.2 KeyPromoter快捷键记忆辅助插件,当你用鼠标的操作可以用快捷键代替时,会自动弹出对应的快捷键提示框,如下图所示。不过有些默认没有快捷键,不太常用的鼠标操作,你操作三次之后,它也会弹出提示框提示你创建对应的快捷键(如新建一个类文件),每次都要点一下,感觉有点烦。 3. 更新日志2017-05-31 初次成文]]></content>
<categories>
<category>开发工具</category>
</categories>
<tags>
<tag>IntelliJ IDEA</tag>
</tags>
</entry>
<entry>
<title><![CDATA[搭建ionic开发环境]]></title>
<url>%2F2017%2F05%2F26%2F%E6%90%AD%E5%BB%BAionic%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%2F</url>
<content type="text"><![CDATA[本篇介绍:如何搭建ionic的开发环境 1. 环境准备1.1 安装node.js下载安装node.js,一般来说一路点next就行了。安装完成后,打开命令行窗口,输入以下命令检查安装是否成功。12C:\Users\lenovo>node -vv7.8.0 1.2 安装npm新版的node.js已经自带npm了,可以在命令行输入以下命令检查是否成功。12C:\Users\lenovo>npm -v4.2.0 1.3 安装cnpm(可选)因为npm的国外镜像比较慢,可以使用淘宝的镜像,打开nodejs命令行客户端,输入以下命令1npm install -g cnpm --registry=https://registry.npm.taobao.org 等待安装完成后就可以使用cnpm命令了。关于这个镜像的具体说明和cnpm的用法,可以到淘宝NPM镜像的网站上去看。 1.4 安装cordova和ionic在ionic命令行客户端输入以下命令1cnpm install -g cordova ionic 2. 创建项目2.1 新建工程进入工程目录,我这里是E:\Projects,输入以下命令1ionic start ionic-demo tabs 其中ionic-demo为项目名称,tabs为ionic预设的几种样式之一 2.2 启动项目进入刚才创建的ionic-demo工程目录,输入以下命令启动项目1ionic serve 项目启动成功后,打开http://localhost:8102就可以访问了。 3. 更新日志2017-05-27 首次成文2017-05-31 增加node.js和npm安装内容]]></content>
<categories>
<category>APP开发</category>
</categories>
<tags>
<tag>ionic</tag>
</tags>
</entry>
</search>