今日内容

  • 项目组件完善
  • 图片上传
  • 细粒度权限控制
  • 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技术相关推荐

  1. Java图片上传+回显技术

    博主最近在项目中多次运用多ajaxfileupload上传图片技术,并带有图片回显功能,后台java也用到了自己封装得处理文件得方法,分享给大家,一起学习应用,我们不止会New 前言 先说一下整体得流 ...

  2. h5 ajax php 图片上传,图片上传生成海报H5技术详解

    我想很多经常做H5同学都会遇到过让用户上传照片的这种需求,那我这里给大家分享一些我常用的一些方法~废话不多时候,下面可以写一些干货,如果有更好的方法欢迎留言讨论! 首先,需要准备一些需要用到的东西. ...

  3. SpringBoot 2.0 多图片上传加回显

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 本文来源:http://r6f.cn/crEY 这两天公司 ...

  4. Spring Boot 实现多图片上传并回显,涨姿势了~

    上传 Controller的代码非常简单,由于用了SpringMVC框架,所以直接用MultipartFile来接即可.由于是多图片上传所以用数组来接.此处应该注意参数名应该和<input> ...

  5. wangEditor - 轻量级web富文本编辑器(可带图片上传)

    业务需求: 通过后台编辑文章和图片,上传到前端界面,展示新闻消息模块.这个时候,需要一款简洁的编辑器,百度编辑器是最常用的一种,但是功能太过于复杂,而wangEditor - 轻量级web富文本编辑器 ...

  6. jeecg uedit 自定义图片上传路径

    jeecg uedit 图片上传配置自定义物理路径,简单描述:我们知道 jeecg 中使用的 uedit 默认图片上传路径为 "当前项目\plug-in\ueditor\jsp\upload ...

  7. 《shop》 --- 商品图片上传功能

    Image  Upload 三.附件上传 涉及技术点: <form enctype="multipart/form-data"> <input type=&quo ...

  8. element显示服务器的图片,Vue+ElementUI+SpringMVC实现图片上传和回显

    Vue+ElementUI+SpringMVC实现图片上传和table回显 而我们也常遇到表单中包含图片上传的需求,并且需要在table中显示图片,所以这里我就讲一下结合后端的SpringMVC框架如 ...

  9. Vue+ElementUI+SpringMVC实现图片上传和回显

    Vue+ElementUI+SpringMVC实现图片上传和table回显 在之前我们已经讲过了 Vue+ElementUI+SpringMVC实现分页 . 而我们也常遇到表单中包含图片上传的需求,并 ...

最新文章

  1. 排列组合中分组(分堆)与分配问题
  2. linux按内容查找文件
  3. Python 计算机视觉(九)—— OpenCV进行图像平滑
  4. 【Storm篇】--Storm并发机制
  5. MyBatis:事务回滚
  6. 科普一下人工智能领域的研究方向
  7. 论文公式编号右对齐_论文不会写?最详细的论文排版技巧
  8. 软件开发工程师证书有用吗_bim工程师证书有用吗
  9. Ubuntu(Deepin)搭建Android开发环境(Android Studio)
  10. 贪心算法:跳跃游戏总结
  11. Go语言http服务器
  12. 3.深入分布式缓存:从原理到实践 --- 动手写缓存
  13. Facebook登录的时候验证邮箱
  14. 2018-09-26工作日报
  15. 神经内科常用评估量表,神经功能缺损评分量表
  16. 刚开始使用push遇到的小问题
  17. Qt tableview 悬浮提示
  18. 前后端及常用语言介绍
  19. hadoop学习笔记4:java实现hdfs -ls/-lsr
  20. 1 dB压缩点_噪声系数_小信号非线性的数学描述

热门文章

  1. UGC社区敏感词过滤原理
  2. 飞思卡尔MC9S12X:CAN驱动函数在主函数中的应用
  3. 让代码看起来更舒服(1):选择适合的配色方案(更新配色方案生成器)
  4. python坦克大战游戏_Python开发的坦克大战游戏
  5. 读-李智慧-大型网站技术架构:核心原理与案例分析
  6. 深入理解Java虚拟机(第二版) 第九章:类加载及执行子系统的案例与实战
  7. 移动APP用户行为分析
  8. 代码命名规范是一种责任也是一种精神(工匠精神)
  9. ProSpec丨人转铁蛋白说明书
  10. python 将数据保存为excel的xls格式