Я сделал это таким образом, но я думаю, что это, безусловно, более элегантное решение (testpdf.vm
и testpdf.xsl
в /WEB-INF/velocity
).
@Controller
@RequestMapping("/doc")
public class DocumentController {
@Autowired
private PdfReportService pdfReportService;
@RequestMapping("/pdf")
public void testPdf(HttpServletResponse response) throws IOException {
Map<String, Object> model = new HashMap<String,Object>();
model.put("message", "Hello World!");
pdfReportService.generatePdf("testpdf", model, response.getOutputStream());
}
}
PdfReportService:
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
import org.apache.log4j.Logger;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
@Service("pdfReportService")
public class PdfReportService {
private final Logger log = Logger.getLogger(getClass());
@Autowired
private VelocityConfigurer velocityConfig;
@Autowired
private ServletContext servletContext;
public void generatePdf(String templateName, Map<String,Object>model, OutputStream out) {
// get an engine
final VelocityEngine engine = velocityConfig.getVelocityEngine();
// get the Template
Template template = engine.getTemplate(templateName+".vm");
// create a context and add data
VelocityContext context = new VelocityContext();
context.put("model", model);
// render the template into a StringWriter
StringWriter writer = new StringWriter();
template.merge(context, writer);
FopFactory fopFactory = FopFactory.newInstance();
try {
//Setup FOP
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
//Setup Transformer
InputStream xstlIn = servletContext.getResourceAsStream("/WEB-INF/velocity/"+templateName+".xsl");
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer(new StreamSource(xstlIn));
//Make sure the XSL transformation's result is piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
//Setup input
byte[] bytes = writer.toString().getBytes("UTF-8");
Source src = new StreamSource(new ByteArrayInputStream(bytes));
//Start XSLT transformation and FOP processing
transformer.transform(src, res);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}