基于Java的SMTP协议邮件发送模拟系统
目录
1. 原理分析
2. 前端页面
3. 数据库设计
4. 后端数据处理
5. 参考文献
6. 注意事项
1. 原理分析
SMTP协议
SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件
的规则,由它来控制信件的中转方式。SMTP协议属于TCP/IP协议簇,它帮助每台计算机在发送或中转信件
时找到下一个目的地。通过SMTP协议所指定的服务器,就可以把E-mail寄到收信人的服务器上了,整个过程
只要几分钟。SMTP服务器则是遵循SMTP协议的发送邮件服务器,用来发送或中转发出的电子邮件。SMTP
是一种TCP协议支持的提供可靠且有效电子邮件传输的应用层协议。
SMTP通信过程:
- 发送端邮件服务器(以下简称客户端)与接收端邮件服务器(以下简称服务器)的25号端口建立TCP连 接。
- 客户端向服务器发送各种命令,来请求各种服务(如认证、指定发送人和接收人)。
- 服务器解析用户的命令,做出相应动作并返回给客户端一个响应。
- 2)和3)交替进行,直到所有邮件都发送完或两者的 连接被意外中断。
Smtp命令(命令不区分大小写,参数区分大小写)
Smtp常见响应
501参数格式错误 |
502命令不可实现 |
503错误的命令序列 |
504命令参数不可实现 |
211系统状态或系统帮助响应 |
214帮助信息 |
220<domain>服务就绪 |
221<domain>服务关闭 |
421<domain>服务未就绪,关闭传输信道 |
250要求的邮件操作完成 |
251用户非本地,将转发向<forward-path> |
450要求的邮件操作未完成,邮箱不可用 |
550要求的邮件操作未完成,邮箱不可用 |
451放弃要求的操作;处理过程中出错 |
551用户非本地,请尝试<forward-path> |
452系统存储不足,要求的操作未执行 |
552过量的存储分配,要求的操作未执行 |
553邮箱名不可用,要求的操作未执行 |
354开始邮件输入,以"."结束 |
554操作失败 |
2. 前端页面
在SMTP协议中,我们需要一个授权码,而不是邮箱的密码,如何开启邮箱的SMTP协议服务请查看以下文章
https://www.cnblogs.com/shangdawei/p/4305989.html
这位大神已经写好了;开启了SMTP服务后,我们就正式入手我们的项目了。我们是模拟邮箱发送,想一想业务逻辑,思路很清晰,分为
注册(注册的时候输入我们的邮箱和对应的授权码而不是邮箱的密码;授权码就是刚刚在开启SMTP协议的时候自己设置的授权码);
登录(从数据库调出数据进行判断)
发送页面
注册页面register.html
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Register</title><link rel="stylesheet" href="./css/Register.css"><script src="./js/register.js"></script>
</head>
<body><form action="./RegisterDo" method="POST" onsubmit="return check()"><div id="con"><div style="background-color:rgba(255, 255, 255, 0);">Register</div><div><label for="username">用户名</label><input type="text" id="username" name="username" autocomplete="off" required></div><div><label for="password">密码</label><input type="password" id="password" name="password" required></div><div><label for="ConfirmPass">确认密码</label><input type="password" id="ConfirmPass" name="ConfirmPass" required></div><div><button type="submit">注 册</button></div></div></form>
</body>
</html>
登录页面Login.html
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Login</title><link rel="stylesheet" href="./css/Login.css">
</head>
<body><div id="Hp"><img src="http://baiducdn.pig66.com/uploadfile/2017/0511/20170511074941526.jpg" alt="头像丢失了"></div><form action="./LoginDo" method="POST"><div id="show"><table><tr><td><input type="text" name="username" placeholder=" Username" class="inp1"></td></tr><tr><td><input type="password" name="password" placeholder=" Password" class="inp1"></td></tr><tr><td><span><input type="checkbox" name="" class="inp2"></span><span class="sp1">Remenmber Me</span><span class="sp2"><a href="register.html">Reqister</a></span></td></tr><tr><td><input type="submit" value="LOGIN" class="bt"></td></tr></table></div></form>
</body>
</html>
发送页面sendmail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>发送邮件</title><link rel="stylesheet" href="./css/sendmail.css"><script src="./js/jquery-3.2.1.min.js"></script>
</head><body><form action="./SendDO" method="post"><div class="box"><div class="box20"><span></span><input type="text" name="username" value=<%=request.getAttribute("username")%>></div><div class="box20"><span></span><input type="text" name="password" value=<%=request.getAttribute("password")%>></div><div class="h"><hr><h1>XX制作制作->欢迎<%=request.getAttribute("username")%>使用模拟邮件发送器网页版</h1><hr></div><div class="box1"><span>收件人:</span><input type="text" name="receiverName" id="receiver" required></div><div class="box2"><span>主 题:</span><input type="text" name="titlename" id="theme" required></div><div class="box3"><span>正 文:</span><textarea name="infoName" id="info" cols="76" rows="10" required></textarea></div><div class="last"><input type="submit" value="发送" id="send"><input type="reset" value="重写" id="reset"></div></div></form>
</body></html>
CSS文件:
Register.css
body{background: url("../imge/3.jpg");background-size: cover;
}#con{color: rgb(245, 243, 243);width: 600px;height: 280px;margin: auto;margin-top: 200px;background-color: rgba(0, 0, 0, 0.4);vertical-align:middle;text-align: center;border-radius: 15px;
}
#con div{margin: auto;width: 500px;margin-top: 15px;font-size: 20px;display:inline-block;background-color: darkorange;
}
.div{background-color: rgba(253, 253, 253, 0);
}
#con label{text-align: center;width: 20%;height: 30px;line-height: 30px;float: left;
}
#con input{width: 79%;height: 30px;font-size: 20px;padding: 0 0;
}
#con button{color:white;width: 100%;font-size: 20px;background-color: aqua;
}
#con button:hover{background-color: rgb(102, 255, 0);
}
Login.css
body{height: 100%;margin: 0 0;background: url(https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1557133865275&di=ddbdf1e859e5bbc82cc91298b45a4f7c&imgtype=0&src=http%3A%2F%2Fpic164.nipic.com%2Ffile%2F20180509%2F18980004_153526848038_2.jpg); background-size: cover;
}
#Hp{margin-top: 100px;height: 100px;line-height: 100px;text-align: center;
}
#Hp img{width: 120px;height: 120px;border-radius: 50%;margin: auto;border:3px solid #fff;
}
#show{width: 400px;margin:auto;margin-top: 50px;font-family: '楷体';font-size: 20px;background:rgba(41, 31, 180, 0.30);border-radius: 5px;border: 1.5px solid #ffffff;
}
#show table{margin:auto;width: 100%;border-spacing: 25px;}
.inp1{background:rgba(41, 31, 180, 0.2);font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;font-size: 25px;color: rgb(255, 255, 255);width: 100%;border-radius: 8px;border: 0;
}
.inp2{width:15px;height:15px;
}
.sp1{font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color: #cdcedb;
}input::-webkit-input-placeholder{color:#cdcedb;
}
.sp2{font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color:#cdcedb;position: relative;float: right;margin-right: 2px;
}
.sp2 a{font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;color:#cdcedb;width:20px;height:20px;text-decoration: none;
}
.sp2 a:hover{color: rgb(80, 71, 202);
}
input.bt{background-color: aqua;width: 100%;border-radius: 4px;border: 0;font-size: 25px;color: rgb(133, 133, 133);
}
.bt:hover{background-color: rgba(80, 71, 202, 0.774);
}
sendmail.css
body {padding: 0;margin: 0;background: url(../imge/7.jpg);background-size: cover;
}
.h{background-color: rgb(180, 214, 246);
}
h1{margin-left: 55px;
}
.box {width: 1200px;height: 710px;margin: auto;margin-top: 50px;background-color: #D2E9FF;
}
.box1 {height: 50px;width: 100%;margin-top: 15px;
}.box2 {height: 50px;width: 100%;
}.box3 {height: 400px;width: 100%;
}
.box3>textarea{width: 1000px;font-size: 25px;
}.box span {display: block;height: 50px;width: 80px;float: left;text-align: center;line-height: 50px;margin-left: 55px;
}.box input {display: block;height: 20px;width: 1000px;float: left;margin-top: 13px;
}#info {height: 400px;overflow: hidden;margin-top: 15px;
}.last {width: 100%;height: 100px;
}#send{width: 70px;height: 30px;background-color: rgb(163, 147, 147); color: rgb(255, 255, 255);margin-top: 40px;font-family: "楷体";border-radius: 10px;border:0px;margin-left: 850px;
}
#send:hover{background-color: rgb(212, 82, 82);
}
#reset{width: 70px;height: 30px;background-color: rgb(163, 147, 147); color: white;margin-top: 40px;font-family: "楷体";border-radius: 10px;border:0px;margin-left: 50px;
}
#reset:hover{background-color: rgb(212, 82, 82);
}
.box20{display: none;
}
js文件:除了以下两个js文件还需要Jquery.js,这个在网上可以下载
register.js
function check(){var username=document.getElementById("username");var password=document.getElementById("password");var regex = /^\w+@\w+.\w+\.?\w+$/;if(!regex.test(username.value)){alert("邮件格式错误!请检查格式!");return false;}if(password.value.length<3){alert("密码长度必须大于3个字符!");return false;}var ConfirmPass=document.getElementById("ConfirmPass");if(ConfirmPass.value!=password.value){alert("两次输入的密码不一致!");return false;}
}
sendmail.js
var regex = /^\w+@\w+.\w+\.?\w+$/;
$(document).ready(function () {$("#receiver").blur(function () {if (!regex.test($("#receiver").val())) {alert("邮箱格式错误!请输入正确的邮箱!");}});$("#reset").click(function (){$("#info").val("");});
});
3. 数据库设计
数据库设计很简单,我们只需要存储用户名和对应的授权码;数据库代码如下
/*
Navicat MySQL Data TransferSource Server : MySQL
Source Server Version : 50617
Source Host : localhost:3306
Source Database : popmailTarget Server Type : MYSQL
Target Server Version : 50617
File Encoding : 65001Date: 2019-05-07 22:22:15
*/SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`username` varchar(25) NOT NULL,`password` varchar(25) NOT NULL,PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
4. 后端数据处理
前端页面和数据库设置已经设置好了,接下来就是对前端传输的数据给后端进行处理,首先要完成注册,要将前端页面的数据存入到数据库中,基于Java的话就选择jdbc。另外要发送邮件还需要一个javax.mail.jar的jar包
连接器下载:https://dev.mysql.com/downloads/connector/j/
javax.mail.jar下载:https://mvnrepository.com/artifact/javax.mail/smtp
下载好放在项目下的WebContent的WEB-INF的lib文件夹下面。
完成以上步骤后我们就可以开始编写代码了。
为了方便我们查询数据库,先写一个jdbc工具类
JDBCTools.java
package com.mail.chtw.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class JDBCTools {private Connection conn;private PreparedStatement ps;private ResultSet rs;public JDBCTools() {//一.加载驱动类try {Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}//二.应用层/*** 1.获取连接* @return* @throws SQLException */public Connection getConnetion() throws SQLException {//三个参数(url,用户,密码)conn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/popmail","root","数据库密码");return conn;}public ResultSet executeQuery(String sql,Object ...obj) {//...可变参数try {//1.产生连接conn = getConnetion();//2.用连接产生prepareStatementps = conn.prepareStatement(sql);//3.设置所有参数for (int i = 0; i < obj.length; i++) {ps.setObject(i+1, obj[i]);}//4.执行查询,产生结果集rs=ps.executeQuery();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return rs;}//增删改public int executeUpdate(String sql,Object ...obj) {int count = 0;try {conn = getConnetion();ps = conn.prepareStatement(sql);for (int i = 0; i < obj.length; i++) {ps.setObject(i+1, obj[i]);}count = ps.executeUpdate();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return count;}//关闭资源public void close() {try {rs.close();ps.close();conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
RegisterDo.java
package com.mail.chtw.html;import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import com.mail.chtw.jdbc.JDBCTools;@WebServlet("/RegisterDo")
public class RegisterDo extends HttpServlet {private static final long serialVersionUID = 1L;protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username =request.getParameter("username");String password = request.getParameter("password");JDBCTools tools = new JDBCTools();response.setContentType("text/html;charset=UTF-8");String sql = "select * from user where username=?";String sql1 = "insert into user value(?,?)";ResultSet rs = tools.executeQuery(sql,username);try {if(rs.next()) {response.getWriter().print("<script>alert('注册失败!该账号已被注册!请重试!');location='register.html';</script>");}else {tools.executeUpdate(sql1, username,password);response.getWriter().print("<script>alert('注册成功!请登录!');location='Login.html';</script>");}} catch (SQLException e) {e.printStackTrace();}}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}
LoginDo.java
package com.mail.chtw.html;import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import com.mail.chtw.jdbc.JDBCTools;@WebServlet("/LoginDo")
public class LoginDo extends HttpServlet {private static final long serialVersionUID = 1L;public LoginDo() {super();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username =request.getParameter("username");String password = request.getParameter("password");JDBCTools tools = new JDBCTools();response.setContentType("text/html;charset=UTF-8");String sql = "select password from user where username=? and password=?";ResultSet rs = tools.executeQuery(sql,username,password);try {if(rs.next()) {request.setAttribute("username",username);request.setAttribute("password", password);request.getRequestDispatcher("./SendMail.jsp").forward(request, response);}else {response.getWriter().print("<script>alert('登录失败!账号或密码错误!请重试!');location='Login.html';</script>");}} catch (SQLException e1) {e1.printStackTrace();}}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}}
SendDO.java
package com.mail.chtw.html;import java.io.IOException;
import java.util.Date;
import java.util.Properties;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@WebServlet("/SendDO")
public class SendDO extends HttpServlet {private static final long serialVersionUID = 1L;public SendDO() {super();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String myemail = request.getParameter("username");String p = request.getParameter("password");String re = request.getParameter("receiverName");String title =new String(request.getParameter("titlename").getBytes("ISO8859-1"),"UTF-8");String body =new String(request.getParameter("infoName").getBytes("ISO8859-1"),"UTF-8");request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");try {connect(myemail,p,title,re,body);request.setAttribute("username",myemail);request.setAttribute("password", p);request.getRequestDispatcher("./SendMail.jsp").forward(request, response);} catch (Exception e) {e.printStackTrace();}}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}public static MimeMessage createMimeMessage(Session session, String sendMail,String title,String receiveMail,String body) throws Exception {// 1. 创建邮件MimeMessage message = new MimeMessage(session); // 2. 发件人message.setFrom(new InternetAddress(sendMail));// 3. 收件人(可以增加多个收件人、抄送、密送)message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiveMail));// 4. 邮件主题message.setSubject(title);// 5. 邮件正文message.setContent(body, "text/html;charset=UTF-8");// 6. 设置发件时间message.setSentDate(new Date());// 7. 保存设置message.saveChanges();return message;}public void connect(String myemail,String p,String title,String re,String body) throws Exception {String myEmailAccount = myemail;String myEmailPassword = p;// 发件人邮箱的 SMTP 服务器地址String myEmailSMTPHost = "smtp.163.com";// 收件人邮箱(替换为自己知道的有效邮箱)String receiveMailAccount = re;Properties props = new Properties(); // 参数配置props.setProperty("mail.transport.protocol", "smtp"); // 使用的协议props.setProperty("mail.smtp.host", myEmailSMTPHost); // 发件人的邮箱的 SMTP 服务器地址props.setProperty("mail.smtp.auth", "true"); // 需要请求认证// 2. 根据配置创建会话对象, 用于和邮件服务器交互Session session = Session.getInstance(props);// 设置为debug模式, 可以查看详细的发送 logsession.setDebug(true);// 3. 创建一封邮件MimeMessage message = createMimeMessage(session, myEmailAccount, title,receiveMailAccount,body);// 4. 根据 Session 获取邮件传输对象Transport transport = session.getTransport();// 5. 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错transport.connect(myEmailAccount, myEmailPassword);// 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人transport.sendMessage(message, message.getAllRecipients());// 7. 关闭连接transport.close();}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"><display-name>POPmail</display-name><welcome-file-list><welcome-file>Login.html</welcome-file></welcome-file-list><servlet><servlet-name>RegisterDo</servlet-name><servlet-class>com.mail.chtw.html.RegisterDo</servlet-class></servlet><servlet><servlet-name>LoginDo</servlet-name><servlet-class>com.mail.chtw.html.LoginDo</servlet-class></servlet><servlet><servlet-name>SendDo</servlet-name><servlet-class>com.mail.chtw.html.SendDo</servlet-class></servlet><servlet-mapping><servlet-name>RegisterDo</servlet-name><url-pattern>/reg/</url-pattern></servlet-mapping>
</web-app>
5. 参考文献
SMTP协议:https://blog.csdn.net/qq_35644234/article/details/68961603
数据库安装配置:https://blog.csdn.net/chen_hao_181/article/details/83861507
邮箱开启SMTP服务:https://www.cnblogs.com/shangdawei/p/4305989.html
6. 注意事项
上面文件中所有以数字命名的图片都需要自己找,并放在指定的文件夹中。这种做法有一个小缺点,就是邮件发送成功后没有提示,但是我们可以从eclipse控制台中看出来发送成功了。
本网站只实现了163邮箱的发送。
欢迎关注熊熊出没ING公众号,不定时跟新Java、python、信息安全等相关知识哦。
基于Java的SMTP协议邮件发送模拟系统相关推荐
- 发送邮件(支持所有smtp协议邮件发送)
1.所需包: javax.mail.jar maven : <!-- https://mvnrepository.com/artifact/javax.mail/mail --> < ...
- SMTP 协议邮件发送工具封装
文章目录 1. 前言 1.1 说明 1.2 建议 1.3 源码 2. 发件人邮箱开通smtp 服务 2.1 为什么开通smtp 服务 2.2 开启服务的步骤 2.3 普通邮箱开启服务图文 3. 工具类 ...
- smtp协议——邮件发送
根据自己使用的邮件服务器,完成smtp协议的服务开启 给特定邮箱发送图文并茂的邮件,邮件正文包含的表格如下所示,显示的图片自己确定. 给特定邮箱发送邮件,邮件附件为"实验报告7 smtp协议 ...
- SMTP协议及POP3协议-邮件发送和接收原理(转)
本文转自https://blog.csdn.net/qq_15646957/article/details/52544099 感谢作者 一. 邮件开发涉及到的一些基本概念 1.1.邮件服务器和电子邮箱 ...
- JavaWeb(三):java和javaWeb实现邮件发送
JavaWeb-实现邮件发送 学习视频:B站 狂神说Java – https://www.bilibili.com/video/BV12J41137hu?p=1 学习资料笔记:csdn dream_F ...
- 使用JAVA工具类进行邮件发送
使用JAVA工具类进行邮件发送 使用JAVA工具类进行邮件发送 文章目录 使用JAVA工具类进行邮件发送 前言 一.前期准备工作 二.使用步骤 1.引入依赖 2.进行发送邮件 前言 提示:我们在开发过 ...
- 基于python的图形化邮件发送程序(支持添加附件)
2019独角兽企业重金招聘Python工程师标准>>> 开发环境:centos7 基于:python3.5 调用库:tkinter smtplib email linux中类outl ...
- java进行qq邮箱邮件发送
1.首先你得开启你的qq的邮箱权限 在qq邮箱中的设置中设置IMAP/SMTP import java.util.Properties;import javax.mail.Authenticator; ...
- java邮件支持_使用Spring的JAVA Mail支持简化邮件发送功能
闲来无事,翻看<Spring in Action>,发现Spring集成了对JAVA Mail的支持,有点小激动的看了一遍,嗯,话说真的简单了很多. Spring的邮件发送的核心是Mail ...
最新文章
- struts2下的helloworld(如何让第一个struts2跑起来)——struts2第一讲
- 三个获取浏览器URL中参数值的方法
- 南瑞变压器保护装置说明书_深圳宝安变压器维修公司
- CRM WebClient UI和Hybris里工作中心跳转的url生成逻辑
- 驱动开发中常用的操作和小知识
- 2022中国素质教育行业报告
- 【C】揭秘rand()函数;
- matlab 和 ampl 结合,AMPL和MATLAB结合使用示例
- 生产计划管理系统实现生产计划流程完美结合
- 目标规划运筹学例题doc_第八章 运筹学 目标规划 案例.doc
- 【蓝桥杯】第八届java A组题详解
- 联想ideapad710s的win10转win7
- 目标客户画像_如何定义目标客户和用户画像
- ppt 计算机图标不见了,显示桌面图标不见了如何恢复.ppt
- overflow与absolute的关系
- 【笔记】MyBatis 大于等于小于等于常用写法
- 《黑客帝国 THE MATRIX》——当你生活在代码的虚拟世界中
- axure字符图标 web字体 iconfont配置
- 老猪带你玩转自定义控件三——sai大神带我实现ios 8 时间滚轮控件
- Linux驱动开发之常见error汇总