POI报表的入门
理解员工管理的的业务逻辑
能够说出Eureka和Feign的作用
理解报表的两种形式和POI的基本操作熟练使用POI完成Excel的导入导出操作
员工管理
需求分析
企业员工管理是人事资源管理系统中最重要的一个环节,分为对员工入职,转正,离职,调岗,员工报表导入导出 等业务逻辑。需求看似复杂,实际上都是对数据库表的基本操作。
数据库表概述
对于员工操作而言,涉及到的数据库表如下表格说明:
代码实现
服务端实现
- 创建员工微服务
ihrm_employee
- 配置文件 application.yml
- 配置Shiro核心配置类ShiroConfiguration
- 配置启动类EmployeeApplication
- 导入资源中提供的基本Controller,Service,Dao,Domain代码
前端实现
导入资源中提供的前端代码。
服务发现组件 Eureka
Eureka是Netflflix开发的服务发现框架,SpringCloud将它集成在自己的子项目spring-cloud-Netflflix中,实现SpringCloud的服务发现功能。Eureka包含两个组件:Eureka Server和Eureka Client。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就别一个内置的、使用轮 询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒, 如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka服务端开发
- 创建ihrm_eureka模块
- 引入依赖 父工程pom.xml定义SpringCloud版本
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M9</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
ihrm_eureka模块pom.xml引入eureka-server
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies>
- 添加application.yml
server: port: 6868 #服务端口 eureka: client: registerWithEureka: false #是否将自己注册到Eureka服务中,本身就是所有无需 注册 fetchRegistry: false #是否从Eureka中获取注册信息 serviceUrl: #Eureka客户端与Eureka服务端进行交互的地址 defaultZone: http://127.0.0.1:${server.port}/eureka/
- 配置启动类
@SpringBootApplication @EnableEurekaServer public class EurekaServer { public static void main(String[] args) { SpringApplication.run(EurekaServer.class, args); } }
微服务注册
我们现在就将所有的微服务都注册到Eureka中,这样所有的微服务之间都可以互相调用了。
- 将其他微服务模块添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
- 修改每个微服务的application.yml,添加注册eureka服务的配置
eureka: client: service-url: defaultZone: http://localhost:6868/eureka instance: prefer-ip-address: true
- 修改每个服务类的启动类,添加注解@EnableEurekaClient
骚戴理解:把微服务都注册到Eureka后可以通过访问:http://localhost:6868进入Eureka网站看微服务的存活情况
微服务调用组件Feign
简介
Feign是简化Java HTTP客户端开发的工具(java-to-httpclient-binder),它的灵感来自于Retrofit、JAXRS-2.0和WebSocket。Feign的初衷是降低统一绑定Denominator到HTTP API的复杂度,不区分是否为restful
快速体验
我们现在在系统微服务调用企业微服务的方法(根据ID查询部门)
- 在ihrm_system模块添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
- 修改ihrm_system模块的启动类,添加注解
@EnableDiscoveryClient @EnableFeignClients
- 在Ihrm_system模块创建com.ihrm.system.client包,包下创建接口
//@FeignClient注解用于指定从哪个服务中调用功能 ,注意里面的名称与被调用的服务名保持一致 @FeignClient(value = "ihrm-company") public interface DepartmentFeignClient { //@RequestMapping注解用于对被调用的微服务进行地址映射 @RequestMapping(value = "/company/departments/{id}/", method = RequestMethod.GET) public Department findById(@PathVariable("id") String id) throws Exception; }
- 修改Ihrm_system模块的 UserController
@Autowired private DepartmentFeignClient departmentFeignClient; //测试通过系统微服务调用企业微服务方法 @RequestMapping(value = "/test/{id}") public void findDeptById(@PathVariable String id){ Department dept = departmentFeignClient.findById(id); System.out.println(dept); }
骚戴理解:Feign组件是谁调用就写在谁那里,例如微服务A远程调用微服务B的接口,那么上面的这些步骤都写在微服务A里面
- 配置Feign拦截器添加请求头
package com.ihrm.common.feign; import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; @Configuration public class FeignConfiguration { //配置feign拦截器,解决请求头问题 @Bean public RequestInterceptor requestInterceptor() { return new RequestInterceptor() { //获取所有浏览器发送的请求属性,请求头赋值到feign public void apply(RequestTemplate requestTemplate) { //请求属性 ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); if(attributes != null) { HttpServletRequest request = attributes.getRequest(); //获取浏览器发起的请求头 Enumeration<String> headerNames = request.getHeaderNames(); if (headerNames != null) { while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); //请求头名称 Authorization String value = request.getHeader(name);//请求头数据 "Bearer b1dbb4cf-7de6-41e5-99e2-0e8b7e8fe6ee" requestTemplate.header(name,value); } } } } }; } }
骚戴理解:在使用Feign组件远程调用其他微服务的时候会丢失请求头,所以要写一个上面的配置类来解决这个问题,其实就是把请求头给配置好,在每次调用其他微服务的时候都把这个请求头设置进去,这样就不缺请求头了
POI报表的概述
需求说明
在企业级应用开发中,Excel报表是一种最常见的报表需求。Excel报表开发一般分为两种形式:
为了方便操作,基于Excel的报表批量上传数据
通过java代码生成Excel报表。
在Saas-HRM系统中,也有大量的报表操作,那么接下来的课程就是一起来学习企业级的报表开发。
Excel的两种形式
目前世面上的Excel分为两个大的版本Excel2003和Excel2007及以上两个版本,两者之间的区别如下:
Excel2003是一个特有的二进制格式,其核心结构是复合文档类型的结构,存储数据量较小;Excel2007 的核心结构是 XML 类型的结构,采用的是基于 XML 的压缩方式,使其占用的空间更小,操作效率更高
常见excel操作工具
Java中常见的用来操作Excl的方式一般有2种:JXL和POI。
JXL只能对Excel进行操作,属于比较老的框架,它只支持到Excel 95-2000的版本。现在已经停止更新和维护。POI是apache的项目,可对微软的Word,Excel,Ppt进行操作,包括office2003和2007,Excl2003和2007。poi现在一直有更新。所以现在主流使用POI。
POI的概述
Apache POI是Apache软件基金会的开源项目,由Java编写的免费开源的跨平台的 Java API,Apache POI提供API
给Java语言操作Microsoft Office的功能。
POI的应用场景
- 数据报表生成
- 数据备份
- 数据批量上传
POI的入门操作
搭建环境
<dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.0.1</version> </dependency> </dependencies>
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格式档案的功能。
API介绍
基本操作
创建Excel
public class PoiTest01 { //测试创建excel文件 public static void main(String[] args) throws Exception { //1.创建workbook工作簿 Workbook wb = new XSSFWorkbook(); //2.创建表单Sheet Sheet sheet = wb.createSheet("test"); //3.文件流 FileOutputStream fos = new FileOutputStream("E:\\test.xlsx"); //4.写入文件 wb.write(fos); fos.close(); } }
骚戴理解:FileOutputStream fos = new FileOutputStream("E:\\test.xlsx");表示把创建的excel文件输出到E:\\test.xlsx路径下
创建单元格
//测试创建单元格 public static void main(String[] args) throws Exception { //1.创建workbook工作簿 Workbook wb = new XSSFWorkbook(); //2.创建表单Sheet Sheet sheet = wb.createSheet("test"); //3.创建行对象,从0开始 Row row = sheet.createRow(3); //4.创建单元格,从0开始 Cell cell = row.createCell(0); //5.单元格写入数据 cell.setCellValue("骚戴"); //6.文件流 FileOutputStream fos = new FileOutputStream("E:\\test.xlsx"); //7.写入文件 wb.write(fos); fos.close(); }
骚戴理解: Row row = sheet.createRow(3);是指定第四行,Cell cell = row.createCell(0);是指定第1列,如图所示:
设置格式
package cn.itcast.poi.test; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileOutputStream; /** * 单元格样式处理 */ public class PoiTest03 { public static void main(String[] args) throws Exception { //创建工作簿 HSSFWorkbook -- 2003 Workbook wb = new XSSFWorkbook(); //2007版本 //创建表单sheet Sheet sheet = wb.createSheet("test"); //创建行对象 参数:索引(从0开始) Row row = sheet.createRow(2); //创建单元格对象 参数:索引(从0开始) Cell cell = row.createCell(2); //向单元格中写入内容 cell.setCellValue("传智播客"); //样式处理 //创建样式对象 CellStyle style = wb.createCellStyle(); style.setBorderTop(BorderStyle.THIN);//上边框 style.setBorderBottom(BorderStyle.THIN);//下边框 style.setBorderLeft(BorderStyle.THIN);//左边框 style.setBorderRight(BorderStyle.THIN);//右边框 //创建字体对象 Font font = wb.createFont(); font.setFontName("华文行楷"); //字体 font.setFontHeightInPoints((short)28);//字号 style.setFont(font); //行高和列宽 row.setHeightInPoints(50);//行高 //列宽的宽度 字符宽度 sheet.setColumnWidth(2,31 * 256);//列宽 //剧中显示 style.setAlignment(HorizontalAlignment.CENTER);//水平居中 style.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中 //向单元格设置样式 cell.setCellStyle(style); //文件流 FileOutputStream pis = new FileOutputStream("E:\\excel\\poi\\test2.xlsx"); //写入文件 wb.write(pis); pis.close(); } }
骚戴理解: sheet.setColumnWidth(0, 31 * 256);//设置第一列的宽度是31个字符宽度,注意这里要乘以256是因为源码里面设计的时候是会除以256
绘制图形
package cn.itcast.poi.test; import org.apache.poi.ss.usermodel.*; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileInputStream; import java.io.FileOutputStream; /** * 插入图片 */ public class PoiTest04 { public static void main(String[] args) throws Exception { //创建工作簿 HSSFWorkbook -- 2003 Workbook wb = new XSSFWorkbook(); //2007版本 //创建表单sheet Sheet sheet = wb.createSheet("test"); //读取图片流 FileInputStream stream = new FileInputStream("E:\\excel\\poi\\logo.jpg"); //转化二进制数组 byte[] bytes = IOUtils.toByteArray(stream); stream.read(bytes); //向POI内存中添加一张图片,返回图片在图片集合中的索引 int index = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);//参数一:图片的二进制数据,参数二:图片类型 //绘制图片工具类 CreationHelper helper = wb.getCreationHelper(); //创建一个绘图对象 Drawing<?> patriarch = sheet.createDrawingPatriarch(); //创建锚点,设置图片坐标 ClientAnchor anchor = helper.createClientAnchor(); anchor.setRow1(0); anchor.setCol1(0); //绘制图片 Picture picture = patriarch.createPicture(anchor, index);//图片位置,图片的索引 picture.resize();//自适应渲染图片 //文件流 FileOutputStream pis = new FileOutputStream("E:\\excel\\poi\\test3.xlsx"); //写入文件 wb.write(pis); pis.close(); } }
骚戴理解:下面的所谓的锚点其实就是图片的起始下标,例如下面设置就是在第一行第一列插入一张图片
//创建锚点,设置图片坐标 ClientAnchor anchor = helper.createClientAnchor(); anchor.setRow1(0); anchor.setCol1(0);