基于JavaMail的Java邮件发送

Author xiuhong.chen@hand-china.com

Desc 简单邮件发送

Date 2017/12/8

项目中需要根据物料资质的状况实时给用户发送邮件,然后我就简单学习了SMTP.

电子邮件的在网络中传输和网页一样需要遵从特定的协议,常用的电子邮件协议包括 SMTP,POP3,IMAP。其中邮件的创建和发送只需要用到 SMTP协议,所以本文也只会涉及到SMTP协议。SMTP 是 Simple Mail Transfer Protocol 的简称,即简单邮件传输协议。

1.导入jar包javax.mail.jar

特别注意:

本测试用例用的 JavaMail 版本是 1.6.0,如果下载到其他版本的 JavaMail 运行时出现问题,请使用 JavaMail 1.6.0 版本再进行尝试。

使用 JavaMail 1.6.0 要求的 JDK 版本必须是 JDK 1.7 以上(建议使用最新版 JDK)。

不要直接就完完全全复制我的代码,需要 修改一下发送的标题、内容、用户昵称,要不然所有人都直接复制我的代码发送,内容一致,邮箱服务器就可能会检测到这些内容是垃圾广告内容,不让你发送,会返回错误码,查询错误码也能查询到失败原因。

2.创建一封简单的电子邮件

首先创建一个 Java 工程,把下载好的 javax.mail.jar 作为类库加入工程

邮件创建步骤:

配置连接邮件服务器的参数( 邮件服务器SMTP, 是否需要SMTP验证 )

创建一个邮件对象( MimeMessage )

设置发件人,收件人 ( 可增加多个收件人,抄送人,密送人 )

设置邮件标题, 正文 , 附件等

设置显示的发送时间

public void sendMail() throws Exception{

System.out.println("sendMailServlet-----start");

//1.创建邮件对象

Properties properties = new Properties();

properties.put("mail.smtp.host", "mail.hand-china.com"); // 指定SMTP服务器

properties.put("mail.smtp.auth", "true"); // 指定是否需要SMTP验证

Session session = Session.getInstance(properties);

MimeMessage mimeMessage =new MimeMessage(session);

/*2.设置发件人

* 其中 InternetAddress 的三个参数分别为: 邮箱, 显示的昵称(只用于显示, 没有特别的要求), 昵称的字符集编码

* */

mimeMessage.setFrom(new InternetAddress("xiuhong.chen@hand-china.com","xiuhong","UTF-8"));

/*3.设置收件人

To收件人 CC 抄送 BCC密送*/

mimeMessage.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress("17862***@qq.com","xiuhong","UTF-8"));

mimeMessage.addRecipient(MimeMessage.RecipientType.TO,new InternetAddress("178622***@qq.com","xiuhong","UTF-8"));

/*4.设置标题和内容*/

mimeMessage.setSubject("测试邮件","UTF-8");

mimeMessage.setContent("Test Content:这是一封测试邮件...","text/html;charset=UTF-8");

mimeMessage.setSentDate(new Date());

/*5.保存邮件*/

mimeMessage.saveChanges();

Transport transport = session.getTransport("smtp"); //获取邮件传输对象

transport.connect("mail.hand-china.com","xiuhong.chen@hand-china.com","*******");

transport.sendMessage(mimeMessage,mimeMessage.getAllRecipients());

transport.close();

System.out.println("sendMailServlet-----end");

}

查看邮箱客户端,可以接收到邮件

某些邮箱服务器要求 SMTP 连接需要使用 SSL 安全认证 (为了提高安全性, 邮箱支持SSL连接, 也可以自己开启),

如果无法连接邮件服务器, 仔细查看控制台打印的 log, 如果有有类似 “连接失败, 要求 SSL 安全连接” 等错误,需要开启SSL安全连接,如下代码:

/*SMTP 服务器的端口 (非 SSL 连接的端口一般默认为 25, 可以不添加, 如果开启了 SSL 连接,需要改为对应邮箱的 SMTP 服务器的端口, 具体可查看对应邮箱服务的帮助,

QQ邮箱的SMTP(SLL)端口为465或587, 其他邮箱自行去查看)*/

final String smtpPort = "465";

props.setProperty("mail.smtp.port", smtpPort);

props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");

props.setProperty("mail.smtp.socketFactory.fallback", "false");

props.setProperty("mail.smtp.socketFactory.port", smtpPort);

3.创建一封包含图片和附件的复杂邮件

一封复杂的邮件内容可以看做是由很多节点(或者可以说是“片段”/“部分”/“零件”)组成,文本、图片、附件等都可以看成是邮件内容中的一个节点。这些节点之间又可以相互关联组合成一个节点。最终组合成一个大节点就是邮件的正文内容。

比如图片和文字是关联关系related,和简单邮件不同之处在于设置图片节点和文本节点

/*创建复杂邮件*/

public void sendMail2()throws Exception{

System.out.println("sendMailServlet-----start2");

//1.创建邮件对象

Properties properties = new Properties();

properties.put("mail.smtp.host", "mail.hand-china.com"); // 指定SMTP服务器

properties.put("mail.smtp.auth", "true"); // 指定是否需要SMTP验证

Session session = Session.getInstance(properties);

MimeMessage message =new MimeMessage(session);

/*2.设置发件人

* 其中 InternetAddress 的三个参数分别为: 邮箱, 显示的昵称(只用于显示, 没有特别的要求), 昵称的字符集编码

* */

message.setFrom(new InternetAddress("xiuhong.chen@hand-china.com","xiuhong","UTF-8"));

/*3.设置收件人

To收件人 CC 抄送 BCC密送*/

message.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress("17862****@qq.com","xiuhong","UTF-8"));

message.addRecipient(MimeMessage.RecipientType.TO,new InternetAddress("17862*****@qq.com","xiuhong","UTF-8"));

/*4.设置标题*/

message.setSubject("测试邮件","UTF-8");

//message.setContent("Test Content:这是一封测试邮件...","text/html;charset=UTF-8");

/*5.设置邮件正文*/

//一个Multipart对象包含一个或多个bodypart对象,组成邮件正文

MimeMultipart multipart = new MimeMultipart();

//读取本地图片,将图片数据添加到"节点"

MimeBodyPart image = new MimeBodyPart();

DataHandler dataHandler1 = new DataHandler(new FileDataSource("C:\\Users\\Chen Xiuhong\\Pictures\\suo.png"));

image.setDataHandler(dataHandler1);

image.setContentID("image_suo");

//创建文本节点

MimeBodyPart text = new MimeBodyPart();

text.setContent("这张图片是��锁","text/html;charset=UTF-8");

//将文本和图片添加到multipart

multipart.addBodyPart(text);

multipart.addBodyPart(image);

multipart.setSubType("related");//关联关系

message.setContent(multipart);

message.setSentDate(new Date());

message.saveChanges();

Transport transport = session.getTransport("smtp");

transport.connect("mail.hand-china.com","xiuhong.chen@hand-china.com","******");

transport.sendMessage(message,message.getAllRecipients());

transport.close();

System.out.println("sendMailServlet-----end2");

}

下边发送一封即有图片文字,又有多个附件的邮件,设置节点关系为混合关系mixed

public void sendMail2()throws Exception{

System.out.println("sendMailServlet-----start2");

//1.创建邮件对象

Properties properties = new Properties();

properties.put("mail.smtp.host", "mail.hand-china.com"); // 指定SMTP服务器

properties.put("mail.smtp.auth", "true"); // 指定是否需要SMTP验证

Session session = Session.getInstance(properties);

MimeMessage message =new MimeMessage(session);

/*2.设置发件人

* 其中 InternetAddress 的三个参数分别为: 邮箱, 显示的昵称(只用于显示, 没有特别的要求), 昵称的字符集编码

* */

message.setFrom(new InternetAddress("xiuhong.chen@hand-china.com","xiuhong","UTF-8"));

/*3.设置收件人

To收件人 CC 抄送 BCC密送*/

message.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress("178622****@qq.com","xiuhong","UTF-8"));

message.addRecipient(MimeMessage.RecipientType.TO,new InternetAddress("17862****9@qq.com","xiuhong","UTF-8"));

/*4.设置标题*/

message.setSubject("测试邮件","UTF-8");

//message.setContent("Test Content:这是一封测试邮件...","text/html;charset=UTF-8");

/*5.设置邮件正文*/

//一个Multipart对象包含一个或多个bodypart对象,组成邮件正文

MimeMultipart multipart = new MimeMultipart();

//读取本地图片,将图片数据添加到"节点"

MimeBodyPart image = new MimeBodyPart();

DataHandler dataHandler1 = new DataHandler(new FileDataSource("C:\\Users\\Chen Xiuhong\\Pictures\\suo.png"));

image.setDataHandler(dataHandler1);

image.setContentID("image_suo");

//创建文本节点

MimeBodyPart text = new MimeBodyPart();

text.setContent("这张图片是��锁","text/html;charset=UTF-8");

//创建附件节点 读取本地文件,并读取附件名称

MimeBodyPart file1 = new MimeBodyPart();

DataHandler dataHandler2 = new DataHandler(new FileDataSource("C:\\Users\\Chen Xiuhong\\Pictures\\clothes.png"));

file1.setDataHandler(dataHandler2);

file1.setFileName(MimeUtility.encodeText(dataHandler2.getName()));

MimeBodyPart file2 = new MimeBodyPart();

DataHandler dataHandler3 = new DataHandler(new FileDataSource("C:\\Users\\Chen Xiuhong\\Downloads\\list.xlsx"));

file2.setDataHandler(dataHandler3);

file2.setFileName(MimeUtility.encodeText(dataHandler3.getName()));

//将文本和图片添加到multipart

multipart.addBodyPart(text);

multipart.addBodyPart(image);

multipart.addBodyPart(file1);

multipart.addBodyPart(file2);

multipart.setSubType("mixed");//混合关系

message.setContent(multipart);

message.setSentDate(new Date());

message.saveChanges();

Transport transport = session.getTransport("smtp");

transport.connect("mail.hand-china.com","xiuhong.chen@hand-china.com","*******");

transport.sendMessage(message,message.getAllRecipients());

transport.close();

Boolean isFlag = true;

logger.info(Calendar.getInstance().getTime()+" : # Send mail to "+" success #");

System.out.println("sendMailServlet-----end2");

}

截图如下:

一般项目中是不会从本地读取文件,需要动态生成文件,这个时候我们可以把生成的文件写入inputStream中,然后传递到sendmail方法中,来创建附件节点,具体代码如下:

MimeBodyPart fileBody = new MimeBodyPart();

DataSource source = new ByteArrayDataSource(inputStream, "application/msexcel");

fileBody.setDataHandler(new DataHandler(source));

fileBody.setFileName(MimeUtility.encodeText(fileName));

4.HAP框架邮件模块详解

HAP框架提供了邮件账户,邮件模板和邮件状态查询三个功能, 我们可以在邮件账户中配置邮件服务器,端口号,以及账户名和密码. 在邮件模板中配置好将要发送的邮件模板,这个模板是HTML格式的,便于我们设置邮件正文格式.下边详细介绍每个模块的功能:

1)邮件账户配置界面:

SYS_MESSAGE_EMAIL_CONFIG : 存放配置代码config_id, 邮件服务器host, 端口号port, account_id

SYS_MESSAGE_EMAIL_ACCOUNT: 存放邮件账户配置Id, 账户代码,用户名userName 密码password

在该界面配置了发送邮件时需要准备的信息, 方便用户在前台界面动态维护, 不需要改变后台代码.

2)邮件模板配置界面

SYS_MESSAGE_TEMPLATE: 存放模板代码, 模板类型, 发送类型(直接发送/定时发送), 邮件账户(在邮件账户界面配置的账户信息) , 邮件标题和内容

其中邮件标题和正文可以设置变量, 后台在代码中可以动态改变这些变量的value 如:

MessageTemplate messageTemplate = messageTemplateMapper.getMsgTemByCode(null,"MQ_EMAIL");

String subject = messageTemplate.getSubject(); //邮件标题

subject = subject.replaceAll("company",companyName);

String content = messageTemplate.getContent(); //邮件content

Date d = new Date();

String newContent=content.replaceAll("time",sdf1.format(d))

.replaceAll("company",companyName)

.replaceAll("expireDate", String.valueOf(count2))

.replaceAll("warnDate", String.valueOf(count1));

5.发送邮件带excel附件

业务背景: 以物料为例,将非有效状态的资质数据以excel附件的形式发送邮件提醒客户. 具体步骤如下:

a. 首先要查询出非有效状态的数据 —此处不展示

b. 其次将数据写入Excel中 ( 此处是提前设置好的模板, 只需要在代码中读取模板,写入数据 )

c. 创建邮件标题和内容 ( 此处是根据框架封装的模块,在前端维护好,邮件模板和邮件账户 )

c. 查询客户邮箱 —此处不展示

d. 发送邮件

在这里重点介绍,如何将数据写入excel中,如何将excel添加到邮件中作为附件, 又是如何获得标题和模板,如何发送邮件的.数据写入excel: 读取模板—>创建工作表—>创建行—>创建单元格—>excel写入工作流

获得模板路径需要通过FreemarkerUtil来获取相对路径, 避免项目部署到服务器上时获取不到模板路径, 模板存放位置为:

/*****一个Excel文件的层次:Excel文件-> 工作表-> 行-> 单元格 对应到POI中,为:

workbook-> sheet-> row-> cell********/

String path = FreemarkerUtil.class.getClassLoader().getResource("").getPath();

String rootPath = path.substring(1, path.indexOf("/WEB-INF/"))+"/WEB-INF/excel/物料资质预警邮件模板.xlsx";

rootPath=rootPath.replace("/","\\");

FileInputStream template = new FileInputStream(rootPath);

XSSFWorkbook workBook = new XSSFWorkbook(template);

XSSFSheet sheet=workBook.getSheetAt(0);

/*水平垂直居中*/

XSSFCellStyle cellStyle = workBook.createCellStyle();

cellStyle.setAlignment(XSSFCellStyle.VERTICAL_CENTER);

cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);

/*设置字体样式*/

XSSFFont cellFont = workBook.createFont();

cellFont.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);

cellFont.setFontHeight((short) 300);

cellStyle.setFont(cellFont);

/*数据写入单元格*/

for(int j=0 ; j

rowIndex++ ;

XSSFRow row=sheet.createRow(rowIndex);

row.createCell(0).setCellValue(gxpMqInfos1.get(j).getOrganizationCode());

row.createCell(1).setCellValue(gxpMqInfos1.get(j).getOrganizationName());

row.createCell(2).setCellValue(gxpMqInfos1.get(j).getItemNo());

row.createCell(3).setCellValue(gxpMqInfos1.get(j).getItemDesc());

row.createCell(4).setCellValue(""); //产品线

row.createCell(5).setCellValue(gxpMqInfos1.get(j).getQualifTpye());

row.createCell(6).setCellValue(gxpMqInfos1.get(j).getQualifName());

row.createCell(7).setCellValue(gxpMqInfos1.get(j).getCertificateNo());

if("".equals(gxpMqInfos1.get(j).getStartDate()) || gxpMqInfos1.get(j).getStartDate() == null){

row.createCell(8).setCellValue("");

}else{

row.createCell(8).setCellValue(sdf.format(gxpMqInfos1.get(j).getStartDate()));

}

if("".equals(gxpMqInfos1.get(j).getStartDate()) || gxpMqInfos1.get(j).getStartDate() == null){

row.createCell(9).setCellValue("");

}else{

row.createCell(9).setCellValue(sdf.format(gxpMqInfos1.get(j).getEndDate()));

}

row.createCell(10).setCellValue(gxpMqInfos1.get(j).getWarningLeadTime());

row.createCell(11).setCellValue(gxpMqInfos1.get(j).getRemainingDays());

row.createCell(12).setCellValue(gxpMqInfos1.get(j).getAlertStatus());

}

/******workBook写入输出流**/

ByteArrayOutputStream baos = new ByteArrayOutputStream();

workBook.write(baos);

baos.flush();

baos.close();

下一步获取邮件账户,邮件标题,内容等

/*******7.4.1)获取界面维护的邮件模板 邮件标题和内容*/

MessageTemplate messageTemplate = messageTemplateMapper.getMsgTemByCode(null,"MQ_EMAIL");

Long accountId = messageTemplate.getAccountId(); //邮件模板表SYS_MESSAGE_TEMPLATE中的 邮件账户ID

/*根据邮件模板表SYS_MESSAGE_TEMPLATE中的邮件账户ID accountId 在邮件账户表SYS_MESSAGE_EMAIL_ACCOUNT中查询 账户(userName password)*/

MessageEmailAccount messageEmailAccount = emailAccountMapper.selectByPrimaryKey(accountId);

/*根据邮件账户表SYS_MESSAGE_EMAIL_ACCOUNT中的configId 在邮件账户配置表SYS_MESSAGE_EMAIL_CONFIG中查询 账户配置信息(host port)*/

MessageEmailConfig messageEmailConfig = messageEmailConfigMapper.selectByPrimaryKey(messageEmailAccount.getConfigId());

String host=messageEmailConfig.getHost(); //邮件服务器

String userName = messageEmailAccount.getUserName();//发送人邮件用户名

String password = messageEmailAccount.getPassword();//发送人邮件密码

String subject = messageTemplate.getSubject(); //邮件标题

subject = subject.replaceAll("company",companyName);

String content = messageTemplate.getContent(); //邮件content

Date d = new Date();

String newContent=content.replaceAll("time",sdf1.format(d))

.replaceAll("company",companyName)

.replaceAll("expireDate", String.valueOf(count2*productLineList.size()))

.replaceAll("warnDate", String.valueOf(count1*productLineList.size()));

发送邮件,将邮件标题,内容和附件名称,以及输入流传到邮件工具类中

for(String email:emailList){

/***每次都需要新建输入流 防止发送给第二个用户的时候 邮件内容为空*/

byte[] bt = baos.toByteArray();

InputStream is = new ByteArrayInputStream(bt, 0, bt.length);

MailUtil mailUtil=new MailUtil(host,userName,password);

mailUtil.sendMail(subject, email, newContent ,"物料资质预警.xlsx", is,null);

}

发送邮件,主要是添加附件:

/*添加附件*/

if(is != null) {

MimeBodyPart fileBody = new MimeBodyPart();

DataSource source = new ByteArrayDataSource(is, "application/msexcel");

fileBody.setDataHandler(new DataHandler(source));

// 中文乱码问题

fileBody.setFileName(MimeUtility.encodeText(fileName));

multipart.addBodyPart(fileBody);

}

完整的发送邮件工具类如下:

public class MailUtil {

private String host;

private String user;

private String password;

static Logger logger = LoggerFactory.getLogger(MailUtil.class);

public MailUtil(String host, String user, String password){

this.host = host;

this.user = user;

this.password = password;

}

public boolean sendMail(String subject, String toMail, String content,String fileName, InputStream is,String ccList) {

boolean isFlag = false;

try {

Properties props = new Properties();

props.put("mail.smtp.host", host); // 指定SMTP服务器

props.put("mail.smtp.auth", "true"); // 指定是否需要SMTP验证

Session session = Session.getDefaultInstance(props);

session.setDebug(false);

MimeMessage message = new MimeMessage(session);

try {

//指定发送人

message.setFrom(new InternetAddress(user));

//指定接收人

message.addRecipient(Message.RecipientType.TO, new InternetAddress(toMail));

//指定抄送人

if(ccList!=null || !"".equals(ccList)){

message.addRecipients(Message.RecipientType.CC,ccList);

}

//设置标题

message.setSubject(subject);

message.addHeader("charset", "UTF-8");

/*添加正文内容*/

//一个Multipart对象包含一个或多个bodypart对象,组成邮件正文

Multipart multipart = new MimeMultipart();

MimeBodyPart contentPart = new MimeBodyPart();

contentPart.setText(content,"UTF-8");

contentPart.setHeader("Content-Type", "text/html; charset=UTF-8");

multipart.addBodyPart(contentPart);

/*添加附件*/

if(is != null) {

MimeBodyPart fileBody = new MimeBodyPart();

DataSource source = new ByteArrayDataSource(is, "application/msexcel");

fileBody.setDataHandler(new DataHandler(source));

// 中文乱码问题

fileBody.setFileName(MimeUtility.encodeText(fileName));

multipart.addBodyPart(fileBody);

}

message.setContent(multipart);

message.setSentDate(new Date());

message.saveChanges();

Transport transport = session.getTransport("smtp");

transport.connect(host, user, password);

transport.sendMessage(message, message.getAllRecipients());

transport.close();

isFlag = true;

logger.info(Calendar.getInstance().getTime()+":#Send mail to"+toMail+"success #");

} catch (Exception e) {

logger.info(Calendar.getInstance().getTime()+":#Send mail to"+toMail+"error #");

logger.info(e.toString());

e.printStackTrace();

isFlag = false;

}

} catch (Exception e) {

e.printStackTrace();

}

return isFlag;

}

效果如下:

java邮件中添加excel_基于javaMail的邮件发送--excel作为附件相关推荐

  1. java邮件中添加excel_使用java api 创建excel内容并发送邮件

    https://github.com/auguszero/javaToolRepsitory 利用java api 创建excel 内容并发送邮件 主要实现功能: 1.通过配置文件设置发送邮件发送方, ...

  2. java channel midi_为Java程序中添加播放MIDI音乐功能

    下载本文示例代码 Java在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐做为点缀,如果播放的音乐是wav等波形音频文件,又挺大,所以背景音乐最好就是MIDI了,可是网上很多播放M ...

  3. win10邮件中添加QQ邮箱无法成功

    win10邮件中添加QQ邮箱无法成功 1.登录QQ邮箱在设置->账户将IMAP由关闭改为开启 2.如果还是无法成功,点击生成授权码 3.出现如下界面后,使用手机发送短信,待发送成功后,点击我已发 ...

  4. java注释中添加删除线_如何在Word中添加和删除注释

    java注释中添加删除线 Leaving comments in a Word document is a good way to leave feedback on a piece you're r ...

  5. 在Mac mail签名中添加的图片,接收方不显示为附件。

    邮件签名中添加的图片,在对方接收时以附件显示,搜索带附件的邮件时是否痛苦,邮件转发后各种的奇形怪状附件在邮件中,做为有强迫症的人来说怎么能忍呢. 现在就从着手解决这个问题. 以自己的笔记本为例 mac ...

  6. Java开发的B/S程序生成并向客户端发送excel文件:浅谈MIME

    Java开发的B/S程序生成并向客户端发送excel文件:浅谈MIME 1.定义 MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型.是设定 ...

  7. java 发送附件_Java 基于javaMail的邮件发送(支持附件)

    基于JavaMail的Java邮件发送 Author xiuhong.chen@hand-china.com Desc 简单邮件发送 Date 2017/12/8 项目中需要根据物料资质的状况实时给用 ...

  8. Java 基于javaMail的邮件发送(支持附件)

    基于JavaMail的Java邮件发送 Author xiuhong.chen@hand-china.com Desc 简单邮件发送 Date 2017/12/8 项目中需要根据物料资质的状况实时给用 ...

  9. java 邮件发送_Java 基于JavaMail的邮件发送

    http://blog.csdn.net/xietansheng/article/details/51673073 http://blog.csdn.net/xietansheng/article/d ...

最新文章

  1. 使用eclipse生成html格式注释文档 [ javadoc ]
  2. 十大迷你iPhone天气应用
  3. IEMLRN:基于图像增强的句子语义表示
  4. hive_0.11中文用户手册
  5. 计算机二级科目电子商务,计算机二级Web数据在电子商务中的应用解析
  6. STM32之RCC配置
  7. python装饰器传递参数_Python装饰器高级版—Python类内定义装饰器并传递self参数...
  8. im4java开发向导
  9. 素性测试AKS算法程序
  10. ElasticSearch 2 (30) - 信息聚合系列之条形图
  11. 实对称矩阵的特征值求法_对称矩阵、对角矩阵与三角矩阵
  12. 华铸CAE70(灰铁).
  13. 基于FPGA的YCbCr颜色空间中颜色参数的变化
  14. 敌退我进 锂电产业链中日韩三国演义
  15. 国内主流的大数据平台厂商有哪些?
  16. 当下推荐系统的分析和关于长尾效应的解决猜想
  17. 【LeetCode】每日一题——保持城市天际线
  18. 编写1个JSP页面,在JSP页面中使用Java程序片输出26个小写的英文字母表。
  19. 【linux系统用户管理】
  20. (区块链溯源)基于Hyperledger Fabric 的农产品区块链溯源方法

热门文章

  1. jsoup的简单实用兼谈一个简单的汇率查询(原创)
  2. Frequency-tuned Salient Region Detection (频率调谐显著性区域检测)
  3. golang直接调用ffmpeg预编译类库(windows)
  4. 编写一个应用程序:输入长方形的长度、宽度,计算长方形的周长、面积并输出:
  5. cartographer中的pose_extrapolator梳理
  6. 101.新拟物渐变加载特效
  7. 表中数据的更改量保存视图
  8. DVWA靶场系列1-环境搭建
  9. 如果你在犹豫要不要去外包公司,不妨看看这篇文章
  10. GPU_GEMS_自然态_渲染水焦散