ЛЕКЦ 07: API ДИЗАЙН БА RESTFUL ҮЙЛЧИЛГЭЭ (API Design & RESTful Services)
Хичээлийн зорилго: API-ийн ойлголт, REST архитектурын зарчмууд, HTTP протокол, RESTful API дизайн, Spring Boot ашиглан API хөгжүүлэх, аюулгүй байдал, баримт бичиг зэргийг Java жишээнүүдтэйгээр эзэмшүүлэх.
Хамрах хүрээ: API тодорхойлолт, REST зарчмууд, HTTP методууд, Status Code, URI дизайн, Request/Response, JSON, Spring Boot REST Controller, DTO Pattern, Validation, Exception Handling, Authentication/Authorization, API Versioning, Documentation (OpenAPI/Swagger), HATEOAS, Rate Limiting.
ХЭСЭГ 1: ОНОЛЫН СУУРЬ (Theory & Foundations)
1.1 API гэж юу вэ?
API (Application Programming Interface) — Програм хоорондын харилцааны гэрээ (contract). Нэг програм нөгөө програмтай мэдээлэл солилцох, функц дуудах боломжийг олгоно.
💡 Зүйрлэл: Зоогийн газрын цэс (меню) шиг — та гал тогооны өрөөнд ороод хоол хийхгүй. ЦЭСНЭЭС сонгоод, зөөгч (API) дамжуулж, хоолоо авна. API = Цэс + Зөөгч.
API-ийн төрлүүд:
| # | Төрөл | Тайлбар | Жишээ |
|---|---|---|---|
| 1 | Web API (REST) | HTTP-ээр дамжуулан ажилладаг | GitHub API, Google Maps API |
| 2 | Library API | Сангийн функцүүд | Java Collections API |
| 3 | OS API | Үйлдлийн системийн интерфейс | Windows API, POSIX |
| 4 | Database API | Мэдээллийн сантай харилцах | JDBC, JPA |
| 5 | GraphQL | Query-д суурилсан | GitHub GraphQL API |
| 6 | gRPC | Өндөр гүйцэтгэлтэй RPC | Google-ийн дотоод үйлчилгээ |
API яагаад чухал вэ?
┌──────────────┐ API ┌──────────────┐
│ Frontend │◄────────────►│ Backend │
│ (React, │ HTTP/JSON │ (Spring │
│ Mobile) │ │ Boot) │
└──────────────┘ └──────┬───────┘
│ API
┌──────▼───────┐
│ Database │
│ (PostgreSQL)│
└──────────────┘
┌──────────────┐ API ┌──────────────┐
│ Гадаад │◄────────────►│ Манай │
│ Систем │ │ Систем │
│ (Банк, │ │ │
│ SMS) │ │ │
└──────────────┘ └──────────────┘
- Frontend ↔ Backend хоорондын гүүр
- Мобайл апп ↔ Сервер хоорондын гүүр
- Гадаад систем (төлбөр, SMS, газрын зураг) ашиглах
- Microservice архитектурт үйлчилгээ хоорондын харилцаа
1.2 REST гэж юу вэ?
REST (Representational State Transfer) — Roy Fielding 2000 онд докторын дипломын ажилдаа тодорхойлсон архитектурын хэв маяг (architectural style). Web-ийн стандарт протокол (HTTP) дээр суурилсан.
💡 Зүйрлэл: Шуудангийн систем шиг — Хаяг (URL) + Үйлдэл (GET/POST) + Агуулга (JSON) = Мэдээлэл солилцох.
REST-ийн 6 зарчим:
| # | Зарчим | Англи | Тайлбар |
|---|---|---|---|
| 1 | Клиент-Сервер | Client-Server | Клиент ба сервер тусдаа, бие даасан |
| 2 | Төлөвгүй | Stateless | Сервер клиентийн төлөв хадгалахгүй — хүсэлт бүр бие даасан |
| 3 | Кэшлэх боломжтой | Cacheable | Хариу кэшлэгдэж болно (хурд нэмэх) |
| 4 | Нэгдмэл интерфейс | Uniform Interface | URL, HTTP метод, JSON — нэгдсэн дүрмээр |
| 5 | Давхарт систем | Layered System | Клиент завсрын давхарга (load balancer, proxy) мэдэхгүй |
| 6 | Код дуудах | Code on Demand (заавал биш) | Сервер клиент руу код (JS) илгээж болно |
Stateless (Төлөвгүй) — Яагаад чухал вэ?
// ❌ STATEFUL — Сервер хэрэглэгчийн төлөв хадгална
Хүсэлт 1: "Нэвтрэх" → Сервер: session["user"] = "Бат"
Хүсэлт 2: "Захиалга" → Сервер: session["user"]-аас "Бат" гэж олно
⚠️ Асуудал: Сервер 2 руу шилжвэл session алга!
// ✅ STATELESS — Хүсэлт бүрт бүх мэдээлэл агуулагдана
Хүсэлт 1: "Нэвтрэх" → Сервер: JWT Token буцаана
Хүсэлт 2: "Захиалга" + Token → Сервер: Token-аас "Бат" гэж мэднэ
✅ Аль ч сервер руу очсон ажиллана (scale хялбар)
1.3 HTTP протокол
1.3.1 HTTP методууд (Verbs)
| Метод | Зорилго | Идемпотент | Аюулгүй | CRUD |
|---|---|---|---|---|
| GET | Нөөц авах (уншиx) | ✅ Тийм | ✅ Тийм | Read |
| POST | Шинэ нөөц үүсгэх | ❌ Үгүй | ❌ Үгүй | Create |
| PUT | Нөөц бүхлээр нь солих | ✅ Тийм | ❌ Үгүй | Update (бүхэлд) |
| PATCH | Нөөцийн зарим хэсгийг өөрчлөх | ❌ Үгүй | ❌ Үгүй | Update (хэсэг) |
| DELETE | Нөөц устгах | ✅ Тийм | ❌ Үгүй | Delete |
Идемпотент = Олон удаа дуудсан ч үр дүн ижил.
GET /students/1→ Хэдэн удаа дуудсан ч ижил оюутан буцна.DELETE /students/1→ Нэг удаа устгана, дахин дуудвал "олдсонгүй" (үр дүн ижил — устгагдсан).POST /students→ Дуудах бүрт ШИНЭ оюутан үүснэ (идемпотент БИШ).
1.3.2 HTTP Status Code (Хариуны код)
| Код | Бүлэг | Тайлбар | Жишээ |
|---|---|---|---|
| 200 | ✅ Success | Амжилттай | GET хариу |
| 201 | ✅ Created | Шинэ нөөц үүссэн | POST амжилттай |
| 204 | ✅ No Content | Амжилттай, хариу хоосон | DELETE амжилттай |
| 400 | ❌ Bad Request | Буруу хүсэлт | Validation алдаа |
| 401 | ❌ Unauthorized | Нэвтрэлт шаардлагатай | Token байхгүй |
| 403 | ❌ Forbidden | Хандах эрхгүй | Эрх хүрэлцэхгүй |
| 404 | ❌ Not Found | Нөөц олдсонгүй | ID буруу |
| 405 | ❌ Method Not Allowed | Метод зөвшөөрөгдөхгүй | GET-ийн оронд PUT |
| 409 | ❌ Conflict | Зөрчил | Давхардсан бүртгэл |
| 422 | ❌ Unprocessable Entity | Боловсруулж чадахгүй | Логик алдаа |
| 429 | ❌ Too Many Requests | Хэт олон хүсэлт | Rate limit |
| 500 | 💥 Internal Server Error | Серверийн дотоод алдаа | Bug, crash |
| 502 | 💥 Bad Gateway | Gateway алдаа | Backend унтарсан |
| 503 | 💥 Service Unavailable | Үйлчилгээ боломжгүй | Засвартай |
Бүлэглэлт:
1xx = Мэдээлэл (Informational)
2xx = Амжилттай (Success) ← Бүгд сайн
3xx = Чиглүүлэлт (Redirection)
4xx = Клиентийн алдаа (Client Error) ← Хэрэглэгч буруу
5xx = Серверийн алдаа (Server Error) ← Сервер буруу
1.3.3 HTTP Headers
| Header | Төрөл | Тайлбар |
|---|---|---|
Content-Type | Request/Response | Агуулгын формат: application/json |
Accept | Request | Клиент хүссэн формат: application/json |
Authorization | Request | Нэвтрэлтийн мэдээлэл: Bearer <token> |
Cache-Control | Response | Кэш тохиргоо: no-cache, max-age=3600 |
Location | Response | Шинэ нөөцийн URL (201 Created-д) |
X-Request-Id | Custom | Хүсэлтийн давтагдашгүй ID (tracking) |
1.4 RESTful URI дизайн
1.4.1 Нөөц (Resource) төвтэй дизайн
🔑 REST-ийн гол зарчим: URI нь НӨӨЦ (noun)-ийг илэрхийлнэ, ҮЙЛДЭЛ (verb)-ийг БИШ. Үйлдлийг HTTP метод илэрхийлнэ.
// ❌ БУРУУ — URI-д үйлдэл (verb) байна
GET /getStudents
GET /getAllStudents
POST /createStudent
PUT /updateStudent/1
DELETE /deleteStudent/1
// ✅ ЗӨӨВ — URI нь нөөцийг илэрхийлж, HTTP метод нь үйлдлийг
GET /students → Бүх оюутан авах
GET /students/1 → ID=1 оюутан авах
POST /students → Шинэ оюутан үүсгэх
PUT /students/1 → ID=1 оюутныг бүхэлд нь шинэчлэх
PATCH /students/1 → ID=1 оюутны зарим хэсгийг өөрчлөх
DELETE /students/1 → ID=1 оюутныг устгах
1.4.2 URI дизайны дүрмүүд
| # | Дүрэм | Зөв | Буруу |
|---|---|---|---|
| 1 | Олон тоо ашиглах | /students | /student |
| 2 | Жижиг үсэг | /students | /Students |
| 3 | Зураас (-) ашиглах | /course-enrollments | /courseEnrollments |
| 4 | Төгсгөлд / байхгүй | /students | /students/ |
| 5 | Файлын өргөтгөлгүй | /students | /students.json |
| 6 | Шатлалтай | /students/1/courses | /getStudentCourses?id=1 |
| 7 | Үйлдэл (verb) байхгүй | POST /students | POST /createStudent |
1.4.3 Шатлалтай нөөц (Nested Resources)
// Оюутны хичээлүүд
GET /students/1/courses → ID=1 оюутны бүх хичээл
GET /students/1/courses/5 → ID=1 оюутны 5-р хичээл
POST /students/1/courses → ID=1 оюутанд хичээл нэмэх
// Хичээлийн оюутнууд
GET /courses/5/students → 5-р хичээлийн бүх оюутан
// Гүнзгий шатлал (2-оос илүү зайлсхий)
GET /universities/1/departments/3/students → Хэт гүнзгий ❌
GET /departments/3/students → Илүү энгийн ✅
1.4.4 Шүүлт, Эрэмбэ, Хуудаслалт (Filtering, Sorting, Pagination)
// Шүүлтүүр (Filter) — Query Parameter ашиглах
GET /students?status=active → Идэвхтэй оюутнууд
GET /students?gpa_min=3.5&status=active → GPA >= 3.5 + идэвхтэй
// Эрэмбэ (Sort)
GET /students?sort=name&order=asc → Нэрээр А→Я
GET /students?sort=gpa&order=desc → GPA-аар буурах
// Хуудаслалт (Pagination)
GET /students?page=1&size=20 → 1-р хуудас, 20 бичлэг
GET /students?page=2&size=20 → 2-р хуудас
// Бүгд хамтдаа
GET /students?status=active&sort=gpa&order=desc&page=1&size=10
1.5 Request & Response формат
1.5.1 JSON формат
JSON (JavaScript Object Notation) — API-ийн хамгийн түгээмэл өгөгдлийн формат.
// Нэг оюутан (Response)
{
"id": 1,
"name": "Батболд",
"email": "batbold@example.com",
"gpa": 3.75,
"status": "ACTIVE",
"enrolledAt": "2024-09-01"
}
// Олон оюутан (Хуудаслалттай Response)
{
"content": [
{"id": 1, "name": "Батболд", "gpa": 3.75},
{"id": 2, "name": "Сарангэрэл", "gpa": 3.90}
],
"page": 1,
"size": 20,
"totalElements": 150,
"totalPages": 8
}
1.5.2 Request Body (POST/PUT)
// POST /students — Шинэ оюутан үүсгэх
{
"name": "Батболд",
"email": "batbold@example.com",
"gpa": 3.75
}
// PUT /students/1 — Оюутныг бүхэлд нь шинэчлэх
{
"name": "Батболд Дорж",
"email": "batbold.dorj@example.com",
"gpa": 3.80
}
// PATCH /students/1 — Зөвхөн email шинэчлэх
{
"email": "new.email@example.com"
}
1.5.3 Алдааны Response (Error Response)
// 400 Bad Request
{
"status": 400,
"error": "Bad Request",
"message": "Validation алдаа",
"details": [
{"field": "email", "message": "Имэйл формат буруу"},
{"field": "name", "message": "Нэр хоосон байж болохгүй"}
],
"timestamp": "2024-09-15T10:30:00",
"path": "/api/v1/students"
}
// 404 Not Found
{
"status": 404,
"error": "Not Found",
"message": "ID=999 оюутан олдсонгүй",
"timestamp": "2024-09-15T10:30:00",
"path": "/api/v1/students/999"
}
1.6 Spring Boot REST API хөгжүүлэлт
1.6.1 Давхарт архитектур (Layered Architecture)
┌────────────────────────────────────────────┐
│ Client (Browser, Mobile) │
└──────────────────┬─────────────────────────┘
│ HTTP Request/Response
┌──────────────────▼─────────────────────────┐
│ Controller Layer (REST API) │
│ @RestController — Хүсэлт хүлээн авах │
└──────────────────┬─────────────────────────┘
│ DTO ↔ Entity
┌──────────────────▼─────────────────────────┐
│ Service Layer (Бизнес логик) │
│ @Service — Бизнес дүрэм, логик │
└──────────────────┬─────────────────────────┘
│ Entity
┌──────────────────▼─────────────────────────┐
│ Repository Layer (Мэдээллийн сан) │
│ @Repository / JpaRepository │
└──────────────────┬─────────────────────────┘
│ SQL
┌──────────────────▼─────────────────────────┐
│ Database (PostgreSQL) │
└────────────────────────────────────────────┘
1.6.2 Entity (Мэдээллийн сангийн хүснэгт)
@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = false)
private Double gpa;
@Enumerated(EnumType.STRING)
private StudentStatus status = StudentStatus.ACTIVE;
@Column(name = "enrolled_at")
private LocalDate enrolledAt;
// Constructor, Getter, Setter
}
public enum StudentStatus {
ACTIVE, INACTIVE, GRADUATED, SUSPENDED
}
1.6.3 DTO (Data Transfer Object)
🔑 DTO яагаад хэрэгтэй? Entity-г шууд API-аар буцаахгүй — нууц мэдээлэл (password), шаардлагагүй талбар (internal ID) задрах эрсдэлтэй.
// Request DTO — Клиентээс ирэх
public record StudentCreateRequest(
@NotBlank(message = "Нэр хоосон байж болохгүй")
String name,
@Email(message = "Имэйл формат буруу")
@NotBlank(message = "Имэйл хоосон байж болохгүй")
String email,
@Min(value = 0, message = "GPA 0-аас бага байж болохгүй")
@Max(value = 4, message = "GPA 4-аас их байж болохгүй")
Double gpa
) {}
// Response DTO — Клиент руу буцах
public record StudentResponse(
Long id,
String name,
String email,
Double gpa,
String status,
LocalDate enrolledAt
) {
public static StudentResponse from(Student student) {
return new StudentResponse(
student.getId(),
student.getName(),
student.getEmail(),
student.getGpa(),
student.getStatus().name(),
student.getEnrolledAt()
);
}
}
1.6.4 Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
Optional<Student> findByEmail(String email);
List<Student> findByStatus(StudentStatus status);
@Query("SELECT s FROM Student s WHERE s.gpa >= :minGpa")
List<Student> findByMinGpa(@Param("minGpa") Double minGpa);
boolean existsByEmail(String email);
}
1.6.5 Service
@Service
@RequiredArgsConstructor
public class StudentService {
private final StudentRepository repository;
public List<StudentResponse> findAll() {
return repository.findAll().stream()
.map(StudentResponse::from)
.toList();
}
public StudentResponse findById(Long id) {
Student student = repository.findById(id)
.orElseThrow(() -> new StudentNotFoundException(
"ID=" + id + " оюутан олдсонгүй"
));
return StudentResponse.from(student);
}
@Transactional
public StudentResponse create(StudentCreateRequest request) {
if (repository.existsByEmail(request.email())) {
throw new DuplicateEmailException(
"'" + request.email() + "' имэйл бүртгэлтэй байна"
);
}
Student student = new Student();
student.setName(request.name());
student.setEmail(request.email());
student.setGpa(request.gpa());
student.setEnrolledAt(LocalDate.now());
Student saved = repository.save(student);
return StudentResponse.from(saved);
}
@Transactional
public StudentResponse update(Long id, StudentCreateRequest request) {
Student student = repository.findById(id)
.orElseThrow(() -> new StudentNotFoundException(
"ID=" + id + " оюутан олдсонгүй"
));
student.setName(request.name());
student.setEmail(request.email());
student.setGpa(request.gpa());
Student saved = repository.save(student);
return StudentResponse.from(saved);
}
@Transactional
public void delete(Long id) {
if (!repository.existsById(id)) {
throw new StudentNotFoundException(
"ID=" + id + " оюутан олдсонгүй"
);
}
repository.deleteById(id);
}
}
1.6.6 Controller
@RestController
@RequestMapping("/api/v1/students")
@RequiredArgsConstructor
public class StudentController {
private final StudentService studentService;
@GetMapping
public ResponseEntity<List<StudentResponse>> findAll() {
return ResponseEntity.ok(studentService.findAll());
}
@GetMapping("/{id}")
public ResponseEntity<StudentResponse> findById(@PathVariable Long id) {
return ResponseEntity.ok(studentService.findById(id));
}
@PostMapping
public ResponseEntity<StudentResponse> create(
@Valid @RequestBody StudentCreateRequest request) {
StudentResponse created = studentService.create(request);
URI location = URI.create("/api/v1/students/" + created.id());
return ResponseEntity.created(location).body(created);
}
@PutMapping("/{id}")
public ResponseEntity<StudentResponse> update(
@PathVariable Long id,
@Valid @RequestBody StudentCreateRequest request) {
return ResponseEntity.ok(studentService.update(id, request));
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
studentService.delete(id);
return ResponseEntity.noContent().build();
}
}
1.6.7 Global Exception Handler
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(StudentNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(StudentNotFoundException ex) {
ErrorResponse error = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
"Not Found",
ex.getMessage(),
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(DuplicateEmailException.class)
public ResponseEntity<ErrorResponse> handleDuplicate(DuplicateEmailException ex) {
ErrorResponse error = new ErrorResponse(
HttpStatus.CONFLICT.value(),
"Conflict",
ex.getMessage(),
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.CONFLICT).body(error);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(
MethodArgumentNotValidException ex) {
List<String> details = ex.getBindingResult().getFieldErrors().stream()
.map(e -> e.getField() + ": " + e.getDefaultMessage())
.toList();
ErrorResponse error = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
"Validation Error",
"Оролтын өгөгдөл буруу",
LocalDateTime.now(),
details
);
return ResponseEntity.badRequest().body(error);
}
}
public record ErrorResponse(
int status,
String error,
String message,
LocalDateTime timestamp,
List<String> details
) {
public ErrorResponse(int status, String error, String message,
LocalDateTime timestamp) {
this(status, error, message, timestamp, null);
}
}
1.7 API хувилбар (Versioning)
Яагаад API хувилбар хэрэгтэй вэ?
API өөрчлөгдөхөд хуучин клиентүүд ЭВДРЭХГҮЙ байх → Хувилбараар удирдах.
| # | Арга | Жишээ | Давуу тал | Сул тал |
|---|---|---|---|---|
| 1 | URI Path | /api/v1/students | Энгийн, тодорхой | URI өөрчлөгдөнө |
| 2 | Query Param | /api/students?version=1 | Уян хатан | Мартаж болно |
| 3 | Header | Accept: application/vnd.api.v1+json | URI цэвэр | Хүндрэлтэй |
| 4 | Media Type | Content-Type: application/vnd.api.v1+json | Стандарт | Нарийн |
Зөвлөмж: URI Path (
/api/v1/...) нь хамгийн энгийн, түгээмэл, ойлгомжтой → Эхлэгчдэд тохиромжтой.
1.8 Authentication & Authorization
1.8.1 Ялгаа
| Ойлголт | Тайлбар | Зүйрлэл |
|---|---|---|
| Authentication (AuthN) | Хэн бэ? Нэвтрэлт | Паспорт шалгах |
| Authorization (AuthZ) | Юу хийж болох вэ? Эрх | VIP билет шалгах |
1.8.2 JWT (JSON Web Token)
┌─────────┐ 1. Login (username, password) ┌─────────┐
│ │ ──────────────────────────────────► │ │
│ Client │ 2. JWT Token │ Server │
│ │ ◄────────────────────────────────── │ │
│ │ 3. Request + Authorization: │ │
│ │ Bearer <token> │ │
│ │ ──────────────────────────────────► │ │
│ │ 4. Response (200 OK) │ │
│ │ ◄────────────────────────────────── │ │
└─────────┘ └─────────┘
JWT бүтэц:
Header.Payload.Signature
// Header
{
"alg": "HS256",
"typ": "JWT"
}
// Payload (Claims)
{
"sub": "batbold@example.com",
"name": "Батболд",
"role": "STUDENT",
"iat": 1694736000,
"exp": 1694822400
}
// Signature
HMACSHA256(base64(header) + "." + base64(payload), secret)
1.8.3 API Key vs OAuth 2.0 vs JWT
| Арга | Тохиромжтой | Тайлбар |
|---|---|---|
| API Key | Энгийн интеграци | Нэг түлхүүр — хялбар, гэхдээ хязгаарлагдмал |
| JWT | Stateless auth | Token-д мэдээлэл агуулагдана, session-гүй |
| OAuth 2.0 | Гуравдагч этгээдийн нэвтрэлт | "Google-ээр нэвтрэх" зэрэг |
1.9 API Баримт бичиг (Documentation)
OpenAPI / Swagger
OpenAPI — API-ийн тодорхойлолтын стандарт формат (YAML/JSON). Swagger UI — OpenAPI-с автоматаар интерактив баримт бичиг үүсгэнэ.
# openapi.yaml жишээ (хялбаршуулсан)
openapi: 3.0.3
info:
title: Student API
version: 1.0.0
paths:
/api/v1/students:
get:
summary: Бүх оюутан авах
responses:
'200':
description: Амжилттай
post:
summary: Шинэ оюутан үүсгэх
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/StudentCreateRequest'
responses:
'201':
description: Үүсгэгдсэн
Spring Boot + Swagger тохиргоо:
// build.gradle
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
// application.yml
springdoc:
api-docs:
path: /api-docs
swagger-ui:
path: /swagger-ui.html
// Controller дээр annotation
@Operation(summary = "Бүх оюутан авах", description = "Бүх оюутны жагсаалт")
@ApiResponse(responseCode = "200", description = "Амжилттай")
@GetMapping
public ResponseEntity<List<StudentResponse>> findAll() { ... }
Swagger UI:
http://localhost:8080/swagger-ui.html— Браузераас API-г шууд туршиж болно.
1.10 REST API шилдэг туршлагууд (Best Practices)
| # | Зарчим | Тайлбар |
|---|---|---|
| 1 | Нөөц төвтэй URI | /students (noun), /createStudent биш (verb) |
| 2 | HTTP метод зөв ашиглах | GET = Унших, POST = Үүсгэх, PUT = Шинэчлэх, DELETE = Устгах |
| 3 | Status Code зөв буцаах | 200, 201, 204, 400, 404, 500 — Зорилгод тохирсон |
| 4 | Хувилбар ашиглах | /api/v1/students |
| 5 | Validation хийх | @Valid, @NotBlank, @Email |
| 6 | Нэгдмэл алдааны формат | ErrorResponse DTO |
| 7 | Хуудаслалт | Олон бичлэгт page, size parameter |
| 8 | DTO ашиглах | Entity шууд буцаахгүй |
| 9 | HTTPS ашиглах | Мэдээлэл шифрлэгдэнэ |
| 10 | Rate Limiting | Хэт олон хүсэлтээс хамгаалах |
| 11 | Баримт бичиг | Swagger / OpenAPI |
| 12 | Idempotency | PUT, DELETE идемпотент байх |
1.11 REST vs GraphQL vs gRPC
| Шинж | REST | GraphQL | gRPC |
|---|---|---|---|
| Протокол | HTTP/JSON | HTTP/JSON | HTTP/2 + Protobuf |
| Хүсэлт | Олон endpoint | Нэг endpoint, query | Service method |
| Over-fetching | Байж болно | Байхгүй (хэрэгтэйгээ сонгоно) | Байхгүй |
| Under-fetching | Байж болно | Байхгүй | Байхгүй |
| Суралцахад | Хялбар | Дунд | Хүнд |
| Хурд | Сайн | Сайн | Хамгийн хурдан |
| Тохиромжтой | CRUD API, вэб | Уян хатан query, mobile | Microservice, real-time |
Over-fetching = Хэрэгцээнээс илүү мэдээлэл ирэх (жишээ: зөвхөн нэр хэрэгтэй, бүх талбар ирэх). Under-fetching = Нэг хүсэлтээр хүрэлцэхгүй, нэмэлт хүсэлт шаардлагатай.
1.12 HATEOAS
HATEOAS (Hypermedia As The Engine Of Application State) — REST-ийн дээд түвшний зарчим. Response дотор дараагийн боломжит үйлдлүүдийн холбоос агуулна.
// HATEOAS Response жишээ
{
"id": 1,
"name": "Батболд",
"email": "batbold@example.com",
"gpa": 3.75,
"_links": {
"self": {"href": "/api/v1/students/1"},
"courses": {"href": "/api/v1/students/1/courses"},
"update": {"href": "/api/v1/students/1", "method": "PUT"},
"delete": {"href": "/api/v1/students/1", "method": "DELETE"}
}
}
💡 Зүйрлэл: Вэб хуудас дахь "Дараах", "Өмнөх", "Засах", "Устгах" товчлуурууд шиг — API-ийн хариунд дараа юу хийж болохыг заасан холбоосууд.
ХЭСЭГ 2: ТҮЛХҮҮР ҮГ БА МЭРГЭЖЛИЙН НЭР ТОМЬЁО (Keywords & Glossary)
| # | Англи нэр томьёо | Монгол утга | Дэлгэрэнгүй тайлбар |
|---|---|---|---|
| 1 | API | Програмын интерфейс | Application Programming Interface — Програм хоорондын харилцааны гэрээ. |
| 2 | REST | Төлөөлөлт шилжүүлэлт | Representational State Transfer — HTTP дээр суурилсан архитектурын хэв маяг. |
| 3 | RESTful | REST зарчимтай | REST зарчмуудыг баримталсан API. |
| 4 | HTTP | Гипертекст дамжуулах протокол | HyperText Transfer Protocol — Web-ийн суурь протокол. |
| 5 | HTTPS | Аюулгүй HTTP | HTTP + TLS/SSL шифрлэлт. |
| 6 | Endpoint | Төгсгөлийн цэг | API-ийн тодорхой URL + HTTP метод хослол. |
| 7 | URI / URL | Нөөцийн хаяг | Uniform Resource Identifier — Нөөцийн байршил. |
| 8 | HTTP Method | HTTP арга | GET, POST, PUT, PATCH, DELETE — Үйлдлийн төрөл. |
| 9 | Status Code | Хариуны код | 200, 404, 500 зэрэг — Хүсэлтийн үр дүнгийн код. |
| 10 | JSON | JSON формат | JavaScript Object Notation — Өгөгдлийн формат. |
| 11 | Request | Хүсэлт | Клиентээс сервер рүү илгээх мэдээлэл. |
| 12 | Response | Хариу | Серверээс клиент рүү буцах мэдээлэл. |
| 13 | Request Body | Хүсэлтийн бие | POST/PUT хүсэлтийн JSON өгөгдөл. |
| 14 | Header | Толгой | HTTP хүсэлт/хариуны нэмэлт мэдээлэл. |
| 15 | Query Parameter | Асуулгын параметр | URL-д ?key=value хэлбэрээр дамжуулах. |
| 16 | Path Variable | Зам хувьсагч | URL-д /students/{id} хэлбэрээр дамжуулах. |
| 17 | Stateless | Төлөвгүй | Сервер клиентийн төлөв хадгалахгүй. |
| 18 | Idempotent | Идемпотент | Олон удаа дуудсан ч үр дүн ижил. |
| 19 | CRUD | CRUD үйлдлүүд | Create, Read, Update, Delete — Суурь үйлдлүүд. |
| 20 | DTO | Мэдээлэл дамжуулах объект | Data Transfer Object — API-ийн хүсэлт/хариуны объект. |
| 21 | Entity | Нэгж | Мэдээллийн сангийн хүснэгтийг илэрхийлэх Java класс. |
| 22 | Repository | Мэдээллийн агуулах | Мэдээллийн сантай харилцах давхарга. |
| 23 | Service | Үйлчилгээний давхарга | Бизнес логик хариуцах давхарга. |
| 24 | Controller | Хянагч | HTTP хүсэлт хүлээн авах, хариу буцаах давхарга. |
| 25 | JWT | JSON Web Token | Stateless нэвтрэлтийн токен. |
| 26 | Authentication | Нэвтрэлт | Хэн бэ? — Хэрэглэгчийг таних. |
| 27 | Authorization | Эрх зүй | Юу хийж болох вэ? — Хандах эрх шалгах. |
| 28 | OAuth 2.0 | OAuth протокол | Гуравдагч этгээдээр нэвтрэх стандарт. |
| 29 | API Key | API түлхүүр | API-д хандах нууц түлхүүр. |
| 30 | Rate Limiting | Хурд хязгаарлалт | Хэт олон хүсэлтээс хамгаалах механизм. |
| 31 | Pagination | Хуудаслалт | Олон бичлэгийг хуудас хуудсаар буцаах. |
| 32 | Filtering | Шүүлт | Бичлэгийг нөхцөлөөр шүүх. |
| 33 | Sorting | Эрэмбэлэлт | Бичлэгийг талбараар эрэмбэлэх. |
| 34 | Swagger / OpenAPI | API баримт бичиг | API-ийн интерактив баримт бичгийн стандарт. |
| 35 | HATEOAS | Гипермедиа | Hypermedia As The Engine Of Application State. |
| 36 | GraphQL | ГрафQL | Query-д суурилсан API хэл. |
| 37 | gRPC | gRPC | Google-ийн өндөр хурдтай RPC framework. |
| 38 | Payload | Ачаа | Хүсэлт/хариуны гол өгөгдөл. |
| 39 | Validation | Баталгаажуулалт | Оролтын өгөгдлийг шалгах. |
| 40 | Serialization | Цуваачлал | Объектыг JSON/XML формат руу хөрвүүлэх. |