细粒度,图片上传,POI技术
今日内容
- 项目组件完善
- 图片上传
- 细粒度权限控制
- POI技术
第一章 附件管理
1. 附件列表
在export_manager_web
模块的com.itheima.web.controller.cargo
下创建ExtCproductController
package com.itheima.web.controller.cargo;
import com.alibaba.dubbo.config.annotation.Reference;import com.github.pagehelper.PageInfo;import com.itheima.domain.cargo.ExtCproductExample;import com.itheima.domain.cargo.Factory;import com.itheima.domain.cargo.FactoryExample;import com.itheima.service.cargo.ExtCproductService;import com.itheima.service.cargo.FactoryService;import com.itheima.web.controller.BaseController;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Controller@RequestMapping("/cargo/extCproduct")public class ExtCproductController extends BaseController {
@Reference private ExtCproductService extCproductService;
@Reference private FactoryService factoryService;
@RequestMapping(value = "/list", name = "附件列表查询") public String list( @RequestParam(defaultValue = "1", name = "page") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize, String contractId, String contractProductId) {
ExtCproductExample extCproductExample = new ExtCproductExample();
//1 查询当前货物下的所有附件 extCproductExample.createCriteria().andContractProductIdEqualTo(contractProductId); PageInfo pageInfo = extCproductService.findByPage(pageNum, pageSize, extCproductExample); request.setAttribute("page", pageInfo);
//2 查询所有生产附件的厂家列表 FactoryExample factoryExample = new FactoryExample(); factoryExample.createCriteria().andCtypeEqualTo("附件"); List<Factory> factoryList = factoryService.findAll(factoryExample); request.setAttribute("factoryList", factoryList);
//3. 回传合同id 和 货物id request.setAttribute("contractId", contractId); request.setAttribute("contractProductId", contractProductId);
return "/cargo/extc/extc-list"; }
}
2. 新增附件
2.1 ExtCproductController
@RequestMapping(value = "/edit", name = "附件新增或编辑")public String edit(ExtCproduct extCproduct) { if (StringUtils.isEmpty(extCproduct.getId())) { //1. 设置主键 extCproduct.setId(UUID.randomUUID().toString());
//2. 设置企业信息 extCproduct.setCompanyId(getCompanyId()); extCproduct.setCompanyName(getCompanyName());
extCproductService.save(extCproduct); } else { extCproductService.update(extCproduct); }
//重定向到list方法 return "redirect:/cargo/extCproduct/list.do?contractId=" + extCproduct.getContractId() + "&contractProductId=" + extCproduct.getContractProductId();}
2.2 ExtCproductServiceImpl
@Override public void save(ExtCproduct extCproduct) { // 查询合同对象 Contract contract = contractDao.selectByPrimaryKey(extCproduct.getContractId()); // 计算小计金额 double amount = extCproduct.getCnumber() * extCproduct.getPrice(); extCproduct.setAmount(amount);
// 保存附件 extCproductDao.insertSelective(extCproduct); // 修改合同的附件种数 contract.setExtNum(contract.getExtNum() + 1); // 修改合同的总金额 contract.setTotalAmount(contract.getTotalAmount() + amount); contractDao.updateByPrimaryKeySelective(contract); }
3. 修改附件
3.1 跳转修改页面
修改ExtCproductController添加代码
@RequestMapping(value = "/toUpdate", name = "跳转附件编辑页面")public String toUpdate(String id) { //1. 根据id查询当前附件信息 ExtCproduct extCproduct = extCproductService.findById(id); request.setAttribute("extCproduct", extCproduct);
//2. 查询所有生产附件的厂家列表 FactoryExample factoryExample = new FactoryExample(); factoryExample.createCriteria().andCtypeEqualTo("附件"); List<Factory> factoryList = factoryService.findAll(factoryExample); request.setAttribute("factoryList", factoryList);
//3. 转发到修改页面 return "/cargo/extc/extc-update";}
3.2 修改附件
修改ExtCproductServiceImpl添加代码
@Override public void update(ExtCproduct extCproduct) {
//根据合同id,得到合同对象 Contract contract = contractDao.selectByPrimaryKey(extCproduct.getContractId());
//根据附件id查询附件的信息 ExtCproduct extCproductOld = extCproductDao.selectByPrimaryKey(extCproduct.getId());
//附件修改 //计算小计金额 Double amount = extCproduct.getPrice() * extCproduct.getCnumber(); extCproduct.setAmount(amount);
//执行修改 extCproductDao.updateByPrimaryKeySelective(extCproduct);
//合同修改 //修改总金额 - 源小计 + 新小计 contract.setTotalAmount(contract.getTotalAmount() - extCproductOld.getAmount() + amount);
// 执行合同修改 contractDao.updateByPrimaryKeySelective(contract); }
4. 删除附件
4.1 ExtCproductController
@RequestMapping(value = "/delete", name = "附件删除")public String delete(String id, String contractId, String contractProductId) { //调用service删除 extCproductService.delete(id);//附件id
//重定向到list方法 return "redirect:/cargo/extCproduct/list.do?contractId=" + contractId + "&contractProductId=" + contractProductId;}
4.2 ExtCproductServiceImpl
@Override public void delete(String id) { //1. 根据附件id查询附件信息 ExtCproduct extCproduct = extCproductDao.selectByPrimaryKey(id);
//2. 根据合同id查询合同信息 Contract contract = contractDao.selectByPrimaryKey(extCproduct.getContractId());
//附件删除 extCproductDao.deleteByPrimaryKey(id);
//货物无影响 //合同修改 //1. 修改合同中的附件数量 - 1 contract.setExtNum(contract.getExtNum() - 1);
//2. 修改合同中的总金额 - 要删除的附件的小计 contract.setTotalAmount(contract.getTotalAmount() - extCproduct.getAmount());
//3. 执行修改 contractDao.updateByPrimaryKeySelective(contract); }
第二章 项目中的图片上传
前端上传到后台: SpringMVC 文件上传解析器( 前端三要素 )
后台上传到七牛云: 工具类
在当前项目中的货物和附件的添加和修改页面, 都是需要做文件上传功能的, 下面就来实现以下
1. 工具类准备
qiniu.accessKey=B6NvfR2Gp_**********wKsJ4ISpdsORS85ZH2Z-qiniu.secretKey=vS5YNOikZj**********G1hZR-7i-NLRbSIL71tBqiniu.bucket=saas-tj4qiniu.rtValue=http://qi8eho848.hn-bkt.clouddn.com/
注意: 一定要删除dao模块中Spring配置文件中的引入外部配置的部分
2. 配置文件上传解析器
在export_manager_web
模块下的resources下的spring/spring-mvc.xml
文件中添加文件上传解析器
<!--文件上传解析器, 这个id不能随便改--><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置上传文件的最大尺寸为 5MB --> <property name="maxUploadSize" value="5242880" /></bean>
3. 代码编写
3.1 页面代码调整
修改页面中文件上传表单的enctype=”multipart/form-data”属性
3.2 后台代码编写
@Autowired private FileUploadUtil fileUploadUtil;
@RequestMapping(value = "/edit", name = "货物新增,修改")public String edit(ContractProduct contractProduct, MultipartFile productPhoto ) { // 文件上传
try { String filePath = fileUploadUtil.upload(productPhoto); contractProduct.setProductImage(filePath); } catch (Exception e) { e.printStackTrace(); System.out.println("文件上传失败"); throw new RuntimeException(e); }
if (StringUtils.isEmpty(contractProduct.getId())) { //1. 设置主键 contractProduct.setId(UUID.randomUUID().toString()); //2. 设置企业信息 contractProduct.setCompanyId(getCompanyId()); contractProduct.setCompanyName(getCompanyName());
contractProductService.save(contractProduct);
} else { contractProductService.update(contractProduct); } //重定向到list方法 return "redirect:/cargo/contractProduct/list.do?contractId=" + contractProduct.getContractId();}
第三章 细粒度权限控制(面试)
粗粒度权限:将权限控制到类型级别 (张三可以访问部门信息 , 但是不能访问用户信息) shiro
细粒度权限:将权限控制到数据级别 (张三可以访问1号用户信息, 但是不能访问2号用户信息) 自己写SQL
一个优秀的后台程序应当做到对权限的细粒度控制, 即数据级别的权限控制
1. 需求分析
在我们的系统中,除了两类管理员之外,员工也分为三类:
- 普通员工:只能看自己的合同数据
- 部门经理:可以看到本部分所有员工的合同数据
- 总经理:可以看到本部门及所有子部门的合同数据
- 4 普通员工:只能看自己的合同数据 select * from co_contract where create_by = 'session获取登录人的id'- 3 部门经理:可以看到本部分所有员工的合同数据 select * from co_contract where create_dept = 'session获取登录人的所在部门的id'- 2 总经理:可以看到本部门及所有子部门的合同数据 select * from co_contract where create_dept like 'session获取登录人的所在部门的id%'
if(degree == 4){ select * from co_contract where create_by = 'session获取登录人的id'}else if(degree == 3){ select * from co_contract where create_dept = 'session获取登录人的所在部门的id'}else if(degree == 2){ select * from co_contract where create_dept like 'session获取登录人的所在部门的id%'}else{ 不受细粒度权限控制}
2. 代码实现
修改ContractController
中查询合同列表的方法
@RequestMapping(value = "/list", name = "合同列表查询") public String list( @RequestParam(defaultValue = "1", name = "page") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {
ContractExample contractExample = new ContractExample();
//1 封装条件 ContractExample.Criteria criteria = contractExample.createCriteria(); criteria.andCompanyIdEqualTo(getCompanyId());
//判断用户等级,根据等级不同去拼接不同条件 Integer degree = getUser().getDegree(); if (degree == 4) {//普通员工 criteria.andCreateByEqualTo(getUser().getId()); } else if (degree == 3) {//部门经理 criteria.andCreateDeptEqualTo(getUser().getDeptId()); } else if (degree == 2) {//总经理 criteria.andCreateDeptLike(getUser().getDeptId() + "%"); }
//2 排序 contractExample.setOrderByClause("create_time desc");
PageInfo pageInfo = contractService.findByPage(pageNum, pageSize, contractExample); request.setAttribute("page", pageInfo);
return "/cargo/contract/contract-list"; }
3. 测试
系统中已经内置好了几个账户用于测试,结构如下,密码都是123 ,分配的角色都是销售专责,权限是只能管理购销合同
第四章 POI报表技术
1. 概述
1.1 简介
在企业内部系统中,有很多地方会用到Excel表格,目前的Excel分为两个大的版本:Excel2003和Excel2007及以上。两者之间的区别如下:
区别 | Excel 2003 | Excel 2007及以上 |
---|---|---|
扩展名 | xls | xlsx |
数据结构 | 二进制格式 | xml格式 |
单sheet数据量 | 行:65535、列:256 | 行:1048576、列:16384 |
特点 | 存储容量有限 | 基于xml压缩,占用空间小,操作效率高 |
Java中常见的用来操作Excl的方式一般有2种:JXL和POI。
JXL只能对Excel进行操作,属于比较老的框架,它只支持到Excel 95-2000的版本,现在已经停止更新和维护。
POI是apache的项目,可对微软的Word、Excel、PPT进行操作,包括office2003和2007两个大版本,是目前主流的操作execl的技术。
1.2 Execl基础概念
Execl基础概念在POI中的API描述如下:
Execl中的概念 | 2003版本对象 | 2007版本对象 |
---|---|---|
工作簿(WorkBook) | HssfWordBook | XssfWorkBook |
工作表(Sheet) | HssfSheet | XssfSheet |
行(Row) | HssfRow | XssfRow |
单元格(Cell) | HssfCell | XssfCell |
2. 入门案例
2.1 创建工程,引入依赖
<dependencies> <!--2003--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.0.1</version> </dependency> <!--2007--> <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>
2.2 创建Execl
package com.itheima.poi;
import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.ss.usermodel.Workbook;import org.apache.poi.xssf.usermodel.XSSFSheet;import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;
/** * @description: * @author: mryhl * @date: Created in 2020/10/17 11:30 * @version: 1.1 */public class CreatePoiDemo {
public static void main(String[] args) throws IOException { // 创建一个Execl工作簿 Workbook workbook = new XSSFWorkbook(); // 使用工作簿创建一个工作表 Sheet sheet = workbook.createSheet(); // 设置列宽 sheet.setColumnWidth(0,20*256); // 使用工作表创建一个行,使用索引计数 Row row = sheet.createRow(0); // 使用行创建一个单元格,使用索引计数 Cell cell = row.createCell(0); // 写入数据 cell.setCellValue("生活就是这么简单");
// 写入文件 workbook.write(new FileOutputStream(new File("E:\\项目一\\资料\\data.xlsx"))); }}
2.3 读取Execl
package com.itheima.poi;
import com.itheima.domain.ContractProduct;import org.apache.poi.ss.usermodel.*;import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.util.ArrayList;import java.util.List;
/** * @description: * @author: mryhl * @date: Created in 2020/10/17 11:43 * @version: 1.1 */public class ReadPoiDemo2 { public static void main(String[] args) throws IOException { // 创建工作簿对象,并读取数据 Workbook workbook = new XSSFWorkbook(new FileInputStream(new File("E:\\项目一\\资料\\3-货物导入模板\\上传货物模板.xlsx"))); // 通过工作簿获取到工作表,通过索引获取 Sheet sheet = workbook.getSheetAt(0); // 通过工作表获取行 获取方式是遍历获取
List<ContractProduct> list1 = new ArrayList<ContractProduct>();
for (int i = 1; i <= sheet.getLastRowNum(); i++) { Row row = sheet.getRow(i); Object[] objects = new Object[row.getLastCellNum()]; for (int j = 1 ; j < row.getLastCellNum(); j++){ objects[j-1]=getCellValue(row.getCell(j)); } //System.out.println(objects.toString()); list1.add(new ContractProduct(objects)); } for (ContractProduct contractProduct : list1) { System.out.println(contractProduct); }
System.out.println(list1);
}
/** * @description * @author mryhl * @date 2020/10/17 11:51 * @return 解析每个单元格的数据 */ public static Object getCellValue(Cell cell) { Object obj = null; CellType cellType = cell.getCellType(); //获取单元格数据类型 switch (cellType) { case STRING: { obj = cell.getStringCellValue();//字符串 break; } //excel默认将日期也理解为数字 case NUMERIC: { if (DateUtil.isCellDateFormatted(cell)) { obj = cell.getDateCellValue();//日期 } else { obj = cell.getNumericCellValue(); // 数字 } break; } case BOOLEAN: { obj = cell.getBooleanCellValue(); // 布尔 break; } default: { break; } } return obj; }}
第五章 货物导入
1. 需求分析
2. 进入货物导入页面
修改ContractProductController, 添加方法
@RequestMapping(value = "/toImport", name = "跳转货物批量上传的页面")public String toImport(String contractId) { //回显合同id request.setAttribute("contractId", contractId);
//转发到上传页面 return "/cargo/product/product-import";}
3. 实现导入功能
3.1 ContractProductController
@RequestMapping(value = "/import", name = "货物批量上传") public String imports(String contractId, MultipartFile file) throws IOException { //1. 接收传递过来的参数 合同id 货物的文件
//2. 读取一个File--流--工作簿 Workbook workbook = new XSSFWorkbook(file.getInputStream());
//3. 使用工作簿获取工作表 Sheet sheet = workbook.getSheetAt(0);
//4. 从工作表获取行 List<ContractProduct> list = new ArrayList<>(); for (int i = 1; i < sheet.getLastRowNum() + 1; i++) { Row row = sheet.getRow(i); //5 从行中获取单元格 Object[] objs = new Object[9]; for (int j = 1; j < row.getLastCellNum(); j++) { //6. 从单元格中获取数据 Cell cell = row.getCell(j); Object cellValue = getCellValue(cell); objs[j - 1] = cellValue; } ContractProduct contractProduct = new ContractProduct(objs); //7 补全信息 contractProduct.setId(UUID.randomUUID().toString()); contractProduct.setContractId(contractId); contractProduct.setCompanyId(getCompanyId()); contractProduct.setCompanyName(getCompanyName());
FactoryExample factoryExample = new FactoryExample(); factoryExample.createCriteria().andFactoryNameEqualTo(contractProduct.getFactoryName()); List<Factory> factories = factoryService.findAll(factoryExample); contractProduct.setFactoryId(factories.get(0).getId());
//8. 封装一个List集合对象 list.add(contractProduct); }
//9 调用service保存 contractProductService.patchSave(list);
//10 跳转页面 return "redirect:/cargo/contractProduct/list.do?contractId=" + contractId; }
//解析每个单元格的数据 public static Object getCellValue(Cell cell) { Object obj = null; CellType cellType = cell.getCellType(); //获取单元格数据类型 switch (cellType) { case STRING: { obj = cell.getStringCellValue();//字符串 break; } //excel默认将日期也理解为数字 case NUMERIC: { if (DateUtil.isCellDateFormatted(cell)) { obj = cell.getDateCellValue();//日期 } else { obj = cell.getNumericCellValue(); // 数字 } break; } case BOOLEAN: { obj = cell.getBooleanCellValue(); // 布尔 break; } default: { break; } } return obj; }
3.2 ContractProductService
void patchSave(List<ContractProduct> list);
3.3 ContractProductServiceImpl
@Overridepublic void patchSave(List<ContractProduct> list) { for (ContractProduct contractProduct : list) { this.save(contractProduct); }}
细粒度,图片上传,POI技术相关推荐
- Java图片上传+回显技术
博主最近在项目中多次运用多ajaxfileupload上传图片技术,并带有图片回显功能,后台java也用到了自己封装得处理文件得方法,分享给大家,一起学习应用,我们不止会New 前言 先说一下整体得流 ...
- h5 ajax php 图片上传,图片上传生成海报H5技术详解
我想很多经常做H5同学都会遇到过让用户上传照片的这种需求,那我这里给大家分享一些我常用的一些方法~废话不多时候,下面可以写一些干货,如果有更好的方法欢迎留言讨论! 首先,需要准备一些需要用到的东西. ...
- SpringBoot 2.0 多图片上传加回显
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 本文来源:http://r6f.cn/crEY 这两天公司 ...
- Spring Boot 实现多图片上传并回显,涨姿势了~
上传 Controller的代码非常简单,由于用了SpringMVC框架,所以直接用MultipartFile来接即可.由于是多图片上传所以用数组来接.此处应该注意参数名应该和<input> ...
- wangEditor - 轻量级web富文本编辑器(可带图片上传)
业务需求: 通过后台编辑文章和图片,上传到前端界面,展示新闻消息模块.这个时候,需要一款简洁的编辑器,百度编辑器是最常用的一种,但是功能太过于复杂,而wangEditor - 轻量级web富文本编辑器 ...
- jeecg uedit 自定义图片上传路径
jeecg uedit 图片上传配置自定义物理路径,简单描述:我们知道 jeecg 中使用的 uedit 默认图片上传路径为 "当前项目\plug-in\ueditor\jsp\upload ...
- 《shop》 --- 商品图片上传功能
Image Upload 三.附件上传 涉及技术点: <form enctype="multipart/form-data"> <input type=&quo ...
- element显示服务器的图片,Vue+ElementUI+SpringMVC实现图片上传和回显
Vue+ElementUI+SpringMVC实现图片上传和table回显 而我们也常遇到表单中包含图片上传的需求,并且需要在table中显示图片,所以这里我就讲一下结合后端的SpringMVC框架如 ...
- Vue+ElementUI+SpringMVC实现图片上传和回显
Vue+ElementUI+SpringMVC实现图片上传和table回显 在之前我们已经讲过了 Vue+ElementUI+SpringMVC实现分页 . 而我们也常遇到表单中包含图片上传的需求,并 ...
最新文章
- 排列组合中分组(分堆)与分配问题
- linux按内容查找文件
- Python 计算机视觉(九)—— OpenCV进行图像平滑
- 【Storm篇】--Storm并发机制
- MyBatis:事务回滚
- 科普一下人工智能领域的研究方向
- 论文公式编号右对齐_论文不会写?最详细的论文排版技巧
- 软件开发工程师证书有用吗_bim工程师证书有用吗
- Ubuntu(Deepin)搭建Android开发环境(Android Studio)
- 贪心算法:跳跃游戏总结
- Go语言http服务器
- 3.深入分布式缓存:从原理到实践 --- 动手写缓存
- Facebook登录的时候验证邮箱
- 2018-09-26工作日报
- 神经内科常用评估量表,神经功能缺损评分量表
- 刚开始使用push遇到的小问题
- Qt tableview 悬浮提示
- 前后端及常用语言介绍
- hadoop学习笔记4:java实现hdfs -ls/-lsr
- 1 dB压缩点_噪声系数_小信号非线性的数学描述