美文网首页
day06项目【整合阿里云OSS和Excel导入分类】

day06项目【整合阿里云OSS和Excel导入分类】

作者: 刊ing | 来源:发表于2020-07-06 20:45 被阅读0次

    1 整合阿里云OSS

    01-阿里云存储OSS

    一、对象存储OSS

    为了解决海量数据存储与弹性扩容,项目中我们采用云存储的解决方案- 阿里云OSS。 

    1、开通“对象存储OSS”服务

    (1)申请阿里云账号

    (2)实名认证

    (3)开通“对象存储OSS”服务

    (4)进入管理控制台

    2、创建Bucket

    选择:标准存储、公共读、不开通

    3、上传默认头像

    创建文件夹avatar,上传默认的用户头像


    02-后端集成OSS

    一、新建云存储微服务

    1、在service模块下创建子模块service-oss

    2、配置pom.xml

    service-oss上级模块service已经引入service的公共依赖,所以service-oss模块只需引入阿里云oss相关依赖即可,

    service父模块已经引入了service-base模块,所以Swagger相关默认已经引入

    <dependencies>

            <!-- 阿里云oss依赖 -->

            <dependency>

                <groupId>com.aliyun.oss</groupId>

                <artifactId>aliyun-sdk-oss</artifactId>

            </dependency>

            <!-- 日期工具栏依赖 -->

            <dependency>

                <groupId>joda-time</groupId>

                <artifactId>joda-time</artifactId>

            </dependency>

        </dependencies>

    3、配置application.properties

    #服务端口

    server.port=8002

    #服务名

    spring.application.name=service-oss

    #环境设置:dev、test、prod

    spring.profiles.active=dev

    #阿里云OSS

    #不同的服务器,地址不同

    aliyun.oss.file.endpoint=your endpoint

    aliyun.oss.file.keyid=your accessKeyId

    aliyun.oss.file.keysecret=your accessKeySecret

    #bucket可以在控制台创建,也可以使用java代码创建

    aliyun.oss.file.bucketname=guli-file

    4、logback-spring.xml

    5、创建启动类

    创建OssApplication.java

    package com.atguigu.oss;

    import org.springframework.boot.SpringApplication;

    import org.springframework.boot.autoconfigure.SpringBootApplication;

    import org.springframework.context.annotation.ComponentScan;

    @SpringBootApplication

    @ComponentScan(basePackages = {"com.atguigu"})

    public class OssApplication {

        public static void main(String[] args) {

            SpringApplication.run(OssApplication.class,args);

        }

    }

    6、启动项目

    报错

    spring boot 会默认加载org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration这个类,

    而DataSourceAutoConfiguration类使用了@Configuration注解向spring注入了dataSource bean,又因为项目(oss模块)中并没有关于dataSource相关的配置信息,所以当spring创建dataSource bean时因缺少相关的信息就会报错。

    @SpringBootApplication(exclude=DataSourceAutoConfiguration.class)

    即可成功:

    二、实现文件上传

    1、从配置文件读取常量

    创建常量读取工具类:ConstantPropertiesUtil.java

    使用@Value读取application.properties里的配置内容

    用spring的 InitializingBean 的 afterPropertiesSet 来初始化配置信息,这个方法将在所有的属性被初始化后调用。

    //当项目已启动,spring接口,spring加载之后,执行接口一个方法

    @Component

    public class ConstantPropertiesUtil implements InitializingBean {

        //读取配置文件内容

        @Value("${aliyun.oss.file.endpoint}")

        private String endpoint;

        @Value("${aliyun.oss.file.keyid}")

        private String keyId;

        @Value("${aliyun.oss.file.keysecret}")

        private String keySecret;

        @Value("${aliyun.oss.file.bucketname}")

        private String bucketName;

        //定义公开静态常量

        public static String END_POINT;

        public static String ACCESS_KEY_ID;

        public static String ACCESS_KEY_SECRET;

        public static String BUCKET_NAME;

        @Override

        public void afterPropertiesSet()throws Exception {

            END_POINT =endpoint;

            ACCESS_KEY_ID =keyId;

            ACCESS_KEY_SECRET =keySecret;

            BUCKET_NAME =bucketName;

        }

    }

    2、文件上传

    创建Service接口:uploadFileAvatar.java

    public interface OssService {

        String uploadFileAvatar(MultipartFile file);

    }

    实现:OssServiceImpl.java

    参考SDK中的:Java->上传文件->简单上传->流式上传->上传文件流

    @Service

    public class OssServiceImpl implements OssService {

        //上传头像到oss

        @Override

        public String uploadFileAvatar(MultipartFile file) {

            // Endpoint以杭州为例,其它Region请按实际情况填写。

            String endpoint =ConstantPropertiesUtil.END_POINT;

            String accessKeyId =ConstantPropertiesUtil.ACCESS_KEY_ID;

            String accessKeySecret =ConstantPropertiesUtil.ACCESS_KEY_SECRET;

            String bucketName =ConstantPropertiesUtil.BUCKET_NAME;

            try {

                // 创建OSSClient实例。

                OSS ossClient =new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);

                // 上传文件流。

                InputStream inputStream = file.getInputStream();

                //获取文件名称

                String fileName = file.getOriginalFilename();

                //调用oss方法实现上传

                //第一个参数 Bucket名称

                //第二个参数 上传到oss文件路径和文件名称 如/aa/bb/1.jpg

                //第三个参数 上传文件输入流

                ossClient.putObject(bucketName,fileName,inputStream);

                // 关闭OSSClient。

                ossClient.shutdown();

               //把上传之后文件的路径返回

                //需要把上传到阿里云oss路径手动拼接出来

                //https://guli-file-1010.oss-cn-beijing.aliyuncs.com/11.jpg

                String url ="https://"+bucketName+"."+endpoint+"/"+fileName;

                return url;

            }catch (IOException e) {

                e.printStackTrace();

                return null;

            }

        }

    }

    3、控制层

    创建controller:FileUploadController.java

    @Api(description="阿里云文件管理")

    @RestController

    @RequestMapping("/eduoss/fileoss")

    @CrossOrigin

    public class OssController {

        @Autowired

        private OssService ossService;

        //上传头像的方法

        @ApiOperation(value ="文件上传")

        @PostMapping

        public R uploadOssFile(@ApiParam(name ="file", value ="文件", required =true)

                                                             @RequestParam("file")MultipartFile file){

            //获取上传文件

            //返回上传到oss的路径

            String url =ossService.uploadFileAvatar(file);

            return R.ok().data("url",url);

        }

    }

    4、重启oss服务

    5、Swagger中测试文件上传

    解决上传文件覆盖问题:

    //1 在文件名称里面添加随机唯一的值

    String uuid =UUID.randomUUID().toString().replaceAll("-","");

    //如qwadsfadeasd01.jpg

    fileName =uuid+fileName;

    //2 把文件按照日期进行分类

    //2020/11/12/01.jpg

    //获取当前日期

    String datePath =new DateTime().toString("yyyy/MM/dd");

    //拼接

    //如2020/11/12/qwadsfadeasd01.jpg

    fileName =datePath +"/" + fileName;

    测试:

    6、配置nginx反向代理

    配置nginx实现请求转发的功能:

    验证:


    03-前端整合上传组件

    一、前端整合图片上传组件

    1、复制头像上传组件

    从vue-element-admin复制组件:

    vue-element-admin/src/components/ImageCropper

    vue-element-admin/src/components/PanThumb

    2、前端参考实现

    src/views/components-demo/avatarUpload.vue

    3、前端添加文件上传组件

    src/views/edu/teacher/save.vue

    template:

    引入组件模块:

    import ImageCropper from '@/components/ImageCropper'

    import PanThumb from '@/components/PanThumb'

    4、设置默认头像(也可不设置)

    onfig/dev.env.js中添加阿里云oss bucket地址

    OSS_PATH:'"https://guli-file.oss-cn-beijing.aliyuncs.com"'

    组件中初始化头像默认地址

    const defaultForm = {

      ......,

      avatar: process.env.OSS_PATH + '/avatar/default.jpg'

    }

    5、js脚本实现上传和图片回显

    export default {

        components: { ImageCropper, PanThumb },

        data(){

            return {

                teacher:{

    .........

                },

                //上传弹框组件是否显示

                imagecropperShow:false,

                imagecropperKey:0,//上传组件key值

                BASE_API: process.env.BASE_API, // 接口API地址

                saveBtnDisabled: false // 保存按钮是否禁用,

            }

        },

       ......,

        methods: {

            //其他函数

            ......,

            close(){//关闭上传弹框方法

                this.imagecropperShow = false;

                // 上传失败后,重新打开上传组件时初始化组件,否则显示上一次的上传结果

                this.imagecropperKey = this.imagecropperKey + 1

            },

            cropSuccess(data){//上传成功方法

                this.imagecropperShow = false;

                //上传之后接口返回图片地址

                this.teacher.avatar = data.url

                // 上传成功后,重新打开上传组件时初始化组件,否则显示上一次的上传结果

                this.imagecropperKey = this.imagecropperKey + 1

            },

    二、测试文件上传

    前后端联调


    2 EasyExcel导入课程分类

    01-EasyExcel读写Excel的基本使用

    一、Excel导入导出的应用场景

    1、数据导入:减轻录入工作量

    2、数据导出:统计信息归档

    3、数据传输:异构系统之间数据传输

    二、EasyExcel简介

    1、EasyExcel特点

        Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。

        EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

        EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。


    02-Excel写

    一、创建项目,实现EasyExcel对Excel写操作

    1、创建一个普通的maven项目

    项目名:excel-easydemo

    2、pom中引入xml相关依赖

    <dependencies>

            <dependency>

                <groupId>com.alibaba</groupId>

                <artifactId>easyexcel</artifactId>

                <version>2.1.1</version>

            </dependency>

        </dependencies>

    3、创建实体类

    设置表头和添加的数据字段

    @Data

    public class DemoData {

        //设置excel表头名称

        @ExcelProperty("学生编号")

        private Integer sno;

        @ExcelProperty("学生姓名")

        private String sname;

    }

    4 、实现写操作

    TestEasyExcel.java

    (1)创建方法循环设置要添加到Excel的数据

    //循环设置要添加的数据,最终封装到list集合中

    private static List<DemoData> getData(){

            List<DemoData> list = new ArrayList<>();

            for (int i=0;i<10;i++){

                DemoData data = new DemoData();

                data.setSno(i);

                data.setSname("lucy"+i);

                list.add(data);

            }

            return list;

        }

    (2)实现最终的添加操作(写法一)

    public static void main(String[] args) {

            //实现excel写的操作

            //1 设置写入文件夹地址和excel文件名称

            String filename = "F:\\write.xlsx";

            //2 调用easyexcel里面的方法实现写操作

            //write方法两个参数:第一个参数文件路径名称,第二个参数实体类class

            EasyExcel.write(filename,DemoData.class).sheet("学生列表").doWrite(getData());

        }

    (3)实现最终的添加操作(写法二)

    public static void main(String[] args) throws Exception {

            // 写法2,方法二需要手动关闭流

            //实现excel写的操作

            //1 设置写入文件夹地址和excel文件名称

            String filename = "F:\\write.xlsx";

            ExcelWriter excelWriter=EasyExcel.write(fileName,DemoData.class).build();

            WriteSheet writeSheet=EasyExcel.writerSheet("写入方法二").build();

            excelWriter.write(data(),writeSheet);

            /// 千万别忘记finish 会帮忙关闭流

            excelWriter.finish();

        }


    03-Excel读

    一、实现EasyExcel对Excel读操作

    1、创建实体类

    @Data

    public class DemoData {

        //设置excel表头名称

        @ExcelProperty(value = "学生编号",index = 0)

        private Integer sno;

        @ExcelProperty(value = "学生姓名",index = 1)

        private String sname;

    }

    2、创建读取操作的监听器

    public class ExcelListener extends AnalysisEventListener<DemoData> {

        //一行一行读取excel内容

        @Override

        public void invoke(DemoData demoData, AnalysisContext analysisContext) {

            System.out.println("******"+demoData);

        }

        //读取表头内容

        @Override

        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {

            System.out.println("表头:"+headMap);

        }

        //读取完成之后

        @Override

        public void doAfterAllAnalysed(AnalysisContext analysisContext) {

        }

    }

    3、调用实现最终的读取

    public class TestEasyExcel {

        public static void main(String[] args) {

            //实现excel读操作

            // 写法1:

            String filename = "F:\\write.xlsx";

            // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭

            EasyExcel.read(filename,DemoData.class,new ExcelListener()).sheet().doRead();

            // 写法2:

            InputStream in = new BufferedInputStream(new FileInputStream("F:\\01.xlsx"));

            ExcelReader excelReader = EasyExcel.read(in, DemoData.class, new ExcelListener()).build();

            ReadSheet readSheet = EasyExcel.readSheet(0).build();

            excelReader.read(readSheet);

            // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的

            excelReader.finish();

        }


    04-前端页面的实现

    一、Excel模板(本案例中使用静态模板)

    1、编辑Excel模板

    2、将文件上传至阿里云OSS

    二、配置路由

    1、添加路由

    {

        path: '/subject',

        component: Layout,

        redirect: '/subject/table',

        name: '课程分类管理',

        meta: { title: '课程分类管理', icon: 'example' },

        children: [

          {

            path: 'table',

            name: '课程分类列表',

            component: () => import('@/views/edu/subject/list'),

            meta: { title: '课程分类列表', icon: 'table' }

          },

          {

            path: 'tree',

            name: '添加课程分类',

            component: () => import('@/views/edu/subject/save'),

            meta: { title: '添加课程分类', icon: 'tree' }

          }

        ]

      },

    2、添加vue组件

    三、表单组件save.vue

    1、js定义数据

    <script>

    export default {

        data(){

            return {

                BASE_API: process.env.BASE_API, // 接口API地址

                importBtnDisabled: false, // 按钮是否禁用,

                loading: false

            }

        },

    2、template

    <template>

      <div class="app-container">

        <el-form label-width="120px">

          <el-form-item label="信息描述">

            <el-tag type="info">excel模版说明</el-tag>

            <el-tag>

              <i class="el-icon-download"/>

              <a :href="'/static/01.xlsx'">点击下载模版</a>

            </el-tag>

          </el-form-item>

          <el-form-item label="选择Excel">

            <el-upload

              ref="upload"    //相当于id='upload'

              :auto-upload="false"

              :on-success="fileUploadSuccess"

              :on-error="fileUploadError"

              :disabled="importBtnDisabled"

              :limit="1"  //限制每次只能上传一个文件

              :action="BASE_API+'/eduservice/edu-subject/addSubject'"

              name="file"

              accept="application/vnd.ms-excel">

              <el-button slot="trigger" size="small" type="primary">选取文件</el-button>

              <el-button

                :loading="loading"

                style="margin-left: 10px;"

                size="small"

                type="success"

                @click="submitUpload">上传到服务器</el-button>

            </el-upload>

          </el-form-item>

        </el-form>

      </div>

    </template>

    3、js上传方法

    methods:{

            //点击按钮上传文件到接口里面

            submitUpload(){

                this.importBtnDisabled = true

                this.loading = true

                //js:document.getElementById("upload").submit()

                this.$refs.upload.submit()

            },

            ........

        }

    4、回调函数

            //上传成功

            fileUploadSuccess(){

                //提示信息

                this.loading = false

                this.$message({

                    type: 'success',

                    message:'添加课程分类成功'

                })

                //跳转课程分类列表

            },

            //上传失败

            fileUploadError(){

                this.loading = false

                this.$message({

                    type:'error',

                    message:'添加课程失败'

                })

            }


    05-课程分类管理接口

    一、添加依赖

    1、service-edu模块配置依赖

    <dependencies>

            <dependency>

                <groupId>com.alibaba</groupId>

                <artifactId>easyexcel</artifactId>

                <version>2.1.1</version>

            </dependency>

        </dependencies>

    二、业务处理

    1、EduSubjectController

    @Api(description="课程分类管理")

    @RestController

    @RequestMapping("/eduservice/edu-subject")

    @CrossOrigin //跨域

    public class EduSubjectController {

        @Autowired

        private EduSubjectService subjectService;

        //添加课程分类

        //获取上传过来的文件把文件内容读取出来

        @PostMapping("addSubject")

        public R addSubject(MultipartFile file){

            //上传过来的excel文件

            subjectService.saveSubject(file,subjectService);

            return R.ok();

        }

    }

    2、创建和Excel对应的实体类

    @Data

    public class SubjectData {

        @ExcelProperty(index = 0)

        private String oneSubjectName;

        @ExcelProperty(index = 1)

        private String twoSubjectName;

    }

    3、EduSubjectService

    (1)接口

    public interface EduSubjectService extends IService<EduSubject> {

        //添加课程分类

        void saveSubject(MultipartFile file,EduSubjectService subjectService);

    }

    (2)实现类

    @Service

    public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {

        //添加课程分类

        @Override

        public void saveSubject(MultipartFile file,EduSubjectService subjectService) {

            try {

                //文件输入流

                InputStream in = file.getInputStream();

                //调用方法进行读取

                EasyExcel.read(in, SubjectData.class,new SubjectExcelListener(subjectService)).sheet().doRead();

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

    4、创建读取Excel监听器

    public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {

        //因为SubjectExcelListener不能交给spring进行管理,需要自己new,不能注入其他对象

        //不能实现数据库操作

        public EduSubjectService subjectService;

        public SubjectExcelListener() {}

        public SubjectExcelListener(EduSubjectService subjectService) {

            this.subjectService = subjectService;

        }

        //读取excel内容,一行一行进行读取

        @Override

        public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {

            if (subjectData == null){

                throw new GuliException(20001,"文件数据为空");

            }

            //一行一行读取,每次读取有两个值,第一个值一级分类,第二个值二级分类

            //判断一级分类是否重复

            EduSubject exitOneSubject = this.exitOneSubject(subjectService, subjectData.getOneSubjectName());

            if (exitOneSubject == null){//没有相同一级分类,进行添加

                exitOneSubject = new EduSubject();

                exitOneSubject.setParentId("0");

                exitOneSubject.setTitle(subjectData.getOneSubjectName()); //一级分类名称

                subjectService.save(exitOneSubject);

            }

            String pid = exitOneSubject.getId();

            //添加二级分类

            //判断二级分类是否重复

            EduSubject exitTwoSubject = this.exitTwoSubject(subjectService, subjectData.getTwoSubjectName(), pid);

            if (exitTwoSubject == null){

                exitTwoSubject = new EduSubject();

                exitTwoSubject.setParentId(pid);

                exitTwoSubject.setTitle(subjectData.getTwoSubjectName()); //一级分类名称

                subjectService.save(exitTwoSubject);

            }

        }

        //判断一级分类不能重复添加

        private EduSubject exitOneSubject(EduSubjectService subjectService, String name){

            QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();

            wrapper.eq("title",name);

            wrapper.eq("parent_id","0");

            EduSubject oneSubject = subjectService.getOne(wrapper);

            return oneSubject;

        }

        //判断二级分类不能重复添加

        private EduSubject exitTwoSubject(EduSubjectService subjectService, String name,String pid){

            QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();

            wrapper.eq("title",name);

            wrapper.eq("parent_id",pid);

            EduSubject twoSubject = subjectService.getOne(wrapper);

            return twoSubject;

        }

        @Override

        public void doAfterAllAnalysed(AnalysisContext analysisContext) {

        }

    }


    06-分类列表展示

    一、前端实现

    1、参考 views/tree/index.vue

    2、创建api

    api/edu/subject.js

    import request from '@/utils/request'

    export default{

        //1 课程分类

        getSubjectList(){

            return request({

                url:`/eduservice/edu-subject/getAllSubject`,

                method:'get'

            })

        }

    }

    3、list.vue

    <template>

      <div class="app-container">

        <el-input v-model="filterText" placeholder="Filter keyword" style="margin-bottom:30px;" />

        <el-tree

          ref="tree2"

          :data="data2"

          :props="defaultProps"

          :filter-node-method="filterNode"

          class="filter-tree"

          default-expand-all

        />

      </div>

    </template>

    <script>

    import subject from '@/api/edu/subject'

    export default {

      data() {

        return {

          filterText: '',

          data2: [], //返回所有分类数据

          defaultProps: {

            children: 'children',

            label: 'title'

          }

        }

      },

      created(){

        this.getAllSubjectList()

      },

      watch: {

        filterText(val) {

          this.$refs.tree2.filter(val)

        }

      },

      methods: {

        getAllSubjectList(){

          subject.getSubjectList()

            .then(response=>{

                this.data2 = response.data.list

            })

        },

        filterNode(value, data) {

          if (!value) return true

          return data.title.toLowerCase().indexOf(value.toLowerCase()) !== -1  //优化前端过滤功能

        }

      }

    }

    </script>

    二、后端实现

    1、创建vo

    //一级分类

    @Data

    public class OneSubject {

        private String id;

        private String title;

        //一个一级分类含有多个二级分类

        private Listchildren =new ArrayList<>();

    }

    //二级分类

    @Data

    public class TwoSubject {

        private String id;

        private String title;

    }

    2、创建controller

        //课程分类列表(树形)
        @ApiOperation(value = "嵌套数据列表")

        @GetMapping("getAllSubject")

        public R getAllSubject(){

            //list集合泛型是一级分类

            List<OneSubject> list = subjectService.getAllOneTwoSubject();

            return R.ok().data("list",list);

        }

    3、创建service

    接口

        //课程分类列表(树形)

        List<OneSubject> getAllOneTwoSubject();

    实现Final

        @Override

        public List<OneSubject> getAllOneTwoSubject() {

            //1 获取一级分类 parent_id=0

            QueryWrapper<EduSubject> wrapperOne = new QueryWrapper<>();

            wrapperOne.eq("parent_id","0");

            List<EduSubject> oneSubjectList = baseMapper.selectList(wrapperOne);

            //2 获取二级分类

            QueryWrapper<EduSubject> wrapperTwo = new QueryWrapper<>();

            wrapperTwo.ne("parent_id","0");

            List<EduSubject> twoSubjectList = baseMapper.selectList(wrapperTwo);

            //创建list集合用于存储最终封装数据

            List<OneSubject> finalSubjectList = new ArrayList<>();

            //3 封装一级分类

            //查询出来的所有一级分类list集合遍历,得到每一个分类对象,获取每一个一级分类对象值

            //封装到要求的list集合里面 List<OneSubject> finalSubjectList

            for (int i = 0; i < oneSubjectList.size(); i++) {

                //得到oneSubjectList每个eduSubject对象

                EduSubject eduSubject = oneSubjectList.get(i);

                //把eduSubject里面获取出来的值,放到oneSubject对象里面

                OneSubject oneSubject = new OneSubject();

    //            oneSubject.setId(eduSubject.getId());

    //            oneSubject.setTitle(eduSubject.getTitle());

                BeanUtils.copyProperties(eduSubject,oneSubject);

                //多个oneSubject放到finalSubjectList里面

                finalSubjectList.add(oneSubject);

                //4 封装二级分类

                //在一级分类循环遍历查询所有二级分类

                //创建list集合封装每一个一级分类的二级分类

                List<TwoSubject> twoFinalSubjectList = new ArrayList<>();

                for (int m = 0; m < twoSubjectList.size(); m++) {

                    //获取每个二级分类

                    EduSubject tSubject = twoSubjectList.get(m);

                    //判断二级分类parentid和一级分类id是否一样

                    if (tSubject.getParentId().equals(eduSubject.getId())){

                        //把tSubject值复制到twoSubject里面,放到twoFinalSubjectList里面

                        TwoSubject twoSubject = new TwoSubject();

                        BeanUtils.copyProperties(tSubject,twoSubject);

                        twoFinalSubjectList.add(twoSubject);

                    }

                }

                //把一级下面所有的二级分类放到一级分类里面

                oneSubject.setChildren(twoFinalSubjectList);

            }

            return finalSubjectList;

        }

    相关文章

      网友评论

          本文标题:day06项目【整合阿里云OSS和Excel导入分类】

          本文链接:https://www.haomeiwen.com/subject/bdvuqktx.html