System Architecture
The platform adopts a Browser/Server (B/S) architecture with clear separation of concerns across three tiers. The presentation layer delivers dynamic content through server-side rendering, while the application layer encapsulates business rules for inventory management, transaction processing, and user authorization. Data persistence utilizes MySQL 8.0 with strict UTF-8mb4 encoding to support international artist metadata and multilingual content.
Database Schema Design
The relational model adheres to third normal form (3NF) to minimize redundancy while maintaining referential integrity. Core entities include:
- UserAccounts: Stores encrypted credentials, contact details, and role assignments
- MusicProducts: Contains album metadata, pricing, stock levels, and cover art URLs
- GenreHierarchy: Supports nested classifications with parent-child relationships
- TransactionRecords: Maintains order history with immutable audit trails
- CartSessions: Temporary storage for pending purchases linked to user sessions
All textual data utilizes utf8mb4_unicode_ci collation to properly handle emoji, special characters, and non-Latin scripts in artist names and album titles.
Authentication Layer
The security implementation employs server-side session management with bcrypt hashing for credential storage. The authentication endpoint validates user identity and establishes session context:
@RestController
@RequestMapping("/api/auth")
public class SecurityController {
private final IdentityService identityService;
public SecurityController(IdentityService identityService) {
this.identityService = identityService;
}
@PostMapping("/login")
public ResponseEntity<AuthResult> authenticate(@RequestBody CredentialPayload payload,
HttpServletRequest request) {
UserPrincipal principal = identityService.authenticate(
payload.getIdentifier(),
payload.getSecret()
);
if (principal != null) {
request.getSession().setAttribute("userContext", principal);
return ResponseEntity.ok(new AuthResult(principal.getId(),
principal.getAccessLevel(),
"/home"));
}
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
}
Registration follows similar patterns with email verification and unique constraint validation on usernames.
Product Catalog Services
The browsing interface implements pagination and dynamic filtering capabilities. The inventory retrieval service demonstrates repository pattern implementation:
@Service
public class CatalogService {
private final MusicRepository musicRepo;
public CatalogService(MusicRepository musicRepo) {
this.musicRepo = musicRepo;
}
public Page<AlbumDto> fetchReleases(int pageNum, int pageSize, Optional<Long> categoryFilter) {
Pageable pageConfig = PageRequest.of(pageNum, pageSize,
Sort.by("releaseDate").descending());
return categoryFilter
.map(catId -> musicRepo.findByGenreId(catId, pageConfig))
.orElseGet(() -> musicRepo.findAll(pageConfig))
.map(this::transformToDto);
}
private AlbumDto transformToDto(MusicAlbum entity) {
return new AlbumDto(entity.getId(), entity.getTitle(),
entity.getArtistName(), entity.getPrice());
}
}
Shopping Cart Implementation
The cart management system utilizes a dual-storage strategy: transient client-side storage for anonymous visitors and persistent database records for authenticated customers. The calculation engine handles pricing logic and availability checks:
@Component
public class CartCalculator {
public CheckoutSummary computeTotals(List<LineItem> items) {
BigDecimal subtotal = items.stream()
.map(i -> i.getPrice().multiply(new BigDecimal(i.getCount())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal tax = subtotal.multiply(new BigDecimal("0.08"));
return new CheckoutSummary(items, subtotal, tax, subtotal.add(tax));
}
}
Administrative Operations
The management console provides comprehensive resource governance through role-based access control. Privileged users can manipulate account permissions, restructure product taxonomies, and modify inventory attributes through secured REST endpoints with audit loggging.
Application Configuration
Externalized configuration utilizes YAML format for environment-specific parameters:
server:
port: ${APP_PORT:8080}
servlet:
context-path: /audiostore
spring:
datasource:
url: jdbc:mysql://${DB_HOST:localhost}:3306/audio_db?useSSL=true&serverTimezone=UTC&characterEncoding=utf8
username: ${DB_USERNAME:app_user}
password: ${DB_PASSWORD:changeme}
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
pool-name: AudioStorePool
maximum-pool-size: 15
minimum-idle: 3
connection-timeout: 20000
jpa:
hibernate:
ddl-auto: validate
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
show-sql: false
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
logging:
level:
root: WARN
com.audiostore: DEBUG
pattern:
console: "%d{ISO8601} %highlight(%-5level) [%thread] %logger{40}: %msg%n"
This configuration employs HikariCP for connection pooling and schema validation to insure structural compatibility between application entities and database tables.