Java: Elegant Sitemap Generation Using 4 Design Patterns and the Open/Closed Principle
This article demonstrates how to generate website sitemap.xml files in Java by combining four design patterns—Strategy, Factory, Template Method, and Builder—along with the Open/Closed Principle, providing extensible, maintainable code illustrated with enums, configuration classes, and concrete implementations.
Sitemap.xml is a file that lists almost all URLs of a website so that search‑engine spiders can crawl the site efficiently. Because a single sitemap file cannot contain more than 50,000 URLs, large sites need a sitemapindex that references multiple child sitemap files.
Enum for Sitemap Types
An enum WebSiteMapBizEnums is introduced to hold the basic information of each sitemap file (main, sku, activity, blog). The enum provides a numeric key, the file name, and a grouping string.
public enum WebSiteMapBizEnums {
MAIN_SITEMAP(1, "main_sitemap.xml", "main"),
SKU_SITEMAP(2, "sku_sitemap.xml", "sku"),
ACTIVITY_SITEMAP(3, "activity_sitemap.xml", "activity"),
BLOG_SITEMAP(4, "blog_sitemap.xml", "blog");
private final Integer key;
private final String fileName;
private String group;
WebSiteMapBizEnums(Integer key, String fileName, String group) {
this.key = key;
this.fileName = fileName;
this.group = group;
}
public Integer getKey() { return key; }
public String getFileName() { return fileName; }
public String getGroup() { return group; }
}Configuration Properties
A WebSitemapProperties class (bound to the sitemap prefix) stores the output directory and domain name, which are later used by the generator.
@ConfigurationProperties("sitemap")
@Data
public class WebSitemapProperties {
private String fileDir;
private String domain;
}Strategy Pattern
A WebSiteMapLocationStrategy interface defines two methods: getEnumType() to identify the sitemap type and executeBuild() to perform the generation. A concrete MainLocationStrategy shows a typical implementation that queries data, builds URL objects, and writes them to the corresponding file.
public interface WebSiteMapLocationStrategy {
WebSiteMapBizEnums getEnumType();
void executeBuild(WebSitemapProperties sitemapProperties);
}
public class MainLocationStrategy implements WebSiteMapLocationStrategy {
@Override
public WebSiteMapBizEnums getEnumType() { return WebSiteMapBizEnums.MAIN_SITEMAP; }
@Override
public void executeBuild(WebSitemapProperties sitemapProperties) {
// 1. query DB
// 2. build URL objects
// 3. write to sitemap.xml
}
}The article lists four ways to register strategies: manual map registration, Java SPI / spring.factories, Spring IOC bean lookup, and reflection. The author adopts the Spring IOC approach, annotating each strategy with @Service and letting the container manage them.
Factory + Open/Closed Principle
A factory class WebSitemapFactory loads all WebSiteMapLocationStrategy beans from the Spring context and stores them in a static map keyed by the enum's numeric key. New sitemap types can be added by creating a new strategy class; no factory code needs to change, satisfying the Open/Closed Principle.
public class WebSitemapFactory {
private static Map<Integer,WebSiteMapLocationStrategy> registerMap = new HashMap<>();
public static void initLoad() {
Map<String, WebSiteMapLocationStrategy> beanMap = SpringContextUtil.getContext().getBeansOfType(WebSiteMapLocationStrategy.class);
for (WebSiteMapLocationStrategy s : beanMap.values()) {
registerMap.put(s.getEnumType().getKey(), s);
}
}
public static WebSiteMapLocationStrategy getSiteMapLocationStrategy(Integer key) {
return registerMap.get(key);
}
}Template Method Pattern
An abstract class AbstractLocationStrategy implements the common workflow: pre‑processing, building the WebSitemapGenerator, writing the file, and post‑processing. Subclasses only need to implement doWebSitemapGeneratorBuild() to provide business‑specific data.
public abstract class AbstractLocationStrategy implements WebSiteMapLocationStrategy {
@Override
public void executeBuild(WebSitemapProperties props) {
try {
processBefore();
WebSitemapGenerator gen = doWebSitemapGeneratorBuild(props);
writeData(gen);
processAfter();
} catch (Exception e) { e.printStackTrace(); }
}
protected abstract WebSitemapGenerator doWebSitemapGeneratorBuild(WebSitemapProperties props) throws Exception;
private void writeData(WebSitemapGenerator gen) { gen.write(); }
protected void processBefore() {}
private void processAfter() {}
}Builder Pattern via sitemapgen4j
The third‑party library sitemapgen4j (version 1.1.2) provides a builder for WebSitemapGenerator. The builder is used in the concrete strategy to set the domain, output directory, date format, and file‑name prefix.
WebSitemapGenerator generator = WebSitemapGenerator.builder(sitemapProperties.getDomain(), new File(sitemapProperties.getFileDir()))
.dateFormat(new W3CDateFormat(W3CDateFormat.Pattern.DAY))
.fileNamePrefix(getEnumType().getFileName())
.build();Inside the concrete ArticleLocationStrategy, the author demonstrates querying dummy data, constructing URLs with WebSitemapUrl, and adding them to the generator.
for (Object article : dataList) {
String url = prefix + "articleId.html";
WebSitemapUrl.Options opt = new WebSitemapUrl.Options(url);
opt.lastMod(new Date());
WebSitemapUrl sitemapUrl = opt.changeFreq(ChangeFreq.DAILY).priority(0.9).build();
websiteMapGen.addUrl(sitemapUrl);
}Client Invocation
The main class loads the factory, creates a WebSitemapProperties instance, iterates over all enum values, retrieves the corresponding strategy from the factory, and executes the build.
public class TestBiz {
public static void main(String[] args) {
WebSitemapFactory.initLoad();
WebSitemapProperties props = new WebSitemapProperties();
for (WebSiteMapBizEnums biz : WebSiteMapBizEnums.values()) {
WebSiteMapLocationStrategy strategy = WebSitemapFactory.getSiteMapLocationStrategy(biz.getKey());
if (strategy != null) {
strategy.executeBuild(props);
}
}
}
}Conclusion
By layering Strategy, Factory, Template Method, and Builder patterns together, the sitemap generation code becomes highly extensible and adheres to the Open/Closed Principle. Adding a new business type only requires a new strategy implementation, while the surrounding infrastructure remains unchanged—an approach that Java engineers can showcase in interviews and apply to similar code‑generation tasks.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ubiquitous Tech
A ubiquitous public account for pirate enthusiasts, regularly sharing curated experiences, tech learning, and growth insights. Currently publishing articles on AI RAG customer service, AI MCP technology, and open-source design. Personal free Knowledge Planet: Awakening New World Programmer.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
