к оглавлению     к 4GL - визуальным средам       Deutsch

Введение в веб-модель MVC Spring

Здесь показано создание простого веб-приложения MVC с помощью инфраструктуры Spring. В приложении пользователь может ввести свое имя в текстовом поле, и после нажатия кнопки "ОК" это имя отображается на второй странице вместе с приветствием.

Инфраструктура Spring – популярная инфраструктура приложений с открытым кодом, предназначенная для упрощения разработки для J2EE. Она состоит из контейнера, инфраструктуры управления элементами и набора интегрируемых служб для веб-интерфейсов пользователя, транзакций и сохранения состояния. В инфраструктуру Spring входит Spring Web MVC – расширяемая инфраструктура MVC для создания веб-приложений.

Среда IDE обеспечивает встроенную поддержку инфраструктуры Spring версий 3.0 и 2.5. Библиотеки инфраструктуры упакованы вместе с IDE и автоматически добавляются в путь к классам проекта при выборе инфраструктуры. Предоставляются параметры настройки, например, название и отображение Spring Web MVC DispatcherServlet. При создании проекта можно зарегистрировать библиотеку JSTL. Также предоставляется поддержка файлов настройки компонента XML, в т.ч. следующие функциональные возможности:

Для получения дополнительных сведений об инфраструктуре Spring посетите веб-сайт http://www.springsource.org/. Более подробное пояснение поведения артефактов инфраструктуры Spring и их взаимодействия с другими объектами в приложении приведено на официальном сайтеSpring Framework Reference Documentation и в документации Spring Framework API.

Содержание

Для работы с этим учебным курсом требуются программное обеспечение и ресурсы, перечисленные ниже.

Программное обеспечение или ресурс Требуемая версия
Среда IDE NetBeans версия Java 6.9
Комплект для разработчика на языке Java (JDK) версия 6
GlassFish Server Open Source Edition 3.0.1

Примечания

Создание проекта с поддержкой веб-модели MVC Spring

Создание схемы проекта с поддержкой веб-модели MVC Spring

Начните с создания проекта веб-приложения с поддержкой инфраструктуры Spring.

  1. В главном меню "Файл" среды IDE выберите пункт "Создать проект" (сочетание клавиш CTRL+SHIFT+N). Выберите категорию "Java Web", затем выберите проект "Веб-приложение". Нажмите кнопку "Далее".
  2. В поле "Имя проекта" введите HelloSpring. Нажмите кнопку "Далее".
  3. На третьем экране "Сервер и параметры настройки" отключите параметр "Enable Contexts and Dependency Injection", поскольку в данном учебном курсе не используется спецификация JSR-299.

    Также убедитесь, что в выпадающем списке "Server" выбран пункт "GlassFish server 3.0.1", и обратите внимание, что версия Java EE по умолчанию для этого сервера — Java EE 6 Web. Нажмите кнопку "Далее".
  4. На четвертом экране мастера на панели "Frameworks" выберите "Spring Web MVC".
    Spring Web MVC отображается на панели Frameworks
    Обратите внимание, что при выборе Spring Web MVC в путь к классам проекта по умолчанию добавляется библиотека JSTL (JavaServer Pages Standard Tag Library). Отключите этот параметр (как показано на снимке экрана), поскольку в этом учебном курсе не требуется JSTL. Также обратите внимание, что в среде IDE можно добавить к проекту библиотеку Spring 2.5, если это требуется.
  5. Выберите вкладку "Конфигурация" и обратите внимание, что в мастере можно настроить имя и отображение сервлета обработчика Spring.
    Параметры настройки Spring
  6. Нажмите кнопку "Готово". В результате создается проект для всего приложения, в т.ч. все метаданные, а также сценарий сборки проекта Ant, с которым можно ознакомиться в окне "Файлы" (сочетание клавиш CTRL+2; &#8984+2 в Mac OS). Структуру шаблона можно просмотреть в окне "Проекты" (сочетание клавиш CTRL+1; &#8984+1 в Mac OS). Также следует отметить, что по умолчанию в редакторе среды IDE открываются четыре файла: dispatcher-servlet.xml, applicationContext.xml, redirect.jsp и index.jsp.
  7. В окне "Проекты" разверните узел проекта "Библиотеки" и обратите внимание, что архивы JAR Spring включены в путь к классам проекта.
    Архивы JAR Spring указаны в узле проекта "Библиотеки"

Выполнение схемы проекта

Перед изменением файлов проекта следует попытаться запустить созданный проект в среде IDE:

  1. Нажмите кнопку "Выполнить проект" (кнопка "Выполнить проект") на главной панели инструментов среды IDE. В среде IDE автоматически запускается сервер GlassFish, если он не был запущен, проект компилируется и развертывается на сервере. Обратите внимание на данные, отображаемые в окне "Вывод" среды IDE (сочетание клавиш CTRL+4; &#8984+4 в Mac OS). В конце этих данных отображается сообщение BUILD SUCCESSFUL.

    Данные в окне "Вывод", отображаемые при выполнении проекта

    В среде IDE запускается обозреватель по умолчанию, и отображается содержимое представления страницы приветствия (/WEB-INF/jsp/index.jsp).

    Страница приветствия в обозревателе

При выполнении проекта в среде IDE, он компилируется и развертывается на сервере, а затем открывается в обозревателе по умолчанию. Более того, среда IDE предоставляет возможность "Развертывание при сохранении", которая включена по умолчанию для веб-проектов. При сохранении файлов в редакторе проект автоматически компилируется и развертывается на сервере. Для просмотра изменений достаточно просто обновить страницу в обозревателе.

Ключ к пониманию произошедших событий представлен в дескрипторе развертывания проекта (web.xml). Чтобы открыть этот файл в редакторе исходных файлов, щелкните правой кнопкой мыши узел WEB-INF > web.xml в окне "Проекты" и выберите команду "Изменить". Точка входа для приложения по умолчанию — redirect.jsp:

<welcome-file-list>
    <welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>

В файле redirect.jsp содержится инструкция перенаправления, направляющая все запросы в index.htm:

<% response.sendRedirect("index.htm"); %>

Обратите внимание, что в дескрипторе развертывания все шаблоны URL-адресов, соответствующие выражению *.htm отображаются на DispatcherServlet Spring.

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>

Полностью определенное имя сервлета диспетчера сервлета org.springframework.web.servlet.DispatcherServlet. Это класс из библиотеки Spring, которая была добавлена в путь к классам проекта при его создании. Чтобы проверить это, разверните узел "Библиотеки" в окне "Проекты". Найдите файл spring-webmvc-3.0.0.RELEASE.jar, затем разверните его и найдите org.springframework.web.servlet > DispatcherServlet.

DispatcherServlet обрабатывает входящие запросы на основе параметров настройки из файла dispatcher-servlet.xml. Откройте файл dispatcher-servlet.xml, щелкнув его вкладку в редакторе. Обратите внимание на следующий код.

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/index.htm">indexController</prop> </props> </property> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" /> <bean name="indexController" class="org.springframework.web.servlet.mvc.ParameterizableViewController" p:viewName="index" />

В этом файле определены три компонента: indexController, viewResolver и urlMapping. Когда DispatcherServlet получает запрос, соответствующий выражению *.htm, например, index.htm, выполняется поиск контроллера внутри urlMapping, способного обработать этот запрос. Выше можно заметить, что существует свойство mappings, связывающее /index.htm с indexController.

Среда выполнения выполняет поиск определения компонента indexController, предоставляемого схемой проекта. Обратите внимание, что класс indexController расширяет класс ParameterizableViewController. Это еще один класс инфраструктуры Spring, который просто возвращает представление. Также обратите внимание, что p:viewName="index" указывает логическое имя представления, которое разрешается с помощью viewResolver путем добавления /WEB-INF/jsp/ слева и добавления .jsp справа. Это позволяет среде выполнения найти файл в папке приложения и предоставить в ответ представление страницы приветствия (/WEB-INF/jsp/index.jsp).

Обзор приложения

Создаваемое приложение состоит из двух страниц JSP (которые называются представлениями в терминологии MVC). Первое представление содержит форму HTML с полем, в которое пользователь вводит свое имя. Второе представление — страница, на которой отображается приветственное сообщение с именем пользователя.

Представления управляются контроллером, который получает запросы к приложению и принимает решение, какие представления вернуть. Также он передает в представления информацию, которая требуется для их отображения (она называется моделью). Контроллер этого приложения называется HelloController.

В сложном веб-приложении бизнес-логика не размещается непосредственно в контроллере. Вместо этого контроллером используется другой объект — служба — при каждом обращении к бизнес-логике. В этом приложении бизнес-логика ограничена обработкой приветственного сообщения, и для этой цели создается служба HelloService.

Реализация службы

Теперь, после проверки правильности настроек среды, можно начать расширение схемы проекта в соответствии с имеющимися требованиями. Начните с создания класса HelloService.

  1. Нажмите на панели инструментов среды IDE кнопку "Создать файл" (Кнопка "Создать файл"). (Также можно нажать сочетание клавиш CTRL+N; ⌘+N в системе Mac.)
  2. Выберите категорию Java, затем Класс Java и нажмите кнопку "Далее".
  3. В мастере создания класса Java введите имя класса HelloService, затем введите имя пакета service, чтобы создать для класса новый пакет.
  4. Нажмите кнопку "Готово". В среде IDE создается и открывается в редакторе новый класс.

Класс HelloService предоставляет очень простую службу. Он принимает в качестве параметра имя, и подготавливает и возвращает строку, содержащую это имя. Создайте в редакторе следующий метод sayHello() для этого класса (изменения помечены полужирным шрифтом).

public class HelloService {

    public String sayHello(String name) {
        return "Hello " + name + "!";
    }
}

Реализация контроллера и модели

Для обработки пользовательских данных и выбора представления для возврата можно использовать SimpleFormController.

  1. Откройте мастер создания файлов с помощью сочетания клавиш CTRL+N (⌘+N в Mac OS). Выберите категорию Spring Framework и тип файла Simple Form Controller.
    Мастер создания файлов — категория "Spring Framework"
    В среде IDE NetBeans есть шаблоны различных артефактов Spring, включая "Файл конфигурации Spring XML", AbstractController и SimpleFormController.
  2. Нажмите кнопку "Далее".
  3. Назовите класс HelloController и создайте для него новый пакет, для этого введите в поле "Package" текст controller. Нажмите кнопку "Готово". В среде IDE создается и открывается в редакторе новый класс.
  4. Укажите свойства контроллера, раскомментировав методы установки, отображаемые шаблоном класса по умолчанию. Чтобы раскомментировать фрагмент кода, выделите его, как показано на рисунке, и нажмите сочетание клавиш CTRL+/ (&#8984+/ в Mac OS).
    Фрагмент кода, выделенный в редакторе
    Нажатие сочетания клавиш CTRL+/ (&#8984+/ в Mac OS) переключает комментарии в редакторе.
  5. Внесите следующие изменения (показаны полужирным шрифтом).
    public HelloController() {
        setCommandClass(Name.class);
        setCommandName("name");
        setSuccessView("helloView");
        setFormView("nameView");
    }
    Параметр FormView позволяет задать имя представления, используемого для отображения формы. Это страница, содержащая текстовое поле для ввода имени пользователя. Параметр SuccessView аналогичным образом позволяет задать имя представления, отображаемого при успешной передаче данных. Параметр CommandName задает имя команды в модели. В данном случае, команда — это объект формы со связанными параметрами запроса Параметр CommandClass определяет имя класса команды. Экземпляр этого класса заполняется и проверяется на допустимость при каждом запросе.

    Обратите внимание, что для Name в методе setCommandClass() отображается ошибка:
    В редакторе отображается ошибка для setCommandClass()
    Требуется создать класс Name в качестве простого компонента, хранящего данные каждого запроса.
  6. В окне "Проекты" щелкните правой кнопкой мыши узел проекта и выберите команду "Создать > Класс Java". Отображается мастер создания класса Java.
  7. Введите имя класса Name и выберите в выпадающем списке пакет controller.
  8. Нажмите кнопку "Готово". Класс Name будет создан и открыт в редакторе.
  9. В классе Name создайте поле value, затем создайте методы доступа (т.е. методы получения и установки) для этого поля. Сначала объявите поле value:
    public class Name {
    
        private String value;
    
    }

    Чтобы быстро ввести "private" можно ввести "pr" и затем нажать клавишу TAB. Автоматически добавляется модификатор доступа "private". Это пример использования шаблонов кода редактора. Полный список шаблонов кода можно просмотреть, выбрав в меню "Справка" пункт "Таблица сочетаний клавиш".


    В среде IDE предусмотрена возможность автоматического создания методов доступа. В редакторе щелкните правой кнопкой мыши value и выберите команду "Вставить код" или нажмите сочетание клавиш ALT+INSERT (CTRL+I в Mac OS). Во всплывающем меню выберите пункт "Методы получения и установки".
    Всплывающее меню "Создать код" в редакторе
  10. В диалоговом окне выберите параметр value : String и нажмите кнопку "ОК". Методы getValue() и setValue() добавляются к классу Name:
    public String getValue() {
        return value;
    }
    
    public void setValue(String value) {
        this.value = value;
    }
  11. Нажмите сочетание клавиш CTRL+TAB и выберите HelloController, чтобы переключиться обратно к классу HelloController. Обратите внимание, что значок ошибки исчез, поскольку класс Name теперь существует. Удалите метод doSubmitAction() и раскомментируйте метод onSubmit(). Метод onSubmit() позволяет создать собственный ModelAndView, что требуется здесь. Внесите следующие изменения:
    @Override
    protected ModelAndView onSubmit(Object command) throws Exception {
        Name name = (Name)command;
        ModelAndView mv = new ModelAndView(getSuccessView());
        mv.addObject("helloMessage", helloService.sayHello(name.getValue()));
        return mv;
    }
    Как указано выше, command приводится к объекту Name. Создается экземпляр ModelAndView и с помощью метода получения в SimpleFormController создается представление. После этого модель заполняется данными. Единственный элемент модели в данном случае — приветственное сообщение, получаемое из ранее созданной службы HelloService. Для добавления к модели приветственного сообщения можно использовать метод addObject() под именем helloMessage.
  12. Исправьте операторы импорта, щелкнув правой кнопкой мыши в редакторе и выбрав команду "Fix Imports" (сочетание клавиш CTRL+SHIFT+I; ⌘+SHIFT+I в Mac OS).
    Диалоговое окно Fix All Imports
  13. Нажмите кнопку "ОК". В начало файла добавляется следующий оператор импорта:
    import org.springframework.web.servlet.ModelAndView;
    Как указано в документации API, этот класс "представляет модель и представление, возвращаемые контроллером для разрешения DispatcherServlet. Представление может принимать форму имени представления String, которое должно быть разрешено объектом ViewResolver; в качестве альтернативы объект View может быть указан непосредственно. Модель — это объект Map, что позволяет использовать несколько объектов, выбираемых по имени."

    Обратите внимание, что на данном этапе исправлены не все ошибки, поскольку класс по-прежнему не может определить класс HelloService и использовать его метод sayHello().
  14. Внутри HelloController объявите частное поле HelloService:
    private HelloService helloService;
    Затем создайте для поля общедоступный метод установки:
    public void setHelloService(HelloService helloService) {
        this.helloService = helloService;
    }
    Щелкните правой кнопкой мыши в области редактора и выберите команду "Исправить операторы импорта" (сочетание клавиш ALT+SHIFT+I; &#+SHIFT+I на компьютере Mac). В начало файла добавляется следующий оператор импорта:
    import service.HelloService;
    Все ошибки исправлены.
  15. Зарегистрируйте HelloService в файле applicationContext.xml. Откройте в редакторе файл applicationContext.xml и введите следующее определение компонента:
    <bean name="helloService" class="service.HelloService" />
    Поддержка Spring в среде IDE включает в себя автозавершение кода в файлах настройки XML для классов Java и ссылок на компоненты. Для вызова автозавершения кода нажмите сочетание клавиш CTRL+ПРОБЕЛ в редакторе:
    Автозавершение кода при нажатии сочетания клавиш CTRL+ПРОБЕЛ
  16. Зарегистрируйте HelloController в файле dispatcher-servlet.xml. Откройте в редакторе файл dispatcher-servlet.xml и введите следующее определение компонента:
    <bean class="controller.HelloController" p:helloService-ref="helloService"/>

Реализация представлений

Для реализации представлений в проекте требуется создать две страницы JSP. Первая из них, nameView.jsp, служит страницей приветствия и позволяет пользователю ввести имя. На второй, helloView.jsp, отображается приветственное сообщение с введенным именем. Сначала создайте helloView.jsp.

  1. В окне "Проекты" щелкните правой кнопкой мыши узел проекта "HelloWeb" и выберите "New > JSP". Откроется мастер "New JSP File". Введите имя файла helloView.
  2. Нажмите кнопку "Готово". Страница JSP создается в папке jsp и открывается в редакторе.
  3. В редакторе измените заголовок файла на Hello, и измените выходное сообщение для получения helloMessage объекта ModelandView, созданного в HelloController.
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Hello</title>
    </head>
    <body>
        <h1>${helloMessage}</h1>
    </body>
    
  4. Тем же способом создайте вторую страницу JSP, и назовите ее nameView.
  5. В редакторе добавьте следующее определение библиотеки тегов Spring к nameView.jsp.
    <%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>
    При этом импортируется библиотека тегов Spring, содержащая полезные теги для реализации представлений как страниц JSP.
  6. Измените содержимое тегов <title> и <h1> на Enter Your Name.
  7. После тега <h1> введите следующий код:
    <spring:nestedPath path="name">
        <form action="" method="post">
            Name:
            <spring:bind path="value">
                <input type="text" name="${status.expression}" value="${status.value}">
            </spring:bind>
            <input type="submit" value="OK">
        </form>
    </spring:nestedPath>
    
    spring:bind позволяет привязать свойство компонента. Тег привязки обеспечивает состояние и значение привязки, которые используются в качестве имени и значения поля ввода. Таким образом, при передаче формы инфраструктуре Spring будет известен способ извлечения переданного значения. Здесь командный класс (controller.Name) имеет свойство value, поэтому нужно установить path равным value.

    spring:nestedPath позволяет добавить к компоненту слева определенный путь. Поэтому при использовании вместе с spring:bind путь к компоненту становится равным name.value. Как уже указывалось, имя команды HelloControllername. Поэтому этот путь ссылается на свойство value компонента name в контексте страницы.
  8. Измените относительную точку входа для приложения. В настоящий момент точка входа по-прежнему index.htm, что в соответствии с разделом Выполнение схемы проекта, перенаправляется на WEB-INF/jsp/index.jsp. Можно указать точку входа для проекта после его развертывания и запуска. В окне "Проекты" щелкните правой кнопкой мыши узел проекта и выберите "Свойства". Открывается диалоговое окно "Свойства проекта". В области "Категории" выберите "Выполнить". В поле "Относительный URL-адрес" введите /hello.htm и нажмите кнопку "ОК".

    Возникает вопрос: где же располагается отображение hello.htm на HelloController? Отображение не добавлялось к компоненту urlMapping, как в случае страницы приветствия схемы проекта index.htm. Такая возможность обеспечивается средствами автоматизации инфраструктуры Spring, предоставляемыми следующим определением компонента dispatcher-servlet.xml:
    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
    Этот компонент отвечает за автоматическое создание отображения URL-адресов для всех зарегистрированных в файле контроллеров. Из полностью определенного имени контроллера (в данном случае controller.HelloController) удаляется имя пакета и суффикс Controller и затем результат используется как образец URL-адреса. Таким образом, для HelloController создается отображение hello.htm. Это средство, однако, не срабатывает для контроллеров, включенных в инфраструктуру Spring, например, ParameterizableViewController. Для них требуется явное отображение.
  9. В окне "Проекты" щелкните правой кнопкой мыши узел проекта и выберите команду "Выполнить". Проект компилируется, развертывается и выполняется. Открывается обозреватель по умолчанию и отображается hello.htm как nameView проекта:
    nameView в обозревателе
    Введите имя в текстовом поле и нажмите клавишу ВВОД. Отображается helloView с приветственным сообщением:
    helloView в обозревателе

Дополнительные сведения

Это заключительный этап введения в инфраструктуру Spring в среде IDE NetBeans. В этом документе показано создание простого веб-приложения MVC в среде IDE NetBeans с помощью инфраструктуры Spring, и рассмотрен интерфейс среды IDE для разработки веб-приложений.

Рекомендуем продолжить изучение инфраструктуры Spring и изучить другие учебные курсы по среде IDE NetBeans, например, Поэтапная разработка приложения MVC инфраструктуры Spring с помощью NetBeans и GlassFish. Это официальный учебный курс по инфраструктуре Spring Томаса Рисберга (Thomas Risberg), адаптированный к среде IDE NetBeans Арулази Десиасиланом (Arulazi Dhesiaseelan).

Многие возможности модуля Spring среды NetBeans могут применяться и в приложениях инфраструктуры Spring, не связанных с веб.

Для ознакомления с другими связанными учебными курсами обратитесь к следующим материалам:

к оглавлению     к 4GL - визуальным средам       Deutsch

Знаете ли Вы, что объект, Object - Объект в программировании - это программный модуль:
- объединяющий в себе данные (свойства) и операции над ними (методы);
- обладающий свойствами наследования, инкапсуляции и полиморфизма. А объекты взаимодействуют между собой, посылая друг другу сообщения.

НОВОСТИ ФОРУМА

Форум Рыцари теории эфира


Рыцари теории эфира
 10.11.2021 - 12:37: ПЕРСОНАЛИИ - Personalias -> WHO IS WHO - КТО ЕСТЬ КТО - Карим_Хайдаров.
10.11.2021 - 12:36: СОВЕСТЬ - Conscience -> РАСЧЕЛОВЕЧИВАНИЕ ЧЕЛОВЕКА. КОМУ ЭТО НАДО? - Карим_Хайдаров.
10.11.2021 - 12:36: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от д.м.н. Александра Алексеевича Редько - Карим_Хайдаров.
10.11.2021 - 12:35: ЭКОЛОГИЯ - Ecology -> Биологическая безопасность населения - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> Проблема государственного терроризма - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> ПРАВОСУДИЯ.НЕТ - Карим_Хайдаров.
10.11.2021 - 12:34: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вадима Глогера, США - Карим_Хайдаров.
10.11.2021 - 09:18: НОВЫЕ ТЕХНОЛОГИИ - New Technologies -> Волновая генетика Петра Гаряева, 5G-контроль и управление - Карим_Хайдаров.
10.11.2021 - 09:18: ЭКОЛОГИЯ - Ecology -> ЭКОЛОГИЯ ДЛЯ ВСЕХ - Карим_Хайдаров.
10.11.2021 - 09:16: ЭКОЛОГИЯ - Ecology -> ПРОБЛЕМЫ МЕДИЦИНЫ - Карим_Хайдаров.
10.11.2021 - 09:15: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Екатерины Коваленко - Карим_Хайдаров.
10.11.2021 - 09:13: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вильгельма Варкентина - Карим_Хайдаров.
Bourabai Research - Технологии XXI века Bourabai Research Institution