feat(SEO): 自动生成和更新网站地图 sitemap.xml
This commit is contained in:
1 parent
f10ffa664e
commit
cfc5d894ab
3 files changed
+135
-1
No files matched your search
@@ -68,4 +68,10 @@ public interface CacheKey {
|
||||
* AI生成图片
|
||||
* */
|
||||
String AI_GEN_PIC = "aiGenPic";
|
||||
|
||||
/**
|
||||
* 网站根目录地址
|
||||
* */
|
||||
String WEB_SITE_ROOT_URL = "websiteRootUrl";
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package com.java2nb.novel.controller.page;
|
||||
|
||||
import com.java2nb.novel.controller.BaseController;
|
||||
import com.java2nb.novel.core.bean.UserDetails;
|
||||
import com.java2nb.novel.core.cache.CacheKey;
|
||||
import com.java2nb.novel.core.cache.CacheService;
|
||||
import com.java2nb.novel.core.utils.ThreadLocalUtil;
|
||||
import com.java2nb.novel.entity.*;
|
||||
import com.java2nb.novel.service.*;
|
||||
@@ -43,6 +45,8 @@ public class PageController extends BaseController {
|
||||
|
||||
private final Map<String, BookContentService> bookContentServiceMap;
|
||||
|
||||
private final CacheService cacheService;
|
||||
|
||||
@RequestMapping("{url}.html")
|
||||
public String module(@PathVariable("url") String url) {
|
||||
return url;
|
||||
@@ -80,7 +84,10 @@ public class PageController extends BaseController {
|
||||
*/
|
||||
@SneakyThrows
|
||||
@RequestMapping(path = {"/", "/index", "/index.html"})
|
||||
public String index(Model model) {
|
||||
public String index(HttpServletRequest request, Model model) {
|
||||
// 将网站根目录地址保存起来
|
||||
String rootUrl = getRootUrl(request);
|
||||
cacheService.set(CacheKey.WEB_SITE_ROOT_URL, rootUrl);
|
||||
//加载小说首页小说基本信息线程
|
||||
CompletableFuture<Map<String, List<BookSettingVO>>> bookCompletableFuture = CompletableFuture.supplyAsync(
|
||||
bookService::listBookSettingVO, threadPoolExecutor);
|
||||
@@ -359,5 +366,21 @@ public class PageController extends BaseController {
|
||||
return "author/register";
|
||||
}
|
||||
|
||||
private String getRootUrl(HttpServletRequest request) {
|
||||
String scheme = request.getScheme(); // http 或 https
|
||||
String serverName = request.getServerName(); // ibiqugu.net
|
||||
int serverPort = request.getServerPort(); // 80 / 443 / 8080
|
||||
|
||||
StringBuilder root = new StringBuilder();
|
||||
root.append(scheme).append("://").append(serverName);
|
||||
|
||||
if (("http".equals(scheme) && serverPort != 80)
|
||||
|
||||
|| ("https".equals(scheme) && serverPort != 443)) {
|
||||
root.append(":").append(serverPort);
|
||||
}
|
||||
return root.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.java2nb.novel.core.schedule;
|
||||
|
||||
|
||||
import com.java2nb.novel.core.cache.CacheKey;
|
||||
import com.java2nb.novel.core.cache.CacheService;
|
||||
import com.java2nb.novel.core.utils.DateUtil;
|
||||
import com.java2nb.novel.entity.Book;
|
||||
import com.java2nb.novel.mapper.BookMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.mybatis.dynamic.sql.render.RenderingStrategies;
|
||||
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.*;
|
||||
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.book;
|
||||
import static com.java2nb.novel.mapper.BookDynamicSqlSupport.lastIndexUpdateTime;
|
||||
import static org.mybatis.dynamic.sql.SqlBuilder.isGreaterThan;
|
||||
import static org.mybatis.dynamic.sql.SqlBuilder.isLessThan;
|
||||
import static org.mybatis.dynamic.sql.select.SelectDSL.select;
|
||||
|
||||
/**
|
||||
* 生产环境自动生成网站地图
|
||||
*
|
||||
* @author cd
|
||||
*/
|
||||
@Profile("prod")
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class SitemapGenSchedule {
|
||||
|
||||
@Value("${spring.web.resources.static-locations}")
|
||||
private String webRootDir;
|
||||
|
||||
private static final String WEB_ROOT_DIR_PREFIX = "file:";
|
||||
|
||||
private final BookMapper bookMapper;
|
||||
|
||||
private final CacheService cacheService;
|
||||
|
||||
/**
|
||||
* 每天自动更新 sitemap.xml 文件
|
||||
*/
|
||||
@Scheduled(cron = "0 0 2 * * ?")
|
||||
public void statistics() {
|
||||
|
||||
if (webRootDir.startsWith(WEB_ROOT_DIR_PREFIX)) {
|
||||
webRootDir = webRootDir.substring(WEB_ROOT_DIR_PREFIX.length());
|
||||
String webRootUrl = cacheService.get(CacheKey.WEB_SITE_ROOT_URL);
|
||||
if (StringUtils.isBlank(webRootUrl)) {
|
||||
return;
|
||||
}
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(webRootDir + "sitemap.xml"))) {
|
||||
// 写入文件头
|
||||
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
writer.write("<urlset>\n");
|
||||
|
||||
Date maxCreateTime = new Date();
|
||||
List<Book> books;
|
||||
do {
|
||||
SelectStatementProvider selectStatement = select(id, createTime, lastIndexUpdateTime)
|
||||
.from(book)
|
||||
.where(createTime, isLessThan(maxCreateTime))
|
||||
.and(wordCount, isGreaterThan(0))
|
||||
.orderBy(createTime.descending())
|
||||
.limit(100)
|
||||
.build()
|
||||
.render(RenderingStrategies.MYBATIS3);
|
||||
books = bookMapper.selectMany(selectStatement);
|
||||
for (Book book : books) {
|
||||
maxCreateTime = book.getCreateTime();
|
||||
if (book.getLastIndexUpdateTime() == null) {
|
||||
continue;
|
||||
}
|
||||
writer.write("<url>\n");
|
||||
writer.write(" <loc>" + webRootUrl + "/book/" + (book.getId()) + ".html" + "</loc>\n");
|
||||
writer.write(
|
||||
" <lastmod>" + DateUtil.formatDate(book.getLastIndexUpdateTime(), DateUtil.DATE_PATTERN)
|
||||
+ "</lastmod>\n");
|
||||
writer.write(" <changefreq>daily</changefreq>\n");
|
||||
writer.write(" <priority>0.8</priority>\n");
|
||||
writer.write("</url>\n");
|
||||
}
|
||||
} while (!books.isEmpty());
|
||||
|
||||
// 写入文件尾
|
||||
writer.write("</urlset>\n");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user