11 spring web - commodity module implementation

Keywords: Spring

1. Complete commodity classification business

1.1 page JS analysis

  1. Life cycle function
	//Define initialization function
    created() {
      //Get commodity classification list data by default
      this.findItemCatList()
    },

  1. Get data function description
async findItemCatList() {
        const {
          data: result
        } = await this.$http.get("/itemCat/findItemCatList/3")
        if (result.status !== 200) return this.$message.error("Failed to get commodity classification list!!")
        this.itemCatList = result.data
      },

1.2 business interface documents

  • Request path: / itemCat/findItemCatList/{level}
  • Request type: get
  • Request parameter: level
Parameter nameParameter descriptionremarks
levelQuery level1 query level 1 Classification 2 query level 1-2 commodity classification 3 query level 1-2-3 commodity classification
  • Business description: querying Level 3 Classification menu data requires a three-tier nested structure
  • Return value: SysResult object
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverLevel 3 commodity classification information

1.3 structure description of commodity classification table

  1. Table structure

  2. sql case exercise

/*All first level menus parent_id=0*/
SELECT * FROM item_cat WHERE parent_id = 0
/*Query the secondary menu of automobile users*/
SELECT * FROM item_cat WHERE parent_id = 249
/*Query the three-level menu of on-board electrical appliances*/
SELECT * FROM item_cat WHERE parent_id = 281

Summary: commodity classification table, through parent_id to specify the parent - child relationship

1.4 edit ItemCatController

@RestController
@CrossOrigin
@RequestMapping("/itemCat")
public class ItemCatController {

    @Autowired
    private ItemCatService itemCatService;

    /**
     * Demand: query commodity classification information
     * Parameters: / {level} 1 level 1 2 level 1 2 Level 3 level 1 2 Level 3
     * url: /itemCat/findItemCatList/{level}  restFul
     * Return value: sysresult (Level 3 list information)
     */
    @GetMapping("findItemCatList/{level}")
    public SysResult findItemCatList(@PathVariable Integer level){

        List<ItemCat> itemCatList = itemCatService.findItemCatList(level);
        return SysResult.success(itemCatList);
    }

}

1.5 edit ItemCatService

package com.jt.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.ItemCatMapper;
import com.jt.pojo.ItemCat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ItemCatServiceImpl implements ItemCatService{

    @Autowired
    private ItemCatMapper itemCatMapper;

    /**
     * Step 1. Query the first level menu list
     * @param level
     * @return
     */
    @Override
    public List<ItemCat> findItemCatList(Integer level) {
        //1. Query level-1 menu
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("parent_id",0);
        List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
        //2. Query secondary menu secondary data is the sub level of primary data encapsulated in primary data
        for(ItemCat oneItemCat : oneList){
            int oneId = oneItemCat.getId(); //Primary object ID
            //Empty original condition must have
            queryWrapper.clear();
            queryWrapper.eq("parent_id",oneId);
            List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);
            for(ItemCat twoItemCat : twoList){
                //Get secondary classification ID
                int twoId = twoItemCat.getId();
                //Query Level 3 list information
                queryWrapper.clear();
                queryWrapper.eq("parent_id",twoId);
                List<ItemCat> threeList = itemCatMapper.selectList(queryWrapper);
                //Encapsulate a tertiary list into a secondary object
                twoItemCat.setChildren(threeList);
            }
            //Encapsulate secondary data into primary objects
            oneItemCat.setChildren(twoList);
        }
        return oneList;
    }
}

1.6 above case analysis

  1. The above case adopts a multi-level cycle. In the future, it will consume 100 server resources, 100 inner layers and 10000 cycles in total. It is acceptable for the time being
  2. The above code frequently accesses the database, resulting in increased database pressure. In severe cases, it may lead to database server downtime. Unacceptable
    Optimization strategy: reduce the number of database accesses

1.7 data structure optimization code

Idea:

  1. Users query all database information. (1-2-3 all data)
  2. The data structure map < K, V > key is unique, and value can be of any type
    Idea: Map < parentid, list >
    example:
  3. Map < 0, list < first level ItemCat Object > >
  4. Map < 249, list < secondary ItemCat Object > >
  5. Map < 281, list < Level 3 ItemCat Object > >
    map is used to encapsulate parent - child relationship

1.8 code implementation

@Service
public class ItemCatServiceImpl implements ItemCatService{

    @Autowired
    private ItemCatMapper itemCatMapper;

    /**
     * Encapsulate all database records with Map collection
     * Encapsulated data:
     *      1.Traverse all data information
     *      2.Get the value of each parentId
     * example:
     *      1.{id=1,parentId=0,name="Zhang San "}
     *      2.{id=2,parentId=0,name="Li Si "}
     *      3.{id=3,parentId=1,name="Wang Wu "}
     *      Map= {
     *          key : value
     *          0   : List[Zhang San object, Li Si object...],
     *          1   : List[Wang Wu...]
     *      }
     * @return
     */
    public Map<Integer,List<ItemCat>> getMap(){
        Map<Integer,List<ItemCat>> map = new HashMap<>();
        //1. Query all database information
        List<ItemCat> itemCatList = itemCatMapper.selectList(null);
        //2. Encapsulate the data into the map set
        for (ItemCat itemCat : itemCatList){
            Integer key = itemCat.getParentId(); //Get parentId as key
            //3. Judge whether there is a value in the map set
            if(map.containsKey(key)){
                //With value: get the List collection and append yourself to it
                map.get(key).add(itemCat);
            }else{
                //No value: add data. Fill yourself as the first element
                List<ItemCat> list = new ArrayList<>();
                list.add(itemCat);
                map.put(key,list);
            }
        }
        return map;
    }

    @Override
    public List<ItemCat> findItemCatList(Integer level) {
        long startTime = System.currentTimeMillis();
        Map<Integer,List<ItemCat>> map = getMap();
        //Obtain child information according to level
        if(level == 1){ //Get only the first level list information
            return map.get(0);
        }
        if(level == 2){ //Obtain primary and secondary data
            return getTwoList(map);
        }
        List<ItemCat> oneList = getThreeList(map);
        long endTime = System.currentTimeMillis();
        System.out.println("Time before optimization: 500ms,Time consuming after optimization:"+(endTime - startTime)+"ms");
        return oneList;
    }

    //To obtain the three-level list information, first obtain the level 1 data, then obtain the level 2 data, and then obtain the level 3 data

    private List<ItemCat> getThreeList(Map<Integer, List<ItemCat>> map) {
        //1. Call the level 2 menu method
        List<ItemCat> oneList = getTwoList(map);
        //2. The implementation idea traverses the primary set, obtains secondary data, and encapsulates the tertiary menu
        for(ItemCat oneItemCat : oneList){
            //2.1 obtaining secondary data
            List<ItemCat> twoList = oneItemCat.getChildren();
            if(twoList == null || twoList.size()==0){
                //Judge whether the secondary collection is null. If it is null, it means there is no secondary menu
                continue;
            }
            for (ItemCat twoItemCat : twoList){
                int twoId = twoItemCat.getId();
                List<ItemCat> threeList = map.get(twoId);
                twoItemCat.setChildren(threeList);
            }
        }
        return oneList;
    }

    //Get the first and second level menu information through the map set
    private List<ItemCat> getTwoList(Map<Integer, List<ItemCat>> map) {
        List<ItemCat> oneList = map.get(0);
        //To obtain secondary information, you should first traverse the primary collection
        for (ItemCat oneItemCat : oneList){
            int oneId = oneItemCat.getId();
            //Get the secondary set according to the primary Id
            List<ItemCat> twoList = map.get(oneId);
            oneItemCat.setChildren(twoList);
        }
        return oneList;
    }


    /**
     * Step 1. Query the first level menu list
     * @param level
     * @return
     */
   /* @Override
    public List<ItemCat> findItemCatList(Integer level) {
        long startTime = System.currentTimeMillis();
        //1.Query level 1 menu
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("parent_id",0);
        List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
        //2.Query Level 2 menu level 2 data is the sub level of level 1 data encapsulated in level 1 data
        for(ItemCat oneItemCat : oneList){
            int oneId = oneItemCat.getId(); //Primary object ID
            //Empty original condition must have
            queryWrapper.clear();
            queryWrapper.eq("parent_id",oneId);
            List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);
            for(ItemCat twoItemCat : twoList){
                //Get secondary classification ID
                int twoId = twoItemCat.getId();
                //Query Level 3 list information
                queryWrapper.clear();
                queryWrapper.eq("parent_id",twoId);
                List<ItemCat> threeList = itemCatMapper.selectList(queryWrapper);
                //Encapsulate a tertiary list into a secondary object
                twoItemCat.setChildren(threeList);
            }
            //Encapsulate secondary data into primary objects
            oneItemCat.setChildren(twoList);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Time consuming: "+ (endTime - startTime)+"ms ");
        return oneList;
    }*/
}

2. Implementation of adding commodity classification

2.1 page JS analysis

  1. Page JS analysis
 		//Define new objects for commodity classification
        itemCatForm: {
          name: '', //Define commodity classification name
          parentId: 0, //Default parent ID=0
          level: 1 //The default is the first level menu
        },
		
		async addItemCatForm() {
        //Verify the whole form first
        this.$refs.itemCatFormRef.validate(async validate => {
          if (!validate) return
          const {
            data: result
          } = await this.$http.post("/itemCat/saveItemCat", this.itemCatForm)
          if (result.status !== 200) return this.$message.error("Failed to add commodity classification")
          this.$message.success("Successfully added commodity classification!!!")
          //If the addition is successful, the classification list information will be refreshed
          this.findItemCatList();
          this.addItemCatDialogVisible = false
        })
      },


2.2 new interface document for commodity classification

  • Request path: / itemCat/saveItemCat
  • Request type: post
  • Request parameter: form data
Parameter nameParameter descriptionremarks
nameCommodity classification nameCannot be null
parentIdUser parent IDCannot be null
levelClassification level1 2 3 commodity classification level
  • Return value: SysResult object
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverCan be null

2.3 editing ItemCatController

/**
     * Business requirements: add a new commodity classification
     * URL:  /itemCat/saveItemCat
     * Type: post
     * Parameters: {name ":" AAAAA "," parentid ": 0," level ": 1} JSON string
     * Return value: SysResult object
     */
    @PostMapping("/saveItemCat")
    public SysResult saveItem(@RequestBody ItemCat itemCat){

        itemCatService.saveItem(itemCat);
        return SysResult.success();
    }

2.4 edit ItemCatService

	@Override
    @Transactional  //Transaction control
    public void saveItem(ItemCat itemCat) {
        Date date = new Date();
        itemCat.setStatus(true).setCreated(date).setUpdated(date);//start-up
        itemCatMapper.insert(itemCat);
    }

3. Delete commodity classification

3.1 deleting a business interface

  • Request path: / itemCat/deleteItemCat
  • Request type: delete
  • Business description: when the deleted node is the parent, it should delete itself and all child nodes
  • Request parameters:
Parameter nameParameter descriptionremarks
IDUser ID numberCannot be null
levelCommodity classification level: Level I, level II and level III
  • Return value result SysResult object
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverCan be null

3.2 front end page JS

1. page JS
<el-button type="danger" icon="el-icon-delete" @click="deleteItemCatBtn(scope.row)">delete</el-button>


2. launch Ajax request
//Pass classification id
        const {data: result} = await this.$http.delete("/itemCat/deleteItemCat",{params:{id:itemCat.id,level:itemCat.level}})
          if(result.status !== 200) return this.$message.error("Failed to delete commodity classification")
          this.$message.success("Data deleted successfully")
          //After the deletion is successful, refresh the page data
          this.findItemCatList()          

3.3 editing ItemCatController

 /**
     * Finish deleting the commodity classification
     * 1. Edit URL: /itemCat/deleteItemCat
     * 2. Parameter: id/level
     * 3. Return value: SysResult()
     */
    @DeleteMapping("/deleteItemCat")
    public SysResult deleteItemCat(Integer id,Integer level){

        itemCatService.deleteItemCat(id,level);
        return SysResult.success();
    }

3.4 editing ItemCatService

//Delete commodity classification data
    @Override
    public void deleteItemCat(Integer id, Integer level) {
        //Judge whether it is a level 3 menu
        if(level == 3){
            itemCatMapper.deleteById(id);
        }

        if(level == 2){
            //If it is level 2, you should first obtain level 3 data, then delete it, and then delete yourself
            //delete from item_cat where parent_id=#{id} or id = #{id}
            QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("parent_id",id)
                        .or()
                        .eq("id",id);
            itemCatMapper.delete(queryWrapper);
        }

        /**
         * How to delete the first level menu?
         *  1.Get secondary ID
         *  Ultimate sql: delete from item_cat where parent_id in (twoIds)
         *          or  id in (twoIds)
         *          or  id = #{id}
         */
        if(level == 1){
            QueryWrapper<ItemCat> queryWrapper = new QueryWrapper();
            queryWrapper.eq("parent_id",id);
            List twoIds = itemCatMapper.selectObjs(queryWrapper);
            //wipe data 
            queryWrapper.clear();
            //Rule: if the level 2 menu has a value, level 2 and level 3 will be deleted
            queryWrapper.in(twoIds.size()>0,"parent_id",twoIds)
                        .or()
                        .in(twoIds.size()>0,"id",twoIds)
                        .or()
                        .eq("id",id);
            itemCatMapper.delete(queryWrapper);
        }
    }

4. Modify commodity classification

4.1 status modification

4.1.1 page JS analysis

1. page JS function
updateStatus(scope.row)

2. page JS
 	  //Modify status information according to ID
      async updateStatus(itemCat) {
        const {
          data: result
        } = await this.$http.put(`/itemCat/status/${itemCat.id}/${itemCat.status}`)
        if (result.status !== 200) return this.$message.error("Failed to modify status")
        this.$message.success("Status modified successfully")
      },

4.1.2 business interface documents

  • Request path: / itemCat/status/{id}/{status}
    • Request type: put
    • Request parameters:
Parameter nameParameter descriptionremarks
IDUser ID numberCannot be null
statusUser status informationCannot be null
  • Return value: SysResult object
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverCan be null

4.1.3 editing ItemCatController

/**
     * Modify commodity classification status
     * URL: /itemCat/status/{id}/{status}
     * Request type: PUT/POST
     * Request parameter: id/status
     * Return value: SysResult object
     */
    @PutMapping("/status/{id}/{status}")
    public  SysResult updateStatus(ItemCat itemCat){

        itemCatService.updateStatus(itemCat);
        return SysResult.success();
    }

4.1.4 edit ItemCatService

	@Override
    @Transactional
    public void updateStatus(ItemCat itemCat) {//id/status
        itemCat.setUpdated(new Date());
        itemCatMapper.updateById(itemCat);
    }

4.2 modifying commodity classification

4.2.1 page JS analysis

	1.Specifies the button to modify
	<el-button type="success" icon="el-icon-edit" @click="updateItemCatBtn(scope.row)">edit</el-button>
	
	2. Echo of data
	//Due to the hierarchical relationship, all modifications can only modify the name
      updateItemCatBtn(itemCat) {
        this.updateItemCatForm = itemCat
        this.updateItemCatDialogVisible = true
      },

	3. Modify page JS
	<el-dialog title="Modify commodity classification" :visible.sync="updateItemCatDialogVisible" width="50%">
      <!-- Define classification form -->
      <el-form :model="updateItemCatForm" :rules="rules" ref="upDateItemCatForm" label-width="100px">
        <el-form-item label="Classification name:" prop="name">
          <el-input v-model="updateItemCatForm.name"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="updateItemCatDialogVisible = false">Cancel</el-button>
        <el-button type="primary" @click="updateItemCat">determine</el-button>
      </span>
    </el-dialog>
     
     4. Modify button JS
       async updateItemCat() {
        //Modify commodity classification information
        const {data: result} =
          await this.$http.put('/itemCat/updateItemCat', this.updateItemCatForm)
        if (result.status !== 200) return this.$message.error("Failed to update product classification")
        this.$message.success("Update commodity classification succeeded")
        this.findItemCatList();
        this.updateItemCatDialogVisible = false;
      },

4.2.2 page interface document

  • Request path: / itemCat/updateItemCat
  • Request type: put
  • Request parameter: form data ItemCat object
  • Return value: SysResult object
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverCan be null

Data analysis:

4.2.3 editing ItemCatController

/**
     * Modify commodity classification name
     * URL: /itemCat/updateItemCat
     * Parameter: JSON string of the whole form
     * Return value: SysResult object
     */
    @PutMapping("/updateItemCat")
    public SysResult updateItemCat(@RequestBody ItemCat itemCat){

        itemCatService.updateItemCat(itemCat);
        return SysResult.success();
    }

4.2.4 edit ItemCatService

 //Since only the name of the page is modified, sql only modifies name/updated
    @Override
    @Transactional
    public void updateItemCat(ItemCat itemCat) {
        //The user only modifies name,updated by id
        ItemCat temp = new ItemCat();
        temp.setId(itemCat.getId())
                .setName(itemCat.getName())
                .setUpdated(new Date());
        itemCatMapper.updateById(temp);
    }

4.3 debug breakpoint debugging

5. Business realization of commodity module

5.1 product page Jump

  1. Edit the routing file of index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../components/Login.vue'
import ElementUI from '../components/ElementUI.vue'
import Home from '../components/Home.vue'
import User from '../components/user/user.vue'
import ItemCat from '../components/items/ItemCat.vue'
import Item from '../components/items/Item.vue'
//Using routing mechanism
Vue.use(VueRouter)
const routes = [
  {path: '/', redirect: '/login'},
  {path: '/login', component: Login},
  {path: '/elementUI', component: ElementUI},
  {path: '/home', component: Home, children: [
     {path: '/user', component: User},
     {path: '/itemCat', component: ItemCat},
     {path: '/item', component: Item}
  ]}
]

  1. Page effect

5.2 automatic data filling

5.2.1 business analysis

Note: if you need to add the creation time / modification time every time you add / update, it is cumbersome. Can you automatically fill in the data through the framework

5.2.2 add auto fill annotation

//pojo base class, completing 2 tasks and 2 dates, realizing serialization
@Data
@Accessors(chain=true)
public class BasePojo implements Serializable{
	@TableField(fill = FieldFill.INSERT) 		//Automatic filling is realized when adding an operation
	private Date created;	//Indicates that assignment is required during warehousing
	@TableField(fill = FieldFill.INSERT_UPDATE) //Automatically fill in when adding / modifying
	private Date updated;	//Indicates the assignment during warehousing / updating
}

5.2.3 configure auto fill class

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    //Framework usage Description: MP automatically completes data injection according to the implementation class. MP framework calls automatically
    //metaObject: Specifies the default rule
    @Override
    public void insertFill(MetaObject metaObject) {
        Date date = new Date();
        this.setFieldValByName("created", date, metaObject);
        this.setFieldValByName("updated", date, metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {

        this.setFieldValByName("updated", new Date(), metaObject);
    }
}

5.3 building commodity level codes

5.3.1 item table design

5.3.2 edit Item POJO

/**
 * @author Liu Yujiang
 * Time: April 7, 2021
 */
@Data
@Accessors(chain = true)
@TableName("item")
public class Item extends BasePojo{
    @TableId(type= IdType.AUTO) 
    private Integer id;         //Item Id No
    private String title;       //Item title information
    private String sellPoint;   //Selling point information
    private Integer price;      //commodity price
    private Integer num;        //Quantity of goods
    private String images;       //Product picture
    private Integer itemCatId;  //Commodity classification ID number
    private Boolean status;     //Status information 0 off shelf 1 on shelf
}

5.3.3 edit hierarchical code structure

5.4 complete the display of commodity list

5.4.1 page analysis

//1. Life cycle function
 created() {
      //1. Obtain commodity list data
      this.getItemList()
    },

//2. Call this.getItemList()
      async getItemList() {
        const {data: result} =
            await this.$http.get("/item/getItemList", {
          params: this.queryItemInfo
        })
        if (result.status !== 200) return this.$message.error("Commodity list query failed")
        this.itemList = result.data.rows
        this.total = result.data.total
      },


5.4.2 interface document description

  • Request path: / item / getitemlist? Query = & pagenum = 1 & PageSize = 10
  • Request type: get
  • Request parameters: receive using pageResult object
Parameter nameParameter descriptionremarks
queryData queried by userCan be null
pageNumNumber of pages for paged queriesA value must be assigned and cannot be null
pageSizeNumber of paged queriesA value must be assigned and cannot be null
  • Return value result:
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverItem paging object

5.4.3 editing ItemController

@RestController
@CrossOrigin
@RequestMapping("/item")
public class ItemController {

    @Autowired
    private ItemService itemService;

    /**
     * Business: realize pagination query of goods
     * URL: /item/getItemList?query=&pageNum=1&pageSize=10
     * Parameters: query = & pagenum = 1 & PageSize = 10
     * Return value: SysResult(PageResult)
     */
    @GetMapping("/getItemList")
    public SysResult getItemList(PageResult pageResult){//3
        //3 + 2 (total records, paging results)
        pageResult  = itemService.getItemList(pageResult);
        return SysResult.success(pageResult);//5
    }
}

5.4.4 edit ItemService

@Service
public class ItemServiceImpl implements ItemService{

    @Autowired
    private ItemMapper itemMapper;

    /**
     *  Requirement: 3 + 2 (total records, paging results)
     *  About selectpage (parameter description)
     *   Parameter 1: paging object provided by page mp
     *   Parameter 2: condition constructor
     * @param pageResult
     * @return
     */
    @Override
    public PageResult getItemList(PageResult pageResult) {
        //1. Build paging object parameter 1: page number parameter 2: how many pages
        Page<Item> page = new Page<>(pageResult.getPageNum(),pageResult.getPageSize());
        //2. Prepare the condition constructor to build the fuzzy query
        QueryWrapper queryWrapper = new QueryWrapper();
        String query = pageResult.getQuery();
        boolean flag = StringUtils.hasLength(query);
        queryWrapper.like(flag,"title",query);

        //3. Realize the automatic encapsulation of paging data according to MP query
        page = itemMapper.selectPage(page,queryWrapper);

        //4. Get the data and return the paging object
        long total = page.getTotal();
        //Get paging results
        List<Item> rows = page.getRecords();
        return pageResult.setTotal(total).setRows(rows);
    }
}

5.4.5 editing paging configuration class

@Configuration  //This is the configuration class
public class MybatisConfig {

    //The database type needs to be specified through the configuration file
    // the latest version
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MARIADB));
        return interceptor;
    }
}

5.4.6 page effect display

5.5 modification of commodity status

5.5.1 page JS analysis

		<template slot-scope="scope">
            <el-switch v-model="scope.row.status" active-color="#13ce66" inactive-color="#ff4949"
              @change="updateStatus(scope.row)"></el-switch>
        </template>
		
		async updateStatus(item) {
        const { data: result} =
        await this.$http.put("/item/updateItemStatus", {
          id: item.id,
          status: item.status
        })
        if (result.status !== 200) return this.$message.error("Update status failed")
        this.$message.success("Update status succeeded")
      },

5.5.2 business interface documents

  • Request path: / item/updateItemStatus
  • Request type: put
  • Request parameters: receive using object
Parameter nameParameter descriptionremarks
idCommodity idCannot be null
statusstatus information Cannot be null
  • Return value result:
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverCan be null

5.5.3 editing ItemController

 /**
     * Modify the status information of goods
     * URL: /item/updateItemStatus
     * Parameters: JSON string {id:xx,status:xx}
     * Return value: SysResult object
     */
    @PutMapping("/updateItemStatus")
    public SysResult updateItemStatus(@RequestBody Item item){

        itemService.updateItemStatus(item);
        return SysResult.success();
    }

5.5.4 edit ItemService

 @Override
    @Transactional //Control transactions
    public void updateItemStatus(Item item) {

        itemMapper.updateById(item);
    }

5.6 deleting goods

5.6.1 page analysis

//Delete data by id
          const {data: result} = await this.$http.delete("/item/deleteItemById", {
            params: {
              id: item.id
            }
          })
          if (result.status !== 200) return this.$message.error("Failed to delete product")
          this.$message.success("Product deleted successfully")
          //Retrieve product list information
          this.getItemList()

5.6.2 business interface documents

  • Request path: / item/deleteItemById
  • Request type: delete
  • Request parameters:
Parameter nameParameter descriptionremarks
IDItem ID numberCannot be null
  • Return value result:
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverCan be null

5.6.3 editing ItemController

 /**
     * Business requirement: delete data according to Id
     * URL: /item/deleteItemById
     * Parameter: id
     * Return value: SysResult object
     */
    @DeleteMapping("/deleteItemById")
    public SysResult deleteItemById(Integer id){

        itemService.deleteItemById(id);
        return SysResult.success();
    }

5.6.4 edit ItemService

 	@Override
    @Transactional
    public void deleteItemById(Integer id) {
    
        itemMapper.deleteById(id);
    }

5.7 adding goods

5.7.1 page Jump

const routes = [
  {path: '/', redirect: '/login'},
  {path: '/login', component: Login},
  {path: '/elementUI', component: ElementUI},
  {path: '/home', component: Home, children: [
     {path: '/user', component: User},
     {path: '/itemCat', component: ItemCat},
     {path: '/item', component: Item},
     {path: '/item/addItem', component: AddItem}
  ]}
]

Page effect:

5.7.2 add page JS

Table structure description:

  1. Save the basic information of goods to the item table
  2. Save item details to item_desc table
 /* Add item button */
      async addItemBtn(){
        //console.log(this.addItemForm)

        //1. Complete form verification
        this.$refs.addItemFormRef.validate( valid => {
          if(!valid) return this.$message.error("Please enter a required item")
        })

        //2. Complete the packaging of commodity parameters
        //2.0 expand commodity prices by 100 times
        this.addItemForm.price = this.addItemForm.price * 100
        //2.1 convert the data of commodity picture into string
        this.addItemForm.images = this.addItemForm.images.join(",")

        //2.5 realize commodity data submission and wrap two small objects with one large object
        let submitAddItem = {
          item : this.addItemForm,
          itemDesc: this.itemDesc
        }
        //console.log(submitAddItem)
        let {data: result} = await this.$http.post("/item/saveItem",submitAddItem)
        if(result.status !== 200) return this.$message.error("Failed to add product")
        this.$message.success("Product added successfully")

        //2.5 after adding, redirect the data to the product display page
        this.$router.push("/item")
      }

5.7.3 service interface description

  • Request path: http://localhost:8091/item/saveItem
    
  • Request type: post
  • Front end transfer parameter analysis
	{
		item: {
			images: "/2021/05/20/da0c1d4781c1499399f090da8b60f359.jpg,/2021/05/20/2ac1c34776a7465887eb019655354c3c.jpg"
			itemCatId: 560
			num: "100"
			price: 718800
			sellPoint: "[Huawei official direct supply,Zhigao 12 interest free 0 down payment,[original] send Huawei original wireless charger+Sports Bluetooth headset+Bluetooth Speaker +Three in one multifunctional data line+Toughened film, etc!"
			title: "Huawei P40 Pro 5G Mobile phone [12 interest free optional gifts] all Netcom smart phone"
		},
		itemDesc: {
				itemDesc: "<ul><li>Brand:&nbsp;<a href=https://list.jd.com/list.html".......      "
		}
	}

  • Request parameters: received using ItemVO object
Parameter nameParameter descriptionremarks
itemItemCommodity basic information object encapsulation
itemDescItemDescProduct details
itemParamItemParamCommodity parameter information
  • ItemVO parameter details:
  • Item object
Parameter nameParameter typeParameter descriptionremarks
titleStringItem title informationCannot be null
sellPointStringCommodity selling point information
priceIntegerCommodity price informationCannot be null. You need to expand the data 100 times
numIntegerCommodity quantity informationCannot be null
imagesStringProduct picture address informationCannot be null
itemCatIdIntegerProduct parent category IDCannot be null
statusBooleanProduct status informationCannot be null
  • itemDesc object

    In order to reduce the coupling of commodity submission code,Large field information details,use ItemDesc Object
    
Parameter nameParameter typeParameter descriptionremarks
idIntegerItem Id informationBecause Item and ItemDesc are one-to-one, they need to rely on the Id value of the Item object
itemDescStringProduct detailsIt contains a large number of html statements
  • Return value result:
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverCan be null

5.7.4 editing ItemController

 /**
     * Finish adding goods
     * 1.URL Address http://localhost:8091/item/saveItem
     * 2.Parameter post itemvo JSON string
     * 3.Return value SysResult object
     */
    @PostMapping("/saveItem")
    public SysResult saveItem(@RequestBody ItemVO itemVO){

        itemService.saveItem(itemVO);
        return SysResult.success();
    }

5.7.5 edit ItemService

 @Override
    @Transactional
    public void saveItem(ItemVO itemVO) {
        Item item = itemVO.getItem();
        //Setting state
        item.setStatus(true);
        itemMapper.insert(item);
    }

6 product file upload

6.1 details of goods warehousing

6.1.1 rich text editor

Note: rich text can achieve the "WYSIWYG" effect on the page

6.1.2 introduction steps

  1. Introducing js
/* Import rich text editor */
import VueQuillEditor from 'vue-quill-editor'

/* Import the style corresponding to the rich text editor */
import 'quill/dist/quill.core.css' // import styles
import 'quill/dist/quill.snow.css' // for snow theme
import 'quill/dist/quill.bubble.css' // for bubble theme

/* Register the rich text editor as a globally available component */
Vue.use(VueQuillEditor)

  1. Using the rich text editor
 <!-- Define rich text editor-->
 <quill-editor ref="myQuillEditor" v-model="itemDesc.itemDesc">
 </quill-editor>

6.1.3 description of ItemDesc

Note: since Item and ItemDesc are typical one-to-one, item.id = itemDesc.id is required

@Data
@Accessors(chain = true)
@TableName("item_desc")
public class ItemDesc extends BasePojo{
    @TableId
    private Integer id;
    private String itemDesc;
}

6.1.4 edit ItemService

 /**
     * Problem: id is the primary key self increment. There is a primary key only after receipt, so
     *      The primary key should be echoed dynamically
     * 1.Mybatis Dynamic echo
     *      <insert id="xxxx" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
     *         insertinto xxxx
     *     </insert>
     * 2.MP It is an enhanced version of mybatis. So it can realize automatic primary key echo!!!
     * @param itemVO
     */
    @Override
    @Transactional
    public void saveItem(ItemVO itemVO) {
        Item item = itemVO.getItem();
        //Setting state
        item.setStatus(true);
        itemMapper.insert(item);
        //Get product details
        ItemDesc itemDesc = itemVO.getItemDesc();
        itemDesc.setId(item.getId());
        itemDescMapper.insert(itemDesc);
    }

6.1.5

Description: to store large fields, modify the database type

6.2 upload commodity pictures

6.2.1 edit page

//1. Define page html
<!-- Dialog box for defining product modification -->
    <!-- Dialog box for defining product modification -->
    <el-dialog title="Commodity modification" :visible.sync="updateDialogVisible" width="60%">
      <!-- Form ready for modification-->
      <el-form :model="updateItem" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
        <el-form-item label="Title Information" prop="title">
          <el-input v-model="updateItem.title"></el-input>
        </el-form-item>
        <el-form-item label="Selling point information" prop="sellPoint">
          <el-input v-model="updateItem.sellPoint"></el-input>
        </el-form-item>
        <el-form-item label="price information " prop="price">
          <el-input v-model="updateItem.price"></el-input>
        </el-form-item>
        <el-form-item label="Quantity information" prop="num">
          <el-input v-model="updateItem.num"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="updateDialogVisible = false">Cancel</el-button>
        <el-button type="primary" @click="dialogVisible = false">determine</el-button>
      </span>
    </el-dialog>
	
	//2. Define page JS
	updateDialogVisible: false,
        updateItem: {},
        //Prepare a validation rule
        rules: {
          title: [
                  { required: true, message: 'Please enter product title information', trigger: 'blur' },
                  { min: 3, max: 50, message: 'The length is between 3 and 50 characters', trigger: 'blur' }
                ],
          sellPoint: [
                  { required: true, message: 'Please enter the selling point information', trigger: 'blur' },
                  { min: 3, max: 50, message: 'The length is between 3 and 50 characters', trigger: 'blur' }
                ],
          price: [
                  { required: true, message: 'Please enter commodity price information', trigger: 'blur' },
                  { min: 3, max: 50, message: 'The length is between 3 and 50 characters', trigger: 'blur' }
                ],
          num: [
                  { required: true, message: 'Please enter product quantity information', trigger: 'blur' },
                  { min: 3, max: 50, message: 'The length is between 3 and 50 characters', trigger: 'blur' }
                ],
        }

	  //Define JS button
	  updateItemBtn(item){
        	console.log("Extended case,You only need to modify the title/selling point/Price/quantity")
        	this.updateDialogVisible = true
        	this.updateItem = item
        	this.updateItem.price = (this.updateItem.price / 100).toFixed(2)
      }

6.2.2 official website description

//1. Official website picture JS description
  <!-- Picture upload JS
        1. action: Represents the address of the picture upload url
        2. file-list: Collection of picture list data[{name:"xx",url:"xxx"},{}]
        3. Hook function: Triggered when certain conditions are met.
        4. on-preview Triggered when the information of the uploaded list is clicked
        5. on-remove  Triggered when a picture is removed from the list
      -->
      <el-upload
        class="upload-demo"
        action="https://jsonplaceholder.typicode.com/posts/"
        :on-preview="handlePreview"
        :on-remove="handleRemove"
        :file-list="fileList"
        list-type="picture">
        <el-button size="small" type="primary">Click upload</el-button>
        <div slot="tip" class="el-upload__tip">Upload only jpg/png Documents, and no more than 500 kb</div>
      </el-upload>
2. page JS Supplementary knowledge
   handlePreview(){
      console.log("Trigger view function!!!!")
    },
    handleRemove(){
      console.log("Triggered on removal!!!!")
    }

6.2.3 picture upload project description

<!--
              one.File upload component description
                1.action: Upload picture address http://localhost:8091/xxx/xxx
                2.on-preview Triggered when a picture is clicked
                3.on-remove  Triggered when a picture is removed
                4.on-success Triggered when the picture is uploaded successfully
                5.multiple   It can support uploading multiple pictures
                6.drag       Allow drag
              two.Request type:    Generally, when uploading byte information,be the first choice post request
              three.Upload file key  explain: When uploading files key=file.
              				 When receiving data at the back end file receive.
            -->
            <el-upload class="upload-demo" :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove"
              :on-success="handleSuccess" list-type="picture" multiple drag>
              <el-button size="small" type="primary">Click upload</el-button>
              <div slot="tip" class="el-upload__tip">Upload only jpg/png Documents, and no more than 500 kb</div>
</el-upload>

//Define file upload path address
uploadUrl: "http://localhost:8091/file/upload",

6.2.4 picture upload interface document description

  • Request path: http://localhost:8091/file/upload
  • Request type: post
  • Request parameters:
Parameter nameParameter descriptionremarks
fileParameter name of file uploadfile carries binary information
  • Return value result:
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverReturn ImageVO object
  • ImageVO object description
Parameter nameParameter typeParameter descriptionremarks
virtualPathStringThe actual path of the picture does not contain disk informationFor example, 2021/11/11/a.jpg does not need to write the disk address
urlPathStringPicture url access addresshttp://image.jt.com/2021/11/11/a.jpg Domain name address needs to be specified
fileNameStringFile name after file uploadUUID.type

6.2.5 editing ImageVO

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ImageVO {

    private String virtualPath; //Picture virtual path dynamic path
    private String urlPath;  //URL address of picture echo
    private String fileName; //File name after file upload
}

6.2.6 edit ItemController

@RestController
@CrossOrigin
@RequestMapping("/file")
public class FileController {

    /**
     * Business description: upload pictures
     * URL: http://localhost:8091/file/upload
     * Type: post
     * Parameter: file byte information
     * Return value: SysResult.success()
     * Extension:
     *      Normally:
     *          Generally, the front end sends byte information to the back end server. Data transmission is realized from outside to inside
     *      Adopt input stream information. InputStream file
     *          Disadvantages of using byte stream: 1. It must be closed manually; 2. The code operation is cumbersome
     *          The implementation of the underlying code
     *       SpringMVC The advanced API multipartfile specifically handles IO stream operations
     *  File upload steps:
     *        1.Get file name
     *        2.Directory for preparing file upload
     *        3.Judge whether the directory exists: upload without Directory: create directory
     *        4.Use tool API method to upload files
     *  Note: MultipartFile supports 1M data by default
     */
     @PostMapping("/upload")
     public SysResult upload(MultipartFile file) throws IOException {
        //1. Get file name
         String fileName = file.getOriginalFilename();
         //2. Prepare the disk address
         String dirPath = "E:/project3/images/";
         //3. Encapsulate the File directory as a File object
         File dirFile = new File(dirPath);
         //4. Judge whether the object exists
         if(!dirFile.exists()){
            //If the file directory does not exist, create a directory
             dirFile.mkdirs(); //Indicates multi-level directory upload
         }
         //5. Full path of package file E:xxx/xxx/a.jpg
         String path = dirPath + fileName;
         File allFile = new File(path);
         //6. Realize file upload and output the IO stream according to the specified object format
         file.transferTo(allFile);
         return SysResult.success();
     }
}

6.3 regular expressions (review)

6.3.1 regular expression description

Regular Expression, also known as Regular Expression. (English: Regular Expression, often abbreviated as regex, regexp or RE in code), a concept of computer science. Regular expressions are often used to retrieve and replace text that conforms to a pattern (rule).
Summary: regular expression is a special format string. It verifies the of text information

6.3.2 matching uncertainty times

6.3.3 fixed matching times

6.3.4 matching value range

6.3.5 group matching

6.3.6 regular case exercises

  1. The matching phone number is required to start with 1 in 11 digits
    Regular expression: 1 [3-9] [0-9] {9}

  2. Require matching mailbox xxxx@qq.com
    Regular expression:

^[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+$

6.4 file upload implementation

6.4.1 editing FileController

@RestController
@CrossOrigin
@RequestMapping("/file")
public class FileController {

    @Autowired
    private FileService fileService;

    /**
     * Business description: upload pictures
     * URL: http://localhost:8091/file/upload
     * Type: post
     * Parameter: multipartfile byte information
     * Return value: SysResult.success()
     * Problem thinking:
     *      1.Complete picture type verification jpg|png|gif
     *      2.Prevent malicious programs a.exe.jpg
     *      3.Store pictures in different directories
     *             3.1.According to the theory of classification, we can, but we have to allocate more
     *             3.2.By time. yyyy/MM/dd
     *      4.Custom file name. Use UUID as picture name
     */
    @PostMapping("/upload")
    public SysResult upload(MultipartFile file) throws IOException {

        ImageVO imageVO = fileService.upload(file);
        if(imageVO == null){
            return SysResult.fail();
        }
        return SysResult.success(imageVO);
    }


    /**
     * Business description: upload pictures
     * URL: http://localhost:8091/file/upload
     * Type: post
     * Parameter: file byte information
     * Return value: SysResult.success()
     * Extension:
     *      Normally:
     *          Generally, the front end sends byte information to the back end server. Data transmission is realized from outside to inside
     *      Adopt input stream information. InputStream file
     *          Disadvantages of using byte stream: 1. It must be closed manually; 2. The code operation is cumbersome
     *          The implementation of the underlying code
     *       SpringMVC The advanced API multipartfile specifically handles IO stream operations
     *  File upload steps:
     *        1.Get file name
     *        2.Directory for preparing file upload
     *        3.Judge whether the directory exists: upload without Directory: create directory
     *        4.Use tool API method to upload files
     *  Note: MultipartFile supports 1M data by default
     */
     /*@PostMapping("/upload")
     public SysResult upload(MultipartFile file) throws IOException {
         //1.Get file name
         String fileName = file.getOriginalFilename();
         //2.Prepare disk address
         String dirPath = "E:/project3/images/";
         //3.Encapsulate the File directory as a File object
         File dirFile = new File(dirPath);
         //4.Judge whether the object exists
         if(!dirFile.exists()){
            //If the file directory does not exist, create a directory
             dirFile.mkdirs(); //Indicates multi-level directory upload
         }
         //5.Full path of package file E:xxx/xxx/a.jpg
         String path = dirPath + fileName;
         File allFile = new File(path);
         //6.Realize file upload and output the IO stream according to the specified object format
         file.transferTo(allFile);
         return SysResult.success();
     }*/
}

6.4.2 editing FileService

package com.jt.service;

import com.jt.vo.ImageVO;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.FileNameMap;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService{

    private String localDirPath = "E:/project3/images";

    //1. Verify that the picture type is xxx.jpg and that the suffix is jpg
    @Override
    public ImageVO upload(MultipartFile file) {

        //1.1 get the file name abc.jpg
        String fileName = file.getOriginalFilename();
        //1.2 convert all to lowercase letters
        fileName = fileName.toLowerCase();
        //1.3 regular check whether it is a picture type
        if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
            //Picture type mismatch program should terminate
            return null;
        }

        //2. Check whether it is a malicious program. How to judge is the height and width of a picture
        //2.1 processing through picture objects
        try {
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int height = bufferedImage.getHeight();
            int width = bufferedImage.getWidth();
            if(height == 0 || width == 0){
                return null;
            }
            //3. Store pictures in directory yyyy/MM/dd
            String dateDir = new SimpleDateFormat("/yyyy/MM/dd/")
                                .format(new Date());
            String dateDirPath = localDirPath + dateDir;
            File dirFile = new File(dateDirPath);
            if(!dirFile.exists()){
                dirFile.mkdirs();
            }

            //4. Prevent duplicate file names from dynamically generating UUID types
            //4.1 dynamically generate UUID
            String uuid = UUID.randomUUID().toString()
                              .replace("-","");
            //4.2 get picture type abc.jpg. Jpg
            String fileType = fileName.substring(fileName.lastIndexOf("."));
            // uuid.jpg
            String newFileName = uuid + fileType;

            //5. Realize file upload 1. Prepare the full file path 2. Encapsulate the object to realize file upload
            String path = dateDirPath + newFileName;
            file.transferTo(new File(path));

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        return null;
    }
}

6.5 file deletion

6.5.1 file deletion JS

6.5.2 file deletion service interface

  • Request path: http://localhost:8091/file/deleteFile
  • Request type: delete
  • Request parameters:
Parameter nameParameter descriptionremarks
virtualPathVirtual path for file uploadWhen deleting, you need to delete it together with the disk path
  • Return value result:
Parameter nameParameter descriptionremarks
statusstatus information 200 indicates that the server request is successful, and 201 indicates that the server is abnormal
msgPrompt information returned by the serverCan be null
dataBusiness data returned by the serverCan be null

6.5.3 editing FileController

 /**
     * Business description: file deletion
     * URL Address: http://localhost:8091/file/deleteFile
     * Request type: delete
     * Parameter: virtualPath virtual path
     * Return value: SysResult object
     */
    @DeleteMapping("/deleteFile")
    public SysResult deleteFile(String virtualPath){

        fileService.deleteFile(virtualPath);
        return SysResult.success();
    }

6.5.4 editing FileService

@Override
    public void deleteFile(String virtualPath) {
        String filePath = localDirPath + virtualPath;
        File file = new File(filePath);
        if(file.exists()){ //If the file exists, delete the data
            file.delete();
        }
    }

6.6 picture path encapsulation

6.6.1 path analysis

  1. Picture network address: https://img14.360buyimg.com/n0/jfs/t2/ac4a3f32ea776da3.jpg
    Protocol: / / Domain Name: 80 / virtual address
  2. Picture address encapsulation: http://image.jt.com:80/2021/11/11/uuid.jpg.

6.6.2 page URL address encapsulation

package com.jt.service;

import com.jt.vo.ImageVO;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.FileNameMap;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class FileServiceImpl implements FileService{

    private String localDirPath = "E:/project3/images";
    private String preUrl = "http://image.jt.com";

    //1. Verify that the picture type is xxx.jpg and that the suffix is jpg
    @Override
    public ImageVO upload(MultipartFile file) {

        //1.1 get the file name abc.jpg
        String fileName = file.getOriginalFilename();
        //1.2 convert all to lowercase letters
        fileName = fileName.toLowerCase();
        //1.3 regular check whether it is a picture type
        if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
            //Picture type mismatch program should terminate
            return null;
        }

        //2. Check whether it is a malicious program. How to judge is the height and width of a picture
        //2.1 processing through picture objects
        try {
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int height = bufferedImage.getHeight();
            int width = bufferedImage.getWidth();
            if(height == 0 || width == 0){
                return null;
            }
            //3. Store pictures in directory yyyy/MM/dd
            String dateDir = new SimpleDateFormat("/yyyy/MM/dd/")
                                .format(new Date());
            String dateDirPath = localDirPath + dateDir;
            File dirFile = new File(dateDirPath);
            if(!dirFile.exists()){
                dirFile.mkdirs();
            }

            //4. Prevent duplicate file names from dynamically generating UUID types
            //4.1 dynamically generate UUID
            String uuid = UUID.randomUUID().toString()
                              .replace("-","");
            //4.2 get picture type abc.jpg. Jpg
            String fileType = fileName.substring(fileName.lastIndexOf("."));
            // uuid.jpg
            String newFileName = uuid + fileType;

            //5. Realize file upload 1. Prepare the full file path 2. Encapsulate the object to realize file upload
            String path = dateDirPath + newFileName;
            file.transferTo(new File(path));

            //6. Realize the return of ImageVO data
            //6.1 prepare virtual path / 2021/11/11/uuid.jpg
            String virtualPath = dateDir + newFileName;
            //6.2 prepare URL address, domain name prefix + virtual path
            String url =  preUrl + virtualPath;
            System.out.println(url);
            return new ImageVO(virtualPath,url,newFileName);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void deleteFile(String virtualPath) {
        String filePath = localDirPath + virtualPath;
        File file = new File(filePath);
        if(file.exists()){ //If the file exists, delete the data
            file.delete();
        }
    }
}

6.7 dynamic attribute assignment

6.7.1 business requirements

Note: if the attribute is written to the java class, it will be inconvenient for later maintenance
Optimization: you can dynamically assign values through the @ value annotation

6.7.2 editing the properties configuration file

image.localDirPath=E:/project3/images
image.preUrl=http://image.jt.com

6.7.3 dynamic attribute assignment

Posted by sometimes on Sun, 05 Dec 2021 20:35:32 -0800