Федеральное агентство железнодорожного транспорта

Омский государственный университет путей сообщения

Кафедра «Автоматика и системы управления»

К ЗАЩИТЕ ДОПУСТИТЬ

____________

«___»_____________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