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
MessageSourcei18n 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
RestTemplateUTF-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 / setting | Mô tả | Mặc định |
|---|---|---|
govex.http.cache.time-to-live-in-days | Thời gian cache tài nguyên tĩnh (js, css, ảnh, i18n...) ở profile prod | 1461 |
geoip.config | Setting (qua govex-cloud-config) chọn nhà cung cấp định vị IP: maxmind hoặc ip2region | không có |
syncCron (trong nội dung geoip.config) | Lịch đồng bộ dữ liệu MaxMind | 0 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 MaxMind | khô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 ý
GeoLocationConfigurationkhông được đăng ký tự động quaAutoConfiguration.imports; cần component-scan bao trùmvn.govex.cloud.web.geo(hoặc@Importthủ công) thì beangeoLocationmới có.- Bean
geoLocationchỉ được tạo khi classpath cóSettingRepositorycủagovex-cloud-config; cấu hình thiếu/sai sẽ dùng fallbackNoneGeoLocationParserImpl. org.lionsoul:ip2regionvàcom.maxmind.geoip2:geoip2được khai báoprovided+optional: muốn dùng parser tương ứng phải tự thêm dependency (kèmgovex-cloud-configkhi dùng beangeoLocation).CachingHttpHeadersFiltervàCookieCsrfFiltercần được đăng ký thủ công nhưFilternếu muốn dùng.WebJacksonModule/GeoLocationJacksonModulekhông tự đăng ký vàoObjectMapper;govex-cloud-oauth2thêm chúng quaSupportJackson2Module.