적용 방법은 아래와 같다.
① 마크다운 문서 작성
② Spring 환경에서 HTML 문서로 동적 변환하여 화면 출력
마크다운 문서를 HTML 로 변환하는 것은 여러 가지 방법을 고려하였으나 filter 를 사용하는 것을 선택했다. 마크다운 파싱과 HTML랜더링은 이슈관리 툴 Jira 로 널리 알려진 Atlassian 의 오픈소스 https://github.com/atlassian/commonmark-java 를 사용하였다.
1. 라이브러리 추가
Maven빌드 툴을 사용하고 있기 때문에 아래와 같이 라이브러리를 pom.xml 파일에 추가한다.
1 2 3 4 5 | < dependency > < groupid >org.springframework.restdocs</ groupid > < artifactid >spring-restdocs-mockmvc</ artifactid > < version >2.0.0.RELEASE</ version > </ dependency > |
2. 필터 만들기
필터는 "org.springframework.web.filter.OncePerRequestFilter" 클래스를 상속받아 구현하였으며 어노테이션을 통하여 배포되도록 구성하였다. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | 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); } } |
댓글 없음:
댓글 쓰기