这个代码同之前写过的一篇文章:使用java + jdbc连接数据库,并解析成XML格式的文件。。另外有对流文件的操作。。
这里不再详述,补充一点的是:java命令行执行带依赖jar包的main函数
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
/**
* 读取SQL Server数据库中邮件相关的数据
*
* @date 2019/08/08
* @author linrui
*
* */
public class SelectSQLServerEmailToXml {
public static final String NEW_FILE_PATH = "D:\\email\\";
public static Map contentMap;
/**
* 程序入口
* */
public static void main(String[] args) throws Exception{
System.out.println("程序正在执行中,请稍后……");
System.out.println();
long beginTime = System.currentTimeMillis();
Connection connection = getConnection();
Statement statement = null;
ResultSet rs = null;
try {
statement = connection.createStatement();
String sql = getSelectSQL();
rs = statement.executeQuery(sql);
} catch (SQLException e) {
System.out.println("操作数据库异常!");
e.printStackTrace();
}
long count = 0;
long filed = 0;
//得到所有的主题
List<String> subjectList = new ArrayList<>();
// try {
while (rs.next()) {
subjectList.add(rs.getString("ZT"));
}
// } catch (SQLException e) {
// throw new RuntimeException("解析所有主题时错误!");
// }
//关闭数据库连接相关的资源
closeAll(connection, statement, null, rs);
//生成xml,并返回生成的条数(有多少个主题,就生成多少条记录)
for (String subject : subjectList) {
contentMap = new HashMap(1);
//附件中的所有文件名(包括办理单)
StringBuilder fileNames = new StringBuilder();
//根据主题获取一条邮件(获取到发件人即可)
Map<String,Object> mailMap = getResultBySubject(subject, fileNames);
try {
//生成xml,并返回生成的条数(有多少个主题,就生成多少条记录)
createXml(mailMap, fileNames);
count++;
} catch (Exception e) {
filed++;
// System.out.println("==========>失败的mailMap为:" + mailMap);
}
}
System.out.println();
System.out.println("程序执行完成。");
System.out.println("生成了" + count + "条xml数据!");
System.out.println("失败了" + filed + "条xml数据!");
System.out.println();
long endTime = System.currentTimeMillis();
System.out.println("总耗时:" + (endTime - beginTime)/1000 + "秒");
}
/**
* 根据主题 去解析每个邮件
*
* @param subject
* @param fileNames 附件名称,用于拼接
* */
private static Map<String, Object> getResultBySubject(String subject, StringBuilder fileNames) {
String filePath = "D:\\botongsoft\\OA\\tomcat5.0\\webapps\\ROOT\\mail";
Map<String, Object> mailMap = new HashMap<>(4);
Connection connection = getConnection();
PreparedStatement preparedStatement = null;
ResultSet rs = null;
String sql = "select * from dbo.MAIL_MESSAGE where ZT = ?";
try{
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, subject);
rs = preparedStatement.executeQuery();
boolean flag = true;
while (rs.next() && flag) {
//解析发件人,得到对应的eml文件所在位置的父文件夹名称
String fjr = rs.getString("FJR");
String fjrName = "";
if (fjr != null) {
if (!fjr.equals("")) {
String[] tempArr = fjr.split("<");
String[] tempArr2 = tempArr[1].split("@");
fjrName = tempArr2[0];
}
}
//这里是按主题去遍历邮件,所以一个主题对应多份邮件,这里只需要找到发送人即可。
// 即如果抛异常,则不是发送人,直接循环下一个
try {
//解析eml文件
mailMap = getEmlContent(filePath + "\\" + fjrName + "\\" + rs.getString("FILENAME") + ".eml", fileNames, rs.getInt(1));
//同理,如果没有抛异常,则就是这份文,记录id、生成目录、并直接退出循环
int sourceIDInt = rs.getInt(1);
mailMap.put("sourceId", sourceIDInt);
// break;//break没有用,无法退出循环!
flag = false;
} catch (Exception e) {
//什么也不做
System.out.println("出异常了,我什么都没做。异常的id为:【" + rs.getInt("MESSAGE_ID") + "】");
}
}
}catch (SQLException e) {
System.out.println("==============》解析主题为:【" + subject + "】的邮件时异常!跳过处理");
} finally {
closeAll(connection, null, preparedStatement, rs);
}
return mailMap;
}
/**
* 生成xml,并返回生成的条数
*
* @param mailMap 数据库查询结果集
* @return int 返回生成xml的条数
* */
private static void createXml(Map<String, Object> mailMap, StringBuilder fileNames) throws Exception {
// 创建解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
//文件id要多次使用,故直接赋值出来
int sourceIDInt = (int)mailMap.get("sourceId");
// String sourceID = (String)mailMap.get("sourceId");
String sourceID = String.valueOf(sourceIDInt);
Document document = db.newDocument();
document.setXmlVersion("1.0");
document.setXmlStandalone(true);
Element docs = document.createElement("docs");
// 向docs根节点中添加子节点doc
Element doc = document.createElement("doc");
//创建一个新的目录
// File file = new File(getNewFilePath());
// file.mkdir();
// file = new File(getNewFilePath() + sourceID);
// file.mkdir();
//每个字段信息
//原文ID
Element item = document.createElement("item");
item.setAttribute("name", "uuid");
CDATASection cdataSection = document.createCDATASection(sourceID);
item.appendChild(cdataSection);
doc.appendChild(item);
//发件人
String fjrAddress = (String)mailMap.get("fjrAddress");
String fjrShortName = fjrAddress.split("@")[0];
String fjrName = getUserName(fjrShortName);
item = getItem(fjrName, "fromAddress", document, cdataSection);
doc.appendChild(item);
//收件人
String sjrAddressList = (String)mailMap.get("sjrAddressList");
String[] sjrMailArr = sjrAddressList.split("。");
StringBuilder toAddressSB = new StringBuilder();
for (String sjrMail: sjrMailArr) {
// System.out.println("收件人邮箱=====》" + sjrMail);
String sjrShortName = sjrMail.split("@")[0];
// System.out.println("收件人简称=====》" + sjrShortName);
String sjrName = getUserName(sjrShortName);
toAddressSB.append(sjrName);
toAddressSB.append(";;");
}
if (toAddressSB.length() > 1) {
toAddressSB.deleteCharAt(toAddressSB.length()-1);
toAddressSB.deleteCharAt(toAddressSB.length()-1);
}
item = getItem(toAddressSB.toString(), "toAddress", document, cdataSection);
doc.appendChild(item);
//邮件主题
String subject = (String)mailMap.get("subject");
item = getItem(subject, "subject", document, cdataSection);
doc.appendChild(item);
//发送日期
Date sendDate = (Date)mailMap.get("sentDate");
String sendDateToString = "";
if(sendDate != null) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sendDateToString = format.format(sendDate);
}
item = getItem(sendDateToString, "sendDate", document, cdataSection);
doc.appendChild(item);
//邮件内容
try {
if (contentMap.size() > 0) {
String htmlContent = (String)contentMap.get("htmlContent");
item = getItem(htmlContent, "htmlContent", document, cdataSection);
doc.appendChild(item);
}
} catch (Exception e) {
System.out.println("没有邮件内容");
}
//附件
if (fileNames.length() > 1) {
fileNames.deleteCharAt(fileNames.length()-1);
fileNames.deleteCharAt(fileNames.length()-1);
fileNames.deleteCharAt(fileNames.length()-1);
fileNames.deleteCharAt(fileNames.length()-1);
fileNames.deleteCharAt(fileNames.length()-1);
}
item = getItem(fileNames.toString(), "附件", document, cdataSection);
doc.appendChild(item);
// 将doc节点添加到docs根节点中
docs.appendChild(doc);
// 将docs节点(已包含doc)添加到dom树中
document.appendChild(docs);
// 创建TransformerFactory对象
TransformerFactory tff = TransformerFactory.newInstance();
// 创建 Transformer对象
Transformer tf = tff.newTransformer();
// 输出内容是否使用换行
tf.setOutputProperty(OutputKeys.INDENT, "yes");
// 创建xml文件并写入内容
tf.transform(new DOMSource(document), new StreamResult(new File(getNewFilePath() + sourceID + "\\basicInfo" +".xml")));
}
/**
* 获取item
*
* @param source 源字段
* @param target 目标字段
* @param document
* @param cdataSection CDATA区
* */
private static Element getItem(String source, String target, Document document, CDATASection cdataSection){
Element item;
item = document.createElement("item");
item.setAttribute("name", target);
cdataSection = document.createCDATASection(source.trim());
item.appendChild(cdataSection);
return item;
}
/**
* 根据拟稿人编号到数据库中查询其名字
*
* @param login_id 登录编号(唯一的)
*
* @return String 用户名称
* */
private static String getUserName(String login_id) {
String userName = "";
Connection connection = getConnection();
PreparedStatement preparedStatement = null;
ResultSet rs = null;
try {
String sql = "select * from dbo.TS_USER where login_id=?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, login_id);
rs = preparedStatement.executeQuery();
while (rs.next()) {
userName = rs.getString("NAME");
}
} catch (SQLException e) {
System.out.println("根据用户编号获取用户名是出现了未知的异常!");
e.printStackTrace();
} finally {
//关闭数据库连接相关的资源
closeAll(connection, null, preparedStatement, rs);
}
return userName;
}
/**
* 获取Connection连接
*
* @return connection
* */
private static Connection getConnection () {
//获取指定的数据库连接信息
Map<String, String> databaseMap = getDatabaseMap();
//声明Connection对象
Connection con = null;
//驱动程序名
String driver = databaseMap.get("driverName");
//URL指向要访问的数据库名
String url = databaseMap.get("url");
//MySQL配置时的用户名
String userName = databaseMap.get("userName");
//MySQL配置时的密码
String password = databaseMap.get("password");
try {
//加载驱动程序
Class.forName(driver);
con = DriverManager.getConnection(url, userName, password);
} catch(ClassNotFoundException e) {
//数据库驱动类异常处理
System.out.println("没有找到驱动!");
e.printStackTrace();
throw new RuntimeException();
} catch(SQLException e) {
//数据库连接失败异常处理
System.out.println("连接失败!");
e.printStackTrace();
throw new RuntimeException();
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
return con;
}
/**
* 获取数据库连接信息
*
* @return Map
* */
private static Map<String, String> getDatabaseMap() {
Map<String, String> databaseMap = new HashMap<>(4);
//读取属性文件
Properties properties = readProperties();
databaseMap.put("driverName", properties.getProperty("driverName"));
databaseMap.put("url", properties.getProperty("url"));
databaseMap.put("userName", properties.getProperty("userName"));
databaseMap.put("password", properties.getProperty("password"));
return databaseMap;
}
/**
* 获取SQL语句
*
* @return String
* */
private static String getSelectSQL() {
Properties properties = readProperties();
return properties.getProperty("selectSQL");
}
/**
* 获取存放文件的路径
*
* @return String
* */
private static String getNewFilePath() {
return NEW_FILE_PATH;
// Properties properties = readProperties();
// return properties.getProperty("newFilePath");
}
/**
* 读取属性文件
*
* @return Properties
* */
private static Properties readProperties() {
InputStream inputStream = null;
Properties properties = null;
try {
//用流读入properties配置文件
inputStream = new FileInputStream("D:\\database.properties");
properties = new Properties();
//从输入字节流读取属性列表(键和元素对)
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
if (properties == null) {
System.out.println("读取属性文件失败,值为null");
throw new RuntimeException();
}
//关闭流
closeToIO(inputStream, null);
return properties;
}
/**
* 关闭数据库连接及操作相关的资源
*
* @param conn 数据库连接
* @param statement 执行数据库操作的对象
* */
private static void closeAll(Connection conn, Statement statement, PreparedStatement preparedStatement, ResultSet resultSet){
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
System.out.println("关闭resultSet资源失败");
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
System.out.println("关闭statement资源失败");
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
System.out.println("关闭preparedStatement资源失败");
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("关闭数据库连接connection失败");
e.printStackTrace();
}
}
}
/**
* 关闭流的资源
* */
private static void closeToIO (InputStream inputStream, OutputStream outputStream) {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
System.out.println("关闭输入流inputStream流异常!");
e.printStackTrace();
}
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
System.out.println("关闭输出流outputStream流异常!");
e.printStackTrace();
}
}
/*************************************************************************************
* **********************下面是解析 .eml 邮件格式的文件的代码 ************************
*************************************************************************************/
/**
* 获取邮件中的内容
* @param filePath 文件路径
*
* @return map
* */
private static Map<String, Object> getEmlContent(String filePath, StringBuilder fileNames, int sourceId) throws Exception{
Map<String, Object> map;
map = parserFile(filePath, fileNames, sourceId);
//System.out.println("============>" + map);
return map;
}
/**
* 解析文件
*
* @param emlPath 文件路径
* */
public static Map<String, Object> parserFile(String emlPath, StringBuilder fileNames, int sourceId) throws Exception {
Map<String, Object> map;
//System.out.println(emlPath);
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
InputStream inMsg;
inMsg = new FileInputStream(emlPath);
Message msg = new MimeMessage(session, inMsg);
map = parseEml(msg, fileNames, sourceId);
return map;
}
private static Map<String, Object> parseEml(Message msg, StringBuilder fileNames, int sourceIDInt) throws Exception {
String sourceIdToString = String.valueOf(sourceIDInt);
//创建目录
File file = new File(getNewFilePath());
file.mkdir();
file = new File(getNewFilePath() + sourceIdToString);
file.mkdir();
Map<String, Object> map = new HashMap<>(10);
// 发件人信息
Address[] froms = msg.getFrom();
if (froms != null) {
InternetAddress addr = (InternetAddress) froms[0];
// System.out.println("发件人地址:" + addr.getAddress());
map.put("fjrAddress",addr.getAddress());
//System.out.println("发件人显示名:" + addr.getPersonal());
map.put("fjrName", addr.getPersonal());
}
//收件人信息
Address[] tos = msg.getAllRecipients();
// List<String> sjrAddressList = new ArrayList<>();
StringBuilder sjrAddressStringBuilder = new StringBuilder();
for (Address a : tos) {
InternetAddress addr = (InternetAddress)a;
//System.out.println("====>收件人地址:" + addr.getAddress());
// sjrAddressList.add(addr.getAddress());
sjrAddressStringBuilder.append(addr.getAddress());
sjrAddressStringBuilder.append("。");
}
map.put("sjrAddressList", sjrAddressStringBuilder.toString());
//System.out.println("邮件主题:" + msg.getSubject());
map.put("subject", msg.getSubject());
//发件日期
//System.out.println("===>发件日期:" + msg.getSentDate());
map.put("sentDate", msg.getSentDate());
// getContent() 是获取包裹内容, Part相当于外包装
Object o = msg.getContent();
if (o instanceof Multipart) {
Multipart multipart = (Multipart) o;
reMultipart(multipart, fileNames, sourceIdToString);
} else if (o instanceof Part) {
Part part = (Part) o;
rePart(part, fileNames, sourceIdToString);
} else {
// System.out.println("类型" + msg.getContentType());
map.put("type", msg.getContentType());
//System.out.println("内容" + msg.getContent());
map.put("content", msg.getContent().toString());
}
return map;
}
/**
* 解析内容
*
* @param part
* @throws Exception
*/
private static void rePart(Part part, StringBuilder fileNames, String sourceIdToString) throws Exception {
if (part.getDisposition() != null) {
String strFileNmae = part.getFileName();
if(strFileNmae != null) {
// MimeUtility.decodeText解决附件名乱码问题
strFileNmae=MimeUtility.decodeText(strFileNmae);
// System.out.println("发现附件: "+ strFileNmae);
// 打开附件的输入流
InputStream in = part.getInputStream();
//取文件明的hash值
String strFileNameHash = String.valueOf(strFileNmae.hashCode());
//保存文件名
fileNames.append(strFileNameHash + ";;" + strFileNmae);
fileNames.append("#####");
// String strFile = "C:\\Users\\lin\\Desktop\\test\\" + strFileNmae;
String strFile = getNewFilePath() + sourceIdToString + "\\" + strFileNameHash;
FileOutputStream out = new FileOutputStream(strFile);
byte[] bytes = new byte[1024];
while(in.read(bytes,0,1024) != -1){
out.write(bytes);
}
in.close();
out.close();
}
//System.out.println("内容类型: "+ MimeUtility.decodeText(part.getContentType()));
//System.out.println("附件内容:" + part.getContent());
} else {
if (part.getContentType().startsWith("text/plain")) {
// System.out.println("文本内容:" + part.getContent());
if (part.getContent() != null && !part.getContent().equals("") ) {
contentMap.put("htmlContent", part.getContent());
}
} else {
// System.out.println("HTML内容:" + part.getContent());
if (part.getContent() != null && !part.getContent().equals("") ) {
contentMap.put("htmlContent", part.getContent());
}
}
}
}
/**
* 接卸包裹(含所有邮件内容(包裹+正文+附件))
* @param multipart
* @throws Exception
*/
private static void reMultipart(Multipart multipart, StringBuilder fileNames, String sourceIdToString) throws Exception {
// System.out.println("邮件共有" + multipart.getCount() + "部分组成");
// 依次处理各个部分
for (int j = 0, n = multipart.getCount(); j < n; j++) {
// System.out.println("处理第" + j + "部分");
Part part = multipart.getBodyPart(j);// 解包, 取出 MultiPart的各个部分,
// 每部分可能是邮件内容,
// 也可能是另一个小包裹(MultipPart)
// 判断此包裹内容是不是一个小包裹, 一般这一部分是 正文 Content-Type: multipart/alternative
if (part.getContent() instanceof Multipart) {
Multipart p = (Multipart) part.getContent();// 转成小包裹
// 递归迭代
reMultipart(p, fileNames, sourceIdToString);
} else {
rePart(part, fileNames, sourceIdToString);
}
}
}
}