IP归属地在线查询平台-2

BUG优化

用户输入 需要严格校验,比如IP地址不正确,还有必要去查询吗?

技术问题

正则表达式

Pattern和Matcher

Pattern是正则表达式引擎

Matcher是匹配器

Matches : 全词匹配

Find : 任意位置

lookingAt : 从前往后匹配

package com;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class TestRegex_01 {

public static void main(String[] args) {

String regex = "\\d{11}";

String tel = "131131131121";

// 创建引擎

Pattern pattern = Pattern.compile(regex);

// 创建匹配器

Matcher matcher = pattern.matcher(tel);

// System.out.println(matcher.matches());

// System.out.println(matcher.find());

System.out.println(matcher.lookingAt());

tel = "我的电话是13113113111";

regex = "我的电话是(\\d{11})";

pattern = Pattern.compile(regex);

matcher = pattern.matcher(tel);

matcher.find();

System.out.println(matcher.group(1));

}

}

封装工具类

package com.tledu.zrz.util;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

/**

 * 正则表达式工具类

 *

 * @author 天亮教育-帅气多汁你泽哥

 * @Date 2021年11月12日 上午9:37:50

 */

public class RegexUtil {

/**

 * 格式验证

 *

 * @param regex

 * @param input

 * @return

 */

public static boolean isValid(String regex, String input) {

Pattern pattern = Pattern.compile(regex);

// 创建匹配器

Matcher matcher = pattern.matcher(input);

return matcher.matches();

}

/**

 * 数据提取

 *

 * @param regex

 * @param input

 * @param groupIndex

 * @return

 */

public static String getMatchContent(String regex, String input,

int groupIndex) {

Pattern pattern = Pattern.compile(regex);

// 创建匹配器

Matcher matcher = pattern.matcher(input);

if (matcher.find()) {

return matcher.group(groupIndex);

}

return null;

}

public static String getMatchContent(String regex, String input) {

return getMatchContent(regex, input, 0);

}

}

测试工具类

package com;

import com.tledu.zrz.util.RegexUtil;

public class TestRegex_02 {

public static void main(String[] args) {

String regex = "\\d{11}";

String tel = "13113113111";

System.out.println(RegexUtil.isValid(regex, tel));

tel = "我的电话是13113113111";

regex = "我的电话是(\\d{11})";

System.out.println(RegexUtil.getMatchContent(regex, tel,1));

}

}

业务问题

package com.tledu.zrz.util;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

/**

 * 正则表达式工具类

 *

 * @author 天亮教育-帅气多汁你泽哥

 * @Date 2021年11月12日 上午9:37:50

 */

public class RegexUtil {

private static String regexIP = "((25[0-5]|2[0-4]\\d|[1]{1}\\d{1}\\d{1}|[1-9]{1}\\d{1}|\\d{1})($|(?!\\.$)\\.)){4}";

/**

 * 校验IP

 * @param ip

 * @return

 */

public static boolean isValidIP(String ip) {

return isValid(regexIP, ip);

}

/**

 * 格式验证

 *

 * @param regex

 * @param input

 * @return

 */

public static boolean isValid(String regex, String input) {

Pattern pattern = Pattern.compile(regex);

// 创建匹配器

Matcher matcher = pattern.matcher(input);

return matcher.matches();

}

/**

 * 数据提取

 *

 * @param regex

 * @param input

 * @param groupIndex

 * @return

 */

public static String getMatchContent(String regex, String input,

int groupIndex) {

Pattern pattern = Pattern.compile(regex);

// 创建匹配器

Matcher matcher = pattern.matcher(input);

if (matcher.find()) {

return matcher.group(groupIndex);

}

return null;

}

public static String getMatchContent(String regex, String input) {

return getMatchContent(regex, input, 0);

}

}

测试

package com;

import com.tledu.zrz.util.RegexUtil;

public class TestRegex_03 {

public static void main(String[] args) {

String ip = "1.1.322.5";

System.out.println(RegexUtil.isValidIP(ip));

}

}

应用

校验应该写在对外提供的接口处

getLocation

IP归属地在线查询平台-2

性能调优

硬件

内存,CPU.磁盘,网络等 都可以实现性能提高

软件

​​​​​​​直接调优

 

哪里慢,就调哪里,不需要花里胡哨的

主要指算法问题,内核层面,难度较大,大部分都是非直接调优

​​​​​​​迂回调优

通过设计,策略,可以通过不用面对底层优化的难题

​​​​​​​迂回调优方向

缓存策略

通过添加时间断点,测试得出,结构化耗时较多

IP归属地在线查询平台-2

一开始,我们一次运行中,先后校验两个IP,需要结构化两次

后来我们使用静态语句块解决了这个问题

做到一次生命周期中,只会结构化一次

现在面临的问题是,需要让多次生命周期,使用同一个结构化之后的对象,就可以解决当前的问题

可以使用序列化和反序列化解决

序列化 : 将内存中对象保存到硬盘中

反序列化 : 把硬盘中对象载入到内存

被序列化的对象必须实现serlizable接口

封装工具类

package com.tledu.zrz.util;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

public class SerDeUtil {

/**

 * 写入

 *

 * @param obj

 * @param objFilePath

 * @throws IOException

 */

public static void saveObject(Object obj, String objFilePath)

throws IOException {

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(

objFilePath));

oos.writeObject(obj);

oos.close();

}

/**

 * 读取

 *

 * @param objFilePath

 * @return

 * @throws ClassNotFoundException

 * @throws IOException

 */

public static Object getObj(String objFilePath)

throws ClassNotFoundException, IOException {

ObjectInputStream ois = new ObjectInputStream(new FileInputStream(

objFilePath));

Object o = ois.readObject();

return o;

}

}

初始化优化

​​​​​​​

只有第一次才序列化,其余的都反序列化即可

判断该文件是否存在,如果存在,就反序列化获取,如果不存在,就序列化写出

注意

public class IPAndLocationPojo implements Serializable,

Comparable<IPAndLocationPojo> {

package com.tledu.zrz.manager;

import com.tledu.zrz.pojo.IPAndLocationPojo;

import com.tledu.zrz.util.FileOperatorUtil;

import com.tledu.zrz.util.IPUtil;

import com.tledu.zrz.util.RegexUtil;

import com.tledu.zrz.util.SerDeUtil;

import java.io.File;

import java.io.IOException;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

/**

 * 该类为项目中管理类

 *

 * @author 天亮教育-帅气多汁你泽哥

 * @Date 2021年11月11日 上午11:45:19

 */

public class DataProcessManager {

private static IPAndLocationPojo[] ipLocationPojoArr = null;

static {

// 地址库文件

String ipLibrartPath = "ip_location_relation.txt";

// 字符编码

String encoding = "utf-8";

// 文件地址

String serde_obj_filepath = "ipLibObj.data";

// 判断序列化文件是否存在

boolean isInit = new File(serde_obj_filepath).exists();

// 存在就反序列化获取

if (isInit) {

try {

Object object = SerDeUtil.getObj(serde_obj_filepath);

ipLocationPojoArr = (IPAndLocationPojo[]) object;

} catch (ClassNotFoundException | IOException e) {

e.printStackTrace();

}

}else{

// 不存在就序列化写出

// 获取数据

List<IPAndLocationPojo> ipAndLocationPojos = null;

try {

ipAndLocationPojos = DataProcessManager.getPojoList(ipLibrartPath,

encoding);

} catch (IOException e) {

e.printStackTrace();

}

// 转换为数组

ipLocationPojoArr = DataProcessManager

.convertListToArrayAndSort(ipAndLocationPojos);

try {

SerDeUtil.saveObject(ipLocationPojoArr, serde_obj_filepath);

} catch (IOException e) {

e.printStackTrace();

}

}

}

/**

 * 对外提供的接口,入参IP出参地址

 *

 * @param ip

 * @return

 */

public static String getLocation(String ip) {

if (RegexUtil.isValidIP(ip)) {

int index = DataProcessManager.binaraySearch(ipLocationPojoArr, ip);

return index == -1 ? "未找到" : ipLocationPojoArr[index].getLocation();

}else{

return "IP地址格式不正确,请重新输入";

}

}

/**

 * 业务类对应的二分法

 *

 * @param ipLocationPojoArr

 *            数组

 * @param ip

 *            ip

 * @return 索引

 */

public static int binaraySearch(IPAndLocationPojo[] ipLocationPojoArr,

String ip) {

// 转换为long类型

long ipLong = IPUtil.ipToLong(ip);

int startIndex = 0;

int endIndex = ipLocationPojoArr.length - 1;

int m = (endIndex + startIndex) / 2;

while (startIndex <= endIndex) {

// 大于等于起始 小于等于结束 说明找到了

// 小于起始 在前半截

// 大于结束 在后半截

if (ipLong > ipLocationPojoArr[m].getEndIPLong()) {

startIndex = m + 1;

} else if (ipLong < ipLocationPojoArr[m].getStartIPLong()) {

endIndex = m - 1;

} else {

return m;

}

m = (startIndex + endIndex) / 2;

}

return -1;

}

/**

 * 将对象集合转换为对象数组并排序

 *

 * @param pojoList

 * @return

 */

public static IPAndLocationPojo[] convertListToArrayAndSort(

List<IPAndLocationPojo> pojoList) {

// 转换为数组

IPAndLocationPojo[] ipLocationPojoArr = new IPAndLocationPojo[pojoList

.size()];

pojoList.toArray(ipLocationPojoArr);

// 排序

Arrays.sort(ipLocationPojoArr);

return ipLocationPojoArr;

}

/**

 * 把读取到的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;

}

}

​​​​​​​引入缓冲流

​​​​​​​

package com.tledu.zrz.util;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

public class SerDeUtil {

/**

 * 对象写出,引入缓冲流

 *

 * @param obj

 * @param objFilePath

 * @param cacheByyeArrayLength

 * @throws IOException

 */

public static void saveObject(Object obj, String objFilePath,

int cacheByyeArrayLength) throws IOException {

FileOutputStream fos = new FileOutputStream(objFilePath);

// 字节数组缓冲流

ByteArrayOutputStream baos = new ByteArrayOutputStream(

cacheByyeArrayLength);

ObjectOutputStream oos = new ObjectOutputStream(baos);

oos.writeObject(obj);

byte[] bytes = baos.toByteArray();

fos.write(bytes);

oos.close();

fos.close();

}

/**

 * 获取,引入缓冲流

 *

 * @param objFilePath

 * @param cacheByyeArrayLength

 * @return

 * @throws ClassNotFoundException

 * @throws IOException

 */

public static Object getObj(String objFilePath, int cacheByyeArrayLength)

throws ClassNotFoundException, IOException {

FileInputStream fis = new FileInputStream(objFilePath);

byte[] bytes = new byte[cacheByyeArrayLength];

fis.read(bytes);

fis.close();

ByteArrayInputStream bais = new ByteArrayInputStream(bytes);

ObjectInputStream ois = new ObjectInputStream(bais);

Object o = ois.readObject();

ois.close();

return o;

}

/**

 * 写入

 *

 * @param obj

 * @param objFilePath

 * @throws IOException

 */

public static void saveObject(Object obj, String objFilePath)

throws IOException {

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(

objFilePath));

oos.writeObject(obj);

oos.close();

}

/**

 * 读取

 *

 * @param objFilePath

 * @return

 * @throws ClassNotFoundException

 * @throws IOException

 */

public static Object getObj(String objFilePath)

throws ClassNotFoundException, IOException {

ObjectInputStream ois = new ObjectInputStream(new FileInputStream(

objFilePath));

Object o = ois.readObject();

ois.close();

return o;

}

}​​​​​​​

StaticValue

package com.tledu.zrz.util;

public class StaticValue {

// 地址库文件

public static String ipLibrartPath = "ip_location_relation.txt";

// 字符编码

public static  String encoding = "utf-8";

// 文件地址

public static  String serde_obj_filepath = "ipLibObj.data";

// 根据文件大小,计算长度

public static  int cacheByteArrayLength = 40*1024*1024;

}

 

上一篇:Java学习笔记4


下一篇:C++基础-正则表达式 regex_match(匹配) regex_search(查找) regex_replace(替换)