2.6 发送短信
2.6.1 导入maven坐标
<dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>3.3.1</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-dysmsapi</artifactId> <version>1.0.0</version> </dependency>
2.6.2 封装工具类
package com.itheima.utils; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.http.MethodType; import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.IClientProfile; /** * 短信发送工具类 */ public class SMSUtils { public static final String VALIDATE_CODE = "SMS_159620392";//发送短信验证码 public static final String ORDER_NOTICE = "SMS_159771588";//体检预约成功通知 /** * 发送短信 * @param phoneNumbers * @param param * @throws ClientException */ public static void sendShortMessage(String templateCode,String phoneNumbers,String param) throws ClientException{ // 设置超时时间-可自行调整 System.setProperty("sun.net.client.defaultConnectTimeout", "10000"); System.setProperty("sun.net.client.defaultReadTimeout", "10000"); // 初始化ascClient需要的几个参数 final String product = "Dysmsapi";// 短信API产品名称(短信产品名固定,无需修改) final String domain = "dysmsapi.aliyuncs.com";// 短信API产品域名(接口地址固定,无需修改) // 替换成你的AK final String accessKeyId = "accessKeyId";// 你的accessKeyId,参考本文档步骤2 final String accessKeySecret = "accessKeySecret";// 你的accessKeySecret,参考本文档步骤2 // 初始化ascClient,暂时不支持多region(请勿修改) IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret); DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain); IAcsClient acsClient = new DefaultAcsClient(profile); // 组装请求对象 SendSmsRequest request = new SendSmsRequest(); // 使用post提交 request.setMethod(MethodType.POST); // 必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式 request.setPhoneNumbers(phoneNumbers); // 必填:短信签名-可在短信控制台中找到 request.setSignName("传智健康"); // 必填:短信模板-可在短信控制台中找到 request.setTemplateCode(templateCode); // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为 // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败 request.setTemplateParam("{\"code\":\""+param+"\"}"); // 可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段) // request.setSmsUpExtendCode("90997"); // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者 // request.setOutId("yourOutId"); // 请求失败这里会抛ClientException异常 SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request); if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) { // 请求成功 System.out.println("请求成功"); } } }
2.6.3 测试短信发送
public static void main(String[] args)throws Exception { SMSUtils.sendShortMessage("SMS_159620392","13812345678","1234"); }
3.定时任务组件Quartz
3.1 Quartz介绍
Quartz是Job scheduling**(作业调度)领域的一个开源项目,Quartz既可以单独使用也可以跟spring框架整合使用**,在实际开发中一般会使用后者。使用Quartz可以开发一个或者多个定时任务,每个定时任务可以单独指定执行的时间,例如每隔1小时执行一次、每个月第一天上午10点执行一次、每个月最后一天下午5点执行一次等。
官网:http://www.quartz-scheduler.org/
maven坐标:
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.1</version> </dependency>
3.2 Quartz入门案例
本案例基于Quartz和spring整合的方式使用。具体步骤:
(1)创建maven工程quartzdemo,导入Quartz和spring相关坐标,pom.xml文件如下
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.itheima</groupId> <artifactId>quartdemo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.1</version> </dependency> </dependencies> </project>
(2)自定义一个Job
package com.itheima.jobs; /** * 自定义Job */ public class JobDemo { public void run(){ System.out.println("job execute..."); } }
(3)提供Spring配置文件spring-jobs.xml,配置自定义Job、任务描述、触发器、调度工厂等
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 注册自定义Job --> <bean id="jobDemo" class="com.itheima.jobs.JobDemo"></bean> <!-- 注册JobDetail,作用是负责通过反射调用指定的Job --> <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!-- 注入目标对象 --> <property name="targetObject" ref="jobDemo"/> <!-- 注入目标方法 --> <property name="targetMethod" value="run"/> </bean> <!-- 注册一个触发器,指定任务触发的时间 --> <bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <!-- 注入JobDetail --> <property name="jobDetail" ref="jobDetail"/> <!-- 指定触发的时间,基于Cron表达式 --> <property name="cronExpression"> <value>0/10 * * * * ?</value> </property> </bean> <!-- 注册一个统一的调度工厂,通过这个调度工厂调度任务 --> <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!-- 注入多个触发器 --> <property name="triggers"> <list> <ref bean="myTrigger"/> </list> </property> </bean> </beans>
(4)编写main方法进行测试
package com.itheima.jobs.com.itheima.app; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main(String[] args) { new ClassPathXmlApplicationContext("spring-jobs.xml"); } }
执行上面main方法观察控制台,可以发现每隔10秒会输出一次,说明每隔10秒自定义Job被调用一次。
3.3 cron表达式
上面的入门案例中我们指定了一个表达式:0/10 * * * * ?
这种表达式称为cron表达式,通过cron表达式可以灵活的定义出符合要求的程序执行的时间。本小节我们就来学习一下cron表达式的使用方法。如下图:
cron表达式分为七个域,之间使用空格分隔。其中最后一个域(年)可以为空。每个域都有自己允许的值和一些特殊字符构成。使用这些特殊字符可以使我们定义的表达式更加灵活。
下面是对这些特殊字符的介绍:
逗号(,):指定一个值列表,例如使用在月域上1,4,5,7表示1月、4月、5月和7月
横杠(-):指定一个范围,例如在时域上3-6表示3点到6点(即3点、4点、5点、6点)
星号(*):表示这个域上包含所有合法的值。例如,在月份域上使用星号意味着每个月都会触发
斜线(/):表示递增,例如使用在秒域上0/15表示每15秒
问号(?):只能用在日和周域上,但是不能在这两个域上同时使用。表示不指定
井号(#):只能使用在周域上,用于指定月份中的第几周的哪一天,例如6#3,意思是某月的第三个周五 (6=星期五,3意味着月份中的第三周)
L:某域上允许的最后一个值。只能使用在日和周域上。当用在日域上,表示的是在月域上指定的月份的最后一天。用于周域上时,表示周的最后一天,就是星期六
W:W 字符代表着工作日 (星期一到星期五),只能用在日域上,它用来指定离指定日的最近的一个工作日
3.4 cron表达式在线生成器
前面介绍了cron表达式,但是自己编写表达式还是有一些困难的,我们可以借助一些cron表达式在线生成器来根据我们的需求生成表达式即可。
4. 图形报表ECharts
4.1 ECharts简介
ECharts缩写来自Enterprise Charts,商业级数据图表,是百度的一个开源的使用JavaScript实现的数据可视化工具,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖轻量级的矢量图形库 ZRender,提供直观、交互丰富、可高度个性化定制的数据可视化图表。
下载地址:https://echarts.baidu.com/download.html
下载完成可以得到如下文件:
解压上面的zip文件:
我们只需要将dist目录下的echarts.js文件引入到页面上就可以使用了
4.2 5分钟上手ECharts
我们可以参考官方提供的5分钟上手ECharts文档感受一下ECharts的使用方式,地址如下:
https://www.echartsjs.com/tutorial.html#5%20%E5%88%86%E9%92%9F%E4%B8%8A%E6%89%8B%20ECharts
第一步:创建html页面并引入echarts.js文件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <!-- 引入 ECharts 文件 --> <script src="echarts.js"></script> </head> </html>
第二步:在页面中准备一个具备宽高的DOM容器。
<body> <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM --> <div id="main" style="width: 600px;height:400px;"></div> </body>
第三步:通过echarts.init方法初始化一个 echarts 实例并通过setOption方法生成一个简单的柱状图
<script type="text/javascript"> // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('main')); // 指定图表的配置项和数据 var option = { title: { text: 'ECharts 入门示例' }, tooltip: {}, legend: { data:['销量'] }, xAxis: { data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); </script>
效果如下:
4.3 查看ECharts官方实例
ECharts提供了很多官方实例,我们可以通过这些官方实例来查看展示效果和使用方法。
官方实例地址:https://www.echartsjs.com/examples/
可以点击具体的一个图形会跳转到编辑页面,编辑页面左侧展示源码(js部分源码),右侧展示图表效果,如下:
要查看完整代码可以点击右下角的Download按钮将完整页面下载到本地。
通过官方案例我们可以发现,使用ECharts展示图表效果,关键点在于确定此图表所需的数据格式,然后按照此数据格式提供数据就可以了,我们无须关注效果是如何渲染出来的。
在实际应用中,我们要展示的数据往往存储在数据库中,所以我们可以发送ajax请求获取数据库中的数据并转为图表所需的数据即可。
5. Apache POI
5.1 POI介绍
Apache POI是用Java编写的免费开源的跨平台的Java API,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能,其中使用最多的就是使用POI操作Excel文件。
jxl:专门操作Excel
maven坐标:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.14</version> </dependency>
POI结构:
HSSF - 提供读写Microsoft Excel XLS格式档案的功能 XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能 HWPF - 提供读写Microsoft Word DOC格式档案的功能 HSLF - 提供读写Microsoft PowerPoint格式档案的功能 HDGF - 提供读Microsoft Visio格式档案的功能 HPBF - 提供读Microsoft Publisher格式档案的功能 HSMF - 提供读Microsoft Outlook格式档案的功能
5.2 入门案例
5.2.1 从Excel文件读取数据
使用POI可以从一个已经存在的Excel文件中读取数据
//创建工作簿 XSSFWorkbook workbook = new XSSFWorkbook("D:\\hello.xlsx"); //获取工作表,既可以根据工作表的顺序获取,也可以根据工作表的名称获取 XSSFSheet sheet = workbook.getSheetAt(0); //遍历工作表获得行对象 for (Row row : sheet) { //遍历行对象获取单元格对象 for (Cell cell : row) { //获得单元格中的值 String value = cell.getStringCellValue(); System.out.println(value); } } workbook.close();
通过上面的入门案例可以看到,POI操作Excel表格封装了几个核心对象:
XSSFWorkbook:工作簿 XSSFSheet:工作表 Row:行 Cell:单元格
上面案例是通过遍历工作表获得行,遍历行获得单元格,最终获取单元格中的值。
还有一种方式就是获取工作表最后一个行号,从而根据行号获得行对象,通过行获取最后一个单元格索引,从而根据单元格索引获取每行的一个单元格对象,代码如下:
//创建工作簿 XSSFWorkbook workbook = new XSSFWorkbook("D:\\hello.xlsx"); //获取工作表,既可以根据工作表的顺序获取,也可以根据工作表的名称获取 XSSFSheet sheet = workbook.getSheetAt(0); //获取当前工作表最后一行的行号,行号从0开始 int lastRowNum = sheet.getLastRowNum(); for(int i=0;i<=lastRowNum;i++){ //根据行号获取行对象 XSSFRow row = sheet.getRow(i); short lastCellNum = row.getLastCellNum(); for(short j=0;j<lastCellNum;j++){ String value = row.getCell(j).getStringCellValue(); System.out.println(value); } } workbook.close();
5.2.2 向Excel文件写入数据
使用POI可以在内存中创建一个Excel文件并将数据写入到这个文件,最后通过输出流将内存中的Excel文件下载到磁盘
//在内存中创建一个Excel文件 XSSFWorkbook workbook = new XSSFWorkbook(); //创建工作表,指定工作表名称 XSSFSheet sheet = workbook.createSheet("传智播客"); //创建行,0表示第一行 XSSFRow row = sheet.createRow(0); //创建单元格,0表示第一个单元格 row.createCell(0).setCellValue("编号"); row.createCell(1).setCellValue("名称"); row.createCell(2).setCellValue("年龄"); XSSFRow row1 = sheet.createRow(1); row1.createCell(0).setCellValue("1"); row1.createCell(1).setCellValue("小明"); row1.createCell(2).setCellValue("10"); XSSFRow row2 = sheet.createRow(2); row2.createCell(0).setCellValue("2"); row2.createCell(1).setCellValue("小王"); row2.createCell(2).setCellValue("20"); //通过输出流将workbook对象下载到磁盘 FileOutputStream out = new FileOutputStream("D:\\itcast.xlsx"); workbook.write(out); out.flush(); out.close(); workbook.close();
6.PDF报表生成技术—JasperReports
6. 1常见的PDF报表生成方式
6.1.1 iText
iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。 iText的安装非常方便,下载iText.jar文件后,只需要在系统的CLASSPATH中加入iText.jar的路径,在程序中就可以使用iText类库了。
maven坐标:
<dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> </dependency>
示例代码:
package com.itheima.app; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; import com.lowagie.text.Paragraph; import com.lowagie.text.pdf.PdfWriter; import java.io.FileNotFoundException; import java.io.FileOutputStream; public class ItextDemo { public static void main(String[] args) { try { Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream("D:\\test.pdf")); document.open(); document.add(new Paragraph("hello itext")); document.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } } } package com.ithe