实现思路:

一、制作模板

1、在word中无非三种格式,文字、图片、表格,目前我所涉及到的业务中只有这三个,其他情况没涉及到没研究,首先需要准备一个模板文件,即xml格式的模板,通过打开一个空白的word文档,另存为xml文件,即可得到一个空白的word模板(可使用notepad++工具打开)

2、获取到空白文档的模板后,再新建一个word,填充文字,再另存为xml,打开并对比之前空白的模板之间的差异,可以找出添加文字后加了哪些代码。如果需要表格,则在空白文档加入加入表格,然后保存为xml文件打开查看代码,对比差异,可以知道具体的代码代表的意思。

3、图片方面的处理,同样是在空白文档中添加图片,然后查看xml代码,其中图片是以base64形式出现的,在替换图片的过程中,是需要将图片的base64码进行替换,所有的需要动态改变的数据,都使用freemarker标签的形式替换,如果不了解的,自行去了解一下freemarker标签的使用,具体的在xml中的代码的代表意思,可以到百度查找。

二、填充模板

1、后台使用jsoup解析HTML代码后,获取html代码中的值,保存到map中。文字段落,图片,表格,可分开处理。解析的HTML代码是通过百度UEditor生成的代码,如果是需要解析完整的正规的html代码,需要另外写解析标签的代码。

2、解析HTML时,可对应保存HTML中标签存在的属性,对应xml中的属性,通过实体来进行设置,遍历标签时,获取实体属性即可

3、填充模板保存后的文件仍然是xml格式的文件,需要另外处理,将文件另存为docx格式的word文档

 

实现代码:

注意:代码仅可以作为参考,即使完全复制,也不一定适合你,仅仅提供一个思路和参考,是否值得借鉴,需要自己评估,或者有更好的方法,欢迎留言评论一起交流

模板代码:(xml模板的代码,只贴出body中的代码)

<w:body>
		<wx:sect>
			<!-- 判断第一部分是文字段落,并遍历第一部分的段落 -->
			<#if part1 == "paragraph">
			<#list paragraphList1 as paragraph>
			<w:p wsp:rsidR="0050577F" wsp:rsidRPr="00177379" wsp:rsidRDefault="00177379">
				<w:pPr>
					<w:jc w:val="${paragraph.align}"/>
					<w:rPr>
						<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
						<wx:font wx:val="宋体"/>
						<w:color w:val="${paragraph.color}"/>
						<#if paragraph_index==0>
						<w:sz w:val="30"/>
						<w:sz-cs w:val="30"/>
						<#else>
						<w:sz w:val="${paragraph.size}"/>
						<w:sz-cs w:val="${paragraph.size}"/>
						</#if>
					</w:rPr>
					<w:spacing w:line="${paragraph.lineHeight}" w:line-rule="auto"/>
				</w:pPr>
				<!-- 遍历段落中的wr,每个wr可定义对应的文字属性,如果内容不为空,则执行文字遍历循环 -->
				<#list paragraph.wrList as wr>
				<#if wr.content??>
				<w:r>
					<w:rPr>
						<w:rFonts w:ascii="${wr.font}" w:fareast="${wr.font}" w:h-ansi="${wr.font}" w:hint="fareast"/>
						<wx:font wx:val="${wr.font}"/>
						<w:color w:val="${wr.color}"/>
						<#if paragraph_index==0>
						<w:sz w:val="30"/>
						<w:sz-cs w:val="30"/>
						<#else>
						<w:sz w:val="${paragraph.size}"/>
						<w:sz-cs w:val="${paragraph.size}"/>
						</#if>
						${wr.bold}
						${wr.tilt}
						${wr.underLine}
					</w:rPr>
					<w:t>${wr.content}</w:t>
				</w:r>
				</#if>
				<!-- 如果是图片,则在wr上添加图片 -->
				<#if wr.hasImg == 1>
				<#list wr.imgList as image>
				<w:r wsp:rsidRPr="006E22D7">
					<w:rPr>
						<w:noProof/>
					</w:rPr>
					<w:pict>
						<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
							<v:stroke joinstyle="miter"/>
							<v:formulas>
								<v:f eqn="if lineDrawn pixelLineWidth 0"/>
								<v:f eqn="sum @0 1 0"/>
								<v:f eqn="sum 0 0 @1"/>
								<v:f eqn="prod @2 1 2"/>
								<v:f eqn="prod @3 21600 pixelWidth"/>
								<v:f eqn="prod @3 21600 pixelHeight"/>
								<v:f eqn="sum @0 0 1"/>
								<v:f eqn="prod @6 1 2"/>
								<v:f eqn="prod @7 21600 pixelWidth"/>
								<v:f eqn="sum @8 21600 0"/>
								<v:f eqn="prod @7 21600 pixelHeight"/>
								<v:f eqn="sum @10 21600 0"/>
							</v:formulas>
							<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
							<o:lock v:ext="edit" aspectratio="t"/>
						</v:shapetype>
						<w:binData w:name="wordml://${image.imgName}.png" xml:space="preserve">${image.imgBase64}</w:binData>
						<v:shape id="${image.imgId}" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:${image.width}pt;height:${image.height}pt;visibility:visible;mso-wrap-style:square">
							<v:imagedata src="wordml://${image.imgName}.png" o:title="${image.imgName}"/>
						</v:shape>
					</w:pict>
				</w:r>
				</#list>
				</#if>
				</#list>
			</w:p>
			</#list>
			</#if>
			<!-- 如果第一部分是表格,则填充表格 -->
			<#if part1 == "table">
			<w:tbl>
				<w:tblPr>
					<w:tblW w:w="8522" w:type="dxa"/>
					<w:tblBorders>
						<w:top w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:left w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:bottom w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:right w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:insideH w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:insideV w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
					</w:tblBorders>
					<!-- 设置表格的对齐方式 -->
					<w:tblLook w:val="${table.tblLook}"/>
				</w:tblPr>
				<w:tblGrid>
					<!-- 表格列,定义的表格有多少列,则遍历显示多少个网格 -->
					<#list table.gridColList as gridCol>
					${gridCol}
					</#list>
				</w:tblGrid>
				<!-- 遍历表格中的行,tr -->
				<#list table.trList as tr>
				<w:tr wsp:rsidR="00616293" wsp:rsidRPr="00616293" wsp:rsidTr="00616293">
					<w:trPr>
						<!-- 设置行高属性 -->
						<w:trHeight w:val="${tr.height}"/>
					</w:trPr>
					<!-- 遍历行中的列 -->
					<#list tr.tdList as td>
					<w:tc>
						<w:tcPr>
							<!-- 列宽属性 -->
							<w:tcW w:w="${td.width}" w:type="dxa"/>
							<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
							<w:tcBorders>
								${td.top}
								${td.right}
								${td.bottom}
								${td.left}
							</w:tcBorders>
							${td.gridSpan}
							${td.merge}
						</w:tcPr>
						<!-- 遍历单元格中的段落文字 -->
						<#list td.paragraphList as paragraph>
						<w:p wsp:rsidR="0050577F" wsp:rsidRPr="00177379" wsp:rsidRDefault="00177379">
							<w:pPr>
								<!-- 设置单元格中段落的属性 -->
								<w:jc w:val="${paragraph.align}"/>
								<w:rPr>
									<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
									<wx:font wx:val="宋体"/>
									<w:color w:val="${paragraph.color}"/>
									<#if tr_index==0>
									<w:sz w:val="30"/>
									<w:sz-cs w:val="30"/>
									<#else>
									<w:sz w:val="${paragraph.size}"/>
									<w:sz-cs w:val="${paragraph.size}"/>
									</#if>
								</w:rPr>
								<w:spacing w:line="${paragraph.lineHeight}" w:line-rule="auto"/>
							</w:pPr>
							<!-- 遍历段落中的wr -->
							<#list paragraph.wrList as wr>
							<!-- 如果内容不为空,则执行文字遍历循环 -->
							<#if wr.content??>
							<w:r>
								<w:rPr>
									<w:rFonts w:ascii="${wr.font}" w:fareast="${wr.font}" w:h-ansi="${wr.font}" w:hint="fareast"/>
									<wx:font wx:val="${wr.font}"/>
									<w:color w:val="${wr.color}"/>
									<#if tr_index==0>
									<w:sz w:val="30"/>
									<w:sz-cs w:val="30"/>
									<#else>
									<w:sz w:val="${paragraph.size}"/>
									<w:sz-cs w:val="${paragraph.size}"/>
									</#if>
									${wr.bold}
									${wr.tilt}
									${wr.underLine}
								</w:rPr>
								<w:t>${wr.content}</w:t>
							</w:r>
							</#if>
							<!-- 如果是图片,则在wr上添加图片 -->
							<#if wr.hasImg == 1>
							<!-- 遍历图片 -->
							<#list wr.imgList as image>
							<w:r wsp:rsidRPr="006E22D7">
								<w:rPr>
									<w:noProof/>
								</w:rPr>
								<w:pict>
									<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
										<v:stroke joinstyle="miter"/>
										<v:formulas>
											<v:f eqn="if lineDrawn pixelLineWidth 0"/>
											<v:f eqn="sum @0 1 0"/>
											<v:f eqn="sum 0 0 @1"/>
											<v:f eqn="prod @2 1 2"/>
											<v:f eqn="prod @3 21600 pixelWidth"/>
											<v:f eqn="prod @3 21600 pixelHeight"/>
											<v:f eqn="sum @0 0 1"/>
											<v:f eqn="prod @6 1 2"/>
											<v:f eqn="prod @7 21600 pixelWidth"/>
											<v:f eqn="sum @8 21600 0"/>
											<v:f eqn="prod @7 21600 pixelHeight"/>
											<v:f eqn="sum @10 21600 0"/>
										</v:formulas>
										<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
										<o:lock v:ext="edit" aspectratio="t"/>
									</v:shapetype>
									<!-- 设置图片base64字符编码 -->
									<w:binData w:name="wordml://${image.imgName}.png" xml:space="preserve">${image.imgBase64}</w:binData>
									<!-- 设置图片属性 -->
									<v:shape id="${image.imgId}" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:${image.width}pt;height:${image.height}pt;visibility:visible;mso-wrap-style:square">
										<v:imagedata src="wordml://${image.imgName}.png" o:title="${image.imgName}"/>
									</v:shape>
								</w:pict>
							</w:r>
							</#list>
							</#if>
							</#list>
						</w:p>
						</#list>
					</w:tc>
					</#list>
				</w:tr>
				</#list>
			</w:tbl>
			</#if>
			<!-- 判断第二部分是文字段落,并遍历第一部分的段落 -->
			<#if part2 == "paragraph">
			<#list paragraphList2 as paragraph>
			<w:p wsp:rsidR="0050577F" wsp:rsidRPr="00177379" wsp:rsidRDefault="00177379">
				<w:pPr>
					<w:jc w:val="${paragraph.align}"/>
					<w:rPr>
						<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
						<wx:font wx:val="宋体"/>
						<w:color w:val="${paragraph.color}"/>
						<#if paragraph_index==0>
						<w:sz w:val="30"/>
						<w:sz-cs w:val="30"/>
						<#else>
						<w:sz w:val="${paragraph.size}"/>
						<w:sz-cs w:val="${paragraph.size}"/>
						</#if>
					</w:rPr>
					<w:spacing w:line="${paragraph.lineHeight}" w:line-rule="auto"/>
				</w:pPr>
				<!-- 遍历段落中的wr,每个wr可定义对应的文字属性,如果内容不为空,则执行文字遍历循环 -->
				<#list paragraph.wrList as wr>
				<#if wr.content?? >
				<w:r>
					<w:rPr>
						<w:rFonts w:ascii="${wr.font}" w:fareast="${wr.font}" w:h-ansi="${wr.font}" w:hint="fareast"/>
						<wx:font wx:val="${wr.font}"/>
						<w:color w:val="${wr.color}"/>
						<#if paragraph_index==0>
						<w:sz w:val="30"/>
						<w:sz-cs w:val="30"/>
						<#else>
						<w:sz w:val="${paragraph.size}"/>
						<w:sz-cs w:val="${paragraph.size}"/>
						</#if>
						${wr.bold}
						${wr.tilt}
						${wr.underLine}
					</w:rPr>
					<w:t>${wr.content}</w:t>
				</w:r>
				</#if>
				<!-- 如果是图片,则在wr上添加图片 -->
				<#if wr.hasImg == 1>
				<#list wr.imgList as image>
				<w:r wsp:rsidRPr="006E22D7">
					<w:rPr>
						<w:noProof/>
					</w:rPr>
					<w:pict>
						<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
							<v:stroke joinstyle="miter"/>
							<v:formulas>
								<v:f eqn="if lineDrawn pixelLineWidth 0"/>
								<v:f eqn="sum @0 1 0"/>
								<v:f eqn="sum 0 0 @1"/>
								<v:f eqn="prod @2 1 2"/>
								<v:f eqn="prod @3 21600 pixelWidth"/>
								<v:f eqn="prod @3 21600 pixelHeight"/>
								<v:f eqn="sum @0 0 1"/>
								<v:f eqn="prod @6 1 2"/>
								<v:f eqn="prod @7 21600 pixelWidth"/>
								<v:f eqn="sum @8 21600 0"/>
								<v:f eqn="prod @7 21600 pixelHeight"/>
								<v:f eqn="sum @10 21600 0"/>
							</v:formulas>
							<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
							<o:lock v:ext="edit" aspectratio="t"/>
						</v:shapetype>
						<w:binData w:name="wordml://${image.imgName}.png" xml:space="preserve">${image.imgBase64}</w:binData>
						<v:shape id="${image.imgId}" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:${image.width}pt;height:${image.height}pt;visibility:visible;mso-wrap-style:square">
							<v:imagedata src="wordml://${image.imgName}.png" o:title="${image.imgName}"/>
						</v:shape>
					</w:pict>
				</w:r>
				</#list>
				</#if>
				
				</#list>
			</w:p>
			</#list>
			</#if>
			<!-- 如果第二部分是表格,则填充表格 -->
			<#if part2 == "table">
			<w:tbl>
				<w:tblPr>
					<w:tblW w:w="8522" w:type="dxa"/>
					<w:tblBorders>
						<w:top w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:left w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:bottom w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:right w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:insideH w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:insideV w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
					</w:tblBorders>
					<!-- 设置表格的对齐方式 -->
					<w:tblLook w:val="${table.tblLook}"/>
				</w:tblPr>
				<w:tblGrid>
					<!-- 表格列,定义的表格有多少列,则遍历显示多少个网格 -->
					<#list table.gridColList as gridCol>
					${gridCol}
					</#list>
				</w:tblGrid>
				<!-- 遍历表格中的行,tr -->
				<#list table.trList as tr>
				<w:tr wsp:rsidR="00616293" wsp:rsidRPr="00616293" wsp:rsidTr="00616293">
					<w:trPr>
						<!-- 设置行高属性 -->
						<w:trHeight w:val="${tr.height}"/>
					</w:trPr>
					<!-- 遍历行中的列 -->
					<#list tr.tdList as td>
					<w:tc>
						<w:tcPr>
							<!-- 列宽属性 -->
							<w:tcW w:w="${td.width}" w:type="dxa"/>
							<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
							<w:tcBorders>
								${td.top}
								${td.right}
								${td.bottom}
								${td.left}
							</w:tcBorders>
							${td.gridSpan}
							${td.merge}
						</w:tcPr>
						<!-- 遍历单元格中的段落文字 -->
						<#list td.paragraphList as paragraph>
						<w:p wsp:rsidR="0050577F" wsp:rsidRPr="00177379" wsp:rsidRDefault="00177379">
							<w:pPr>
								<!-- 设置单元格中段落的属性 -->
								<w:jc w:val="${paragraph.align}"/>
								<w:rPr>
									<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
									<wx:font wx:val="宋体"/>
									<w:color w:val="${paragraph.color}"/>
									<w:sz w:val="${paragraph.size}"/>
									<w:sz-cs w:val="${paragraph.size}"/>
								</w:rPr>
								<!-- 设置行间距 -->
								<w:spacing w:line="${paragraph.lineHeight}" w:line-rule="auto"/>
							</w:pPr>
							<!-- 遍历段落中的wr -->
							<#list paragraph.wrList as wr>
							<!-- 如果内容不为空,则执行文字遍历循环 -->
							<#if wr.content??>
							<w:r>
								<w:rPr>
									<w:rFonts w:ascii="${wr.font}" w:fareast="${wr.font}" w:h-ansi="${wr.font}" w:hint="fareast"/>
									<wx:font wx:val="${wr.font}"/>
									<w:color w:val="${wr.color}"/>
									<w:sz w:val="${wr.size}"/>
									<w:sz-cs w:val="${wr.size}"/>
									${wr.bold}
									${wr.tilt}
									${wr.underLine}
								</w:rPr>
								<w:t>${wr.content}</w:t>
							</w:r>
							</#if>
							<!-- 如果是图片,则在wr上添加图片 -->
							<#if wr.hasImg == 1>
							<!-- 遍历图片 -->
							<#list wr.imgList as image>
							<w:r wsp:rsidRPr="006E22D7">
								<w:rPr>
									<w:noProof/>
								</w:rPr>
								<w:pict>
									<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
										<v:stroke joinstyle="miter"/>
										<v:formulas>
											<v:f eqn="if lineDrawn pixelLineWidth 0"/>
											<v:f eqn="sum @0 1 0"/>
											<v:f eqn="sum 0 0 @1"/>
											<v:f eqn="prod @2 1 2"/>
											<v:f eqn="prod @3 21600 pixelWidth"/>
											<v:f eqn="prod @3 21600 pixelHeight"/>
											<v:f eqn="sum @0 0 1"/>
											<v:f eqn="prod @6 1 2"/>
											<v:f eqn="prod @7 21600 pixelWidth"/>
											<v:f eqn="sum @8 21600 0"/>
											<v:f eqn="prod @7 21600 pixelHeight"/>
											<v:f eqn="sum @10 21600 0"/>
										</v:formulas>
										<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
										<o:lock v:ext="edit" aspectratio="t"/>
									</v:shapetype>
									<!-- 设置图片base64字符编码 -->
									<w:binData w:name="wordml://${image.imgName}.png" xml:space="preserve">${image.imgBase64}</w:binData>
									<!-- 设置图片属性 -->
									<v:shape id="${image.imgId}" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:${image.width}pt;height:${image.height}pt;visibility:visible;mso-wrap-style:square">
										<v:imagedata src="wordml://${image.imgName}.png" o:title="${image.imgName}"/>
									</v:shape>
								</w:pict>
							</w:r>
							</#list>
							</#if>
							</#list>
						</w:p>
						</#list>
					</w:tc>
					</#list>
				</w:tr>
				</#list>
			</w:tbl>
			</#if>
			<!-- 判断第三部分是文字段落,并遍历第一部分的段落 -->
			<#if part3?? && part3 == "paragraph">
			<#list paragraphList3 as paragraph>
			<w:p wsp:rsidR="0050577F" wsp:rsidRPr="00177379" wsp:rsidRDefault="00177379">
				<w:pPr>
					<w:jc w:val="${paragraph.align}"/>
					<w:rPr>
						<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
						<wx:font wx:val="宋体"/>
						<w:color w:val="${paragraph.color}"/>
						<#if paragraph_index==0>
						<w:sz w:val="30"/>
						<w:sz-cs w:val="30"/>
						<#else>
						<w:sz w:val="${paragraph.size}"/>
						<w:sz-cs w:val="${paragraph.size}"/>
						</#if>
					</w:rPr>
					<w:spacing w:line="${paragraph.lineHeight}" w:line-rule="auto"/>
				</w:pPr>
				<!-- 遍历段落中的wr,每个wr可定义对应的文字属性,如果内容不为空,则执行文字遍历循环 -->
				<#list paragraph.wrList as wr>
				<#if wr.content??>
				<w:r>
					<w:rPr>
						<w:rFonts w:ascii="${wr.font}" w:fareast="${wr.font}" w:h-ansi="${wr.font}" w:hint="fareast"/>
						<wx:font wx:val="${wr.font}"/>
						<w:color w:val="${wr.color}"/>
						<#if paragraph_index==0>
						<w:sz w:val="30"/>
						<w:sz-cs w:val="30"/>
						<#else>
						<w:sz w:val="${paragraph.size}"/>
						<w:sz-cs w:val="${paragraph.size}"/>
						</#if>
						${wr.bold}
						${wr.tilt}
						${wr.underLine}
					</w:rPr>
					<w:t>${wr.content}</w:t>
				</w:r>
				</#if>
				<!-- 如果是图片,则在wr上添加图片 -->
				<#if wr.hasImg == 1>
				<#list wr.imgList as image>
				<w:r wsp:rsidRPr="006E22D7">
					<w:rPr>
						<w:noProof/>
					</w:rPr>
					<w:pict>
						<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
							<v:stroke joinstyle="miter"/>
							<v:formulas>
								<v:f eqn="if lineDrawn pixelLineWidth 0"/>
								<v:f eqn="sum @0 1 0"/>
								<v:f eqn="sum 0 0 @1"/>
								<v:f eqn="prod @2 1 2"/>
								<v:f eqn="prod @3 21600 pixelWidth"/>
								<v:f eqn="prod @3 21600 pixelHeight"/>
								<v:f eqn="sum @0 0 1"/>
								<v:f eqn="prod @6 1 2"/>
								<v:f eqn="prod @7 21600 pixelWidth"/>
								<v:f eqn="sum @8 21600 0"/>
								<v:f eqn="prod @7 21600 pixelHeight"/>
								<v:f eqn="sum @10 21600 0"/>
							</v:formulas>
							<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
							<o:lock v:ext="edit" aspectratio="t"/>
						</v:shapetype>
						<w:binData w:name="wordml://${image.imgName}.png" xml:space="preserve">${image.imgBase64}</w:binData>
						<v:shape id="${image.imgId}" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:${image.width}pt;height:${image.height}pt;visibility:visible;mso-wrap-style:square">
							<v:imagedata src="wordml://${image.imgName}.png" o:title="${image.imgName}"/>
						</v:shape>
					</w:pict>
				</w:r>
				</#list>
				</#if>
				</#list>
			</w:p>
			</#list>
			</#if>
			<w:sectPr wsp:rsidR="0050577F" wsp:rsidRPr="00177379">
				<w:pgSz w:w="11906" w:h="16838"/>
				<w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851" w:footer="992" w:gutter="0"/>
				<w:cols w:space="425"/>
				<w:docGrid w:type="lines" w:line-pitch="312"/>
			</w:sectPr>
		</wx:sect>
	</w:body>

解析html代码:

/**
 * 解析word
 * @Description: 
 *
 * @Date 2018年7月31日 
 * @author lxs
 * @version 2.1.4
 * 
 */
public class ParseWordUtil {
	public static Map<String, Object> getDataMap(Map<String, String> partMap, 
			Map<String, List<Map<String, String>>> sealMap, List<String> imgVariable) 
					throws IOException, BadElementException{
		// 填充word的数据
		Map<String,Object> dataMap = new HashMap<String, Object>();
		// 根据标签的不连续,区分部分
		for(int i = 0; i < partMap.size(); i++){
			String partContent = partMap.get("part"+(i+1));
			List<WParagraph> paragraphList = null;
			Table table = new Table();
			// 获取p标签
			if(partContent.startsWith("<p")){
				// 传入部分HTML代码,将内容解析为word文档的段落文本
				paragraphList = ParseWordUtil.getParagraphList(partContent, sealMap, imgVariable);
			} 
			// 获取table标签
			else if(partContent.startsWith("<table")){
				Document subDoc = Jsoup.parseBodyFragment(partContent);
				Elements e = subDoc.select("tr");
				// 获取td列表的列数
				List<String> gridColList = ParseWordUtil.getGridColList(e);
				int cellSize = 0;
				if(gridColList != null && gridColList.size() > 0){
					cellSize = gridColList.size();
				}
				// 获取tr列表
				List<Tr> trList = ParseWordUtil.getTrList(e, cellSize, sealMap, imgVariable);
				// 设置table属性
				table.setGridColList(gridColList);
				table.setTrList(trList);
			}

			if(partContent.startsWith("<p")){
				dataMap.put("part"+(i+1), "paragraph");
				dataMap.put("paragraphList"+(i+1), paragraphList);
			} else if(partContent.startsWith("<table")){
				dataMap.put("part"+(i+1), "table");
				dataMap.put("table", table);
			}
		}
		return dataMap;
	}

	/**
	 * 获取html部分内容,根据段落和表格区分部分
	 * @Description:
	 * @param childNodes
	 * @return 
	 * @author lxs
	 * @date 2018年7月31日
	 */
	public static Map<String, String> getPartMap(List<Node> childNodes){
		Map<String, String> partMap = new HashMap<String,String>();
		List<String> tarFlag = new ArrayList<String>();
		int changeFlag = 1;
		// 遍历子标签
		for (Node node : childNodes) {
			if(node.nodeName().trim().equals("#text")){
				continue;
			}
			tarFlag.add(node.nodeName());
			if(tarFlag.size() > 1){
				//判断,最后一个是否和上一个标签一致,不一致时,改变标志+1
				if(!(tarFlag.get(tarFlag.size()-1).equals(tarFlag.get(tarFlag.size()-2)))){
					++ changeFlag;
				}
			}
			// 如果是p标签
			if(node.toString().startsWith("<p")){
				if(partMap.get("part"+changeFlag) == null){
					partMap.put("part"+changeFlag, "");
				}
				partMap.put("part"+changeFlag, partMap.get("part"+changeFlag) + node.toString());
			}
			// 如果是table标签
			else if(node.toString().startsWith("<table")){
				if(partMap.get("part"+changeFlag) == null){
					partMap.put("part"+changeFlag, "");
				}
				partMap.put("part"+changeFlag, partMap.get("part"+changeFlag) + node.toString());
			}
		}
		return partMap;
	}

	/**
	 * 传入部分HTML标签的代码,返回段落列表文本
	 * @Description:
	 * @param subHtml
	 * @return 
	 * @author lxs
	 * @throws IOException 
	 * @throws BadElementException 
	 * @date 2018年7月30日
	 */
	public static List<WParagraph> getParagraphList(String subHtml, 
			Map<String, List<Map<String, String>>> sealMap, List<String> imgVariable) 
					throws IOException, BadElementException{
		List<WParagraph> paragraphList = new ArrayList<WParagraph>();
		// 解析文档,获取所有p标签
		Document subDoc = Jsoup.parseBodyFragment(subHtml);
		List<Node> nodeP = subDoc.body().childNodes();
		// 遍历所有p标签
		for (Node node : nodeP) {
			if(node.nodeName().equals("#text")){
				continue;
			}
			WParagraph paragraph = new WParagraph();
			// 获取p标签的style属性
			String pStyle = node.attr("style");
			if(pStyle != null && pStyle != ""){
				// 找到字体对齐方式,
				int alignStart = pStyle.indexOf("text-align:");
				int alignEnd = pStyle.indexOf(";", alignStart);
				String align = "";
				// 设置word段落的对齐方式
				if(alignStart > -1 && alignEnd > -1){
					align = pStyle.substring(alignStart+"text-align:".length(), alignEnd);
					paragraph.setAlign(align.trim());

				} else if(alignStart > -1 && alignEnd == -1){
					align = pStyle.substring(alignStart+"text-align:".length());
					paragraph.setAlign(align.trim());
				}
			}
			// 解析单个p标签
			List<Wr> wrList = getWrList(node.toString(), sealMap, imgVariable);
			if(wrList == null || wrList.size() == 0){
				continue;
			}
			// word段落设置 w:r列表
			paragraph.setWrList(wrList);
			// 设置段落列表
			paragraphList.add(paragraph);
		}
		return paragraphList;
	} 

	/**
	 * 获取列数量
	 * @Description:
	 * @param tdNum
	 * @return 
	 * @author lxs
	 * @date 2018年7月30日
	 */
	public static List<String> getGridColList(Elements e) {
		// 获取表格中的列数
		int tdNum = 0;
		for (Element element : e) {
			int cellNums = 0;
			for (Node tdNode : element.childNodes()) {
				if(tdNode.nodeName().equals("#text")){
					continue;
				}
				cellNums ++;
			}
			if(cellNums >= tdNum){
				tdNum = cellNums;
				cellNums = 0;
			}
		}
		if(tdNum == 0){
			return null;
		}
		final int tableWidth = 9800;
		int colWidth = tableWidth/tdNum;
		List<String> gridColList = new ArrayList<String>();
		for (int i = 0; i < tdNum; i++) {
			gridColList.add("<w:gridCol w:w=\""+colWidth+"\"/>");
		}
		return gridColList;
	}

	/**
	 * 获取tr列表
	 * @Description:
	 * @param e
	 * @param tdWidth
	 * @return 
	 * @author lxs
	 * @throws IOException 
	 * @throws BadElementException 
	 * @date 2018年7月30日
	 */
	public static List<Tr> getTrList(Elements e, int cellSize, Map<String, 
			List<Map<String, String>>> sealMap, List<String> imgVariable) 
					throws IOException, BadElementException {
		List<Tr> trList = new ArrayList<Tr>();
		// 遍历表格tr
		for (Element element : e) {
			// 如果tr没有子节点则不处理
			if(element.children().size() == 0){
				continue;
			}
			Tr tr = new Tr();
			// 获取tr的td列表,并设置td列表
			List<Td> tdList = getTdList(element, cellSize, sealMap, imgVariable);
			tr.setTdList(tdList);
			// 设置tr列表
			trList.add(tr);
		}
		return trList;
	}

	/**
	 * 根据tr标签,获取一行的td列表
	 * @Description:
	 * @param element
	 * @return 
	 * @author lxs
	 * @throws IOException 
	 * @throws BadElementException 
	 * @date 2018年7月30日
	 */
	public static List<Td> getTdList(Element element, int cellSize, 
			Map<String, List<Map<String, String>>> sealMap, List<String> imgVariable) 
					throws IOException, BadElementException {
		List<Node> childTd = element.childNodes();
		List<Td> tdList = new ArrayList<Td>();
		int tdWidth = 9800/cellSize;
		// 遍历tr中的td
		for (Node tdNode : childTd) {
			if(tdNode.nodeName().equals("#text")){
				continue;
			}
			Td td = new Td();
			// 设置单元格宽度
			td.setWidth(tdWidth+"");
			// 设置单元格合并属性
			if(tdNode.hasAttr("colspan")){
				String colSpan = tdNode.attr("colspan");
				td.setGridSpan("<w:gridSpan w:val=\""+ colSpan +"\"/>");
			}
			String tdStyle = tdNode.attr("style");
			if(tdStyle != null && tdStyle != ""){
				String[] styleArr = tdStyle.split(";");
				for (String str : styleArr) {
					if(str.contains("border-top")){
						int index = str.indexOf(":");
						if(str.substring(index+1).trim().equals("none")){
							td.setTop("<w:top w:val=\"nil\"/>");
						}
					}
					if(str.contains("border-right")){
						int index = str.indexOf(":");
						if(str.substring(index+1).trim().equals("none")){
							td.setRight("<w:right w:val=\"nil\"/>");
						}
					}
					if(str.contains("border-bottom")){
						int index = str.indexOf(":");
						if(str.substring(index+1).trim().equals("none")){
							td.setBottom("<w:bottom w:val=\"nil\"/>");
						}
					}
					if(str.contains("border-left")){
						int index = str.indexOf(":");
						if(str.substring(index+1).trim().equals("none")){
							td.setLeft("<w:left w:val=\"nil\"/>");
						}
					}
				}
			}
			// 获取td中的所有标签
			List<Node> childP = tdNode.childNodes();
			// 如果td没有p标签
			Document spanDoc = Jsoup.parseBodyFragment(tdNode.toString());
			// 查找td中的所有p标签,不存在p标签,则另外处理
			Elements pElement = spanDoc.select("p");
			if(pElement.size() == 0){
				List<WParagraph> subParagraphList = getSubParagraphList(childP, sealMap, imgVariable);
				td.setParagraphList(subParagraphList);
				tdList.add(td);
				continue;
			}
			
			List<WParagraph> paragraphList = getParagraphList(childP.toString(), sealMap, imgVariable);
			// td 段落列表
			td.setParagraphList(paragraphList);
			tdList.add(td);
		}
		// 行设置多个单元格列表
		return tdList;
	}

	/**
	 * 处理td中不存在p标签的数据
	 * @Description:
	 * @param tdChilds td下的子标签
	 * @param sealMap 图片列表
	 * @param imgVariable 图片变量
	 * @return 
	 * @author lxs
	 * @throws IOException 
	 * @throws BadElementException 
	 * @date 2018年8月2日
	 */
	public static List<WParagraph> getSubParagraphList(List<Node> tdChilds,
			Map<String, List<Map<String, String>>> sealMap,
			List<String> imgVariable) throws BadElementException, IOException {
		List<Wr> wrList = getWrList(tdChilds.toString(), sealMap, imgVariable);
		List<WParagraph> paragraphList = new ArrayList<WParagraph>();
		// 当获取未获取到其他标签内容时,尝试获取td中的文本内容
		if(wrList.size() != 0){
			WParagraph paragraph  = new WParagraph();
			paragraph.setWrList(wrList);
			paragraphList.add(paragraph);
		}else{
			for (Node nodeStr : tdChilds) {
				if(!nodeStr.toString().equals("<br>")){
					Wr wr = new Wr();
					wr.setContent(nodeStr.toString());
					wrList.add(wr);
				}
			}
			WParagraph paragraph  = new WParagraph();
			paragraph.setWrList(wrList);
			paragraphList.add(paragraph);
		}
		return paragraphList;
	}
	
	/**
	 * 解析单个p标签
	 * @Description:
	 * @param pText p标签内容
	 * @param sealMap 图片路径列表
	 * @param imgVariable 图片变量
	 * @return 
	 * @author lxs
	 * @throws IOException 
	 * @throws BadElementException 
	 * @date 2018年7月30日
	 */
	public static List<Wr> getWrList(String pText, 
			Map<String, List<Map<String, String>>> sealMap,
			List<String> imgVariable) 
					throws IOException, BadElementException{
		List<Wr> wrList = new ArrayList<Wr>();
		// 处理p标签中,自身文本内容和标签内容的顺序问题
		String handleText = handleContextOfP(pText);
		Document spanDoc = Jsoup.parseBodyFragment(handleText);
		
		// p标签自身存在内容
		Elements p = spanDoc.select("p");
		if(p.size() > 0){
			String pOwnText = p.get(0).ownText();
			// 清除转义空格,制表符,换行,
			pOwnText = pOwnText.replaceAll("\\s*|\t|\r|\n", "");
			// 清除一般的空格
			pOwnText = pOwnText.replaceAll(" ", "");
			// 清除HTML中 形式的空格
			pOwnText = pOwnText.replaceAll("[\\s\\u00A0]+", "");
			if(pOwnText.length() > 0){
				Wr wr = new Wr();
				wr.setContent(pOwnText);
				wrList.add(wr);
			}
		}
		// 查找该标签下的所有span标签
		Elements spanElement = spanDoc.select("span");
		int spanElementSize = spanElement.size();
		// 存放span列表
		List<Element> spanList = new ArrayList<Element>();
		/** 遍历获取有所span标签列表 **/
		for(int i = 0; i < spanElementSize; i++){
			int spanChilds = spanElement.get(i).childNodes().size();
			Element e = spanElement.get(i);
			// 如果标签的内容为空,则跳过,不解析
			if(e.text().isEmpty() || e.ownText().length() == 0){
				continue;
			}
			// 如果没有子标签,则添加进span列表中
			if(spanChilds <= 1){
				spanList.add(e);
			} 
			// 如果存在子标签
			else if(spanChilds > 1){
				// 先将自身内容取出
				String selfText = e.ownText();
				// 将所有子节点的内容清空,重新设置内容
				e.empty();
				e.text(selfText);
				spanList.add(e);
			}
		}
		/** 遍历span列表,将span中的内容封装到word文档的w:r中 **/
		for (Element span : spanList) {
			// 过滤span元素中,< 开头和 > 结尾的所有内容
			// span元素的父级标签
			String spanParentTag = span.parent().tagName();
			// 存在子标签strong
			if(span.text().contains("<strong>")){
				List<Wr> subWrList = getSubSpan(span);
				wrList.addAll(subWrList);
				continue;
			}
			// w:r为图片变量, 即span的内容为图片的变量
			if(imgVariable.contains(span.text())){
				List<Wr> subWrList = getHasImgSpan(span, sealMap);
				wrList.addAll(subWrList);
				continue;
			}
			// 新建一个w:r对象
			Wr wr = new Wr();
			// 如果父标签为strong,w:r设置加粗
			if(spanParentTag.equals("strong")){
				wr.setBold("<w:b/>");
			}
			//String str = handleStr(span.text());
			wr.setContent(span.text().replace("`", " "));
			wrList.add(wr);
		}
		// 过滤重复标签
		for(int i = 0; i < wrList.size(); i++){
			if(i >= 1){
				if( wrList.get(i).getContent() != null && wrList.get(i).getContent().equals(wrList.get(i-1).getContent())){
					wrList.remove(i);
				}
			}
		}
		return wrList;
	}
	
	/**
	 * 处理存在html空格的字符串
	 * @Description:
	 * @param text
	 * @return 
	 * @author lxs
	 * @date 2018年9月11日
	 */
	/*private static String handleStr(String text) {
		int index = text.indexOf(" ");
		Pattern p = Pattern.compile(" ", Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(text);
		int count = 0;
		while (m.find()) {
			count++;
		}
		StringBuffer sb = new StringBuffer();
		if(count > 6){
			sb.append(text.replace("`", ""));
			sb.insert(0, "  ");
		}else{
			sb.append(text.replace("`", ""));
			sb.insert(0, "       ");
		}
		return sb.toString();
	}*/

	/**
	 * 处理在p标签中存在自身内容和标签内容时,存在的内容顺序混乱问题
	 * @Description:
	 * @param pText
	 * @return 
	 * @author lxs
	 * @date 2018年9月11日
	 */
	private static String handleContextOfP(String pText) {
		Document spanDoc = Jsoup.parseBodyFragment(pText);
		List<Node> childNodes = spanDoc.body().childNodes();
		List<Node> handleNodes = new ArrayList<Node>();
		for (Node node : childNodes) {
			// 若子节点以p标签为开头的,则处理,否则不处理
			if(node.toString().trim().startsWith("<p")){
				for (int i = 0; i< node.childNodeSize(); i++ ) {
					// 如果p的子节点是文本内容,不存在标签,将文本内容用span包含
					if("#text".equals(node.childNode(i).nodeName())){
						if(node.childNode(i).toString().length() <= 0 ){
							continue;
						}
						Element e = new Element("span");
						String nodeText = node.childNode(i).toString().replaceAll("[\\s\\u00A0]+", " ");
						String[] strArr = nodeText.split(";");
						int count = 0;
						for (String str : strArr) {
							if(str.equals("nbsp")){
								count ++;
							}
						}
						if(count <= 6){
							nodeText = nodeText.replaceAll(" ", "`");
						}else{
							/*for(int j = 0; j < 5; j++){
								nodeText = nodeText.replace(" ", "`");
							}*/
							nodeText = nodeText.replaceAll(" ", "`");
						}
						e.appendText(nodeText);
						node.childNode(i).replaceWith(e);
						handleNodes.add(node);
						// 去除重复的数据
						for (int j = 0; j < handleNodes.size(); j++) {
							if(j > 0 && handleNodes.get(j).toString().equals(handleNodes.get(j - 1).toString())){
								handleNodes.remove(j);
								continue;
							}
						}
					}
				}
			} else{
				handleNodes.add(node);
			}
		}
		if(handleNodes.size() > 0){
			return handleNodes.toString();
		} else{
			return pText;
		}
	}

	/**
	 * 处理span元素中存在strong标签的元素
	 * @Description:
	 * @param subSpanText
	 * @return 
	 * @author lxs
	 * @date 2018年8月1日
	 */
	public static List<Wr> getSubSpan(Element subSpanText){
		List<Wr> wrList = new ArrayList<Wr>();
		// 将文本内容,和strong标签的内容分开存储
		String spanText = subSpanText.text();
		List<String> spanTextList = new ArrayList<String>();
		int start = -1;
		int end = -1;
		while(true){
			start = spanText.indexOf("<strong>");
			end = spanText.indexOf("</strong>");
			if(start > -1 && end > -1){
				spanTextList.add(spanText.substring(0, start));
				spanTextList.add(spanText.substring(start, "</strong>".length()+end));
				spanText = spanText.substring("</strong>".length()+end);
			} else{
				spanTextList.add(spanText);
				break;
			}
		}
		// 遍历span,生成wr
		for (String spanStr : spanTextList) {
			Wr wr = new Wr();
			// 如果存在strong标签,则删除标签,保留内容
			if(spanStr.contains("<strong>")){
				wr.setBold("<w:b/>");
				int startIndex = -1;
				int endIndex = -1;
				while(true){
					String newEleText = "";
					startIndex = spanStr.indexOf("<");
					endIndex = spanStr.indexOf(">");
					if(startIndex > -1 && endIndex > -1){
						newEleText += spanStr.substring(0,startIndex);
						newEleText += spanStr.substring(endIndex+1);
					} else {
						break;
					}
					spanStr = newEleText;
				}
			}
			wr.setContent(spanStr);
			wrList.add(wr);
		}
		return wrList;
	}
	
	/**
	 * 处理span中的图片变量
	 * @Description:
	 * @param element span标签内容
	 * @param sealMap 图片列表
	 * @return
	 * @throws BadElementException
	 * @throws IOException 
	 * @author lxs
	 * @date 2018年7月31日
	 */
	public static List<Wr> getHasImgSpan(Element element,  Map<String, List<Map<String, String>>> sealMap) throws BadElementException, IOException{
		List<Wr> wrList = new ArrayList<Wr>();
		Wr wr = new Wr();
		// 如果span的内容包含印章标签则,设置图片
		if(element.text().equals("${agentSeal}")){
			if(StringUtil.isEmpty(sealMap.get("agentSeal")) || sealMap.get("agentSeal").size() <= 0){
				wr.setContent("     ");
				wrList.add(wr);
			} else{
				wr.setHasImg(1);
				List<WImage> imgList = getImgList(sealMap.get("agentSeal"), "agentSeal");
				wr.setImgList(imgList);
				wrList.add(wr);
			}
		}
		if(element.text().equals("${reviewSeal}")){
			if(StringUtil.isEmpty(sealMap.get("reviewSeal")) || sealMap.get("reviewSeal").size() <= 0){
				wr.setContent("     ");
				wrList.add(wr);
			} else{
				wr.setHasImg(1);
				List<WImage> imgList = getImgList(sealMap.get("reviewSeal"), "reviewSeal");
				wr.setImgList(imgList);
				wrList.add(wr);
			}
		}
		if(element.text().equals("${approveSeal}")){
			if(StringUtil.isEmpty(sealMap.get("approveSeal")) || sealMap.get("approveSeal").size() <= 0){
				wr.setContent("     ");
				wrList.add(wr);
			}else{
				wr.setHasImg(1);
				List<WImage> imgList = getImgList(sealMap.get("approveSeal"), "approveSeal");
				wr.setImgList(imgList);
				wrList.add(wr);
			}
		}
		if(element.text().equals("${deptSeal}")){
			if(StringUtil.isEmpty(sealMap.get("deptSeal")) || sealMap.get("deptSeal").size() <= 0){
				wr.setContent("     ");
				wrList.add(wr);
			}else{
				wr.setHasImg(1);
				List<WImage> imgList = getImgList(sealMap.get("deptSeal"), "deptSeal", "120", "80");
				wr.setImgList(imgList);
				wrList.add(wr);
			}
		}
		if(element.text().equals("${companySeal}")){
			if(StringUtil.isEmpty(sealMap.get("company")) || sealMap.get("company").size() <= 0){
				wr.setContent("     ");
				wrList.add(wr);
			}else{
				wr.setHasImg(1);
				List<WImage> imgList = getImgList(sealMap.get("company"), "company", "120", "80");
				wr.setImgList(imgList);
				wrList.add(wr);
			}
		}
		return wrList;
	}

	/**
	 * 获取图片列表
	 * @Description:
	 * @param sealList
	 * @param imgName
	 * @return 
	 * @author lxs
	 * @throws IOException 
	 * @throws BadElementException 
	 * @date 2018年7月31日
	 */
	public static List<WImage> getImgList(List<Map<String,String>> sealList, String imgName) throws IOException, BadElementException{
		int sealLen = sealList.size();
		List<WImage> imgList = new ArrayList<WImage>();
		for(int i = 0; i< sealLen; i++){
			WImage img = new WImage();
			//Image image = Image.getInstance(sealList.get(i).get("sealPath"));
			// 个人章大小
			//img.setHeight(image.getHeight()+"");
			//img.setWidth(image.getHeight()+"");
			img.setHeight("30");
			img.setWidth("65");
			img.setImgId(imgName + "_" + i);
			img.setImgName(imgName + "_" + i);
			img.setImgBase64(ImageHandleUtil.getImgStr(sealList.get(i).get("sealPath")));
			imgList.add(img);
		}
		return imgList;
	}
	
	/**
	 * 获取图片列表
	 * @Description:
	 * @param sealList
	 * @param imgName
	 * @return 
	 * @author lxs
	 * @throws IOException 
	 * @throws BadElementException 
	 * @date 2018年7月31日
	 */
	public static List<WImage> getImgList(List<Map<String,String>> sealList, String imgName, String width, String height) throws IOException, BadElementException{
		int sealLen = sealList.size();
		List<WImage> imgList = new ArrayList<WImage>();
		for(int i = 0; i< sealLen; i++){
			WImage img = new WImage();
			Image image = Image.getInstance(sealList.get(i).get("sealPath"));
			// 部门章
			//img.setHeight(image.getHeight()+"");
			//img.setWidth(image.getHeight()+"");
			float imgHeight= image.getHeight();
			float imgWidth = image.getWidth();
			float resNumber = (imgHeight - imgWidth) > 0 ? (imgHeight - imgWidth) : -(imgHeight - imgWidth);
			if(resNumber > 20){
				img.setHeight(height);
				img.setWidth(width);
			} else{
				img.setHeight("120");
				img.setWidth("120");
			}
			img.setImgId(imgName + "_" + i);
			img.setImgName(imgName + "_" + i);
			img.setImgBase64(ImageHandleUtil.getImgStr(sealList.get(i).get("sealPath")));
			imgList.add(img);
		}
		return imgList;
	}
}

其他的一些实体类以及属性,根据自己的需求创建:

java如何将html字符串转图片 java html转word 图片_java如何将html字符串转图片

使用到的工具类:

1、图片转base64

java如何将html字符串转图片 java html转word 图片_#if_02

2、StringUtil的字符串非空判断:

java如何将html字符串转图片 java html转word 图片_#if_03

使用到的包:

1、jsoup

2、itextpdf

 

该功能主要是通过前台使用百度UEditor富文本编辑器,编辑模板并添加变量,然后保存,后台通过解析保存的模板源代码,替换变量。填充模板来实现的,如果有发现问题,或者有建议的,欢迎指出,感激不尽,有问题的也可以留言评论。