Федеральное агентство железнодорожного транспорта
Омский государственный университет путей сообщения
Кафедра «Автоматика и системы управления»
К ЗАЩИТЕ ДОПУСТИТЬ
____________
«___»_____________2017 г.
РАЗРАБОТКА ПРИЛОЖЕНИЯ НА ПЛАТФОРМЕ JAVA
Пояснительная записка к курсовой работе
ИНМВ.400000.000 ПЗ
Студент гр. 23 - и ____________ «__»________2017 г. Руководитель – доцент кафедры АиСУ ____________ «__»________2017 г. |
Омск 2017
Реферат
УДК 681.3.06
Пояснительная записка к курсовой работе содержит 17 страниц, 8 рисунков, 5 использованных источников, 4 приложения.
Spring, JUnit, Mock-объект, Spring Boot, Maven, Kotlin, data-class, веб-сервер.
Объектом курсовой работы является веб-сервер.
Цель курсовой работы – реализовать веб-сервер с JPA с помощью фреймворка Spring.
Результатом курсовой работы является рабочий веб-сервер с базой данных.
Веб-сервер разработан с использованием среды программирования IntelliJ IDEA Communiy Edition 2016.3. Исходный код программы написан на языке Java v.8 и Kotlin v.1.1.0. Пояснительная записка выполнена в текстовом редакторе Microsoft Word 2007.
Содержание
Введение 4
1 Spring Framework 5
1.1 Spring MVC 5
1.2 Maven 5
2 JPA 6
3 Kotlin 7
4 Запуск и тестирование веб-сервера 8
4.1 Запуск веб-сервера 8
4.2 Тестирование веб-сервера 8
Заключение 10
Библиографический список 11
одержимое файла pom. xml 12
истинги класса и интерфейса для JPA 14
истинги класса контроллера и точки запуска сервера 15
истинг класса тестирования 16
Введение
В настоящее время особой ценностью является информация, доступ к которой можно получить с помощью сети интернет. Интернет представляет собой совокупность веб-серверов, которые отвечают на запросы пользователя и предоставляют необходимую информацию.
Веб-сервер — сервер, принимающий HTTP-запросы от клиентов, обычно веб-браузеров, и выдающий им HTTP-ответы, как правило, вместе с HTML-страницей, изображением, файлом, медиа-потоком или другими данными.
Клиент, которым обычно является веб-браузер, передаёт веб-серверу запросы на получение ресурсов, обозначенных URL-адресами.
Веб-сервер можно создать программным путем с помощью разнообразных фреймоворков.
Фреймворк – это программный код, предназначенный для решения типичной задачи. В отличии от библиотечного метода, работа фреймворка зависит не от переданных методу агрументов, а модифицируется изменением участвующих в работе классов и объектов.
Целью данной работы является создание REST-сервера с JPA, который бы выполнял набор CRUD команд. Сервер должен создаваться с помощью фреймворка Spring, включать в себя класс на языке Kotlin и компоноваться системой сборки Maven. Сервер должен быть протестирован с помощью mock-объектов JUnit тестами.
1 Spring Framework
Spring Framework обеспечивает комплексную модель разработки и конфигурации для современных бизнес-приложений на Java - на любых платформах. Ключевой элемент Spring - поддержка инфраструктуры на уровне приложения: основное внимание уделяется "водопроводу" бизнес-приложений, поэтому разработчики могут сосредоточиться на бизнес-логике без лишних настроек в зависимости от среды исполнения.
1.1 Spring MVC
Один из самых главных разделов фреймворка Spring — Spring MVC. Фреймворк Spring Web model-view-controller (MVC) работает вокруг DispatcherServlet, который распределяет запросы по обработчикам. В нём настраивается мэппинг запросов, локали, временные зоны и многое другое. Обработчик по умолчанию строится на аннотациях @Controller и @RequestMapping, которые предоставляют широкий набор гибких методов для обработки запросов. После версии Spring 3.0. механизм @Controller так же позволяет создавать RESTful веб сайты и приложения, используя аннотацию @PathVariable и другие возможности.
В Spring Web MVC есть возможность использовать любой объект в качестве команды или объекта с обратной связью; нет необходимости реализовывать какой-либо специальный интерфейс фреймворка или базовый класс. Связывание данных в Spring является очень гибким: например, оно рассматривает несоответствие типов как ошибки валидации и поэтому это может быть обработано в приложении, а не в качестве системных ошибок. Таким образом, вам не нужно дублировать свойства бизнес-объектов, в качестве простых нетипизированных строк для ваших объектов форм. Поэтому можно легко обрабатывать неправильные подтверждения или правильно конвертировать их в строки. Вместо этого, желательно связывать такие объекты напрямую с объектами бизнес логики.
1.2 Maven
Maven – это фреймворк для автоматизации сборки проектов специфицированных на XML-языке. Сборка происходит по установленным зависимостям в файле pom. xml. Чтобы добавить или исключить какие-либо библиотеки или плагины в сборке проекта, достаточно просто указать зависимость в файле pom. xml и Maven автоматически его подключит и встроит в проект. Также в. xml файле указываются зависимости Spring Boot.
В Spring Boot уже включена Spring-платформа и сторонние библиотеки, для более простого запуска приложений. Пример файла pom. xml из проекта веб-сервера можно увидеть в приложении А.
2 JPA
JPA – это технология, обеспечивающая объектно-реляционное отображение простых JAVA объектов и предоставляющая API для сохранения, получения и управления такими объектами.
Сам JPA не умеет ни сохранять, ни управлять объектами, JPA только определяет правила: как что-то будет действовать. JPA также определяет интерфейсы, которые должны будут быть реализованы провайдерами. Плюс к этому JPA определяет правила о том, как должны описываться метаданные отображения и о том, как должны работать провайдеры. Дальше, каждый провайдер, реализуя JPA определяет получение, сохранение и управление объектами. У каждого провайдера реализация разная.
У JPA существуют разные реализации:
– Hibernate
– Oracle TopLink
– Apache OpenJPA
Наиболее высокую популярность среди этих реализаций завоевала Hibernate. Эта технология является ORM-решением для языка Java. ORM – это отображение объектов какого-либо объектно-ориентированного языка в структуры реляционных баз данных. Hibernate не только создает связи между Java классами и таблицами баз данных, но также предоставляет средства для автоматического построения запросов и извлечения данных и может значительно уменьшить время разработки. Hibernate генерирует SQL вызовы и освобождает разработчика от ручной обработки результирующего набора данных и конвертации объектов, сохраняя приложение портируемым во все SQL базы данных.
В самом проекте объекты для JPA помечаются аннотациями. Класс, который будет являться сущностью в базе данных, отмечается аннотацией @Entity. Так как этот класс является сущностью для базы данных, в нем должен быть указан ключ, в нашем случае это ID. Интерфейс репозитория – @Repository. Этот интерфейс наследуется от интерфейса JpaRepository<T, F>, где T – объект нашей сущности (класс с пометкой @Entity), а F – должен быть того же типа, что и ID из класса-сущности. При правильном наследовании Spring предоставит реализованные методы указанные в интерфейсе. Пример реализации сущности и репозитория представлен в приложении Б.
3 Kotlin
Kotlin – язык программирования, разработанный компанией JetBrains, работающий на платформе Java. Он использует JDK, как и сама Java, но имеет другой синтаксис. Решение не ново - уже существуют языки, которые так делают: Scala и Closure, например. Появились они, в основном, из-за проблем с самой Java в плане синтаксиса. То есть, Java - язык надежный, хороший, добротный, на нём можно писать серверные приложения, но синтаксис у него, скажем так, излишне многословный. Kotlin помог разработчикам писать программы с меньшим количеством кода. Помимо всего того, что есть в Java, он добавляет вещи из мира функционального программирования. Это значительно облегчает написание кода - делает его короче и выразительнее. Чем меньше кода мы пишем, тем меньше кода нужно поддерживать, писать меньше тестов. Собственно, большинство языков появилось по этой самой причине - поменять синтаксис Java, сделать его более удобным, более прагматичным.
В реализованном проекте используется такая возможность языка как data-class (синтаксис представлен на рисунке 1). Это класс с единственным назначением – хранение данных. Функционал этого класса, зависит от самих данных, которые в нем хранятся. Data-class позволяет избавиться от большого количества шаблонного кода, который используется при создании аналогичного класса на языке Java. Для автоматической генерации конструктора со всеми аргументами нужно задать начальные значения всех полей. А перед тем как добавить объект на постоянное хранение, его также нужно создать в памяти, для этого создается вторичный конструктор с двумя параметрами. Пример выполнения данных действий представлен в приложении Б.
![]()
Рисунок 1 – Создание data-class на языке Kotlin
4 Запуск и тестирование веб-сервера
4.1 Запуск веб-сервера
Для запуска веб-сервера необходимо создать контроллер, который будет реагировать на определенные действия пользователя. Так как реализуется REST-сервер, то необходимо создать основные команды сервера: GET, POST, DELETE, PUT. Контроллер будет реагировать на введенный адрес, находить его на своей карте запросов и выполнять нужное действие. Например, при введении в строку веб-браузера значения «/expenses», то контроллер среди всех своих команд, найдет именно его, увидит, что здесь присутствует реализация запроса GET и данные находятся в формате json. Затем выполнит метод указанный для этого запроса, в нашем случае это метод getExpenses(), который в своем теле вызывает функцию из JpaRepository (рисунок 2). Результат выполнения можно увидеть на рисунке 3.
![]()
Рисунок 2 – Реализация реакции контроллера на запрос GET

Рисунок 3 – Ответ на запрос GET
Также существует «точечный» вариант запроса GET, который возвращает только 1 элемент из всех на сервере. Метод запроса и ответ сервера можно увидеть на рисунках 4 и 5 соответственно.
![]()
Рисунок 4 – Реализация реакции на контроллера на запрос GET по ID

Рисунок 5 – Ответ на запрос GET по ID
4.2 Тестирование веб-сервера
Spring test позволяет писать JUnit тесты для сервера. Для этого создается mock-объект (объект-имитация), который будет симулировать действия клиента. Объекты этого класса умеют делать запросы к серверу, получать и анализировать ответы. Для создания mock-объекта в Spring требуется объект типа WebApplicationContext, который создается при запуске сервера. Аннотация @Autowired указывает Spring инициализировать ссылку на соответствующий объект. Аннотация @Before, указывает на метод, который будет запускаться перед всеми тестами и создавать Mock-объект (рисунок 6).

Рисунок 6 – Создание Mock-объекта для тестирования сервера
Функции тестирования помечаются аннотацией @Test и выглядят следующим образом. Создается объект класса ResultActions, который может проверить правильность ответа, полученного запросом от Mock-объекта. Например, на рисунке 7, показана функция тестирования запроса DELETE. С помощью Mock-объекта отправляется запрос на сервер и результат сохраняется в объекте perform типа ResultActions. С помощью функции andExpect(status().isOk) проходит проверка правильно ли выполнился запрос и какой статус вернул сервер. Затем создается новы объект типа ResultActions, чтобы проверить метод DELETE, путем просмотра данных с сервера. Если элементов стало на единицу меньше чем было, проверка происходит с помощью jsonPath, значит тест пройден успешно (рисунок 8). Листинг класса тестирования находится в приложении Г.

Рисунок 7 – Пример функции тестирования

Рисунок 8 – Результаты тестирования веб-сервера
Заключение
В данной работе был рассмотрен базовый функционал фреймворка Spring и JPA. Произведено знакомство с современным языком программирования Kotlin и реализация класса на нем.
Полученный веб-сервер полностью функционирует, корректно отвечает на все запросы и хранит в себе базу данных.
Функциональность сервера проверена с помощью JUnit тестов и использованием Mock-объектов.
Библиографический список
Spring MVC [Электронный ресурс] / Режим доступа: http://javastudy. ru/spring-mvc/spring-mvc-basic/ JUnit [Электронный ресурс] / Режим доступа: https://habrahabr. ru/post/120101/ Классы данных [Электронный ресурс] / Режим доступа: https://kotlinlang. ru/docs/reference/data-classes. html Maven [Электронный ресурс] / Режим доступа: http://www. apache-maven. ru/ СТП ОмГУПС-1.2-2005. Работы студенческие учебные и выпускные квалификационные: общие требования и правила оформления текстовых документов. – Омский Государственный Университет Путей Сообщения, Омск, 2005. 28с.
Приложение А
Содержимое файла pom. xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven. apache. org/POM/4.0.0" xmlns:xsi="http://www. w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven. apache. org/POM/4.0.0 http://maven. apache. org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com. example</groupId>
<artifactId>Jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Jpa</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org. springframework. boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project. build. sourceEncoding>UTF-8</project. build. sourceEncoding>
<project. reporting. outputEncoding>UTF-8</project. reporting. outputEncoding>
<java. version>1.8</java. version>
<kotlin. version>1.1.0</kotlin. version>
</properties>
<dependencies>
<dependency>
<groupId>org. springframework. boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org. springframework. boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com. h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org. springframework. boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org. jetbrains. kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>${kotlin. version}</version>
</dependency>
<dependency>
<groupId>org. jetbrains. kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin. version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org. springframework. boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org. jetbrains. kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin. version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org. apache. maven. plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Приложение Б
Листинги класса и интерфейса для JPA
@Entity
data class Expense (
@Id
@GeneratedValue(strategy = GenerationType. AUTO)
val Id:Long? = null,
val name: String = "Название",
var cost:Float = (-1.0).toFloat(),
val category:String = "Категория"){
constructor(_name:String, _cost:Float, _category:String) : this(
name = _name,
cost = _cost,
category = _category
) {}
}
@Repository
public interface ExpenseRepository extends JpaRepository<Expense, Long> {
Expense findByName(String name);
}
Приложение В
Листинги класса контроллера и точки запуска сервера
@RestController
public class ExpenseController {
private ExpenseRepository expenseRepository;
@Autowired
public ExpenseController (ExpenseRepository expenseRepository) {
this. expenseRepository = expenseRepository;
expenseRepository. save(new Expense("Хлеб", 100, "Еда"));
expenseRepository. save(new Expense("Масло", 10, "Жидкость"));
expenseRepository. save(new Expense("Вода", 70, "Вода"));
}
@RequestMapping(value = "/expenses", method = RequestMethod. GET, headers = "Accept=application/json")
public List<Expense> getExpenses(){
return expenseRepository. findAll();
}
@RequestMapping(value = "/expenses/{id}", method = RequestMethod. GET, headers = "Accept=application/json")
public Expense getExpensesId(@PathVariable Long id){
return expenseRepository. findOne(id);
}
@RequestMapping(value = "/expenses/{id}", method = RequestMethod. DELETE, headers = "Accept=application/json")
public void deleteExpense (@PathVariable Long id){
expenseRepository. delete(id);
}
@RequestMapping(value = "/expenses", method = RequestMethod. POST, headers = "Accept=application/json")
public void postExpense(@RequestBody Expense expense){
expenseRepository. save(expense);
}
@RequestMapping(value = "/expenses", method = RequestMethod. PUT, headers = "Accept=application/json")
public void updateExpense (@RequestBody Expense expense){ expenseRepository. findByName(expense. getName()).setCost(expense. getCost());
Expense exp = expenseRepository. findByName(expense. getName());
expenseRepository. save(exp);
System. out. println(exp);
}
}
@SpringBootApplication
public class JpaApplication {
public static void main(String[] args) {
SpringApplication. run(JpaApplication. class, args);
}
}
Приложение Г
Листинг класса тестирования
@RunWith(SpringRunner. class)
@SpringBootTest
public class JpaApplicationTests {
private MockMvc mockMvc;
private ExpenseController expenseController;
private ExpenseRepository expenseRepository;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setup() throws Exception {
mockMvc = webAppContextSetup(webApplicationContext).build();
}
@Test
public void contextLoads() {
}
@Test
public void getExpenses() throws Exception {
ResultActions perform = mockMvc. perform(get("/expenses"));
perform. andExpect(status().isOk())
.andExpect(jsonPath("$.[1].name", is("Масло")))
.andExpect(jsonPath("$.[1].cost", is(10.)))
.andExpect(jsonPath("$.[1].category", is("Жидкость")));
}
@Test
public void addExpense() throws Exception {
String expens = new ObjectMapper().writeValueAsString(new Expense("Лук", 100, "Растения"));
ResultActions perform = mockMvc. perform(post("/expenses").accept(MediaType. APPLICATION_JSON).contentType(MediaType. APPLICATION_JSON).content(expens));
perform. andExpect(status().isOk());
ResultActions performm = mockMvc. perform(get("/expenses/4"));
performm. andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("Лук")))
.andExpect(jsonPath("$.cost", is(100.)))
.andExpect(jsonPath("$.category", is("Растения")));
}
@Test
public void updateCountry() throws Exception {
String expens = new ObjectMapper().writeValueAsString(new Expense("Хлеб",500, "Еда"));
ResultActions perform = mockMvc. perform(put("/expenses").accept(MediaType. APPLICATION_JSON).contentType(MediaType. APPLICATION_JSON).content(expens));
perform. andExpect(status().isOk());
ResultActions performm = mockMvc. perform(get("/expenses/1"));
performm. andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("Хлеб")))
.andExpect(jsonPath("$.cost", is(500.)))
.andExpect(jsonPath("$.category", is("Еда")));
}
Листинг Г, лист 1
@Test
public void getExpensebyId() throws Exception {
ResultActions perform = mockMvc. perform(get("/expenses/2"));
perform. andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("Масло")))
.andExpect(jsonPath("$.cost", is(10.)))
.andExpect(jsonPath("$.category", is("Жидкость")));
}
@Test
public void deleteExpenses() throws Exception {
ResultActions perform = mockMvc. perform(delete("/expenses/1"));
perform. andExpect(status().isOk());
ResultActions performm = mockMvc. perform(get("/expenses"));
performm. andExpect(jsonPath("$.length()", is(2)));
}
}
Листинг Г, лист 2


