Chuyển tới nội dung chính

Hạ tầng Web MVC

govex-cloud-web cung cấp hạ tầng Web MVC dùng chung: formatter cho java.time, chuyển String sang enum, MessageSource đa ngôn ngữ, bean RestTemplate UTF-8, phân tích User-Agent và định vị theo địa chỉ IP. Thêm dependency cho mọi service web để chuẩn hoá cách nhận/parse dữ liệu đầu vào.

Khi nào sử dụng

  • Service cần parse ngày giờ, enum từ request param/query theo chuẩn thống nhất.
  • Cần MessageSource i18n dùng chung với các service khác.
  • Cần phân tích User-Agent (browser, phiên bản, device, platform) cho audit/thiết bị đăng nhập.
  • Cần định vị theo địa chỉ IP (MaxMind hoặc ip2region) cho log bảo mật.
  • Cần bean RestTemplate UTF-8 sẵn có thay vì tự khởi tạo.

Cài đặt

Thêm dependency (không khai version — version do BOM quản lý, xem Cài đặt):

<dependency>
<groupId>vn.govex.cloud</groupId>
<artifactId>govex-cloud-web</artifactId>
</dependency>

Auto-configuration MVC (formatter, enum converter, MessageSource, RestTemplate, UserAgentParser) tự bật khi dependency có trên classpath.

Cấu hình

Property / settingMô tảMặc định
govex.http.cache.time-to-live-in-daysThời gian cache tài nguyên tĩnh (js, css, ảnh, i18n...) ở profile prod1461
geoip.configSetting (qua govex-cloud-config) chọn nhà cung cấp định vị IP: maxmind hoặc ip2regionkhông có
syncCron (trong nội dung geoip.config)Lịch đồng bộ dữ liệu MaxMind0 0 1 * * ?
sessionKey (trong nội dung geoip.config)License key tải dữ liệu GeoLite2-City — bắt buộc khi dùng MaxMindkhông có

Cache tài nguyên tĩnh chỉ áp dụng ở profile prod; các môi trường khác không cache.

Sử dụng

Cấu hình cache tài nguyên tĩnh

govex:
http:
cache:
time-to-live-in-days: 365

Chuyển String sang enum bằng @EnumConvert

Enum implement BaseEnum và đánh dấu đúng một method static chuyển đổi:

public enum AppType implements BaseEnum {

STANDARD("standard", "Ứng dụng thông thường"),
INTEGRATION("integration", "Ứng dụng tích hợp");

private final String code;
private final String desc;

// constructor, getters...

@JsonCreator
@EnumConvert
public static AppType getType(String code) {
return Arrays.stream(values())
.filter(type -> type.code.equals(code))
.findFirst()
.orElse(null);
}
}

Phân tích User-Agent và định vị IP

@RequiredArgsConstructor
@Service
public class LoginService {

private final UserAgentParser userAgentParser;
private final GeoLocationParser geoLocationParser;

public void track(HttpServletRequest request) {
UserAgent userAgent = userAgentParser.getUserAgent(request);
GeoLocation location = geoLocationParser.getGeoLocation(request.getRemoteAddr());
// lưu log đăng nhập: browser, device, khu vực...
}
}

Dùng i18n và RestTemplate

Đặt file src/main/resources/i18n/messages.properties:

user.notFound=Không tìm thấy người dùng
@RequiredArgsConstructor
@Service
public class UserService {

private final MessageSource messageSource;
private final RestTemplate restTemplate;

public String notFoundMessage(Locale locale) {
return messageSource.getMessage("user.notFound", null, locale);
}
}

Lưu ý

  • GeoLocationConfiguration không được đăng ký tự động qua AutoConfiguration.imports; cần component-scan bao trùm vn.govex.cloud.web.geo (hoặc @Import thủ công) thì bean geoLocation mới có.
  • Bean geoLocation chỉ được tạo khi classpath có SettingRepository của govex-cloud-config; cấu hình thiếu/sai sẽ dùng fallback NoneGeoLocationParserImpl.
  • org.lionsoul:ip2regioncom.maxmind.geoip2:geoip2 được khai báo provided + optional: muốn dùng parser tương ứng phải tự thêm dependency (kèm govex-cloud-config khi dùng bean geoLocation).
  • CachingHttpHeadersFilterCookieCsrfFilter cần được đăng ký thủ công như Filter nếu muốn dùng.
  • WebJacksonModule/GeoLocationJacksonModule không tự đăng ký vào ObjectMapper; govex-cloud-oauth2 thêm chúng qua SupportJackson2Module.