mirror of https://github.com/halo-dev/halo
pref: RSS/Atom (#1342)
* 1.Add the lastBuildDate in RSS. 2.Add the updated in Atom. 3.Change the date format in RSS and Atom 4.Add the lastModified in the response header. * fix code stylepull/1353/head
parent
1a3254deba
commit
6ac9c7d231
|
@ -5,7 +5,12 @@ import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||||
import freemarker.template.Template;
|
import freemarker.template.Template;
|
||||||
import freemarker.template.TemplateException;
|
import freemarker.template.TemplateException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.OptionalLong;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.RegExUtils;
|
import org.apache.commons.lang3.RegExUtils;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
@ -47,6 +52,8 @@ public class ContentFeedController {
|
||||||
|
|
||||||
private static final String XML_MEDIA_TYPE = MediaType.APPLICATION_XML_VALUE + UTF_8_SUFFIX;
|
private static final String XML_MEDIA_TYPE = MediaType.APPLICATION_XML_VALUE + UTF_8_SUFFIX;
|
||||||
|
|
||||||
|
private static final String LAST_MODIFIED_HEADER = "Last-Modified";
|
||||||
|
|
||||||
private final PostService postService;
|
private final PostService postService;
|
||||||
|
|
||||||
private final CategoryService categoryService;
|
private final CategoryService categoryService;
|
||||||
|
@ -70,7 +77,7 @@ public class ContentFeedController {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get post rss
|
* Get post rss.
|
||||||
*
|
*
|
||||||
* @param model model
|
* @param model model
|
||||||
* @return rss xml content
|
* @return rss xml content
|
||||||
|
@ -79,8 +86,13 @@ public class ContentFeedController {
|
||||||
*/
|
*/
|
||||||
@GetMapping(value = {"feed", "feed.xml", "rss", "rss.xml"}, produces = XML_MEDIA_TYPE)
|
@GetMapping(value = {"feed", "feed.xml", "rss", "rss.xml"}, produces = XML_MEDIA_TYPE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String feed(Model model) throws IOException, TemplateException {
|
public String feed(Model model, HttpServletResponse response)
|
||||||
model.addAttribute("posts", buildPosts(buildPostPageable(optionService.getRssPageSize())));
|
throws IOException, TemplateException {
|
||||||
|
List<PostDetailVO> posts = buildPosts(buildPostPageable(optionService.getRssPageSize()));
|
||||||
|
model.addAttribute("posts", posts);
|
||||||
|
Timestamp lastModified = this.getLastModifiedTime(posts);
|
||||||
|
this.lastModified2ResponseHeader(response, lastModified);
|
||||||
|
model.addAttribute("lastModified", lastModified);
|
||||||
Template template = freeMarker.getConfiguration().getTemplate("common/web/rss.ftl");
|
Template template = freeMarker.getConfiguration().getTemplate("common/web/rss.ftl");
|
||||||
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
||||||
}
|
}
|
||||||
|
@ -97,13 +109,18 @@ public class ContentFeedController {
|
||||||
@GetMapping(value = {"feed/categories/{slug}",
|
@GetMapping(value = {"feed/categories/{slug}",
|
||||||
"feed/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE)
|
"feed/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String feed(Model model, @PathVariable(name = "slug") String slug)
|
public String feed(Model model, @PathVariable(name = "slug") String slug,
|
||||||
|
HttpServletResponse response)
|
||||||
throws IOException, TemplateException {
|
throws IOException, TemplateException {
|
||||||
Category category = categoryService.getBySlugOfNonNull(slug);
|
Category category = categoryService.getBySlugOfNonNull(slug);
|
||||||
CategoryDTO categoryDTO = categoryService.convertTo(category);
|
CategoryDTO categoryDTO = categoryService.convertTo(category);
|
||||||
|
List<PostDetailVO> posts =
|
||||||
|
buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO);
|
||||||
model.addAttribute("category", categoryDTO);
|
model.addAttribute("category", categoryDTO);
|
||||||
model.addAttribute("posts",
|
model.addAttribute("posts", posts);
|
||||||
buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO));
|
Timestamp lastModified = this.getLastModifiedTime(posts);
|
||||||
|
this.lastModified2ResponseHeader(response, lastModified);
|
||||||
|
model.addAttribute("lastModified", lastModified);
|
||||||
Template template = freeMarker.getConfiguration().getTemplate("common/web/rss.ftl");
|
Template template = freeMarker.getConfiguration().getTemplate("common/web/rss.ftl");
|
||||||
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
||||||
}
|
}
|
||||||
|
@ -118,8 +135,13 @@ public class ContentFeedController {
|
||||||
*/
|
*/
|
||||||
@GetMapping(value = {"atom", "atom.xml"}, produces = XML_MEDIA_TYPE)
|
@GetMapping(value = {"atom", "atom.xml"}, produces = XML_MEDIA_TYPE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String atom(Model model) throws IOException, TemplateException {
|
public String atom(Model model, HttpServletResponse response)
|
||||||
model.addAttribute("posts", buildPosts(buildPostPageable(optionService.getRssPageSize())));
|
throws IOException, TemplateException {
|
||||||
|
List<PostDetailVO> posts = buildPosts(buildPostPageable(optionService.getRssPageSize()));
|
||||||
|
model.addAttribute("posts", posts);
|
||||||
|
Timestamp lastModified = this.getLastModifiedTime(posts);
|
||||||
|
this.lastModified2ResponseHeader(response, lastModified);
|
||||||
|
model.addAttribute("lastModified", lastModified);
|
||||||
Template template = freeMarker.getConfiguration().getTemplate("common/web/atom.ftl");
|
Template template = freeMarker.getConfiguration().getTemplate("common/web/atom.ftl");
|
||||||
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
||||||
}
|
}
|
||||||
|
@ -136,13 +158,18 @@ public class ContentFeedController {
|
||||||
@GetMapping(value = {"atom/categories/{slug}",
|
@GetMapping(value = {"atom/categories/{slug}",
|
||||||
"atom/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE)
|
"atom/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String atom(Model model, @PathVariable(name = "slug") String slug)
|
public String atom(Model model, @PathVariable(name = "slug") String slug,
|
||||||
|
HttpServletResponse response)
|
||||||
throws IOException, TemplateException {
|
throws IOException, TemplateException {
|
||||||
Category category = categoryService.getBySlugOfNonNull(slug);
|
Category category = categoryService.getBySlugOfNonNull(slug);
|
||||||
CategoryDTO categoryDTO = categoryService.convertTo(category);
|
CategoryDTO categoryDTO = categoryService.convertTo(category);
|
||||||
|
List<PostDetailVO> posts =
|
||||||
|
buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO);
|
||||||
model.addAttribute("category", categoryDTO);
|
model.addAttribute("category", categoryDTO);
|
||||||
model.addAttribute("posts",
|
model.addAttribute("posts", posts);
|
||||||
buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO));
|
Timestamp lastModified = this.getLastModifiedTime(posts);
|
||||||
|
this.lastModified2ResponseHeader(response, lastModified);
|
||||||
|
model.addAttribute("lastModified", lastModified);
|
||||||
Template template = freeMarker.getConfiguration().getTemplate("common/web/atom.ftl");
|
Template template = freeMarker.getConfiguration().getTemplate("common/web/atom.ftl");
|
||||||
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
return FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
|
||||||
}
|
}
|
||||||
|
@ -248,4 +275,19 @@ public class ContentFeedController {
|
||||||
});
|
});
|
||||||
return posts.getContent();
|
return posts.getContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Timestamp getLastModifiedTime(List<PostDetailVO> posts) {
|
||||||
|
OptionalLong lastModifiedTimestamp =
|
||||||
|
posts.stream().mapToLong(post -> post.getEditTime().getTime()).max();
|
||||||
|
if (lastModifiedTimestamp.isEmpty()) {
|
||||||
|
return new Timestamp(System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
return new Timestamp(lastModifiedTimestamp.getAsLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lastModified2ResponseHeader(HttpServletResponse response, Timestamp time) {
|
||||||
|
SimpleDateFormat dateFormat =
|
||||||
|
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);
|
||||||
|
response.setHeader(LAST_MODIFIED_HEADER, dateFormat.format(time));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<subtitle type="text">${user.description!}</subtitle>
|
<subtitle type="text">${user.description!}</subtitle>
|
||||||
</#if>
|
</#if>
|
||||||
</#if>
|
</#if>
|
||||||
<updated>${.now?iso_local}</updated>
|
<updated>${lastModified?iso_local}</updated>
|
||||||
<#if category??>
|
<#if category??>
|
||||||
<id>${category.fullPath!}</id>
|
<id>${category.fullPath!}</id>
|
||||||
<#else>
|
<#else>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<#setting locale="en_US">
|
||||||
<rss version="2.0">
|
<rss version="2.0">
|
||||||
<channel>
|
<channel>
|
||||||
<#if category??>
|
<#if category??>
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
</#if>
|
</#if>
|
||||||
</#if>
|
</#if>
|
||||||
<generator>Halo ${version!}</generator>
|
<generator>Halo ${version!}</generator>
|
||||||
|
<lastBuildDate>${lastModified?string('EEE, dd MMM yyyy HH:mm:ss z')}</lastBuildDate>
|
||||||
<#if posts?? && posts?size gt 0>
|
<#if posts?? && posts?size gt 0>
|
||||||
<#list posts as post>
|
<#list posts as post>
|
||||||
<item>
|
<item>
|
||||||
|
@ -35,7 +37,7 @@
|
||||||
<![CDATA[${post.summary!}]]>
|
<![CDATA[${post.summary!}]]>
|
||||||
</#if>
|
</#if>
|
||||||
</description>
|
</description>
|
||||||
<pubDate>${post.createTime?iso_local}</pubDate>
|
<pubDate>${post.createTime?string('EEE, dd MMM yyyy HH:mm:ss z')}</pubDate>
|
||||||
</item>
|
</item>
|
||||||
</#list>
|
</#list>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
Loading…
Reference in New Issue