写在前面:将用户操作日志以xml、word、pdf、excel格式的文件导出。
导出xml使用JAXB的注解实现,实体如下
import javax.xml.bind.annotation.*;
import java.util.List;
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "", propOrder = {
"title",
"log"
})
@XmlRootElement(name = "Body")
public class Submit {
private String title;
protected List logX;
@XmlElementWrapper(name = "logList")
public List getLog() {
return logX;
}
public void setLog(List logX) {
this.logX = logX;
}
@XmlElement(name = "title", required = true,nillable=true)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
LogX实体如下:
import javax.xml.bind.annotation.*;
import java.io.Serializable;
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "", propOrder = {
"username",
"operationIp",
"createTime",
"operation",
"content"
})
@XmlRootElement(name = "log")
public class LogX implements Serializable {
private static final long serialVersionUID = 1L;
protected String content;
protected String createTime;
protected String operation;
protected String username;
protected String operationIp;
@XmlElement(name = "content", required = true,nillable = true)
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@XmlElement(name = "createTime", required = true,nillable = true)
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
@XmlElement(name = "operation", required = true,nillable = true)
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
@XmlElement(name = "username", required = true,nillable = true)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@XmlElement(name = "operationIp", required = true,nillable = true)
public String getOperationIp() {
return operationIp;
}
public void setOperationIp(String operationIp) {
this.operationIp = operationIp;
}
}
@XmlAccessorType:便于对象与xml文件之间的转换
@XmlType中:参数propOrder指定映射XML时的节点顺序,使用该属性时,必须列出JavaBean对象中的所有字段,否则会报错。
@XmlRootElement :xml 文件的根元素
@XmlElementWrapper:仅允许出现在集合属性上,使用该注解后,将会在原xml结点上再包装一层xml
@XmlElement:字段,方法,参数级别的注解。该注解可以将被注解的(非静态)字段,或者被注解的get/set方法对应的字段映射为本地元素,也就是子元素。参数 name用于指定映射时的节点名称,指定生成元素的名字,若不指定,默认使用方法名小写作为元素名;参数 required字段是否必须,默认为false;参数 nillable是否处理空数据,默认为false。
其他关于JAXB的注解,大家就根据需要自行百度一下~
Submit submit = new Submit();
submit.setTitle(date2Str + "_logs");
//这里给loxList集合赋值
List logXList = new ArrayList<>();
submit.setLog(logXList);
JAXBContext jc = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
String fileName = submit.getTitle() + ".xml";
ByteArrayOutputStream bis = null;
FileOutputStream fileOutputStream = null;
try {
jc = JAXBContext.newInstance(Submit.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
StringWriter writer = new StringWriter();
marshaller.marshal(submit, writer);
String content = writer.toString().replaceAll(JoinConstant.JAXB_NILL_STR, "");
byte[] bs = content.getBytes("UTF-8");
File file2 = new File(fileName);
fileOutputStream = new FileOutputStream(file2);
file2.createNewFile();
fileOutputStream.write(bs);
fileOutputStream.close();
download(file2, res);
} catch (JAXBException e) {
e.printStackTrace();
throw new RuntimeException("xml生成出错", e);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
try {
if (null != bis) bis.close();
if (null != stream) stream.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
涉及到的download方法如下:
private void download(File file, HttpServletResponse res) {
String fileName = file.getName();
res.setHeader("content-type", "application/octet-stream");
res.setContentType("application/octet-stream;charset=UTF-8");
res.setHeader("Content-Disposition", "attachment; filename=" + fileName);
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
OutputStream os = null;
try {
os = res.getOutputStream();
bis = new BufferedInputStream(new FileInputStream(
new File(file.getAbsolutePath())));
int i = bis.read(buff);
while (i != -1) {
os.write(buff, 0, buff.length);
os.flush();
i = bis.read(buff);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用freemarker技术在web后台导出word文档:
具体步骤为:
1、设计word模版
2、修改ftl模版
3、 填充数值,导出word模板
4、生成Word模板
生产word模版主要为:一个是把word文档另存为xml文档;然后把xml文档后缀改为ftl文档****
如下图,我所需要的模板为:
然后使用sublime打开后缀名为ftl的文件,通过sublime插件,将ftl文件格式化,然后找到如下图所示位置进行编辑
注意${log.xh}等其他的标签的修改
代码如下:
Map beanParams = new HashMap();
//这里给loglist集合赋值
List loglist = new ArrayList<>();
String date2Str = DateSearchUtils.date2Str(new Date());
beanParams.put("title", date2Str+"日志信息");
beanParams.put("loglist", loglist);
beanParams.put("attention", "请注意确保所有信息的正确性");
WordExportUtil.WordExportUtil(request, response, WordExportUtil.WORD_2003, "日志信息列表导出", "templateFile.ftl", beanParams,getExcelDir());
涉及到的WordExportUtil.WordExportUtil()方法如下:
public static String WORD_2007 = "WORD_2007";
public static String WORD_2003 = "WORD_2003";
/**
* 设置下载文件中文件的名称
* @param filename
* @param request
* @return
*/
public static String encodeFilename(String filename, HttpServletRequest request) {
String agent = request.getHeader("USER-AGENT");
try {
if ((agent != null) && (-1 != agent.indexOf("MSIE"))) {
String newFileName = URLEncoder.encode(filename, "UTF-8");
newFileName = StringUtils.replace(newFileName, "+", "%20");
if (newFileName.length() > 150) {
newFileName = new String(filename.getBytes("GB2312"), "ISO8859-1");
newFileName = StringUtils.replace(newFileName, " ", "%20");
}
return newFileName;
}
if ((agent != null) && (-1 != agent.indexOf("Mozilla")))
return MimeUtility.encodeText(filename, "UTF-8", "B");
return URLEncoder.encode(filename, "UTF-8");
} catch (Exception ex) {
return filename;
}
}
/**
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param version Word_2003/Word_2007
* @param docFileName 生成的doc临时文件名
* @param templateFile freemark模板文件名
* @param beanParams 入参数据: Map类型
*/
public static void writeResponse(HttpServletRequest request, HttpServletResponse response, String version, String docFileName, String templateFile, Map beanParams,String getExcelDir) {
writeResponse(request, response, version, "temp", docFileName, "template", templateFile, beanParams, getExcelDir);
}
/**
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param version Word_2003/Word_2007
* @param docTempDir 生成的doc临时文件目录
* @param docFileName 生成的doc临时文件名
* @param templateDir 存放freemark模板的目录
* @param templateFile freemark模板文件名
* @param beanParams 入参数据: Map类型
*/
public static void writeResponse( HttpServletRequest request, HttpServletResponse response, String version, String docTempDir, String docFileName, String templateDir, String templateFile, Map beanParams,String getExcelDir) {
Configuration config = new Configuration();
ServletContext sc = request.getSession().getServletContext();
InputStream is = null;
File previewFile = null;
try {
config.setDirectoryForTemplateLoading(new File(getExcelDir));
config.setObjectWrapper(new DefaultObjectWrapper());
Template template = config.getTemplate(templateFile, "UTF-8");
String date2Str = DateSearchUtils.date2Str(new Date());
String docFileName1 = date2Str+"_logs";
if (WORD_2007.equals(version)) {
docFileName1 = encodeFilename(docFileName1 + ".docx", request);
} else {
docFileName1 = encodeFilename(docFileName1 + ".doc", request);
}
String docName = "D:\\join\\excel"+docFileName;
FileOutputStream fos = new FileOutputStream(docName);
Writer out = new OutputStreamWriter(fos, "UTF-8");
template.process(beanParams, out);
out.flush();
out.close();
previewFile = new File(docName);
is = new FileInputStream(previewFile);
response.reset();
if (WORD_2007.equals(version)) {
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8");
}else{
response.setContentType("application/vnd.ms-word;charset=UTF-8");
}
response.addHeader("Content-Disposition", "attachment;filename="+docFileName1);
byte[] b = new byte[1024];
int len;
while ((len=is.read(b)) >0) {
response.getOutputStream().write(b,0,len);
}
response.getOutputStream().flush();
response.getOutputStream().close();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(previewFile!=null){
previewFile.delete();
}
}
}
// 新建文件
String date2Str = DateSearchUtils.date2Str(new Date());
String fileName = date2Str + "_logs.pdf";
Document document = new Document();
File file = new File(fileName);
PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 中文字体
com.itextpdf.text.Font FontChinese18 = new com.itextpdf.text.Font(bfChinese, 18, com.itextpdf.text.Font.BOLD);
//设置名字
Paragraph pg_bt = new Paragraph("日志列表", FontChinese18);
pg_bt.setAlignment(Element.ALIGN_CENTER);
document.add(pg_bt);
// Font fontChineseBold = new Font(bfChinese, 14, Font.BOLD);//内容字体特殊加粗
Font titleChinese = new Font(bfChinese, 18, Font.BOLD);// 标题字体
// Font noteChinese = new Font(bfChinese, 12, Font.BOLD);//设置内容加粗的区
Font contenttitleChinese = new Font(bfChinese, 12, Font.BOLD);// 内容小标题字体
//这里给logViews 集合赋值
List logViews = new ArrayList<>();
// 每行加空白
pg_bt = new Paragraph(" ", titleChinese);
pg_bt.setAlignment(Element.ALIGN_LEFT);
document.add(pg_bt);
SimpleDateFormat start = new SimpleDateFormat("HH:mm");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
PdfPTable table5 = new PdfPTable(2);
int width5[] = {80, 20};
table5.setWidths(width5);
PdfPCell cell51 = new PdfPCell(new Paragraph("日志打印时间 : " + sdf.format(new Date()), contenttitleChinese));
PdfPCell cell52 = new PdfPCell(new Paragraph("", contenttitleChinese));
cell51.setBorder(0);
cell52.setBorder(0);
table5.addCell(cell51);
table5.addCell(cell52);
table5.setHorizontalAlignment(Element.ALIGN_LEFT);
document.add(table5);
//加入空行
Paragraph blankRow51 = new Paragraph(18f, " ", contenttitleChinese);
document.add(blankRow51);
int col = 6;
PdfPTable table = new PdfPTable(col);
BaseColor bc = new BaseColor(102, 204, 255);
//设置表格占PDF文档100%宽度
table.setWidthPercentage(100);
table.setWidths(new int[]{8, 12, 15, 20, 15, 30});
BaseColor lightGrey01 = new BaseColor(0xCC, 0xCC, 0xCC);
PdfPCell cell0 = toPdfPCell("序号", Element.ALIGN_CENTER);
cell0.setBackgroundColor(lightGrey01);
table.addCell(cell0);
PdfPCell cell1 = toPdfPCell("用户名", Element.ALIGN_CENTER);
cell1.setBackgroundColor(lightGrey01);
table.addCell(cell1);
PdfPCell cell2 = toPdfPCell("访问ip", Element.ALIGN_CENTER);
cell2.setBackgroundColor(lightGrey01);
table.addCell(cell2);
PdfPCell cell3 = toPdfPCell("创建时间", Element.ALIGN_CENTER);
cell3.setBackgroundColor(lightGrey01);
table.addCell(cell3);
PdfPCell cell4 = toPdfPCell("操作", Element.ALIGN_CENTER);
cell4.setBackgroundColor(lightGrey01);
table.addCell(cell4);
PdfPCell cell5 = toPdfPCell("日志内容", Element.ALIGN_CENTER);
cell5.setBackgroundColor(lightGrey01);
table.addCell(cell5);
if (logViews.size() > 0) {
for (LogView view : logViews) {
table.addCell(toPdfPCell(view.getXh(), Element.ALIGN_CENTER));
table.addCell(toPdfPCell(view.getUsername(), Element.ALIGN_CENTER));
table.addCell(toPdfPCell(view.getAccessEndIp(), Element.ALIGN_CENTER));
table.addCell(toPdfPCell(DateSearchUtils.longToDate(view.getCreateTime()), Element.ALIGN_CENTER));
table.addCell(toPdfPCell(view.getOperation(), Element.ALIGN_CENTER));
table.addCell(toPdfPCell(view.getContent(), Element.ALIGN_CENTER));
}
}
document.add(table);
document.close();
download(file, res);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
涉及到的toPdfPCell()方法如下:
public PdfPCell toPdfPCell(String name, int align) throws DocumentException, IOException {
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 中文字体
Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);// 内容字体
PdfPCell cell = new PdfPCell(new Paragraph(name, fontChinese));
cell.setHorizontalAlignment(align);// 设置内容水平居中显示
cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 设置垂直居中
return cell;
}
参考地址:http://easypoi.mydoc.io/
com.lowagie
itext
2.1.7
com.itextpdf
itextpdf
5.5.1
com.yulintu
common-excel
RELEASE
compile
org.freemarker
freemarker
2.3.23
org.springframework
spring-jms
5.2.0.RELEASE
compile
com.itextpdf
itext-asian
5.2.0
javax.mail
mail
RELEASE
效果图如下:
写在最后:可能在进行这个功能实现时,我所采用的方法并不是最合理的,大家一起学习嘛