How Spring Boot quickly implements IP address resolution
Introduction:
If you use local ip resolution, we will use ip2region. This project maintains a more detailed local ip address correspondence table. If you want to use it in an offline environment, you need to import this project. Depend on, and specify the version, the methods of different versions may be different.
<!-- ip库--> <dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>2.6.3</version> </dependency>
Development:
You need to download the xdb file to the project file directory when using it. Even if you use ip2region to query completely based on the xdb file, the response time of a single query is at the level of ten microseconds. , memory accelerated query can be enabled in the following two ways:
vIndex index cache: Use a fixed 512KiB memory space to cache vector index data, reduce one IO disk operation, and maintain average query efficiency Stable between 10-20 microseconds.
xdb entire file cache: Load the entire xdb file into memory. The memory usage is equal to the size of the xdb file. There is no disk IO operation and microsecond-level query efficiency is maintained.
/** * ip查询 */ @Slf4j public class IPUtil { private static final String UNKNOWN = "unknown"; protected IPUtil(){ } /** * 获取 IP地址 * 使用 Nginx等反向代理软件, 则不能通过 request.getRemoteAddr()获取 IP地址 * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址, * X-Forwarded-For中第一个非 unknown的有效IP字符串,则为真实IP地址 */ public static String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; } public static String getAddr(String ip){ String dbPath = "src/main/resources/ip2region/ip2region.xdb"; // 1、从 dbPath 加载整个 xdb 到内存。 byte[] cBuff; try { cBuff = Searcher.loadContentFromFile(dbPath); } catch (Exception e) { log.info("failed to load content from `%s`: %s\n", dbPath, e); return null; } // 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。 Searcher searcher; try { searcher = Searcher.newWithBuffer(cBuff); } catch (Exception e) { log.info("failed to create content cached searcher: %s\n", e); return null; } // 3、查询 try { String region = searcher.searchByStr(ip); return region; } catch (Exception e) { log.info("failed to search(%s): %s\n", ip, e); } return null; }
Here we encapsulate ip resolution into a tool class, including two methods of obtaining IP and ip address resolution. The ip resolution can be obtained in the request. After obtaining the IP, you need to find the resolution of the corresponding IP address in xdb based on the IP. Since the local database may have certain deficiencies, some IPs cannot be resolved.
Online analysis:
If you want to obtain more comprehensive IP address information, you can use the online database. What is provided here is the IP analysis of whois.pconline.com. The IP analysis is in my The performance is very smooth during use, and only a few IPs cannot be resolved.
@Slf4j public class AddressUtils { // IP地址查询 public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; // 未知地址 public static final String UNKNOWN = "XX XX"; public static String getRealAddressByIP(String ip) { String address = UNKNOWN; // 内网不查询 if (IpUtils.internalIp(ip)) { return "内网IP"; } if (true) { try { String rspStr = sendGet(IP_URL, "ip=" + ip + "&json=true" ,"GBK"); if (StrUtil.isEmpty(rspStr)) { log.error("获取地理位置异常 {}" , ip); return UNKNOWN; } JSONObject obj = JSONObject.parseObject(rspStr); String region = obj.getString("pro"); String city = obj.getString("city"); return String.format("%s %s" , region, city); } catch (Exception e) { log.error("获取地理位置异常 {}" , ip); } } return address; } public static String sendGet(String url, String param, String contentType) { StringBuilder result = new StringBuilder(); BufferedReader in = null; try { String urlNameString = url + "?" + param; log.info("sendGet - {}" , urlNameString); URL realUrl = new URL(urlNameString); URLConnection connection = realUrl.openConnection(); connection.setRequestProperty("accept" , "*/*"); connection.setRequestProperty("connection" , "Keep-Alive"); connection.setRequestProperty("user-agent" , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); connection.connect(); in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); String line; while ((line = in.readLine()) != null) { result.append(line); } log.info("recv - {}" , result); } catch (ConnectException e) { log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); } catch (SocketTimeoutException e) { log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); } catch (IOException e) { log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); } catch (Exception e) { log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); } finally { try { if (in != null) { in.close(); } } catch (Exception ex) { log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); } } return result.toString(); } }
Scenario:
So in what process of development is it more appropriate to obtain the IP address? Our interceptor will be used here. Intercept every request that enters the service, perform pre-operations, and complete the parsing of the request header, IP acquisition, and IP address resolution when entering, so that the IP address and other information can be reused in all subsequent processes.
/** * 对ip 进行限制,防止IP大量请求 */ @Slf4j @Configuration public class IpUrlLimitInterceptor implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) { //更新全局变量 Constant.IP = IPUtil.getIpAddr(httpServletRequest); Constant.IP_ADDR = AddressUtils.getRealAddressByIP(Constant.IP); Constant.URL = httpServletRequest.getRequestURI(); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) { //通过本地获取 // 获得ip // String ip = IPUtil.getIpAddr(httpServletRequest); //解析具体地址 // String addr = IPUtil.getAddr(ip); //通过在线库获取 // String ip = IpUtils.getIpAddr(httpServletRequest); // String ipaddr = AddressUtils.getRealAddressByIP(ipAddr); // log.info("IP >> {},Address >> {}",ip,ipaddr); } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { } }
如果想要执行我们的ip 解析拦截器,需要在spring boot的视图层进行拦截才会触发我们的拦截器。
@Configuration public class WebConfig implements WebMvcConfigurer { @Autowired IpUrlLimitInterceptor ipUrlLimitInterceptor; //执行ip拦截器 @Override public void addInterceptors(InterceptorRegistry registry){ registry.addInterceptor(ipUrlLimitInterceptor) // 拦截所有请求 .addPathPatterns("/**"); } }
通过这样的一套流程下来,我们就能实现对每一个请求进行ip 获取、ip解析,为每个请求带上具体ip地址的小尾巴。
The above is the detailed content of How Spring Boot quickly implements IP address resolution. For more information, please follow other related articles on the PHP Chinese website!

Start Spring using IntelliJIDEAUltimate version...

When using MyBatis-Plus or other ORM frameworks for database operations, it is often necessary to construct query conditions based on the attribute name of the entity class. If you manually every time...

Java...

How does the Redis caching solution realize the requirements of product ranking list? During the development process, we often need to deal with the requirements of rankings, such as displaying a...

Conversion of Java Objects and Arrays: In-depth discussion of the risks and correct methods of cast type conversion Many Java beginners will encounter the conversion of an object into an array...

Solutions to convert names to numbers to implement sorting In many application scenarios, users may need to sort in groups, especially in one...

Detailed explanation of the design of SKU and SPU tables on e-commerce platforms This article will discuss the database design issues of SKU and SPU in e-commerce platforms, especially how to deal with user-defined sales...

How to set the SpringBoot project default run configuration list in Idea using IntelliJ...


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Dreamweaver CS6
Visual web development tools

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment