javascript
在Spring中使用Asciidoctor:使用Spring MVC渲染Asciidoc文档
Asciidoc是一種基于文本的文檔格式,因此如果要將文檔提交到版本控制系統中并跟蹤不同版本之間的更改,它非常有用。 這使Asciidoc成為編寫書籍,技術文檔,常見問題解答或用戶手冊的理想工具。
創建Asciidoc文檔后,很可能要發布該文檔,而做到這一點的一種方法是將該文檔發布到我們的網站上。 今天,我們將學習如何使用AsciidoctorJ將Asciidoc文檔轉換為HTML,以及如何使用Spring MVC渲染創建HTML。
我們的應用程序的要求是:
- 它必須支持從類路徑中找到的Asciidoc文檔。
- 它必須支持作為String對象給出的Asciidoc標記。
- 它必須將Asciidoc文檔轉換為HTML并呈現創建HTML。
- 它必須將創建HTML“嵌入”到我們的應用程序布局中。
讓我們從獲取Maven所需的依賴關系開始。
使用Maven獲取所需的依賴關系
通過執行以下步驟,我們可以使用Maven獲得所需的依賴關系:
首先 ,我們可以通過將以下代碼段添加到我們的POM文件中來啟用Spring IO平臺:
<dependencyManagement><dependencies><dependency><groupId>io.spring.platform</groupId><artifactId>platform-bom</artifactId><version>1.0.2.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies> </dependencyManagement>其次 ,我們可以按照以下步驟配置所需的依賴項:
pom.xml文件的相關部分如下所示:
<dependencies><!-- Logging --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></dependency><!-- Spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><!-- Java EE --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><scope>provided</scope></dependency><!-- Sitemesh --><dependency><groupId>org.sitemesh</groupId><artifactId>sitemesh</artifactId><version>3.0.0</version></dependency><!-- AsciidoctorJ --><dependency><groupId>org.asciidoctor</groupId><artifactId>asciidoctorj</artifactId><version>1.5.0</version></dependency> </dependencies>因為我們使用Spring IO Platform,所以不必指定Spring IO Platform中的工件的依賴版本。
讓我們繼續并開始實現我們的應用程序。
使用Spring MVC渲染Asciidoc文檔
通過執行以下步驟,我們可以滿足應用程序的要求:
讓我們開始吧。
配置Sitemesh
我們要做的第一件事是配置Sitemesh。 我們可以按照以下三個步驟配置Sitemesh:
首先 ,我們必須在Web應用程序配置中配置Sitemesh過濾器。 我們可以按照以下步驟配置Web應用程序:
WebAppConfig類的源代碼如下所示(突出顯示了Sitemesh配置):
import org.sitemesh.config.ConfigurableSiteMeshFilter; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet;import javax.servlet.DispatcherType; import javax.servlet.FilterRegistration; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import java.util.EnumSet;public class WebAppConfig implements WebApplicationInitializer {private static final String DISPATCHER_SERVLET_NAME = "dispatcher";private static final String SITEMESH3_FILTER_NAME = "sitemesh";private static final String[] SITEMESH3_FILTER_URL_PATTERNS = {"*.jsp", "/asciidoctor/*"};@Overridepublic void onStartup(ServletContext servletContext) throws ServletException {AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();rootContext.register(WebAppContext.class);configureDispatcherServlet(servletContext, rootContext);configureSitemesh3Filter(servletContext);servletContext.addListener(new ContextLoaderListener(rootContext));}private void configureDispatcherServlet(ServletContext servletContext, WebApplicationContext rootContext) {ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME,new DispatcherServlet(rootContext));dispatcher.setLoadOnStartup(1);dispatcher.addMapping("/");}private void configureSitemesh3Filter(ServletContext servletContext) {FilterRegistration.Dynamic sitemesh = servletContext.addFilter(SITEMESH3_FILTER_NAME, new ConfigurableSiteMeshFilter());EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);sitemesh.addMappingForUrlPatterns(dispatcherTypes, true, SITEMESH3_FILTER_URL_PATTERNS);} }- 如果要看一下示例應用程序的應用程序上下文配置類,可以從Github中獲得它 。
其次 ,我們必須創建為我們的應用程序提供一致外觀的裝飾器。 我們可以按照以下步驟進行操作:
裝飾器文件( layout.jsp )的源代碼如下所示(與Sitemesh相關的部分已突出顯示):
<!doctype html> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title><sitemesh:write property="title"/></title><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" type="text/css" href="${contextPath}/static/css/bootstrap.css"/><link rel="stylesheet" type="text/css" href="${contextPath}/static/css/bootstrap-theme.css"/><script type="text/javascript" src="${contextPath}/static/js/jquery-2.1.1.js"></script><script type="text/javascript" src="${contextPath}/static/js/bootstrap.js"></script><sitemesh:write property="head"/> </head> <body> <nav class="navbar navbar-inverse" role="navigation"><div class="container-fluid"><!-- Brand and toggle get grouped for better mobile display --><div class="navbar-header"><button type="button" class="navbar-toggle" data-toggle="collapse"data-target="#bs-example-navbar-collapse-1"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button></div><div class="collapse navbar-collapse"><ul class="nav navbar-nav"><li><a href="${contextPath}/">Document list</a></li></ul></div></div> </nav> <div class="container-fluid"><sitemesh:write property="body"/> </div> </body> </html>第三 ,我們必須配置Sitemesh以使用在第二步中創建的裝飾器文件。 我們可以按照以下步驟進行操作:
sitemesh3.xml文件如下所示:
<sitemesh><mapping path="/*" decorator="/WEB-INF/layout/layout.jsp"/> </sitemesh>這就對了。 現在,我們已經配置了Sitemesh,以為我們的應用程序提供一致的外觀。 讓我們繼續前進,了解如何實現將Asciidoc標記轉換為HTML并呈現所創建HTML的視圖類。
實施視圖類
在開始實現將Asciidoc標記轉換為HTML并呈現創建HTML的視圖類之前,我們必須快速了解一下我們的需求。 與該步驟相關的要求是:
- 我們的解決方案必須支持從類路徑中找到的Asciidoc文檔。
- 我們的解決方案必須支持作為String對象給出的Asciidoc標記。
- 我們的解決方案必須將Asciidoc文檔轉換為HTML并呈現創建HTML。
這些要求建議我們應該創建三個視圖類。 這些視圖類如下所述:
- 我們應該創建一個抽象基類,該基類包含將Asciidoc標記轉換為HTML并呈現創建HTML的邏輯。
- 我們應該創建一個視圖類,該類可以從類路徑中找到的文件中讀取Asciidoc標記。
- 我們應該創建一個可以從String對象讀取Asciidoc標記的視圖類。
換句話說,我們必須創建以下類結構:
首先 ,我們必須實現AbstractAsciidoctorHtmlView類。 此類是一個抽象基類,可將Asciidoc標記轉換為HTML并呈現創建HTML。 我們可以按照以下步驟實現此類:
AbstractAsciidoctorHtmlView類的源代碼如下所示:
import org.asciidoctor.Asciidoctor; import org.asciidoctor.Options; import org.springframework.http.MediaType; import org.springframework.web.servlet.view.AbstractView;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.Reader; import java.io.Writer; import java.util.Map;public abstract class AbstractAsciidoctorHtmlView extends AbstractView {public AbstractAsciidoctorHtmlView() {super.setContentType(MediaType.TEXT_HTML_VALUE);}protected abstract Reader getAsciidocMarkupReader();@Overrideprotected void renderMergedOutputModel(Map<String, Object> model,HttpServletRequest request,HttpServletResponse response) throws Exception {//Set the content type of the response to 'text/html'response.setContentType(super.getContentType());Asciidoctor asciidoctor = Asciidoctor.Factory.create();Options asciidoctorOptions = getAsciidoctorOptions();try (//Get the reader that reads the rendered Asciidoc document//and the writer that writes the HTML markup to the request bodyReader asciidoctorMarkupReader = getAsciidocMarkupReader();Writer responseWriter = response.getWriter();) {//Transform Asciidoc markup into HTML and write the created HTML //to the response bodyasciidoctor.render(asciidoctorMarkupReader, responseWriter, asciidoctorOptions);}}private Options getAsciidoctorOptions() {Options asciiDoctorOptions = new Options();//Ensure that Asciidoctor includes both the header and the footer of the Asciidoc //document when it is transformed into HTML.asciiDoctorOptions.setHeaderFooter(true);return asciiDoctorOptions;} }其次 ,我們必須實現ClasspathFileAsciidoctorHtmlView類。 此類可以從類路徑中找到的文件中讀取Asciidoc標記。 我們可以按照以下步驟實現此類:
ClasspathFileAsciidoctorHtmlView類的源代碼如下所示:
import java.io.InputStreamReader; import java.io.Reader;public class ClasspathFileAsciidoctorHtmlView extends AbstractAsciidoctorHtmlView {private final String asciidocFileLocation;public ClasspathFileAsciidoctorHtmlView(String asciidocFileLocation) {super();this.asciidocFileLocation = asciidocFileLocation;}@Overrideprotected Reader getAsciidocMarkupReader() {return new InputStreamReader(this.getClass().getResourceAsStream(asciidocFileLocation));} }第三 ,我們必須實現StringAsciidoctorHtmlView類,該類可以從String對象讀取Asciidoc標記。 我們可以按照以下步驟實現此類:
StringAsciidoctorHtmlView的源代碼如下所示:
import java.io.Reader; import java.io.StringReader;public class StringAsciidoctorHtmlView extends AbstractAsciidoctorHtmlView {private final String asciidocMarkup;public StringAsciidoctorHtmlView(String asciidocMarkup) {super();this.asciidocMarkup = asciidocMarkup;}@Overrideprotected Reader getAsciidocMarkupReader() {return new StringReader(asciidocMarkup);} }現在,我們已經創建了所需的視圖類。 讓我們繼續研究如何在Spring MVC Web應用程序中使用這些類。
使用創建的視圖類
我們的最后一步是創建使用創建的視圖類的控制器方法。
我們必須實現以下描述的兩種控制器方法:
- renderAsciidocDocument()方法處理發送到url'/ asciidoctor / document'的GET請求,然后將Asciidoc文檔轉換為HTML并呈現創建HTML。
- renderAsciidocString()方法處理發送到url'/ asciidoctor / string'的GET獲取請求,然后將Asciidoc 字符串轉換為HTML并呈現創建HTML。
AsciidoctorController類的源代碼如下所示:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView;@Controller public class AsciidoctorController {private static final String ASCIIDOC_FILE_LOCATION = "/asciidoctor/document.adoc";private static final String ASCIIDOC_STRING = "= Hello, AsciiDoc (String)!\n" +"Doc Writer <doc@example.com>\n" +"\n" +"An introduction to http://asciidoc.org[AsciiDoc].\n" +"\n" +"== First Section\n" +"\n" +"* item 1\n" +"* item 2\n" +"\n" +"1\n" +"puts \"Hello, World!\"";@RequestMapping(value = "/asciidoctor/document", method = RequestMethod.GET)public ModelAndView renderAsciidocDocument() {//Create the view that transforms an Asciidoc document into HTML and//renders the created HTML.ClasspathFileAsciidoctorHtmlView docView = new ClasspathFileAsciidoctorHtmlView(ASCIIDOC_FILE_LOCATION);return new ModelAndView(docView);}@RequestMapping(value = "/asciidoctor/string", method = RequestMethod.GET)public ModelAndView renderAsciidocString() {//Create the view that transforms an Asciidoc String into HTML and//renders the created HTML.StringAsciidoctorHtmlView stringView = new StringAsciidoctorHtmlView(ASCIIDOC_STRING);return new ModelAndView(stringView);} }附加信息:
- @Controller批注的Javadoc
- @RequestMapping注釋的Javadoc
- ModelAndView類的Javadoc
現在,我們已經創建了使用我們的視圖類的控制器方法。 當我們的應用程序的用戶調用url'/ asciidoctor / document'的GET請求時,呈現HTML頁面的源代碼如下所示(由Asciidoctor創建的部分被突出顯示):
<!doctype html><html> <head><title>Hello, AsciiDoc (File)!</title><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" type="text/css" href="/static/css/bootstrap.css"/><link rel="stylesheet" type="text/css" href="/static/css/bootstrap-theme.css"/><script type="text/javascript" src="/static/js/jquery-2.1.1.js"></script><script type="text/javascript" src="/static/js/bootstrap.js"></script><meta charset="UTF-8"> <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="generator" content="Asciidoctor 1.5.0"> <meta name="author" content="Doc Writer"><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic|Noto+Serif:400,400italic,700,700italic|Droid+Sans+Mono:400"> <link rel="stylesheet" href="./asciidoctor.css"></head> <body> <nav class="navbar navbar-inverse" role="navigation"><div class="container-fluid"><!-- Brand and toggle get grouped for better mobile display --><div class="navbar-header"><button type="button" class="navbar-toggle" data-toggle="collapse"data-target="#bs-example-navbar-collapse-1"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button></div><div class="collapse navbar-collapse"><ul class="nav navbar-nav"><li><a href="/">Document list</a></li></ul></div></div> </nav> <div class="container-fluid"><div id="header"> <h1>Hello, AsciiDoc (File)!</h1> <div class="details"> <span id="author" class="author">Doc Writer</span><br> <span id="email" class="email"><a href="mailto:doc@example.com">doc@example.com</a></span><br> </div> </div> <div id="content"> <div id="preamble"> <div class="sectionbody"> <div class="paragraph"> <p>An introduction to <a href="http://asciidoc.org">AsciiDoc</a>.</p> </div> </div> </div> <div class="sect1"> <h2 id="_first_section">First Section</h2> <div class="sectionbody"> <div class="ulist"> <ul> <li> <p>item 1</p> </li> <li> <p>item 2</p> </li> </ul> </div> <div class="listingblock"> <div class="content"> <pre class="highlight"><code class="language-ruby" data-lang="ruby">puts "Hello, World!"</code></pre> </div> </div> </div> </div> </div> <div id="footer"> <div id="footer-text"> Last updated 2014-09-21 14:21:59 EEST </div> </div></div> </body> </html>如我們所見,由Asciidoctor創建HTML嵌入到我們的布局中,這為我們的應用程序用戶提供了一致的用戶體驗。
讓我們繼續并評估此解決方案的優缺點。
利弊
我們解決方案的優點是:
- 呈現HTML文檔與我們應用程序的其他頁面具有相同的外觀。 這意味著我們可以為應用程序的用戶提供一致的用戶體驗。
- 我們可以呈現靜態文件和可以從數據庫加載的字符串。
我們解決方案的缺點是:
- 我們的簡單應用程序的war文件很大(51.9 MB)。 原因是,即使Asciidoctor具有Java API,它也是用Ruby編寫的。 因此,我們的應用程序需要兩個大的jar文件:
- asciidoctorj-1.5.0.jar文件的大小為27.5MB。
- 當用戶請求時,我們的應用程序將Asciidoc文檔轉換為HTML。 這對我們的控制器方法的響應時間有負面影響,因為文檔越大,處理該文檔所花費的時間就越長。
- 將Asciidoc文檔呈現為HTML的第一個請求比下一個請求慢4-5倍。 我沒有剖析該應用程序,但我認為JRuby與此有關。
- 目前,如果我們要將Asciidoc文檔轉換為PDF文檔,則無法使用此技術。
讓我們繼續并總結從這篇博客文章中學到的知識。
摘要
這篇博客文章教會了我們三件事:
- 我們了解了如何配置Sitemesh,以為我們的應用程序提供一致的外觀。
- 我們學習了如何創建將Asciidoc文檔轉換為HTML并呈現所創建HTML的視圖類。
- 即使我們的解決方案有效,它也有很多缺點,可能使其在現實生活中無法使用。
本教程的下一部分描述了如何解決此解決方案的性能問題。
PS:如果您想體驗本博客文章的示例應用程序,可以從Github獲得 。
翻譯自: https://www.javacodegeeks.com/2014/10/using-asciidoctor-with-spring-rendering-asciidoc-documents-with-spring-mvc.html
總結
以上是生活随笔為你收集整理的在Spring中使用Asciidoctor:使用Spring MVC渲染Asciidoc文档的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深圳驾校备案流程(深圳驾校备案)
- 下一篇: ddos攻击需要多少肉鸡(ddos10g