好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

JAVA使用Ip2region获取IP定位信息的操作方法

ip2region - 准确率99.9%的离线IP地址定位库,0.0x毫秒级查询

ip2region - 是国内开发者开发的离线IP地址定位库,针对国内IP效果较好,国外的部分IP只能显示国家。

项目gitee地址:

?

1

https://gitee测试数据/lionsoul/ip2region.git

先安装依赖

?

1

2

3

4

5

< dependency >

     < groupId >org.lionsoul</ groupId >

     < artifactId >ip2region</ artifactId >

     < version >1.7.2</ version >

</ dependency >

下载离线IP定位库

离线数据库在项目的data文件夹下,名称为 ip2region.db ,其他2个文件是用于生成离线库的,可不用下载。

?

1

https://gitee测试数据/lionsoul/ip2region/blob/master/data/ip2region.db

下载到离线数据库后,我们需要读取这个数据库,我们可以放在项目的 resources 目录,但是我不建议这样做,这样打包的jar会变得很大,部署时麻烦。

我们指定一个绝对路径,这个部署的时候也不用每次上传,这个数据库一般不会修改,如果数据库更新了,单独上传即可。

因为我们项目使用阿里云oss,服务器也在阿里云,所以我就把数据库存到oss中,阿里云内网读取还是很快的,这样免得我修改地址,更新数据库我也只需要在本地上传到oss即可。

下面我们定义类封装ip2region

记录映射实体 IpInfo.java

该类用于接受解析后的数据,我们也可以使用map来接收,我这里就使用模型来组装数据。

类使用 lombok ,如果不喜欢的自行修改为普通类。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

import lombok.Data;

/**

  * 域名信息.

  *

  * @author https://HdhCmsTestcnblogs测试数据/lixingwu

  * @date 2022-05-24 15:07:47

  */

@Data

public class IpInfo {

     /*** 国家 */

     private String country;

     /*** 地区 */

     private String region;

     /*** 省 */

     private String province;

     /*** 市 */

     private String city;

     /*** 运营商 */

     private String isp;

}

ip解析工具类 Ip2regionAnalysis.java

该类主要用于加载数据库和解析IP信息,然后把查询的结果组装为IpInfo的;

这个类我使用了使用单例模式(双重校验锁DCL)进行编写,在构造函数里加载IP数据库,这样数据库就只会加载一遍。

类中还用到了工具包 hutool ,需要自行引入,具体操作自行百度。

?

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

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

import cn.hutool.core.collection.CollUtil;

import cn.hutool.core.io.IoUtil;

import cn.hutool.core.io.StreamProgress;

import cn.hutool.core.lang.Dict;

import cn.hutool.core.net.NetUtil;

import cn.hutool.core.util.NumberUtil;

import cn.hutool.core.util.StrUtil;

import cn.hutool.http.HttpUtil;

import com.yunding.vote.domain.IpInfo;

import lombok.extern.slf4j.Slf4j;

import org.lionsoul.ip2region.DataBlock;

import org.lionsoul.ip2region.DbConfig;

import org.lionsoul.ip2region.DbMakerConfigException;

import org.lionsoul.ip2region.DbSearcher;

import javax.servlet.http.HttpServletRequest;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.util.HashSet;

import java.util.Optional;

/**

  * 使用单例模式(双重校验锁DCL)

  *

  * @author https://HdhCmsTestcnblogs测试数据/lixingwu

  * @date 2022-05-24 10:45:42

  */

@Slf4j

public class Ip2regionAnalysis {

     private volatile static Ip2regionAnalysis analysis;

     /**

      * TODO 这个数据库地址,改成自己的,不要用这地址啊,这个需要登录才能下载

      * ip数据库地址

      */

     public static final String IP_REGION_DB_URL = "https://gitee测试数据/lionsoul/ip2region/raw/master/data/ip2region.db" ;

     /**

      * ip数据库字节

      */

     private final byte [] dbBinStr;

     /**

      * 初始化,下载ip数据库文件转为为文件输出流

      */

     private Ip2regionAnalysis() {

         // 下载IP数据库文件

         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

         HttpUtil.download(IP_REGION_DB_URL, outputStream, false , new StreamProgress() {

             @Override

             public void start() {

                 log.info( "下载IP数据库文件..." );

             }

             @Override

             public void progress( long progressSize) {

             }

             @Override

             public void finish() {

                 double fileSize = NumberUtil.div(outputStream.size(), ( 1024 * 1024 ), 2 );

                 log.info( "IP数据库文件下载成功,数据库文件大小[{}MB]" , fileSize);

             }

         });

         dbBinStr = outputStream.toByteArray();

         IoUtil.close(outputStream);

     }

     /**

      * 获取IP解析单例

      *

      * @return Ip2regionAnalysis

      */

     public static Ip2regionAnalysis getInstance() {

         if (analysis == null ) {

             synchronized (Ip2regionAnalysis. class ) {

                 if (analysis == null ) {

                     analysis = new Ip2regionAnalysis();

                 }

             }

         }

         return analysis;

     }

     /**

      * <p>方法名称:解析Ip信息.</p>

      * <p>详细描述:.</p>

      * <p>创建时间:2022-05-24 11:26:59</p>

      * <p>创建作者:lixingwu</p>

      * <p>修改记录:</p>

      *

      * @param ip IP地址

      * @return 国家|区域|省份|城市|ISP

      */

     public Optional<String> getIpInfo(String ip) {

         if (IpAddressUtil.validIp(ip)) {

             try {

                 DbConfig config = new DbConfig();

                 DbSearcher searcher = new DbSearcher(config, dbBinStr);

                 // 搜索数据

                 DataBlock search = searcher.memorySearch(ip);

                 // 数据格式:国家|区域|省份|城市|ISP

                 return Optional.of(search.getRegion());

             } catch (DbMakerConfigException | IOException e) {

                 e.printStackTrace();

                 log.error( "Ip解析失败:{}" , e.toString());

             }

         }

         return Optional.empty();

     }

     /**

      * <p>方法名称:解析Ip信息.</p>

      * <p>详细描述:.</p>

      * <p>创建时间:2022-05-24 11:26:59</p>

      * <p>创建作者:lixingwu</p>

      * <p>修改记录:</p>

      *

      * @param ips IP地址集合

      * @return Dict({ ip : info })

      */

     public Dict getIpInfo(HashSet<String> ips) {

         try {

             DbConfig config = new DbConfig();

             DbSearcher searcher = new DbSearcher(config, dbBinStr);

             DataBlock search;

             Dict dataset = Dict.create();

             for (String ip : ips) {

                 if (IpAddressUtil.validIp(ip)) {

                     search = searcher.memorySearch(ip);

                     dataset.set(ip, search.getRegion());

                 }

             }

             return dataset;

         } catch (DbMakerConfigException | IOException e) {

             e.printStackTrace();

             log.error( "Ip解析失败:{}" , e.toString());

         }

         return Dict.create();

     }

     /**

      * <p>方法名称:数字ip获取信息.</p>

      * <p>详细描述:.</p>

      * <p>创建时间:2022-05-24 13:15:23</p>

      * <p>创建作者:lixingwu</p>

      * <p>修改记录:</p>

      *

      * @param ip 数字IP

      * @return 国家|区域|省份|城市|ISP

      */

     public Optional<String> getIpInfo( long ip) {

         String longIpv4 = NetUtil.longToIpv4(ip);

         return getIpInfo(longIpv4);

     }

     /**

      * <p>方法名称:获取请求对象的IP信息.</p>

      * <p>详细描述:.</p>

      * <p>创建时间:2022-05-24 11:50:59</p>

      * <p>创建作者:lixingwu</p>

      * <p>修改记录:</p>

      *

      * @param request 请求对象

      * @return 国家|区域|省份|城市|ISP

      */

     public Optional<String> getIpInfo(HttpServletRequest request) {

         String ip = IpAddressUtil.getIpAddr(request);

         return getIpInfo(ip);

     }

     /**

      * <p>方法名称:获取IP信息的字典.</p>

      * <p>详细描述:.</p>

      * <p>创建时间:2022-05-24 11:52:58</p>

      * <p>创建作者:lixingwu</p>

      * <p>修改记录:</p>

      *

      * @param ip IP地址

      * @return the dict

      */

     public IpInfo getIpInfoBean(String ip) {

         Optional<String> ipInfo = getIpInfo(ip);

         IpInfo info = new IpInfo();

         if (ipInfo.isPresent()) {

             //国家|区域|省份|城市|ISP

             String[] split = StrUtil.split(ipInfo.get(), "|" );

             info.setCountry(split[ 0 ]);

             info.setRegion(split[ 1 ]);

             info.setProvince(split[ 2 ]);

             info.setCity(split[ 3 ]);

             info.setIsp(split[ 4 ]);

         }

         return info;

     }

     /**

      * <p>方法名称:数字ip获取信息字典.</p>

      * <p>详细描述:.</p>

      * <p>创建时间:2022-05-24 13:15:23</p>

      * <p>创建作者:lixingwu</p>

      * <p>修改记录:</p>

      *

      * @param ip 数字IP

      * @return 国家|区域|省份|城市|ISP

      */

     public IpInfo getIpInfoBean( long ip) {

         String longIpv4 = NetUtil.longToIpv4(ip);

         return getIpInfoBean(longIpv4);

     }

     /**

      * <p>方法名称:获取IP信息的字典.</p>

      * <p>详细描述:.</p>

      * <p>创建时间:2022-05-24 11:52:58</p>

      * <p>创建作者:lixingwu</p>

      * <p>修改记录:</p>

      *

      * @param request 请求对象

      * @return the dict

      */

     public IpInfo getIpInfoBean(HttpServletRequest request) {

         String ip = IpAddressUtil.getIpAddr(request);

         return getIpInfoBean(ip);

     }

     /**

      * 测试

      */

     public static void main(String[] args) {

         log.info( "121.8.215.106 \t {}" , Ip2regionAnalysis.getInstance().getIpInfoBean( "121.8.215.106" ));

         log.info( "183.247.152.98 \t {}" , Ip2regionAnalysis.getInstance().getIpInfoBean( "183.247.152.98" ));

         log.info( "14.29.139.251 \t {}" , Ip2regionAnalysis.getInstance().getIpInfoBean( "14.29.139.251" ));

         log.info( "183.247.152.98 \t {}" , Ip2regionAnalysis.getInstance().getIpInfoBean( "183.247.152.98" ));

         log.info( "27.105.130.93 \t {}" , Ip2regionAnalysis.getInstance().getIpInfoBean( "27.105.130.93" ));

         log.info( "124.205.155.147 \t {}" , Ip2regionAnalysis.getInstance().getIpInfoBean( "124.205.155.147" ));

         // 批量解析,返回字典数据:ip:解析信息

         final HashSet<String> ipSet = CollUtil.newHashSet(

                 "47.92.113.71" , "221.226.75.86" , "124.205.155.155" ,

                 "47.57.188.208" , "121.8.215.106" , "121.8.215.106"

         );

         Dict dict = Ip2regionAnalysis.getInstance().getIpInfo(ipSet);

         log.info( "{}" , dict.toString());

         log.info( "{}\t{}" , "121.8.215.106" , dict.getStr( "121.8.215.106" ));

     }

}

测试输出

14:19:12.791 [main] DEBUG cn.hutool.log.LogFactory - Use [Slf4j] Logger As Default.
14:19:14.150 [main] INFO util.Ip2regionAnalysis - 下载IP数据库文件...
14:19:14.633 [main] INFO util.Ip2regionAnalysis - IP数据库文件下载成功,数据库文件大小[8.33MB]
14:19:14.645 [main] INFO util.Ip2regionAnalysis - 121.8.215.106      IpInfo(country=中国, region=0, province=广东省, city=广州市, isp=电信)
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 183.247.152.98      IpInfo(country=中国, region=0, province=浙江省, city=杭州市, isp=移动)
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 14.29.139.251      IpInfo(country=中国, region=0, province=广东省, city=深圳市, isp=电信)
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 183.247.152.98      IpInfo(country=中国, region=0, province=浙江省, city=杭州市, isp=移动)
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 27.105.130.93      IpInfo(country=中国, region=0, province=台湾省, city=台北, isp=So-Net)
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 124.205.155.147      IpInfo(country=中国, region=0, province=北京, city=北京市, isp=鹏博士)
14:19:14.648 [main] INFO util.Ip2regionAnalysis - {221.226.75.86=中国|0|江苏省|南京市|电信, 47.57.188.208=中国|0|香港|0|阿里云, 47.92.113.71=中国|0|河北省|张家口市|阿里云, 121.8.215.106=中国|0|广东省|广州市|电信, 124.205.155.155=中国|0|北京|北京市|鹏博士}
14:19:14.682 [main] INFO util.Ip2regionAnalysis - 121.8.215.106    中国|0|广东省|广州市|电信

在第一次调用getInstance时会去下载数据库文件会比较耗时,其他后面的操作就很快了,基本上几毫秒就查询到了。

所以如果嫌第一次慢的,可以在程序启动完成后手动调用,预热一下,在实际业务就会使用缓存的数据库了。

实际使用

在项目中我编写了一个 CommonController.java ,然后使用编写的类提供了一个接口,用于获取IP的信息。

?

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

import cn.hutool.extra.servlet.ServletUtil;

import com.yunding.vote测试数据mon.api.CommonResult;

import com.yunding.vote测试数据mon.limiter.RInterfaceLimit;

import com.yunding.vote.domain.IpInfo;

import com.yunding.vote.util.Ip2regionAnalysis;

import io.swagger.annotations.Api;

import io.swagger.annotations.ApiOperation;

import lombok.extern.slf4j.Slf4j;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

import javax.servlet.http.HttpServletRequest;

/**

  * 公共控制层,该类方法不会记录日志

  */

@RestController

@Api (tags = "公共控制层" , description = "公共控制层" )

@RequestMapping ( "/common" )

@Slf4j

public class CommonController {

     @Resource

     private HttpServletRequest request;

     @ApiOperation ( "获取IP的信息,100QPS" )

     @GetMapping (value = "/ipInfo/{ip}" )

     @RInterfaceLimit (rate = 100 )

     public CommonResult<IpInfo> getIpInfo( @PathVariable String ip) {

         String clientIp = ServletUtil.getClientIP(request);

         IpInfo ipInfo = Ip2regionAnalysis.getInstance().getIpInfoBean(ip);

         return CommonResult.success(ipInfo);

     }

}

上面这个类只是告诉大家是怎么使用 Ip2regionAnalysis 这个类的,大家根据自己的项目自行调整。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

GET http: //127.0.0.1:8080/api/v1/common/ipInfo/121.8.215.106

 

>>>

{

   "code" : 200 ,

   "data" : {

     "country" : "中国" ,

     "region" : 0 ,

     "province" : "广东省" ,

     "city" : "广州市" ,

     "isp" : "电信"

   },

   "message" : "操作成功"

}

到此这篇关于JAVA使用Ip2region获取IP定位信息的文章就介绍到这了,更多相关java获取IP定位信息内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

原文链接:https://HdhCmsTestcnblogs测试数据/lixingwu/p/16317568.html

查看更多关于JAVA使用Ip2region获取IP定位信息的操作方法的详细内容...

  阅读:14次