使用Spring Boot和MyBatis Plus整合实现商品二维码生成

前言

二维码已经成为现代商业的常用工具,二维码不仅能够实现快速付款,还能够实现商品信息的展示。在这篇文章中,我们将使用Spring Boot和MyBatis Plus整合来实现商品二维码的生成。在本文中,我们将讨论如何使用Spring Boot和MyBatis Plus实现商品信息的查询、生成二维码、以及二维码的显示与分享等操作。

开发环境

以下是本篇文章使用的开发环境:

  • JDK 1.8+
  • IntelliJ IDEA
  • Spring Boot 2.3.0.RELEASE
  • MyBatis Plus 3.4.0
  • MySQL 5.6+

项目结构

我们先来看一下我们的项目结构:

├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           ├── config
│   │   │           │   └── MyBatisPlusConfig.java
│   │   │           ├── controller
│   │   │           │   └── GoodsController.java
│   │   │           ├── dao
│   │   │           │   └── GoodsMapper.java
│   │   │           ├── pojo
│   │   │           │   └── Goods.java
│   │   │           ├── service
│   │   │           │   ├── IGoodsService.java
│   │   │           │   └── impl
│   │   │           │       └── GoodsServiceImpl.java
│   │   │           └── util
│   │   │               ├── QRCodeUtil.java
│   │   │               └── WxShareUtil.java
│   │   ├── resources
│   │   │   ├── application.properties
│   │   │   ├── mapper
│   │   │   │   └── GoodsMapper.xml
│   │   │   └── static
│   │   │       └── images
│   │   │           └── qrcode
│   │   └── webapp
│   └── test
└── pom.xml

在以上项目结构中,我们使用Maven作为构建工具,项目主要包括了config、controller、dao、pojo、service、util这几个包。

数据库设计

本文我们将实现的是一个购物系统。其中,商品信息的存储我们使用了MySQL数据库。在这里,我们先来看下我们需要存储哪些信息。

  • 商品编号(goods_id)
  • 商品名称(goods_name)
  • 商品价格(goods_price)
  • 商品库存(goods_stock)
  • 商品描述(goods_description)
  • 商品图片(goods_image)

以下是我们的商品信息表的设计:

CREATE TABLE `goods` (
  `goods_id` int(11) NOT NULL COMMENT '商品编号',
  `goods_name` varchar(255) NOT NULL COMMENT '商品名称',
  `goods_price` decimal(10,2) NOT NULL COMMENT '商品价格',
  `goods_stock` int(11) NOT NULL COMMENT '商品库存',
  `goods_description` varchar(255) DEFAULT NULL COMMENT '商品描述',
  `goods_image` varchar(255) NOT NULL COMMENT '商品图片',
  PRIMARY KEY (`goods_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品信息表';

MyBatis Plus配置

MyBatis Plus是MyBatis的增强工具,它简化了MyBatis操作,让开发人员更加专注于业务开发。我们在这里配置MyBatis Plus,以便让它在我们的项目中更好地发挥作用。

@Configuration
@MapperScan("com.example.dao")
public class MyBatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

我们使用了@Configuration来注解这个类,表示这是一个配置类。在这个配置类中,我们使用了@MapperScan注解来扫描我们的Mapper接口,并将它们注入到Spring容器中。同时,我们还配置了一个PaginationInterceptor,它是MyBatis Plus提供的分页插件,让我们在分页查询的时候更加方便。

商品实体类

商品实体类对应了数据库中的goods表,包含了商品的所有信息字段。

@Data
public class Goods {
    private Integer goodsId;
    private String goodsName;
    private BigDecimal goodsPrice;
    private Integer goodsStock;
    private String goodsDescription;
    private String goodsImage;
}

我们使用了@Data注解来自动生成getter和setter方法,这样我们就可以在其他地方方便地使用商品实体类了。

商品DAO接口

我们使用MyBatis Plus提供的BaseMapper来实现商品信息的查询、添加、修改、删除等操作。

public interface GoodsMapper extends BaseMapper<Goods> {
}

我们只需要继承BaseMapper接口,MyBatis Plus就会自动帮我们生成相应的SQL语句了。

商品Service接口

商品Service接口对应了我们的业务需求,实现了对商品的增删改查等操作。

public interface IGoodsService {
    boolean addGoods(Goods goods);
    boolean deleteGoodsById(Integer goodsId);
    boolean updateGoods(Goods goods);
    Goods getGoodsById(Integer goodsId);
    List<Goods> getGoodsList();
}

我们定义了添加商品、删除商品、修改商品、查询商品、查询商品列表等几个方法。在这里,我们使用了boolean类型的返回值来表示这些操作是否执行成功。

商品Service实现类

现在我们来实现IGoodsService接口中的方法。

@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements IGoodsService {
    @Override
    public boolean addGoods(Goods goods) {
        return save(goods);
    }

    @Override
    public boolean deleteGoodsById(Integer goodsId) {
        return removeById(goodsId);
    }

    @Override
    public boolean updateGoods(Goods goods) {
        return updateById(goods);
    }

    @Override
    public Goods getGoodsById(Integer goodsId) {
        return getById(goodsId);
    }

    @Override
    public List<Goods> getGoodsList() {
        return list();
    }
}

我们使用了@Service注解来将这个类注入到Spring容器中。在这里,我们继承了ServiceImpl类,它是MyBatis Plus提供的Service实现类。我们的操作就是在这个类中实现的。

生成二维码

现在我们来讨论如何使用Java代码生成含商品信息的二维码。我们使用了zxing这个Java库来生成二维码。

public class QRCodeUtil {
    // 生成二维码的大小
    private static final int QRCODE_SIZE = 300;
    // 生成二维码的文件格式
    private static final String QRCODE_FORMAT = "png";
    // 二维码字体的设置
    private static final Map<EncodeHintType, Object> hints = new HashMap<>();

    static {
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        hints.put(EncodeHintType.MARGIN, 2);
    }

    /**
     * 生成二维码
     *
     * @param content    二维码内容
     * @param image      logo文件
     * @param needCompress 是否需要压缩
     * @return 二维码图片
     * @throws IOException io异常
     * @throws WriterException WriterException异常
     */
    public static BufferedImage createImage(String content, File image, boolean needCompress) throws IOException, WriterException {
        // 生成二维码的核心代码
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);

        // 构造一个空的bufferedImage
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage imageBuffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        // 将矩阵数据画到bufferedImage中去
        for (int x = 0; x < width; x++) {
            for (int y = 0;y < height; y++) {
                imageBuffer.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }

        if (image != null) {
            // 在二维码中添加logo
            insertImage(imageBuffer, image, needCompress);
        }

        return imageBuffer;
    }

    /**
     * 将图片添加到二维码中间
     *
     * @param source       二维码图片
     * @param insertImage  logo图片
     * @param needCompress 是否需要压缩
     * @throws IOException io异常
     */
    private static void insertImage(BufferedImage source, File insertImage, boolean needCompress) throws IOException {
        Image src = ImageIO.read(insertImage);
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        if (needCompress) {
            if (width > QRCODE_SIZE * 0.2) {
                width = (int) (QRCODE_SIZE * 0.2);
            }
            if (height > QRCODE_SIZE * 0.2) {
                height = (int) (QRCODE_SIZE * 0.2);
            }

            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null);
            g.dispose();
            src = image;
        }

        // 插入logo
        Graphics2D graph = source.createGraphics();
        int x = (QRCODE_SIZE - width) / 2;
        int y = (QRCODE_SIZE - height) / 2;
        graph.drawImage(src, x, y, width, height, null);
        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }
}

在这个类中,我们定义了一个createImage方法来生成二维码。它接受三个参数:二维码的内容、logo文件、以及是否需要压缩。

微信分享

在本文中,我们使用了WxShareUtil类来实现微信分享。WxShareUtil是一个封装好的Java类,它使用了微信提供的API来实现微信分享的功能。在这里,我们只需要调用这个类中的方法即可。

public class WxShareUtil {
    /**
     * 分享链接到朋友圈
     *
     * @param title   链接标题
     * @param desc    链接描述
     * @param linkUrl 链接url
     * @param imgUrl  分享图片url
     */
    public static void shareLinkToTimeline(String title, String desc, String linkUrl, String imgUrl) {
        WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
        config.setAppId("your app id");
        config.setSecret("your app secret");
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(config);
        try {
            WxMpMaterialNews wxMpMaterialNews = new WxMpMaterialNews();
            WxMpMaterialNews.WxMpMaterialNewsArticle article = new WxMpMaterialNews.WxMpMaterialNewsArticle();
            article.setTitle(title);
            article.setDescription(desc);
            article.setUrl(linkUrl);
            article.setThumbMediaId(wxMpService.getMaterialService().mediaUpload(WxConsts.MaterialType.IMAGE, ResourceUtils.getFile(imgUrl)));

            wxMpMaterialNews.addArticle(article);
            wxMpService.getMaterialService().materialNewsUpload(wxMpMaterialNews);
            // 分享链接到朋友圈
            WxMpKefuMessage wxMpKefuMessage = WxMpKefuMessage.NEWS()
                    .addArticle(article)
                    .toUser("@all")
                    .build();
            wxMpService.getKefuService().sendKefuMessage(wxMpKefuMessage);
        } catch (WxErrorException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

在这个类中,我们定义了一个shareLinkToTimeline方法来分享链接到朋友圈。它接受四个参数:链接标题、链接描述、链接url、以及分享图片url。在这里,我们使用了微信提供的Java SDK来实现分享操作。

商品Controller

现在我们来实现商品相关的Controller。

@RestController
@RequestMapping("/goods")
public class GoodsController {
    @Autowired
    private IGoodsService goodsService;

    /**
     * 获取商品列表
     */
    @GetMapping("/list")
    public List<Goods> getGoodsList() {
        return goodsService.getGoodsList();
    }

    /**
     * 添加商品
     */
    @PostMapping
    public boolean addGoods(@RequestBody Goods goods) {
        return goodsService.addGoods(goods);
    }

    /**
     * 修改商品信息
     */
    @PutMapping("/{goodsId}")
    public boolean updateGoods(@PathVariable Integer goodsId, @RequestBody Goods goods) {
        goods.setGoodsId(goodsId);
        return goodsService.updateGoods(goods);
    }

    /**
     * 删除商品
     */
    @DeleteMapping("/{goodsId}")
    public boolean deleteGoods(@PathVariable Integer goodsId) {
        return goodsService.deleteGoodsById(goodsId);
    }

    /**
     * 生成商品二维码
     */
    @GetMapping("/{goodsId}/qrcode")
    public ResponseEntity<InputStreamResource> generateQRCode(@PathVariable Integer goodsId) {
        try {
            // 获取商品信息
            Goods goods = goodsService.getGoodsById(goodsId);
            if (goods == null) {
                return ResponseEntity.notFound().build();
            }

            // 生成二维码
            File imageFile = new File("src/main/resources/static/images/qrcode/" + goodsId + ".png");
            if (!imageFile.exists()) {
                imageFile.getParentFile().mkdirs();
                QRCodeUtil.createImage(JSONObject.toJSONString(goods), null, true);
            }

            // 返回二维码的输入流
            FileInputStream fileInputStream = new FileInputStream(imageFile);
            return ResponseEntity.ok().contentType(MediaType.IMAGE_PNG).contentLength(imageFile.length()).body(new InputStreamResource(fileInputStream));
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    /**
     * 在微信中分享商品
     */
    @GetMapping("/{goodsId}/share")
    public void shareGoods(@PathVariable Integer goodsId) {
        try {
            // 获取商品信息
            Goods goods = goodsService.getGoodsById(goodsId);
            if (goods == null) {
                return;
            }

            // 分享链接到朋友圈
            WxShareUtil.shareLinkToTimeline(goods.getGoodsName(), goods.getGoodsDescription(), "http://localhost:8080/goods/" + goodsId + "/qrcode", "src/main/resources/static/images/logo.png");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这个Controller中,我们实现了获取商品列表、添加商品、修改商品、删除商品、生成商品二维码、分享商品等几个操作。在生成商品二维码的时候,我们使用了QRCodeUtil来生成二维码图片,并将其保存到本地。在分享商品的时候,我们使用了WxShareUtil来实现微信分享操作。

总结

在本文中,我们学习了如何使用Spring Boot和MyBatis Plus来实现商品二维码的生成,并且能够用微信等工具扫码查看。我们通过实现商品信息的增删改查来满足我们的业务需求,并且通过Java代码生成二维码和微信分享来实现了商品信息的展示和分享等功能。这些操作都是在Spring Boot和MyBatis Plus的基础上完成的。

最后,希望本文能对大家有所帮助,也欢迎大家批评指正

你可能感兴趣的:(mybatis,java,mysql)