赞
踩
最近在工作中遇见一个业务场景是获取用户真实的ip地址。就跟现在网上评论展示ip一样的业务场景。然后自己就去了解了一下,
- <!--查询ip归属地-->
- <dependency>
- <groupId>org.lionsoul</groupId>
- <artifactId>ip2region</artifactId>
- <version>1.7.2</version>
- </dependency>
-
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.5</version>
- </dependency>
工具类里面需要使用ip2region.db这个文件。在加载的时候,需要下载仓库中的 ip2region.db 文件,然后放到 resource 目录下
以下文件是文件链接,可自取。
链接:https://pan.baidu.com/s/1PDd_BnpdaOOkYnAc5cB36A?pwd=LA7M
本工具类会将完整的封装方法放入,在使用的时候只需要自己调用即可,非常简单明了。
在工具类里面也会将具体的方法导的具体的包显示出来,便于自己查看溯源。
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.io.FileUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.lionsoul.ip2region.DataBlock;
- import org.lionsoul.ip2region.DbConfig;
- import org.lionsoul.ip2region.DbSearcher;
- import org.lionsoul.ip2region.Util;
- import org.springframework.core.io.Resource;
- import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
- import org.springframework.core.io.support.ResourcePatternResolver;
-
- import javax.servlet.http.HttpServletRequest;
- import java.io.File;
- import java.io.InputStream;
- import java.lang.reflect.Method;
-
- @Slf4j
- public class IpUtil {
-
- public static String getIpAddr(HttpServletRequest request) {
- String ip = request.getHeader("X-Real-IP");
- if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
- return ip;
- }
- ip = request.getHeader("X-Forwarded-For");
- if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
- // 多次反向代理后会有多个IP值,第一个为真实IP。
- int index = ip.indexOf(',');
- if (index != -1) {
- return ip.substring(0, index);
- } else {
- return ip;
- }
- } else {
- return request.getRemoteAddr();
- }
- }
-
- public static String getCityInfo(String ip) throws Exception {
- //获得文件流时,因为读取的文件是在打好jar文件里面,不能直接通过文件资源路径拿到文件,但是可以在jar包中拿到文件流
- ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
- Resource[] resources = resolver.getResources("ip2region.db");
- Resource resource = resources[0];
- InputStream is = resource.getInputStream();
- File target = new File("ip2region.db");
- FileUtils.copyInputStreamToFile(is, target);
- is.close();
- if (StringUtils.isEmpty(String.valueOf(target))) {
- log.error("Error: Invalid ip2region.db file");
- return null;
- }
- DbConfig config = new DbConfig();
- DbSearcher searcher = new DbSearcher(config, String.valueOf(target));
- //查询算法
- //B-tree, B树搜索(更快)
- int algorithm = DbSearcher.BTREE_ALGORITHM;
- try {
- //define the method
- Method method;
- method = searcher.getClass().getMethod("btreeSearch", String.class);
- DataBlock dataBlock;
- if (!Util.isIpAddress(ip)) {
- log.error("Error: Invalid ip address");
- }
- dataBlock = (DataBlock) method.invoke(searcher, ip);
- String ipInfo = dataBlock.getRegion();
- if (!StringUtils.isEmpty(ipInfo)) {
- ipInfo = ipInfo.replace("|0", "");
- ipInfo = ipInfo.replace("0|", "");
- }
- return ipInfo;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- public static String getIpPossession(String ip) throws Exception {
- String cityInfo = getCityInfo(ip);
- if (!StringUtils.isEmpty(cityInfo)) {
- cityInfo = cityInfo.replace("|", " ");
- String[] cityList = cityInfo.split(" ");
- if (cityList.length > 0) {
- // 国内的显示到具体的省
- if ("中国".equals(cityList[0])) {
- if (cityList.length > 1) {
- return cityList[1];
- }
- }
- // 国外显示到国家
- return cityList[0];
- }
- }
- return "未知";
- }
-
- }
此时就可以显示正常信息了。
如果显示这个错误的话,说明本地自己写的AOP,joinPoint.getArgs()返回的数组中携带有Request或者Response对象,导致序列化异常。
这个时候我们添加如下就可以4了
- Object[] args = point.getArgs();
- Object[] arguments = new Object[args.length];
- for (int i = 0; i < args.length; i++) {
- if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
- //ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
- //ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
- continue;
- }
- arguments[i] = args[i];
- }
- String paramter = "";
- if (arguments != null) {
- try {
- paramter = JSONObject.toJSONString(arguments);
- } catch (Exception e) {
- paramter = arguments.toString();
- }
- }
- log.info("请求接口名:{}", point.getSignature().getName());
- log.info("请求参数:{}", paramter);
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。