Skip to main content

jobconverter文档详解

版本: 4.2.0
https://github.com/sbraconnier/jodconverter/wiki/Getting-Started

概览

Jodconvert , 是一个java的文档转换器, 利用 openoffice 或 libreOffice 来进行文档格式转换.

其支持的格式如下:

对于html格式的特殊注意:

  • HTML可以用作输入格式,但您不应期望OOo像Chrome或IE那样正确地呈现复杂的网页。 仅适用于简单和“打印机友好”的网页。
  • HTML可以用作输出格式,但是所有其他格式总是生成单个输出文件,HTML可以生成多个文件。 实际上,除了HTML文件之外,输入文档中包含的任何图像也将保存在同一目录中。 这需要您的代码格外小心,特别是在Web环境中。

应用场景

  • 作为java类库使用
  • 作为命令行工具使用
  • 作为web应用使用

添加依赖

Maven

<properties>
    <jodconverter.version>4.1.1</jodconverter.version>
</properties>
<dependencies>
   <dependency>
      <groupId>org.jodconverter</groupId>
      <artifactId>jodconverter-local</artifactId>
      <version>${jodconverter.version}</version>
   </dependency>
</dependencies>

Gradle

ext {
    jodconverterVersion = 4.2.0
}
compile "org.jodconverter:jodconverter-local:$jodconverterVersion"

使用要求

  • java 1.7 及以上
  • openoffice 或 libreOffice 的稳定版本

参数配置

workingDir
该属性用来设置office临时文件配置目录。每个office进程启动时,一个文件配置目录将会被创建。当使用InputStream/OutputStream来转换时,这个目录也会被创建。默认由指定的路径为java.io.tmpdir

templateProfileDir
为了避免进程被中断或者用户使用了另一个OOo实例,LocalOfficeManager会为OOo进程创建一个临时配置文件目录。使用这个属性,你可以提供一个包含个性化设置的临时配置文件目录。OfficeManager会将以其为模板,来生成临时配置文件目录。所以当我们创建新的OOo实例时,都会使用相同的配置。默认情况虾,这个临时的配置文件由OOo使用默认配置来创建,并且其依赖于 -nofirststartwizard这个命令选项。

killExistingProcess
该属性能够指定,当一个包含相同connection string的office进程启动,是否杀死一个已经存在的office进程。默认为true.

processTimeout
当尝试调用一个office进程时(开始/中止),该属性可以设置超时时间,单位为毫秒。默认为120000(2 minutes)

processRetryInterval
每当尝试调用一个office进程时(开始/中止)的间隙,可用该属性设置延迟,单位为毫秒。默认为250(0.25 seconds)

taskExecutionTimeout
该属性设置执行一个任务的最大时间,若超过这个时间任务仍未执行,则当前任务被中止且执行下个任务。默认为12000(两分钟)

maxTasksPerProcess
该属性设置一个office进程在重启之前所能执行的最大任务数。默认为200个。

disableOpengl
当启动一个新的office进程时(在LibreOffice的情况下),该属性能够指定是否禁止OpenGL。如果OpenGL已经根据office进程使用的用户配置禁用,那么将不会执行任何操作。如果该属性改变,那么office进程必须重启。如果LO进程奔溃,那么你可以尝试测试该属性。默认为false

taskQueueTimeout
该属性用来设置一个任务在转换队列中的最大生存时间。如果等待时间超过最大生存时间或者有OfficeException异常抛出,则任务将会从队列中移除。默认为30000(30 seconds)

软件测试–Bug等级划分方法

测试BUG等级划分标准

  • Blocker(崩溃):阻碍开发或测试工作的问题;造成系统崩溃、死机、死循环,导致数据库数据丢失,与数据库连接错误,主要功能丧失,基本模块缺失等问题。如:代码错误、死循环、数据库发生死锁、重要的一级菜单功能不能使用等
  • Critical(严重):系统主要功能部分丧失、数据库保存调用错误、用户数据丢失,一级功能菜单不能使用但是不影响其他功能的测试。功能设计与需求严重不符,模块无法启动或调用,程序重启、自动退出,关联程序间调用冲突,安全问题、稳定性等。如:软件中数据保存后数据库中显示错误,用户所要求的功能缺失,程序接口错误,数值计算统计错误等(该等级问题出现在不影响其他功能测试的情况下可以继续该版本测试)。
  • Major(一般):功能没有完全实现但是不影响使用,功能菜单存在缺陷但不会影响系统稳定性。如:操作时间长、查询时间长、格式错误、边界条件错误,删除没有确认框、数据库表中字段过多等(该问题实际测试中存在最多,合理安排解决BUG,解决率关系版本的优化程度)
  • Minor(次要):界面、性能缺陷,建议类问题,不影响操作功能的执行,可以优化性能的方案等。如:错别字、界面格式不规范,页面显示重叠、不该显示的要隐藏,描述不清楚,提示语丢失,文字排列不整齐,光标位置不正确,用户体验感受不好,可以优化性能的方案等(此类问题在测试初期较多,优先程度较低;在测试后期出现较少,应及时处理)

【转载】微服务架构下的分布式Session管理

大家好,很高兴在这里和大家进行微课堂的分享,今天进行分享的主题是《微服务架构下的分布式Session管理》。

主要大纲:

一、应用架构变迁下的Session管理

二、微服务架构下的Session管理

三、Session管理实践分享

一、应用架构变迁下的Session管理

Session一词直译为“会话”,意指有始有终的一系列动作/消息。Session是Web应用蓬勃发展的产物之一,在Web应用中隐含有“面向连接”和“状态保持”两个含义,同时也指代了Web服务器与客户端之间进行状态保持的解决方案。

在Web应用诞生之初,应用服务器与浏览器之间仅仅只是基于HTTP协议进行通信。而HTTP协议是无状态的,也就是说每一个请求之间都是相互独立的,互不关联。但是随着应用业务复杂化,服务器需要按照用户的一系列业务操作向用户提供某些特定的、按需的内容。这时候就需要通过保存用户状态,将用户的请求关联起来。Session管理正是这一问题的解决方案。

早期的Web应用基本都采用的是单体架构,也就是把一个使用了分层架构的Web应用部署在单节点Web服务器上的架构类型。在这种架构中,虽然采用了分层架构,将整个应用分为了表现层、业务逻辑层和数据访问层,每一层各司其职,让Web应用的各个方面都有所改善。但这样的分层只是停留于逻辑上。由于将所有代码部署在单个服务器节点上,随着应用不断迭代开发,单体应用将会发展成巨石型应用,臃肿不堪,难以维护。

在这样的单体架构中,由于所有的用户请求都是由这个唯一的服务器进行响应处理,所以只要把保存了用户信息和状态的Session对象,存放在应用服务器内存里,就能轻松地达到保持用户状态的目的。

随着Web应用的发展,用户访问量和业务复杂度与日俱增,应用的性能和代码的维护难度成为应用的瓶颈,为了突破瓶颈,开发者开始尝试在应用架构中引入负载均衡器,继而演化出了集群和分布式两种架构类型。

  • 集群,是指在多个服务器节点上部署相同的应用,例如上图中的服务器B和C,然后通过负载均衡器的分发功能,把用户请求分发到集群中的任意一个服务器节点上。如果有更大的访问量,只要向集群中增加服务器节点,就能改善压力。集群既能保证应用的高可用,又能提高应用的负载能力。
  • 分布式,是把原来的单体架构应用,通过分而治之的手段,按照业务功能,切分成一些小的模块应用,部署在不同服务器节点上,例如上图中的服务器A和B。然后通过负载均衡器和门户应用整合起来,组成一个完整的应用。

集群和分布式架构中,后端包含了多个服务器节点。当用户进行登录时,登录请求是由其中一个服务器节点进行响应,而后续的用户请求将可能被负载均衡器分发到其他服务器节点,这时候就可能因为这个服务器节点上没有用户Session,导致服务器判定用户是未登录状态,让用户重新登录。

所以,在集群和分布式架构中,必须保证用户进行登陆后,架构中的所有服务器节点都能共享Session数据。常用的Session管理方案有如下3种:

1、将Session对象保存在Cookie,然后存放在浏览器端。每次浏览器向服务器发送请求的时候,都会把整个Session对象放在请求里一起发送到服务器,以此来实现Session共享。这样的方案实现起来特别方便,但是由于Cookie的存储容量比较小,所以这个方案只适用于Session数据量小的场景。

2、Session复制。部分应用服务器能够支持Session复制功能,例如Tomcat。用户可以通过修改配置文件,让应用服务器进行Session复制,保持每一个服务节点的Session数据达到一致。但是这个方案的实现依赖于应用服务器。当应用被大量用户访问时,每个服务器都需要有一部分内存用来存放Session,同时因为大量Session通过网路传输进行复制,将会占用网络资源,还可能因为网络延迟导致程序异常。

3、Session粘滞。利用负载均衡器的分发能力,将同一浏览器上同一用户的请求,都定向发送到固定服务器上,让这个服务器处理该用户的所有请求,这样只要这个服务器上保存了用户Session,就能保证用户的状态一致性。但是这个方案依赖于负载均衡器,而且只适用于横向扩展的集群场景,不能满足分布式场景。

二、微服务架构下的Session管理

微服务架构是将一个应用拆分成一套小而相互关联的微服务,微服务之间通过暴露出来的API被其他微服务或系统所调用。在运行时 ,每个微服务实例通常是一个云虚拟机或者一个Docker。众多微服务综合起来,构成了一个完整的微服务架构应用。

微服务架构中的微服务一般可以分为两类:无状态服务和有状态服务。无状态服务比如应用服务器提供的公共服务,通常不保存数据,方便进行横向扩展。有状态服务则需要进行数据存储,例如数据库服务和缓存服务。在Web应用中,Session用来存储用户状态信息,所以Session管理也是有状态服务的一种。

微服务架构可以近似地看做是一个大型的分布式架构系统,但是与分布式架构相比,微服务架构让应用模块的划分更为精细,每个微应用大小合适,方便进行维护和管理。通过使用devops平台,可以让微服务模块的开发部署变得很敏捷

当应用由十几个甚至数十个部署在不同节点上的微服务组成时,如果还是沿用分布式架构中的Session管理方案,将会让Session管理的复杂度直线上升,同时很难保证整个架构中Session数据的一致性。

因此,在微服务架构下的Session管理,我们应该另辟蹊径,不再将Session对象保存在服务器的内存里,而是在应用架构中引入独立的中间存储介质,将整个应用架构中的Session对象进行统一管理。

个人认为,一个好的Session集中管理方案,应该具备以下4个特点:

  • 中间存储介质的读写速度要快。因为使用了Session集中管理后,将会在Session的读写操作中引入网络传输,与保存在服务器本地内存相比,读写速率会有所下降,所以必须保证中间存储介质的读写速度。
  • 中间存储介质要高可用。整个应用架构中的Session对象都将被保存在中间存储介质中,如果不能保证存储介质的高可用,整个应用都将变得不稳定。
  • Session管理方案要保证对用户的透明性,切换成集中管理后 ,对用户的使用应该是不会与影响的,用户使用的时候对方案改变无感知。
  • 管理方案不该和某一应用服务器耦合,应该适用于所有常规应用服务器。

从上述特点可以看出,Session集中管理的技术选型,应该从Session存储介质和管理方案实现两方面进行考虑。

三、Session管理实践分享

因为Session存储介质需要有较高的读写性能,所以应该选择缓存服务器作为存储介质。我们在进行微服务Session管理实践的时候,对目前业内常用的两种缓存服务器,Redis和Memcache,进行了对比,准备在两者之中选一个合适的缓存服务器来进行Session存储。

从表中的数据可能看出,虽然Redis的读写性能稍弱于Memcache,但是Redis支持的数据类型较多,而且支持数据的持久化。

此外,Memcache使用Slab Allocation机制进行内存管理,通过将内存分隔成特定长度块来解决内存碎片问题。同时Memcache采用最近最少使用(LRU)算法对slab进行内存回收。这就意味着,如果所有Session对象的大小大致相同,将会被Memcache存放在大小合适的slab中进行存储,一但这些slab被存满,再有新的数据进来,里面的存放的时间相对较早的Session对象就会被清除,导致用户变成未登录状态。

对比之后发现Redis更加适合用于Session存储。而且Redis3.0之后,提供了良好的主从复制和集群能力,能够很好地保证Session存储的高可用。Redis还提供了数据失效和订阅通知的能力,能为Session共享提供良好的支撑。

在Session集中管理方案的实现上,目前常用的方案有两种,一种是Memcache-Tomcat-Session,另一种是Spring Session。

Memcache-Tomcat-Session是一个基于Memcache和Tomcat实现Session集中管理的开源方案,通过修改Tomcat的server.xml文件,使用扩展的SessionManager替换Tomcat原有的Session管理器来实现集中管理。这个方案实现起来比较简单,但是与Tomcat耦合,不适用于其他应用服务器。

Spring Session是Spring提供的一套Session管理方案,通过一个SessionFilter将所有访问应用的请求都拦截下来,然后使用Request包装类接管Session管理。SpringSession不与应用服务器耦合,能适用于常规服务器。同时还提供了在浏览器下对同一应用存储多个Session等功能。

SpringSession优点颇多,所以开始的时候我们曾尝试将SpringSession集成到公司产品中来,进行Session集中管理,但在集成过程中考虑到以下几点,最终放弃了集成。

  • SpringSession功能丰富,但我们并不是都需要。
  • SpringSession的实现代码量较多,还需要配合Spring-data-redis进行使用。如果后续要对Session管理的代码进行修改维护,需要把SpringSession的代码都梳理一遍,学习维护成本比较高。

所以最终我们决定使用Redis作为Session的存储介质,然后参考SpringSession的实现理念,自己设计开发一套轻量级的Session集中管理实现。

同样使用SessionFilter进行用户请求拦截,然后通过Request包装类接管应用服务器的Session管理。在Request包装类中重写getSession方法。让用户在进行Session读写的时候去Redis中进行操作,而且使用Session的方法与过去一样,使得管理方案对用户透明。

在Session共享模块与Redis之间,基于jedis开发了一个分布式缓存SDK,用于进行通信,同时SDK可以提供扩展性,后续如果需要支持其他的缓存服务器,只要对SDK进行扩展开发即可。

然后为了保证Session集中管理方案的高可用,将会搭建Redis集群来存储Session对象。

这是一个推荐客户搭建的最小Redis集群,集群中共有4个Redis节点,两主两从。两个Master节点用来对Session数据进行分片存储,而Slaver节点用来对Matser进行数据备份和读写分离。

总结

maven filter和resource

1. 利用filter实现对资源文件(resouces)过滤


maven filter可利用指定的xxx.properties中对应的key=value对资源文件中的${key}进行替换,最终把你的资源文件中的username=${key}替换成username=val

       <!-- 过滤器,用于过滤resource中的各个文件 --> 
        <filters>
            <filter>src/main/resources/filtersTest.properties</filter>
        </filters>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <!-- 是否使用过滤器 -->
                <filtering>true</filtering>
            </resource>
        </resources>

2. 利用profile来切换环境

<profiles>
    <profile>
        <id>dev</id>

        <!-- 默认激活开发配制,使用config-dev.properties来替换设置过虑的资源文件中的${key} -->
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <build>
            <filters>
                <filter>config-dev.properties</filter>
            </filters>
        </build>
    </profile>
    <profile>
        <id>test</id>
        <build>
            <filters>
                <filter>config-dev.properties</filter>
            </filters>
        </build>
    </profile>
    <profile>
        <id>product</id>
        <build>
            <filters>
                <filter>config-product.properties</filter>
            </filters>
        </build>
    </profile>
</profiles>

3. 命令


maven clean install -Ptest — 激活id=”test”的profile