拟写一个java后端接受api数据并进行数据套打生成新的word然后供前端下载
templatePath与tempOutputPath两个变量由前端在调用api的时候动态传输给后端
当前代码运行提示如下错误
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'exportWordController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'template.path' in value "${template.path}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:414)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:929)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:591)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
at jnpf.JnpfAdminApplication.main(JnpfAdminApplication.java:27)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'template.path' in value "${template.path}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:191)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:936)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1332)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:710)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:693)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:408)
... 15 common frames omitted
当前java代码如下:
package jnpf.controller;
import org.apache.commons.lang3.StringUtils; // 导入用于字符串操作的工具类
import org.apache.poi.xwpf.usermodel.*; // 导入Apache POI库中处理Word文档的类
import org.mybatis.logging.Logger; // MyBatis日志记录器导入(但未使用)
import org.mybatis.logging.LoggerFactory; // MyBatis日志工厂导入(但未使用)
import org.springframework.beans.factory.annotation.Value; // 用于注入配置文件中的值
import org.springframework.http.HttpHeaders; // 用于构建HTTP响应头
import org.springframework.http.MediaType; // 定义媒体类型常量
import org.springframework.http.ResponseEntity; // 用于构建HTTP响应实体
import org.springframework.web.bind.annotation.PostMapping; // 标记处理POST请求的方法
import org.springframework.web.bind.annotation.RequestBody; // 用于将请求体绑定到方法参数
import org.springframework.web.bind.annotation.RequestMapping; // 定义请求映射的路径
import org.springframework.web.bind.annotation.RestController; // 标记为RESTful控制器
import java.io.File; // 操作文件的类
import java.io.FileInputStream; // 用于读取文件输入流
import java.io.FileOutputStream; // 用于写入文件输出流
import java.io.IOException; // 异常处理,与输入输出相关
import java.nio.file.Files; // 用于读取文件到字节数组
import java.nio.file.Path; // 文件路径相关的类
import java.nio.file.Paths; // 创建Path实例的工具类
import java.util.Map; // 用于存储键值对数据
@RestController // 标记该类为一个REST控制器
@RequestMapping("/export-word") // 设置控制器处理的请求路径前缀
public class ExportWordController {
@Value("${template.path}") // 注入配置文件中定义的模板文件路径
private String templatePath;
@Value("${temp.output.path}") // 注入配置文件中定义的临时输出文件路径
private String tempOutputPath;
@PostMapping // 标记该方法处理POST请求
public ResponseEntity<byte[]> exportWord(@RequestBody Map<String, String> data) throws IOException { // 接受JSON格式的请求体数据,转换为Map<String, String>
// 读取模板文件
XWPFDocument templateDocument = new XWPFDocument(new FileInputStream(templatePath)); // 使用Apache POI读取Word模板
// 遍历模板文件中的段落并替换文本
for (XWPFParagraph paragraph : templateDocument.getParagraphs()) { // 对每个段落
for (XWPFRun run : paragraph.getRuns()) { // 对段落中的每个run(文本片段)
for (Map.Entry<String, String> entry : data.entrySet()) { // 对传入的数据项
String key = entry.getKey(); // 获取替换关键字
String value = entry.getValue(); // 获取替换值
replaceTextInRun(run, key, value); // 调用方法替换文本
}
}
}
// 保存并返回文件
File outputFile = new File(tempOutputPath); // 创建输出文件对象
FileOutputStream out = new FileOutputStream(outputFile); // 创建文件输出流
templateDocument.write(out); // 将修改后的文档写入输出文件
out.close(); // 关闭输出流
templateDocument.close(); // 关闭文档对象
// 返回文件作为HTTP响应
HttpHeaders headers = new HttpHeaders(); // 创建HTTP响应头
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=output.docx"); // 设置下载附件的头部信息
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 设置内容类型为二进制流
return ResponseEntity.ok() // 构建响应实体
.headers(headers) // 添加响应头
.contentType(MediaType.APPLICATION_OCTET_STREAM) // 再次设置内容类型,确保兼容性
.body(Files.readAllBytes(outputFile.toPath())); // 读取文件内容并作为响应体
}
// 替换指定run中的文本
private void replaceTextInRun(XWPFRun run, String key, String value) {
if (StringUtils.containsIgnoreCase(run.getText(0), key)) { // 忽略大小写检查关键字是否存在
String newText = StringUtils.replace(run.getText(0), key, value); // 替换文本
run.setText(newText, 0); // 更新run的文本内容
}
}
// 日志配置(虽然导入了MyBatis的Logger,但实际上没有使用)
@SuppressWarnings("unused") // 告诉编译器忽略此变量未使用的警告
private static final Logger log = LoggerFactory.getLogger(ExportWordController.class); // 实例化日志记录器
}
当前前端代码如下:
```html
<template>
<div>
<!-- 其他组件内容 -->
<button @click="exportWord">导出Word文档</button>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
templatePath: 'public/word/word.docx',
tempOutputPath: 'public/word/wordoutput.docx',
documentData: {
title: '文档标题',
content: '这里是文档内容...',
images: ['image1.jpg', 'image2.png'],
tables: [
{ header: ['列1', '列2'], rows: [['数据1', '数据2'], ['数据3', '数据4']] },
],
},
};
},
methods: {
async exportWord() {
try {
const response = await axios.post('http://localhost:3000/dev/export-word', {
templatePath: this.templatePath,
tempOutputPath: this.tempOutputPath,
documentData: this.documentData,
}, {
responseType: 'blob',
});
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'output.docx');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.error('导出Word文档失败:', error);
}
},
},
};
</script>
```