精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

如何利用HTML5與MongoDB創建位置感知Web應用程序

譯文
開發 前端 MongoDB
在日常生活中,我們都離不開位置識別類應用程序。Foursquare、Facebook等應用程序幫助我們和我們的家人朋友分享當前位置(或者正在參觀的景點)。而像Google Local這樣的應用則幫助我們找到當前位置附近有哪些自己需要的服務設施或業務場所。

在日常生活中,我們都離不開位置識別類應用程序。Foursquare、Facebook等應用程序幫助我們和我們的家人朋友分享當前位置(或者正在參觀的景點)。而像Google Local這樣的應用則幫助我們找到當前位置附近有哪些自己需要的服務設施或業務場所。如此,如果我們需要找到一家離自己最近的咖啡廳,完全可以通過Google Local快速獲取建議并立刻動身前往。這不僅大大方便了日常生活,還能夠幫助企業將自己的產品推銷給更理想的受眾群體。無論是對消費者還是對企業,這都堪稱完美的雙贏局面。

要創建這樣一款應用程序,大家首先需要獲取用戶的地理位置信息。根據維基百科的解釋,“地理信息是指某個對象所處的現實地理位置”。就目前來看,Web應用程序中還沒有出現標準化的用戶地理位置獲取方式。雖然Google Gears這樣的開源庫能夠從用戶處獲取位置信息,但這套庫已經停止發展、只能運行在舊版本瀏覽器當中而且不支持W3C地理位置API。W3C GeoLocation API提供了一套規范,能夠通過標準化腳本訪問與托管設備相關的地理信息。Geo Location并不提供對HTML 5的官方支持,但這仍然無法阻止人們的熱情,而且我們經常聽說開發人員將GeoLocation API與HTML 5相對接。該API以用戶所收集的地理信息為基礎建立抽象層,從而保證所有瀏覽器都支持地理定位API。大家可以訪問??http://caniuse.com/#feat=geolocation??獲取下列圖表。

?

應用程序用例——找工作應用

在本文中,我們將創建一款能夠感知地理位置的找工作應用。應用程序將根據用戶的特定技能(例如Java、Scala以及MongoDB等)尋找最近的求職地點。應用將利用W3C GeoLocation API實現用戶定位。接下來,應用程序將用戶位置繪制在谷歌地圖當中。大家可以訪問??http://localjobshtml5-cix.rhcloud.com/??獲取這款應用。用戶圖標對應用戶當前地理位置,公文包圖標則對應目標求職地點。 

如果大家點擊任何公文包圖標,地圖會如下圖所示自動放大。而當我們關閉信息窗口,畫面會再次縮小。另外,大家可以在標記中查看求職場所與當前位置之間的距離、對應職務以及其它相關資料。用戶位置與工作位置之間的距離由MongDB的地理空間功能所支持,我們會在后面的文章中進一步討論這個話題。

?

應用程序技術堆棧

這款應用的創建需要使用以下技術堆棧:

Java EE 6 : 我們將使用數項Java EE 6規范——JAX-RS以及CDI。JAX-RS屬于針對Restful Web服務的Java API,其作用在于根據REST架構模式為網絡服務創建提供Java API。CDI則是Context and Dependency Injection(背景與關聯性注入)的縮寫。CDI允許開發者將Java EE組件與生命周期背景進行綁定、注入,而后通過事件觸發與觀察機制以松散的耦合方式實現交互。

MongoDB : MongoDB是一套面向文檔的NoSQL數據存儲機制。我們將把工作數據保存在MongoDB當中并在應用程序中使用其地理空間功能。

HTML 5 : 我們將利用HTML 5創建應用程序客戶端,并利用W3C GeoLocation API獲取用戶的當前位置。

谷歌地圖 : 應用程序將利用谷歌地圖來處理用戶位置以及求職信息。

OpenShift : 應用程序將被部署到OpenShift公共PaaS當中。

應用程序源代碼

這款應用程序的源代碼被發布在GitHub當中,地址為:??https://github.com/shekhargulati/localjobshtml5??

前續條件

在我們著手創建應用程序之前,首先需要進行以下幾項設置任務:

1. 注冊一個OpenShift賬戶。賬戶注冊完全免費,而且紅帽將為每位用戶免費提供三套Gear用于運行應用程序。截至本文截稿時,該賬戶可以獲得1.5GB內存容量與3GB磁盤存儲空間。

2. 在設備上安裝rhc客戶工具。rhc是一套ruby gem包,因此大家需要在設備上安裝ruby 1.8.7或者更高版本。要安裝rhc,大家需輸入:

sudo gem install rhc

如果當前已經安裝過ruby,請確保其處于最新版本。要更新rhc工具,請執行如下所示命令:

sudo gem update rhc

如需其它相關rhc命令行工具設置說明,請點擊下列網址查看相關資料:??https://openshift.redhat.com/community/developers/rhc-client-tools-install??

1 利用rhc setup命令設置OpenShift賬戶。這條命令將幫助大家創建一個命名空間并將自己的ssh密鑰上傳至OpenShift服務器。

#p#

開始創建應用程序

現在我們已經完成了全部前續設置工作,現在開始創建應用程序。我們將從創建OpenShift應用程序開始。在與PaaS協作時,大家首先需要明確一點:PaaS是用來創建應用程序的。因此,現在我們要擺脫過去以虛擬機或者服務器為中心的理念,將全部精力集中在應用程序身上。

創建JBossEAP MongoDB OpenShift應用程序

要創建名為“localjobs”且使用JBossEAP與MongDB的應用程序,我們首先要執行以下命令:

rhc app create localjobs jbosseap mongodb-2.2

這將為我們創建一套應用程序容器,也就是所謂gear,并為其配置全部必要的SELinux政策以及cgroup配置。OpenShift還將為我們設置一個私有git庫,并將該庫克隆到本地系統當中。最后,OpenShift會將DNS發送至外部環境。大家可以通過??http://localjobs-domain-name.rhcloud.com??訪問該應用。將其中的域名替換為您自己的獨特域名即可。

上述命令將創建一套標準化Maven項目模板。有趣的是,在pom.xml文件中存在一段名為openshift的配置信息,如下所示。因此,當大家將自己的源代碼推送至OpenShift時,該Maven配置文件將付諸執行。該配置文件不會引發任何影響——而只是創建一個名為ROOT的war文件,從而保證我們的應用程序可用于root背景之下。

<profiles>
<profile>
<id>openshift</id>
<build>
<finalName>localjobs</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<outputDirectory>deployments</outputDirectory>
<warName>ROOT</warName>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

接下來,我們將把index.html與snoop.jsp兩個文件從自己的git庫中移除——它們的歷史使命已經完成。如果大家不太熟悉git的運作方式,請點擊此處閱讀由Lars Vogel撰寫的上手指南。

git rm -f src/main/webapp/index.html src/main/webapp/snoop.jsp
git commit -am "deleted template files"

添加MongoDB Java驅動程序關聯性

由OpenShift創建的pom.xml文件已經擁有全部與Java EE 6相關的關聯性。為了使用MongoDB,我們還需要添加MongoDB Java驅動關聯性。我使用的是MongoDB Java驅動的最新版本。將下列關聯性內容添加到pom.xml文件當中。大家可以點擊此處在github上查看完整的pom.xml文件。

<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.10.1</version>
</dependency>

啟用CDI

CDI代表背景與關聯性注入。之所以在應用程序中使用CDI,是因為我們需要利用關聯性注入來代替手動創建對象。CDI容器將管理bean生命周期,這樣我們作為開發者只需要編寫業務邏輯即可。為了讓JBossEAP應用程序服務器了解到我們正在使用CDI,我們需要在WEB-INF文件夾下創建一個beans.xml文件。該文件可以保持空白,但它的存在會使容器了解到需要加載CDI框架。Beans.xml文件的內容如下所示:

<?xml version="1.0"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://jboss.org/schema/cdi/beans_1_0.xsd"/>

編寫MongDB數據庫連接類

接下來,我們將創建一個應用程序作用域bean,用于管理MongoDB數據庫連接。該連接類同時起效于本地系統與OpenShift端。大家可以點擊此處在github中查看該類的完整內容。

@ApplicationScoped
public class DBConnection {

private DB mongoDB;

@PostConstruct
public void afterCreate() {
System.out.println("just see if we can say anything");

String host = System.getenv("OPENSHIFT_MONGODB_DB_HOST");

if (host == null || "".equals(host)) {
// Create Local MongoDB Connection
} else {
String mongoport = System.getenv("OPENSHIFT_MONGODB_DB_PORT");
String user = System.getenv("OPENSHIFT_MONGODB_DB_USERNAME");
String password = System.getenv("OPENSHIFT_MONGODB_DB_PASSWORD");
String db = System.getenv("OPENSHIFT_APP_NAME");
int port = Integer.decode(mongoport);

Mongo mongo = null;
try {
mongo = new Mongo(host, port);
} catch (UnknownHostException e) {
System.out.println("Couldn't connect to Mongo: "
+ e.getMessage() + " :: " + e.getClass());
}

mongoDB = mongo.getDB(db);

if (mongoDB.authenticate(user, password.toCharArray()) == false) {
System.out.println("Failed to authenticate DB ");
}
}

}

@Produces
public DB getDB() {
return mongoDB;
}

}

在應用程序運行過程中,@ApplicationScoped bean將始終存在,并在應用程序關閉的同時被刪除。這正是我們希望通過MongoDB驅動所達到的連接池對象保留效果。

編寫RESTful后端

現在我們開始利用JAX-RS為自己的應用程序編寫RESTful后端。我們將通過創建一個用于擴展javax.ws.rs.ApplicationPath的類激活JAX-RS。大家需要指定一條基礎url,并將其作為網絡服務的訪問地址。要實現這一目的,我們需要利用ApplicationPath注釋為這個類添加注釋。如下列代碼所示,我利用“/api”作為基礎URL:

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/api")
public class JaxRsActivator extends Application {
/* class body intentionally left blank */
}

在成功激活了JAX-RS之后,我們現在可以編寫自己的REST服務。大家可以訪問http://localjobs-domain-name/api/jobs/{skills}?longitude={longitude}&latitude={latitude}以查看REST端點。該REST端點將搜尋周邊經緯度范圍內全部與求職者技能相符的工作崗位。

@Path("/jobs")
public class JobsRestService {

@Inject
private DB db;

@GET
@Path("/{skills}")
@Produces(MediaType.APPLICATION_JSON)
public List<Job> allJobsNearToLocationWithSkill(
@PathParam("skills") String skills,
@QueryParam("longitude") double longitude,
@QueryParam("latitude") double latitude) {

String[] skillsArr = skills.split(",");
BasicDBObject cmd = new BasicDBObject();
cmd.put("geoNear", "jobs");
double lnglat[] = { longitude, latitude };
cmd.put("near", lnglat);
cmd.put("num", 10);
BasicDBObject skillsQuery = new BasicDBObject();
skillsQuery.put("skills",
new BasicDBObject("$in", Arrays.asList(skillsArr)));
cmd.put("query", skillsQuery);
cmd.put("distanceMultiplier", 111);

CommandResult commandResult = db.command(cmd);

BasicDBList results = (BasicDBList)commandResult.get("results");
List<Job> jobs = new ArrayList<Job>();
for (Object obj : results) {
Job job = new Job((BasicDBObject)obj);
jobs.add(job);
}
return jobs;
}
}

上面所示的代碼會創建一條MongoDB附近位置查詢,其結果文件數量被限制為10個。MongoDB返回的結果將作為數據中的數值。由于我們利用經度與緯度進行定位,返回的數據也以經緯度為基礎。不過MongoDB還提供一套距離換數選項,允許我們將經緯度結果換算成更易理解的公里或者英里。在上面的代碼中,我將經緯度結果轉換為111公里。最后,我們將數據轉換為一個名為Job的域對象并將其返回。@Produces注釋將負責將數據轉換至JSON當中。

#p#

將數據載入至MongoDB當中

執行下列命令將數據載入至運行在OpenShift gear中的MongoDB。

在本地設備上,運行rhc app show。這條命令將返回應用程序的詳細信息,如下所示:

$ rhc app show -a localjobs

localjobs @ http://localjobs-newideas.rhcloud.com/ (uuid: 5195d8fe5973ca386f000083)
-----------------------------------------------------------------------------------
Created: 12:45 PM
Gears: 1 (defaults to small)
Git URL: ssh://5195d8fe5973ca386f000083@localjobs-newideas.rhcloud.com/~/git/localjobs.git/
SSH: 5195d8fe5973ca386f000083@localjobs-newideas.rhcloud.com

jbosseap-6.0 (JBoss Enterprise Application Platform 6.0)
--------------------------------------------------------
Gears: Located with mongodb-2.2

mongodb-2.2 (MongoDB NoSQL Database 2.2)
----------------------------------------
Gears: Located with jbosseap-6.0
Connection URL: mongodb://$OPENSHIFT_MONGODB_DB_HOST:$OPENSHIFT_MONGODB_DB_PORT/
Database Name: localjobs
Password: qySukKdKrZQT
Username: admin

記錄下SSH URL并利用scp命令將jobs-data.json文件復制到我們的應用程序gear當中。大家可以點擊此處下載jobs-data.json文件。

$ scp jobs-data.json <ssh url>:app-root/data

接著將SSH插入到應用當中,使用如下所示的rhc app ssh命令:

$ rhc app ssh -a localjobs

將ssh導入至應用程序gear中后,將目錄變更為app-root/data,也就是我們復制jobs-data.json文件的目錄。

$ cd app-root/data

下面運行mongoimport命令將數據導入至MongoDB數據庫當中。

$ mongoimport -d localjobs -c jobs --file jobs
data.json -u $OPENSHIFT_MONGODB_DB_USERNAME -p
$OPENSHIFT_MONGODB_DB_PASSWORD -h
$OPENSHIFT_MONGODB_DB_HOST -port
$OPENSHIFT_MONGODB_DB_PORT

上面顯示的代碼將把159個job對象導入至MongoDB當中。

最后,我們需要在工作集合中創建地理位置索引。MongoDB只支持二維地理位置索引。大家只能為每個集合匹配一套地理位置索引。在默認情況下,二維地理位置索引假設經度與緯度數值在-180(含180)到180(不含180)之間(即[-180,180])。要創建地理信息索引,需要執行下列命令:

$ mongo

$ use localjobs

$ db.jobs.ensureIndex({"location" : "2d"})

測試RESTful服務

下面,我們將提供源代碼并向OpenShift推送變更內容,即創建項目、創建新的war文件并將其部署到運行在OpenShift上的JBossEAP當中。

$ git add .
$ git commit -am "RESful backend done"

$ git push

在代碼創建與war文件部署工作完成后,我們就可以利用curl命令對REST服務進行測試了。

curl -i -H "Accept: application/json" http://localjobs-newideas.rhcloud.com/api/jobs/java,scala?longitude=-121.894955&latitude=37.339386


HTTP/1.1 200 OK
Date: Fri, 17 May 2013 08:39:11 GMT
Server: Apache-Coyote/1.1
Content-Type: application/json
Vary: Accept-Encoding
Transfer-Encoding: chunked

[{"companyName":"CyberCoders","jobTitle":"Embedded Java Applications Engineer","distance":4153.025944882882,"skills":["java"],"formattedAddress":"1400 North Shoreline Boulevard, Mountain View, CA, United States","longitude":-122.078488,"latitude":37.414198},{"companyName":"CyberCoders","jobTitle":"Embedded Java Applications Engineer","distance":4153.025944882882,"skills":["java"],"formattedAddress":"1400 North Shoreline Boulevard, Mountain View, CA, United States","longitude":-122.078488,"latitude":37.414198}
.....
]

美化應用程序

現在我們已經證實了應用程序的REST服務工作正常,接下來要做的是構建應用的用戶界面。在本文中,我們只需創建一套非常簡單的應用用戶界面,即提供一套表單,用戶可以借助它輸入個人技能,并通過div承載谷歌地圖渲染完成的求職場所與用戶位置。如下所示在src/main/webapp文件夾中創建一個index.html文件:

<!DOCTYPE html>
<html>
<head>
<title>LocalJobs : Find jobs near to you</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
body {
padding-top: 60px;
padding-bottom: 100px;
}

#map-canvas {
height: 500px;
width: 100%;
}
.job_info {border: 1px solid #000;padding: 15px;width: 300px}
.job_info h3 {margin-bottom: 10px}
</style>
<link href="css/bootstrap.css" rel="stylesheet">
<link href="css/bootstrap-responsive.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/jquery.tagsinput.css" />
<link href="css/jquery.loadmask.css" rel="stylesheet" type="text/css" />

</head>
<body>

<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" class="btn btn-navbar" data-toggle="collapse"
data-target=".nav-collapse">
<span class="icon-bar"></span> <span class="icon-bar"></span> <span
class="icon-bar"></span>
</button>
<a class="brand" href="#">LocalJobs</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="#">Home</a></li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>

<div id="main" class="container">


<form id="jobSearchForm" class="form-horizontal">
<div class="control-group">
<div class="controls">
<input type="text" id="skills" name="skills" class="input-xlarge"
placeholder="Enter skills for which you want to search jobs"
required>
</div>
</div>

<div class="control-group">
<div class="controls">
<button id="findJobsButton" type="submit" class="btn btn-success">Find
Jobs</button>
</div>
</div>

</form>

</div>

<div id="map-canvas"></div>

<script type="text/x-mustache-template" id="job-template">


<div class="jobBox">
<h3>{{jobtitle}}</h3>
<p> {{company}} </p>
<address> {{address}} </address>
<p> {{skills}}</p>
<p> {{distance}} </p>
</div>
</script>

<script src="js/jquery.js"></script>
<script src="js/jquery.tagsinput.js"></script>
<script type="text/javascript" src="js/jquery.loadmask.min.js"></script>
<script
src="https://maps.googleapis.com/maps/api/js?sensor=true"></script>
<script src="js/bootstrap.js"></script>
<script src="js/underscore.js"></script>
<script src="js/backbone.js"></script>
<script src="js/mustache.js"></script>

<script type="text/javascript">
$( document ).ready( function() {
$('#skills').tagsInput({
defaultText : "add skills"
});
});
</script>

<script src="js/app.js"></script>
</body>
</html>

上面顯示的index.html是一個HTML 5文件,而且使用HTML 5的文檔類型。我們的應用使用Twitter Bootstrap,這是一款免費工具集合,用于創建網站以及web應用程序。它包含了以HTML以及CSS為基礎的設計模板,提供全套排版、表格、按鈕、圖表、導航、其它界面組件以及備選JavaScript擴展。大家可以點擊此處從本項目的github庫中獲取全部相關css.js文件。

檢查GeoLocation支持

由于我們的應用程序以用戶位置為基礎,因此在進一步調整應用程序之前需要首先檢查GeoLocation API。為了檢查用戶瀏覽器對GeoLocation API的支持效果,需要將如下所示記錄準備函數添加進來。如果用戶瀏覽器支持GeoLocation,那么導航對象中將具有geolocation對象。大家還可以利用Modernizr等開源庫檢測HTML 5功能。如果用戶瀏覽器不支持geolocation,大家需要禁用表單提交按鈕。

<script type="text/javascript">
if(!navigator.geolocation){
alert('Your browser does not support geolocation. Please download latest browser version.');
$("#findJobsButton").attr("disabled", "disabled");
}
</script>

#p#

在提交表單中查找工作

現在我們已經確認用戶瀏覽器能夠支持GeoLocation API,接下來要做的就是根據用戶的個人技能為其查找理想工作。此項目利用Backbone.js為我們的客戶端代碼添加結構。如果大家對backbone.js不太熟悉,可以點擊此處查看我之前發表的博文《利用Backbone.js、JaxRS、MongoDB以及OpenShift創建單頁面Web應用程序》,那里提供了與利用backbone.js創建應用有關的詳細說明。請將app.js文件考慮到src/main/webapp目錄下的js文件夾當中。下面展示的是經過精簡的app.js文件內容,這是為了適當縮減本文的篇幅。

// app.js
(function($){

var LocalJobs = {};
window.LocalJobs = LocalJobs;

var template = function(name) {
return Mustache.compile($('#'+name+'-template').html());
};

LocalJobs.HomeView = Backbone.View.extend({
tagName : "form",
el : $("#main"),

events : {
"submit" : "findJobs"
},

render : function(){
console.log("rendering home page..");
$("#map-canvas").empty();
return this;
},

findJobs : function(event){
event.preventDefault();
$("#map-canvas").empty();
$("#jobSearchForm").mask("Finding Jobs ...");
var skills = this.$('input[name=skills]').val().split(',');

console.log("skills : "+skills);

var self = this;

var mapOptions = {
zoom: 3,
center: new google.maps.LatLng(-34.397, 150.644),
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
}
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);


navigator.geolocation.getCurrentPosition(function(position){
var longitude = position.coords.longitude;
var latitude = position.coords.latitude;
console.log('longitude .. '+longitude);
console.log('latitude .. '+latitude);

$("#jobSearchForm").unmask();
self.plotUserLocation(new google.maps.LatLng(latitude, longitude),map);

$.get("api/jobs/"+skills+"/?longitude="+longitude+"&latitude="+latitude , function (results){
$("#jobSearchForm").unmask();
self.renderResults(results,self,map);
});
}, function(e){
$("#jobSearchForm").unmask();
// handle error

},
{ timeout: 45000 }

);

},

plotUserLocation : function(latLng , map){

},

renderResults : function(results,self,map){
var infoWindow = new google.maps.InfoWindow();
_.each(results,function(result){
self.renderJob(result,map , infoWindow);
});

},

renderJob : function(result , map , infoWindow){
}




});


LocalJobs.Router = Backbone.Router.extend({
el : $("#main"),

routes : {
"" : "showHomePage"
},
showHomePage : function(){
console.log('in home page...');
var homeView = new LocalJobs.HomeView();
this.el.append(homeView.render().el);
}

});

var app = new LocalJobs.Router();
Backbone.history.start();


})(jQuery);

下面我們一起來解讀代碼的具體含義。

1. 上面展示的代碼旨在創建一個backbone路由實例,并將其作為root DOM的主div。下面我們點擊基礎url,路由機制會調用映射HomeView的showHomePage函數。渲染函數中的HomeView用于通過id map-canvas清空div。

2. 在HomeView當中,我們擁有一套針對表單提交的事件偵聽器。因此,當用戶輸入個人技能并按下“提交”按鈕后,findJobs函數將被調用。

3. findJobs函數是一切運行的基礎。

3.1 我們首先利用技能名稱獲取輸入值,然后利用逗號將內容分割,這樣就構成了一套技能數組。

3.2 我們接著創建一個谷歌地圖對象并為其設置一些默認值。

3.3 下面我們調用navigator.geolocation對象上的getCurrentPosition方法。此方法只有一項必要參數success_callback與兩項可選參數error_callback,外加可選對象PositionOptions。

3.4 如果getCurrentPosition被調用成功,則繼續調用success_callback。這條回調函數擁有一項參數——position。這個position對象負責保留用戶的經偉度結果,并在地圖上繪制用戶的當前位置。

3.5 在用戶位置繪制完成之后,則通過jQuery進行獲取調用。

3.6 最后所有結果都將經過迭代并顯示在地圖之上。

推送代碼

現在大家可以將代碼推送至OpenShift處并查看應用程序在云中的運行效果。

git add .
git commit -am "localjobs app with UI"
git push

按照我所羅列的提示內容,應用程序將運行在https://localjobs-domain-name.rhcloud.com/位置。大家可以將具體域名替換為自己的命名空間。

總結

在本篇博文中,我們共同探討了如何利用HTML 5 GeoLocation API以及MongoDB Geo位置索引功能創建位置感知類應用程序。希望文章內容能給大家的開發工作帶來啟示,感謝閱讀。

原文鏈接:??https://www.openshift.com/blogs/how-to-build-location-aware-web-applications-using-html5-and-mongodb??

責任編輯:林師授 來源: 51CTO
相關推薦

2015-02-05 10:11:44

HTML5Application

2012-05-24 15:49:35

HTML5

2014-03-20 10:50:44

HTML5 定位技術

2009-01-19 11:07:42

C#Web.NET

2009-07-29 17:42:47

ibmdwWeb2.0

2009-08-27 11:53:45

ibmdw云計算

2012-09-04 10:15:00

IBMdw

2012-06-11 09:37:41

2012-01-01 22:07:28

jQMjQuery MobiHTHL5

2016-05-27 15:44:12

H5LeanCloudWex5

2009-09-03 17:36:13

C#創建Web應用程序

2009-09-15 23:40:52

2013-11-19 15:35:01

2011-05-25 09:34:30

HTML5cssjavascript

2015-07-03 11:07:39

HTML5移動Web

2015-11-20 17:09:36

jsWeb應用程序

2013-06-24 10:21:47

面向對象Web應用JavaScript

2024-09-06 10:46:04

2012-06-07 09:15:14

ibmdw

2013-09-03 15:45:50

點贊
收藏

51CTO技術棧公眾號

麻豆精品传媒视频| 中文字幕av日韩| 国产免费观看高清视频| 免费在线性爱视频| 狠狠色综合播放一区二区| 欧美黑人xxx| 亚洲天堂久久新| 激情不卡一区二区三区视频在线| 精品国产精品三级精品av网址| 欧美在线视频二区| 性中国xxx极品hd| 天堂va蜜桃一区二区三区漫画版| 久久国产精品亚洲| 91理论片午午论夜理片久久| 日韩网站在线免费观看| 国产精品视频二区三区| 成人中文字幕电影| 国产精品视频大全| 中文字幕一区二区三区精品| 99久久亚洲精品| 日韩精品免费电影| 国产精品果冻传媒| 曰本一区二区| 91黄色免费看| 国产精品自拍片| 成人免费观看视频大全| 日本一区免费视频| 久久99精品久久久久久秒播放器| 国产乱码精品一区二区三区精东| 日韩精品电影在线观看| 欧美劲爆第一页| 美国黄色小视频| 久久香蕉国产| 永久免费看mv网站入口亚洲| 影音先锋人妻啪啪av资源网站| 蜜桃精品视频| 欧美一区二区三区四区视频 | 欧美网站在线| 久久夜色精品亚洲噜噜国产mv | 亚洲欧美视频在线观看视频| 亚洲v欧美v另类v综合v日韩v| 亚洲三级黄色片| 不卡的电视剧免费网站有什么| 147欧美人体大胆444| 国产精品探花视频| 极品少妇xxxx精品少妇| 国产精品久久久久久久一区探花| 国产婷婷色一区二区在线观看| 一本久道久久综合狠狠爱| 久久久久久久久国产| 青娱乐免费在线视频| 欧美va天堂在线| 久久91亚洲人成电影网站 | 国产中文字幕在线看| 久久综合色综合88| 日本欧美精品久久久| 欧美偷拍视频| 久久精品欧美日韩| 亚洲bbw性色大片| 在线免费观看的av网站| 国产精品久久久久久久久免费相片| 亚洲国产精品毛片| 精品176二区| 一区二区三区欧美日| 国产精品视频网站在线观看| 女人天堂av在线播放| 婷婷夜色潮精品综合在线| 无码精品a∨在线观看中文| 成人亚洲欧美| 欧美羞羞免费网站| 亚洲欧美手机在线| 一区二区三区视频免费视频观看网站| 精品日韩在线一区| 色婷婷av777| 水蜜桃精品av一区二区| 久久国产精品偷| 日韩黄色一级大片| 美女爽到高潮91| 99国产在线观看| 日韩有码第一页| 国产欧美日韩在线视频| ijzzijzzij亚洲大全| 2018av在线| 欧美日韩中文另类| 亚洲AV无码久久精品国产一区| 欧美挤奶吃奶水xxxxx| 一区二区三区回区在观看免费视频| 男人的午夜天堂| 日韩视频在线一区二区三区 | 亚洲男人电影天堂| 欧美一级视频免费看| 欧美性xxx| 欧美一区二区精美| 老司机福利av| 欧美视频www| 999在线精品| 伊人久久久久久久久久久久久| 三级黄色片在线观看| 黑人一区二区三区四区五区| 国产国语videosex另类| www.久久综合| 中文字幕久久午夜不卡| 国产成人永久免费视频| 成人日韩精品| 亚洲黄色在线看| 成人性视频免费看| 国产欧美一区二区三区国产幕精品| 国产欧美日韩亚洲精品| 污污网站免费在线观看| 综合久久久久综合| 国产精品亚洲a| 1204国产成人精品视频| 中文字幕不卡av| 欧美一级特黄视频| 国产99久久久精品| 国产91av视频在线观看| 中文av在线全新| 亚洲电影免费观看| 高h视频免费观看| 麻豆专区一区二区三区四区五区| 精品蜜桃传媒| 国语对白在线刺激| 日韩三级.com| 肉色超薄丝袜脚交69xx图片 | 2019中文字幕在线| 亚洲av无码片一区二区三区| 国产精品女主播av| 婷婷丁香激情网| 嫩草一区二区三区| 2023亚洲男人天堂| 四虎免费在线观看| 亚洲成a人片在线观看中文| 超碰在线超碰在线| 91九色精品国产一区二区| 国产精品黄页免费高清在线观看| 香蕉视频黄在线观看| 午夜欧美视频在线观看| 人妻激情偷乱频一区二区三区| 欧美日韩国产在线一区| 亚洲tv在线观看| 国产剧情在线| 欧美一区二区三区免费观看视频| 国产又黄又粗又猛又爽的| 日本特黄久久久高潮 | 久久久久久少妇| 久久精品免费一区二区三区| 国产精品老牛影院在线观看| 日韩电影网址| 91官网在线免费观看| 波多野结衣办公室33分钟| 久久一区中文字幕| 日韩一二三区不卡在线视频| 日韩一级二级| xxav国产精品美女主播| 国产精品污视频| 一区二区三区日韩在线观看| jjzzjjzz欧美69巨大| 在线综合视频| 日本不卡一区二区三区视频| 另类中文字幕国产精品| 中文字幕亚洲欧美日韩在线不卡| 91高潮大合集爽到抽搐| 亚洲女子a中天字幕| 波多野结衣办公室双飞 | 国产精品欧美一级免费| 国产一级片自拍| 欧美日本久久| 久久96国产精品久久99软件| av在线一区不卡| 日日骚久久av| 成人免费视频国产| 色哟哟日韩精品| 91ts人妖另类精品系列| 成人午夜激情片| 成年人免费在线播放| 久久精品国产68国产精品亚洲| 91在线免费看网站| 99re6在线精品视频免费播放| 精品在线欧美视频| 中文字幕一区二区三区免费看| 亚洲欧美乱综合| 黄色片视频免费观看| 日本不卡123| 99er在线视频| 神马午夜久久| 91亚洲精品一区二区| 欧美一级鲁丝片| 久久精品一本久久99精品| 日批视频免费播放| 欧美日韩和欧美的一区二区| 久久香蕉精品视频| 欧美激情一区二区三区四区| 国产原创剧情av| 久久www免费人成看片高清| 男人添女荫道口图片| 精品一区av| 国产在线资源一区| 狂野欧美性猛交xxxx| 91极品视频在线| 黄视频网站在线| 亚洲欧美综合图区| 性猛交xxxx乱大交孕妇印度| 欧洲av在线精品| 国产精品日日夜夜| 亚洲欧洲日产国码二区| 中文人妻一区二区三区| 国产一区二区伦理| 免费激情视频在线观看| 亚洲国产91| 91制片厂免费观看| 国产一区二区电影在线观看| 国产99午夜精品一区二区三区 | 欧美日韩成人在线| 亚洲影院在线播放| 亚洲国产精品久久不卡毛片| 少妇高潮惨叫久久久久| 久久久久一区二区三区四区| 少妇熟女视频一区二区三区| 久久 天天综合| 999在线免费视频| 国产精品社区| 国产亚洲黄色片| 亚洲欧美亚洲| 波多野结衣激情| 久久成人综合| 西游记1978| 欧美一区二区三| 日本一区二区久久精品| 亚洲品质自拍| 欧美福利精品| 欧美人成在线观看ccc36| 91免费观看| 日本超碰一区二区| 91欧美精品成人综合在线观看| 色综合一本到久久亚洲91| 欧美在线视频免费观看| 成年人在线网站| 91精品国产91久久久久久| 久草在线视频福利| 久久久久久久激情视频| 成人免费高清观看| 欧美国产精品人人做人人爱| 婷婷在线播放| 欧美激情精品久久久久久免费印度| 在线观看操人| 色综合天天综合网国产成人网 | 国产综合视频在线观看| 免费成人高清在线视频| 国产日韩欧美在线观看| 日本午夜精品久久久久| 成人激情视频免费在线| 麻豆久久一区| 狠狠色综合色区| 伊人久久大香线蕉无限次| 欧美一区二区福利| jlzzjlzz亚洲女人| 国产高清精品软男同| 在线一区电影| 国产精品视频网站在线观看| 日韩视频一区二区三区在线播放免费观看| 自拍日韩亚洲一区在线| 亚洲中午字幕| 在线观看高清免费视频| 国内成人精品2018免费看| 少妇丰满尤物大尺度写真| 丁香激情综合五月| a级大片在线观看| 国产精品免费观看视频| 人妻少妇精品一区二区三区| 亚洲高清三级视频| 波多野结衣啪啪| 欧美另类z0zxhd电影| 亚洲福利在线观看视频| 亚洲男人天堂视频| 免费在线观看黄色| 欧美激情亚洲综合一区| 性欧美18xxxhd| 成人激情在线观看| 欧美巨大xxxx| 一级日韩一区在线观看| 欧美日韩精品| 无需播放器的av| 国产成人精品在线看| 熟女少妇内射日韩亚洲| 亚洲精品成人悠悠色影视| 国产精品100| 欧美一区二区福利视频| 天堂av在线7| 久久精品亚洲一区| 国产伦精品一区二区三区视频金莲| 国产精品中文字幕在线| 久久人人爽人人爽人人片av不| 亚洲精品人成| 国产一区二区三区成人欧美日韩在线观看 | 日韩午夜av一区| 毛片在线播放网站| 欧美日韩国产成人高清视频| 免费高清视频在线一区| 国产三级精品在线不卡| 亚洲乱码免费伦视频| 亚洲中文字幕无码专区| 国产精品综合视频| 免费在线观看a视频| 性久久久久久久| 国产av一区二区三区精品| 中文字幕不卡av| 欧美理论影院| 狠狠色狠狠色综合人人| 中国精品18videos性欧美| 天美星空大象mv在线观看视频| 成人天堂资源www在线| 中文字幕乱码av| 色播五月激情综合网| 日批视频免费播放| 欧美激情中文网| 97久久精品一区二区三区的观看方式| 欧美精品一区在线| a91a精品视频在线观看| 欧美污在线观看| 日韩一区在线免费观看| 波多野结衣小视频| 亚洲毛片在线免费观看| 国产激情在线播放| 99在线视频播放| 亚洲欧美色图| 色天使在线观看| 国产精品沙发午睡系列990531| 男人天堂av在线播放| 日韩精品极品在线观看播放免费视频| 福利在线导航136| 俄罗斯精品一区二区| 欧美日本一区| 成人性生交视频免费观看| 中文字幕一区二区三区乱码在线| 久久国产乱子伦精品| 亚洲品质视频自拍网| jk漫画禁漫成人入口| 欧美人xxxxx| 免费在线亚洲欧美| 中文字幕狠狠干| 欧美视频免费在线观看| 婷婷五月综合久久中文字幕| 性色av一区二区三区在线观看 | 欧美日韩亚洲综合一区二区三区激情在线| 精品动漫3d一区二区三区免费| 欧美熟妇精品一区二区| 亚洲一区二区三区四区的 | 影音先锋欧美精品| 成人免费在线观看视频| 亚洲精品一品区二品区三品区 | 日本免费视频在线观看| 国产一区视频在线| 在线成人激情| 深夜视频在线观看| 精品日本美女福利在线观看| 午夜影院免费体验区| 国产成人精品999| 日韩综合在线| 手机av在线网站| 亚洲成人自拍偷拍| 欧美女v视频| 国产精品无av码在线观看| 亚洲激情中文在线| 稀缺呦国内精品呦| 色综合久久久久综合| 97在线观看免费观看高清| 成人在线一区二区| 最新亚洲视频| 影音先锋制服丝袜| 日韩欧美精品在线| 日韩电影毛片| 一区二区不卡在线观看| 国产成人亚洲综合a∨婷婷| 日韩欧美一级视频| 中文字幕一区二区精品| 玖玖玖视频精品| 欧美 激情 在线| 日韩美女久久久| 完全免费av在线播放| 91精品国产色综合久久| av老司机在线观看| 亚洲精品欧美精品| 成人美女视频在线观看| 免费精品一区二区| 久久99久久99精品免观看粉嫩| 日韩欧美在线精品| 一起操在线视频| 精品久久香蕉国产线看观看gif| 成人jjav| 国产精品区一区| 热久久免费视频| 国产香蕉在线视频| 色偷偷av亚洲男人的天堂| 欧美美女在线直播| 久久发布国产伦子伦精品| 在线视频中文字幕一区二区| 成人黄色在线电影| 视频在线观看成人| 不卡的av电影在线观看| 一区二区日韩视频|