发布时间:2018-04-01作者:laosun阅读(8031)
Java 动态生成网站sitemap地图,可无限扩展;sitemap.xml 是有限制的,单个sitemap文件不能包括超过50000个URL,不能超过10兆(M)。所以我们需要设置sitemap索引主文件。
Java 动态生成网站sitemap地图,可无限扩展,博主在写这篇文章的时候,网站sitemap放部署了两天。之前也是找寻一些开源api,但是发现很多写的都比较死,如果一个站点万级的文章,那么这个sitemap如何生成,很可怕,sitemap.xml 是有限制的,所以我们需要分批分块生成,设置主sitemap sitemapindex索引文件,引用多个子sitemap子文件,主要内容放入子sigtemap内。
单个sitemap文件不能包括超过50000个URL,不能超过10兆(M)
单个管理员帐户向google提交的sitemaps不能超过500个;
一个sitemap中可以索引多个sitemaps;
Sitemap 索引文件最多可列出 1,000 个 Sitemap;
本博客站点设置sitemap的方法是,根据导航栏目设置,每个导航栏目对应一个sitemap.xml。 其实这个扩展性也不好,但是对于博主来说已经足够了,能乘载几十万的文章了。真正的大型网站估计都不需要sitemap.xml
直接看代码吧!sitemap的结构什么的,我就不介绍了,本sitemap读写速度非常快,毫秒级!
好了,下载工具包:
<!-- https://mvnrepository.com/artifact/com.google.code/sitemapgen4j --> <dependency> <groupId>com.google.code</groupId> <artifactId>sitemapgen4j</artifactId> <version>1.0.1</version> </dependency>
生成源码:
博主为了大家都能看明白,又重新做了一个简版,保证大家都能看明白!
执行之前大家请先修改 String realPath = "/Users/sun/Documents"; 这是生成目录。
生产环境下,需要最好获取当前项目的根目录。
import java.io.File; import java.io.PrintWriter; import java.io.Writer; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import org.apache.commons.lang.StringUtils; import com.google.common.collect.Lists; import com.redfin.sitemapgenerator.ChangeFreq; import com.redfin.sitemapgenerator.WebSitemapGenerator; import com.redfin.sitemapgenerator.WebSitemapUrl; import com.sunjs.utils.SiteMapUtils; import com.sunjs.utils.Sitemap; public class Sunjs { public static String DATE_FORMAT = "yyyy-MM-dd"; public static void main(String[] args) { Sunjs sunjs = new Sunjs(); sunjs.createSiteMap(); } /** * 动态生成sitemap * 目录,web根目录,就是你的站点首页 index.html所在同级目录 * @author sun * @date 2018年3月31日 下午8:02:47 */ public void createSiteMap(){ try { long start = System.currentTimeMillis(); String WEBSITE = "https://www.sunjs.com"; /** 存储位置,实际应用项目中,需要指到网站的根目录 request.getSession().getServletContext().getRealPath("/") **/ String realPath = "/Users/sun/Documents"; List<Category> cList = findCategoryBy(); if(cList==null || cList.size()<1){ return ; } List<String> siteMapList = Lists.newArrayList();//存放子sitemap路径的list集合 for(Category category:cList){ /** 查询每个分类下对应的文章 **/ List<Article> aList = findArticleBy(category.getId()); if(aList!=null && aList.size()>0){ //start ====================================================================== String path = realPath+"/sitemap/"+category.getId(); fileExists(path);//判断文件夹是否存在,不存在则创建 WebSitemapGenerator sitemapGenerator = WebSitemapGenerator.builder(WEBSITE, new File(path)).gzip(false).build(); for(Article article:aList){//遍历取出来的文章 String url = "https://www.sunjs.com";//文章详情页的url地址 WebSitemapUrl sitemapUrl = new WebSitemapUrl.Options(url).lastMod(formatDate(article.getAddTime(), DATE_FORMAT)).priority(0.9).changeFreq(ChangeFreq.HOURLY).build(); sitemapGenerator.addUrl(sitemapUrl); } sitemapGenerator.write(); // end ====================================================================== siteMapList.add(WEBSITE+"/sitemap/"+category.getId()+"/sitemap.xml");//主索引文件需要这个路径 } } //TODO //其实分类 - list 页 url也应该存一个sitemap,看自己吧,如果也想告诉搜索引擎,我的list列表页也很重要,那么就做 /** 生成主索引文件 **/ if(siteMapList!=null && siteMapList.size()>0){ Collection<Sitemap> s = new ArrayList(); for(String url:siteMapList){ s.add(new Sitemap(url)); } Writer wt = new PrintWriter(new File(realPath+"/sitemap.xml")); SiteMapUtils.writeSitemapIndex(wt, s.iterator()); wt.close(); } long end = System.currentTimeMillis(); System.out.println("生成Sitemap完毕, 共耗时:"+(end-start)); } catch (Exception e) { e.printStackTrace(); } } /** * 模拟数据库查询 - 查询符合条件的文章分类 * @author sun * @date 2018年3月31日 下午8:12:41 * @param categoryId * @return */ public List<Category> findCategoryBy(){ List<Category> cList = Lists.newArrayList(); cList.add(new Category(1, new Date())); cList.add(new Category(2, new Date())); return cList; } /** * 模拟数据库查询 - 查询符合条件的文章 * @author sun * @date 2018年3月31日 下午7:47:50 * @return */ public List<Article> findArticleBy(Integer categoryId){ System.out.println("查询文章分类id为 "+categoryId+" 的所有符合条件的文章"); List<Article> aList = Lists.newArrayList(); aList.add(new Article(10, new Date())); aList.add(new Article(11, new Date())); aList.add(new Article(12, new Date())); return aList; } /** * 格式化日期 * @author sun * @date 2018年3月31日 下午8:05:30 * @param date * @param pattern * @return */ public static String formatDate(Date date, String pattern) { if (StringUtils.isEmpty(pattern)) { pattern = DATE_FORMAT; } DateFormat df = new SimpleDateFormat(pattern); return df.format(date); } /** * 判断文件目录是否存在 如果不存在,则创建新的文件夹 * @author sun * @date 2018年3月31日 下午7:58:24 * @param path */ public static void fileExists(String path) { try { File file = new File(path); if (!file.exists()) { file.mkdirs(); } } catch (Exception e) { e.printStackTrace(); } } /** * 分类 * @author sun * @date 2018年3月31日 下午8:12:21 */ public class Category{ private int id; private Date addTime; public Category(int i, Date addTime) { super(); this.id = i; this.addTime = addTime; } public int getId() { return id; } public void setId(int id) { this.id = id; } public Date getAddTime() { return addTime; } public void setAddTime(Date addTime) { this.addTime = addTime; } } /** * 文章 * @author sun * @date 2018年3月31日 下午7:31:42 */ public class Article{ private int id; private Date addTime; public Article(int i, Date addTime) { super(); this.id = i; this.addTime = addTime; } public int getId() { return id; } public void setId(int id) { this.id = id; } public Date getAddTime() { return addTime; } public void setAddTime(Date addTime) { this.addTime = addTime; } } }
SiteMapUtils.java
package com.sunjs.utils; import java.io.IOException; import java.io.Writer; import java.util.Iterator; import javax.xml.bind.DataBindingException; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.PropertyException; public class SiteMapUtils { protected final static String URLSET_START = "<?xml version='1.0' encoding='UTF-8'?>\n" + "<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + " xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\"\n" + " xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n"; protected final static String URLSET_END = "\n</urlset>"; protected final static String SITEMAPINDEX_START = "<?xml version='1.0' encoding='UTF-8'?>\n" // + "<?xml-stylesheet type=\"text/xsl\" href=\"http://lusongsong.com/zb_users/plugin/Nobird_Seo_Tools/Sitemap/sitemap.xsl\"?>" + "<sitemapindex xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + " xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd\"\n" + " xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n"; protected final static String SITEMAPINDEX_END = "\n</sitemapindex>"; public static void writeSitemapIndex(Writer writer, Iterator<? extends Sitemap> mappings) throws IOException { writeXml(writer, SITEMAPINDEX_START, mappings, SITEMAPINDEX_END); } public static long writeUrlset(Writer writer, Iterator<Url> urls) throws IOException { return writeXml(writer, URLSET_START, urls, URLSET_END); } private static long writeXml(Writer writer, String start, Iterator<?> it, String end) throws IOException { writer.write(start); long count = writeSubtree(writer, it); writer.write(end); return count; } public static long writeSubtree(Writer writer, Iterator<?> it) throws IOException { long size = 0; Marshaller m; try { JAXBContext jc = JAXBContext.newInstance(Sitemap.class, Url.class); m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FRAGMENT, true); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); } catch (PropertyException e) { throw new DataBindingException(e); } catch (JAXBException e) { throw new DataBindingException(e); } boolean first = true; while (it.hasNext()) { if (first) first = false; else writer.write("\n"); try { m.marshal(it.next(), writer); } catch (JAXBException e) { throw new IOException(e); } size++; } return size; } }
Sitemap.java
package com.sunjs.utils; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "sitemap") public class Sitemap { private String ioc; public Sitemap() { } public Sitemap(String ioc) { super(); this.ioc = ioc; } @XmlElement(name = "ioc") public String getIoc() { return ioc; } public void setIoc(String ioc) { this.ioc = ioc; } }
Url.java
package com.sunjs.utils; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "url") public class Url { private String ioc; public Url() { } public Url(String ioc) { super(); this.ioc = ioc; } @XmlElement(name = "ioc") public String getIoc() { return ioc; } public void setIoc(String ioc) { this.ioc = ioc; } }
博主发表文章之前没有检查文章源码是否完整,给大家造成的不便深感抱歉!
上边博主发出的源码已经经过博主自己的校验。按照步骤来是没有问题的。
版权属于: 技术客
原文地址: https://www.sunjs.com/article/detail/de0570bfda0441a7a9b4f189f38dd0ab.html
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。