Автор: MICHAEL R. (Intel) 11 февраля 2015 г.
Тема
В этой статье описывается способ предоставления доступа к серверной базе данных REST с помощью приложения Android* с использованием СУБД MongoDB* и платформы Spring IO*.
Содержание
Введение
По мере роста популярности и развития возможностей смартфонов и планшетов они становятся нашими постоянными, удобными и надежными спутниками в повседневной жизни. В связи с этим перед разработчиками открываются все новые и новые возможности для создания инновационных приложений с целью использования уникальных характеристик мобильных платформ. Компании используют планшеты для предоставления своим клиентам более качественных услуг и увеличения прибыли. Эти устройства подключаются к бекэнд серверу по беспроводному каналу. В качестве одного из сценариев использования можно привести ресторан: посетителям, сидящим за каждым столиком, предлагается планшет, с помощью которого можно просмотреть меню, сделать заказ и оплатить счет. Наличие централизованного внутреннего сервера, с которым взаимодействуют планшеты, обеспечивает новые возможности для управления ресторанным бизнесом, анализа данных, внесения изменений в меню и повышения качества обслуживания. В этой статье рассматривается способ предоставления доступа к серверной базе данных REST с помощью приложения Android*. В первой части статьи рассматриваются используемые средства, настройка среды и создание базы данных для ресторана. Во второй части описывается метод доступа к базе данных с помощью приложения Android.
Средства разработки
При создании пробной версии очень важно найти гибкое решение, которое позволяет быстро настроить и запустить сервер. Платформа Spring IO представляет собой свободное программное решение на базе сервера Apache* Tomcat, совместимое с большим количеством различных баз данных. Эта платформа является удобным средством для организации взаимодействия между клиентом Android и сервером Linux* с помощью интерфейса REST. На стороне сервера используются следующие компоненты: ОС Ubuntu* Linux 14, СУБД MongoDB и платформа Spring IO для реализации архитектуры REST. На стороне клиента используются следующие компоненты: интегрированная среда разработки Android Studio, API-интерфейсы Spring RestTemplate для обращения к серверу, библиотека Jackson для парсинга ответов JSON и конфигурация Android Virtual Device (AVD) для эмуляции устройств Android. Дополнительную информацию об этих компонентах вы найдете по ссылкам ниже.
http://spring.io/understanding/REST
https://developer.android.com/sdk/installing/studio.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.
Создание базы данных
Начальный проект в среде 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.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; } }
Создайте репозиторий базы данных ресторана (RestaurantRepository.java) и определите запросы.
Путь к корневому каталогу базы данных на сервере: http://localhost: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.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 http://localhost:8080/menu
Просмотрите ответ JSON.
В данном примере в базе данных содержится элемент меню «Тако».
{"_links" : {"self" : {"href" : "http://localhost:8080/menu{?page,size,sort}","templated" : true }, "search" : {"href" : "http://localhost:8080/menu/search" } }, "_embedded" : {"menu" : [ {"menuCategoryName" : "Mexican","menuItemName" : "Tacos","menuItemPrice" : "$15","isSpecial" : false,"specialmenuItemPrice" : "$7.50","_links" : {"self" : {"href" : "http://localhost:8080/menu/5488c2ee44ae7e3fab758edd" } } } ] }, "page" : {"size" : 20,"totalElements" : 1,"totalPages" : 1,"number" : 0 } }
Доступ к базе данных
4.1. Настройка прав и зависимостей для проекта Android
Запустите Android Studio и создайте новый проект. После создания проекта необходимо добавить в манифест разрешение на интернет-подключение, а также добавить зависимость Spring RestTemplate и зависимость для парсинга 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' }
Приложению необходим метод обработки и парсинга ответа JSON. Для этого можно создать объекты Java для представления ответа. Библиотека Jackson отлично подходит для парсинга ответа JSON и использования объектов Java. Для ее применения необходимо добавить к объектам Java примечания для библиотеки Jackson. Объекты Java можно создать вручную или воспользоваться удобным средством, которое создает объекты для определенного ответа JSON (http://www.jsonschema2pojo.org/). Ниже показан класс меню для данного примера с примечаниями для библиотеки 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); } }
Доступ к базе данных осуществляется с помощью стандартного HTTP-интерфейса на основе метода REST, который позволяет выполнять такие простые операции, как POST, PUT, GET и DELETE. Модуль RestTemplate предлагает удобный API-интерфейс для выполнения этих операций в классе AsyncTask, что обеспечивает стабильную работу приложения. Приведенные ниже фрагменты кода иллюстрируют способ доступа к базе данных ресторана и управления ею.
Создание экземпляра RestTemplate и пути к серверу.
private RestTemplate rest = new RestTemplate();
private String url = "http://192.168.1.110:8080/menu/";
Активация парсинга JSON с помощью библиотеки Jackson.
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; } }
Заключение
В этой статье описан способ предоставления доступа к серверной базе данных REST с помощью приложения Android. Вначале были рассмотрены необходимые программные средства и процесс настройки среды. Затем был показан пример создания базы данных ресторана и запросов с помощью СУБД MongoDB и платформы Spring IO. В завершение было продемонстрировано использование средств платформы Spring IO в приложении Android для разбора ответа JSON и управления базой данных.
++ Пример исходного кода распространяется на условиях лицензии Intel Sample Source Code License.
Об авторе
Майк Райли (Mike Rylee) — инженер по программному обеспечению в корпорации Intel. В настоящее время он занимается разработкой средств для реализации и поддержки приложений Android.
Дополнительные сведения об оптимизации при компиляции см. в нашем уведомлении об оптимизации.