基于地理区域的广告推送模块

近期遇到一个奇怪的需求,行车记录仪的后台需要可以根据地理区域对用户推送广告信息。这里的地理区域不同于市、省的划分,而是广告发布者在地图上选择的任意区域(中国境内),这意味着我们可以向大到城市、小到一个洗车行、停车场、快餐店等等小企业出租广告,并且可以根据用户选择的区域大小、区域竞争(比如商家买断某块区域中同类广告的投放权)进行阶梯收费。

 

功能描述:

商家或管理员在广告投放页面中选择任意形状的地理区域,当用户进入此广告区域时,商家投放的广告将通过后台服务器推送给用户。


功能难点:

1.在页面中模拟用户选择区域范围

2.如何判断GPS中的经纬度是否在地图上的广告区域中

 

实现过程:

1.使用百度地图完成该功能

2.在广告投放页面中使用百度地图完成区域选择和获取地理位置点

3.将用户选择的区域地理位置点上传到后台并保存至数据库中

3.结合行车记录仪每3分钟上传一次行车轨迹,取轨迹记录中的一个经纬度

4.将轨迹记录的经纬度和数据库中的区域位置点进行比较,判断该经纬度是否在区域中

5.如果在广告区域中,服务器将广告信息推送给行车记录仪

 

实现效果:

        用户选择地理区域看起来是这样的:

基于地理区域的广告推送模块_第1张图片

代码:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE>
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>信息发布</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	
	<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.2"></script>
	
	<script type="text/javascript" src="style/jquery-1.10.2.js"></script>

  </head>

<body>

<div style="width:100%;height:480px;border:1px solid gray" id="container"></div>
<p>
<input id="startBtn" type="button" onclick="startTool();" value="开始选取区域" />
<input type="button" onclick="map.clearOverlays();points=[];closeMark=0;document.getElementById('polygonArea').value='';" value="清除" />

<input type="hidden" id="polygonArea" value="" />
<hr>

	<table>
		<tr>
			<td>发布IDAAD信息:</td>
			<td><textarea name="message" id="message" clos="30" rows="7" style="height: 100%; width: 500px; 
				background-attachment: fixed; background-repeat: no-repeat; border-style: solid; 
				border-color: red";overflow-y:hidden;overflow-x:hidden;border:1;></textarea>
			</td>
		</tr>
		<tr>
			<td></td>
			<td>
				&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;
				&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;
				<label><input name="mesType" type="radio" value="0" />推送信息</label> 
				<label><input name="mesType" type="radio" value="1" checked />广告信息</label> 
			</td>
		</tr>
		<tr>
			<td></td>
			<td>
				&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;
				&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;
				&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;
				&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;
				&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;
			<input type="button" value="&ensp;&ensp;&ensp;&ensp;发布信息&ensp;&ensp;&ensp;&ensp;" onclick="message()" />
			</td>
		</tr>
	</table>

<hr>

</body>  
</html>

<script type="text/javascript">
var map = new BMap.Map("container");
map.centerAndZoom("深圳", 12); 

map.enableScrollWheelZoom();

var key = 1; 
var newpoint;   
var points = [];   
var polyline = new BMap.Polyline(); 
var polygon;	
var closeMark = 0;
var dataPool = "";

function startTool(){

	if(key==1){
        document.getElementById("startBtn").style.background = "green";
        document.getElementById("startBtn").style.color = "white";
        document.getElementById("startBtn").value = "开启状态";
        key=0;
    } else{
        document.getElementById("startBtn").style.background = "red";
        document.getElementById("startBtn").value = "关闭状态";
        key=1;
    }
}
map.addEventListener("click",function(e){
	if(closeMark == 1){
		alert("已经闭合选择区域,请清除后重新选择!");
		return false;
	}

    newpoint = new BMap.Point(e.point.lng,e.point.lat);
    if(key==0){
	var markerhead = new BMap.Marker(newpoint);      
	map.addOverlay(markerhead);                   

        points.push(newpoint);  
        polyline.setPath(points); 
        map.addOverlay(polyline);  
	dataPool+=e.point.lng + "," + e.point.lat + "|";
    }
});

map.addEventListener("dblclick",function(e){
	if(key==0){
		closeMark = 1;
        map.disableDoubleClickZoom();
		polygon = new BMap.Polygon(points);
        map.addOverlay(polygon);
        
        var polygonArea=document.getElementById("polygonArea");
        polygonArea.value = dataPool;
    }
});

function submitFun(){
	if(key == 1){
		alert("您还没有选择区域!");
		return false;
	}
	if(closeMark == 0){
		alert("开始提交");
	}else{
		alert("您选择的区域没有闭合,请双击闭合!");
	}
}

function message(){
	var message=document.getElementById("message").value.trim();
	var mesTypes=document.getElementsByName("mesType");
	var polygonArea=document.getElementById("polygonArea").value.trim();
	var mesType="";
	
	if(key == 1){
		alert("您还没有选择区域!");
		return false;
	}
	
	if(closeMark == 0){
		alert("您选择的区域没有闭合,请双击闭合!");
		return false;
	}
	
	if ( polygonArea.length < 1 ) {
		alert("请选择区域");
		return false;
	};
	
	if ( message.length < 1 ) {
		alert("message不能为空");
		document.getElementById("message").focus();
		return false;
	};
	
    for(var i=0;i<mesTypes.length;i++){
        if(mesTypes[i].checked){ 
            //alert(mesTypes[i].value);
            mesType = mesTypes[i].value;
            break;
        }   
    }
    if ( mesType.length < 1 ) {
		alert("请选择消息类型!");
		return false;
	};
    
	$.ajax({
	  	url:'message',
		type:'GET',
		data:"UserLmessage="+message+"&mesType="+mesType+"&polygonArea="+polygonArea,
		success:function(data){
			if(data=="OK"){
				alert("发布成功!");
			}else{
				alert("发布失败!");
			}
		}
	});

}

</script>


        功能中的最难点,就是判断一个经纬度是否在广告投放的区域中。百度地图、高德地图只在javascriptAPI和AndroidSDK中提供了接口,所以如何判断成功了最大的难点,我想到的折中方法是在html页面中使用javascriptAPI中的接口进行判断,然后将判断结果回传到服务器中。

        javascriptAPI代码:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>行政区域工具</title>

<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.2"></script>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>

String.prototype.getQueryString = function(name)
{
  var reg = new RegExp("(^|&|\\?)"+ name +"=([^&]*)(&|$)"), r;
  if (r=this.match(reg)) return unescape(r[2]); return null;
};
var polygonArea = location.search.getQueryString("polygonArea");
var carPoiont = location.search.getQueryString("carPoiont");

stringJudge(polygonArea,carPoiont);

function stringJudge(polygonArea,carPoiont){
	var points=[];
	var dps = polygonArea.split("|");
    for(var i=0;i<dps.length-1;i++){
		var dpArr = dps[i].split(",");
		var newpoint = new BMap.Point(dpArr[0],dpArr[1]);
		points.push(newpoint); 
    }

	var ply = new BMap.Polygon(points);

	var carPoionts = carPoiont.split(",");

    var pt =new BMap.Point(carPoionts[0],carPoionts[1]);
    
    var result = BMapLib.GeoUtils.isPointInPolygon(pt, ply);
    if(result == true){
	sentGeoResult(polygonArea,"YES");
    }else{
    
    }
}

function sentGeoResult(polygonArea,areaRangeMark){
	$.ajax({
        type: "GET",
        url: "GeoResult?date="+new Date().getTime(),  
        data: {areaRangeMark:areaRangeMark,polygonArea:polygonArea},
        success:function(data){
            
        }
 	});
}

</script>

</head>

</html>


        javascriptAPI很好的解决了这个难题,接下来如何在action中调用html页面,使之执行javascript代码并返回结果让我想了好久,使用了很多种方法还是无法重新调起执行,每一次都是将html页面获取过来,导致进度停滞了一天,今天终于让我找到了方法,嘿嘿~~~

        使用htmlunit完美的解决了这个问题,灵感来自于网络爬虫,htmlunit能够将网页读取出来,执行完网页的代码并返回结果。

        htmlunit代码:

public static void AreaJud(String url) throws Exception {
    final WebClient webClient = new WebClient();

    webClient.setAjaxController(new NicelyResynchronizingAjaxController());

    webClient.getPage(url);
}

        仅仅三行代码就解决了,当然htmlunit不止这点功能,使用htmlunit来做这个完全是大材小用,关于htmlunit的使用将在下一篇博客中介绍。

        

至此,推送广告功能就做完了,其实不止推送广告模块,在关于车辆防盗的电子围栏功能中也可以使用,估计还能做得更好。















你可能感兴趣的:(基于地理区域的广告推送模块)