在Spring中使用Asciidoctor:使用Spring MVC渲染Asciidoc文档

Asciidoc是一种基于文本的文档格式,因此如果要将文档提交到版本控制系统中并跟踪不同版本之间的更改,它非常有用。 这使Asciidoc成为编写书籍,技术文档,常见问题解答或用户手册的理想工具。

创建Asciidoc文档后,很可能要发布该文档,而做到这一点的一种方法是将该文档发布到我们的网站上。 今天,我们将学习如何使用AsciidoctorJ将Asciidoc文档转换为HTML,以及如何使用Spring MVC渲染创建HTML。

我们的应用程序的要求是:

  • 它必须支持从类路径中找到的Asciidoc文档。
  • 它必须支持作为String对象给出的Asciidoc标记。
  • 它必须将Asciidoc文档转换为HTML并呈现创建HTML。
  • 它必须将创建HTML“嵌入”到我们的应用程序布局中。

让我们从获取Maven所需的依赖关系开始。

使用Maven获取所需的依赖关系

通过执行以下步骤,我们可以使用Maven获得所需的依赖关系:

  1. 启用Spring IO平台 。
  2. 配置所需的依赖项。

首先 ,我们可以通过将以下代码段添加到我们的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>

其次 ,我们可以按照以下步骤配置所需的依赖项:

  1. pom.xml文件中配置日志记录依赖性。
  2. 将spring-webmvc依赖项添加到pom.xml文件。
  3. 将Servlet API依赖项添加到POM文件中。
  4. 在POM文件中配置Sitemesh(版本3.0.0)依赖性。 Sitemesh确保我们应用程序的每个页面使用一致的外观。
  5. 将asciidoctorj依赖性(版本1.5.0)添加到pom.xml文件。 AsciidoctorJ是Asciidoctor的Java API,我们使用它来将Asciidoc文档转换为HTML。

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文档

通过执行以下步骤,我们可以满足应用程序的要求:

  1. 配置我们的Web应用程序和Sitemesh过滤器。
  2. 实现视图类,这些视图类负责将Asciidoc文档转换为HTML并呈现创建HTML。
  3. 实现使用创建的视图类的控制器方法。

让我们开始吧。

配置Sitemesh

我们要做的第一件事是配置Sitemesh。 我们可以按照以下三个步骤配置Sitemesh:

  1. 在Web应用程序配置中配置Sitemesh过滤器。
  2. 创建用于为我们的应用程序创建一致外观的装饰器。
  3. 配置Sitemesh过滤器使用的装饰器。

首先 ,我们必须在Web应用程序配置中配置Sitemesh过滤器。 我们可以按照以下步骤配置Web应用程序:

  1. 创建一个实现WebApplicationInitializer接口的WebAppConfig类。
  2. 通过执行以下步骤来实现WebApplicationInitializer接口的onStartup()方法 :
    1. 创建一个AnnotationConfigWebApplicationContext对象并将其配置为处理我们的应用程序上下文配置类。
    2. 配置调度程序servlet 。
    3. 配置Sitemesh过滤器以处理应用程序的JSP页面和使用url模式'/ asciidoctor / *'的所有控制器方法返回HTML
    4. 将新的ContextLoaderListener对象添加到ServletContext中ContextLoaderListener负责启动和关闭Spring WebApplicationContext

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中获得它 。

其次 ,我们必须创建为我们的应用程序提供一致外观的装饰器。 我们可以按照以下步骤进行操作:

  1. 将装饰器文件创建到src / main / webapp / WEB-INF目录。 我们的示例应用程序的装饰器文件称为layout.jsp
  2. 将提供一致外观HTML添加到创建的装饰器文件中。
  3. 确保Sitemesh将从返回HTML中找到的标题添加到Web浏览器呈现HTML中。
  4. 配置Sitemesh,将从返回HTML的开头找到HTML元素添加到呈现HTML的开头。
  5. 确保Sitemesh将在返回HTML中找到的正文添加到显示给用户HTML中。

装饰器文件( 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以使用在第二步中创建的装饰器文件。 我们可以按照以下步骤进行操作:

  1. src / main / webapp / WEB-INF目录中创建一个sitemesh3.xml文件。
  2. 将Sitemesh配置为使用我们的装饰器处理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标记的视图类。

换句话说,我们必须创建以下类结构:

asciidoctor-html-views

首先 ,我们必须实现AbstractAsciidoctorHtmlView类。 此类是一个抽象基类,可将Asciidoc标记转换为HTML并呈现创建HTML。 我们可以按照以下步骤实现此类:

  1. 创建AbstractAsciidoctorHtmlView类并扩展AbstractView类。
  2. 在创建的类中添加一个构造函数,并将视图的内容类型设置为“ text / html”。
  3. 将一个受保护的抽象方法getAsciidocMarkupReader()添加到创建的类,并将其返回类型设置为Reader 。 此抽象类的子类必须实现此方法,并且此方法的实现必须返回一个Reader对象,该对象可用于读取呈现的Asciidoc标记。
  4. 将私有的getAsciidoctorOptions()方法添加到创建的类中,并通过返回Asciidoctor的配置选项来实现它。
  5. 重写AbstractView类的renderMergedOutputModel()方法 ,并通过将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标记。 我们可以按照以下步骤实现此类:

  1. 创建ClasspathFileAsciidoctorHtmlView类,并扩展AbstractAsciidoctorHtmlView类。
  2. 在创建的类中添加一个名为asciidocFileLocation的私有String字段。 此字段包含转换为HTML的Asciidoc文件的位置。 必须以Class类的getResourceAsStream()方法可以理解的格式指定此位置。
  3. 创建一个构造器,该构造器将呈现的Asciidoc文件的位置作为构造器参数。 通过调用超类的构造函数并将呈现的Asciidoc文件的位置存储到asciidocFileLocation字段中来实现构造函数
  4. 重写getAsciidocMarkupReader()方法并通过返回一个新的InputStreamReader对象来实现它,该对象用于读取从类路径中找到的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标记。 我们可以按照以下步骤实现此类:

  1. 创建StringAsciidoctorHtmlView类,并扩展AbstractAsciidoctorHtmlView类。
  2. 在创建的类中添加一个名为asciidocMarkup的私有String字段。 此字段包含已转换为HTML的Asciidoc标记。
  3. 创建一个将呈现的Asciidoc标记用作构造函数参数的构造函数。 通过调用超类的构造函数并将呈现的Asciidoc标记设置为asciidocMarkup字段来实现此构造函数。
  4. 重写getAsciidocMarkupReader()方法,并通过返回一个新的StringReader对象来实现它,该对象用于读取存储在asciidocMarkup字段中的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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362103.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

http强缓存在firefox和chrome之间的差异

最近回顾HTTP缓存知识的时候发现了一个问题&#xff0c;设置了强缓存和协商缓存的文件&#xff0c;点击浏览器的刷新按钮的时候在chrome和firefox中的表现不一样。具体表现为chrome走强缓存没有再次发起请求。firefox却在强缓存没有失效的情况下发了请求&#xff0c;返回了304走…

垃圾收集器–串行,并行,CMS,G1(以及Java 8中的新增功能)

4个Java垃圾收集器–错误的选择如何严重影响性能 在2014年&#xff0c;对于大多数开发人员来说&#xff0c;还有两件事仍然是个谜&#xff1a;垃圾收集和了解异性。 由于我对后者知之甚少&#xff0c;所以我认为我会对前者大吃一惊&#xff0c;特别是因为在该领域中&#xff0c…

基于webpack的react脚手架

一、前言&#xff1a;react的cli开发模式太过于简单&#xff0c;好多东西都要自己配置 二、这里有个简单的配置&#xff0c;可以直接上手开发(不熟悉webpack和npm的绕路)&#xff0c;已经完成的配置如下 1&#xff1a;默认ejs模板 2&#xff1a;编译less、scss 3&#xff1…

不要错过使用jOOλ或jOOQ编写Java 8 SQL单行代码的机会

越来越多的人通过为他们的业务采用功能性编程来赶上我们平台的最新更新。 在Data Geekery &#xff0c;我们将Java 8用于jOOQ集成测试&#xff0c;因为将新的Streams API与lambda表达式一起使用使生成临时测试数据变得非常容易。 但是&#xff0c; 我们并不认为JDK提供了尽可…

node实现简单的群体聊天工具

一、使用的node模块 1、express当做服务器 2、socket.io 前后通信的桥梁 3、opn默认打开浏览器的模块(本质上用不到) 难点&#xff1a;前后通信 源码地址&#xff1a;https://github.com/wjf444128852/SimpleChat 欢迎clone并运行、扩展改进、issues 二、基础样子&#…

使用Spring Security的多租户应用程序的无状态会话

从前&#xff0c; 我发表了一篇文章&#xff0c;解释了构建无状态会话的原理 。 巧合的是&#xff0c;我们再次针对多租户应用程序执行同一任务。 这次&#xff0c;我们将解决方案集成到Spring Security框架中&#xff0c;而不是自己构建身份验证机制。 本文将解释我们的方法和…

What?一个 Dubbo 服务启动要两个小时!

前言 前几天在测试环境碰到一个非常奇怪的与 dubbo 相关的问题&#xff0c;事后我在网上搜索了一圈并没有发现类似的帖子或文章&#xff0c;于是便有了这篇。 希望对还未碰到或正在碰到的朋友有所帮助。 现象 现象是这样的&#xff0c;有一天测试在测试环境重新部署一个 dubbo …

使用Project Lombok减少Java应用程序中的样板代码

对Java编程语言最常提出的批评之一是它需要大量的样板代码 。 对于简单的类尤其如此&#xff0c;该类只需要存储一些值就可以。 您需要这些值的getter和setter&#xff0c;也许您还需要一个构造函数&#xff0c;覆盖equals&#xff08;&#xff09;和 hashcode&#xff08;&am…

十六、CI框架之数据库操作get用法

一、使用数据库的Get方法读取内容&#xff0c;如下代码&#xff1a; 二、数据库如下&#xff1a; 二、效果如下&#xff1a; 转载于:https://www.cnblogs.com/tianpan2019/p/11141809.html

WCF系列(二) -- 使用配置文件构建和使用WCF服务

当然&#xff0c;配置一个ServiceHost除了上面说的完全使用代码的方式&#xff0c;更好的方式是使用配置文件&#xff0c;把一些可能需要修改的属性跟代码分离&#xff0c;放到配置文件中&#xff0c;这样可以提供服务配置的灵活性&#xff0c;也更容易维护。 看看前面那个不用…

如何使用github搭建个人博客

1、去github官网注册个人帐号&#xff1a;没有的&#xff1a;猛戳这里去注册&#xff0c;比如我的账户名&#xff1a;wjf444128852&#xff0c;我的已经汉化(可在github里搜索github如何汉化有插件) 2、点击仓库-新建&#xff0c;仓库名字必须是&#xff1a;你的github帐号.git…

Spring Boot和Spring Data REST –通过REST公开存储库

使用Spring Boot和Spring Data REST&#xff0c;通过REST公开Spring Data存储库非常容易。 使用最少的代码&#xff0c;您可以创建遵循HATEOAS原理的JPA实体的REST表示。 我决定重用Spring PetClinic的JPA实体&#xff08;业务层&#xff09;作为本文的基础。 应用基础 PetCli…

jQuery Ajax – Servlets集成:构建完整的应用程序

网上有很多教程&#xff0c;它们解释了有关使用servlet和JSP页面进行Java Web开发的一些知识&#xff0c;但是&#xff0c;我从来没有找到对于初学者来说足够简洁&#xff0c;简单的教程。 这样的教程应该解释创建一个简单的Web应用程序的整个过程&#xff0c;包括前端&#xf…

信息系统开发平台OpenExpressApp - 应用模型ApplicationModel

下图为OpenExpressApp的系统架构图&#xff0c;其中在应用模型是作为一种元数据贯穿于整个架构&#xff0c;应用模型运行在OpenExpressApp框架之上。应用模型是OEA的核心&#xff0c;理解好应用模型才能更好的使用OEA。 应用模型贯穿于整个架构层 模型关注what OEA希望从重复的…

关于页面布局间距使用的经验之谈

在页面布局的时候遇到一个问题在此记录。 有如下布局需求。页面上大多数都是这样的&#xff0c;一块一块从上到下排列。 块与块之间的间距需要固定由谁来负责。例如第一个块和第二个块之间的间距&#xff0c;就需要第二个块的margin-top完成&#xff0c;文字和第二个块之间的间…

canvas绘制经典折线图(一)

最终效果图如下&#xff1a; 实现步骤如下&#xff1a;注-引用了jQuery HTML代码 <!doctype html><html lang"en"><head><meta charset"UTF-8"><meta name"Generator" content"EditPlus"><meta nam…

win7笔记本为手机共享wifi

1、cmd netsh wlan set hostednetwork modeallow ssidyourname keyyourpassword 开启win7的虚拟wifi&#xff0c;让电脑变成无线路由器 这时&#xff0c;网络连接中会多出一个网卡为“Microsoft Virtual WiFi Miniport Adapter”的无线连接2。如果没有&#xff0c;需要更新无线…

createjs中shape的属性regX和regY

官方文档说regX和regY是图形与注册点的距离。 那么注册点是什么呢&#xff1f; 我理解注册点就是图形的x/y对应的点图形动效的原点就是注册点 如果修改图形的regX和regY值图形在画布上的位置是会被改变的&#xff0c;但是注册点其实并没有被改变。因为图形的x/y值并没有被改…

H3C 单区域OSPF配置示例二

转载于:https://www.cnblogs.com/fanweisheng/p/11163688.html

身份反模式:联邦筒仓和意大利面条身份

分析公司Quocirca的最新研究证实&#xff0c;现在许多企业的外部用户比内部用户更多&#xff1a;在欧洲&#xff0c;有58&#xff05;的企业直接与其他企业和/或消费者的用户进行交易&#xff1b; 仅在英国&#xff0c;这一数字就达到了65&#xff05;。 如果您回顾历史&#x…