Pull to refresh

Делаем мэш-ап Twitter'а и Google Maps за 20 минут на Grails

Reading time 14 min
Views 3.3K
Original author: Vladimir Grichina

Введение


Для многих разработчиков Java часто является синонимом ужасно занудных корпоративных приложений. Она ассоциируется с многочисленными конфигурационными файлами формата XML, шаблонным кодом и т.д. Поэтому как правило вместо нее разработчики используют динамические языки (такие как Ruby, Python, PHP) для разработки своих проектов, особенно для простых утилит, мэш-апов и т.п.

Однако в среде Java многое изменилось за последние несколько лет. Появилось много фрейморков освобождающих разрабочика от бремени корпоративных («энтерпрайзных») приложений. Grails вероятно — один из лучших. Он основан на Groovy, динамическом языке на платформе Java. Groovy создан специально для Java-программистов и переход на него максимально безболезненый. Grails используе хорошо известные, надежные и эффективные библиотеки Java (Spring, Hibernate и т.п.) для выполнения всей тяжелой работы. Существует также система плагинов и плагины для почти для всех широко используемых библиотек Java.

В этом посте я раскажу, как сделать мэш-ап из Twitter'а и Google Maps в течении всего 20 минут. Конечный результат будет выглядеть примерно следующим образом:
Geo Twitter Complete



Подготовка среды разработки


Сначала неплохо бы убедится, что установлена правильная версия JDK. Лучше всего просто скачать последнюю версию JDK здесь.
Установите ее и установите переменную среды JAVA_HOME так чтоб она указывала на каталог установки.

Затем скачайте последний релиз Grails отсюда.
Распакуйте архив в любое место, а затем установите переменную среды GRAILS_HOME чтоб она указывала на каталог в который был распакован архив. Также убедитесь что подкаталог bin/ каталога установки Grails упоминается в переменной окружения PATH.

После выполнения вышеупомянутых шагов будет возможно запускать команды Grails в консоли. Можно набрать grails help чтоб проверить это. Должен появится список доступных команд.

Основные понятия


Grails основан на шаблоне проектирования MVC. Модель представлена в domain-классах, контроллеры классами контроллеров, отображение — GSP страницами. В этом проекте используются только классы контроллеров и GSP, так как модель предоставляется Twitter API.

Не помешает прочитать краткое руководство пользователя для начала. Дополнительную информацию можно получить в руководстве пользователя. В частности, в этом посте пригодится информация о контроллерах и GSP.

Создание каркаса приложения


Одна из возможностей Grails освобождающая разработчика от «энтерпрайзного» бремени Java — возможность автоматически генерировать каркас основного приложения.
Чтобы сделать это просто наберите:

grails create-app geo_twitter

Это создаст приложение geo_twitter в текущем рабочем каталоге. Перейдите в этот каталог для всех дальнейших шагов.

Приступая к работе с Google Maps


Интеграция Google Maps проста и хорошо поддерживается Google. Однако вам сначала нужно получить ключ API, чтобы получить доступ ко всем услугам. Не бойтесь — это просто, быстро и бесплатно.

Для начала неплохо бы подчистить основной шаблон разметки (layout) — можно удалить логотип Grails и т.д. Откройте grails-app/views/layout/main.gsp и исправьте так, чтоб он выглядел следующим образом:

<html>
    <head>
        <title><g:layoutTitle default="Grails" /></title>
        <link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" />
        <link rel="shortcut icon" href="${resource(dir:'images',file:'favicon.ico')}" type="image/x-icon" />
        <g:layoutHead />
    </head>
    <body>
        <g:layoutBody />
    </body>
</html>


Потом отредактируйте grails-app/views/index.gsp чтоб интергрировать Google Maps как то так:

<html>
    <head>
        <title>Welcome to GeoTwitter!</title>
        <meta name="layout" content="main" />

        <script src="www.google.com/jsapi?key=YOUR_GOOGLE_MAPS_API_KEY" type="text/javascript"></script>

        <script type="text/javascript">
            google.load("maps", "2.x");
            google.load("jquery", "1.3.1");
        
            google.setOnLoadCallback(function() {
                $(document).ready(function() {
                    var map = new GMap2(document.getElementById('map'));
                    var vinnitsa = new GLatLng(49.2325477, 28.4744695); // Replace this by coordinates of your own city ;)
                    map.setCenter(vinnitsa, 8);
                    map.addControl(new GLargeMapControl());
                });
            });
        </script>
    </head>
    <body>
        <div id="map" style="width:800px; height:600px">
        </div>
    </body>
</html>


Конечный результат будет выглядеть как-то так:

Geo Twitter Start

Форма для Twitter'а и верстка


Добавьте простую форму с именем пользователя на страницу index.gsp.

<div class="form">
    <form action="" id="twitter">
        <p>
            <label>twitter id:</label>
            <input type="text" id="name" name="name" value=""/>
        </p>
        <p class="submit">
            <input type="submit" value="Map my friends!">
        </p>
    </form>
</div>


Затем замените основные стили в web-app/css/main.css на что-то вроде этого:

body {
    font-family: Verdana, Helvetica, sans-serif;
    margin: 1em;
}

#map {
    position: absolute;
    width: 800px;
    height: 600px;
    left: 19em;
    top: 1em;
}

.form {
    border: 1px dashed gray;
    width: 15em;
    padding: 0.5em;
}

.form label {
    width: 7em;
    display: block;
    float: left;
}

.form input {
    width: 10em;
}

.form .submit {
    padding-left: 7em;
}


Вы получите нечто подобное:
Geo Twitter Login Form


Немного особой Grails-магии серверной логики


Чтобы сделать что-то на самом деле работает, нужно добавить серверную логику. Сначала установим плагин Grails для работы с Twitter.

grails install-plugin twitter

Теперь нам нужно создать контроллер, который будет выдавать список друзей из Twitter с информацией об их местонахождении и т.д.

grails create-controller Twitter

Команда выше сгенерирует файл grails-app/controllers/TwitterController.groovy со скелетом контроллера. Его надо заменить реализацией контроллера который будет выдавать информацию о друзьях в формате JSON. Он будет также обращаться к сервису геокодирования, чтобы получать координаты на карте по имени данной местности.

import grails.converters.*

class TwitterController {
    // Google Maps API key
    static def API_KEY = "Insert your Google Maps API key here"

    // TwitterService instance will be injected into this variable by Spring
    def twitterService

    def friendsJson = {
        // Get friends of given user
        def friends = getFriends(params.name)
        // Render friends list as JSON
        render(friends as JSON)
    }

    private def getFriends(String userName) {
        def friends = twitterService.getFriends(params.name)
        
        // Return only the needed fields for each user and retrieve coordinates for location
        friends.collect { it ->
            [
                screenName: it.screenName,
                name: it.name,
                pictureUrl: it.profileImageUrl as String,
                bio: it.description,
                status: it.status?.text,
                coords: getCoordsFromLocation(it.location)
            ]    
        }
    }
    
    /**
     * This method gets coordinates on map for given location string.
     */

    private def getCoordsFromLocation(String location) {
        if (location) {
            if (location.contains("iPhone:")) {
                // There can be coords specified in location
                // like iPhone: 39.035248,-77.138687
                location = location.replace("iPhone: ", "")
                def parts = location.split(",")
                return [latitude: parts[0], longitude: parts[1]]
            } else {
                // Encode location as URL
                def encodedLocation = URLEncoder.encode(location)
                // Call web service by retrieving URL content
                def response = 
                    "maps.google.com/maps/geo?q=${encodedLocation}&output=xml&key=${API_KEY}".toURL().getText()
                // Parse response XML
                def root = new XmlSlurper().parseText(response)
                if (root.Response.Placemark.size() == 1) {
                    def coords = root.Response.Placemark.Point.coordinates.text()
                    def parts = coords.split(",")
                    if (parts.size() > 1) {
                        return [latitude: parts[1] as Double, longitude: parts[0] as Double]
                    }
                }
            }
        }

        // No coordinates are determined
        return null
    }
}


Использование AJAX для получения данных от сервера


После того как мы написали логику контроллера, нужно написать JS код, который будет получать данные с сервера и отображать их на карте. Этот код можно разместить в обработчике отправки формы, но сначала надо задать правильное действие для формы:
action="${createLink(controller: 'twitter', action: 'friendsJson'}"

Потом добавим обработчик в index.gsp, наподобие:

google.load("maps""2.x");
google.load("jquery""1.3.1");

google.setOnLoadCallback(function() {
    $(document).ready(function() {
        // Create and configure Google Map control
        var map = new GMap2(document.getElementById("map"));
        var vinnitsa = new GLatLng(49.232547728.4744695);
        map.setCenter(vinnitsa, 4);
        map.addControl(new GLargeMapControl());
        // Add form submit handler
        var form = $("#twitter");
        form.submit(function() {
            $.getJSON(form.attr("action"+ "?" + form.serialize(), function (data) {
                // Clear all markers
                map.clearOverlays();
                // Loop through friends list and add markers to map
                $.each(data, function (i, item) {
                    if (item.coords) {
                        var marker = new GMarker(new GLatLng(item.coords.latitude, item.coords.longitude));
                        map.addOverlay(marker);
                        var popup = '<img style="width: 48px; height:48px;" src="' + item.pictureUrl + '">' + 
                            item.name + ' (' + item.screenName + ') <br>' + 
                            item.bio + '<br>' + item.status;
                        GEvent.addListener(marker, "click"function() {
                            marker.openInfoWindowHtml(popup);
                        });
                    }
                });
            });
            // Indicate that form should not actually be submitted
            return false;
        });
    });
});


Теперь, когда вы введете имя и нажмете кнопку «Map my friends!» получите следующую картину:

Geo Twitter Complete

Демо и исходники


  • Исходники демо-проекта можно взять в репозитории GitHub
  • Демо можно посмотреть на нашем демо-сервере (смотрите ссылку в блоге на английском), если он не упадет, а он таки упадет :)


Полезно почитать еще


Tags:
Hubs:
+23
Comments 44
Comments Comments 44

Articles