still under construction

This commit is contained in:
2021-08-20 23:40:43 +09:00
parent 2ee272598a
commit 14af7dfe4e
37 changed files with 185 additions and 349 deletions

View File

@@ -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")

View File

@@ -31,4 +31,5 @@ public class Application {
} }
} }
} }

View File

@@ -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"));
}
}

View File

@@ -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
* *

View File

@@ -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));
}*/
}

View File

@@ -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 {

View File

@@ -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}",

View File

@@ -1,8 +0,0 @@
/*
* Project Asgard
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package com.elex_project.asgard.controller;

View File

@@ -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;
} }
} }

View File

@@ -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;
}
}

View File

@@ -1,8 +0,0 @@
/*
* Project Asgard
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package com.elex_project.asgard.model;

View File

@@ -12,5 +12,5 @@ import org.springframework.stereotype.Service;
@Slf4j @Slf4j
@Service @Service
public class NoteService { public class DocumentService {
} }

View File

@@ -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() {
} }

View File

@@ -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;
} }

View File

@@ -1,8 +0,0 @@
/*
* Project Asgard
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package com.elex_project.asgard.service;

View File

@@ -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);
} }
} }

View File

@@ -1,8 +0,0 @@
/*
* Project Asgard
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package com.elex_project.asgard.supplements;

View File

@@ -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~!!!");
} }
} }
} }

View File

@@ -1,8 +0,0 @@
/*
* Project Asgard
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package com.elex_project.asgard.view;

View File

@@ -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

View File

@@ -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 &copy; 2021</p> <p>Copyright &copy; 2021</p>
</footer> </footer>
</div> </div>

View File

@@ -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>$&nbsp;</span><span>http get {{path}}</span> <span class="blue" th:text="${path}">{{path}}</span><span>$&nbsp;</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>$&nbsp;</span><input type="text"/> <span class="blue" th:text="${path}">{{path}}</span><span>$&nbsp;</span><input type="text"/>
</p> </p>
</body> </body>
</html> </html>

View File

@@ -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>

View 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 &copy; 2021. Elex. All Rights Reserved.
</footer>
</div>
</div>
</body>
</html>

View File

@@ -1,3 +0,0 @@
<footer th:fragment="footer">
Copyright &copy;
</footer>

View File

@@ -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>

View File

@@ -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>

View File

@@ -11,4 +11,4 @@ include("app")
include("sitemap") include("sitemap")
include("linkback") include("linkback")
include("address-finder") include("web-app")

View File

@@ -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]", "")

View File

@@ -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));*/
} }
} }

View File

@@ -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,}", " ");
}
} }

View File

@@ -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));
} }

View File

@@ -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;
}

View File

@@ -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";
} }