最近项目中需要发送邮件 功能 本项目中代码
前端jsp页面代码
sendEmail.jsp
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/webpage/include/taglib.jsp"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="decorator" content="default"/>
<!-- SUMMERNOTE -->
<link href="${ctxStatic}/summernote/summernote.css" rel="stylesheet">
<link href="${ctxStatic}/summernote/summernote-bs3.css" rel="stylesheet">
<script src="${ctxStatic}/summernote/summernote.min.js"></script>
<script src="${ctxStatic}/summernote/summernote-zh-CN.js"></script>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content">
<sys:message content="${message}"/>
<div class="row">
<div class="col-sm-12 animated fadeInRight">
<div class="mail-box-header">
<c:if test="${'0' eq userSend }">
<div class="pull-right tooltip-demo">
<button class="btn btn-white btn-sm" data-toggle="tooltip" data-placement="left" οnclick="editSmtp()"><i class="fa fa-file-text-o"></i> 设置邮箱服务器</button>
<table:importExcel url="${ctx}/tools/email/importEmail" title="导入Excel发送"></table:importExcel>
</div>
</c:if>
<h2>
写邮件
</h2>
</div>
<div class="mail-box">
<div class="mail-body">
<form:form id="inputForm" modelAttribute="mailBox" action="${ctx}/tools/email/send" method="post" class="form-horizontal">
<input type="hidden" name="userSend" value="${userSend }">
<div class="form-group">
<label class="col-sm-2 control-label"><font color="red">*</font>发送到:</label>
<div class="col-sm-8">
<input type="text" placeholder="输入多个邮件地址请用英文符号;隔开" id="emailAddress" name="emailAddress" class="form-control" value="${emails }">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"><font color="red">*</font>主题:</label>
<div class="col-sm-8">
<input type="text" id="title" name="title" class="form-control" value="">
</div>
</div>
<input type="hidden" id="content" name="content"><!-- 内容 -->
</form:form>
</div>
<div class="mail-text h-200">
<div class="summernote">
</div>
<div class="clearfix"></div>
</div>
<div class="mail-body text-right tooltip-demo">
<button type="button" class="btn btn-primary btn-sm" οnclick="sendLetter()"> <i class="fa fa-reply"></i> 发送</button>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.i-checks').iCheck({
checkboxClass: 'icheckbox_square-green',
radioClass: 'iradio_square-green',
});
$('.summernote').summernote({
lang: 'zh-CN'
});
});
var edit = function () {
$('.click2edit').summernote({
focus: true
});
};
var save = function () {
var aHTML = $('.click2edit').code(); //save HTML If you need(aHTML: array).
$('.click2edit').destroy();
};
function sendLetter(){
if($("#emailAddress").val()==''){
top.layer.alert('收件人不能为空!', {icon: 0});
return;
}
if($("#title").val()==''){
top.layer.alert('主题不能为空!', {icon: 0});
return;
}
$("#content").val($(".note-editable").html());
var index = layer.load(1, {
shade: [0.3,'#fff'] //0.1透明度的白色背景
});
$("#inputForm").submit();
}
function editSmtp(){
openDialog("设置邮箱服务器","${ctx}/tools/email/setSmtp","600px", "400px","${target}");
}
</script>
</body>
</html>
emailSmtpForm.jsp
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/webpage/include/taglib.jsp"%>
<html>
<head>
<title>邮件服务器设置</title>
<meta name="decorator" content="default"/>
<script type="text/javascript">
var validateForm;
function doSubmit(){//回调函数,在编辑和保存动作时,供openDialog调用提交表单。
if(validateForm.form()){
$("#inputForm").submit();
return true;
}
return false;
}
$(document).ready(function() {
validateForm = $("#inputForm").validate({
submitHandler: function(form){
loading('正在提交,请稍等...');
form.submit();
},
errorContainer: "#messageBox",
errorPlacement: function(error, element) {
$("#messageBox").text("输入有误,请先更正。");
if (element.is(":checkbox")||element.is(":radio")||element.parent().is(".input-append")){
error.appendTo(element.parent().parent());
} else {
error.insertAfter(element);
}
}
});
});
</script>
</head>
<body class="hideScroll">
<form:form id="inputForm" modelAttribute="systemConfig" action="${ctx}/tools/email/saveSmtp" method="post" class="form-horizontal">
<form:hidden path="id"/>
<form:hidden path="smsName"/>
<form:hidden path="smsPassword"/>
<table class="table table-bordered table-condensed dataTables-example dataTable no-footer">
<tbody>
<tr>
<td class="active" width="25%"><label class="pull-right"><font color="red">*</font>邮箱服务器地址:</label></td>
<td>
<form:select path="smtp" class="form-control required">
<form:option value="" label=""/>
<form:options items="${fns:getDictList('smtp')}" itemLabel="label" itemValue="value" htmlEscape="false"/>
</form:select>
</td>
</tr>
<tr>
<td class="active"><label class="pull-right"><font color="red">*</font>邮箱服务器端口:</label></td>
<td>
<form:input path="port" htmlEscape="false" class="form-control number"/>
</td>
</tr>
<tr>
<td class="active"><label class="pull-right"><font color="red">*</font>是否开启SSL:</label></td>
<td>
<form:radiobuttons path="openSSL" items="${fns:getDictList('yes_no')}" itemLabel="label"
itemValue="value" htmlEscape="false" class="i-checks required"/>
</td>
</tr>
<tr>
<td class="active"><label class="pull-right"><font color="red">*</font>系统邮箱地址:</label></td>
<td>
<form:input path="mailName" htmlEscape="false" class="form-control"/>
</td>
</tr>
<tr>
<td class="active"><label class="pull-right"><font color="red">*</font>系统邮箱密码:</label></td>
<td>
<form:input path="mailPassword" htmlEscape="false" class="form-control"/>
</td>
</tr>
</tbody>
</table>
</form:form>
</body>
</html>
sendEmailResult.jsp
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/webpage/include/taglib.jsp"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="decorator" content="default"/>
<!-- SUMMERNOTE -->
<link href="${ctxStatic}/summernote/summernote.css" rel="stylesheet">
<link href="${ctxStatic}/summernote/summernote-bs3.css" rel="stylesheet">
<script src="${ctxStatic}/summernote/summernote.min.js"></script>
<script src="${ctxStatic}/summernote/summernote-zh-CN.js"></script>
</head>
<body class="gray-bg">
<div class="lock-word animated fadeInDown">
</div>
<div class="middle-box text-center lockscreen animated fadeInDown" style="width:400px">
<div>
<div class="m-b-md">
<img alt="image" style="width:150px;"class="img-circle circle-border" src="${ctxStatic}/images/success.jpg">
</div>
<sys:message hideType="0" content="${result}"/>
<c:if test="${'0' eq userSend }">
<form class="m-t" role="form" action="index.html">
<a href="${ctx}/tools/email" class="btn btn-primary block full-width">返回</a>
</form>
</c:if>
</div>
</div>
</body>
</html>
在 用户管理页面 也有发送邮件功能 jsp如下
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/webpage/include/taglib.jsp"%>
<html>
<head>
<title>用户管理</title>
<meta name="decorator" content="default"/>
<script type="text/javascript">
function sendLetter(){
var ids="";
$("#contentTable tbody tr td input.i-checks:checkbox").each(function(){
if(true == $(this).is(':checked')){
ids += $(this).attr("id")+",";
}
});
if(ids.substr(ids.length-1) == ','){
ids = ids.substr(0, ids.length-1);
}
if(ids == ""){
top.layer.alert('请至少选择一条数据!', {icon: 0, title:'警告'});
return;
}
openDialogView('发送邮件', '${ctx}/tools/email/index?ids='+ids,'1200px', '630px');
}
</script>
</head>
<body>
<div class="wrapper wrapper-content">
<sys:message content="${message}"/>
<!-- 查询条件 -->
<div class="row">
<div class="col-sm-12">
<form:form id="searchForm" modelAttribute="user" action="${ctx}/sys/user/list" method="post" class="form-inline">
<input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}"/>
<input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}"/>
<table:sortColumn id="orderBy" name="orderBy" value="${page.orderBy}" callback="sortOrRefresh();"/><!-- 支持排序 -->
<div class="form-group">
<span>归属公司:</span>
<sys:treeselect id="company" name="company.id" value="${user.company.id}" labelName="company.name" labelValue="${user.company.name}"
title="公司" url="/sys/office/treeData?type=1" cssClass=" form-control input-sm" allowClear="true" cssStyle="width:150px"/>
<span>登录名:</span>
<form:input path="loginName" htmlEscape="false" maxlength="30" class=" form-control input-sm" style="width:150px"/>
<span>归属部门:</span>
<sys:treeselect id="office" name="office.id" value="${user.office.id}" labelName="office.name" labelValue="${user.office.name}"
title="部门" url="/sys/office/treeData?type=2" cssClass=" form-control input-sm" allowClear="true" notAllowSelectParent="true" cssStyle="width:150px"/>
<span>姓 名:</span>
<form:input path="name" htmlEscape="false" maxlength="30" class=" form-control input-sm" style="width:150px"/>
<span>人员类别:</span>
<form:select path="personType" class="form-control m-b">
<form:option value="" label=""/>
<form:options items="${fns:getDictList('personType')}" itemLabel="label" itemValue="value" htmlEscape="false"/>
</form:select>
</div>
</form:form>
<br/>
</div>
</div>
<!-- 工具栏 -->
<div class="row">
<div class="col-sm-12">
<div class="pull-left">
<shiro:hasPermission name="sys:user:add">
<table:addRow url="${ctx}/sys/user/form" title="用户" width="800px" height="625px"></table:addRow><!-- 增加按钮 -->
</shiro:hasPermission>
<shiro:hasPermission name="sys:user:edit">
<table:editRow url="${ctx}/sys/user/form" id="contentTable" title="用户" width="800px" height="680px"></table:editRow><!-- 编辑按钮 -->
</shiro:hasPermission>
<shiro:hasPermission name="sys:user:del">
<table:delRow url="${ctx}/sys/user/deleteAll" id="contentTable"></table:delRow><!-- 删除按钮 -->
</shiro:hasPermission>
<shiro:hasPermission name="sys:user:import">
<table:importExcel url="${ctx}/sys/user/import"></table:importExcel><!-- 导入按钮 -->
</shiro:hasPermission>
<shiro:hasPermission name="sys:user:export">
<table:exportExcel url="${ctx}/sys/user/export"></table:exportExcel><!-- 导出按钮 -->
</shiro:hasPermission>
<button class="btn btn-white btn-sm " data-toggle="tooltip" data-placement="left" οnclick="sortOrRefresh()" title="刷新"><i class="glyphicon glyphicon-repeat"></i> 刷新</button>
<button type="button" class="btn btn-white btn-sm" οnclick="sendLetter()"> <i class="fa fa-pencil"></i> 发送邮件</button>
</div>
<div class="pull-right">
<button class="btn btn-primary btn-rounded btn-outline btn-sm " οnclick="search()" ><i class="fa fa-search"></i> 查询</button>
<button class="btn btn-primary btn-rounded btn-outline btn-sm " οnclick="reset()" ><i class="fa fa-refresh"></i> 重置</button>
</div>
</div>
</div>
<table id="contentTable" class="table table-striped table-bordered table-hover table-condensed dataTables-example dataTable">
<thead>
<tr>
<th><input type="checkbox" class="i-checks"></th>
<th class="sort-column login_name">登录名</th>
<th class="sort-column name">姓名</th>
<th class="sort-column mobile">手机</th>
<th class="sort-column email">邮箱</th>
<th class="sort-column c.name">归属公司</th>
<th class="sort-column o.name">归属部门</th>
<th class="sort-column o.name">人员类别</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${page.list}" var="user">
<tr>
<td> <input type="checkbox" id="${user.id}" class="i-checks"></td>
<td><a href="#" οnclick="openDialogView('查看用户', '${ctx}/sys/user/form?id=${user.id}','800px', '680px')">${user.loginName}</a></td>
<td>${user.name}</td>
<td>${user.mobile}</td>
<td>${user.email}</td>
<td>${user.company.name}</td>
<td>${user.office.name}</td>
<td>${fns:getDictLabel(user.personType, 'personType', '')}</td>
<td>
<shiro:hasPermission name="sys:user:view">
<a href="#" οnclick="openDialogView('查看用户', '${ctx}/sys/user/form?id=${user.id}','800px', '680px')" class="btn btn-info btn-xs" ><i class="fa fa-search-plus"></i> 查看</a>
</shiro:hasPermission>
<shiro:hasPermission name="sys:user:edit">
<a href="#" οnclick="openDialog('修改用户', '${ctx}/sys/user/form?id=${user.id}','800px', '700px', 'officeContent')" class="btn btn-success btn-xs" ><i class="fa fa-edit"></i> 修改</a>
</shiro:hasPermission>
<shiro:hasPermission name="sys:user:del">
<a href="${ctx}/sys/user/delete?id=${user.id}" οnclick="return confirmx('确认要删除该用户吗?', this.href)" class="btn btn-danger btn-xs"><i class="fa fa-trash"></i> 删除</a>
</shiro:hasPermission>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<table:page page="${page}"></table:page>
</div>
</body>
</html>
对应的controller如下:EmailController.java
/**
* Copyright © 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
*/
package com.jeeplus.modules.tools.web;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.google.common.collect.Lists;
import com.jeeplus.common.config.Global;
import com.jeeplus.common.mail.MailSendUtils;
import com.jeeplus.common.utils.StringUtils;
import com.jeeplus.common.utils.excel.ExportExcel;
import com.jeeplus.common.utils.excel.ImportExcel;
import com.jeeplus.common.utils.excel.annotation.ExcelField;
import com.jeeplus.common.web.BaseController;
import com.jeeplus.modules.rgssys.entity.SalaryDetailInfo;
import com.jeeplus.modules.sys.entity.SystemConfig;
import com.jeeplus.modules.sys.entity.User;
import com.jeeplus.modules.sys.service.SystemConfigService;
import com.jeeplus.modules.sys.utils.UserUtils;
/**
* 发送外部邮件
* @author lgf
* @version 2016-01-07
*/
@Controller
@RequestMapping(value = "${adminPath}/tools/email")
public class EmailController extends BaseController {
@Autowired
private SystemConfigService systemConfigService;
/**
* 打开邮件页面
*/
@RequestMapping(value = {"index", ""})
public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
String ids = request.getParameter("ids");
if(StringUtils.isNotBlank(ids)){
String[] idArr = ids.split(",");
StringBuffer emailsStr = new StringBuffer();
for(String id : idArr){
User user = UserUtils.get(id);
if(StringUtils.isNotBlank(user.getEmail())){
emailsStr.append(user.getEmail()).append(";");
}
}
model.addAttribute("emails", emailsStr.toString());
model.addAttribute("userSend", "1");
}else{
model.addAttribute("userSend", "0");
}
return "modules/tools/sendEmail";
}
/**
* 发送邮件
*/
@RequestMapping("send")
public String send(String emailAddress, String userSend, HttpServletResponse response, String title, String content, Model model) throws Exception {
SystemConfig config = systemConfigService.get("1");
String[]addresses = emailAddress.split(";");
String result = "";
for(String address: addresses){
boolean isSuccess = MailSendUtils.sendEmail(config.getSmtp(), config.getPort(), config.getOpenSSL(), config.getMailName(),
config.getMailPassword(), address, title, StringEscapeUtils.unescapeHtml4(content), "2");
if(isSuccess){
result += address+":<font color='green'>发送成功!</font><br/>";
}else{
result += address+":<font color='red'>发送失败!</font><br/>";
}
}
model.addAttribute("result", result);
model.addAttribute("userSend", userSend);
return "modules/tools/sendEmailResult";
}
/**
* 下载Excel邮件数据模板
*/
@RequestMapping(value = "importEmail/template")
public String importEmailTemplate(HttpServletResponse response, RedirectAttributes redirectAttributes) {
try {
String fileName = "Excel邮件模板.xlsx";
List<SalaryDetailInfo> list = Lists.newArrayList();
new ExportExcel("工资明细", SalaryDetailInfo.class, 1).setDataList(list).write(response, fileName).dispose();
return null;
} catch (Exception e) {
addMessage(redirectAttributes, "导入模板下载失败!失败信息:"+e.getMessage());
}
return "redirect:"+Global.getAdminPath()+"/tools/email/?repage";
}
/**
* Excel发送邮件
*/
@RequestMapping(value = "importEmail", method=RequestMethod.POST)
public String importFile(MultipartFile file, RedirectAttributes redirectAttributes, Model model) {
StringBuilder failureMsg = new StringBuilder();
StringBuilder successMsg = new StringBuilder();
try {
SystemConfig config = systemConfigService.get("1");
ImportExcel ei = new ImportExcel(file, 1, 0);
List<SalaryDetailInfo> list = ei.getDataList(SalaryDetailInfo.class);
for (SalaryDetailInfo info : list){
if(StringUtils.isBlank(info.getEmail())){
continue;
}
StringBuffer title = new StringBuffer();
title.append(info.getMonth() + "月" + info.getEmployeeName() +"(" + info.getEmployeeID() + ")工资明细表");
StringBuffer content = new StringBuffer();
Field[] fields = info.getClass().getDeclaredFields();
for(Field filed : fields){
String type = filed.getGenericType().toString();
if(!type.endsWith("Double")){
continue;
}
String name = filed.getName();
name = name.substring(0, 1).toUpperCase() + name.substring(1);
Method m = info.getClass().getMethod("get"+name);
Double value = (Double) m.invoke(info);
ExcelField ef = m.getAnnotation(ExcelField.class);
if(value != null){
content.append(ef.title()+":" + value.toString() + "<br/>");
}
}
boolean isSuccess = MailSendUtils.sendEmail(config.getSmtp(), config.getPort(), config.getOpenSSL(), config.getMailName(),
config.getMailPassword(), info.getEmail(), title.toString(), StringEscapeUtils.unescapeHtml4(content.toString()), "2");
if(isSuccess){
successMsg.append(info.getEmail()).append(";");
}else{
failureMsg.append(info.getEmail()).append(";");
}
}
} catch (Exception e) {
e.printStackTrace();
addMessage(redirectAttributes, "导入失败!失败信息:"+e.getMessage());
return "redirect:"+Global.getAdminPath()+"/tools/email/?repage";
}
String result = "";
if(successMsg.length() > 0){
successMsg.append("发送成功!");
result += successMsg.toString();
}
if(failureMsg.length() > 0){
failureMsg.append("发送失败!");
result += "<br>" + failureMsg.toString();
}
model.addAttribute("result", result);
return "modules/tools/sendEmailResult";
}
/**
* 设置邮箱服务器
* @param model
* @return
*/
@RequestMapping(value = "setSmtp")
public String setSmtp(Model model){
SystemConfig systemConfig = systemConfigService.get("1");
model.addAttribute("systemConfig", systemConfig);
return "modules/tools/emaiSmtpForm";
}
/**
* 设置邮箱服务器保存
* @param systemConfig
* @param model
* @param redirectAttributes
* @return
* @throws Exception
*/
@RequestMapping(value = "saveSmtp")
public String saveSmtp(SystemConfig systemConfig, Model model, RedirectAttributes redirectAttributes) throws Exception{
try {
systemConfigService.save(systemConfig);
addMessage(redirectAttributes, "保存成功!");
} catch (Exception e) {
e.printStackTrace();
addMessage(redirectAttributes, "保存失败!失败信息:"+e.getMessage());
}
return "redirect:"+Global.getAdminPath()+"/tools/email/?repage";
}
}
工具类三个
package com.jeeplus.common.mail;
/**
*
*/
import javax.mail.*;
public class MailAuthenticator extends Authenticator{
String userName=null;
String password=null;
public MailAuthenticator(){
}
public MailAuthenticator(String username, String password) {
this.userName = username;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication(userName, password);
}
}
package com.jeeplus.common.mail;
/**
*发送邮件需要使用的基本信息
*
*/
import java.util.Properties;
public class MailBody {
// 发送邮件的服务器的IP和端口
private String mailServerHost;
private String mailServerPort = "25";
// 邮件发送者的地址
private String fromAddress;
// 邮件接收者的地址
private String toAddress;
// 登陆邮件发送服务器的用户名和密码
private String userName;
private String password;
// 是否需要身份验证
private boolean validate = false;
//是否开启SSL(0.否 1.是)
private String openSSL = "1";
// 邮件主题
private String subject;
// 邮件的文本内容
private String content;
// 邮件附件的文件名
private String[] attachFileNames;
/**
* 获得邮件会话属性
*/
public Properties getProperties(){
Properties p = System.getProperties();
p.setProperty("mail.smtp.host", this.mailServerHost);
p.setProperty("mail.smtp.port", this.mailServerPort);
if("1".equals(this.openSSL)){
p.setProperty("mail.smtp.socketFactory.port", this.mailServerPort);
p.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
p.setProperty("mail.smtp.socketFactory.fallback", "false");
}
p.setProperty("mail.smtp.auth", this.validate ? "true" : "false");
return p;
}
public String getMailServerHost() {
return mailServerHost;
}
public void setMailServerHost(String mailServerHost) {
this.mailServerHost = mailServerHost;
}
public String getMailServerPort() {
return mailServerPort;
}
public void setMailServerPort(String mailServerPort) {
this.mailServerPort = mailServerPort;
}
public boolean isValidate() {
return validate;
}
public void setValidate(boolean validate) {
this.validate = validate;
}
public String[] getAttachFileNames() {
return attachFileNames;
}
public void setAttachFileNames(String[] fileNames) {
this.attachFileNames = fileNames;
}
public String getFromAddress() {
return fromAddress;
}
public void setFromAddress(String fromAddress) {
this.fromAddress = fromAddress;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getToAddress() {
return toAddress;
}
public void setToAddress(String toAddress) {
this.toAddress = toAddress;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getContent() {
return content;
}
public void setContent(String textContent) {
this.content = textContent;
}
public String getOpenSSL() {
return openSSL;
}
public void setOpenSSL(String openSSL) {
this.openSSL = openSSL;
}
}
package com.jeeplus.common.mail;
/**
* 简单邮件(不带附件的邮件)发送器
*/
import java.util.Date;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
public class MailSendUtils {
/**
* 以文本格式发送邮件
* @param mailInfo 待发送的邮件的信息
*/
public boolean sendTextMail(MailBody mailInfo) throws Exception{
// 判断是否需要身份认证
MailAuthenticator authenticator = null;
Properties pro = mailInfo.getProperties();
if (mailInfo.isValidate()) {
// 如果需要身份认证,则创建一个密码验证器
authenticator = new MailAuthenticator(mailInfo.getUserName(), mailInfo.getPassword());
}
// 根据邮件会话属性和密码验证器构造一个发送邮件的session
Session sendMailSession = Session.getDefaultInstance(pro,authenticator);
// logBefore(logger, "构造一个发送邮件的session");
// 根据session创建一个邮件消息
Message mailMessage = new MimeMessage(sendMailSession);
// 创建邮件发送者地址
Address from = new InternetAddress(mailInfo.getFromAddress());
// 设置邮件消息的发送者
mailMessage.setFrom(from);
// 创建邮件的接收者地址,并设置到邮件消息中
Address to = new InternetAddress(mailInfo.getToAddress());
mailMessage.setRecipient(Message.RecipientType.TO,to);
// 设置邮件消息的主题
mailMessage.setSubject(mailInfo.getSubject());
// 设置邮件消息发送的时间
mailMessage.setSentDate(new Date());
// 设置邮件消息的主要内容
String mailContent = mailInfo.getContent();
mailMessage.setText(mailContent);
// 发送邮件
Transport.send(mailMessage);
System.out.println("发送成功!");
return true;
}
/**
* 以HTML格式发送邮件
* @param mailInfo 待发送的邮件信息
*/
public boolean sendHtmlMail(MailBody mailInfo) throws Exception{
// 判断是否需要身份认证
MailAuthenticator authenticator = null;
Properties pro = mailInfo.getProperties();
//如果需要身份认证,则创建一个密码验证器
if (mailInfo.isValidate()) {
authenticator = new MailAuthenticator(mailInfo.getUserName(), mailInfo.getPassword());
}
// 根据邮件会话属性和密码验证器构造一个发送邮件的session
Session sendMailSession = Session.getDefaultInstance(pro,authenticator);
// 根据session创建一个邮件消息
Message mailMessage = new MimeMessage(sendMailSession);
// 创建邮件发送者地址
Address from = new InternetAddress(mailInfo.getFromAddress());
// 设置邮件消息的发送者
mailMessage.setFrom(from);
// 创建邮件的接收者地址,并设置到邮件消息中
Address to = new InternetAddress(mailInfo.getToAddress());
// Message.RecipientType.TO属性表示接收者的类型为TO
mailMessage.setRecipient(Message.RecipientType.TO,to);
// 设置邮件消息的主题
mailMessage.setSubject(mailInfo.getSubject());
// 设置邮件消息发送的时间
mailMessage.setSentDate(new Date());
// MiniMultipart类是一个容器类,包含MimeBodyPart类型的对象
Multipart mainPart = new MimeMultipart();
// 创建一个包含HTML内容的MimeBodyPart
BodyPart html = new MimeBodyPart();
// 设置HTML内容
html.setContent(mailInfo.getContent(), "text/html; charset=utf-8");
mainPart.addBodyPart(html);
// 将MiniMultipart对象设置为邮件内容
mailMessage.setContent(mainPart);
// 发送邮件
Transport.send(mailMessage);
return true;
}
/**
* @param SMTP
* 邮件服务器
* @param PORT
* 端口
* @param EMAIL
* 本邮箱账号
* @param PAW
* 本邮箱密码
* @param toEMAIL
* 对方箱账号
* @param TITLE
* 标题
* @param CONTENT
* 内容
* @param TYPE
* 1:文本格式;2:HTML格式
*/
public static boolean sendEmail(String SMTP, String PORT, String openSSL, String EMAIL,
String PAW, String toEMAIL, String TITLE, String CONTENT,
String TYPE) {
// 这个类主要是设置邮件
MailBody mailInfo = new MailBody();
mailInfo.setMailServerHost(SMTP);
mailInfo.setMailServerPort(PORT);
mailInfo.setValidate(true);
mailInfo.setOpenSSL(openSSL);
mailInfo.setUserName(EMAIL);
mailInfo.setPassword(PAW);
mailInfo.setFromAddress(EMAIL);
mailInfo.setToAddress(toEMAIL);
mailInfo.setSubject(TITLE);
mailInfo.setContent(CONTENT);
// 这个类主要来发送邮件
MailSendUtils sms = new MailSendUtils();
try {
if ("1".equals(TYPE)) {
return sms.sendTextMail(mailInfo);
} else {
return sms.sendHtmlMail(mailInfo);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
其中额外继承的类 、 调用的类有
/**
* Copyright © 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
*/
package com.jeeplus.common.web;
import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import javax.validation.Validator;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ui.Model;
import org.springframework.validation.BindException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.jeeplus.common.beanvalidator.BeanValidators;
import com.jeeplus.common.mapper.JsonMapper;
import com.jeeplus.common.utils.DateUtils;
/**
* 控制器支持类
* @author jeeplus
* @version 2013-3-23
*/
public abstract class BaseController {
/**
* 日志对象
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 管理基础路径
*/
@Value("${adminPath}")
protected String adminPath;
/**
* 前端基础路径
*/
@Value("${frontPath}")
protected String frontPath;
/**
* 前端URL后缀
*/
@Value("${urlSuffix}")
protected String urlSuffix;
/**
* 验证Bean实例对象
*/
@Autowired
protected Validator validator;
/**
* 服务端参数有效性验证
* @param object 验证的实体对象
* @param groups 验证组
* @return 验证成功:返回true;严重失败:将错误信息添加到 message 中
*/
protected boolean beanValidator(Model model, Object object, Class<?>... groups) {
try{
BeanValidators.validateWithException(validator, object, groups);
}catch(ConstraintViolationException ex){
List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
list.add(0, "数据验证失败:");
addMessage(model, list.toArray(new String[]{}));
return false;
}
return true;
}
/**
* 服务端参数有效性验证
* @param object 验证的实体对象
* @param groups 验证组
* @return 验证成功:返回true;严重失败:将错误信息添加到 flash message 中
*/
protected boolean beanValidator(RedirectAttributes redirectAttributes, Object object, Class<?>... groups) {
try{
BeanValidators.validateWithException(validator, object, groups);
}catch(ConstraintViolationException ex){
List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
list.add(0, "数据验证失败:");
addMessage(redirectAttributes, list.toArray(new String[]{}));
return false;
}
return true;
}
/**
* 服务端参数有效性验证
* @param object 验证的实体对象
* @param groups 验证组,不传入此参数时,同@Valid注解验证
* @return 验证成功:继续执行;验证失败:抛出异常跳转400页面。
*/
protected void beanValidator(Object object, Class<?>... groups) {
BeanValidators.validateWithException(validator, object, groups);
}
/**
* 添加Model消息
* @param message
*/
protected void addMessage(Model model, String... messages) {
StringBuilder sb = new StringBuilder();
for (String message : messages){
sb.append(message).append(messages.length>1?"<br/>":"");
}
model.addAttribute("message", sb.toString());
}
/**
* 添加Flash消息
* @param message
*/
protected void addMessage(RedirectAttributes redirectAttributes, String... messages) {
StringBuilder sb = new StringBuilder();
for (String message : messages){
sb.append(message).append(messages.length>1?"<br/>":"");
}
redirectAttributes.addFlashAttribute("message", sb.toString());
}
/**
* 客户端返回JSON字符串
* @param response
* @param object
* @return
*/
protected String renderString(HttpServletResponse response, Object object) {
return renderString(response, JsonMapper.toJsonString(object));
}
/**
* 客户端返回字符串
* @param response
* @param string
* @return
*/
protected String renderString(HttpServletResponse response, String string) {
try {
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().print(string);
return null;
} catch (IOException e) {
return null;
}
}
/**
* 参数绑定异常
*/
@ExceptionHandler({BindException.class, ConstraintViolationException.class, ValidationException.class})
public String bindException() {
return "error/400";
}
/**
* 授权登录异常
*/
@ExceptionHandler({AuthenticationException.class})
public String authenticationException() {
return "error/403";
}
/**
* 初始化数据绑定
* 1. 将所有传递进来的String进行HTML编码,防止XSS攻击
* 2. 将字段中Date类型转换为String类型
*/
@InitBinder
protected void initBinder(WebDataBinder binder) {
// String类型转换,将所有传递进来的String进行HTML编码,防止XSS攻击
binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
}
@Override
public String getAsText() {
Object value = getValue();
return value != null ? value.toString() : "";
}
});
// Date 类型转换
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
setValue(DateUtils.parseDate(text));
}
// @Override
// public String getAsText() {
// Object value = getValue();
// return value != null ? DateUtils.formatDateTime((Date)value) : "";
// }
});
}
}
/**
* Copyright © 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
*/
package com.jeeplus.modules.sys.entity;
import org.hibernate.validator.constraints.Length;
import com.jeeplus.common.persistence.DataEntity;
import com.jeeplus.common.utils.excel.annotation.ExcelField;
/**
* 系统配置Entity
* @author liugf
* @version 2016-02-07
*/
public class SystemConfig extends DataEntity<SystemConfig> {
private static final long serialVersionUID = 1L;
private String smtp; // 邮箱服务器地址
private String port; // 邮箱服务器端口
private String mailName; // 系统邮箱地址
private String mailPassword; // 系统邮箱密码
private String openSSL; // 开启SSL
private String smsName; // 短信用户名
private String smsPassword; // 短信密码
private boolean test = false;
public SystemConfig() {
super();
}
public SystemConfig(String id){
super(id);
}
@Length(min=0, max=64, message="邮箱服务器地址长度必须介于 0 和 64 之间")
@ExcelField(title="邮箱服务器地址", align=2, sort=1)
public String getSmtp() {
return smtp;
}
public void setSmtp(String smtp) {
this.smtp = smtp;
}
@Length(min=0, max=64, message="邮箱服务器端口长度必须介于 0 和 64 之间")
@ExcelField(title="邮箱服务器端口", align=2, sort=2)
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
@Length(min=0, max=64, message="系统邮箱地址长度必须介于 0 和 64 之间")
@ExcelField(title="系统邮箱地址", align=2, sort=3)
public String getMailName() {
return mailName;
}
public void setMailName(String mailName) {
this.mailName = mailName;
}
@Length(min=0, max=64, message="系统邮箱密码长度必须介于 0 和 64 之间")
@ExcelField(title="系统邮箱密码", align=2, sort=4)
public String getMailPassword() {
return mailPassword;
}
public void setMailPassword(String mailPassword) {
this.mailPassword = mailPassword;
}
@Length(min=0, max=64, message="短信用户名长度必须介于 0 和 64 之间")
@ExcelField(title="短信用户名", align=2, sort=5)
public String getSmsName() {
return smsName;
}
public void setSmsName(String smsName) {
this.smsName = smsName;
}
@Length(min=0, max=64, message="短信密码长度必须介于 0 和 64 之间")
@ExcelField(title="短信密码", align=2, sort=6)
public String getSmsPassword() {
return smsPassword;
}
public void setSmsPassword(String smsPassword) {
this.smsPassword = smsPassword;
}
public void setTest(boolean test) {
this.test = test;
}
public boolean isTest() {
return test;
}
public String getOpenSSL() {
return openSSL;
}
public void setOpenSSL(String openSSL) {
this.openSSL = openSSL;
}
}
/**
* Copyright © 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
*/
package com.jeeplus.modules.sys.service;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.jeeplus.common.persistence.Page;
import com.jeeplus.common.service.CrudService;
import com.jeeplus.modules.sys.entity.SystemConfig;
import com.jeeplus.modules.sys.dao.SystemConfigDao;
/**
* 系统配置Service
* @author liugf
* @version 2016-02-07
*/
@Service
@Transactional(readOnly = true)
public class SystemConfigService extends CrudService<SystemConfigDao, SystemConfig> {
public SystemConfig get(String id) {
return super.get(id);
}
public List<SystemConfig> findList(SystemConfig systemConfig) {
return super.findList(systemConfig);
}
public Page<SystemConfig> findPage(Page<SystemConfig> page, SystemConfig systemConfig) {
return super.findPage(page, systemConfig);
}
@Transactional(readOnly = false)
public void save(SystemConfig systemConfig) {
super.save(systemConfig);
}
@Transactional(readOnly = false)
public void delete(SystemConfig systemConfig) {
super.delete(systemConfig);
}
}
/**
* Copyright © 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
*/
package com.jeeplus.common.config;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.util.Map;
import java.util.Properties;
import org.apache.ibatis.io.Resources;
import org.springframework.core.io.DefaultResourceLoader;
import com.ckfinder.connector.ServletContextFactory;
import com.google.common.collect.Maps;
import com.jeeplus.common.utils.PropertiesLoader;
import com.jeeplus.common.utils.StringUtils;
/**
* 全局配置类
* @author jeeplus
* @version 2014-06-25
*/
public class Global {
/**
* 当前对象实例
*/
private static Global global = new Global();
/**
* 保存全局属性值
*/
private static Map<String, String> map = Maps.newHashMap();
/**
* 属性文件加载对象
*/
private static PropertiesLoader loader = new PropertiesLoader("jeeplus.properties");
/**
* 显示/隐藏
*/
public static final String SHOW = "1";
public static final String HIDE = "0";
/**
* 是/否
*/
public static final String YES = "1";
public static final String NO = "0";
/**
* 对/错
*/
public static final String TRUE = "true";
public static final String FALSE = "false";
/**
* 上传文件基础虚拟路径
*/
public static final String USERFILES_BASE_URL = "/userfiles/";
/**
* 获取当前对象实例
*/
public static Global getInstance() {
return global;
}
/**
* 获取配置
* @see ${fns:getConfig('adminPath')}
*/
public static String getConfig(String key) {
String value = map.get(key);
if (value == null){
value = loader.getProperty(key);
map.put(key, value != null ? value : StringUtils.EMPTY);
}
return value;
}
/**
* 获取管理端根路径
*/
public static String getAdminPath() {
return getConfig("adminPath");
}
/**
* 获取前端根路径
*/
public static String getFrontPath() {
return getConfig("frontPath");
}
/**
* 获取URL后缀
*/
public static String getUrlSuffix() {
return getConfig("urlSuffix");
}
/**
* 是否是演示模式,演示模式下不能修改用户、角色、密码、菜单、授权
*/
public static Boolean isDemoMode() {
String dm = getConfig("demoMode");
return "true".equals(dm) || "1".equals(dm);
}
/**
* 在修改系统用户和角色时是否同步到Activiti
*/
public static Boolean isSynActivitiIndetity() {
String dm = getConfig("activiti.isSynActivitiIndetity");
return "true".equals(dm) || "1".equals(dm);
}
/**
* 页面获取常量
* @see ${fns:getConst('YES')}
*/
public static Object getConst(String field) {
try {
return Global.class.getField(field).get(null);
} catch (Exception e) {
// 异常代表无配置,这里什么也不做
}
return null;
}
/**
* 获取上传文件的根目录
* @return
*/
public static String getUserfilesBaseDir() {
String dir = getConfig("userfiles.basedir");
if (StringUtils.isBlank(dir)){
try {
dir = ServletContextFactory.getServletContext().getRealPath("/");
} catch (Exception e) {
return "";
}
}
if(!dir.endsWith("/")) {
dir += "/";
}
// System.out.println("userfiles.basedir: " + dir);
return dir;
}
/**
* 获取工程路径
* @return
*/
public static String getProjectPath(){
// 如果配置了工程路径,则直接返回,否则自动获取。
String projectPath = Global.getConfig("projectPath");
if (StringUtils.isNotBlank(projectPath)){
return projectPath;
}
try {
File file = new DefaultResourceLoader().getResource("").getFile();
if (file != null){
while(true){
File f = new File(file.getPath() + File.separator + "src" + File.separator + "main");
if (f == null || f.exists()){
break;
}
if (file.getParentFile() != null){
file = file.getParentFile();
}else{
break;
}
}
projectPath = file.toString();
}
} catch (IOException e) {
e.printStackTrace();
}
return projectPath;
}
/**
* 写入properties信息
*
* @param key
* 名称
* @param value
* 值
*/
public static void modifyConfig(String key, String value) {
try {
// 从输入流中读取属性列表(键和元素对)
Properties prop = getProperties();
prop.setProperty(key, value);
String path = Global.class.getResource("/jeeplus.properties").getPath();
FileOutputStream outputFile = new FileOutputStream(path);
prop.store(outputFile, "modify");
outputFile.close();
outputFile.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 返回 Properties
* @param fileName 文件名 (注意:加载的是src下的文件,如果在某个包下.请把包名加上)
* @param
* @return
*/
public static Properties getProperties(){
Properties prop = new Properties();
try {
Reader reader = Resources.getResourceAsReader("/jeeplus.properties");
prop.load(reader);
} catch (Exception e) {
return null;
}
return prop;
}
}
package com.jeeplus.modules.rgssys.entity;
import com.jeeplus.common.persistence.DataEntity;
import com.jeeplus.common.utils.excel.annotation.ExcelField;
/**
* 工资明细Entity
* @author chengxu
* @version 2017-05-10
*/
public class SalaryDetailInfo extends DataEntity<SalaryDetailInfo> {
private static final long serialVersionUID = 1L;
private String month; //月份
private String employeeID; //员工编号
private String employeeName; //姓名
private Double baseSalary; //基本工资
private Double performanceAward; //业绩奖励
private Double secrecyFee; //保密费
private Double total; //工资总额
private Double projectCapital; //项目资金
private Double countDays; //计补天数
private Double attendanceDays; //考勤天数
private Double commuterAllowance; //通勤补助
private Double lunchAllowance; //午餐补助
private Double selfEndowmentInsurance; //个人负担养老保险
private Double selfMedicalInsurance; //个人负担医疗保险
private Double selfUnemployInsurance;//个人负担失业保险
private Double otherDeductions; //其他扣款
private Double selfProvidentFund; //个人负担公积金
private Double lateEarlyDeductions; //缺勤扣款
private Double totalDeductions; //扣款合计
private Double adjustWages; //调整工资
private Double grossPay; //税前工资
private Double selfIncomeTax; //个人所得税
private Double realPay; //实得工资
private String email; //邮箱地址
public SalaryDetailInfo(){
super();
}
public SalaryDetailInfo(String id){
super(id);
}
@ExcelField(title="月份", align=2, sort=1)
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
@ExcelField(title="员工编号", align=2, sort=2)
public String getEmployeeID() {
return employeeID;
}
public void setEmployeeID(String employeeID) {
this.employeeID = employeeID;
}
@ExcelField(title="姓名", align=2, sort=3)
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
@ExcelField(title="基本工资", align=2, sort=4)
public Double getBaseSalary() {
return baseSalary;
}
public void setBaseSalary(Double baseSalary) {
this.baseSalary = baseSalary;
}
@ExcelField(title="业绩奖励", align=2, sort=5)
public Double getPerformanceAward() {
return performanceAward;
}
public void setPerformanceAward(Double performanceAward) {
this.performanceAward = performanceAward;
}
@ExcelField(title="保密费", align=2, sort=6)
public Double getSecrecyFee() {
return secrecyFee;
}
public void setSecrecyFee(Double secrecyFee) {
this.secrecyFee = secrecyFee;
}
@ExcelField(title="工资总额", align=2, sort=7)
public Double getTotal() {
return total;
}
public void setTotal(Double total) {
this.total = total;
}
@ExcelField(title="项目资金", align=2, sort=8)
public Double getProjectCapital() {
return projectCapital;
}
public void setProjectCapital(Double projectCapital) {
this.projectCapital = projectCapital;
}
@ExcelField(title="计补天数", align=2, sort=9)
public Double getCountDays() {
return countDays;
}
public void setCountDays(Double countDays) {
this.countDays = countDays;
}
@ExcelField(title="考勤天数", align=2, sort=10)
public Double getAttendanceDays() {
return attendanceDays;
}
public void setAttendanceDays(Double attendanceDays) {
this.attendanceDays = attendanceDays;
}
@ExcelField(title="通勤补助", align=2, sort=11)
public Double getCommuterAllowance() {
return commuterAllowance;
}
public void setCommuterAllowance(Double commuterAllowance) {
this.commuterAllowance = commuterAllowance;
}
@ExcelField(title="午餐补助", align=2, sort=12)
public Double getLunchAllowance() {
return lunchAllowance;
}
public void setLunchAllowance(Double lunchAllowance) {
this.lunchAllowance = lunchAllowance;
}
@ExcelField(title="个人负担养老保险", align=2, sort=13)
public Double getSelfEndowmentInsurance() {
return selfEndowmentInsurance;
}
public void setSelfEndowmentInsurance(Double selfEndowmentInsurance) {
this.selfEndowmentInsurance = selfEndowmentInsurance;
}
@ExcelField(title="个人负担医疗保险", align=2, sort=14)
public Double getSelfMedicalInsurance() {
return selfMedicalInsurance;
}
public void setSelfMedicalInsurance(Double selfMedicalInsurance) {
this.selfMedicalInsurance = selfMedicalInsurance;
}
@ExcelField(title="个人负担失业保险", align=2, sort=15)
public Double getSelfUnemployInsurance() {
return selfUnemployInsurance;
}
public void setSelfUnemployInsurance(Double selfUnemployInsurance) {
this.selfUnemployInsurance = selfUnemployInsurance;
}
@ExcelField(title="其他扣款", align=2, sort=16)
public Double getOtherDeductions() {
return otherDeductions;
}
public void setOtherDeductions(Double otherDeductions) {
this.otherDeductions = otherDeductions;
}
@ExcelField(title="个人负担公积金", align=2, sort=17)
public Double getSelfProvidentFund() {
return selfProvidentFund;
}
public void setSelfProvidentFund(Double selfProvidentFund) {
this.selfProvidentFund = selfProvidentFund;
}
@ExcelField(title="缺勤扣款", align=2, sort=18)
public Double getLateEarlyDeductions() {
return lateEarlyDeductions;
}
public void setLateEarlyDeductions(Double lateEarlyDeductions) {
this.lateEarlyDeductions = lateEarlyDeductions;
}
@ExcelField(title="扣款合计", align=2, sort=19)
public Double getTotalDeductions() {
return totalDeductions;
}
public void setTotalDeductions(Double totalDeductions) {
this.totalDeductions = totalDeductions;
}
@ExcelField(title="调整工资(+ -)", align=2, sort=20)
public Double getAdjustWages() {
return adjustWages;
}
public void setAdjustWages(Double adjustWages) {
this.adjustWages = adjustWages;
}
@ExcelField(title="税前工资", align=2, sort=21)
public Double getGrossPay() {
return grossPay;
}
public void setGrossPay(Double grossPay) {
this.grossPay = grossPay;
}
@ExcelField(title="个人所得税", align=2, sort=22)
public Double getSelfIncomeTax() {
return selfIncomeTax;
}
public void setSelfIncomeTax(Double selfIncomeTax) {
this.selfIncomeTax = selfIncomeTax;
}
@ExcelField(title="实得工资", align=2, sort=23)
public Double getRealPay() {
return realPay;
}
public void setRealPay(Double realPay) {
this.realPay = realPay;
}
@ExcelField(title="邮箱地址", align=2, sort=24)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
其他 Excel工具类 参考 我的Excel原创文章
页面引入的summernote插件 如图
其他需要 的jar包 参考 Java Email需要的jar包
mail.jar 和activation.jar等等