冥加

语言是窗户,不然就是墙


  • 首页

  • 分类

  • 标签

  • 归档

Java日常小记

发表于 2018-06-07 | 分类于 Java

简单记录一下java日常问题,欢迎指教:

1.Java小记 —— Java中String引用传参
对象和其他对象不太一样,是不可变的,所以再作为参数传递的时候和基本类型一样,都是“值传参”,要想达到“引用传参”的效果,就要使用StringBuffer/StringBuilder

2.Java小记 —— 浮点数(double、float)的格式格式化问题及处理
对科学计数显示、指定小数位、四舍五入、精度丢失、正负号等问题的处理进行了举例说明

2.Java小记 —— 日期时间转换问题(相差一小时)
记录日期字符串、long和日期对象相互转化时,转换错误、转换不准确(相差一小时)等问题的处理

记录中…

参照Java学Golang

发表于 2018-05-07 | 分类于 Golang

最近在学习使用golang,在学习新的语言时,如果可以对照着一门自己熟悉的语言来学习会容易很多,本人是名java程序猿,所以就对照着Java来学习,以”温故知新“的方式来记录一下学习过程。

以摘要的形式整理在此,欢迎指教:

1.参照Java学Go(一)—— 初识Go
(刚开始,先从语言界定、环境搭建、helloword和包结构等内容与java进行比较)

2.参照Java学Go(二)—— 变量和常量、基本数据类型
(通过变量、常量的定义,以及基本的数据类型使用与java进行比较)

3.参照Java学Go(三)—— 内置类型:数组、切片slice、集合map

记录中…

OpenLayer3画多边形框选坐标

发表于 2018-04-11 | 分类于 技能

之前用OpenLayer 3 写了个画多边形框选获得坐标的demo:

欢迎下载(送分)

下载的朋友反应
1,不能框选,(确实是我描述有误,是框选区域坐标),我后续补上;
2,不能矩形选择,这个其实是可以的,TEST_Box的方法其实传了矩形(box)参数,但是我在方法内部又将参数改成了多边形(Polygon),将该行注释掉就可以了;

SecureCRT配置导入导出

发表于 2018-04-10 | 分类于 技能

又换了个本,软件重新装一通,SecureCRT的里边的配置太多,一个一个的重新配肯定不行,所以在这儿说下配置的正确导入导出:

网上很多说直接把Config文件夹直接拷贝(导出),黏贴(导入)到新的SecureCRT配置目录,可是这样是有问题的,很多原宿主机的用户信息也都会带到新的配置中导致一些错误,比如使用秘钥验证的时候就会提示/Users/原宿主用户名/.ssh/xxx.pub不存在,所以这样导入是不对的,正确的做法应该是把Config/Seessins目录中的配置信息(仅仅是配置信息,Default.ini,FolderData.ini文件都不需要)拷贝到新的配置目录下的Sessions文件夹下即可,这种重新打开SecureCRT就会看到之前的配置了。

Config目录查看:Options -> Global Options… -> General 其中 Configuration folder就是Config目录了

Win10更新后VirtualBox启动虚拟机报错

发表于 2018-04-09 | 分类于 技能

Win10更新重启后导致VirtualBox无法正常启动虚拟机,提示“不能为虚拟电脑打开一个新任务”,错误码(0x80004005)。解决办法参考:VirtualBox相关问题处理纪录

go开发环境搭建

发表于 2018-03-25 | 分类于 技能

随着区块链技术的火热,作为以太坊的主要开发语言的go也随之更加的火热起来,接下来就简单记录一下go开发环境的搭建:

1,首先就是下载安装包:
下载地址:https://golang.org/dl/
也可以使用这个地址:https://golang.google.cn/dl/。
我的安装环境是mac,安装很简单,不需要下载源码,直接下载pkg包,然后直接安装即可。
macOS下默认安装到:/usr/local/go

2,环境变量的配置:
sudo vi /etc/profile
添加如下内容:

1
2
3
#go
export GOROOT=/usr/local/go
export PATH=$PATH:/$GOROOT/bin

保存后,使之生效:
1
source /etc/profile

验证:查看go版本
1
go version

3,编写HelloWord
创建test.go文件,编辑内容如下:
1
2
3
4
5
6
7
package main

import "fmt"

func main(){
fmt.Println("let's go!");
}

保存完毕后,打开终端输入:go run test.go
将输入:let’s go!

4,idea安装go插件
开发当然少不了ide,由于java开发的习惯,倾向于使用idea,go的插件在线安装通常都是连接失败,需要手动下载和安装,详见:Intellij Idea安装go插件

DELETE不能使用别名?是我不会用

发表于 2018-03-20 | 分类于 技能

今天碰到一个sql问题,就是在delete中加了别名,导致报错了:”[Err] 1064 - You have an error in your SQL syntax; …”

简单说下过程,本来是一个简单的delete语句:

1
2
delete from table1 
where status=2;

后需要增加关联条件,所以在后边追加了where条件,为了关联写着方便为表添加了别名,变为:
1
2
3
delete from table1 a 
where a.status=2
and EXISTS (select b.id from table2 b where b.fid=a.id);

就是这样报错了,提示语法错误,还觉得挺纳闷,将delete 换成 select * (通常为了省事,验证sql的时候换成select),没有问题,执行正确。

百度很多说“mysql delete 不能使用别名”的,去掉别名后果然正常:

1
2
3
delete from table1 
where status=2
and EXISTS (select id from table2 where table2.fid=table1.id);

虽然问题解决了,但是更纳闷了,delete不能用别名?!,当然不是,是我用错了!
1
2
3
delete a from table1 a 
where a.status=2
and EXISTS (select b.id from table2 b where b.fid=a.id);

如上,delete使用别名的时候,要在delete和from间加上删除表的别名,这样才是正确的写法。
(MySQL DELETE的语法详见 , Oracle没有这种要求)。

MyBatis插件执行顺序问题

发表于 2018-03-14 | 分类于 技能

之前因为觉得spring cache的使用比较麻烦,所以弄了两个简单的MyBatisCache自动缓存插件 ,在测试过程中,PageHelper插件的版本变化引出了插件执行顺序的问题:
起因:PageHelper v4.x和v5.x在实现上进行了改变,PageHelper主要是拦截Executor的query方法,为select语句添加物理分页语句,问题就出在query方法上,query方法有两个:

1
2
1,<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
2,<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;

两个方法参数不一样,其中第一个方法是被第二个方法座位内部调用,所以一般mybatis的插件对于Executer的query拦截都是拦截的第二个方法,包括PageHelper在v5之前也都是这么拦截的,所以在通常情况下插件执行顺序是这样的:
比如插件配置如下:
1
2
3
4
5
6
7
<property name="plugins">
<array>
<bean class="xxx.xxx.Interceptor1"/>
<bean class="xxx.xxx.Interceptor2"/>
<bean class="xxx.xxx.Interceptor3"/>
</array>
</property>

如,配置了三个插件,三个插件的拦截配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
//Interceptor1:
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
//Interceptor2:
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
//Interceptor3:
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})

三个插件的都是针对Executor类的四个参数的query方法进行拦截,这种情况下,拦截器的加载顺序是1、2、3,但是在interceptorChain.pluginAll()方法的层层代理处理后,拦截器的执行顺序变成了:
3拦截前处理 > 2拦截前处理 > 1拦截前处理 > executor.query() > 1拦截后处理 > 2拦截后处理 > 3拦截后处理

这个顺序在使用过多个拦截器的人应该比较清楚,具体的原理就不多说了,以上是通常情况,但是在PageHelperV5对拦截方法进行变动,他的拦截处理后,跳过了Executor的四个参数query方法的调用,直接调用6个参数的query方法,这样就会导致多个插件执行顺序上的问题:

接着按照上边的例子说,将Interceptor2换成Interceptor2.1:

1
2
3
4
5
6
7
<property name="plugins">
<array>
<bean class="xxx.xxx.Interceptor1"/>
<bean class="xxx.xxx.Interceptor2.1"/>
<bean class="xxx.xxx.Interceptor3"/>
</array>
</property>

执行顺序变成了:
1
3 > 2.1 > 1 executor.query() > 1 > 2.1 > 3

但是1根本就不会执行,实际的执行顺序是:
1
3 > 2.1 > executor.query(6参数) > 2.1 > 3

因为从2.1之后executor的四个参数的方法被跳过了,直接执行了6参数的query,所以Interceptor1没有拦截到,这就是问题所在。
对于PageHelperV5打破”拦截秩序“的问题,作者也做了说明,QueryInterceptor规范 ,针对Interceptor1的问题,PageHelperV5作者给出的解决办法:
1,修改Interceptor1的拦截策略,同时拦截4个和6个参数的query方法,这样就不再受“打破秩序者”的干扰;
2,让“打破秩序者”最后执行,调整Interceptor1拦截器的配置顺序,放到Interceptor2.1的后边,变成:

1
2
3
4
5
6
7
<property name="plugins">
<array>
<bean class="xxx.xxx.Interceptor2.1"/>
<bean class="xxx.xxx.Interceptor1"/>
<bean class="xxx.xxx.Interceptor3"/>
</array>
</property>

PageHelperV5的这种改变面上看主要是可以直接获得boundSql等对象,不用再次转换,其他的改变还没有看,希望经验者多多指教!

说说RESTFUL中的方法:GET、POST、PUT、PATCH、DELETE、OPTIONS、HEAD、TRACE

发表于 2018-03-13 | 分类于 技能

目前互联网公司的应用架构基本都是前后端分离,后端的接口也基本上都是采用restful架构了,接下来就说说restful的使用。
使用restful架构最主要的是遵循rest的思想:“统一资源接口“。
REST全称:Representational State Transfer,翻译成中文就是“表述性状态转移”,表述的对象就是资源,在web的rertful架构中都是通过uri来一一对应资源,比如:/api/person/1。
URI既可以看成是资源的地址,也可以看成是资源的名称,代表的就是唯一的资源,但是不能表示对资源的操作,操作是结合标准的http方法(get、post、put等)来实现的。

下面说下restful的http方法有哪些:
GET、HEAD、POST、PUT、DELETE、OPTIONS、TRACE、PATCH
根据RFC2616第九章说明,http方法的定义有两点:safe and Idempotent,即安全性和幂等性,可以结合这两点对以上方法进行说明

1,GET
安全、幂等;
用于获取资源;

2,HEAD
安全、幂等;
与get方法类似,但不返回message body内容,仅仅是获得获取资源的部分信息(content-type、content-length);
restful框架中较少使用

3,POST
非安全、非幂等;
用于创建子资源

4,PUT
非安全、幂等;
用于创建、更新资源;

5,DELETE
非安全、幂等;
删除资源;

6,OPTIONS
安全、幂等;
用于url验证,验证接口服务是否正常;

7,TEACE
安全、幂等;
维基百科“回显服务器收到的请求,这样客户端可以看到(如果有)哪一些改变或者添加已经被中间服务器实现。”
restful框架中较少使用

8,PATCH
非安全、幂等;
用于创建、更新资源,于PUT类似,区别在于PATCH代表部分更新;
后来提出的接口方法,使用时可能去要验证客户端和服务端是否支持;

接下来说一下日常中的使用:

1,post和put的区别:
post和put的区别在于uri,或者说post用于创建子资源,比如接口:POST /api/person/ 会创建一个资源比如 /api/person/1或者/api/person/2 … 或者/api/person/n,创建了新的uri,而put方法创建资源的uri是 PUT /api/person/1,这样就创建了一个资源,如果1已经存在那么就是更新,所以put并不是只是更新操作。再有post是非幂等的。
通常情况下,我们都会将post、get、put、delete对应到CRUD操作上,但实际上put并不是只能更新。

2,patch的使用:
patch是2010后成为的正式http方法,详见RFC5789,它是对put的补充,在没有patch之前,我们都是用put进行更新操作,这时候我们的接口中通常会有一个逻辑规则,如:如果对象的的一个字符属性为NULL,那么就是不更新该属性(字段)值,如果对象的字符属性是“”,那么就更新该属性(字段)的值,通过这种方式来避免全部覆盖的操作。现在有了patch就解决了这种判断,在put接口中不管属性是不是null,都进行更新,在patch接口中就对非null的进行更新;

3,uri的使用问题
上边也介绍过了,uri即使代表资源的,通过不同的方法来区分操作,那么像如下的接口就已经违反了restful规范:
GET /api/getPerson/1
DELETE /api/delPerson/1
GET /api/person/get/1
DELETE /api/person/delete/1
在复合规范的前提下,uri的定义应该也是实际使用中应该考虑的,比如uri包涵那些信息?如版本、资源分类、资源名称、表述格式等,对于设计上的不多说了,直接看下面的url:
/api/1.0/person/man/1.xml
/api/2.0/person/man/1.json
这样的url很常见也很直观,对不同版本接口增加了版本信息,并且对数据的表述格式进行了显式指定,不是不好,但是按照“统一资源接口”的思想,资源的uri已经不唯一了。
有说对于版本号,表述形式等可以放到http的accept中进行指定,但具体没有验证过,希望经验人士多多指教!

4,查询问题的讨论:
按照rest建议,查询操作要使用get方法,但是实际情况中处理起来比较麻烦,如:报表统计查询,需要传递的参数很多,就SpingMVC来说,如果采用get方法,那么@RequestParam接收的参数非常多,接口很难看,通常会封装为java对象,希望通过@RqeustBody接收并处理,但这是不支持get方法,所以很蛋疼;
对于这种情况,最简单的方式就是改成post方式,而且很多公司都是这么干的,但又觉得违反了restful规范;不改成post方式的话可能就需要将传递的参数对象细腻转为json串,后端字符串接收后再转为对象,这样感觉耶不太好,url中显式输出参数信息,个别情况json串太长活着包含特殊字符等也都很麻烦。
希望经验人士多多指教!

初五.2018

发表于 2018-03-04 | 分类于 生活

@房山- 北京

12
桂斌

桂斌

希望世界和平

14 日志
4 分类
32 标签
© 2018 桂斌