적용 방법은 아래와 같다.
① 마크다운 문서 작성
② Spring 환경에서 HTML 문서로 동적 변환하여 화면 출력
마크다운 문서를 HTML 로 변환하는 것은 여러 가지 방법을 고려하였으나 filter 를 사용하는 것을 선택했다. 마크다운 파싱과 HTML랜더링은 이슈관리 툴 Jira 로 널리 알려진 Atlassian 의 오픈소스 https://github.com/atlassian/commonmark-java 를 사용하였다.
1. 라이브러리 추가
Maven빌드 툴을 사용하고 있기 때문에 아래와 같이 라이브러리를 pom.xml 파일에 추가한다.
org.springframework.restdocs spring-restdocs-mockmvc 2.0.0.RELEASE
2. 필터 만들기
필터는 "org.springframework.web.filter.OncePerRequestFilter" 클래스를 상속받아 구현하였으며 어노테이션을 통하여 배포되도록 구성하였다. import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.apache.tika.io.IOUtils;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.context.support.ServletContextResourceLoader;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.UrlPathHelper;
import architecture.community.web.util.ServletUtils;
@WebFilter(filterName = "makedownFilter", urlPatterns = "*.md")
public class MakedownViewFilter extends OncePerRequestFilter {
private Logger log = LoggerFactory.getLogger(getClass());
private UrlPathHelper urlPathHelper = new UrlPathHelper();
private ResourceLoader resourceLoader ;
@Override
protected void initFilterBean() throws ServletException {
super.initFilterBean();
resourceLoader = new ServletContextResourceLoader(this.getServletContext());
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String url = urlPathHelper.getLookupPathForRequest(request);
Resource resouce = getResourceForUrl(url);
log.debug("URL : {} - {}", url, resouce.exists() );
// 리소스가 존재하는 경우만 처리하며 이외의 경우는 다음 필터가 적용 되도록 한다.
if( resouce.exists() ) {
Parser parser = Parser.builder().build();
Node document = parser.parse(
FileUtils.readFileToString(resouce.getFile(), ServletUtils.DEFAULT_HTML_ENCODING)
);
HtmlRenderer renderer = HtmlRenderer.builder().build();
ServletUtils.setContentType(ServletUtils.DEFAULT_HTML_CONTENT_TYPE, response);
IOUtils.write(
renderer.render(document),
response.getWriter()
);
response.flushBuffer();
return;
}
super.doFilter(request, response, filterChain);
}
/**
* url 에 해당한는 리소스를 리턴한다.
* @param url
* @return
*/
protected Resource getResourceForUrl(String url) {
return resourceLoader.getResource(url);
}
}
댓글 없음:
댓글 쓰기