65.9K
CodeProject 正在变化。 阅读更多。
Home

从 Android 应用访问基于 REST 的数据库后端

2015 年 4 月 6 日

CPOL

6分钟阅读

viewsIcon

22034

本文的目的是展示一种使用 MongoDB* 和 Spring IO* 从 Android* 应用访问基于 REST 的数据库后端的方法。

英特尔® 开发人员专区提供用于跨平台应用开发的工具和操作指南、平台和技术信息、代码示例以及同行专业知识,以帮助开发人员创新并取得成功。加入我们的Android物联网英特尔® 实感™ 技术Windows社区,下载工具、访问开发套件、与志同道合的开发人员分享想法,并参与黑客马拉松、比赛、路演和本地活动。

目录

  1. 引言
  2. 使用的工具
    1. 环境设置
  3. 创建数据库
  4. 访问数据库
    1. 设置 Android 项目和权限
    2. 解析 JSON 响应
    3. 操作数据库
  5. 摘要

介绍

随着智能手机和平板设备的性能和普及度不断增长,它们正成为我们日常随身携带、熟练使用和依赖的计算设备中的一部分。这为开发人员提供了持续的创新机会,可以利用移动设备提供的独特便携平台进行软件开发。企业正在其场所部署平板设备,以增强客户体验并提供更大的收入机会。这些设备具有能够与后端服务器通信的无线连接。餐厅是一个有趣的例子,平板设备被部署到每张桌子上,允许客户浏览菜单、准备好后点餐,并在用餐结束后支付账单。拥有一个每个平板电脑都可以与之通信的集中式后端服务器,为餐厅管理、分析、动态菜单和改进服务带来了新的机会。本文讨论了从 Android 应用程序访问基于 REST 的数据库后端的方法。特别是,文章的第一部分将讨论所使用的工具、环境设置以及如何创建餐厅数据库。该

使用的工具

在创建概念验证时,拥有一种灵活的解决方案,能够快速启动并运行服务器,这是非常理想的。Spring IO 平台是一个开源解决方案,它使用 Apache* Tomcat 服务器并与各种数据库配合使用。Spring 提供了一个框架,可以轻松实现 Android 客户端和 Linux* 服务器通过 REST 接口进行通信。服务器端使用的组件包括 Ubuntu* Linux 14 作为操作系统,MongoDB 作为数据库,以及 Spring IO 平台作为 REST 服务。客户端使用的组件包括 Android Studio 作为开发 IDE,Spring REST Template API 用于与服务器通信,Jackson 库用于解析 JSON 响应,以及 AVD 用于 Android 设备模拟。请参阅下面的链接,了解有关这些组件的更多信息。

http://www.ubuntu.com/

https://mongodb.ac.cn/

https://springframework.org.cn/

https://springframework.org.cn/understanding/REST

https://tomcat.net.cn/

https://developer.android.com.cn/sdk/installing/studio.html

https://docs.springframework.org.cn/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html

http://wiki.fasterxml.com/JacksonHome

环境设置

要设置服务器和客户端环境,请按照以下步骤安装 Linux、软件包和 Android Studio。

安装 Ubuntu Linux 14 并连接到本地网络。

http://www.ubuntu.com/download

从终端安装软件包。

MongoDB

				sudo apt-get update

				sudo apt-get install –y mongodb-org

		git

				sudo apt-get install git

		gradle

				sudo apt-get install gradle

		curl

				sudo apt-get install curl

		java

				sudo add-apt-repository ppa:webupd8team/java
				sudo apt-get update
				sudo apt-get install oracle-java8-installer

安装 Android Studio

https://developer.android.com.cn/sdk/index.html

创建数据库

Spring 启动项目为使用 MongoDB 创建持久性后端提供了一个很好的起点,该后端使用 HTTP JSON 接口访问数据库。创建包含菜单项和价格的餐厅数据库非常容易。此外,可以在几行代码中定义查询。请参阅下面的步骤来创建数据库、创建查询和运行服务。

获取 Spring 启动项目。

git clone https://github.com/spring-guides/gs-accessing-mongodb-data-rest.git

进入初始源代码目录。

cd gs-accessing-mongodb-data-rest/initial/src/main/java/hello

创建 Restaurant 对象 (Restaurant.java)。

		
		import org.springframework.data.annotation.Id;
		
		public class Restaurant {

			@Id private String id;

			private String menuCategoryName;

			private String menuItemName;

			private String menuItemPrice;

			private Boolean isSpecial;

			private String specialmenuItemPrice;


			public String getmenuCategoryName() {

				  return menuCategoryName;		
			
			}

			public void setmenuCategoryName(String menuCategoryName) {

				  this.menuCategoryName = menuCategoryName;	  
			
			}

			public String getmenuItemName() {

				  return menuItemName;
			
			}

			public void setmenuItemName(String menuItemName) {

				  this.menuItemName = menuItemName;
			
			}

			public String getmenuItemPrice() {

				  return menuItemPrice;
			
			}

			public void setmenuItemPrice(String menuItemPrice) {

				  this.menuItemPrice = menuItemPrice;
			
			}

			public Boolean getisSpecial(){

				  return isSpecial;
			
			}

			public void setisSpecial(Boolean isSpecial){

				  this.isSpecial = isSpecial;
			
			}

			public String getspecialmenuItemPrice(){

				  return specialmenuItemPrice;
			
			}

			public void setspecialmenuItemPrice(String specialmenuItemPrice){

				  this.specialmenuItemPrice = specialmenuItemPrice;   
			
			}
		
		}

使用查询创建 Restaurant 数据库存储库 (RestaurantRepository.java)。

服务器上数据库根的路径将是 https://:8080/menu。下面定义的接口中有两个查询。findByMenuItemName 允许按 menuItemName 搜索。findByMenuCategoryName 允许按 menuCategoryName 搜索。

		
		import java.util.List;
		
		import org.springframework.data.mongodb.repository.MongoRepository;

		import org.springframework.data.repository.query.Param;

		import org.springframework.data.rest.core.annotation.RepositoryRestResource;

 
		@RepositoryRestResource(collectionResourceRel = "menu", path = "menu")

		public interface RestaurantRepository extends MongoRepository {

			List findByMenuItemName(@Param("name") String name);

			List findByMenuCategoryName(@Param("name") String name);

		}

创建 Application 类 (Application.java)。

下面显示的应用程序类是服务的主要入口点,并包含在服务中使用 Spring IO 和 MongoDB 的配置。

		
		import org.springframework.boot.SpringApplication;

		import org.springframework.boot.autoconfigure.EnableAutoConfiguration;

		import org.springframework.context.annotation.Configuration;

		import org.springframework.context.annotation.Import;

		import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

		import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;

		 
		@Configuration

		@EnableMongoRepositories

		@Import(RepositoryRestMvcConfiguration.class)

		@EnableAutoConfiguration

		public class Application {		 

			   public static void main(String[] args) {

					  SpringApplication.run(Application.class, args);

			   }
		
		}

进入初始目录。

cd gs-accessing-data-mongodb/initial/

使用 Gradle 构建。

./gradlew build

运行服务器。

java –jar build/libs/<project_name>.jar

访问数据库。

curl https://:8080/menu

查看 JSON 响应。

在此示例中,数据库包含一个 Tacos 菜单项

		
		{

			"_links" : {

			"self" : {

			"href" : "https://:8080/menu{?page,size,sort}",

			"templated" : true

				},

			"search" : {

			"href" : "https://:8080/menu/search"

				}

			},

			"_embedded" : {

			"menu" : [ {

			"menuCategoryName" : "Mexican",

			"menuItemName" : "Tacos",

			"menuItemPrice" : "$15",

			"isSpecial" : false,

			"specialmenuItemPrice" : "$7.50",

			"_links" : {

				"self" : {

					"href" : "https://:8080/menu/5488c2ee44ae7e3fab758edd"

					}

				}

			} ]

		},

			"page" : {

			"size" : 20,

			"totalElements" : 1,

			"totalPages" : 1,

			"number" : 0

			}

		}

访问数据库

4.1. 设置 Android 项目权限和依赖项

启动 Android Studio 并创建一个新项目。创建新项目后,需要将互联网权限添加到清单、Spring Rest Template 依赖项和 Jackson JSON 解析依赖项中,如下所示。

将互联网权限添加到清单 (AndroidManifest.xml)。

<uses-permission android:name="android.permission.INTERNET">

添加 RestTemplate 和 Jackson 库依赖项 (build.gradle)。

apply plugin: 'com.android.application'.

		
		android {

			compileSdkVersion 21

			buildToolsVersion "21.1.1"

 
			defaultConfig {

				applicationId "com.example.test.myapplication"

				minSdkVersion 7

				targetSdkVersion 21

				versionCode 1

				versionName "1.0"

			}

			buildTypes {

				release {

					minifyEnabled false

					proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

				}

			}

			packagingOptions {

				exclude 'META-INF/ASL2.0'

				exclude 'META-INF/LICENSE'

				exclude 'META-INF/license.txt'

				exclude 'META-INF/NOTICE'

				exclude 'META-INF/notice.txt'

			}

		}
		
		dependencies {

			compile 'com.android.support:appcompat-v7:+'

			compile fileTree(dir: 'libs', include: ['*.jar'])

			compile 'org.springframework.android:spring-android-rest-template:1.0.1.RELEASE'

			compile 'com.fasterxml.jackson.core:jackson-databind:2.3.2'

		}

4.2. 解析 JSON 响应

该应用需要一种方法来理解 JSON 响应并能够解析它。一种方法是创建表示响应的 Java 对象。Jackson 库是一个方便的库,可用于解析 JSON 响应并使用 Java 对象。要使用此库,Jackson 注解会添加到 Java 对象中。Java 对象可以手动创建,但有一个方便的工具可以帮助为给定 JSON 响应创建它们,网址为 http://www.jsonschema2pojo.org/。此示例的 Menu Class 如下所示,带有 Jackson 注解。

		
		package com.example.test.myapplication;

		import com.fasterxml.jackson.annotation.JsonAnyGetter;

		import com.fasterxml.jackson.annotation.JsonAnySetter;

		import com.fasterxml.jackson.annotation.JsonIgnore;

		import com.fasterxml.jackson.annotation.JsonInclude;

		import com.fasterxml.jackson.annotation.JsonProperty;

		import com.fasterxml.jackson.annotation.JsonPropertyOrder;

		 
		import java.util.HashMap;

		import java.util.Map;

			@JsonInclude(JsonInclude.Include.NON_NULL)

			@JsonPropertyOrder({

				"menuCategoryName",

				"menuItemName",

				"menuItemPrice",

				"isSpecial",

				"specialmenuItemPrice",

				"_links"

			})

		public class Menu {

			@JsonProperty("menuCategoryName")

			private String menuCategoryName;

			@JsonProperty("menuItemName")

			private String menuItemName;

			@JsonProperty("menuItemPrice")

			private String menuItemPrice;

			@JsonProperty("isSpecial")

			private Boolean isSpecial;

			@JsonProperty("specialmenuItemPrice")

			private String specialmenuItemPrice;

			@JsonProperty("_links")

			private Links_ Links;

			@JsonIgnore

			private Map additionalProperties = new HashMap();
	
			
			@JsonProperty("menuCategoryName")

			public String getMenuCategoryName() {

				return menuCategoryName;

			}

 
			@JsonProperty("menuCategoryName")

			public void setMenuCategoryName(String menuCategoryName) { this.menuCategoryName = menuCategoryName; }

 
			@JsonProperty("menuItemName")

			public String getMenuItemName() {

			return menuItemName;

			}

 
			@JsonProperty("menuItemName")

			public void setMenuItemName(String menuItemName) {

				this.menuItemName = menuItemName;

			}

 
			@JsonProperty("menuItemPrice")

			public String getMenuItemPrice() {

				return menuItemPrice;

			}

 
			@JsonProperty("menuItemPrice")

			public void setMenuItemPrice(String menuItemPrice) {

				this.menuItemPrice = menuItemPrice;

			}

 
			@JsonProperty("isSpecial")

			public Boolean getIsSpecial() {

				return isSpecial;

			}

 
			@JsonProperty("isSpecial")

			public void setIsSpecial(Boolean isSpecial) {

				this.isSpecial = isSpecial;

			}

 
			@JsonProperty("specialmenuItemPrice")

			public String getSpecialmenuItemPrice() {

				return specialmenuItemPrice;

			}

 
			@JsonProperty("specialmenuItemPrice")

			public void setSpecialmenuItemPrice(String specialmenuItemPrice) { this.specialmenuItemPrice = specialmenuItemPrice; }

 
			@JsonProperty("_links")

			public Links_ getLinks() {

				return Links;

			}

 
			@JsonProperty("_links")

			public void setLinks(Links_ Links) {

				this.Links = Links;

			}

 
			@JsonAnyGetter

			public Map getAdditionalProperties() {

				return this.additionalProperties;

			}


			@JsonAnySetter

			public void setAdditionalProperty(String name, Object value) { this.additionalProperties.put(name, value); }	 

		}

4.3. 操作数据库

数据库通过基于 REST 的简单 HTTP 接口进行访问,以执行 POST、PUT、GET 和 DELETE 等基本操作。RestTemplate 提供了一个很好的 API,可以在 AsyncTask 中执行这些操作,从而使应用程序保持响应。下面的代码片段显示了如何访问和操作餐厅数据库的示例。

创建 RestTemplate 实例和服务器路径。

             private RestTemplate rest = new RestTemplate();
             
             private String url = "http://192.168.1.110:8080/menu/";

启用 Jackson 库 JSON 解析。

RestTemplate rest = new RestTemplate();

rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

创建菜单项实例

		
		Menu myMenuItem = new Menu();

             myMenuItem.setMenuCategoryName("Mexican");

             myMenuItem.setMenuItemName("Tacos");

             myMenuItem.setMenuItemPrice("$15");

             myMenuItem.setIsSpecial(false);

             myMenuItem.setSpecialmenuItemPrice("$7.50");

向数据库添加新的菜单项 (POST)

添加新的菜单项是一个 POST 操作,它将新的菜单项传递给任务。

		
		new Http_POST_Task().execute(myMenuItem);
		
		private class Http_POST_Task extends AsyncTask {

			@Override

			protected Void doInBackground(Menu... menuItem) {

				try{

				   rest.postForObject(url,menuItem[0],Restaurant.class);

				}

				catch (Exception e) {

					Log.e("MainActivity", e.getMessage(), e);

				}

				return null;

			}

		}

从数据库中删除菜单项 (DELETE)。

删除菜单项是一个 DELETE 操作,它将菜单项传递给任务以进行删除。

		
		new Http_DELETE_Task().execute(myMenuItem);
		
		private class Http_DELETE_Task extends AsyncTask {

			@Override

			protected Void doInBackground(Menu... menuItem) {

				try {

					//DELETE

					String urlStr = menuItem[0].getLinks().getSelf().getHref();

					rest.delete(new URI(urlStr));

				}

				catch (Exception e) {

					Log.e("MainActivity", e.getMessage(), e);

				}
	 
				return null;

			}

		}

在数据库中搜索菜单项 (GET) 搜索菜单项执行 findByMenuItemName 查询以获取指定的菜单项

		try {

			myMenuItem = new Http_findByMenuItemName_Task().execute("Tacos").get();

			} catch (InterruptedException e) {

				e.printStackTrace();

			} catch (ExecutionException e) {

				e.printStackTrace();

			}

		private class Http_findByMenuItemName_Task extends AsyncTask {

			@Override

			protected Menu doInBackground(String... menuItemName) {

				try	{

					String queryURL = url+"search/findByMenuItemName?name="+menuItemName[0];

					Restaurant restaurant = rest.getForObject(queryURL, Restaurant.class);

					return restaurant.getEmbedded().getMenu().get(0);

				}

				catch (Exception e) {

					Log.e("MainActivity", e.getMessage(), e);

				}

				return null;

			}

		}

更新数据库中现有菜单项 (GET) (PUT)。

更新现有菜单项执行 GET 查询操作以获取现有菜单项

		
		try {

			myMenuItem = new Http_findByMenuItemName_Task().execute("Tacos").get();

			} catch (InterruptedException e) {

				e.printStackTrace();

			} catch (ExecutionException e) {

				e.printStackTrace();

			}

修改现有菜单项,然后执行 PUT 操作。

		
		myMenuItem.setMenuCategoryName("Chinese");

		myMenuItem.setMenuItemName("Crab Puffs");

		myMenuItem.setMenuItemPrice("$7");

		myMenuItem.setIsSpecial(true);

		myMenuItem.setSpecialmenuItemPrice("$5");

		new Http_PUT_Task().execute(myMenuItem);

	private class Http_PUT_Task extends AsyncTask<Menu,Void,Void> {

        @Override

        protected Void doInBackground(Menu... menuItem) {

            try {

				String urlStr = menuItem[0].getLinks().getSelf().getHref();

				rest.put(new URI(urlStr),menuItem[0]);

            }

            catch (Exception e) {

                Log.e("MainActivity", e.getMessage(), e);

            }

            return null;

        }

    }

总结

本文展示了一种从 Android 应用程序访问基于 REST 的数据库后端的方法。首先讨论了使用的工具和环境设置。演示了使用 MongoDB 和 Spring IO 创建示例餐厅数据库以及查询。文章最后展示了如何在 Android 应用程序中使用 Spring IO 框架来解析 JSON 响应和操作数据库。

++此示例源代码根据英特尔示例源代码许可发布。

关于作者

Mike Rylee 是英特尔公司的软件工程师。他目前从事 Android 应用启用工作。

© . All rights reserved.