- •Аннотация
- •Cодержание
- •Введение
- •1. Теоретические основы и архитектурные принципы Web-сервисов
- •1.1. Протокол soap и стандарты ws-*
- •1.2. Архитектурный стиль rest
- •1.3. Сравнение форматов данных: xml против json
- •1.4. Сравнительная характеристика подходов
- •2. Проектирование и программная реализация системы
- •2.1. Обоснование выбора стека технологий
- •2.2. Архитектурная организация серверной части
- •2.3. Реализация уровня данных (Data Access Layer)
- •2.4. Реализация soap-сервиса
- •2.5. Реализация rest-сервиса
- •2.6. Реализация клиентского приложения и сбор метрик
- •3. Анализ производительности
- •3.1. Методика тестирования
- •3.2. Результаты тестирования
- •3.2.1. Анализ размера данных (Traffic Overhead)
- •3.2.2. Анализ вычислительной сложности (Parsing Time)
- •3.2.3. Анализ времени загрузки в плохих условиях (Slow 3g)
- •3.3. Итоговое сравнение и выводы
- •Список использованных источников
- •Приложение а Код файла student.Wsdl
- •Листинг программного кода серверной части. Index.Ts
- •Листинг программного кода серверной части. Student.Repository.Ts
- •Листинг программного кода серверной части. Student.Soap.Ts
- •Листинг программного кода серверной части. Rest.Service.Ts
- •Листинг программного кода серверной части. Soap.Service.Ts
- •Листинг программного кода серверной части. ServicePanel.Vue
Листинг программного кода серверной части. Student.Soap.Ts
import { studentService } from '@/student/student.service';
export const soapService = {
StudentService: {
StudentPort: {
getStudent: async function (args: { id: string }) {
const student = await studentService.getStudentById(Number(args.id));
return { student };
},
// НОВЫЙ МЕТОД
getStudents: async function () {
const students = await studentService.getAllStudents();
return { students };
},
createStudent: async function (args: {
name: string;
specialization: string;
course: string;
}) {
const newStudent = await studentService.createStudent({
name: args.name,
specialization: args.specialization,
course: Number(args.course),
});
return { student: newStudent };
},
},
},
};
Листинг программного кода серверной части. Rest.Service.Ts
import type {
Student,
CreateStudentDto,
RequestMetrics,
} from "@/types/student";
const API_URL = "http://localhost:8000/api/students";
// ==========================================
// 1. ХЕЛПЕР ДЛЯ ЗАМЕРОВ (Специфика курсовой)
// ==========================================
async function measure<T>(
label: string,
requestAction: () => Promise<Response>,
): Promise<{ data: T; metrics: RequestMetrics }> {
const startTotal = performance.now();
// 1. СЕТЬ (Скачиваем текст, но не парсим в объект)
const response = await requestAction();
const textData = await response.text();
// 2. ЗАМЕР ПАРСИНГА
const startParse = performance.now();
const jsonData = JSON.parse(textData);
const endParse = performance.now();
const endTotal = performance.now();
const rawString = JSON.stringify(jsonData, null, 2);
return {
data: jsonData,
metrics: {
method: label,
protocol: "REST",
duration: endTotal - startTotal,
parsingTime: endParse - startParse,
dataSize: rawString.length,
rawResponse: rawString,
},
};
}
// ==========================================
// 2. ЭКСПОРТ ДЛЯ UI (Адаптер)
// ==========================================
/*
App.vue импортирует именно это.
ServicePanel получит то, что ждет (данные + метрики),
а внутри мы вызываем чистый pureRestService.
*/
export const restService = {
async getAll() {
return measure("Get List", () => fetch(API_URL));
},
async create(student: CreateStudentDto) {
return measure("Create", () =>
fetch(API_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(student),
}),
);
},
};
Листинг программного кода серверной части. Soap.Service.Ts
import type {
Student,
CreateStudentDto,
RequestMetrics,
} from "@/types/student";
const SOAP_URL = "http://localhost:8000/soap";
async function measure<T>(
label: string,
xmlBody: string,
parseLogic: (rawXml: string) => T,
): Promise<{ data: T; metrics: RequestMetrics }> {
const startTotal = performance.now();
const response = await fetch(SOAP_URL, {
method: "POST",
headers: { "Content-Type": "text/xml" },
body: xmlBody,
});
const textResponse = await response.text();
const startParse = performance.now();
const parsedData = parseLogic(textResponse);
const endParse = performance.now();
const endTotal = performance.now();
return {
data: parsedData,
metrics: {
method: label,
protocol: "SOAP",
duration: endTotal - startTotal,
parsingTime: endParse - startParse,
dataSize: textResponse.length,
rawResponse: textResponse,
},
};
}
export const soapService = {
async getAll() {
const xml = `
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://www.examples.com/wsdl/StudentService.wsdl">
<soapenv:Header/>
<soapenv:Body><tns:getStudentsRequest/></soapenv:Body>
</soapenv:Envelope>`;
return measure<Student[]>("Get List", xml, (rawXml) => {
const parser = new DOMParser();
const doc = parser.parseFromString(rawXml, "text/xml");
const nodes = doc.getElementsByTagName("students");
const students: Student[] = [];
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (!node) continue;
const getId = (tag: string) =>
node.getElementsByTagName(tag)[0]?.textContent;
students.push({
id: Number(getId("id") || 0),
name: getId("name") || "",
specialization: getId("specialization") || "",
course: Number(getId("course") || 0),
});
}
return students;
});
},
async create(student: CreateStudentDto) {
const xml = `
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://www.examples.com/wsdl/StudentService.wsdl">
<soapenv:Header/>
<soapenv:Body>
<tns:createStudentRequest>
<tns:name>${student.name}</tns:name>
<tns:specialization>${student.specialization}</tns:specialization>
<tns:course>${student.course}</tns:course>
</tns:createStudentRequest>
</soapenv:Body>
</soapenv:Envelope>`;
return measure<any>("Create", xml, (rawXml) => {
return rawXml;
});
},
};
