曝光一个爽约的人

PS:本次直接曝光这个人我所知道的信息,因为我个人特别痛恨这种没有契约精神的骗子,并不是她退出而不肯A苏梅岛的房费,而是因为把我拉黑,如果要喷我,请看完整个事件过程。

首先声明一下,我是很公平,很民主的,所有的预订及行程规划都是跟队友分享的,绝对不独裁,因为每个人都应该有知情权的,即使他们不看。

我是第一次在某个网站(qiongyouwang)里约的,远离屌丝网站,以后还是继续去磨房约,反正以后不在这里约了,这次打算约4个人~6个人一起去泰国南部玩,主要都是海岛,以前都是在其他各大户外网站,在行程定下来之后,从来没有遇到过爽约的时间,但是今年却遇到了,事情是这样子的:“行程商量了半个月,也定下来了,我们一共5个人,接着在12月20日预定酒店,每次预订酒店,我就把这个地区的酒店列个5家左右,因为大家都很忙,所以我做成了pdf带连接的文档,让大家选,预定下来之后,因为苏梅岛的酒店很紧张,只有48小时能取消。本人从未被爽约过,所以也相信小伙伴们的人品,就说这个酒店是不可取消的,这里我就不收取大家的订金了,如果你们要取消,请自觉A一下房费,或者在48小时内回复我,我好取消重新预定。”

后来其中一个队友,女性,叫梁鑫淼,wx号是miaoess,电话是1355208498518301356513,职业是java开发工程师(丢了我们同行业的脸),她通知我说因为找工作,找到了,然后要取消去泰国的行程。我说:“可以的,但是苏梅岛的酒店取消不了你要A一下”。当时她没有正面回答我这个问题。

接着我就把行程剩下的酒店全部预定完,然后她跟我说,她找工作不顺利,打算跟我一起去,我就爽快的说,可以的,那就一起,接着我就去把剩下的酒店改成了5个人,就这样子把酒店预订从原来的4个人预订到5个人,我不烦人家酒店的人员也烦了。= =

这里要吐槽一下,你找工作不顺利,是因为伪造资料,你伪造资料也好,但是也要做的完美一点,中间还让我做她的工作背景调查的人,我还帮忙帮她撒谎—~~~~,聊天记录如下 :

wKgED1w7-rCAUnphAAS-I_ftFsI835

然后过了大约一周没有跟我联系,我今天就问她,你签证下来了吗?然后她没有说下来了,而是找借口说不去了,大家约伴以后注意一点,免得像我这样子遇到了那么大的坑。

注:这里她并不是不去了,而是在大群里面还是屌丝(穷游)网重新约人了,我就纳闷,你就加入组织了,还去重新拉人,最后还我把拉黑,骗我说不去了。

然后我就说,苏梅岛的酒店取消不了,你要A房间费用,然后她就说那个涛(另外一个人)去,他没有预定房间,其实涛也是被她抛弃的,后来涛找了我,问我预定酒店的时候跟他说一下,所以我知道他是预定了的。她就一直骗我,说他没预定,后来我再次找涛证实了一下,是预定了的。

最后我就跟她说,我试试发邮件给酒店,看看能不能取消,结果,你猜怎么着?我被拉黑了,平生第一次被人这样子玩哦 – -。

其实你不去就不去,提前说,早点跟我说,如果我今天不找她,估计到了苏梅岛才会知道她不来了,一点契约精神都没有,还出来混。

后来我已经联系酒店,申请取消房间,现在还有半个月的时间,但是不知道会不会给我免费取消,如果不会的话,那我只有自己啃了另外一间的房费了。

最后,大家出来一起玩,开心就好,有什么事情,你可以直接跟我说,你不肯出那510元的房费,我出也可以,为什么当初不收你们的定金?因为我相信你们的人品,如果连最基本的人品都没有,那这个人是有多失败???我当领队那么多年,这也是我遇到的第一次。

今天的聊天记录:

1552742397-9522-gED1w7--6ACczuAAZ78ADYTpc888

1552742396-2920-gED1w7---ABjveAAX2itOj9ko626

1552742397-6672-gED1w7-ACAEqcpAAde3FfFJqU611

1552742453-6360-gED1w7-AKAcZAcAAXCTIxRwpM063

理解Sharding jdbc原理

相比于Spring基于AbstractRoutingDataSource实现的分库分表功能,Sharding jdbc在单库单表扩展到多库多表时,兼容性方面表现的更好一点。例如,spring实现的分库分表sql写法如下:

select id, name, price, publish, intro
from book${tableIndex}
where id = #{id,jdbcType=INTEGER}

sql中的表名book需要加一个分表的后缀tableIndex,也就是需要在sql注入的参数中指定插入哪个表。相比,Sharding jdbc在这一块封装的更好一点。其sql中,根本不需要指定tableIndex,而是根据分库分表策略自动路由。

select id, name, price, publish, intro
from book
where id = #{id,jdbcType=INTEGER}

Sharding jdbc的这种特性,在水平扩展的时候无疑更具有吸引力。试想一下,一个项目开发一段时间后,单库单表数据量急剧上升,需要分库分表解决数据库的访问压力。而现有sql配置都是基于单库单表实现的,如果基于spring的AbstractRoutingDataSource实现,需要修改每一个相关表的sql,修改涉及较多地方,出错概率较大。而基于Sharding jdbc实现时,sql无需修改,只需要在spring中添加Sharding jdbc的相关配置即可,减少了修改面,大大简化分库分表的实现难度。

那么,Sharding jdbc是如何实现这种分库分表的逻辑呢?下面我们用一段简单、易懂的代码描述Sharding jdbc的原理。

通常我们在写一段访问数据库的数据时,逻辑是这样的:

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(“application.xml”);
DataSource dataSource = ctx.getBean(“dataSource”, DataSource.class);
Connection connection = dataSource.getConnection();

String sql = “select id, name, price, publish, intro from book where id = 111″;
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
// handle ResultSet…

Sharding jdbc是基于JDBC协议实现的,当我们获得dataSource时,这个dataSource是Sharding jdbc自己定义的一个SpringShardingDataSource类型的数据源,该数据源在返回getConnection()及prepareStatement()时,分别返回ShardingConnection和ShardingPreparedStatement的实例对象。然后在executeQuery()时,ShardingPreparedStatement做了这样的一件事:

根据逻辑sql,经过分库分表策略逻辑计算,获得分库分表的路由结果SQLRouteResult;
SQLRouteResult中包含真实的数据源以及转换后的真正sql,利用真实的数据源去执行获得ResultSet;
将ResultSet列表封装成一个可以顺序读的ResultSet对象IteratorReducerResultSet。

class ShardingPreparedStatement implements PreparedStatement {

@Override
public ResultSet executeQuery() throws SQLException {
List<SQLRouteResult> routeResults = routeSql(logicSql);

List<ResultSet> resultSets = new ArrayList<>(routeResults.size());
for (SQLRouteResult routeResult : routeResults) {
PreparedStatement ps = routeResult.getDataSource().getConnection.prepareStatement(routeResult.getParsedSql());
ResultSet rs = ps.executeQuery();
resultSets.add(rs);
}

return new IteratorReducerResultSet(resultSets);
}
…..

}

其中,分库分表策略的sql路由过程,我们将Sharding jdbc中的相关代码全部抽出来,放到一起来观看这个过程的实现:

// 环境准备
@SuppressWarnings(“resource”)
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(“application.xml”);
SpringShardingDataSource dataSource = ctx.getBean(SpringShardingDataSource.class);
Field field = SpringShardingDataSource.class.getSuperclass().getDeclaredField(“shardingContext”);
field.setAccessible(true);
ShardingContext sctx = (ShardingContext)field.get(dataSource);
ShardingRule shardingRule = sctx.getShardingRule();

String logicSql = “select id, name, price, publish, intro from book where id = ?”;
List<Object> parameters = new ArrayList<>();
parameters.add(2000);

// sql解析
MySqlStatementParser parser = new MySqlStatementParser(logicSql);
MySQLSelectVisitor visitor = new MySQLSelectVisitor();
SQLStatement statement = parser.parseStatement();
visitor.getParseContext().setShardingRule(shardingRule);
statement.accept(visitor);

SQLParsedResult parsedResult = visitor.getParseContext().getParsedResult();
if (visitor.getParseContext().isHasOrCondition()) {
new OrParser(statement, visitor).fillConditionContext(parsedResult);
}
visitor.getParseContext().mergeCurrentConditionContext();
System.out.println(“Parsed SQL result: ” + parsedResult);
System.out.println(“Parsed SQL: ” + visitor.getSQLBuilder());
parsedResult.getRouteContext().setSqlBuilder(visitor.getSQLBuilder());
parsedResult.getRouteContext().setSqlStatementType(SQLStatementType.SELECT);

// 分库分表路由
SQLRouteResult result = new SQLRouteResult(parsedResult.getRouteContext().getSqlStatementType(), parsedResult.getMergeContext(), parsedResult.getGeneratedKeyContext());
for (ConditionContext each : parsedResult.getConditionContexts()) {
Collection<Table> tables = parsedResult.getRouteContext().getTables();
final Set<String> logicTables = new HashSet<>();
tables.forEach(a -> logicTables.add(a.getName()));

SingleTableRouter router = new SingleTableRouter(shardingRule,
logicTables.iterator().next(),
each,
parsedResult.getRouteContext().getSqlStatementType());

RoutingResult routingResult = router.route();

// sql改写 –> routingResult.getSQLExecutionUnits()
// —> SingleRoutingTableFactor.replaceSQL(sqlBuilder).buildSQL()
// 结果合并
result.getExecutionUnits().addAll(routingResult.getSQLExecutionUnits(parsedResult.getRouteContext().getSqlBuilder()));
}
// amendSQLAccordingToRouteResult(parsedResult, parameters, result);
for (SQLExecutionUnit each : result.getExecutionUnits()) {
System.out.println(each.getDataSource() + ” ” + each.getSql() + ” ” + parameters);
}

  • 准备环境。由于Sharding jdbc分库分表中ShardingRule这个类是贯穿整个路由过程,我们在Spring中写好Sharding jdbc的配置,利用反射获取一个这个对象。(Sharding jdbc版本以及配置,在文章最后列出,方便debug这个过程)
  • sql解析。Sharding jdbc使用阿里的Druid库解析sql。在这个过程中,Sharding jdbc实现了一个自己的sql解析内容缓存容器SqlBuilder。当语法分析中解析到一个表名的时候,在SqlBuilder中缓存一个sql相关的逻辑表名的token。并且,Sharding jdbc会将sql按照语义解析为多个segment。例如,”select id, name, price, publish, intro from book where id = ?”将解析为,”select id, name, price, publish, intro | from | book | where | id = ?”。
  • 分库分表路由。根据ShardingRule中指定的分库分表列的参数值,以及分库分表策略,实行分库分表,得到一个RoutingResult 。RoutingResult 中包含一个真实数据源,以及逻辑表名和实际表名。
  • sql改写。在SqlBuilder中,查找sql中解析的segment,将和逻辑表名一致的segment替换成实际表名。(segment中可以标注该地方是不是表名)
    以上代码执行结果如下:

Parsed SQL result: SQLParsedResult(routeContext=RouteContext(tables=[Table(name=book, alias=Optional.absent())], sqlStatementType=null, sqlBuilder=null), generatedKeyContext=GeneratedKeyContext(columns=[], columnNameToIndexMap={}, valueTable={}, rowIndex=0, columnIndex=0, autoGeneratedKeys=0, columnIndexes=null, columnNames=null), conditionContexts=[ConditionContext(conditions={})], mergeContext=MergeContext(orderByColumns=[], groupByColumns=[], aggregationColumns=[], limit=null))
Parsed SQL: SELECT id, name, price, publish, intro FROM [Token(book)] WHERE id = ?
dataSource1 SELECT id, name, price, publish, intro FROM book_00 WHERE id = ? [2000]
dataSource2 SELECT id, name, price, publish, intro FROM book_02 WHERE id = ? [2000]
dataSource1 SELECT id, name, price, publish, intro FROM book_02 WHERE id = ? [2000]
dataSource2 SELECT id, name, price, publish, intro FROM book_01 WHERE id = ? [2000]
dataSource0 SELECT id, name, price, publish, intro FROM book_00 WHERE id = ? [2000]
dataSource0 SELECT id, name, price, publish, intro FROM book_01 WHERE id = ? [2000]
dataSource2 SELECT id, name, price, publish, intro FROM book_00 WHERE id = ? [2000]
dataSource1 SELECT id, name, price, publish, intro FROM book_01 WHERE id = ? [2000]
dataSource0 SELECT id, name, price, publish, intro FROM book_02 WHERE id = ? [2000]

实际上,我们可以用更通俗易懂的代码表示sql改写的这个过程:

String logicSql = “select id, name, price, publish, intro from book where id = 111″;
MySqlStatementParser parser = new MySqlStatementParser(logicSql);
SQLStatement statement = parser.parseStatement();
MySQLSimpleVisitor visitor = new MySQLSimpleVisitor();
statement.accept(visitor);

String logicTable = “book”;
String realTable = “book_00″;
String token = “\\$\\{” + logicTable + “\\}”;

String sqlBuilder = visitor.getAppender().toString();
String sql = sqlBuilder.replaceAll(token, realTable);

System.out.println(sqlBuilder);
System.out.println(sql);

 

结果如下:

SELECT id, name, price, publish, intro
FROM ${book}
WHERE id = 111
SELECT id, name, price, publish, intro
FROM book_00
WHERE id = 111

以上,大致将Sharding jdbc的原理及实现过程介绍了一下,如果想要了解正真的实现过程和细节,还需要对照代码仔细推敲。

本文的实现环境:

<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-config-spring</artifactId>
<version>1.4.0</version>
</dependency>

application.xml:

<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:tx=”http://www.springframework.org/schema/tx”
xmlns:context=”http://www.springframework.org/schema/context”
xmlns:rdb=”http://www.dangdang.com/schema/ddframe/rdb”
xsi:schemaLocation=”
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.dangdang.com/schema/ddframe/rdb
http://www.dangdang.com/schema/ddframe/rdb/rdb.xsd”>

<context:property-placeholder location=”classpath:jdbc.properties” ignore-unresolvable=”true” />

<bean id=”dataSource0″ class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
<property name=”driverClassName” value=”com.mysql.jdbc.Driver” />
<property name=”url” value=”${jdbc.mysql.url0}” />
<property name=”username” value=”${jdbc.mysql.username0}” />
<property name=”password” value=”${jdbc.mysql.password0}” />
</bean>

<bean id=”dataSource1″ class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
<property name=”driverClassName” value=”${driver}” />
<property name=”url” value=”${jdbc.mysql.url1}” />
<property name=”username” value=”${jdbc.mysql.username1}” />
<property name=”password” value=”${jdbc.mysql.password1}” />
</bean>

<bean id=”dataSource2″ class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
<property name=”driverClassName” value=”${driver}” />
<property name=”url” value=”${jdbc.mysql.url2}” />
<property name=”username” value=”${jdbc.mysql.username2}” />
<property name=”password” value=”${jdbc.mysql.password2}” />
</bean>

<!– sharding jdbc –>
<rdb:strategy id=”tableShardingStrategy” sharding-columns=”id”
algorithm-class=”com.wy.sharding.MemberSingleKeyTableShardingAlgorithm” />

<rdb:data-source id=”shardingDataSource”>
<rdb:sharding-rule data-sources=”dataSource0,dataSource1,dataSource2″>
<rdb:table-rules>
<rdb:table-rule logic-table=”book”
actual-tables=”book_0${0..2}”
table-strategy=”tableShardingStrategy”/>
</rdb:table-rules>
</rdb:sharding-rule>
</rdb:data-source>
</beans>

MemberSingleKeyTableShardingAlgorithm.java:

public class MemberSingleKeyTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Integer> {

public String doEqualSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) {
String routeDBSuffix = getRouteDBSuffix(shardingValue.getValue());
for (String each : availableTargetNames) {
if (each.endsWith(routeDBSuffix)) {
return each;
}
}
throw new IllegalArgumentException();
}

public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) {
Collection<String> result = new LinkedHashSet<String>(availableTargetNames.size());
for (int value : shardingValue.getValues()) {
String routeDBSuffix = getRouteDBSuffix(value);
for (String tableName : availableTargetNames) {
if (tableName.endsWith(routeDBSuffix)) {
result.add(tableName);
}
}
}
return result;
}

public Collection<String> doBetweenSharding(Collection<String> availableTargetNames,
ShardingValue<Integer> shardingValue) {
Collection<String> result = new LinkedHashSet<String>(availableTargetNames.size());
Range<Integer> range = (Range<Integer>) shardingValue.getValueRange();
for (int i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
String routeDBSuffix = getRouteDBSuffix(i);
for (String each : availableTargetNames) {
if (each.endsWith(routeDBSuffix)) {
result.add(each);
}
}
}
return result;
}

public String getRouteDBSuffix(Integer shardingCode) {
int modValue = shardingCode % 3;
return “0” + modValue;
}

}

 

FormData接口

FormData 接口提供了一种表示表单数据的键值对的构造方式,经过它的数据可以使用 XMLHttpRequest.send() 方法送出,本接口和此方法都相当简单直接。如果送出时的编码类型被设为 "multipart/form-data",它会使用和表单一样的格式。

你也可以将它直接传递给构造器 URLSearchParams, if you want to generate query parameters in the way a <form> would do if it were using simple GET submission.

An object implementing FormData can directly be used in a for...of structure, instead of entries()for (var p of myFormData) is equivalent to for (var p of myFormData.entries()).

构造函数

FormData()
创建一个新的 FormData 对象。

 

方法

FormData.append()
Appends a new value onto an existing key inside a FormData object, or adds the key if it does not already exist.
FormData.delete()
Deletes a key/value pair from a FormData object.
FormData.entries()
Returns an iterator allowing to go through all key/value pairs contained in this object.
FormData.get()
Returns the first value associated with a given key from within a FormData object.
FormData.getAll()
Returns an array of all the values associated with a given key from within a FormData.
FormData.has()
Returns a boolean stating whether a FormData object contains a certain key.
FormData.keys()
Returns an iterator allowing to go through all keys of the key/value pairs contained in this object.
FormData.set()
Sets a new value for an existing key inside a FormData object, or adds the key/value if it does not already exist.
FormData.values()
Returns an iterator allowing to go through all values contained in this object.

 

 

IntelliJ IDEA 常用快捷键Mac篇

在 IntelliJ IDEA 中有两个 Mac 版本的快捷键,分别为 Mac OS X 和 Mac OS X 10.5+, 其中 Mac OS X 10.5+ 为 IntelliJ IDEA 默认的快捷键版本。此外,建议将 Mac 系统中与 IntelliJ IDEA 冲突的快捷键取消或更改,不建议改 IntelliJ IDEA 的默认快捷键。

Mac 键盘符号和修饰键说明

  •  ——> Command
  •  ——> Shift
  •  ——> Option
  •  ——> Control
  • ↩︎ ——> Return/Enter
  •  ——> Delete
  •  ——> 向前删除键(Fn + Delete)
  •  ——> 上箭头
  •  ——> 下箭头
  •  ——> 左箭头
  •  ——> 右箭头
  •  ——> Page Up(Fn + ↑)
  •  ——> Page Down(Fn + ↓)
  •  ——> 右制表符(Tab键)
  •  ——> 左制表符(Shift + Tab)
  •  ——> Escape(Esc)
  • End ——> Fn + →
  • Home ——> Fn + ←

Part 1:Editing(编辑)

快捷键 作用
Control + Space 基本的代码补全(补全任何类、方法、变量)
Control + Shift + Space 智能代码补全(过滤器方法列表和变量的预期类型)
Command + Shift + Enter 自动结束代码,行末自动添加分号
Command + P 显示方法的参数信息
Control + J 快速查看文档
Shift + F1 查看外部文档(在某些代码上会触发打开浏览器显示相关文档)
Command + 鼠标放在代码上 显示代码简要信息
Command + F1 在错误或警告处显示具体描述信息
Command + NControl + EnterControl + N 生成代码(gettersetterhashCodeequalstoString、构造函数等)
Control + O 覆盖方法(重写父类方法)
Control + I 实现方法(实现接口中的方法)
Command + Option + T 包围代码(使用if...elsetry...catchforsynchronized等包围选中的代码)
Command + / 注释 / 取消注释与行注释
Command + Option + / 注释 / 取消注释与块注释
Option + 方向键上 连续选中代码块
Option + 方向键下 减少当前选中的代码块
Control + Shift + Q 显示上下文信息
Option + Enter 显示意向动作和快速修复代码
Command + Option + L 格式化代码
Control + Option + O 优化 import
Control + Option + I 自动缩进线
Tab / Shift + Tab 缩进代码 / 反缩进代码
Command + X 剪切当前行或选定的块到剪贴板
Command + C 复制当前行或选定的块到剪贴板
Command + V 从剪贴板粘贴
Command + Shift + V 从最近的缓冲区粘贴
Command + D 复制当前行或选定的块
Command + Delete 删除当前行或选定的块的行
Control + Shift + J 智能的将代码拼接成一行
Command + Enter 智能的拆分拼接的行
Shift + Enter 开始新的一行
Command + Shift + U 大小写切换
Command + Shift + ] / Command + Shift + [ 选择直到代码块结束 / 开始
Option + Fn + Delete 删除到单词的末尾
Option + Delete 删除到单词的开头
Command + 加号 / Command + 减号 展开 / 折叠代码块
Command + Shift + 加号 展开所以代码块
Command + Shift + 减号 折叠所有代码块
Command + W 关闭活动的编辑器选项卡

Part 2:Search / Replace(查询/替换)

快捷键 作用
Double Shift 查询任何东西
Command + F 文件内查找
Command + G 查找模式下,向下查找
Command + Shift + G 查找模式下,向上查找
Command + R 文件内替换
Command + Shift + F 全局查找(根据路径)
Command + Shift + R 全局替换(根据路径)
Command + Shift + S 查询结构(Ultimate Edition 版专用,需要在 Keymap 中设置)
Command + Shift + M 替换结构(Ultimate Edition 版专用,需要在 Keymap 中设置)

Part 3:Usage Search(使用查询)

快捷键 作用
Option + F7 / Command + F7 在文件中查找用法 / 在类中查找用法
Command + Shift + F7 在文件中突出显示的用法
Command + Option + F7 显示用法

Part 4:Compile and Run(编译和运行)

快捷键 作用
Command + F9 编译 Project
Command + Shift + F9 编译选择的文件、包或模块
Control + Option + R 弹出 Run 的可选择菜单
Control + Option + D 弹出 Debug 的可选择菜单
Control + R 运行
Control + D 调试
Control + Shift + RControl + Shift + D 从编辑器运行上下文环境配置

Part 5:Debugging(调试)

快捷键 作用
F8 进入下一步,如果当前行断点是一个方法,则不进入当前方法体内
F7 进入下一步,如果当前行断点是一个方法,则进入当前方法体内,如果该方法体还有方法,则不会进入该内嵌的方法中
Shift + F7 智能步入,断点所在行上有多个方法调用,会弹出进入哪个方法
Shift + F8 跳出
Option + F9 运行到光标处,如果光标前有其他断点会进入到该断点
Option + F8 计算表达式(可以更改变量值使其生效)
Command + Option + R 恢复程序运行,如果该断点下面代码还有断点则停在下一个断点上
Command + F8 切换断点(若光标当前行有断点则取消断点,没有则加上断点)
Command + Shift + F8 查看断点信息

Part 6:Navigation(导航)

快捷键 作用
Command + O 查找类文件
Command + Shift + O 查找所有类型文件、打开文件、打开目录,打开目录需要在输入的内容前面或后面加一个反斜杠/
Command + Option + O 前往指定的变量 / 方法
Control + 方向键左 / Control + 方向键右 左右切换打开的编辑 tab 页
F12 返回到前一个工具窗口
Esc 从工具窗口进入代码文件窗口
Shift + Esc 隐藏当前或最后一个活动的窗口,且光标进入代码文件窗口
Command + Shift + F4 关闭活动 run/messages/find/... tab
Command + L 在当前文件跳转到某一行的指定处
Command + E 显示最近打开的文件记录列表
Option + 方向键左 / Option + 方向键右 光标跳转到当前单词 / 中文句的左 / 右侧开头位置
Command + Option + 方向键左 / Command + Option + 方向键右 退回 / 前进到上一个操作的地方
Command + Shift + Delete 跳转到最后一个编辑的地方
Option + F1 显示当前文件选择目标弹出层,弹出层中有很多目标可以进行选择(如在代码编辑窗口可以选择显示该文件的 Finder)
Command + B / Command + 鼠标点击 进入光标所在的方法/变量的接口或是定义处
Command + Option + B 跳转到实现处,在某个调用的方法名上使用会跳到具体的实现处,可以跳过接口
Option + SpaceCommand + Y 快速打开光标所在方法、类的定义
Control + Shift + B 跳转到类型声明处
Command + U 前往当前光标所在方法的父类的方法 / 接口定义
Control + 方向键下 / Control + 方向键上 当前光标跳转到当前文件的前一个 / 后一个方法名位置
Command + ] / Command + [ 移动光标到当前所在代码的花括号开始 / 结束位置
Command + F12 弹出当前文件结构层,可以在弹出的层上直接输入进行筛选(可用于搜索类中的方法)
Control + H 显示当前类的层次结构
Command + Shift + H 显示方法层次结构
Control + Option + H 显示调用层次结构
F2 / Shift + F2 跳转到下一个 / 上一个突出错误或警告的位置
F4 / Command + 方向键下 编辑 / 查看代码源
Option + Home 显示到当前文件的导航条
F3 选中文件 / 文件夹 / 代码行,添加 / 取消书签
Option + F3 选中文件 / 文件夹/代码行,使用助记符添加 / 取消书签
Control + 0Control + 9 定位到对应数值的书签位置
Command + F3 显示所有书签

Part 7:Refactoring(重构)

快捷键 作用
F5 复制文件到指定目录
F6 移动文件到指定目录
Command + Delete 在文件上为安全删除文件,弹出确认框
Shift + F6 重命名文件
Command + F6 更改签名
Command + Option + N 一致性
Command + Option + M 将选中的代码提取为方法
Command + Option + V 提取变量
Command + Option + F 提取字段
Command + Option + C 提取常量
Command + Option + P 提取参数

Part 8:VCS / Local History(版本控制 / 本地历史记录)

快捷键 作用
Command + K 提交代码到版本控制器
Command + T 从版本控制器更新代码
Option + Shift + C 查看最近的变更记录
Control + C 快速弹出版本控制器操作面板

Part 9:Live Templates(动态代码模板)

快捷键 作用
Command + Option + J 弹出模板选择窗口,将选定的代码使用动态模板包住
Command + J 插入自定义动态代码模板

Part 10:General(通用)

快捷键 作用
Command + 1Command + 9 打开相应编号的工具窗口
Command + S 保存所有
Command + Option + Y 同步、刷新
Control + Command + F 切换全屏模式
Command + Shift + F12 切换最大化编辑器
Option + Shift + F 添加到收藏夹
Option + Shift + I 检查当前文件与当前的配置文件
Control + ` 快速切换当前的 scheme(切换主题、代码样式等)
Command + , 打开 IDEA 系统设置
Command + ; 打开项目结构对话框
Shift + Command + A 查找动作(可设置相关选项)
Control + Shift + Tab 编辑窗口标签和工具窗口之间切换(如果在切换的过程加按上 delete,则是关闭对应选中的窗口)

 

IntelliJ IDEA 恢复代码的方法

在咱们正常开发项目的时候,难免遇到在开发过程中由于某种原因,想要将代码恢复到前一版本的情景。特别是在咱们删除了某些代码,想要恢复之前删除的代码的时候,了解这个在 IntelliJ IDEA 中恢复代码的方法就显得尤为重要啦!现在,以一些测试代码为例,进行详细的讲解:

1548307563-1584-2594ed191f636422748391692620

如上图所示,这是博主之前写的测试恒等运算符和equals()区别的测试类。接下来,咱们在这段代码中添加一条输出语句:

1548307563-3258-75df465d98636422748413123846

如上图所示,咱们添加了一条输出hello world的代码。现在嘛,有这样一个场景,那就是:要求咱们仅输出==equal()的区别即可,不需要添加额外的输出语句。这就要求咱们将代码恢复到之前的状态啦!在此忽略直接删除代码的方法,那该怎么办呢?

1548307563-7901-e519b59080636422748431374890

如上图所示,咱们只需要选择对应的类文件,点击鼠标右键,然后依次选择Local HistoryShow History,进入如下界面:

1548307563-1333-0c2c9183c1636422748455726282

如上图所示,最左边展示了版本记录,由于博主仅进行过这一次修改,因此这里只显示了2 minutes ago的版本记录;在往右看,依次展示了前一版本与当前版本的代码,并给出了区别,可谓是清晰简洁:

1548307563-5886-9bd91a431a636422748473177280

然后,选择咱们想要恢复的版本,呃,好吧,现在咱们仅有一个版本可以选择,点击鼠标右键,选择Revert

1548307563-1961-cfec6931cf636422748496828633

如上图所示,当咱们点击Revert之后,右侧的两个版本同步至“前一版本”,并给出了恢复提示。最后,咱们再回到代码编辑区检查一下是否真的恢复到前一版本了呢?

1548307568-2756-86d3bc87fa636422748521520046

如上图所示,显然咱们的操作成功了,代码已经恢复至前一版本啦!

12829303132115
 
Copyright © 2008-2021 lanxinbase.com Rights Reserved. | 粤ICP备14086738号-3 |