File 和 Item 块

FileController

package com.jt.controller;

import com.jt.service.FileService;
import com.jt.vo.ImageVO;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
@RestController
@RequestMapping("/file")
@CrossOrigin
public class FileController {
    @Autowired
    private FileService fileService;
    /**
     * URL: /file/upload
     * 类型: post
     * 参数: file=字节信息
     * 返回值: SysResult(ImageVO)
     * 知识点:
     *   SpringMVC针对与IO操作开发了MultipartFile
     *   底层实现就是常规IO流,简化了用户的操作过程.无需手动关流
     *   SpringMVC中默认支持最大1M
     * 步骤:
     *      1.获取文件名称
     *      2.准备文件路径
     *      3.准备文件上传的全路径
     *      4.实现文件上传操作
     */
    @PostMapping("/upload")
    public SysResult upload(MultipartFile file){
        ImageVO imageVO = fileService.upload(file);
        if (imageVO==null){
            return SysResult.fail();
        }
        return SysResult.success(imageVO);
    }

    @DeleteMapping("/deleteFile")
    public SysResult deleteFile(String virtualPath){
        fileService.deleteFile(virtualPath);
        return SysResult.success();
    }



    /*  整体目的是: 将用户从前端过来的文件,解析,指定服务器存储地址,上传到服务器磁盘里*/
    //                      继承输入流
    public SysResult upload1(MultipartFile file) throws IOException {
        //将文件上传到前端,前端传给服务器处理
        // 1.获取文件名称  a.jpg
        String fileName = file.getOriginalFilename();
        //2.准备文件目录,确保文件存在
        String dir = "D:/project3/images";
        File dirFile = new File(dir);//只为确保路径是否存在,保证正常存储
        if(!dirFile.exists()){//判断目录是否存在
            dirFile.mkdirs(); //创建多级目录
        }
        String path = dir + "/" + fileName;
        //将文件上传到服务器磁盘,访问时先去数据库找地址,
        // 根据地址访问服务器磁盘里的文件
        file.transferTo(new File(path));
        return SysResult.success();
    }


}

FileServiceImpl

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.text.SimpleDateFormat;
import java.util.Date;

@Service
public class FileServiceImpl implements FileService {

    //定义文件的根目录
    private String rootDir = "D:/project3/images";
    //定义图片服务器网址
    private String rootURl = "http://image.jt.com";

    /*
     * 思路:
     *  1.校验文件是否为图片  校验图片类型     正则表达式
     *  2.防止文件为恶意程序  木马.exe.jpg     用图片属性 长和宽,属性不可赋予是自动生成,如不是图片则没有
     *  3.分目录存储         按照时间维度划分
     *  4.防止文件重名       UUID
     *
     */
    @Override
    //MultipartFile类,主要是来实现以表单的形式进行文件上传功能,可获取文件的名字路径类型及转文件为输入流等
    public ImageVO upload(MultipartFile file) {
        /*1.获取图片名称,全部转化为小写*/
        String fileName = file.getOriginalFilename().toLowerCase();
        if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
        //java中\是转义,也是将特殊字符转普通字符,第一个\是java表示第二个\是普通的\,第二个\是正则表示后面的.是普通的.
            return null;
        }

       /* 2.通过校验宽度和高度判断是否为图片 bufferedImage图片包装对象*/
        try {
    //  BufferedImage可获取和操作图片基本属性 ,ImageIO可进行简单地图片IO操作,这里将file读入,生成BufferedImage对象
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            if(width == 0 || height == 0){
                return null;
            }

            /* 3.分目录存储*/

            String datePath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
            String FileDir = rootDir + datePath;
            File dirFile = new File(FileDir);
            if (!dirFile.exists()){ //不能用null
                dirFile.mkdirs();
            }

            /* 4.防止文件重名 */
            String UUID = java.util.UUID.randomUUID().toString();
            int index = fileName.lastIndexOf(".");
            String fileType = fileName.substring(index);
            fileName = UUID+fileType;

            /*  5.文件上传(存到服务器磁盘)*/
            String path = FileDir + fileName;
            file.transferTo(new File(path));

            /* 6.准备ImageVO数据返回 /2021/11/11/uuid.jpg*/
            //封装vo对象
            String virtualPath = datePath + fileName;
//            String urlPath = "https://img14.360buyimg.com/n1/s546x546_jfs/t1/171192/11/27659/163115/61b021c9E8fbcf225/ac484bab6fac460e.jpg";
            //按照要求封装图片网络地址
            //http://image.jt.com/2021/11/11/uuid.jpg
            String urlPath =  rootURl + virtualPath;//暂时不能打开,因为服务器网址还没开
                                                    //可以在网址换成全本地全地址,能在网页打开图片
            System.out.println(urlPath);
            //virtualPath虚拟地址就是动态地址,url网络地址:域名+虚拟地址
            ImageVO imageVO = new ImageVO(virtualPath, urlPath, fileName);
            return imageVO;

        } catch (IOException e) {
            //一般条件下为了不影响代码结构,将检查异常,转化为运行时异常
            //往外抛异常影响层级结构
            //自己try-catch要是出错无法处理,
            //所以转换常运行时异常
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    public void deleteFile(String virtualPath) {    //传过来会解码
        String localPath = rootDir + virtualPath;
        File file = new File(localPath);
        if (file.exists()){
            file.delete();//delete()只能删除空包或文件
        }
    }
}

ItemController

package com.jt.controller;

import com.jt.pojo.Item;
import com.jt.service.ItemService;
import com.jt.vo.ItemVO;
import com.jt.vo.PageResult;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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

    @Autowired
    private ItemService itemService;

    /*     商品列表展现    */
    @GetMapping("/getItemList")
    public SysResult getItemList(PageResult pageResult){
        pageResult = itemService.getItemList(pageResult);
        return SysResult.success(pageResult);
    }


    /*      商品新增       */
    @PostMapping("/saveItem")
    public SysResult saveItem(ItemVO itemVO){
        itemService.saveItem(itemVO);
        return SysResult.success();
    }


    /*     商品删除     */
    @DeleteMapping("/deleteItemById")
    public SysResult deleteItemById(int id){
        itemService.deleteItemById(id);
        return SysResult.success();
    }

    /*     商品 状态 修改     */
    @PutMapping("/updateItemStatus")
    public SysResult updateItemStatus(Item item){
        itemService.updateItemStatus(item);
        return SysResult.success();
    }

    /*      商品数据修改      */

}

ItemServiceImpl

package com.jt.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jt.mapper.ItemDescMapper;
import com.jt.mapper.ItemMapper;
import com.jt.pojo.Item;
import com.jt.pojo.ItemDesc;
import com.jt.vo.ItemVO;
import com.jt.vo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

@Service
public class ItemServiceImpl implements ItemService{
    /*  一个表对应的建立一个Mapper,注入对应类的泛型
    *   两个关联的表可注入同一个service,一起使用
    * */
    @Autowired
    private ItemMapper itemMapper;
    @Autowired
    private ItemDescMapper itemDescMapper;

    /*     商品列表展现    */
    @Override
    @Transactional
    public PageResult getItemList(PageResult pageResult) {
        //模糊查询
        String query = pageResult.getQuery();
        boolean flag = StringUtils.hasLength(query);
        QueryWrapper<Item> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(flag,"title",query);//查询条件
        List<Item> list = itemMapper.selectList(queryWrapper);//结果列表
        //定义分页对象
        IPage<Item> page =
                new Page<>(pageResult.getPageNum(), pageResult.getPageSize());
        //调用分页查询,传入分页对象和条件构造器
        //相当于传入查询条件,分页页数,条数,底层自行根据这些帮分页,省了自己分页
        //返回的还是个page对象,但此时的page有2+2信息
        page = itemMapper.selectPage(page, queryWrapper);
        long total = page.getTotal();//获取查询结果总条数
        List<Item> records = page.getRecords();//获取传入条数和页数,数据后的分页结果
        //存入pageresult返回给前面
        pageResult.setTotal(total).setRows(records);
        System.out.println("加载完成");
        return pageResult;
    }


    /*      商品新增
     * 需求: 完成2部分入库操作
     * 步骤1: 完成Item入库操作
     * 步骤2: 完成ItemDesc入库操作 item.id=itemDesc.id
     * mybatis 知识讲解
     *  <insert id="xxxx" useGeneratedKeys="true"
     *             keyColumn="id"
     *             keyProperty="id">
     *         新增sql
     *  </insert>
     *  MP知识讲解:
     *      MP基于对象的方式操作数据,如果实现数据的入库操作,
     *      则数据都会与对象绑定,动态回显.
     *  难点知识: 如何实现数据回显!!!!!!
     * @param itemVO
     */
    @Override
    @Transactional
    public void saveItem(ItemVO itemVO) {
        Item item = itemVO.getItem().setStatus(true);
        //刚开始id为null,入库操作时候,id在数据库中会自动赋值
        //赋值之后,对象中的ID依然为null
        itemMapper.insert(item);
        ItemDesc itemDesc = itemVO.getItemDesc().setId(item.getId());
        itemDescMapper.insert(itemDesc);
    }

    /*     商品删除     */
    @Override
    @Transactional
    public void deleteItemById(int id) {
        itemMapper.deleteById(id);
        itemDescMapper.deleteById(id);
    }

    /*      商品状态修改      */
    @Override
    public void updateItemStatus(Item item) {
        itemMapper.updateById(item);
    }





}

MybatisPlusConfig

package com.jt.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*MybatisPlus可以实现跨数据库.
用户操作的是对象,但是由MP动态的生成对应的Sql语句.
如果需要使用分页,则需要额外的指定数据库版本. 需要编辑配置类.*/
@Configuration  //标识配置类
public class MybatisPlusConfig {

    //将自定义的对象交给Spring容器管理 告诉MP 使用的mysql/mariadb数据库
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor
                (new PaginationInnerInterceptor(DbType.MARIADB));
        return interceptor;
    }
}

SystemException

package com.jt.aop;

import com.jt.vo.SysResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/*      全局异常处理机制,所有异常都会往上抛,都会经过,只拦截cController层就行, */
@RestControllerAdvice   //advice 通知,
public class SystemException {

    //指定异常进行拦截捕获
    @ExceptionHandler(RuntimeException.class)
    public SysResult exception(Exception e){
        e.printStackTrace();//处理异常,在控制台输出,不然不好找错
        return SysResult.fail();//给前端页面一个正向反馈
    }
}

在调用JNI接口写文件时,出现了一个错误消息"FORTIFY: fwrite: null FILE*"。这个错误消息通常意味着代码中的文件指针为空,导致无法对文件进行写入操作。根据引用中的信息,可以看到在代码中可能存在一个空的文件指针。同时,根据引用和引用中的代码片段,可以看到在代码中有一段注释掉的代码,其中包含了打开文件和写入操作的相关代码。因此,可能的原因是在代码中某处文件指针未正确地赋初值或者在写入文件之前未对文件进行正确的打开操作,导致文件指针为空,从而触发了fwrite null file的错误消息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [安卓JNI踩坑 FORTIFY: fwrite: null FILE*](https://blog.csdn.net/qq_33183456/article/details/105473826)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [fwrite file code](https://blog.csdn.net/mianhuantang848989/article/details/39524885)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值