这里之所以调用新浪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】读取网页中的内容》(点击打开链接)中通过缓冲区读者的方式来获取远程信息。