still under construction
This commit is contained in:
@@ -41,8 +41,8 @@ tasks.asciidoctor {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":sitemap"))
|
implementation(project(":sitemap"))
|
||||||
implementation(project(":linkback"))
|
implementation(project(":linkback"))
|
||||||
|
implementation(project(":web-app"))
|
||||||
|
|
||||||
implementation(project(":address-finder"))
|
|
||||||
implementation("com.vladsch.flexmark:flexmark-all:0.62.2")
|
implementation("com.vladsch.flexmark:flexmark-all:0.62.2")
|
||||||
|
|
||||||
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
|
||||||
|
|||||||
@@ -31,4 +31,5 @@ public class Application {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Project Asgard
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021. Elex. All Rights Reserved.
|
||||||
|
* https://www.elex-project.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.elex_project.asgard.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer;
|
||||||
|
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AsgardCacheCustomizer implements CacheManagerCustomizer<ConcurrentMapCacheManager> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void customize(ConcurrentMapCacheManager cacheManager) {
|
||||||
|
cacheManager.setCacheNames(Arrays
|
||||||
|
.asList("sitemap", "syndication/rss", "syndication/atom"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,8 @@ package com.elex_project.asgard.config;
|
|||||||
|
|
||||||
import com.elex_project.asgard.supplements.Markdown;
|
import com.elex_project.asgard.supplements.Markdown;
|
||||||
import com.elex_project.asgard.view.AsgardLocaleResolver;
|
import com.elex_project.asgard.view.AsgardLocaleResolver;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
|
import org.springframework.cache.support.SimpleCacheManager;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.servlet.LocaleResolver;
|
import org.springframework.web.servlet.LocaleResolver;
|
||||||
@@ -16,32 +18,14 @@ import org.springframework.web.servlet.LocaleResolver;
|
|||||||
@Configuration
|
@Configuration
|
||||||
public class Config {
|
public class Config {
|
||||||
|
|
||||||
/*@Bean
|
|
||||||
public RestTemplate restTemplate() {
|
|
||||||
return new RestTemplate();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*@Bean
|
|
||||||
public HttpTraceRepository httpTraceRepository() {
|
|
||||||
return new InMemoryHttpTraceRepository();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locale resolver, 디폴트 로캐일을 지정한다.
|
* Locale resolver, 디폴트 로캐일을 지정한다.
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public LocaleResolver localeResolver() {
|
public LocaleResolver localeResolver() {
|
||||||
/*SessionLocaleResolver localeResolver = new SessionLocaleResolver();
|
|
||||||
localeResolver.setDefaultLocale(Locale.ENGLISH);
|
|
||||||
localeResolver.setLocaleAttributeName("lc");
|
|
||||||
localeResolver.setTimeZoneAttributeName("tz");
|
|
||||||
return localeResolver;*/
|
|
||||||
|
|
||||||
return new AsgardLocaleResolver();
|
return new AsgardLocaleResolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Markdown parser
|
* Markdown parser
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* Project Asgard
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
|
||||||
* https://www.elex-project.com/
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.elex_project.asgard.controller;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
abstract class BaseController {
|
|
||||||
|
|
||||||
/*@NotNull
|
|
||||||
protected Map<String, Object> map() {
|
|
||||||
final HashMap<String, Object> map = new HashMap<>();
|
|
||||||
map.put("html_lang", lang());
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private String lang() {
|
|
||||||
return getHttpRequest()
|
|
||||||
.map(request -> request.getLocale().toLanguageTag())
|
|
||||||
.orElse("en");
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
protected URI getRequestURI() {
|
|
||||||
return getHttpRequest()
|
|
||||||
.map(request -> URI.create(request.getRequestURI()))
|
|
||||||
.orElse(URI.create("/"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<ServletRequestAttributes> getRequestAttributes() {
|
|
||||||
return Optional
|
|
||||||
.ofNullable((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Optional<HttpServletRequest> getHttpRequest() {
|
|
||||||
return getRequestAttributes()
|
|
||||||
.map(ServletRequestAttributes::getRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Optional<HttpServletResponse> getHttpResponse() {
|
|
||||||
return getRequestAttributes()
|
|
||||||
.map(ServletRequestAttributes::getResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
protected String[] getAttributeNames() {
|
|
||||||
return getRequestAttributes()
|
|
||||||
.map(attr -> attr.getAttributeNames(RequestAttributes.SCOPE_REQUEST))
|
|
||||||
.orElse(new String[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
protected String[] getSessionAttributeNames() {
|
|
||||||
return getRequestAttributes()
|
|
||||||
.map(attr -> attr.getAttributeNames(RequestAttributes.SCOPE_SESSION))
|
|
||||||
.orElse(new String[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
protected Optional<Object> getAttribute(@NotNull final String key) {
|
|
||||||
return getRequestAttributes()
|
|
||||||
.map(attr -> attr.getAttribute(key, RequestAttributes.SCOPE_REQUEST));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
protected Optional<Object> getSessionAttribute(@NotNull final String key) {
|
|
||||||
return getRequestAttributes()
|
|
||||||
.map(attr -> attr.getAttribute(key, RequestAttributes.SCOPE_SESSION));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setAttribute(@NotNull final String key, final Object value) {
|
|
||||||
getRequestAttributes()
|
|
||||||
.ifPresent(attr -> attr.setAttribute(key, value, RequestAttributes.SCOPE_REQUEST));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setSessionAttribute(@NotNull final String key, final Object value) {
|
|
||||||
getRequestAttributes()
|
|
||||||
.ifPresent(attr -> attr.setAttribute(key, value, RequestAttributes.SCOPE_SESSION));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removeAttribute(@NotNull final String key) {
|
|
||||||
getRequestAttributes()
|
|
||||||
.ifPresent(attr -> attr.removeAttribute(key, RequestAttributes.SCOPE_REQUEST));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removeSessionAttribute(@NotNull final String key) {
|
|
||||||
getRequestAttributes()
|
|
||||||
.ifPresent(attr -> attr.removeAttribute(key, RequestAttributes.SCOPE_SESSION));
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
@@ -7,27 +7,25 @@
|
|||||||
|
|
||||||
package com.elex_project.asgard.controller;
|
package com.elex_project.asgard.controller;
|
||||||
|
|
||||||
import com.elex_project.asgard.service.NoteService;
|
import com.elex_project.asgard.service.DocumentService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Controller
|
@Controller
|
||||||
public class NoteController extends BaseController {
|
public class DocumentController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private NoteService noteService;
|
private DocumentService documentService;
|
||||||
|
|
||||||
/*@GetMapping(path = "/*")
|
/*@GetMapping(path = "/*")
|
||||||
public ModelAndView reader(){
|
public ModelAndView reader(){
|
||||||
@@ -35,7 +33,7 @@ public class NoteController extends BaseController {
|
|||||||
return new ModelAndView("document", map());
|
return new ModelAndView("document", map());
|
||||||
}*/
|
}*/
|
||||||
@GetMapping(path = "/*")
|
@GetMapping(path = "/*")
|
||||||
public ModelAndView editor(@RequestParam boolean edit, ModelAndView model) {
|
public ModelAndView editor(@RequestParam(required = false) boolean edit, ModelAndView model) {
|
||||||
if (edit) {
|
if (edit) {
|
||||||
model.setViewName("edit");
|
model.setViewName("edit");
|
||||||
} else {
|
} else {
|
||||||
@@ -9,6 +9,7 @@ package com.elex_project.asgard.controller;
|
|||||||
|
|
||||||
import com.elex_project.asgard.service.SitemapService;
|
import com.elex_project.asgard.service.SitemapService;
|
||||||
import com.elex_project.asgard.service.SyndicationService;
|
import com.elex_project.asgard.service.SyndicationService;
|
||||||
|
import com.elex_project.asgard.syndication.SyndicationType;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -19,15 +20,13 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @link http://www.robotstxt.org/robotstxt.html
|
* @link http://www.robotstxt.org/robotstxt.html
|
||||||
* @link http://humanstxt.org/
|
* @link http://humanstxt.org/
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Controller
|
@Controller
|
||||||
public class HomeController extends BaseController {
|
public class HomeController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private SyndicationService syndicationService;
|
private SyndicationService syndicationService;
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -73,8 +72,7 @@ public class HomeController extends BaseController {
|
|||||||
@ResponseStatus(HttpStatus.OK)
|
@ResponseStatus(HttpStatus.OK)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String rss() {
|
public String rss() {
|
||||||
return syndicationService.getRssSyndication();
|
return syndicationService.getSyndication(SyndicationType.RSS_2);
|
||||||
//return "syndication/rss2";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,7 +84,7 @@ public class HomeController extends BaseController {
|
|||||||
@ResponseStatus(HttpStatus.OK)
|
@ResponseStatus(HttpStatus.OK)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String atom() {
|
public String atom() {
|
||||||
return syndicationService.getAtomSyndication();
|
return syndicationService.getSyndication(SyndicationType.ATOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(path = "/trackback/{id}",
|
@PostMapping(path = "/trackback/{id}",
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
/*
|
|
||||||
* Project Asgard
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
|
||||||
* https://www.elex-project.com/
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.elex_project.asgard.controller;
|
|
||||||
@@ -8,8 +8,7 @@
|
|||||||
package com.elex_project.asgard.model;
|
package com.elex_project.asgard.model;
|
||||||
|
|
||||||
import com.elex_project.asgard.supplements.StringArrayConverter;
|
import com.elex_project.asgard.supplements.StringArrayConverter;
|
||||||
import lombok.Data;
|
import lombok.*;
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.data.annotation.CreatedDate;
|
import org.springframework.data.annotation.CreatedDate;
|
||||||
import org.springframework.data.annotation.LastModifiedDate;
|
import org.springframework.data.annotation.LastModifiedDate;
|
||||||
@@ -18,11 +17,14 @@ import javax.persistence.*;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "notes")
|
@Table(name = "documents")
|
||||||
public class Note {
|
public class Document {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
private long id;
|
private long id;
|
||||||
@@ -48,7 +50,7 @@ public class Note {
|
|||||||
@LastModifiedDate
|
@LastModifiedDate
|
||||||
private LocalDateTime modifiedOn;
|
private LocalDateTime modifiedOn;
|
||||||
|
|
||||||
public static Note of(){
|
public static Document of() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* Project Asgard
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
|
||||||
* https://www.elex-project.com/
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.elex_project.asgard.model;
|
|
||||||
|
|
||||||
import com.elex_project.asgard.supplements.InetAddressConverter;
|
|
||||||
import com.elex_project.asgard.supplements.StringArrayConverter;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
import static com.elex_project.asgard.supplements.RequestLogInterceptor.REQUEST_TIME;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Entity
|
|
||||||
@Table(name = "http_trace")
|
|
||||||
public class HttpTraceModel {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
|
||||||
private long id;
|
|
||||||
@Column
|
|
||||||
private LocalDateTime requestTime;
|
|
||||||
@Column
|
|
||||||
private Long elapsed;
|
|
||||||
@Column
|
|
||||||
private String requestUrl;
|
|
||||||
@Column
|
|
||||||
private String requestMethod;
|
|
||||||
@Column
|
|
||||||
private String userAgent;
|
|
||||||
@Column
|
|
||||||
private String referer;
|
|
||||||
@Column
|
|
||||||
@Convert(converter = StringArrayConverter.class)
|
|
||||||
private String[] acceptLang;
|
|
||||||
@Column
|
|
||||||
@Convert(converter = InetAddressConverter.class)
|
|
||||||
private InetAddress ipAddress;
|
|
||||||
|
|
||||||
public static HttpTraceModel of(final HttpServletRequest request, final HttpServletResponse response) {
|
|
||||||
final HttpTraceModel model = new HttpTraceModel();
|
|
||||||
model.requestUrl = request.getRequestURI();
|
|
||||||
model.requestMethod = request.getMethod();
|
|
||||||
model.userAgent = request.getHeader("User-Agent");
|
|
||||||
model.referer = request.getHeader("Referer");
|
|
||||||
|
|
||||||
final String acceptLang = request.getHeader("Accept-Language");
|
|
||||||
if (null != acceptLang) {
|
|
||||||
model.acceptLang = acceptLang.replaceAll(";q=[0-9.]*", "").split(",");
|
|
||||||
} else {
|
|
||||||
model.acceptLang = new String[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
model.requestTime = (LocalDateTime) request.getAttribute(REQUEST_TIME);
|
|
||||||
if (null != model.requestTime) {
|
|
||||||
model.elapsed = Duration.between(model.requestTime, LocalDateTime.now()).toMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
String ip = request.getHeader("X-Forwarded-For");
|
|
||||||
if (null == ip) ip = request.getHeader("X-Real-Ip");
|
|
||||||
if (null == ip) ip = request.getRemoteAddr();
|
|
||||||
try {
|
|
||||||
model.ipAddress = InetAddress.getByName(ip);
|
|
||||||
} catch (UnknownHostException ignore) {
|
|
||||||
}
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
/*
|
|
||||||
* Project Asgard
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
|
||||||
* https://www.elex-project.com/
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.elex_project.asgard.model;
|
|
||||||
@@ -12,5 +12,5 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class NoteService {
|
public class DocumentService {
|
||||||
}
|
}
|
||||||
@@ -13,8 +13,11 @@ import com.elex_project.asgard.sitemap.Sitemap;
|
|||||||
import com.elex_project.asgard.sitemap.SitemapItem;
|
import com.elex_project.asgard.sitemap.SitemapItem;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.cache.annotation.CacheConfig;
|
import org.springframework.cache.annotation.CacheConfig;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -25,6 +28,11 @@ public class SitemapService extends BaseSitemapService {
|
|||||||
@Override
|
@Override
|
||||||
protected Sitemap sitemap() {
|
protected Sitemap sitemap() {
|
||||||
final Sitemap sitemap = new Sitemap();
|
final Sitemap sitemap = new Sitemap();
|
||||||
|
sitemap.addItem(SitemapItem.builder()
|
||||||
|
.loc("https://www.elex-project.com/address-finder/")
|
||||||
|
.lastMod(LocalDate.of(2021,8,19).atStartOfDay())
|
||||||
|
.changeFreq(Frequency.NEVER)
|
||||||
|
.build());
|
||||||
sitemap.addItem(SitemapItem.builder()
|
sitemap.addItem(SitemapItem.builder()
|
||||||
.loc("https://aaa.com/1")
|
.loc("https://aaa.com/1")
|
||||||
.lastMod(LocalDateTime.now())
|
.lastMod(LocalDateTime.now())
|
||||||
@@ -37,7 +45,13 @@ public class SitemapService extends BaseSitemapService {
|
|||||||
return sitemap;
|
return sitemap;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@CacheEvict(allEntries = true)
|
@Cacheable
|
||||||
|
@Override
|
||||||
|
public String getSitemap() {
|
||||||
|
return super.getSitemap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@CacheEvict(allEntries = true)
|
||||||
public void clearCaches() {
|
public void clearCaches() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ package com.elex_project.asgard.service;
|
|||||||
import com.elex_project.asgard.syndication.BaseSyndicationService;
|
import com.elex_project.asgard.syndication.BaseSyndicationService;
|
||||||
import com.elex_project.asgard.syndication.Syndication;
|
import com.elex_project.asgard.syndication.Syndication;
|
||||||
import com.elex_project.asgard.syndication.SyndicationItem;
|
import com.elex_project.asgard.syndication.SyndicationItem;
|
||||||
|
import com.elex_project.asgard.syndication.SyndicationType;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.cache.annotation.CacheConfig;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -19,12 +23,16 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@CacheConfig(cacheNames = "syndication")
|
||||||
@Service
|
@Service
|
||||||
//@CacheConfig(cacheNames = "templates/syndication")
|
|
||||||
public class SyndicationService extends BaseSyndicationService {
|
public class SyndicationService extends BaseSyndicationService {
|
||||||
|
@Cacheable
|
||||||
|
@Override
|
||||||
|
public String getSyndication(SyndicationType type) {
|
||||||
|
return super.getSyndication(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@CacheEvict(allEntries = true)
|
||||||
//@CacheEvict(allEntries = true)
|
|
||||||
public void clearCaches() {
|
public void clearCaches() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -60,7 +68,7 @@ public class SyndicationService extends BaseSyndicationService {
|
|||||||
.url("https://something.com/2")
|
.url("https://something.com/2")
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
final List<SyndicationItem> items = new ArrayList<>();// todo
|
final List<SyndicationItem> items = new ArrayList<>();// todo read from db
|
||||||
items.forEach(syndication::addItem);
|
items.forEach(syndication::addItem);
|
||||||
return syndication;
|
return syndication;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
/*
|
|
||||||
* Project Asgard
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
|
||||||
* https://www.elex-project.com/
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.elex_project.asgard.service;
|
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
package com.elex_project.asgard.supplements;
|
package com.elex_project.asgard.supplements;
|
||||||
|
|
||||||
import com.elex_project.asgard.model.HttpTraceModel;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
@@ -15,11 +14,12 @@ import org.springframework.web.servlet.ModelAndView;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class RequestLogInterceptor implements HandlerInterceptor {
|
public class RequestLogInterceptor implements HandlerInterceptor {
|
||||||
public static final String REQUEST_TIME = "elex.request.time";
|
private static final String REQUEST_TIME = "elex.request.time";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler)
|
public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler)
|
||||||
@@ -37,8 +37,8 @@ public class RequestLogInterceptor implements HandlerInterceptor {
|
|||||||
@Override
|
@Override
|
||||||
public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex)
|
public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final HttpTraceModel traceModel = HttpTraceModel.of(request, response);
|
Duration elapsed = Duration
|
||||||
log.info("Http Trace: {}", traceModel);
|
.between((LocalDateTime) request.getAttribute(REQUEST_TIME), LocalDateTime.now());
|
||||||
|
log.info("Http Trace: {}", elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
/*
|
|
||||||
* Project Asgard
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
|
||||||
* https://www.elex-project.com/
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.elex_project.asgard.supplements;
|
|
||||||
@@ -14,10 +14,13 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
public class ViewModelInterceptor implements HandlerInterceptor {
|
public class ViewModelInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||||
|
ModelAndView modelAndView) throws Exception {
|
||||||
if (null != modelAndView) {
|
if (null != modelAndView) {
|
||||||
modelAndView.addObject("title", "Title~!!!");
|
modelAndView.addObject("title", "Title~!!!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
/*
|
|
||||||
* Project Asgard
|
|
||||||
*
|
|
||||||
* Copyright (c) 2021. Elex. All Rights Reserved.
|
|
||||||
* https://www.elex-project.com/
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.elex_project.asgard.view;
|
|
||||||
@@ -8,5 +8,5 @@ Name:
|
|||||||
|
|
||||||
/* SITE */
|
/* SITE */
|
||||||
Front-end: HTML5, CSS3, Javascript, Material Design Components, Node-js(yarn, webpack, babel), Scss
|
Front-end: HTML5, CSS3, Javascript, Material Design Components, Node-js(yarn, webpack, babel), Scss
|
||||||
Back-end: Spring-boot, Mustache, Hibernate
|
Back-end: Spring-boot, Mustache, Thymeleaf, Hibernate
|
||||||
Server: Docker, MariaDB, Tomcat, Nginx, Linux
|
Server: Docker, MariaDB, Tomcat, Nginx, Linux
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{html_lang}}">
|
<html xmlns:th="http://www.thymeleaf.org" th:lang="${#locale.language}">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
{{> fragments/meta}}
|
<th:block th:replace="~{fragments :: meta}"></th:block>
|
||||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet" />
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
||||||
<link rel="author" href="/humans.txt" />
|
<link rel="author" href="/humans.txt" />
|
||||||
<link rel="stylesheet" href="/bundle.css" />
|
<link rel="stylesheet" href="/bundle.css" />
|
||||||
<title>{{title}}</title>
|
<title th:text="${title}">{{title}}</title>
|
||||||
<script src="/bundle.js"></script>
|
<script src="/bundle.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
</main>
|
</main>
|
||||||
<footer class="mdc-layout-grid">
|
<footer class="mdc-layout-grid" th:include="~{fragments :: footer}">
|
||||||
<p>Copyright © 2021</p>
|
<p>Copyright © 2021</p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
<head>
|
<head>
|
||||||
<title>{{status}} - {{message}}</title>
|
<title th:text="|${status} - ${message}|">{{status}} - {{message}}</title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||||
@@ -16,13 +16,13 @@
|
|||||||
<body>
|
<body>
|
||||||
<p class="inline">
|
<p class="inline">
|
||||||
<span class="green">www-user@elex-project.com</span><span>:</span>
|
<span class="green">www-user@elex-project.com</span><span>:</span>
|
||||||
<span class="blue">{{path}}</span><span>$ </span><span>http get {{path}}</span>
|
<span class="blue" th:text="${path}">{{path}}</span><span>$ </span><span th:text="|http get ${path}|">http get {{path}}</span>
|
||||||
</p>
|
</p>
|
||||||
<p>{{status}} - {{message}}</p>
|
<p th:text="|${status} - ${message}|">{{status}} - {{message}}</p>
|
||||||
<p>Trace:<br /> {{trace}}</p>
|
<p th:utext="|Trace:<br/> ${trace}|">Trace:<br /> {{trace}}</p>
|
||||||
<p class="inline">
|
<p class="inline">
|
||||||
<span class="green">www-user@elex-project.com</span><span>:</span>
|
<span class="green">www-user@elex-project.com</span><span>:</span>
|
||||||
<span class="blue">{{path}}</span><span>$ </span><input type="text"/>
|
<span class="blue" th:text="${path}">{{path}}</span><span>$ </span><input type="text"/>
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
<head>
|
<head>
|
||||||
<title>{{status}} - {{message}}</title>
|
<title th:text="|${status} - ${message}|">{{status}} - {{message}}</title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p>Oops-404!</p>
|
<p>Oops-404!</p>
|
||||||
<h1>{{status}}</h1>
|
<h1 th:text="${status}">{{status}}</h1>
|
||||||
<p>{{message}}</p>
|
<p th:text="${message}">{{message}}</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
52
app/src/main/resources/templates/fragments.html
Normal file
52
app/src/main/resources/templates/fragments.html
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title th:text="${title}">{{title}}</title>
|
||||||
|
<th:block th:fragment="meta">
|
||||||
|
<meta property="og:title" content="{{title}}" />
|
||||||
|
<meta property="og:url" content="{{url}}" />
|
||||||
|
<meta name="description" property="og:description" content="{{description}}" />
|
||||||
|
<meta property="og:locale" content="{{html_lang}}" />
|
||||||
|
<meta property="og:site_name" content="Elex Project" />
|
||||||
|
<meta property="og:image" content="{{image}}" />
|
||||||
|
<meta property="og:type" content="article" />
|
||||||
|
<meta property="og:article:section" content="{{section}}" />
|
||||||
|
<meta name="keyword" property="og:article:tag" content="{{tag}}" />
|
||||||
|
<meta property="og:article:published_time" content="{{published_time}}" />
|
||||||
|
<meta property="og:article:modified_time" content="{{modified_time}}" />
|
||||||
|
<meta name="author" property="og:article:author" content="{{author}}"/>
|
||||||
|
</th:block>
|
||||||
|
<link rel="stylesheet" href="/persona.min.css" />
|
||||||
|
<script>
|
||||||
|
let toggle = function () {
|
||||||
|
const elem = document.querySelector(".layout");
|
||||||
|
elem.classList.toggle("closed");
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="layout">
|
||||||
|
<div class="sidebar">
|
||||||
|
<nav class="nav">
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<header class="header">
|
||||||
|
<span class="icon-button material-icons" onclick="toggle();">menu</span>
|
||||||
|
<h1 class="grow" th:text="${title}">{{title}}</h1>
|
||||||
|
</header>
|
||||||
|
<div class="main">
|
||||||
|
<main>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
<footer th:fragment="footer">
|
||||||
|
Copyright © 2021. Elex. All Rights Reserved.
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<footer th:fragment="footer">
|
|
||||||
Copyright ©
|
|
||||||
</footer>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<head th:fragment="meta">
|
|
||||||
<meta property="og:title" content="{{title}}" />
|
|
||||||
<meta property="og:url" content="{{url}}" />
|
|
||||||
<meta name="description" property="og:description" content="{{description}}" />
|
|
||||||
<meta property="og:locale" content="{{html_lang}}" />
|
|
||||||
<meta property="og:site_name" content="Elex Project" />
|
|
||||||
<meta property="og:image" content="{{image}}" />
|
|
||||||
<meta property="og:type" content="article" />
|
|
||||||
<meta property="og:article:section" content="{{section}}" />
|
|
||||||
<meta name="keyword" property="og:article:tag" content="{{tag}}" />
|
|
||||||
<meta property="og:article:published_time" content="{{published_time}}" />
|
|
||||||
<meta property="og:article:modified_time" content="{{modified_time}}" />
|
|
||||||
<meta name="author" property="og:article:author" content="{{author}}"/>
|
|
||||||
</head>
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title th:text="${title}">{{title}}</title>
|
<title th:text="${title}">{{title}}</title>
|
||||||
<th:block th:include="~{fragments/meta :: meta}"></th:block>
|
<th:block th:replace="~{fragments :: meta}"></th:block>
|
||||||
<link rel="stylesheet" href="/persona.min.css" />
|
<link rel="stylesheet" href="/persona.min.css" />
|
||||||
<script>
|
<script>
|
||||||
let toggle = function () {
|
let toggle = function () {
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
<p>...</p>
|
<p>...</p>
|
||||||
</main>
|
</main>
|
||||||
<footer th:replace="~{fragments/footer :: footer}">
|
<footer th:replace="~{fragments :: footer}">
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,4 +11,4 @@ include("app")
|
|||||||
include("sitemap")
|
include("sitemap")
|
||||||
include("linkback")
|
include("linkback")
|
||||||
|
|
||||||
include("address-finder")
|
include("web-app")
|
||||||
|
|||||||
@@ -20,17 +20,13 @@ import java.io.StringWriter;
|
|||||||
* @link https://www.sitemaps.org/ko/protocol.html
|
* @link https://www.sitemaps.org/ko/protocol.html
|
||||||
*/
|
*/
|
||||||
public abstract class BaseSitemapService {
|
public abstract class BaseSitemapService {
|
||||||
private final Mustache template;
|
|
||||||
|
|
||||||
protected BaseSitemapService() {
|
|
||||||
MustacheFactory factory = new DefaultMustacheFactory();
|
|
||||||
template = factory.compile("sitemap/sitemap.mustache");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Sitemap sitemap();
|
protected abstract Sitemap sitemap();
|
||||||
|
|
||||||
public String getSitemap() {
|
public String getSitemap() {
|
||||||
StringWriter writer = new StringWriter();
|
final MustacheFactory factory = new DefaultMustacheFactory();
|
||||||
|
final Mustache template = factory.compile("sitemap/sitemap.mustache");
|
||||||
|
final StringWriter writer = new StringWriter();
|
||||||
template.execute(writer, sitemap());
|
template.execute(writer, sitemap());
|
||||||
return writer.toString()
|
return writer.toString()
|
||||||
.replaceAll("[\n\t]", "")
|
.replaceAll("[\n\t]", "")
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ import java.time.format.DateTimeFormatter;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Builder
|
@Builder
|
||||||
public class SitemapItem {
|
public class SitemapItem {
|
||||||
private static final ZoneId defaultZone = ZoneOffset.ofHours(0).normalized();
|
|
||||||
|
|
||||||
private String loc;
|
private String loc;
|
||||||
private LocalDateTime lastMod;
|
private LocalDateTime lastMod;
|
||||||
private Frequency changeFreq;
|
private Frequency changeFreq;
|
||||||
@@ -36,7 +34,5 @@ public class SitemapItem {
|
|||||||
|
|
||||||
public String getLastModIso(){
|
public String getLastModIso(){
|
||||||
return Formatter.formatIso(lastMod);
|
return Formatter.formatIso(lastMod);
|
||||||
/*return lastMod.atZone(ZoneId.systemDefault())
|
|
||||||
.format(DateTimeFormatter.ISO_ZONED_DATE_TIME.withZone(defaultZone));*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,31 +13,29 @@ import com.github.mustachejava.MustacheFactory;
|
|||||||
|
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
|
||||||
//@Service
|
|
||||||
public abstract class BaseSyndicationService {
|
public abstract class BaseSyndicationService {
|
||||||
private final Mustache templateRss, templateAtom;
|
|
||||||
|
|
||||||
public BaseSyndicationService(){
|
|
||||||
MustacheFactory factory = new DefaultMustacheFactory();
|
|
||||||
templateRss = factory.compile("syndication/rss2.mustache");
|
|
||||||
templateAtom = factory.compile("syndication/atom.mustache");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Syndication syndication();
|
protected abstract Syndication syndication();
|
||||||
|
|
||||||
public String getRssSyndication() {
|
public String getSyndication(final SyndicationType type) {
|
||||||
StringWriter writer = new StringWriter();
|
final MustacheFactory factory = new DefaultMustacheFactory();
|
||||||
templateRss.execute(writer, syndication());
|
final Mustache template;
|
||||||
|
final StringWriter writer = new StringWriter();
|
||||||
|
switch (type) {
|
||||||
|
case ATOM:
|
||||||
|
template = factory.compile("syndication/rss2.mustache");
|
||||||
|
break;
|
||||||
|
case RSS_2:
|
||||||
|
template = factory.compile("syndication/atom.mustache");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Unknown Syndication Type.");
|
||||||
|
}
|
||||||
|
template.execute(writer, syndication());
|
||||||
|
|
||||||
return writer.toString()
|
return writer.toString()
|
||||||
.replaceAll("[\n\t]", "")
|
.replaceAll("[\n\t]", "")
|
||||||
.replaceAll("\\s{2,}", " ");
|
.replaceAll("\\s{2,}", " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAtomSyndication() {
|
|
||||||
StringWriter writer = new StringWriter();
|
|
||||||
templateAtom.execute(writer, syndication());
|
|
||||||
return writer.toString()
|
|
||||||
.replaceAll("[\n\t]","")
|
|
||||||
.replaceAll("\\s{2,}", " ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,22 +7,26 @@
|
|||||||
|
|
||||||
package com.elex_project.asgard.syndication;
|
package com.elex_project.asgard.syndication;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
public interface Formatter {
|
public abstract class Formatter {
|
||||||
|
|
||||||
static final ZoneId defaultZone = ZoneOffset.ofHours(0).normalized();
|
private static final ZoneId defaultZone = ZoneOffset.ofHours(0).normalized();
|
||||||
|
|
||||||
static String formatIso(final LocalDateTime time){
|
private Formatter(){}
|
||||||
|
|
||||||
|
public static @NotNull String formatIso(final @NotNull LocalDateTime time){
|
||||||
return time.atZone(ZoneId.systemDefault())
|
return time.atZone(ZoneId.systemDefault())
|
||||||
.format(DateTimeFormatter.ISO_ZONED_DATE_TIME.withZone(defaultZone));
|
.format(DateTimeFormatter.ISO_ZONED_DATE_TIME.withZone(defaultZone));
|
||||||
}
|
}
|
||||||
|
|
||||||
static String formatRfc(final LocalDateTime time){
|
public static @NotNull String formatRfc(final @NotNull LocalDateTime time){
|
||||||
return time.atZone(ZoneOffset.systemDefault())
|
return time.atZone(ZoneOffset.systemDefault())
|
||||||
.format(DateTimeFormatter.RFC_1123_DATE_TIME.withZone(defaultZone));
|
.format(DateTimeFormatter.RFC_1123_DATE_TIME.withZone(defaultZone));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,8 @@
|
|||||||
* https://www.elex-project.com/
|
* https://www.elex-project.com/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.elex_project.asgard.config;
|
package com.elex_project.asgard.syndication;
|
||||||
|
|
||||||
|
public enum SyndicationType {
|
||||||
|
RSS_2, ATOM;
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("/address-finder")
|
@RequestMapping("/address-finder")
|
||||||
public class AppController {
|
public class AppController {
|
||||||
@GetMapping("/**")
|
@GetMapping("/")
|
||||||
public String index(){
|
public String index(){
|
||||||
return "address-finder";
|
return "address-finder";
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user