自定义获取ip和地址的接口
现存的获取ip的方法很多,但是有好多会不定时停掉,偶尔会请求不到
所以自己定义一个ip请求接口,放在本地服务器,以供本地请求调用
思路是:通过纯真获取ip数据库文件txt文件,然后将该文件导入到数据库中,然后新增两个字段,将这个文件的两个ip换成long,然后通过传入的ip来判断是否在这个之间,来获取地址
1、通过纯真ip工具获取ip地址库(5天左右更新一次库),txt文件
工具
链接:https://pan.baidu.com/s/1LK9r72KTpY8vIYIEhf5y2g
提取码:i5ei
复制这段内容后打开百度网盘手机App,操作更方便哦
傻瓜式安装,然后解压
然后你会获取到一个这样的txt文件
本人用的是mysql,导入文本到数据库需要按照一定的格式,所以这里有两个工具类来将这个文本转化一下格式,因为这个是导入不进去的
2、处理txt文件,导入数据库
上述txt文件中空格的个数不等,有多个,我们只需要每个字段后面保留一个,只需要四个字段
我的思路是将所有的空格替换成一个;号,然后将第4个;后面的;替换成空格,(由于读写文件有异常,目前本人无法提供更好的方法解决,只能分两步,如果有更好的方法还望各位不吝赐教)
package com.myiptest.utils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 由于纯真获取ip生成的txt文件不够标准,不能直接导入到数据库,
*
* 所以需要将所有的空格替换成统一的字符 ;
*
* 然后在把第三个以后的; 替换成空
* @author Administrator
*
*/
public class FileUtil {
/**
* 替换所有的空格为 ;
*/
public static void aaa() {
String regEx = "[' ']+"; // 一个或多个空格
Pattern p = Pattern.compile(regEx);
try {
String encoding = "UTF8"; // 字符编码(可解决中文乱码问题 )
File file = new File("C:/Users/Administrator/Desktop/aaa.txt");
if (file.isFile() && file.exists()) {
InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
BufferedReader bufferedReader = new BufferedReader(read);
FileOutputStream out = null;
out = new FileOutputStream(new File("C:/Users/Administrator/Desktop/bbb.txt"));
String lineTXT = null;
int count = 0;
while ((lineTXT = bufferedReader.readLine()) != null) {
count += 1;
Matcher m = p.matcher(lineTXT);
String str = m.replaceAll(";").trim();
System.out.println(str.substring(0, str.length()));
out.write((str.substring(0, str.length())+"\r\n").getBytes());
}
read.close();
out.close();
} else {
System.out.println("找不到指定的文件!");
}
} catch (Exception e) {
System.out.println("读取文件内容操作出错");
e.printStackTrace();
}
}
/**
* 替换第三个之后的; 为 空格
* @param string
* @return
*/
public static void changeTo(){
String regEx = ";"; // 一个或多个空格
Pattern p = Pattern.compile(regEx);
try {
String encoding = "UTF8"; // 字符编码(可解决中文乱码问题 )
File file = new File("C:/Users/Administrator/Desktop/data2.txt");
if (file.isFile() && file.exists()) {
InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
BufferedReader bufferedReader = new BufferedReader(read);
FileOutputStream out = null;
out = new FileOutputStream(new File("C:/Users/Administrator/Desktop/data3.txt"));
String lineTXT = null;
while ((lineTXT = bufferedReader.readLine()) != null) {
//这里是获取";"符号的位置
Matcher m = p.matcher(lineTXT);
int mIdx = 0;
while(m.find()) {
mIdx++;
//当"/"符号第次出现的位置
if(mIdx == 4){
break;
}
}
if (mIdx >= 4) {
int index = m.start();
System.out.println(index);
String string = lineTXT.substring(0, index);
String replace = lineTXT.substring(index).replace(";", "");
String newText = new StringBuffer(string).append(replace).toString();
System.out.println(newText);
out.write((newText+"\r\n").getBytes());
}else {
out.write((lineTXT+"\r\n").getBytes());
}
}
read.close();
out.close();
} else {
System.out.println("找不到指定的文件!");
}
} catch (Exception e) {
System.out.println("读取文件内容操作出错");
e.printStackTrace();
}
}
/**
* 获取第n次出现的 ; 的位置
* @param string
* @param num
* @return
*/
public static int getCharacterPosition(String string,int num){
//这里是获取"/"符号的位置
Matcher slashMatcher = Pattern.compile(";").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == num){
break;
}
}
return slashMatcher.start();
}
/**
* 将IP换成int数(这里会出现pauseInt异常,未找到原因,所以暂时只能使用数据库修改)
*/
public static void changeIpToNumber(){
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(
"C:/Users/Administrator/Desktop/test.txt"));
bw = new BufferedWriter(
new FileWriter(
"C:/Users/Administrator/Desktop/test2.txt"));
String lineString = null;
int i = 0;
while (true) {
i++;
// BufferedReader 的readline 方法,直接读取一行数据
lineString = br.readLine();
if (lineString == null) {
break;
} else {
int first = FileUtil.getCharacterPosition(lineString, 1);
int second = FileUtil.getCharacterPosition(lineString, 2);
String ip = lineString.substring(0, first);
String address = lineString.substring(first+1,second);
long ip2int = IPUtil.ip2int(ip);
long ip2int2 = IPUtil.ip2int(address);
lineString = lineString + ";"+ip2int+";"+ip2int2;
bw.write(lineString); // 写入一行数据
bw.newLine(); // 另起一行
System.out.println(lineString);
}
}
} catch (Exception e) {
System.out.println(e);
} finally {
try {
bw.close();
br.close();
} catch (IOException e) {
System.out.println(e);
}
}
}
public static void main(String[] args) {
changeIpToNumber();
}
}
替换成功后生成一个有规律的txt文件,使用Navicat工具导入
具体导入方法传送门
导入成功之后的数据库
这里附送整理好的原文件
链接:https://pan.baidu.com/s/1fyO_fEaveWBtuQUtJIejxQ
提取码:sv7v
复制这段内容后打开百度网盘手机App,操作更方便哦
3、开始代码
项目框架为springboot项目,这里只贴部分代码
目录结构
pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test.getip</groupId>
<artifactId>getIp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.1</thymeleaf-layout-dialect.version>
<poi.version>3.13</poi.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- aop依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!-- 通用mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.1.5</version>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid数据源驱动 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<phase>package</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
<configurationFile>src/main/resources/config/mybatis-generator.xml</configurationFile>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<finalName>getip</finalName>
</build>
</project>
yml
server:
port: 8089
tomcat:
uri-encoding: utf-8
spring:
datasource:
# 数据库访问配置, 使用druid数据源
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ipaddress?useUnicode=true&characterEncoding=utf8
username: root
password: 123456
# 连接池配置
initial-size: 5
min-idle: 5
max-active: 20
# 连接等待超时时间
max-wait: 30000
# 配置检测可以关闭的空闲连接间隔时间
time-between-eviction-runs-millis: 60000
# 配置连接在池中的最小生存时间
min-evictable-idle-time-millis: 300000
validation-query: select '1' from dual
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
max-open-prepared-statements: 20
max-pool-prepared-statement-per-connection-size: 20
# 配置监控统计拦截的filters, 去掉后监控界面sql无法统计, 'wall'用于防火墙
filters: stat
# Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔
aop-patterns: com.myiptest.service.*
# WebStatFilter配置
web-stat-filter:
enabled: true
# 添加过滤规则
url-pattern: /*
# 忽略过滤的格式
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
thymeleaf:
cache: false
aop:
proxy-target-class: true
mybatis:
config-location: classpath:config/mybatis-config.xml
# type-aliases扫描路径
type-aliases-package: com.myiptest.domain
# mapper xml实现扫描路径
mapper-locations: classpath:mapper/*.xml
property:
order: BEFORE
#mappers 多个接口时逗号隔开
mapper:
mappers: com.myiptest.common.MyMapper
not-empty: false
identity: MYSQL
order: after
logging:
level:
com:
myiptest:
dao: DEBUG
controller
package com.myiptest.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.myiptest.domain.Ip;
import com.myiptest.service.IpService;
import com.myiptest.utils.IPUtil;
import com.myiptest.utils.ReturnDatas;
@Controller
public class IPController {
@Autowired
private IpService service;
/**
* 返回首页
* @param model
* @param response
* @return
*/
@RequestMapping("/")
public String index(Model model, HttpServletResponse response) {
return "index";
}
/**
* 获取本机ip
* @param request
* @return
*/
@GetMapping("/getLocalAddr")
public @ResponseBody ReturnDatas getLocalAddr(HttpServletRequest request){
ReturnDatas data = ReturnDatas.getSuccessReturnDatas();
String ip = IPUtil.getIP(request);
System.out.println("ip = "+ip);
String address = service.getAddress2(ip);
Ip ip2 = new Ip();
ip2.setIp(ip);
ip2.setAddress(address);
data.setData(ip2);
return data;
}
/**
* 查询ip
*/
@GetMapping("/getAddr")
public @ResponseBody ReturnDatas getIpAddr(HttpServletRequest request){
ReturnDatas data = ReturnDatas.getSuccessReturnDatas();
String ip = request.getParameter("ip");
System.out.println("ip = "+ip);
String address = service.getAddress2(ip);
Ip ip2 = new Ip();
ip2.setIp(ip);
ip2.setAddress(address);
data.setData(ip2);
return data;
}
@RequestMapping("/test")
public @ResponseBody String update(Model model, HttpServletResponse response) {
service.updateAll();
return "success";
}
}
service
这里需要说明一下,在获取到的ip地址并不是一对一的,是一个区段,在某个区段是某一个地方的,所以这里用的递归将一个ip反复从数据库比对,(当然算法学的好的朋友可以用字符串比对算法)
比如:47.101.25.111
首先会查47.101.25.111,查不到会再次执行该方法 查47.101.25,然后查不到查47.101
如果输入的是192.168开头会返回局域网,如果查到最后还是没查到,返回没有值
package com.myiptest.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.myiptest.common.BaseService;
import com.myiptest.dao.IpMapper;
import com.myiptest.domain.Ip;
import com.myiptest.service.IpService;
import com.myiptest.utils.IPUtil;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;
@Service
public class IpServcieImpl extends BaseService<Ip> implements IpService{
@Autowired
private IpMapper mapper;
/*
*没用
*/
@Override
public String getAddress(String ip) {
String s = null;
Example example = new Example(Ip.class);
Criteria criteria = example.createCriteria();
criteria.andLike("ip", ip+"%");
List<Ip> ipaddrs = this.mapper.selectByExample(example);
//如果相似查询没查到 就将ip最后一位去除,再次查找
if (ipaddrs.size() == 0) {
//返回局域网
if(ip.equals("192.168")){
s = "局域网";
}else{
if(!ip.contains(".")){
s = "没有对应的地址";
}else{
String substring = ip.substring(0,ip.lastIndexOf('.'));
if (s == null) {
s = getAddress(substring);
}
}
}
}else{
//如果查到,就获取第一个的ip的地址
Ip ipaddr = ipaddrs.get(0);
if (ipaddr != null) {
s = ipaddr.getCity()+" "+ipaddr.getAddress();
}
}
return s;
}
public String getAddress2(String ip) {
Ip ipaddr = this.mapper.selectByIp(IPUtil.ip2int(ip));
return ipaddr.getCity()+" "+ipaddr.getAddress();
}
@Override
public List<Ip> selectAll() {
return this.mapper.selectAll();
}
@Override
public Ip selectByKey(Object key) {
return null;
}
@Override
public int save(Ip entity) {
return 0;
}
@Override
public int delete(Object key) {
return 0;
}
@Override
public int batchDelete(List<String> list, String property, Class<Ip> clazz) {
return 0;
}
@Override
public int updateAll(Ip entity) {
return 0;
}
@Override
public int updateNotNull(Ip entity) {
return 0;
}
@Override
public List<Ip> selectByExample(Object example) {
return null;
}
@Override
public void updateAll() {
List<Ip> selectAll = this.selectAll();
for (int i = 0; i < selectAll.size(); i++) {
Ip ip = selectAll.get(i);
ip.setIpint(IPUtil.ip2int(ip.getIp()));
ip.setIpaddressint(IPUtil.ip2int(ip.getIpaddress()));
this.mapper.updateByIp(ip);
}
}
}
打包
执行clean package
然后执行该jar即可,这里代码比较简单,就不做详细介绍
源码传送门(没积分的可以私聊我)
项目成功后首选将数据库中新增两个字段
然后 xxx:端口号/test
请求一下,将所有数据的这两行填充数据
或者直接导入我的
链接:https://pan.baidu.com/s/1MiNdFAtYAjNZDKGBGBXevQ
提取码:qvij
复制这段内容后打开百度网盘手机App,操作更方便哦
成功页面
致此,感谢您的观看。