IP归属地查询项目

一、项目介绍

1.背景

根据IP得到位置,加标签
进行大数据分析,比如淘宝推荐等提供优质数据

www.ip.cn 等 查询IP

2.需求

IP 分析 归属地信息 , 查找在毫秒内完成

IP地址库,公网都是开放的

IANA : 国际组织,负责公网IP维护分发

3.技术栈

Eclipse ,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装

4.目标

通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力:
1 面向对象程序设计
2 工具类封装与使用写法
3 文件IO流
4 字符串处理
5 二分法查找
6 IP地址的不同形式的使用

二、相关问题

强化项目思维

不管好方法还是差方法,先尝试把功能实现

再考虑对代码进行优化,最优为止

三、主要思路

1 解析提供的地址库字符串,为结构化数据格式
2 基于结构化数据构建成某个数据结构,加速给定IP地址的查找速度
3 封装成响应的工具类API,开放其响应的方法,即给定IP地址可以再ms内计算得到其位置信息
4 工具类只有一个入参一个出参 入参是IP 出参是地址

四、研发项目分类

1.应用开发类项目

解决某些特定功能而开发的应用软件,比如QQ,微信,Eclipse等

2.Web开发类项目

以B/S架构为主,也就是网页形式访问的在线系统,如各类官网等

3.中小型应用类开发项目的流程

1 需求概述 : 需求描述,说清楚你要干什么,为什么做这个
在互联网公司中,根据IP地址获取归属地信息是非常广泛的,开发的这个项目就能解决这个问题

2 需求分析 : 需要根据需求概述,用技术角度来看一下这个项目是否可行
可行性一定是可以做的
需求分析的梳理
三方面 : 输入,输出,已具备的物料(前置条件)
输入 : 给定任意一个IP地址
输出 : 返回IP对应的归属地
前置条件 :
IP地址库
JavaSE
面向对象
IO
常用类
二分法
正则表达式校验

3 开发步骤拆分,可以理解为解耦,把一个拆分为多个
        1 读取IP地址库
        2 解析IP地址每行数据,进行结构化
                找到无结构化数据的规则,进行结构化处理
                简单来说,就是根据需求,生成实体类        
                        Entity/model : 实体类,一般该类和数据库表是一一对应的
                        DTO : 先不管
                        Pojo : 无特殊意义,纯粹的业务对象
        3 把对象加入List中
        4 转换为数组,方便二分法操作
                为什么不直接转换为数组?
                        数组长度问题,不清楚有多少行,有多少空行等
                ArrayList转数组,不会消耗很多时间,因为底层就是数组
        5 解决二分法查找的技术问题
        6 完成比较逻辑
        7 对外提供访问接口
        8 测试

4 细节开发与风险控制

5 BUG修复,调优,标准化

6 正式上线

7 项目总结,项目复盘

五、代码研发

1.无脑读取文件

在test文件夹下 创建 TestFileIO_01.java

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;

/**
 * 1 定义文件路径
 * 
 * 2 通过节点流对接到文本上
 * 
 * 3 将节点流转换为字符流
 * 
 * 4 通过缓冲流对接到输入流
 * 
 * 5 读取
 * 
 * 6 关闭流
 * 
 */
public class TestFileIO_01 {
	public static void main(String[] args) {
		// 地址库文件
		String ipLibrartPath = "ip_location_relation.txt";
		// 字符编码
		String encoding = "utf-8";
		try (
		// 字节流
		FileInputStream fis = new FileInputStream(ipLibrartPath);
				// 转换为字符流
				Reader reader = new InputStreamReader(fis, encoding);
				// 封装缓冲流
				BufferedReader br = new BufferedReader(reader);) {
			String temp = null;
			while ((temp = br.readLine()) != null) {
				System.out.println(temp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

2.文本文件读取工具类

工具类封装 :
1 先写测试类,确认输入与输出技术问题
2 抽象出了输入与输出,形成方法的入参和出参
3 工具代码实现,测试

2.1 工具类

package util;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

/**
 * 读取文件
 * 
 */
public class FileOperatorUtil {

	/**
	 * 读取文件,并返回List
	 * 
	 * @param txtFilePath
	 *            字符串格式的文件路径
	 * @param encoding
	 *            字符编码
	 * @return
	 * @throws IOException
	 */
	public static List<String> getLineList(String txtFilePath, String encoding)
			throws IOException {
		List<String> lineLine = new ArrayList<String>();
		// 字节流
		FileInputStream fis = new FileInputStream(txtFilePath);
		// 转换为字符流
		Reader reader = new InputStreamReader(fis, encoding);
		// 封装缓冲流
		BufferedReader br = new BufferedReader(reader);
		String temp = null;
		while ((temp = br.readLine()) != null) {
			lineLine.add(temp);
		}
		// 关闭资源
		br.close();
		return lineLine;
	}
}

2.2 测试工具类

import java.io.IOException;
import java.util.List;

import util.FileOperatorUtil;

/**
 * 测试工具类
 */
public class TestFileIO_02 {
	public static void main(String[] args) throws IOException {
		// 地址库文件
		String ipLibrartPath = "ip_location_relation.txt";
		// 字符编码
		String encoding = "utf-8";
		List<String> lineList = FileOperatorUtil.getLineList(ipLibrartPath,
				encoding);
		for (String string : lineList) {
			System.out.println(string);
		}
	}
}

3.数据结构化

1 可以找无结构化数据的组织规则,进行抽象,转换为结构化
2 根据数据组织进行数据抽象
3 解析数据,保存到对应的对象中
Model,pojo,dto

4.抽象pojo类

4.1 抽象封装

package pojo;

/**
 * 结构化实体类
 * 
 */
public class IPAndLocationPojo {
	
	@Override
	public String toString() {
		return "IPAndLocationPojo [startIP=" + startIP + ", endIP=" + endIP
				+ ", location=" + location + "]";
	}

	/**
	 * 起始IP
	 */
	private String startIP;
	/**
	 * 结束IP
	 */
	private String endIP;
	/**
	 * 归属地
	 */
	private String location;

	public String getStartIP() {
		return startIP;
	}

	public void setStartIP(String startIP) {
		this.startIP = startIP;
	}

	public String getEndIP() {
		return endIP;
	}

	public void setEndIP(String endIP) {
		this.endIP = endIP;
	}

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}

	public IPAndLocationPojo(String startIP, String endIP, String location) {
		super();
		this.startIP = startIP;
		this.endIP = endIP;
		this.location = location;
	}

	public IPAndLocationPojo() {
		super();
	}

}

4.2 数据拆分,转换为对象

package com;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import pojo.IPAndLocationPojo;
import util.FileOperatorUtil;

/**
 * 转换为结构化对象
 * 
 */
public class TestNonStructToStruct_01 {
	public static void main(String[] args) throws IOException {

		// 地址库文件
		String ipLibrartPath = "ip_location_relation.txt";
		// 字符编码
		String encoding = "utf-8";
		List<String> lineList = FileOperatorUtil.getLineList(ipLibrartPath,
				encoding);
		List<IPAndLocationPojo> ipAndLocationPojos = new ArrayList<IPAndLocationPojo>();
		// 遍历 获取每一行
		for (String string : lineList) {
			if (string == null || string.trim().equals("")) {
				continue;
			}
			// 以\t分割,得到三个列
			String[] columnArray = string.split("\t");
			// 创建结构化对象
			IPAndLocationPojo ipAndLocationPojo = new IPAndLocationPojo(
					columnArray[0], columnArray[1], columnArray[2]);
			// 保存到集合中
			ipAndLocationPojos.add(ipAndLocationPojo);
		}

		// 遍历集合
		for (IPAndLocationPojo ipAndLocationPojo : ipAndLocationPojos) {
			System.out.println(ipAndLocationPojo);
		}
	}
}

5.封装DataProcessManager类

5.1 把数据封装到对象中并保存list里面

package manager;

import pojo.IPAndLocationPojo;
import util.FileOperatorUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 该类为项目中管理类
 * 
 */
public class DataProcessManager {
	/**
	 * 把读取到的List<String> 转换为 List<IPAndLocationPojo>
	 * 
	 * @param ipLibrartPath
	 * @param encoding
	 * @return
	 * @throws IOException
	 */
	public static List<IPAndLocationPojo> getPojoList(String ipLibrartPath,
			String encoding) throws IOException {
		List<String> lineList = FileOperatorUtil.getLineList(ipLibrartPath,
				encoding);
		List<IPAndLocationPojo> ipAndLocationPojos = new ArrayList<IPAndLocationPojo>();
		// 遍历 获取每一行
		for (String string : lineList) {
			if (string == null || string.trim().equals("")) {
				continue;
			}
			// 以\t分割,得到三个列
			String[] columnArray = string.split("\t");
			// 创建结构化对象
			IPAndLocationPojo ipAndLocationPojo = new IPAndLocationPojo(
					columnArray[0], columnArray[1], columnArray[2]);
			// 保存到集合中
			ipAndLocationPojos.add(ipAndLocationPojo);
		}
		return ipAndLocationPojos;
	}
}

5.2 测试

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import cmanager.DataProcessManager;
import pojo.IPAndLocationPojo;
import util.FileOperatorUtil;

/**
 * 转换为结构化对象
 * 
 */
public class TestNonStructToStruct_02 {
	public static void main(String[] args) throws IOException {

		// 地址库文件
		String ipLibrartPath = "ip_location_relation.txt";
		// 字符编码
		String encoding = "utf-8";
		List<IPAndLocationPojo> ipAndLocationPojos = DataProcessManager.getPojoList(ipLibrartPath, encoding);
		for (IPAndLocationPojo ipAndLocationPojo : ipAndLocationPojos) {
			System.err.println(ipAndLocationPojo);
		}
	}
}

6.数据化集合转换为数组

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import manager.DataProcessManager;
import pojo.IPAndLocationPojo;

public class TestListToArray_01 {
	public static void main(String[] args) throws IOException {
		List<String> list = new ArrayList<String>();
		list.add("a");
		list.add("
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值