Thursday, 23.11.2017, 23:12
The Life After Team Site
Главная страница | Разработка простого веб сервиса - Форум | Регистрация | Вход
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
Page 1 of 11
Forum moderator: Ingvord, Helga 
Форум » Проекты команды » Программирование » Разработка простого веб сервиса (как мы это делали)
Разработка простого веб сервиса
IngvordDate: Wednesday, 17.02.2010, 18:42 | Message # 1
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Итак, дорогие друзья, предположим вы, а точнее мы, решили забацать новый интернет сервис... С чего начать?

Ну, во-первых, стоит оценить перспективность проекта... положим проект весьма перспективен.

Во-вторых, необходимо прикинуть инфраструктуру...

В-третьих, выбрать техническую базу (программную, равно как и аппаратную)

Далее увидим по ходу дела, подозреваю, что потребуется реализовать хотя бы beta версию, и с этим идти по Миру искать инвестора.... но до этого ещё далеко.

Здесь рассмотрим техническую сторону вопроса, т.е. предполагается, что проект действительно перспективный. На остальном попытаемся отсановиться по подробнее.


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Wednesday, 24.02.2010, 13:30 | Message # 2
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Так как в итоге планируется разработать простенький веб-сервис (даже без регистрации). Точнее страничку, на которой пользователь по запросу сможет получить интересующую его информацию. Вся бизнес логика данного сервиса уместиться в паре сервлетов smile

Поразмыслив немного, пришли к выводу, что лучшим вариантом инфраструктуры будет следующая связка: javascriptMVC + tomcat + MySQL.

JavaScriptMVC - навороченный фреймворк для разработки сайтов (точнее тонких клиентов) на javascript. Подробнее тут. Мы остановились на версии 1.5.5, так как на мой взгляд она наиболее оптимальна.

Tomcat довольно легковесный servlet контейнер, что нам и требуется. Мы взяли версию 6.20

В качестве транспортного протокола между сервером и клиентом решили взять JSONP. Опять же на мой взгляд с ним гораздо приятнее работать чем с XML, как на серверной стороне так и на клиентской (JQuery forever smile ) тут отличная статья для начинающих.

MySQL - что тут сказать? Всё очевидно. Даже бесплатных хостов с поддержкой MySQL море. Собственно этот факт и стал решающим.

Итак, с инфраструктурой и программной реализацией определились. По поводу аппаратной: на данный момент особо сказать нечего, ясно что это будет некий хост с tomcat и MySQL.


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Thursday, 25.02.2010, 17:20 | Message # 3
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Итак мы подошли к самому главному - непосредственно разработке.

С чего начать? Ну видимо начать придёться с пустого листа. Заходим в свою любимую IDE (jIDEA в частности) и создаём пустой maven2 проект.

Так как мы разрабатываем веб сервис, фактически web приложение, необходимо указать maven'у сей факт: в pom.xml добавляем строчку "<packaging>war</packaging>" в описание проекта. Подробнее про maven war plugin можно почитать тут.

Структура проект при этом должна быть следующая:
/
|--src
|--main
| |--java
| |--javascript
| |--webapp
| |--WEB-INF
| |--web.xml
|--test

В папку javascript распаковываем содержимое архива javascriptMVC.

Далее настраиваем tomcat в IDE. В jIDEA Run->Edit Configuration->'+'->tomcat->local. На вкладке server указываем путь к установке tomcat (желательно чтобы в пути не было пробелов). На вкладке Deployment указываем наш war'ник. Итак рабочее место в целом готово. Мы пока не подключили Data Sources, сделаем это позже. Важно что теперь можно запустить tomcat из под IDE.

Следующим шагом необходимо правильно организовать сборку проекта. Так как щас кроме WEB-INF/web.xml в нашем war ничего нет.

Самым простым решением является просто копирование содержимого из javascript в webapp. Однако - это не совсем правильно, так как таким образом в наш war попадёт много лишнего и весить это чудо будет порядка 9 метров.

Оптимальное решение - перед тем как архивировать проект в war из под maven. Необходимо запускать поставляемый вместе с javascriptMVC компрессор кода и копировать в webapp только то, что действительно нужно для работы сайта. Как это сделать? Ответ - с помощью ant:

Создаем build.xml в root проекта рядом с pom.xml.

Ниже приведены примеры запуска разных команд.

Пример запуска компрессора [утилита, поставляемая вместе с javascriptmvc для сжатия приложения. Подробнее тут](под Windows):

Code
            
<target name="compile-javascript">
                <echo>Compressing javascript...</echo>
                <echo>Executing: js.bat apps/app/compress.js</echo>
                <exec dir="${src}" executable="cmd.exe">
                    <arg value="/c"/>
                    <arg value="js.bat"/>
                    <arg line="apps\\app\\compress.js"/>
                </exec>
            </target>

и копируем только то, что необходимо:

Code

<echo>Copying source files...</echo>
                <copy todir="${build}/jmvc" overwrite="true">
                    <fileset dir="${src}/jmvc">
                        <include name="include.js"/>
                    </fileset>
                </copy>
                <copy todir="${build}/apps" overwrite="true">
                    <fileset dir="${src}/apps">
                        <exclude name="**/compress.js"/>
                        <exclude name="**/test.js"/>
                        <exclude name="**/app_production.html"/>
                    </fileset>
                </copy>
                <copy file="${src}/apps/app/app_production.html" tofile="${build}/index.html"/>

Если всё сделано правильно, то теперь, при запуске tomcat, http://localhost:8080 должен показывать стартовую страничку javascriptMVC. И наш war весить порядка 25 Kb.

Однако работать с клиентской стороной удобнее локально, просто запуская javascript/index.html в браузерею Обратите внимание, что мы копируем app_production.html в webapp/index.html, это сделано для того чтобы не забывать деплоить war на сервер с javascript в продакшн моде (<script language="javascript" type="text/javascript" src="../../jmvc/include.js?app,production"></script>).


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Friday, 26.02.2010, 14:25 | Message # 4
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Ура!

Теперь можно набросать примерчки 'Hello World!' для освоения процесса разработки под javascriptMVC.

Итак шаг 1.

Создаём папочку hello_world в /src/main/javascript/apps.
Добавляем hello_world.js в /src/main/javascript/apps с примерно следующим содержимым:

Code

include.resources();
include.plugins('controller','view');

include(function(){
      include.models();
      include.controllers();
      include.views();
});

В папку hello_world добавляем hello_world_production.html:

Code

<html>
<head>
        <title>Hello World</title>
</head>
<body>
<div id="content"></div>
<script language="javascript" type="text/javascript" src="jmvc/include.js?hello_world,production"></script>
</body>
</html>

Копируем содержимое этого файла с заменой production -> development в /src/main/javascript/index.html

Далее создаём файл /hello_world/compress.js:

Code

MVCOptions = {
     onload: false,
     compress_callback: function(total){
         var compressed = MVCOptions.collect_and_compress(total);
         MVCOptions.save('apps/hello_world/production.js', compressed);
         print("Compressed to 'apps/hello_world/production.js'.");
         var app = new MVCObject.DApplication(total, "hello_world");
         app.generate();
         print("Generated docs.");
     },
     env : "compress"
}

load('jmvc/rhino/compression/htmlparser.js');
load('jmvc/rhino/compression/env.js');
load('jmvc/rhino/compression/helpers.js');

window.location = 'index.html';

Проверить что всё сделано правильно можно собрав проект с нуля (ant+maven[package]) и задеплоив его на сервер. Должна открыться пустая страница с title'ом Hello World smile


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Friday, 26.02.2010, 14:55 | Message # 5
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Продолжаем работу над Hello World.

Шаг 2.

Мы хотим получить простенькое web приложение, из двух страничек. На первой - пользователю предлагается в вести имя. После нажатия кнопки пользователю выдаётся привестсвие: Hello, <имя>!!!

Итак. Создаём контроллер hello_world_controller.js (/src/main/javascript/controllers):

Code

HelloWorldController = MVC.Controller.extend('main',{
         load: function(params){
          document.getElementById('content').innerHTML = new View({url:'views/hello_world_main.ejs'}).render();
         }
});

Незабываем зарегистрировать его в hello_world.js [include.controllers('hello_world');]

Далее создаём views/hello_world_main.ejs:

Code

<input type="text" id="txtName" size="7" value="Enter your name"/>
<input type="button" id="btnOk" value="  OK  "/>

View также необходимо зарегистрировать в hello_world.js [include.views('views/hello_world_main');]. Это необходимо для того, чтобы при компиляции javascript (когда мы вызываем компрессор) все наши view добавились в production.js, что существенно ускоряет их загрузку непосредственно на сайте.

Итак если теперь мы запустим наше приложение, то на страницу должны будут добавиться два input поля: текст и кнопка. Напомню, что такие вещи можно проверять локально, просто открыв index.html в браузере.

Продолжаем. Теперь нам необходимо добавить реакцию на нажатие кнопки. Создаём контроллер button_controller.js:

Code

BtnController = MVC.Controller.extend('btnOk',{
       click: function(params){
        var txtName = document.getElementById('txtName');
           var userName = txtName.value;

           document.getElementById('content').innerHTML = new View({url:'views/hello_world_response.ejs'}).render({data:userName});
       }
});

И views/hello_world_response.ejs:

Code

<h1>Hello, <%= data%>!!!</h1>

Собираем, проверяем что всё работает как ожидалось, радуемся.

Итак мы получили готовое к бою приложение smile

Про .ejs можно почитать тут.
Про привязку контроллеров к элементам на странице тут.

Домашнее задание - написать функциональный тест нашего приложения.


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Friday, 26.02.2010, 15:38 | Message # 6
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Прикрепляю архив с исходниками проекта.
Attachments: site.zip(1675Kb)


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Monday, 01.03.2010, 15:17 | Message # 7
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Итак продолжим разработку нашего сервиса.

Сегодня мы хотим расширить наше приложение, подключив к обработке запроса серверную сторону. В терминах нашего приложения Hello World это означает, что мы хотим отправлять имя пользователя на сервер, изменять его там (например, дописывать слово 'glorious' перед именем) и возвращать обратно.

Напоминаю, в качестве транспортного протокола было решено использовать JSONP. Бизнес логику на сервере реализовывать с помощью servlet технологии.

Шаг 1. На клиентской стороне разрабатываем модель. Про модели в javascriptmvc можно почитать тут.

Создаём hello_world_model.js:

Code

Task = MVC.Model.extend('task',
{
      processName: function(name,callback){
          jQuery.getJSON("http://localhost:8888/hello_world_servlet?name=" + name + "&callback=?", callback);
      }},{})

Не забываем про регистрацию новых сущностей в hello_world.js

Code

include.resources();
include.plugins('controller','view','model');

include(function(){
     include.models('hello_world_model');
     include.controllers('hello_world','button');
     include.views('views/hello_world_main','views/hello_world_response');
});

Всё бы хорошо, да только нашу модель пока нельзя никак использовать. jQuery не определён. А теперь внимание - важный момент: подключение плагина в javascriptmvc. Почему это важно? Так как в терминах javascriptmvc любая функциональность, должна быть оформлена в виде плагина. Это не прихоть разработчиков, так на много одобнее поддерживать и развивать ваш код. Что можно назвать плагином? - Например, это может быть коннектор к базе данных (если вы разрабатываете .hta приложение) итд итп

Поехали в /src/main/javascript/jmvc/plugins создаём папочку jquery, куда помещаем необходимую библиотеку (в нашем случае jquery-1.4.2.min.js). Далее создаём файл setup.js:

Code

include('jquery-1.4.2.min');

Регистрируем плагин в hello_world.js [include.plugins('controller','view','model','jquery');]


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Thursday, 11.03.2010, 16:34 | Message # 8
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Итак продолжим расширять наше риложение за счёт подключения серверной логики.

Создаём сервлет. В IDEE на вкладке web тыкаем правой кнопкой мыши и выбираем New -> Servlet. Далее в диалоге вписываем имя сервлета (MyServlet), package какой понравиться, в нашем случае - test. Помещаем его в src/main/java.

В параметрах сервлета указываем Display Name - JsonServlet.

После этого назначаем servlet-mapping в web.xml:

Code

<!DOCTYPE web-app PUBLIC
       "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
       "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
        <display-name>Archetype Created Web Application</display-name>
          <servlet>
              <servlet-name>MyServlet</servlet-name>
              <display-name>JsonServlet</display-name>
              <servlet-class>test.MyServlet</servlet-class>
          </servlet>
          <servlet-mapping>
              <servlet-name>MyServlet</servlet-name>
              <url-pattern>/json</url-pattern>
          </servlet-mapping>
</web-app>

Добавляем servlet-api:2.3 dependency в pom.xml:

Code

dependency>
               <groupId>javax.servlet</groupId>
               <artifactId>servlet-api</artifactId>
               <version>2.3</version>
           </dependency>

Реализуем наш сервлет:

Code

protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
           String jsonData = getDataAsJson(request.getParameter("name"));
           String output = request.getParameter("callback") + "(" + jsonData + ");";

           response.setContentType("text/javascript");

           PrintWriter out = response.getWriter();
           out.println(output);
       }

Code

private String getDataAsJson(String name) {
           JSONObject o = new JSONObject();

           try {
               o.put("name", "Glorious " + name);
           } catch (JSONException e) {
               return "request failed";
           }

           return o.toString();
       }

Для того чтобы всё скомпилировалось нам также потребуется добавить новую maven dependency - json:20090211

Итак серверную часть завершили. Теперь необходимо реализовать вызов нашего сервлета с клиента. Для этого правим button_controller#click:

Code

click: function(params){
       var txtName = document.getElementById('txtName');
          var userName = txtName.value;

          Task.process(userName,function(response){
              var changedUserName = response.name;

              document.getElementById('content').innerHTML = new View({url:'views/hello_world_response.ejs'}).render({data:changedUserName});
          });
      }

Итак, если теперь пересобрать проект и запустить tomcat после ввода имени мы получим следующий ответ: Hello, Glorious Ingvord!!!

Pretty good, isn't it? cool


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Friday, 19.03.2010, 15:13 | Message # 9
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Прикрепляю исходники.
Attachments: 0411945.zip(1728Kb)


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Friday, 19.03.2010, 15:25 | Message # 10
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Существенной частью любой программы является обработка ошибок. ©

Однако количество повторяющихся ошибок можно снизить, если старательно покрывать разрабатываемую функциональность тестами.

Попробуем проделать сие полезное дело применительно к нашему веб сервису. Начнём с клиентской части. Подробнее про тестирование в javascriptMVC можно почитать тут.

В качестве демонстрации мы разработаем два простых теста: unit и функциональный.

Начнём с функционального теста:

В src/main/javascript/test/functional создаём файл btnOk_controller_test.js:

Code

new Test.Controller('btn',{
    test_click: function(){
           var inpTxt = document.getElementById('txtName');
                   inpTxt.value = 'Ingvord';

     var action = this.Click('#btnOk');          

     this.assert("Hello, Glorious Ingvord!!!",document.getElementById('content').innerText)
    }
},'functional');

Обратим внимание, что имя файла нашего теста ("btnOk_") совпадает с именем контроллера, описанного в файле button_controller.js:1
[BtnController = MVC.Controller.extend('btnOk',{]. А имя самого теста ("btn") совпадает с префиксом имени инстанса контроллера ("BtnController").

Эти манипуляции с именами позволяют javascriptMVC подгружать наши тесты, даже если мы не описали файл test.js в src/main/javascript/apps/hello_world. Чего мы действительно не сделали smile

Итак запускаем наше приложение в тестовом режиме. Для этого необходимо:
1) заменить 'development' на 'test' в index.html;
2) запустить серверную часть (собрать war и запустить tomcat).

Далее открываем index.html в любимом браузере, соглашаемся разрешить поп-апы. После чего откроется консоль тестирования javascriptMVC, с примерно следующим содержанием:

Quote

You are running "hello_world" in the test environment.

Test Controller not found at "test/functional/main_controller_test.js"

Loading: "test/functional/btnOk_controller_test.js"

There is no application test file at:
"apps/hello_world/test.js"
Use it to include your test files.

Test includes:
include.unit_tests('product')
include.functional_tests('widget')

Переходим на вкладку "Functional" и прогоняем тесты. Радостно радуемся тому что все тесты прошли.


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
IngvordDate: Monday, 03.01.2011, 18:13 | Message # 11
TLA Leader
Group: Администраторы
Messages: 189
Reputation: 1
Status: Offline
Пример простой интеграции JavaScriptMVC 3.0.4 с maven.

Для сборки (очистки) JavaScriptMVC приложения используется ant скрипт из build.xml.

В pom.xml на package и clean вызываются соответствующие команды ant.

Примечание: в архиве отсутствует сам JavaScriptMVC фреймворк, так что для корректной работы примера потребуется распаковать javascriptmvc-3.0.4 в <root>/src/main/javascriptmvc

Attachments: business-intell.zip(70Kb)


"Я интересуюсь будущим потому, что собираюсь провести там всю свою жизнь" Чарльз Кеттеринг

Коммунизм и Ислам — такие разные идеологии, а методы и результаты одни и те же

 
Форум » Проекты команды » Программирование » Разработка простого веб сервиса (как мы это делали)
Page 1 of 11
Search:

Copyright TLA © 2006