IP段转CIDR

经常使用nginx、apache时候需要对某个ip段进行白名单或黑名单控制,而它的配置是以CIDR的方式进行的,所以此工具可以方便的做到从IP段到CIDR的转换。

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
import java.util.ArrayList;
import java.util.List;

public class Ip2Cidr {


public static void main(String[] args) {
System.out.println(range2cidrlist("10.104.0.12","10.104.0.35"));
}

public static List<String> range2cidrlist(String startIp, String endIp) {
long start = ipToLong(startIp);
long end = ipToLong(endIp);

ArrayList<String> pairs = new ArrayList<String>();
while (end >= start) {
byte maxsize = 32;
while (maxsize > 0) {
long mask = CIDR2MASK[maxsize - 1];
long maskedBase = start & mask;

if (maskedBase != start) {
break;
}

maxsize--;
}
double x = Math.log(end - start + 1) / Math.log(2);
byte maxdiff = (byte) (32 - Math.floor(x));
if (maxsize < maxdiff) {
maxsize = maxdiff;
}
String ip = longToIP(start);
pairs.add(ip + "/" + maxsize);
start += Math.pow(2, (32 - maxsize));
}
return pairs;
}

public static final int[] CIDR2MASK = new int[] { 0x00000000, 0x80000000,
0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000,
0xFE000000, 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000, 0xFFFFF800,
0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0,
0xFFFFFFE0, 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
0xFFFFFFFF };

private static long ipToLong(String strIP) {
long[] ip = new long[4];
String[] ipSec = strIP.split("\\.");
for (int k = 0; k < 4; k++) {
ip[k] = Long.valueOf(ipSec[k]);
}

return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
}

private static String longToIP(long longIP) {
StringBuffer sb = new StringBuffer("");
sb.append(String.valueOf(longIP >>> 24));
sb.append(".");
sb.append(String.valueOf((longIP & 0x00FFFFFF) >>> 16));
sb.append(".");
sb.append(String.valueOf((longIP & 0x0000FFFF) >>> 8));
sb.append(".");
sb.append(String.valueOf(longIP & 0x000000FF));

return sb.toString();
}
}

阅读全文

RPM查询用法(转)

转自:http://blog.csdn.net/fengyifei11228/article/details/6526149

命令格式: rpm {-q|–query} [select-options] [query-options]   

对系统中已安装软件的查询

  1. 查询系统已安装的软件
    语法:rpm -q 软件名
    举例:[root@localhost beinan]# rpm -q gaim
    gaim-1.3.0-1.fc4   

  2. 查看系统中所有已经安装的包,要加 -a 参数
    [root@localhost RPMS]# rpm -qa
    如果分页查看,再加一个管道 |和more命令;

    [root@localhost RPMS]# rpm -qa |more
    在所有已经安装的软件包中查找某个软件,比如说 gaim ;可以用 grep 抽取出来;

    [root@localhost RPMS]# rpm -qa |grep gaim
    上面这条的功能和 rpm -q gaim 输出的结果是一样的

  3. 查询一个已经安装的文件属于哪个软件包
    语法 rpm -qf 文件名
    注:文件名所在的绝对路径要指出
    举例:
    [root@localhost RPMS]# rpm -qf /usr/lib/libacl.la
    libacl-devel-2.2.23-8

  4. 查询已安装软件包都安装到何处
    语法:rpm -ql 软件名 或 rpm rpmquery -ql 软件名
    举例:
    [root@localhost RPMS]# rpm -ql lynx
    [root@localhost RPMS]# rpmquery -ql lynx

  5. 查询一个已安装软件包的信息
    语法格式: rpm -qi 软件名
    举例:
    [root@localhost RPMS]# rpm -qi lynx

  6. 查看一下已安装软件的配置文件
    语法格式:rpm -qc 软件名
    举例:
    [root@localhost RPMS]# rpm -qc lynx

  7. 查看一个已经安装软件的文档安装位置
    语法格式: rpm -qd 软件名
    举例:
    [root@localhost RPMS]# rpm -qd lynx

  8. 查看一下已安装软件所依赖的软件包及文件
    语法格式: rpm -qR 软件名
    举例:
    [root@localhost beinan]# rpm -qR rpm-python

总结:对于一个软件包已经安装,我们可以把一系列的参数组合起来用
比如 rpm -qil
[root@localhost RPMS]# rpm -qil lynx

阅读全文

Mybatis Invalid bound statement (not found)问题分析

今天又因为精心大意犯一个错,而且以前也已经遇到过,但是没有进行总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Caused by: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.xxx.xxx.monitor.mapper.XXXXMapper.loadAllServices
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:189) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:43) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:58) ~[mybatis-3.2.7.jar:3.2.7]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:51) ~[mybatis-3.2.7.jar:3.2.7]
at com.sun.proxy.$Proxy35.loadAllServices(Unknown Source) ~[na:na]
...
...
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_79]
at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_79]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:354) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:305) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
... 74 common frames omitted

查了好多网上资料,其实都没有说到我这个问题的根本上。

后来分析了好一大阵后才发现是maven编译时的配置出问题,加上下面这个配置就好了。

阅读全文

Fastjson的一个BUG

项目中使用的fastjson版本为:1.1.41,今天突然在重启线上服务器后莫名出现异常,而这个异常以前重来没有出现过,这个异常类似这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
com.alibaba.fastjson.JSONException: write javaBean error
at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:212) ~[fastjson-1.1.41.jar:na]
at Serializer_6.write1(Unknown Source) ~[na:na]
at Serializer_6.write(Unknown Source) ~[na:na]
at com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:369) ~[fastjson-1.1.41.jar:na]
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:418) ~[fastjson-1.1.41.jar:na]
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:568) ~[fastjson-1.1.41.jar:na]
...
...
...
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_79]
Caused by: java.lang.ClassCastException: com.google.common.collect.Lists$TransformingSequentialList cannot be cast to com.xxx.common.dto.pager.PagerData
at Serializer_9.write1(Unknown Source) ~[na:na]
at Serializer_9.write(Unknown Source) ~[na:na]
at com.alibaba.fastjson.serializer.ObjectFieldSerializer.writeValue(ObjectFieldSerializer.java:115) ~[fastjson-1.1.41.jar:na]
at com.alibaba.fastjson.serializer.ObjectFieldSerializer.writeProperty(ObjectFieldSerializer.java:68) ~[fastjson-1.1.41.jar:na]
at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:194) ~[fastjson-1.1.41.jar:na]
... 66 common frames omitted

百思不得其解,因为我返回的对象中根本就没有com.xxx.common.dto.pager.PagerData 这个对象信息,为什么在序列化的时候会出现这个错误呢,非常怪异。让人十分摸不着头脑的是这个错误是重启服务器后发生。毕竟线上一直在报错,当时情急之下的解决办法试了两个方法:

  1. 再次重启服务器
    重新启动服务器几次,错误依然,仅仅一次代码的小调整(根本和报错的问题风马牛不相及),但是启动服务器就报这个错,给跪了!
  2. 赶紧找其它json类库暂时替代
    json框架毕竟我还是熟悉几个的,情急下只能仓促使用Gson(google出品的json框架)临时替代了fastjson的json序列化输出,问题解决!!!

阅读全文

关于Guava类库中Lists.transform的问题解析

这里讲述是的google的Guava类库中的一个需要注意的问题,如下:

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
public class GuavaListTest {

public static class TestDO {
private String name;
private int age;
private String description;

public TestDO(String name, int age, String description) {
this.name = name;
this.age = age;
this.description = description;
}

public TestDO() {
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}
}

public static class TestDTO {
private String name;
private int age;
private String description;

public TestDTO(String name, int age, String description) {
this.name = name;
this.age = age;
this.description = description;
}

public TestDTO() {
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}
}

public static void main(String[] args) {

List<TestDTO> retList = query();

System.out.println(JSON.toJSONString(retList,true));


}

private static List<TestDTO> query() {
List<TestDO> queryList = ImmutableList.of(
new TestDO("test1", 18, "test obj1"),
new TestDO("test2", 19, "test obj2"),
new TestDO("test3", 20, "test obj3")
);

List<TestDTO> retList = Lists.transform(queryList, new Function<TestDO, TestDTO>() {
@Override
public TestDTO apply(TestDO input) {
return DTOUtils.createAndCopy(TestDTO.class, input);
}
});

//此处是见证神奇的地方
for(TestDTO dto : retList){
dto.setAge(dto.getAge()+1);
}
return retList;
}

}

这段代码的输出是什么?

阅读全文

KMP字符串搜索算法

一篇介绍KMP字符串搜索算法的好文章:http://kb.cnblogs.com/page/176818/

阅读全文

SVN版本控制系统分支的用法及分析

SVN是一种软件开发中非常流行的源代码版本控制工具软件,它能保存你每一次的源代码提交历史,便于我们对源码的历史做追溯,这样的好处是:

  • 可以浏览软件源代码版本的演化历史以及回滚相关历史版本代码
  • 分支系统优秀,可以多人进行协作开发
  • 管理方便,逻辑明确,符合一般人思维习惯。
  • 易于管理,集中式服务器更能保证代码安全性。
  • 代码一致性非常高。

SVN适合开发人数不多的项目开发。大部分软件配置管理的大学教材都是使用SVN系统。

其中SVN的分支功能可以说是SVN源代码控制系统的核心功能。根据trunk分支的功用不同我将分支的使用方式分为两类:

  • 以trunk作为稳定发布分支(Basically stable)
  • 以trunk作为开发分支(Basically unstable)

以trunk作为稳定发布分支
以trunk作为稳定发布分支

顾名思义这个分支原则主导思想是trunk只包含稳定的随时可发布的代码。branches则用于开发新功能/修正bug/发布前的QA控制/重构/实验性质功能试点。一切未经测试验证的代码都禁止向trunk提交。
这个是我从参加工作以来历届公司的开发方式,什么是以trunk作为稳定发布分支?这里我们从第一份的源代码说起,第一份源代码我们提交到SVN上的trunk上,并进行开发,开发完结后我们发布第一个版本,我们称之为第一个稳定版本,在第一个稳定版本完成后,以后所有的开发都不会在trunk上进行提交,什么意思呢?假如这时有一个新需求到来,那么就从主干trunk上提取一份代码(术语叫分支)到另一分支目录(一般分支目录取名branches),建立自己的开发分支,测试也是在分支上完成功能测试。待要发布时才将分支代码合并到主干上。因为主干trunk上的代码从一开始到每次迭代都是非常稳定的,所以这种方式叫以trunk为稳定发布分支的开发方式。每当开发完成某项功能,并达到发布标准且分支源代码已经合并到trunk分支后,我们就会以当前的trunk打出一个标签(tag),标识一个稳定的版本(里程碑)。

这种开发方式的优点是:

  • trunk代码非常稳定,始终存在一个功能稳定的分支可用
  • 代码开发的并行度非常高
  • 代码之间的抗干扰非常强

缺点是:

  • 可能会存在较多分支(一般以某个功能或某几个功能作为一个功能分支开发)
  • 代码发布前需要合并到trunk,可能会产生代码冲突,需要人工合并

目前大部分的互联网公司的源代码分支开发方式都是采用的这种方式。

阅读全文

关于apache http转发后后端应用获取前端port问题

apache+jetty转发配置下,jetty下应用获取request.getServerPort()获取到的是jetty的端口,而非apache入口的端口,情形如下:

apache通过配置虚拟主机:

1
2
3
4
5
6
<VirtualHost *:80>
ServerName "admin.test.com"
ProxyRequests Off
ProxyPass / http://localhost:6808/
ProxyPassReverse / http://localhost:6808/
</VirtualHost>

在80端口接受外界访问,然后转发到端口6808上。

阅读全文

Nginx负载均衡重定向问题

当负载端口不是80时,发现所有 response.sendRedirect() 重定向的页面都返回80端口,后来发现是代理设置Header时没有指定Ngnix监听的负载端口

#设置被代理服务器的端口或套接字,以及URL

1
proxy_set_header Host $host:6112;

阅读全文

tomcat/jetty容器之间的路径兼容性问题

在项目中使用springmvc框架时,在controller方法中返回的view路径字符串最后和xml文件配置中的配置路径进行整合,从而形成一个完成的视图文件路径,然后在tomcat和jetty身上两者之间的差异出现问题:

1
2
3
4
5
<bean id="internalViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/view/jsp"
p:suffix=".jsp"
p:order="1"/>

阅读全文