图书管理系统(四)图书管理系统实战(二)

简介: 图书管理系统(四)图书管理系统实战(二)

1. 前言

前一篇文章 图书管理系统实战(一) 中,我们已经编写了 pojo、dao 层以及配置 dao 层对应的 mapper,从现在开始,我们开始编写 service 层和 controller 层。


2. service 层

2.1 预约业务操作码

在正式编写 service 层之前,我们先定义一个预约图书操作返回码的数据字段,用于反馈给客户信息;


返回码 说明

1 预约成功

0 预约失败

-1 预约重复

-2 系统异常


package com.cunyu.utils;
import com.cunyu.dto.AppointDto;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : AppointStateEnum
 * @date : 2020/7/24 10:50
 * @description : 定义预约业务的数据字典
 */
@Getter
@AllArgsConstructor
public enum AppointStateEnum {
    SUCCESS(1, "预约成功"), FAILURE(0, "预约失败"), REPEAT(-1, "预约重复"), SYSTEMERROR(-2, "系统异常");
    private int state;
    private String stateInfo;
    /**
     * @param stat 状态码
     * @return
     * @description 获取状态码对应 enum
     * @date 2020/7/24 10:57
     * @author cunyu1943
     * @version 1.0
     */
    public static AppointStateEnum stateOf(int stat) {
        for (AppointStateEnum state : values()
        ) {
            if (stat == state.getState()) {
                return state;
            }
        }
        return null;
    }
}

3.2 数据传输层

定义好预约业务的数据字典之后,新建一个数据传输类用来传输我们的预约结果;

package com.cunyu.dto;
import com.cunyu.pojo.Appointment;
import com.cunyu.utils.AppointStateEnum;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : AppointDto
 * @date : 2020/7/24 10:46
 * @description : 用于数据传输,封装
 */
@Data
@NoArgsConstructor
public class AppointDto {
    private int bookId;
    // 状态码
    private int state;
    // 状态信息
    private String stateInfo;
    // 预约成功的对象
    private Appointment appointment;
    //    预约失败的构造器
    public AppointDto(int bookId, AppointStateEnum appointStateEnum) {
        this.bookId = bookId;
        this.state = appointStateEnum.getState();
        this.stateInfo = appointStateEnum.getStateInfo();
    }
    //    预约成功的构造器
    public AppointDto(int bookId, AppointStateEnum appointStateEnum, Appointment appointment) {
        this.bookId = bookId;
        this.state = appointStateEnum.getState();
        this.stateInfo = appointStateEnum.getStateInfo();
        this.appointment = appointment;
    }
}

2.3 service 业务代码编写

2.3.1 BookService.java

package com.cunyu.service;
import com.cunyu.dto.AppointDto;
import com.cunyu.pojo.Book;
import java.util.List;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : BookService
 * @date : 2020/7/24 10:44
 * @description : Book 业务接口
 */
public interface BookService {
    /**
     * @param bookId 图书 ID
     * @return 对应 ID 的图书
     * @description 根据图书 id 查询图书
     * @date 2020/7/24 11:41
     * @author cunyu1943
     * @version 1.0
     */
    Book getById(int bookId);
    /**
     * @param
     * @return 所有图书的列表
     * @description 获取图书列表
     * @date 2020/7/24 11:41
     * @author cunyu1943
     * @version 1.0
     */
    List<Book> getList();
    /**
     * @param bookId    图书 id
     * @param studentId 学生 Id
     * @return
     * @description 返回预约结果
     * @date 2020/7/24 11:39
     * @author cunyu1943
     * @version 1.0
     */
    AppointDto appoint(int bookId, int studentId);
}

2.3.2 BookServiceImpl.java

package com.cunyu.service.impl;
import com.cunyu.dao.AppointmentDao;
import com.cunyu.dao.BookDao;
import com.cunyu.dto.AppointDto;
import com.cunyu.pojo.Appointment;
import com.cunyu.pojo.Book;
import com.cunyu.service.BookService;
import com.cunyu.utils.AppointStateEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : BookServiceImpl
 * @date : 2020/7/24 11:43
 * @description : Book 业务接口实现类
 */
@Service
public class BookServiceImpl implements BookService {
    //    依赖注入
    @Autowired
    private BookDao bookDao;
    @Autowired
    private AppointmentDao appointmentDao;
    public Book getById(int bookId) {
        return bookDao.queryById(bookId);
    }
    public List<Book> getList() {
        return bookDao.queryAll(0, 3);
    }
    public AppointDto appoint(int bookId, int studentId) {
        AppointDto appointDto = null;
        try {
            // 减库存
            int update = bookDao.reduceNumber(bookId);
            if (update <= 0) {
                System.out.println(AppointStateEnum.FAILURE);
            } else {
                // 执行预约操作
                int insert = appointmentDao.insertAppointment(bookId, studentId);
                if (insert <= 0) {
                    System.out.println(AppointStateEnum.REPEAT);
                } else {
                    Appointment appointment = appointmentDao.queryByKeyWithBook(bookId, studentId);
                    appointDto = new AppointDto(bookId, AppointStateEnum.SUCCESS, appointment);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return appointDto;
    }
}

2.4 测试

package com.cunyu.service.impl;
import com.cunyu.service.BookService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : BookServiceImplTest
 * @date : 2020/7/24 11:53
 * @description : BookServiceImpl 测试类
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/spring-*.xml")
public class BookServiceImplTest {
    @Autowired
    private BookService bookService;
    @Test
    public void testAppoint() {
        int bookId = 1;
        int studentId = 18301343;
        System.out.println(bookService.appoint(bookId, studentId));
    }
}

下图是我们测试后数据库中的数据,说明此时我们的 service 层接口测试成功。

image.png

2.5 封装结果

既然我们的 service 层接口和实现类都编写好了,我们就需要将结果进行封装成 json 格式,方便我们传到 controller 交互使用。

package com.cunyu.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : ResultDto
 * @date : 2020/7/24 12:11
 * @description : 封装结果为 json
 */
@Data
@NoArgsConstructor
public class ResultDto<T> {
    // 是否预约成功
    private boolean success;
    // 预约成功返回的数据
    private T data;
    // 错误信息
    private String error;
    // 预约成功的构造器
    public ResultDto(boolean success, T data) {
        this.success = success;
        this.data = data;
    }
    // 预约失败的构造器
    public ResultDto(boolean success, String error) {
        this.success = success;
        this.error = error;
    }
}

3. controller 层

编写好 service 层之后,我们就剩下最后的 controller 层了;

package com.cunyu.controller;
import com.cunyu.dto.AppointDto;
import com.cunyu.dto.ResultDto;
import com.cunyu.pojo.Book;
import com.cunyu.service.BookService;
import com.cunyu.utils.AppointStateEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : BookController
 * @date : 2020/7/24 12:20
 * @description : Book controller 层
 */
@Controller
@RequestMapping("/book")
public class BookController {
    @Autowired
    private BookService bookService;
    // url:ip:port:/book/list
    @GetMapping("/list")
    private String list(Model model) {
        List<Book> bookList = bookService.getList();
        model.addAttribute("bookList", bookList);
        return "list";
    }
    @GetMapping(value = "/{bookId}/detail")
    private String detail(@PathVariable("bookId") Integer bookId, Model model) {
        if (bookId == null) {
            return "redirect:/book/list";
        }
        Book book = bookService.getById(bookId);
        if (book == null) {
            return "forward:/book/list";
        }
        model.addAttribute("book", book);
        return "detail";
    }
    //ajax 传递 json 数据到前端
    @RequestMapping(value = "/{bookId}/appoint", method = RequestMethod.POST, produces = {"application/json; charset=utf-8"})
    @ResponseBody
    private ResultDto<AppointDto> appoint(@PathVariable("bookId") Integer bookId, @RequestParam("studentId") Integer studentId) {
        if (studentId == null || studentId.equals("")) {
            return new ResultDto<>(false, "学号不能为空");
        }
        AppointDto appointDto = null;
        try {
            appointDto = bookService.appoint(bookId, studentId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ResultDto<AppointDto>(true, appointDto);
    }
}

4. 前端

好了,我们的后台就开发完毕了,接下来就可以去编写前端页面了。然后启动 Tomcat,访问对应 url 即可。

4.1 list.jsp

<%--
  Created by IntelliJ IDEA.
  User: cunyu
  Date: 2020/7/23
  Time: 9:47
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>图书列表页</title>
</head>
<body>
<h1>${bookList}</h1>
</body>
</html>

image.png

4.2 detail.jsp

<%--
  Created by IntelliJ IDEA.
  User: cunyu
  Date: 2020/7/23
  Time: 10:02
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>图书详情页</title>
</head>
<body>
    <h1>${book.name}</h1>
    <h2>${book.bookId}</h2>
    <h2>${book.number}</h2>
</body>
</html>

image.png

5. 总结

到此,我们的后台所有服务都写好了,SSM 框架整合配置,与应用实例部分已经结束,前端部分就简单写了个数据展示页面。

目录
相关文章
|
存储 Kubernetes Cloud Native
一文搞懂云原生架构
目前,每个 IT 资源或产品都作为服务提供。而且伴随云计算的滚滚浪潮,云原生(CloudNative)的概念应运而生,云原生很火,火得一塌糊涂,都0202年了,如果还不懂云原生,那真的out了。因此,云原生软件开发成为每个企业的关键要求,无论其规模和性质如何。在加入云计算潮流之前,了解什么是云原生架构以及如何为云原生应用程序需求设计正确的架构非常重要。
一文搞懂云原生架构
|
存储 关系型数据库 MySQL
DataX: 阿里开源的又一款高效数据同步工具
DataX 是由阿里巴巴集团开源的一款大数据同步工具,旨在解决不同数据存储之间的数据迁移、同步和实时交换的问题。它支持多种数据源和数据存储系统,包括关系型数据库、NoSQL 数据库、Hadoop 等。 DataX 提供了丰富的数据读写插件,可以轻松地将数据从一个数据源抽取出来,并将其加载到另一个数据存储中。它还提供了灵活的配置选项和高度可扩展的架构,以适应各种复杂的数据同步需求。
|
10月前
|
监控 负载均衡 Java
5 大 SpringCloud 核心组件详解,8 张图彻底弄懂
本文图文详解 Spring Cloud 的五大核心组件,帮助深入理解和掌握微服务架构。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
5 大 SpringCloud 核心组件详解,8 张图彻底弄懂
|
5月前
|
存储 消息中间件 SQL
数据中台架构与技术体系
本文介绍了数据中台的整体架构设计,涵盖数据采集、存储、计算、服务及治理等多个层面。在数据采集层,通过实时与离线方式整合多类型数据源;存储层采用分层策略,包括原始层、清洗层、服务层和归档层,满足不同访问频率需求;计算层提供批处理、流处理、交互式分析和AI计算能力,支持多样化业务场景。数据服务层封装数据为标准化API,实现灵活调用,同时强调数据治理与安全,确保元数据管理、质量监控、权限控制及加密措施到位,助力企业构建高效、合规的数据管理体系。
1570 13
|
11月前
|
前端开发 Java 应用服务中间件
21张图解析Tomcat运行原理与架构全貌
【10月更文挑战第2天】本文通过21张图详细解析了Tomcat的运行原理与架构。Tomcat作为Java Web开发中最流行的Web服务器之一,其架构设计精妙。文章首先介绍了Tomcat的基本组件:Connector(连接器)负责网络通信,Container(容器)处理业务逻辑。连接器内部包括EndPoint、Processor和Adapter等组件,分别处理通信、协议解析和请求封装。容器采用多级结构(Engine、Host、Context、Wrapper),并通过Mapper组件进行请求路由。文章还探讨了Tomcat的生命周期管理、启动与停止机制,并通过源码分析展示了请求处理流程。
|
9月前
|
Prometheus 监控 Cloud Native
无痛入门Prometheus:一个强大的开源监控和告警系统,如何快速安装和使用?
Prometheus 是一个完全开源的系统监控和告警工具包,受 Google 内部 BorgMon 系统启发,自2012年由前 Google 工程师在 SoundCloud 开发以来,已被众多公司采用。它拥有活跃的开发者和用户社区,现为独立开源项目,并于2016年加入云原生计算基金会(CNCF)。Prometheus 的主要特点包括多维数据模型、灵活的查询语言 PromQL、不依赖分布式存储、通过 HTTP 拉取时间序列数据等。其架构简单且功能强大,支持多种图形和仪表盘展示模式。安装和使用 Prometheus 非常简便,可以通过 Docker 快速部署,并与 Grafana 等可
4335 2
|
11月前
|
Java Apache Maven
Java将word文档转换成pdf文件的方法?
【10月更文挑战第13天】Java将word文档转换成pdf文件的方法?
3530 1
|
消息中间件 存储 缓存
面试官问我:如何设计一个秒杀场景?
在之前的工作经历中,我做过营销相关项目,接触过关于票券秒杀的高并发场景,秒杀场景也算是最热门的高并发场景之一了。 下面我就把我对秒杀场景的一些理解简单写下来,仅供大家参考,欢迎留言纠错或者补充。
868 0
面试官问我:如何设计一个秒杀场景?
|
Linux 开发工具 Windows
在WSL2中安装IntelliJ IDEA开发工具
在WSL2中安装IntelliJ IDEA开发工具
1219 2
|
Java 开发者 Spring
springboot DDD的概念以及实战
【5月更文挑战第15天】领域驱动设计(Domain-Driven Design,简称DDD)是一种软件设计方法论,它强调基于业务领域的复杂性来构建软件
1150 2

热门文章

最新文章