这里之所以调用新浪api接口,主要是可以避免我们在本地存放一个ip归属地库,
同时,我们在本地要存放用户的ip,仅仅存放其ip就可以了,无须存放其归属地,节省一个字段。
如下图,写一个带有获取客户端IP地址的网页:
首先,在Eclipse的目录结构如下:
里面除了servlet的支持包之外,就一个.jsp与一个.java。
其中这里用到Servlet3.0,因此web.xml没有任何东西:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
</web-app>
之后,index.jsp通过Javascript的Ajax,向ipGetTest.java中获取相应的Json。Javascript与Servlet的交互原理已经在《【Servlet】Servlet3.0与纯javascript通过Ajax交互》(点击打开链接)中说过了,这里不再赘述!以下是index.jsp中的代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Javaweb-IP查询</title>
</head>
<body>
<p>IP:<span id="ip"></span></p>
<p>IP归属地:<span id="area"></span></p>
</body>
</html>
<script>
//创建Ajax对象,不同浏览器有不同的创建方法,其实本函数就是一个简单的new语句而已。
function createXMLHttpRequest() {
var XMLHttpRequest1;
if (window.XMLHttpRequest) {
XMLHttpRequest1 = new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
XMLHttpRequest1 = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
XMLHttpRequest1 = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return XMLHttpRequest1;
}
function ajax() {
var XMLHttpRequest1 = createXMLHttpRequest();
//指明相应页面
var url = "./ipGetTest";
XMLHttpRequest1.open("POST", url, true);
//这里没法解释,你所有JavaScript的请求头都这样写就对了,不会乱码
XMLHttpRequest1.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
//对于ajaxRequest,本js.html将会传递param1与param2给你。
XMLHttpRequest1.send(null);
//对于返回结果怎么处理的问题
XMLHttpRequest1.onreadystatechange = function() {
//这个4代表已经发送完毕之后
if (XMLHttpRequest1.readyState == 4) {
//200代表正确收到了返回结果
if (XMLHttpRequest1.status == 200) {
//json返回结果
var data=eval("("+XMLHttpRequest1.responseText+")");
document.getElementById("ip").innerHTML=data.ip;
document.getElementById("area").innerHTML=decodeURIComponent(data.area1)+decodeURIComponent(data.area2);
} else {
//如果不能正常接受结果,你肯定是断网,或者我的服务器关掉了。
alert("网络连接中断!");
}
}
};
}
ajax();
</script>
index.jsp将会从ipGetTest.java中获取如下的Json:
其中http://ipapi.sinaapp.com/api.php?f=text&ip=xxx这个新浪的api,如果f=text则返回文本信息,如果时f=json则返回json字符串,当然这个json字符串还需要自己如上代码所示地,需要通过decodeURIComponent讲utf-8编码,搞成中文。
这里的起始地址与结束地址,就是该网段ip的起始地址与结束地址。
关键是ipGetTest.java这个文件,这个文件分三步,首先通过request对象,获取用户访问的IP,之后通过Java向远程获取数据的技术获取网页内容。
获取到的文本信息,直接打印到控制台,获取到Json信息直接打印到这个Servlet上面。
package ipGet;
import java.io.*;
import java.net.URL;
import java.util.Scanner;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
@WebServlet(name = "ipGetTest", urlPatterns = { "/ipGetTest" })
public class ipGetTest extends HttpServlet {
private static final long serialVersionUID = 1L;
private Scanner scanner;
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 这两行是为了这个Servlet能够正常打印数据的
PrintStream out = new PrintStream(response.getOutputStream());
response.setContentType("text/html;charSet=utf-8");
// 获取客户端ip
String ip = "";
if (request.getHeader("x-forwarded-for") == null) {
ip = request.getRemoteAddr();
} else {
ip = request.getHeader("x-forwarded-for");
}
System.out.print("你的ip为:" + ip + "\n");
// 获取ip归属地的文本信息
StringBuilder ipText = new StringBuilder("");
String url = "http://ipapi.sinaapp.com/api.php?f=text&ip=" + ip;
scanner = new Scanner(new URL(url).openConnection().getInputStream(),
"utf-8");
while (scanner.hasNext()) {
ipText.append(scanner.next());
}
System.out.println(ipText);
// 获取ip归属地的json信息
StringBuilder ipJson = new StringBuilder("");
url = "http://ipapi.sinaapp.com/api.php?f=json&ip=" + ip;
scanner = new Scanner(new URL(url).openConnection().getInputStream(),
"utf-8");
while (scanner.hasNext()) {
ipJson.append(scanner.next());
}
out.println(ipJson);
}
}
由于只能通过服务器语言才能获取到客户端的IP,因此,只能这样搞。
这里Java获取远程信息,通过《【Java】打印流与缓冲区读者完成输入与输出到文件操作》(点击打开链接)中使用Scanner的方法改造了《【Java】读取网页中的内容》(点击打开链接)中通过缓冲区读者的方式来获取远程信息。