ЛЕКЦ 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 формат руу хөрвүүлэх. |
ХЭСЭГ 3: ЛАБОРАТОРИ БА ПРАКТИК ЗААВАР (Labs & Step-by-Step Guide)
3.1 Лабораторийн зорилго
Энэ лабораторид та Spring Boot ашиглан RESTful API бүтээж, бодит дадлага хийнэ:
- Spring Boot төсөл үүсгэх
- CRUD REST API хөгжүүлэх (Entity, DTO, Repository, Service, Controller)
- Validation ба Exception Handling
- Swagger/OpenAPI баримт бичиг
Хэл: Java 17+ | Framework: Spring Boot 3.x | IDE: Eclipse IDE
3.2 Лаб 1: Spring Boot төсөл үүсгэх
Алхам 1: Spring Initializr ашиглах
https://start.spring.io руу орж:
| Тохиргоо | Утга |
|---|---|
| Project | Maven |
| Language | Java |
| Spring Boot | 3.2.x |
| Group | com.example |
| Artifact | student-api |
| Packaging | Jar |
| Java | 17 |
Алхам 2: Dependency нэмэх
<!-- pom.xml -->
<dependencies>
<!-- Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JPA + Database -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- H2 Database (хөгжүүлэлтийн орчинд) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Swagger/OpenAPI -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Алхам 3: application.yml тохиргоо
# src/main/resources/application.yml
server:
port: 8080
spring:
datasource:
url: jdbc:h2:mem:studentdb
driver-class-name: org.h2.Driver
username: sa
password:
h2:
console:
enabled: true
path: /h2-console
jpa:
hibernate:
ddl-auto: create-drop
show-sql: true
springdoc:
swagger-ui:
path: /swagger-ui.html
Алхам 4: Ажиллуулах
./mvnw spring-boot:run
Шалгах:
http://localhost:8080/h2-console→ H2 Database consolehttp://localhost:8080/swagger-ui.html→ Swagger UI
3.3 Лаб 2: CRUD REST API хөгжүүлэх
Алхам 1: Entity үүсгэх
// src/main/java/com/example/studentapi/entity/Student.java
package com.example.studentapi.entity;
import jakarta.persistence.*;
import java.time.LocalDate;
@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)
@Column(nullable = false)
private StudentStatus status = StudentStatus.ACTIVE;
@Column(name = "enrolled_at")
private LocalDate enrolledAt = LocalDate.now();
public Student() {}
public Student(String name, String email, Double gpa) {
this.name = name;
this.email = email;
this.gpa = gpa;
}
// Getter, Setter методууд
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public Double getGpa() { return gpa; }
public void setGpa(Double gpa) { this.gpa = gpa; }
public StudentStatus getStatus() { return status; }
public void setStatus(StudentStatus status) { this.status = status; }
public LocalDate getEnrolledAt() { return enrolledAt; }
public void setEnrolledAt(LocalDate enrolledAt) { this.enrolledAt = enrolledAt; }
}
// src/main/java/com/example/studentapi/entity/StudentStatus.java
package com.example.studentapi.entity;
public enum StudentStatus {
ACTIVE, INACTIVE, GRADUATED, SUSPENDED
}
Алхам 2: DTO үүсгэх
// src/main/java/com/example/studentapi/dto/StudentCreateRequest.java
package com.example.studentapi.dto;
import jakarta.validation.constraints.*;
public record StudentCreateRequest(
@NotBlank(message = "Нэр хоосон байж болохгүй")
@Size(min = 2, max = 100, message = "Нэр 2-100 тэмдэгт байх ёстой")
String name,
@NotBlank(message = "Имэйл хоосон байж болохгүй")
@Email(message = "Имэйл формат буруу")
String email,
@NotNull(message = "GPA заавал оруулна")
@Min(value = 0, message = "GPA 0-аас бага байж болохгүй")
@Max(value = 4, message = "GPA 4-аас их байж болохгүй")
Double gpa
) {}
// src/main/java/com/example/studentapi/dto/StudentResponse.java
package com.example.studentapi.dto;
import com.example.studentapi.entity.Student;
import java.time.LocalDate;
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()
);
}
}
Алхам 3: Repository үүсгэх
// src/main/java/com/example/studentapi/repository/StudentRepository.java
package com.example.studentapi.repository;
import com.example.studentapi.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface StudentRepository extends JpaRepository<Student, Long> {
Optional<Student> findByEmail(String email);
boolean existsByEmail(String email);
}
Алхам 4: Custom Exception үүсгэх
// src/main/java/com/example/studentapi/exception/StudentNotFoundException.java
package com.example.studentapi.exception;
public class StudentNotFoundException extends RuntimeException {
public StudentNotFoundException(String message) {
super(message);
}
}
// src/main/java/com/example/studentapi/exception/DuplicateEmailException.java
package com.example.studentapi.exception;
public class DuplicateEmailException extends RuntimeException {
public DuplicateEmailException(String message) {
super(message);
}
}
Алхам 5: Service үүсгэх
// src/main/java/com/example/studentapi/service/StudentService.java
package com.example.studentapi.service;
import com.example.studentapi.dto.*;
import com.example.studentapi.entity.Student;
import com.example.studentapi.exception.*;
import com.example.studentapi.repository.StudentRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class StudentService {
private final StudentRepository repository;
public StudentService(StudentRepository repository) {
this.repository = 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(
request.name(), request.email(), request.gpa()
);
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);
}
}
Алхам 6: Controller үүсгэх
// src/main/java/com/example/studentapi/controller/StudentController.java
package com.example.studentapi.controller;
import com.example.studentapi.dto.*;
import com.example.studentapi.service.StudentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.net.URI;
import java.util.List;
@RestController
@RequestMapping("/api/v1/students")
@Tag(name = "Student API", description = "Оюутны CRUD API")
public class StudentController {
private final StudentService studentService;
public StudentController(StudentService studentService) {
this.studentService = studentService;
}
@GetMapping
@Operation(summary = "Бүх оюутан авах")
public ResponseEntity<List<StudentResponse>> findAll() {
return ResponseEntity.ok(studentService.findAll());
}
@GetMapping("/{id}")
@Operation(summary = "ID-аар оюутан авах")
public ResponseEntity<StudentResponse> findById(@PathVariable Long id) {
return ResponseEntity.ok(studentService.findById(id));
}
@PostMapping
@Operation(summary = "Шинэ оюутан үүсгэх")
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}")
@Operation(summary = "Оюутны мэдээлэл шинэчлэх")
public ResponseEntity<StudentResponse> update(
@PathVariable Long id,
@Valid @RequestBody StudentCreateRequest request) {
return ResponseEntity.ok(studentService.update(id, request));
}
@DeleteMapping("/{id}")
@Operation(summary = "Оюутан устгах")
public ResponseEntity<Void> delete(@PathVariable Long id) {
studentService.delete(id);
return ResponseEntity.noContent().build();
}
}
Алхам 7: Global Exception Handler
// src/main/java/com/example/studentapi/exception/GlobalExceptionHandler.java
package com.example.studentapi.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
@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(), null
);
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(), null
);
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);
}
}
// src/main/java/com/example/studentapi/exception/ErrorResponse.java
package com.example.studentapi.exception;
import java.time.LocalDateTime;
import java.util.List;
public record ErrorResponse(
int status,
String error,
String message,
LocalDateTime timestamp,
List<String> details
) {}
3.4 Лаб 3: API тестлэх (cURL / Swagger)
cURL ашиглан тестлэх:
# 1. Шинэ оюутан үүсгэх (POST)
curl -X POST http://localhost:8080/api/v1/students \
-H "Content-Type: application/json" \
-d '{
"name": "Батболд",
"email": "batbold@example.com",
"gpa": 3.75
}'
# Хариу: 201 Created + StudentResponse JSON
# 2. Бүх оюутан авах (GET)
curl http://localhost:8080/api/v1/students
# Хариу: 200 OK + List<StudentResponse>
# 3. ID-аар оюутан авах (GET)
curl http://localhost:8080/api/v1/students/1
# Хариу: 200 OK + StudentResponse
# 4. Оюутны мэдээлэл шинэчлэх (PUT)
curl -X PUT http://localhost:8080/api/v1/students/1 \
-H "Content-Type: application/json" \
-d '{
"name": "Батболд Дорж",
"email": "batbold.dorj@example.com",
"gpa": 3.80
}'
# Хариу: 200 OK + Шинэчлэгдсэн StudentResponse
# 5. Оюутан устгах (DELETE)
curl -X DELETE http://localhost:8080/api/v1/students/1
# Хариу: 204 No Content
# 6. Validation алдаа тестлэх
curl -X POST http://localhost:8080/api/v1/students \
-H "Content-Type: application/json" \
-d '{
"name": "",
"email": "буруу-имэйл",
"gpa": 5.0
}'
# Хариу: 400 Bad Request + Validation алдааны жагсаалт
# 7. Олдохгүй оюутан тестлэх
curl http://localhost:8080/api/v1/students/999
# Хариу: 404 Not Found + "ID=999 оюутан олдсонгүй"
Swagger UI ашиглан тестлэх:
http://localhost:8080/swagger-ui.htmlнээх- "Student API" бүлгийг дарж нээх
- "Try it out" товч дарах
- Параметр оруулж "Execute" дарах
- Response шалгах
3.5 Лаб 4: Хуудаслалт ба Шүүлт нэмэх
Controller-д хуудаслалт нэмэх:
// StudentController.java — findAll методыг шинэчлэх
@GetMapping
@Operation(summary = "Оюутны жагсаалт (хуудаслалттай)")
public ResponseEntity<Page<StudentResponse>> findAll(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "id") String sortBy,
@RequestParam(defaultValue = "asc") String order) {
Sort sort = order.equalsIgnoreCase("desc")
? Sort.by(sortBy).descending()
: Sort.by(sortBy).ascending();
Page<StudentResponse> result = studentService.findAll(
PageRequest.of(page, size, sort)
);
return ResponseEntity.ok(result);
}
// StudentService.java — findAll методыг шинэчлэх
public Page<StudentResponse> findAll(Pageable pageable) {
return repository.findAll(pageable)
.map(StudentResponse::from);
}
Тестлэх:
# 1-р хуудас, 5 бичлэг, GPA-аар буурах
curl "http://localhost:8080/api/v1/students?page=0&size=5&sortBy=gpa&order=desc"
ХЭСЭГ 4: ШАЛГАЛТЫН АСУУЛТ (Knowledge Check — 100 тест)
Тест 1
API гэж юу вэ?
- A) Зөвхөн вэб хуудас
- B) Програм хоорондын харилцааны гэрээ (интерфейс)
- C) Мэдээллийн сан
- D) Зөвхөн мобайл апп
Зөв хариулт: B
Тайлбар: API = Application Programming Interface. Нэг програм нөгөө програмтай мэдээлэл солилцох, функц дуудах боломжийг олгодог гэрээ.
Тест 2
REST гэдэг юуны товчлол вэ?
- A) Remote Execution System Transfer
- B) Representational State Transfer
- C) Request-Server Technology
- D) Resource Extraction Standard Tool
Зөв хариулт: B
Тайлбар: REST = Representational State Transfer. Roy Fielding 2000 онд тодорхойлсон, HTTP дээр суурилсан архитектурын хэв маяг.
Тест 3
REST-ийн "Stateless" зарчим юу гэсэн утгатай вэ?
- A) Сервер клиентийн session хадгална
- B) Хүсэлт бүр бие даасан — сервер клиентийн төлөв хадгалахгүй
- C) Клиент сервертэй холбогдохгүй
- D) Зөвхөн GET хүсэлт ашиглах
Зөв хариулт: B
Тайлбар: Stateless = Хүсэлт бүрт шаардлагатай бүх мэдээлэл (token, параметр) агуулагдана. Сервер session хадгалахгүй → Scale хялбар, аль ч сервер хариулж чадна.
Тест 4
HTTP GET метод юу хийдэг вэ?
- A) Нөөц үүсгэх
- B) Нөөц устгах
- C) Нөөц уншиx (авах)
- D) Нөөц шинэчлэх
Зөв хариулт: C
Тайлбар: GET = Read. Серверээс мэдээлэл авах. Сервер дээрх өгөгдлийг ӨӨРЧЛӨХГҮЙ (safe + idempotent).
Тест 5
HTTP POST метод юу хийдэг вэ?
- A) Нөөц уншиx
- B) Шинэ нөөц ҮҮСГЭХ
- C) Нөөц устгах
- D) Нөөцийн зарим хэсгийг өөрчлөх
Зөв хариулт: B
Тайлбар: POST = Create. Шинэ нөөц үүсгэнэ. Дуудах бүрт ШИНЭ нөөц үүснэ → Идемпотент БИШ.
Тест 6
HTTP PUT ба PATCH-ийн ялгаа юу вэ?
- A) Ялгаагүй
- B) PUT = нөөцийг БҮХЭЛД нь солих, PATCH = зарим ХЭСГИЙГ өөрчлөх
- C) PUT = устгах, PATCH = үүсгэх
- D) PUT = уншиx, PATCH = устгах
Зөв хариулт: B
Тайлбар: PUT = Бүх талбарыг илгээж, бүхлээр солих. PATCH = Зөвхөн өөрчлөх талбаруудыг илгээх. Жишээ: Зөвхөн email солих → PATCH.
Тест 7
"Идемпотент" (Idempotent) гэж юу вэ?
- A) Хурдан ажиллах
- B) Олон удаа дуудсан ч үр дүн ИЖИЛ байх
- C) Зөвхөн нэг удаа дуудах
- D) Алдаагүй байх
Зөв хариулт: B
Тайлбар: GET, PUT, DELETE = Идемпотент (10 удаа дуудсан ч ижил үр дүн). POST = Идемпотент БИШ (дуудах бүрт шинэ нөөц үүснэ).
Тест 8
HTTP 200 status code юу гэсэн утгатай вэ?
- A) Шинэ нөөц үүссэн
- B) Амжилттай (OK)
- C) Нөөц олдсонгүй
- D) Серверийн алдаа
Зөв хариулт: B
Тайлбар: 200 OK = Хүсэлт амжилттай. GET хүсэлтийн хариуд хамгийн түгээмэл.
Тест 9
HTTP 201 status code юу гэсэн утгатай вэ?
- A) Хүсэлт амжилттай
- B) Шинэ нөөц амжилттай ҮҮССЭН (Created)
- C) Агуулга хоосон
- D) Чиглүүлэлт
Зөв хариулт: B
Тайлбар: 201 Created = POST хүсэлтийн амжилттай хариу. Шинэ нөөц үүссэн, Location header-т шинэ URL буцна.
Тест 10
HTTP 404 status code юу гэсэн утгатай вэ?
- A) Серверийн алдаа
- B) Нэвтрэлт шаардлагатай
- C) Нөөц ОЛДСОНГҮЙ (Not Found)
- D) Буруу хүсэлт
Зөв хариулт: C
Тайлбар: 404 Not Found = Хүсэлт илгээсэн нөөц серверт олдсонгүй. Жишээ:
/students/999— ID=999 оюутан байхгүй.
Тест 11
HTTP 500 status code юу гэсэн утгатай вэ?
- A) Клиентийн алдаа
- B) Нөөц олдсонгүй
- C) Серверийн ДОТООД алдаа (Internal Server Error)
- D) Хэт олон хүсэлт
Зөв хариулт: C
Тайлбар: 500 = Серверт bug, crash, exception гарсан. 5xx = Серверийн буруу. 4xx = Клиентийн буруу.
Тест 12
HTTP 401 ба 403-ийн ялгаа юу вэ?
- A) Ялгаагүй
- B) 401 = Нэвтрэлт ШААРДЛАГАТАЙ (хэн бэ мэдэхгүй), 403 = Нэвтэрсэн ч ЭРХ ХҮРЭЛЦЭХГҮЙ
- C) 401 = Олдсонгүй, 403 = Серверийн алдаа
- D) 401 = Шинэ нөөц, 403 = Устгагдсан
Зөв хариулт: B
Тайлбар: 401 Unauthorized = "Чи хэн бэ?" (Token байхгүй/буруу). 403 Forbidden = "Чи хэн бэ мэднэ, гэхдээ эрхгүй" (Student → Admin хуудас).
Тест 13
RESTful URI дизайнд аль нь ЗӨӨВ вэ?
- A)
GET /getStudents - B)
GET /students - C)
GET /getAllStudentsList - D)
GET /fetchStudentData
Зөв хариулт: B
Тайлбар: REST = Нөөц (noun) төвтэй URI.
/students= Нөөц. Үйлдлийг HTTP метод (GET) илэрхийлнэ. URI-д verb (get, fetch, create) байхгүй.
Тест 14
URI-д олон тоо ашиглах дүрэм аль нь зөв вэ?
- A)
/student(ганц тоо) - B)
/students(олон тоо) - C)
/student_list - D)
/studentData
Зөв хариулт: B
Тайлбар: REST стандарт: Нөөцийн нэрийг ОЛОН ТООГООР бичих.
/students= Оюутнуудын цуглуулга./students/1= Нэг оюутан.
Тест 15
Шатлалтай нөөцийн (nested resource) зөв жишээ аль нь вэ?
- A)
GET /getStudentCourses?studentId=1 - B)
GET /students/1/courses - C)
GET /courses-of-student-1 - D)
GET /studentCourses/1
Зөв хариулт: B
Тайлбар:
/students/1/courses= ID=1 оюутны хичээлүүд. Шатлал → Нөөцийн хамаарлыг тодорхой илэрхийлнэ. 2-3 түвшнээс илүү гүнзгий зайлсхий.
Тест 16
Query Parameter юунд ашигладаг вэ?
- A) Нөөц үүсгэх
- B) Шүүлт, эрэмбэ, хуудаслалт —
?status=active&page=1&size=10 - C) Нөөц устгах
- D) Нэвтрэх
Зөв хариулт: B
Тайлбар: Query Parameter (
?key=value) = Нөөцийн цуглуулгыг шүүх, эрэмбэлэх, хуудаслах. Нөөцийн ID-г PATH-аар (/students/1), шүүлтийг QUERY-ээр.
Тест 17
JSON формат дахь зөв бичиглэл аль нь вэ?
- A)
{name: "Бат"} - B)
{"name": "Бат"} - C)
{name = "Бат"} - D)
<name>Бат</name>
Зөв хариулт: B
Тайлбар: JSON = Түлхүүр (key) ЗААВАЛ давхар хашилттай ("").
{"name": "Бат"}= Зөв.{name: "Бат"}= JavaScript-д зөв, JSON-д БУРУУ.
Тест 18
DTO (Data Transfer Object) яагаад хэрэгтэй вэ?
- A) Шаардлагагүй
- B) Entity-г шууд API-аар буцаахгүй — нууц мэдээлэл задрахаас хамгаалах, API гэрээг тусгаарлах
- C) Зөвхөн тест бичихэд
- D) Зөвхөн формат солиход
Зөв хариулт: B
Тайлбар: Entity шууд буцаавал: password задарна, internal ID ил гарна, Entity өөрчлөхөд API эвдэрнэ. DTO = API-ийн гэрээг Entity-ээс тусгаарлах.
Тест 19
Spring Boot-д @RestController annotation юу хийдэг вэ?
- A) Мэдээллийн сан холбох
- B) HTTP хүсэлт хүлээн авч, JSON хариу буцаах REST Controller зарлах
- C) Тест ажиллуулах
- D) Security тохируулах
Зөв хариулт: B
Тайлбар:
@RestController=@Controller+@ResponseBody. Бүх метод автоматаар JSON/XML буцаана. HTML view биш, DATA буцаана.
Тест 20
@GetMapping("/{id}") дахь {id} юу вэ?
- A) Query Parameter
- B) Path Variable — URL-ийн хэсэг болж дамжуулагдах хувьсагч
- C) Header
- D) Request Body
Зөв хариулт: B
Тайлбар:
{id}= Path Variable./students/1дахь1= id утга.@PathVariable Long idашиглан авна.
Тест 21
@RequestBody annotation юу хийдэг вэ?
- A) URL-аас параметр авах
- B) HTTP хүсэлтийн BODY дахь JSON-ийг Java объект руу хөрвүүлэх
- C) Header авах
- D) Cookie авах
Зөв хариулт: B
Тайлбар:
@RequestBody StudentCreateRequest request= Клиентийн илгээсэн JSON → Java объект (deserialization). POST, PUT хүсэлтэд ашиглана.
Тест 22
ResponseEntity юу хийдэг вэ?
- A) Зөвхөн JSON буцаах
- B) HTTP Status Code + Header + Body-г бүрэн хянах боломжийг олгох
- C) Зөвхөн алдаа буцаах
- D) Зөвхөн string буцаах
Зөв хариулт: B
Тайлбар:
ResponseEntity.created(location).body(dto)= 201 + Location header + Body. Status code, header, body-г бүгдийг удирдах боломжтой.
Тест 23
@Valid annotation юу хийдэг вэ?
- A) Код компайлдах
- B) DTO дахь validation annotation-уудыг (@NotBlank, @Email г.м.) идэвхжүүлж шалгах
- C) Тест ажиллуулах
- D) Лог бичих
Зөв хариулт: B
Тайлбар:
@Valid @RequestBody StudentCreateRequest request→@NotBlank,@Min,@Maxзэрэг шалгалтууд ажиллана. Буруу бол 400 Bad Request.
Тест 24
@RestControllerAdvice юу хийдэг вэ?
- A) Controller үүсгэх
- B) Бүх Controller-ийн Exception-ийг НЭГДМЭЛ газар зохицуулах (Global Exception Handler)
- C) Тест бичих
- D) Security тохируулах
Зөв хариулт: B
Тайлбар:
@RestControllerAdvice+@ExceptionHandler= Бүх алдааг нэг газар зохицуулж, нэгдмэл формат (ErrorResponse) буцаана.
Тест 25
JWT (JSON Web Token) юу вэ?
- A) Мэдээллийн сан
- B) Stateless нэвтрэлтийн токен — Header.Payload.Signature бүтэцтэй
- C) API баримт бичиг
- D) Тестийн framework
Зөв хариулт: B
Тайлбар: JWT = Нэвтрэлтийн мэдээлэл (хэн бэ, ямар эрхтэй, хэзээ дуусах) агуулсан, гарын үсэгтэй токен.
Authorization: Bearer <token>header-ээр дамжуулна.
Тест 26
Authentication ба Authorization-ийн ялгаа юу вэ?
- A) Ялгаагүй
- B) Authentication = ХЭН бэ? (нэвтрэлт), Authorization = ЮУ хийж болох вэ? (эрх)
- C) Authentication = эрх, Authorization = нэвтрэлт
- D) Хоёулаа нэвтрэлт
Зөв хариулт: B
Тайлбар: Authentication = Паспорт шалгах (хэн бэ?). Authorization = VIP билет шалгах (юу хийж болох вэ?). Эхлээд AuthN → дараа AuthZ.
Тест 27
API Versioning-ийн хамгийн түгээмэл арга аль нь вэ?
- A) Хувилбар ашиглахгүй
- B) URI Path —
/api/v1/students - C) Зөвхөн Header
- D) Зөвхөн Cookie
Зөв хариулт: B
Тайлбар: URI Path versioning = Хамгийн энгийн, тодорхой, түгээмэл.
/api/v1/...→/api/v2/.... Хуучин клиент v1 ашиглаж, шинэ клиент v2 ашиглана.
Тест 28
Swagger / OpenAPI юу хийдэг вэ?
- A) Код бичих
- B) API-ийн ИНТЕРАКТИВ баримт бичиг үүсгэх — endpoint, параметр, хариуг харуулах, шууд тестлэх
- C) Мэдээллийн сан үүсгэх
- D) Deploy хийх
Зөв хариулт: B
Тайлбар: Swagger UI = API-ийн бүх endpoint, параметр, хариуг визуал харуулж, "Try it out" товчоор шууд тестлэх боломжтой.
Тест 29
Rate Limiting юу хийдэг вэ?
- A) Код хурдасгах
- B) Нэг клиентийн хэт олон хүсэлтийг ХЯЗГААРЛАХ — DDoS, abuse-аас хамгаалах
- C) Мэдээллийн сан optimize хийх
- D) Тест ажиллуулах
Зөв хариулт: B
Тайлбар: Rate Limiting = Жишээ: 1 минутад 100 хүсэлт. Хэтэрвэл 429 Too Many Requests. API-ийн тогтвортой байдал, аюулгүй байдлыг хамгаална.
Тест 30
HATEOAS гэж юу вэ?
- A) HTTP протокол
- B) Response дотор дараагийн боломжит үйлдлүүдийн ХОЛБООС (link) агуулах REST зарчим
- C) Мэдээллийн сан
- D) Тестийн framework
Зөв хариулт: B
Тайлбар: HATEOAS = Response дотор
_linksхэсэгтself,update,delete,coursesзэрэг холбоос. Клиент API-г "судалж" (discover) ашиглаж чадна.
Тест 31
REST vs GraphQL — GraphQL-ийн давуу тал юу вэ?
- A) Хурдан
- B) Клиент яг ХЭРЭГТЭЙ талбаруудаа сонгож авна — over-fetching, under-fetching-гүй
- C) Суралцахад хялбар
- D) Бүх тохиолдолд REST-ээс дээр
Зөв хариулт: B
Тайлбар: GraphQL = Нэг endpoint, клиент query-ээр хэрэгтэй талбаруудаа л авна. REST = Олон endpoint, бүх талбар буцна (over-fetching). Гэхдээ GraphQL суралцахад хэцүү.
Тест 32
Content-Type: application/json header юу гэсэн утгатай вэ?
- A) HTML файл
- B) Хүсэлт/хариуны АГУУЛГА нь JSON формат
- C) XML файл
- D) Текст файл
Зөв хариулт: B
Тайлбар:
Content-Type= Илгээж буй агуулгын формат.application/json= JSON. Сервер, клиент хоёулаа өгөгдлийг зөв боловсруулахад ашиглана.
Тест 33
Authorization: Bearer eyJhbGci... header юу хийдэг вэ?
- A) JSON илгээх
- B) JWT Token дамжуулж, нэвтрэлтийг баталгаажуулах
- C) Content type тохируулах
- D) Cache тохируулах
Зөв хариулт: B
Тайлбар:
Bearer= Токен төрлийн нэвтрэлт. Сервер token-ийг шалгаж, хэн бэ, ямар эрхтэйг мэднэ. Хүсэлт бүрт header-ээр дамжуулна.
Тест 34
Spring Boot-д @Transactional annotation юу хийдэг вэ?
- A) Тест ажиллуулах
- B) Методын бүх DB үйлдлийг НЭГ transaction-д багтааж, алдаа гарвал БҮГДИЙГ буцаах (rollback)
- C) Лог бичих
- D) Cache тохируулах
Зөв хариулт: B
Тайлбар:
@Transactional= Бүх DB үйлдэл амжилттай бол commit, нэг ч алдаа гарвал бүгдийг rollback. Өгөгдлийн бүрэн бүтэн байдал (ACID).
Тест 35
"Over-fetching" гэж юу вэ?
- A) Хэрэгцээнээс бага мэдээлэл ирэх
- B) Хэрэгцээнээс ИЛҮҮ мэдээлэл ирэх — зөвхөн нэр хэрэгтэй, бүх талбар ирэх
- C) Алдаа гарах
- D) Сервер унах
Зөв хариулт: B
Тайлбар: Over-fetching = REST-ийн нийтлэг асуудал.
GET /students/1→ Зөвхөн нэр хэрэгтэй ч, бүх талбар (email, gpa, status...) ирнэ. GraphQL энэ асуудлыг шийднэ.
Тест 36
"Under-fetching" гэж юу вэ?
- A) Хэрэгцээнээс илүү мэдээлэл ирэх
- B) Нэг хүсэлтээр хүрэлцэхгүй — нэмэлт хүсэлт шаардагдах
- C) Серверийн алдаа
- D) Validation алдаа
Зөв хариулт: B
Тайлбар: Under-fetching =
/students/1авсан, гэхдээ хичээлүүдийг авахын тулд/students/1/coursesдахин дуудах хэрэгтэй. GraphQL нэг query-ээр шийднэ.
Тест 37
Layered Architecture-д Controller → Service → Repository дарааллын зорилго юу вэ?
- A) Зөвхөн дүрэм
- B) Үүрэг хуваарилалт — Controller = HTTP, Service = Бизнес логик, Repository = DB
- C) Зөвхөн хурд
- D) Зөвхөн аюулгүй байдал
Зөв хариулт: B
Тайлбар: Давхарт архитектур = Separation of Concerns. Controller нь HTTP-ийг удирдана, Service нь бизнес дүрэм хариуцна, Repository нь DB-тай харилцана. Тус тусдаа тестлэж болно.
Тест 38
JpaRepository юу хийдэг вэ?
- A) Controller үүсгэх
- B) CRUD методуудыг АВТОМАТААР олгох — findAll, findById, save, deleteById г.м.
- C) Тест бичих
- D) JSON хөрвүүлэх
Зөв хариулт: B
Тайлбар:
JpaRepository<Student, Long>extend хийхэдfindAll(),findById(),save(),deleteById()зэрэг методууд автоматаар бэлэн болно. SQL бичих шаардлагагүй.
Тест 39
Java record юу хийдэг вэ?
- A) Файл бичих
- B) Immutable data class — constructor, getter, equals, hashCode, toString автоматаар үүсгэх
- C) Exception шидэх
- D) Лог бичих
Зөв хариулт: B
Тайлбар:
record StudentResponse(Long id, String name) {}= Immutable DTO. Getter, constructor, equals, hashCode, toString автомат. DTO-д маш тохиромжтой.
Тест 40
@NotBlank ба @NotNull-ийн ялгаа юу вэ?
- A) Ялгаагүй
- B)
@NotNull= null биш,@NotBlank= null биш + хоосон string биш + зөвхөн хоосон зай биш - C)
@NotBlankнь тоонд ашиглагдана - D)
@NotNullнь String-д ашиглагддаггүй
Зөв хариулт: B
Тайлбар:
@NotNull=nullбиш байхад хангалттай (хоосон "" зөвшөөрнө).@NotBlank=nullбиш +""биш +" "биш. String-д@NotBlankилүү тохиромжтой.
Тест 41
HTTP 204 No Content хэзээ буцаадаг вэ?
- A) GET хүсэлтэд
- B) DELETE амжилттай — хариу body хоосон
- C) POST хүсэлтэд
- D) Алдаа гарахад
Зөв хариулт: B
Тайлбар: 204 = Амжилттай, гэхдээ буцаах өгөгдөл байхгүй. DELETE амжилттай → 204 No Content. Body хоосон.
Тест 42
HTTP 409 Conflict хэзээ буцаадаг вэ?
- A) Нөөц олдсонгүй
- B) Давхардсан мэдээлэл (жишээ: имэйл бүртгэлтэй) — бизнес дүрмийн зөрчил
- C) Серверийн алдаа
- D) Нэвтрэлт шаардлагатай
Зөв хариулт: B
Тайлбар: 409 Conflict = Хүсэлт формат зөв, гэхдээ бизнес дүрэмтэй зөрчилдөж байна. Жишээ: "batbold@example.com имэйл бүртгэлтэй байна."
Тест 43
@RequestParam ба @PathVariable-ийн ялгаа юу вэ?
- A) Ялгаагүй
- B)
@PathVariable= URL зам (/students/1),@RequestParam= Query (?page=1) - C) Хоёулаа body-аас авна
- D) Хоёулаа header-аас авна
Зөв хариулт: B
Тайлбар:
/students/{id}→@PathVariable Long id.?page=1&size=10→@RequestParam int page. Нөөцийн ID = Path, шүүлт/хуудас = Query.
Тест 44
@PostMapping annotation юу хийдэг вэ?
- A) GET хүсэлт хүлээн авах
- B) HTTP POST хүсэлтийг тухайн метод руу чиглүүлэх
- C) DELETE хүсэлт хүлээн авах
- D) Бүх хүсэлт хүлээн авах
Зөв хариулт: B
Тайлбар:
@PostMapping= HTTP POST хүсэлт → Шинэ нөөц үүсгэх.@GetMapping= GET,@PutMapping= PUT,@DeleteMapping= DELETE.
Тест 45
Spring Boot application.yml файл юунд ашигладаг вэ?
- A) Код бичих
- B) Програмын ТОХИРГОО — port, database URL, JPA тохиргоо зэрэг
- C) Тест бичих
- D) HTML бичих
Зөв хариулт: B
Тайлбар:
application.yml= Програмын бүх тохиргоо.server.port,spring.datasource.url,spring.jpa.hibernate.ddl-autoзэрэг. Hardcode-гүй.
Тест 46
cURL гэж юу вэ?
- A) Програмчлалын хэл
- B) Командын мөрөөс HTTP хүсэлт илгээх хэрэгсэл
- C) Мэдээллийн сан
- D) IDE
Зөв хариулт: B
Тайлбар: cURL = Terminal-аас API тестлэх.
curl -X POST http://localhost:8080/api/v1/students -H "Content-Type: application/json" -d '{"name":"Бат"}'.
Тест 47
H2 Database юу вэ?
- A) Production мэдээллийн сан
- B) Java-д суулгасан жижиг мэдээллийн сан — хөгжүүлэлт, тестэд тохиромжтой (in-memory)
- C) NoSQL мэдээллийн сан
- D) Кеш систем
Зөв хариулт: B
Тайлбар: H2 = In-memory DB. Програм ажиллаж байх үед л өгөгдөл хадгалагдана. Хөгжүүлэлт, тестэд маш тохиромжтой. Production-д PostgreSQL, MySQL ашиглана.
Тест 48
spring.jpa.hibernate.ddl-auto=create-drop юу хийдэг вэ?
- A) Зөвхөн уншиx
- B) Програм эхлэхэд хүснэгт ҮҮСГЭЖ, зогсоход УСТГАХ
- C) Зөвхөн шинэчлэх
- D) Юу ч хийхгүй
Зөв хариулт: B
Тайлбар:
create-drop= Хөгжүүлэлтийн орчинд тохиромжтой. Production-дvalidateэсвэлnoneашиглана.update= Хүснэгтийг шинэчлэх (устгахгүй).
Тест 49
RESTful API-д URI-д camelCase ашиглаж болох уу?
- A) Зөвшөөрнө
- B) Болохгүй — жижиг үсэг + зураас (-) ашиглах:
/course-enrollments - C) PascalCase ашиглана
- D) UPPER_CASE ашиглана
Зөв хариулт: B
Тайлбар: URI стандарт: Жижиг үсэг + зураас.
/course-enrollments= Зөв./courseEnrollments= camelCase буруу. URI нь case-sensitive → Стандарт чухал.
Тест 50
@Service annotation юу хийдэг вэ?
- A) Controller зарлах
- B) Spring Bean зарлах — бизнес логик агуулсан Service давхаргын класс
- C) Entity зарлах
- D) Тест зарлах
Зөв хариулт: B
Тайлбар:
@Service= Spring IoC Container-д Bean болж бүртгэгдэнэ. Constructor Injection-аар бусад Bean-д тарина. Бизнес логик = Service давхарга.
Тест 51
Pagination-д page=0&size=10 гэсэн параметрүүд юу гэсэн утгатай вэ?
- A) 0 бичлэг, 10 хуудас
- B) Эхний хуудас (0-indexed), хуудас бүрт 10 бичлэг
- C) 10-р хуудас
- D) 0-аас 10 хүртэлх ID
Зөв хариулт: B
Тайлбар:
page=0= Эхний хуудас (0-indexed).size=10= Хуудас бүрт 10 бичлэг. 150 бичлэг → 15 хуудас (0-14).
Тест 52
API-д Location header хэзээ буцаадаг вэ?
- A) GET хүсэлтэд
- B) POST → 201 Created — Шинэ нөөцийн URL-ийг
Locationheader-т буцаах - C) DELETE хүсэлтэд
- D) Бүх хүсэлтэд
Зөв хариулт: B
Тайлбар:
POST /students→ 201 Created +Location: /api/v1/students/5. Клиент шинэ нөөцийн хаягийг мэдэж, шууд хандаж болно.
Тест 53
gRPC нь REST-ээс юугаараа ялгаатай вэ?
- A) Ялгаагүй
- B) HTTP/2 + Protocol Buffers (binary) ашигладаг — илүү хурдан, бага хэмжээтэй
- C) Зөвхөн JSON ашигладаг
- D) Зөвхөн GET метод
Зөв хариулт: B
Тайлбар: gRPC = HTTP/2 + Protobuf (binary). JSON-оос 5-10x жижиг, хурдан. Microservice хоорондын харилцаанд тохиромжтой. Гэхдээ browser шууд ашиглахад хэцүү.
Тест 54
OAuth 2.0 юу хийдэг вэ?
- A) Мэдээллийн сан
- B) Гуравдагч этгээдээр (Google, Facebook) нэвтрэх стандарт протокол
- C) API баримт бичиг
- D) Тест framework
Зөв хариулт: B
Тайлбар: OAuth 2.0 = "Google-ээр нэвтрэх". Хэрэглэгч нууц үгээ манай системд ӨГӨХГҮЙГЭЭР, Google-ээр баталгаажуулж нэвтэрнэ. Access Token авна.
Тест 55
API Key ба JWT-ийн ялгаа юу вэ?
- A) Ялгаагүй
- B) API Key = Энгийн түлхүүр (хэн бэ мэдэхгүй), JWT = Хэрэглэгчийн мэдээлэл агуулсан токен
- C) JWT нь аюулгүй биш
- D) API Key нь илүү аюулгүй
Зөв хариулт: B
Тайлбар: API Key = Хаалганы түлхүүр (хэн барьж байгаа мэдэхгүй). JWT = Паспорт (хэн, ямар эрхтэй, хэзээ дуусах мэдээлэл агуулагдана).
Тест 56
Дараах кодын гол асуудал юу вэ?
@GetMapping("/students")
public List<Student> findAll() {
return repository.findAll();
}
- A) Асуудалгүй
- B) Entity-г шууд буцааж байна — DTO ашиглах ёстой
- C) Нэрлэлт буруу
- D) Annotation буруу
Зөв хариулт: B
Тайлбар: Entity шууд буцаавал: password зэрэг нууц талбар задарна, Entity өөрчлөхөд API эвдэрнэ. StudentResponse DTO ашиглах ёстой.
Тест 57
@ExceptionHandler annotation юу хийдэг вэ?
- A) Exception үүсгэх
- B) Тодорхой Exception төрлийг барьж, тохирсон хариу буцаах метод зарлах
- C) Бүх алдааг нуух
- D) Лог бичих
Зөв хариулт: B
Тайлбар:
@ExceptionHandler(StudentNotFoundException.class)= StudentNotFoundException гарахад энэ метод ажиллаж, 404 + ErrorResponse буцаана.
Тест 58
Дараах status code-ийн зөв хэрэглээ аль нь вэ?
- A) POST амжилттай → 200
- B) POST амжилттай → 201 Created
- C) POST амжилттай → 204
- D) POST амжилттай → 301
Зөв хариулт: B
Тайлбар: POST = Шинэ нөөц үүсгэх → 201 Created + Location header. 200 = Ерөнхий амжилт (GET-д). 204 = Агуулга хоосон (DELETE-д).
Тест 59
@Column(unique = true) юу хийдэг вэ?
- A) Тогтмол хувьсагч
- B) Мэдээллийн сангийн баганад ДАВТАГДАШГҮЙ хязгаарлалт тавих
- C) Primary key болгох
- D) Index үүсгэх
Зөв хариулт: B
Тайлбар:
@Column(unique = true)= Email зэрэг давтагдаж болохгүй утга. Хоёр оюутан ижил имэйлтэй байж болохгүй → DB-д unique constraint.
Тест 60
Serialization ба Deserialization гэж юу вэ?
- A) Ялгаагүй
- B) Serialization = Java объект → JSON. Deserialization = JSON → Java объект
- C) Хоёулаа JSON → объект
- D) Хоёулаа объект → JSON
Зөв хариулт: B
Тайлбар: Response буцахад: Student → JSON (Serialization). Request ирэхэд: JSON → StudentCreateRequest (Deserialization). Jackson library автоматаар хийнэ.
Тест 61
REST API-д Idempotent key юунд хэрэгтэй вэ?
- A) Формат солиход
- B) Сүлжээний алдаанаас давхар POST (давхар үүсгэлт) гарахаас сэргийлэх
- C) Зөвхөн хурд нэмэх
- D) Лог бичих
Зөв хариулт: B
Тайлбар: Клиент POST илгээсэн, хариу ирэхгүй → Дахин илгээх → 2 дахь нөөц үүсэх!
Idempotency-Keyheader ашиглавал сервер давхар хүсэлтийг мэдэж, ижил хариу буцаана.
Тест 62
Spring Boot-д @GeneratedValue(strategy = GenerationType.IDENTITY) юу хийдэг вэ?
- A) Гараар ID оноох
- B) DB автоматаар ID үүсгэх (auto-increment)
- C) UUID үүсгэх
- D) Timestamp үүсгэх
Зөв хариулт: B
Тайлбар:
IDENTITY= Мэдээллийн сан auto-increment ашиглан ID үүсгэнэ. Оюутан нэмэх бүрт ID автоматаар 1, 2, 3... болж нэмэгднэ.
Тест 63
@Enumerated(EnumType.STRING) юу хийдэг вэ?
- A) Тоогоор хадгалах
- B) Enum утгыг DB-д STRING болгон хадгалах (жишээ: "ACTIVE", "INACTIVE")
- C) JSON руу хөрвүүлэх
- D) Validation хийх
Зөв хариулт: B
Тайлбар:
EnumType.STRING= "ACTIVE" гэж хадгална.EnumType.ORDINAL= 0, 1, 2 гэж хадгална (Enum дараалал өөрчлөгдвөл эвдэрнэ → STRING ашиглах).
Тест 64
Page<T> объект юу агуулдаг вэ?
- A) Зөвхөн өгөгдөл
- B) Өгөгдөл + хуудсын мэдээлэл (нийт бичлэг, нийт хуудас, одоогийн хуудас)
- C) Зөвхөн тоо
- D) Зөвхөн хуудсын дугаар
Зөв хариулт: B
Тайлбар:
Page<StudentResponse>=content(өгөгдлийн жагсаалт) +totalElements,totalPages,number(хуудсын дугаар),size. Клиент хуудаслалтыг хялбар хийнэ.
Тест 65
CORS (Cross-Origin Resource Sharing) гэж юу вэ?
- A) Кеш систем
- B) Өөр домэйноос API дуудахыг зөвшөөрөх/хориглох механизм
- C) Мэдээллийн сан
- D) Тестийн framework
Зөв хариулт: B
Тайлбар: CORS =
localhost:3000(React) →localhost:8080(API). Өөр домэйн = Cross-Origin. Сервер@CrossOriginэсвэл CORS тохиргоогоор зөвшөөрнө.
Тест 66
@CrossOrigin annotation юу хийдэг вэ?
- A) Exception зохицуулах
- B) Тодорхой домэйноос API руу хандахыг ЗӨВШӨӨРӨХ (CORS)
- C) Validation хийх
- D) Лог бичих
Зөв хариулт: B
Тайлбар:
@CrossOrigin(origins = "http://localhost:3000")= React frontend-аас хандахыг зөвшөөрнө. Production-д тодорхой домэйнууд л зөвшөөрөх.
Тест 67
Дараах аль нь REST API best practice БИШ вэ?
- A) Нөөц төвтэй URI
- B) HTTP метод зөв ашиглах
- C) Entity-г шууд API-аар буцаах
- D) Validation хийх
Зөв хариулт: C
Тайлбар: Entity шууд буцаах = Best practice БИШ. DTO ашиглах = Best practice. Нууц мэдээлэл задрах, API-Entity хатуу холбогдох эрсдэлтэй.
Тест 68
HTTP 429 status code юу гэсэн утгатай вэ?
- A) Серверийн алдаа
- B) Хэт олон хүсэлт (Too Many Requests) — Rate Limit хэтэрсэн
- C) Нөөц олдсонгүй
- D) Нэвтрэлт шаардлагатай
Зөв хариулт: B
Тайлбар: 429 = Rate Limiting-д хүрсэн. "1 минутад 100 хүсэлт" хязгаар хэтэрсэн.
Retry-Afterheader-т хэзээ дахин оролдохыг заана.
Тест 69
@RequestMapping("/api/v1/students") юу хийдэг вэ?
- A) Тест зарлах
- B) Тухайн Controller-ийн БҮХИЙ Endpoint-ийн суурь URL тодорхойлох
- C) Entity зарлах
- D) Validation хийх
Зөв хариулт: B
Тайлбар:
@RequestMapping("/api/v1/students")= Класс түвшинд. Дотор@GetMapping("/{id}")→ Бүтэн URL:/api/v1/students/{id}.
Тест 70
Дараах аль нь "Safe" HTTP метод вэ?
- A) POST
- B) GET — Сервер дээрх өгөгдлийг ӨӨРЧЛӨХГҮЙ
- C) DELETE
- D) PUT
Зөв хариулт: B
Тайлбар: Safe = Сервер дээрх state-ийг өөрчлөхгүй. GET, HEAD, OPTIONS = Safe. POST, PUT, PATCH, DELETE = Unsafe (state өөрчилнө).
Тест 71
REST-ийн "Uniform Interface" зарчим юу вэ?
- A) Нэг хэл ашиглах
- B) URL, HTTP метод, JSON зэргийг НЭГДМЭЛ, СТАНДАРТ дүрмээр ашиглах
- C) Нэг сервер ашиглах
- D) Нэг клиент ашиглах
Зөв хариулт: B
Тайлбар: Uniform Interface = REST-ийн гол зарчим. Бүх нөөц ижил дүрмээр (URL = noun, HTTP method = verb, JSON = формат). Стандарт → Бүх хөгжүүлэгч ойлгоно.
Тест 72
"Cacheable" зарчим яагаад чухал вэ?
- A) Аюулгүй байдал
- B) Хариуг кэшлэж, давтан хүсэлтэд хурдан хариулах — серверийн ачааллыг бууруулах
- C) Зөвхөн формат
- D) Зөвхөн нэрлэлт
Зөв хариулт: B
Тайлбар: GET хариуг кэшлэж болно → Дахин дуудахад серверт хандахгүй, кэшээс авна.
Cache-Control,ETagheader-аар удирдана.
Тест 73
ETag header юунд ашигладаг вэ?
- A) Нэвтрэлт
- B) Нөөцийн хувилбарыг мэдэх — өөрчлөгдсөн эсэхийг шалгаж, шаардлагагүй дамжуулалтаас зайлсхийх
- C) Rate limiting
- D) CORS
Зөв хариулт: B
Тайлбар:
ETag: "abc123"= Нөөцийн fingerprint. КлиентIf-None-Match: "abc123"header-ээр дуудна → Өөрчлөгдөөгүй бол 304 Not Modified (body илгээхгүй).
Тест 74
API Gateway юу хийдэг вэ?
- A) Код бичих
- B) Бүх API хүсэлтийг нэг цэгээр дамжуулж, routing, auth, rate limiting, load balancing хийх
- C) Тест ажиллуулах
- D) Мэдээллийн сан удирдах
Зөв хариулт: B
Тайлбар: API Gateway = Бүх хүсэлтийн "нэг хаалга". Routing (аль сервис рүү чиглүүлэх), Authentication, Rate Limiting, Load Balancing. Жишээ: Kong, AWS API Gateway.
Тест 75
"Content Negotiation" гэж юу вэ?
- A) Нэвтрэлт
- B) Клиент хүссэн формат (JSON/XML)-аар хариу буцаах —
Acceptheader ашиглах - C) Rate limiting
- D) Validation
Зөв хариулт: B
Тайлбар: Клиент
Accept: application/json→ JSON хариу.Accept: application/xml→ XML хариу. Сервер клиентийн хүсэлтийн дагуу формат сонгоно.
Тест 76
Дараах аль нь зөв Error Response формат вэ?
- A)
{"error": "fail"} - B)
{"status": 404, "error": "Not Found", "message": "ID=5 оюутан олдсонгүй", "timestamp": "...", "path": "/api/v1/students/5"} - C)
"Something went wrong" - D)
500
Зөв хариулт: B
Тайлбар: Сайн Error Response = status + error + тодорхой message + timestamp + path. Клиент алдааг ОЙЛГОЖ, дебаг хийж чадна.
Тест 77
@Tag annotation (Swagger) юу хийдэг вэ?
- A) Тест бичих
- B) Swagger UI дээр endpoint-уудыг БҮЛЭГЛЭЖ, нэр, тайлбар өгөх
- C) Validation хийх
- D) Exception зохицуулах
Зөв хариулт: B
Тайлбар:
@Tag(name = "Student API", description = "Оюутны CRUD API")= Swagger UI дээр endpoint-уудыг "Student API" бүлэг дотор харуулна.
Тест 78
@Operation annotation (Swagger) юу хийдэг вэ?
- A) Тест бичих
- B) Тодорхой endpoint-ийн summary, description, response бичих — Swagger UI-д харуулах
- C) Validation хийх
- D) Exception зохицуулах
Зөв хариулт: B
Тайлбар:
@Operation(summary = "Бүх оюутан авах")= Swagger UI-д endpoint бүрийн тайлбар харуулна. API баримт бичиг = Хөгжүүлэгчийн хамгийн сайн найз.
Тест 79
Webhook ба REST API-ийн ялгаа юу вэ?
- A) Ялгаагүй
- B) REST = Клиент ДУУДНА (pull), Webhook = Сервер МЭДЭГДЭНЭ (push) — үйл явдал гарахад
- C) Webhook нь илүү хурдан
- D) REST нь илүү аюулгүй
Зөв хариулт: B
Тайлбар: REST = Клиент хэзээ хүсвэл дуудна (polling). Webhook = Үйл явдал гарахад сервер клиентийн URL руу POST хүсэлт илгээнэ (real-time мэдэгдэл).
Тест 80
HTTPS нь HTTP-ээс юугаараа ялгаатай вэ?
- A) Ялгаагүй
- B) TLS/SSL шифрлэлт нэмсэн — мэдээлэл шифрлэгдэж дамжуулагдана
- C) Хурдан
- D) Зөвхөн GET ашигладаг
Зөв хариулт: B
Тайлбар: HTTPS = HTTP + TLS шифрлэлт. Мэдээлэл (password, token, хувийн мэдээлэл) шифрлэгдэж дамжуулагдана → Man-in-the-middle халдлагаас хамгаална.
Тест 81
Дараах аль нь Richardson Maturity Model-ийн хамгийн дээд түвшин вэ?
- A) Level 0 — Нэг endpoint, нэг метод
- B) Level 3 — HATEOAS (Hypermedia Controls)
- C) Level 1 — Resources
- D) Level 2 — HTTP Verbs
Зөв хариулт: B
Тайлбар: Level 0 = Нэг URI, POST. Level 1 = Нөөц төвтэй URI. Level 2 = HTTP метод зөв. Level 3 = HATEOAS. Дээд түвшин = "Жинхэнэ REST".
Тест 82
@Size(min=2, max=100) annotation юу хийдэг вэ?
- A) Тоон хязгаар
- B) String-ийн УРТТАЙ 2-100 тэмдэгт хязгаар тавих
- C) Массивын хэмжээ
- D) Бүх төрөлд ашиглана
Зөв хариулт: B
Тайлбар:
@Size(min=2, max=100)= String утгын урт 2-100 тэмдэгт байх ёстой. Хэт богино нэр ("A"), хэт урт нэр зайлсхийнэ.
Тест 83
@Min ба @Max annotation юунд ашигладаг вэ?
- A) String-д
- B) Тоон утгын доод/дээд ХЯЗГААР тавих —
@Min(0) @Max(4) Double gpa - C) Boolean-д
- D) Огноонд
Зөв хариулт: B
Тайлбар:
@Min(0) @Max(4)= GPA 0.0-4.0 хооронд байх ёстой. Хязгаараас гадуур утга ирвэл 400 Bad Request.
Тест 84
Microservice архитектурт API яагаад чухал вэ?
- A) Шаардлагагүй
- B) Microservice бүр тусдаа, API-аар л бие биетэйгээ ХАРИЛЦАНА
- C) Зөвхөн нэг сервис байна
- D) Мэдээллийн сан хуваалцана
Зөв хариулт: B
Тайлбар: Microservice = Жижиг, бие даасан сервисүүд. Student Service ↔ Course Service ↔ Payment Service. Бүгд API (REST/gRPC)-аар харилцана. API = Microservice-ийн "хэл".
Тест 85
"Contract-First" API дизайн гэж юу вэ?
- A) Эхлээд код бичих
- B) Эхлээд API-ийн ТОДОРХОЙЛОЛТ (OpenAPI spec) бичиж, дараа нь кодыг бичих
- C) Зөвхөн тест бичих
- D) Баримт бичиг бичэхгүй
Зөв хариулт: B
Тайлбар: Contract-First = OpenAPI YAML/JSON эхлээд бичих → Frontend, Backend баг зэрэг ажиллаж чадна. API-ийн "гэрээг" эхлээд тохирох.
Тест 86
ResponseEntity.noContent().build() юу буцаадаг вэ?
- A) 200 OK + JSON
- B) 204 No Content — Body хоосон
- C) 404 Not Found
- D) 500 Error
Зөв хариулт: B
Тайлбар:
noContent()= 204 status code, body хоосон. DELETE амжилттай → Устгасан тул буцаах өгөгдөл байхгүй.
Тест 87
ResponseEntity.created(location).body(dto) юу буцаадаг вэ?
- A) 200 OK
- B) 201 Created + Location header + DTO body
- C) 204 No Content
- D) 404 Not Found
Зөв хариулт: B
Тайлбар: POST амжилттай → 201 + Location:
/api/v1/students/5(шинэ нөөцийн URL) + Body: StudentResponse JSON.
Тест 88
"Backward Compatibility" яагаад API-д чухал вэ?
- A) Чухал биш
- B) Хуучин клиентүүд API шинэчлэгдсэн ч ЭВДРЭХГҮЙ үргэлжлүүлэн ажиллах
- C) Зөвхөн хурд
- D) Зөвхөн аюулгүй байдал
Зөв хариулт: B
Тайлбар: v1 API → v2 нэмэхдээ v1-ийг УСТГАХГҮЙ. Мобайл апп (хуучин хувилбар) v1 ашиглаж байна → Устгавал апп эвдэрнэ. Шинэ → v2, хуучин → v1 хэвээр.
Тест 89
@Email annotation юу шалгадаг вэ?
- A) Нэр
- B) String утга имэйл ФОРМАТ-д нийцэж байгаа эсэхийг шалгах
- C) Нас
- D) ID
Зөв хариулт: B
Тайлбар:
Тест 90
Spring Boot-д orElseThrow() юу хийдэг вэ?
- A) Утга буцаах
- B) Optional-д утга БАЙХГҮЙ бол Exception шидэх
- C) Лог бичих
- D) Null буцаах
Зөв хариулт: B
Тайлбар:
repository.findById(id).orElseThrow(() -> new StudentNotFoundException(...))= ID-аар олдохгүй бол Exception. Null буцаахгүй → NullPointerException-ээс хамгаалах.
Тест 91
Pageable interface юу хийдэг вэ?
- A) HTML хуудас
- B) Хуудаслалтын мэдээлэл (хуудсын дугаар, хэмжээ, эрэмбэ) Spring Data-д дамжуулах
- C) Exception зохицуулах
- D) JSON хөрвүүлэх
Зөв хариулт: B
Тайлбар:
PageRequest.of(page, size, sort)= Pageable объект. RepositoryfindAll(pageable)→ DB-д LIMIT, OFFSET автоматаар нэмэгдэнэ.
Тест 92
"Idempotent" DELETE-ийн зөв ажиллагаа аль нь вэ?
- A) 2 дахь DELETE-д 500 буцаах
- B) 1 дахь DELETE → 204, 2 дахь DELETE → 404 (аль аль тохиолдолд нөөц байхгүй → идемпотент)
- C) 2 дахь DELETE-д дахин устгах
- D) Exception шидэх
Зөв хариулт: B
Тайлбар: Идемпотент = Үр дүн ижил. 1 удаа устгасан → 204. Дахин дуудвал → 404 (аль хэдийн устгагдсан). Хоёр тохиолдолд нөөц "устгагдсан" → Ижил.
Тест 93
API-д "Deprecation" гэж юу вэ?
- A) Шинэ функц нэмэх
- B) Хуучин endpoint/функцыг "хуучирсан" гэж тэмдэглэж, ирээдүйд устгахыг анхааруулах
- C) Алдаа засах
- D) Тест бичих
Зөв хариулт: B
Тайлбар:
@Deprecated+Sunsetheader = "Энэ endpoint v2-д солигдсон. 2025-06-01-д устгагдана." Клиентэд шилжих хугацаа өгнө.
Тест 94
"N+1 Problem" гэж юу вэ?
- A) Нэрлэлтийн асуудал
- B) 1 query-ээр жагсаалт авч, бичлэг бүрд нэмэлт query ажиллуулах → N+1 query
- C) Зөвхөн UI асуудал
- D) Зөвхөн тестийн асуудал
Зөв хариулт: B
Тайлбар: 100 оюутан авах (1 query) + оюутан бүрийн хичээл авах (100 query) = 101 query! JPA
@EntityGraph,JOIN FETCH, DTO projection-оор шийднэ.
Тест 95
Postman юу хийдэг вэ?
- A) Код бичих
- B) API тестлэх GUI хэрэгсэл — хүсэлт илгээх, хариу шалгах, collection хадгалах
- C) Мэдээллийн сан
- D) Deploy хийх
Зөв хариулт: B
Тайлбар: Postman = API тестлэх хамгийн түгээмэл GUI хэрэгсэл. Request илгээх, response шалгах, environment тохируулах, collection хуваалцах.
Тест 96
"API-First Design" гэж юу вэ?
- A) Backend эхлээд бичих
- B) API-ийн тодорхойлолтыг хамгийн ЭХЭНД бичиж, бүх баг тэр гэрээний дагуу ажиллах
- C) Frontend эхлээд бичих
- D) Тест эхлээд бичих
Зөв хариулт: B
Тайлбар: API-First = OpenAPI spec → Frontend + Backend зэрэг эхэлнэ. Mobile + Web + Partner бүгд ижил API гэрээ. Зөрчилдөл бага, хурд нэмнэ.
Тест 97
@Table(name = "students") annotation юу хийдэг вэ?
- A) Controller тодорхойлох
- B) Entity-г мэдээллийн сангийн "students" ХҮСНЭГТТЭЙ холбох
- C) DTO тодорхойлох
- D) Тест тодорхойлох
Зөв хариулт: B
Тайлбар:
@Table(name = "students")= Java Student класс → DB-ийн "students" хүснэгт. Нэр зөрөх бол заавал зааж өгнө.
Тест 98
REST API-д "Bulk Operation" (олон бичлэг нэг дор) хэрхэн хийх вэ?
- A) Нэг нэгээр дуудах
- B)
POST /students/batch— Request body-д олон бичлэг агуулсан массив дамжуулах - C) GET ашиглах
- D) Боломжгүй
Зөв хариулт: B
Тайлбар: 100 оюутан нэмэх = 100 POST дуудах (удаан).
POST /students/batch+[{...}, {...}]= Нэг хүсэлт. Network overhead бага, хурдан.
Тест 99
"Health Check" endpoint юу вэ?
- A) Оюутны мэдээлэл
- B)
GET /actuator/health— Системийн ажиллагаа, DB холболт, дискний зай зэргийг шалгах - C) Тест ажиллуулах
- D) Код шалгах
Зөв хариулт: B
Тайлбар: Health Check = Monitoring системүүд (Kubernetes, Load Balancer) API амьд байгаа эсэхийг шалгана.
{"status": "UP"}→ Ажиллаж байна.
Тест 100
REST API яагаад орчин үеийн програм хангамжийн бүтээлтэд хамгийн чухал вэ?
- A) Зөвхөн нэг хэрэглээнд
- B) Frontend-Backend, Mobile-Server, Microservice хоорондын ХЭЛНИЙ ҮЛ ХАМААРАН харилцах стандарт
- C) Зөвхөн вэб хуудаст
- D) Зөвхөн том компаниудад
Зөв хариулт: B
Тайлбар: REST API = Орчин үеийн системүүдийн "lingua franca" (нийтлэг хэл). React ↔ Spring Boot ↔ Mobile ↔ Гуравдагч систем. HTTP + JSON = Хэлний, платформын ялгаагүй. API сайн = Систем сайн.
📚 Ашигласан эх сурвалжууд:
- Roy Fielding — Architectural Styles and the Design of Network-based Software Architectures (2000, PhD Dissertation)
- Richardson, Leonard — RESTful Web APIs (O'Reilly, 2013)
- Spring Boot Reference Documentation — docs.spring.io
- OpenAPI Specification 3.0 — swagger.io/specification
- RFC 7231 — HTTP/1.1 Semantics and Content
- RFC 7519 — JSON Web Token (JWT)
- Google API Design Guide — cloud.google.com/apis/design
- Microsoft REST API Guidelines — github.com/microsoft/api-guidelines