Bookstore management system (backend interface)

      Based on the fact that I recently helped a friend to complete the project, I completely collapsed. There are no java development tools, no SpringBoot+vue to write front-end additions, deletions, modifications, checks, no use of Renren open source framework and Ruoyi framework, etc. . . . . . . . .

 So, come up with a set of super simple java development tutorials. To help those with poor coding skills understand SpringBoot+Vue development, this set of tutorials is different from the one I wrote before. This set is more refined, simpler, easier to understand, and more powerful.

 achieve effect

 

In short, it is suitable for learning reference for friends who know some ssm framework and know a little js and vue (*^▽^*)

Preparation:

Baidu network disk address of java development tools:

Link: https://pan.baidu.com/s/18gH-6AsQtHtIIyJNxJPl9w?pwd=1111 
Extraction code: 1111

I have prepared mysql, database visualization tool Navicat, new version of idea, vscode, node.js 18 and 16 version running files, crack files and even jdk for you.

There are cracking tutorials on the Internet, just find a tutorial and install it. If you really can't, you leave a message below, and I will contact you when I see it.

development tools:

idea 2021.1.3           maven 3.8.1           node 16         vscode 17

jdk 1.8                        mysql 8.0             Navicat 16       

Project Gitee warehouse address: Super simple front-end and back-end SpringBoot+Vue practice project: The project structure is a front-end and back-end separation mode. The bookstore management system developed using the SpringBoot framework and the Vue framework can realize crud operations such as uploading and modifying books in the bookstore. (gitee.com)

Development steps:

1、sql

CREATE TABLE `book` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '序号',
  `picture` varchar(2000) DEFAULT NULL COMMENT '图片',
  `name` varchar(200)  DEFAULT NULL COMMENT '书本名称',
  `introduce` varchar(200)  DEFAULT NULL COMMENT '介绍',
  `publish` varchar(200)  DEFAULT NULL COMMENT '出版社',
  `auth` varchar(200)  DEFAULT NULL COMMENT '作者',
  `price` double DEFAULT NULL COMMENT '价格',
  `is_deleted` tinyint unsigned DEFAULT '0' COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',
  `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
  `gmt_modified` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=8 COMMENT='书本信息表';

2. Create a new SpringBoot project with idea

 Then click Next to select dependencies. Here we can choose a web one, and we will configure the others later. My SpringBoot version here is 2.6.13

 3. Add pom dependency and modify application.properties configuration file

Add pom dependencies

<dependencies>
        <!--spring web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!---->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.17</version>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>

        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>

        <!--spring2.X集成redis所需common-pool12-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.6.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.12</version>
        </dependency>
    </dependencies>

Because we want to realize the upload, modification, and display of book pictures, and strive for the simplest way, then we can only create a new folder locally to store pictures, and then configure a mapping relationship for users to access. Here I created a new images folder on the E drive to store pictures

# 应用服务 WEB 访问端口
server.port=8785
server.tomcat.uri-encoding=UTF-8

# 应用连接数据库
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/book?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# mybatis-plus 配置
# 配置mapper.xml文件位置
mybatis-plus.mapper-locations=classpath:/mapper/**/*.xml
# 配置mybatis打印SQL
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 全局配置mybatis主键自增策略
mybatis-plus.global-config.db-config.id-type=auto

#文件上传地址
file-save-path=E:/images/


# 数据库时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=Asia/Shanghai

 Then build the project framework, that is, the entity, mapper, service, controller, config, utils directories are built, and then delete the original web and static

 

 The entity class is stored under the entity package, and the book entity class implements the Serializable interface to achieve serialization. @Data, @TableName, @TableId and @TableFiled annotations are provided by mybatis-plus. @TableName is used to mark which table you are mapping, @ TableId is used to map the primary key of the table and the primary key auto-increment strategy. I use integer auto-increment here. The rest is also true.

@Data
@TableName("book")
public class Book implements Serializable{

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;

    /**
     * 书本图片
     */
    @TableField("picture")
    private String picture;

    /**
     * 书本名称
     */
    @TableField("name")
    private String name;

    /**
     * 书本介绍
     */
    @TableField("introduce")
    private String introduce;

    /**
     * 出版社
     */
    @TableField("publish")
    private String publish;

    /**
     * 作者
     */
    @TableField("auth")
    private String auth;

    /**
     * 价格
     */
    @TableField("price")
    private Double price;

    /**
     * 删除标志
     */
    @TableField("is_deleted")
    private Integer isDeleted;

    /**
     * 创建时间
     */
    @TableField("gmt_create")
    private Date gmtCreate;

    /**
     * 修改时间
     */
    @TableField("gmt_modified")
    private Date gmtModified;
}

Stored under the utils package are some utility classes and packaged unified request API return types

public class Code {
    //系统业务执行成功
    public static final String WORK_OK = "00000";

    //系统业务出错
    public static final String WORK_ERR = "A0001";

    //业务执行中
    public static final String WORKING = "A0002";
}

 

public class R {

    private String code;
    private String message;
    private Object data;

    public R() {
    }

    public R(String code, String message) {
        this.code = Code.WORK_OK;
        this.message = message;
    }

    public R(String code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }


    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }


}
public class TimeUtil {

    public static Date getTime(){
        Date date = new Date();
        return date;
    }
}

Then write several configuration classes under the config folder to achieve a total of mybatis-plus paging, web mapping, and cross-domain

 CorsConfig configuration cross-domain

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOriginPatterns("*")
            .allowCredentials(true)
            .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
            .maxAge(3600);
    }
}

 MybatisPlusConfig implements paging plug-in configuration, here you can also configure other excellent plug-ins of mybatis-plus

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

 WebConfig configuration map resource

@Configuration
public class WebConfig implements WebMvcConfigurer {
    /**
     * 图片保存路径,自动从yml文件中获取数据
     *   示例: E:/images/
     */
    @Value("${file-save-path}")
    private String fileSavePath;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        /**
         * 配置资源映射
         * 意思是:如果访问的资源路径是以“/images/”开头的,
         * 就给我映射到本机的“E:/images/”这个文件夹内,去找你要的资源
         * 注意:E:/images/ 后面的 “/”一定要带上
         */
        registry.addResourceHandler("/images/**")
                .addResourceLocations("file:"+fileSavePath);
    }
}

Then write the controller layer interface, BookController here has a total of 6 interfaces

BookController

@RestController
@RequestMapping("book")
public class BookController {

    @Autowired
    private BookService bookService;

    /**
     * 时间格式化
     */
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd/");

    /**
     * 图片保存路径
     */
    @Value("${file-save-path}")
    private String fileSavePath;

    /**
     * 图片上传
     *
     * @param file
     * @param request
     * @return
     */
    @PostMapping("/upload")
    public R uploadPicture(@RequestParam("file") MultipartFile file, HttpServletRequest request) {

        String directory = simpleDateFormat.format(TimeUtil.getTime());


        /**
         * 文件保存目录 E:/images/2020/03/15/
         * 如果目录不存在,则创建
         */
        File dir = new File(fileSavePath + directory);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        System.out.println("图片上传,保存的位置:" + fileSavePath + directory);

        /**
         * 给文件重新设置一个名字
         * 后缀
         */
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        String newFileName = UUID.randomUUID().toString().replaceAll("-", "") + suffix;

        //4.创建这个新文件
        File newFile = new File(fileSavePath + directory + newFileName);
        //5.复制操作
        try {
            file.transferTo(newFile);
            //协议 :// ip地址 :端口号 / 文件目录(/images/2020/03/15/xxx.jpg)
            String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/images/" + directory + newFileName;
            System.out.println("图片上传,访问URL:" + url);
            return new R(Code.WORK_OK, "上传成功", url);
        } catch (IOException e) {
            return new R(Code.WORK_ERR, "IO异常");
        }
    }


    /**
     * 书城条件分页查询
     * @param current
     * @param pageSize
     * @param book
     * @return
     */
    @PostMapping("/list/{current}/{pageSize}")
    public R selectPage(@PathVariable("current") long current,@PathVariable("pageSize") long pageSize,
                        @RequestBody Book book){
        //mybatis-plus分页
        Page<Book> page = new Page<>(current, pageSize);
        QueryWrapper<Book> wrapper = new QueryWrapper<>();

        String name = book.getName();
        if (!StringUtils.isEmpty(name)){
            wrapper.like("name",name);
        }
        wrapper.eq("is_deleted","0");
        wrapper.orderByDesc("gmt_modified");

        Page<Book> result = bookService.selectPage(page, wrapper);
        if (StringUtils.isEmpty(String.valueOf(result.getRecords()))){
            return new R(Code.WORK_ERR,"查询为空");
        }
        return new R(Code.WORK_OK,"操作成功",result);
    }

    /**
     * 书城新增一本书
     * @param book
     * @return
     */
    @PostMapping("/add-one-book")
    public R addBookInfo(@RequestBody Book book){
        int flag = bookService.addBookInfo(book);
        if (flag != 1){
            return new R(Code.WORK_ERR,"新增书本信息失败!");
        }else {
            return new R(Code.WORK_OK,"新增书本信息成功!");
        }
    }

    /**
     * 根据id获取书本信息
     * @param id
     * @return
     */
    @GetMapping("/get-one-book/{id}")
    public R getOneBook(@PathVariable("id") Integer id){
        Book result = bookService.getOneBook(id);
        if (!Strings.isNotEmpty(result.getName())){
            return new R(Code.WORK_ERR,"根据id获取书本信息失败!");
        }
        return new R(Code.WORK_OK,"获取书本信息成功",result);
    }

    /**
     * 修改一本书的信息
     * @param book
     * @return
     */
    @PostMapping("/upd-one-book")
    public R updOneBook(@RequestBody Book book){
        int flag = bookService.updOneBook(book);
        if (flag != 1){
            return new R(Code.WORK_ERR,"新增书本信息失败!");
        }else {
            return new R(Code.WORK_OK,"新增书本信息成功!");
        }
    }

    /**
     * 删除一本书
     * @param book
     * @return
     */
    @PostMapping("/delete-one-book")
    public R deleteOneBook(@RequestBody Book book){
        int flag = bookService.deleteOneBook(book);
        if (flag != 1){
            return new R(Code.WORK_ERR,"新增书本信息失败!");
        }else {
            return new R(Code.WORK_OK,"新增书本信息成功!");
        }
    }
}

Service layer interface

BookService

public interface BookService {

    /**
     * 书城条件分页查询
     * @param page
     * @param wrapper
     * @return
     */
    Page<Book> selectPage(Page<Book> page, QueryWrapper<Book> wrapper);

    /**
     * 增加一本书的信息
     * @param book
     * @return
     */
    int addBookInfo(Book book);

    /**
     * 根据id获取书本信息
     * @param id
     * @return
     */
    Book getOneBook(Integer id);

    /**
     * 删除一本书
     * @param book
     * @return
     */
    int deleteOneBook(Book book);

    /**
     * 修改一本书的信息
     * @param book
     * @return
     */
    int updOneBook(Book book);
}

BookServiceImpl

@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookMapper bookMapper;

    /**
     * 书城条件分页查询
     *
     * @param page
     * @param wrapper
     * @return
     */
    @Override
    public Page<Book> selectPage(Page<Book> page, QueryWrapper<Book> wrapper) {
        return bookMapper.selectPage(page,wrapper);
    }

    /**
     * 增加一本书的信息
     *
     * @param book
     * @return
     */
    @Override
    public int addBookInfo(Book book) {
        Book entity = new Book();
        entity.setId(book.getId());
        entity.setPicture(book.getPicture());
        entity.setName(book.getName());
        entity.setIntroduce(book.getIntroduce());
        entity.setPublish(book.getPublish());
        entity.setAuth(book.getAuth());
        entity.setPrice(book.getPrice());
        entity.setIsDeleted(0);
        entity.setGmtCreate(TimeUtil.getTime());
        entity.setGmtModified(TimeUtil.getTime());
        return bookMapper.insert(entity);
    }

    /**
     * 根据id获取书本信息
     *
     * @param id
     * @return
     */
    @Override
    public Book getOneBook(Integer id) {
        Book book = bookMapper.selectById(id);
        return book;
    }

    /**
     * 删除一本书
     *
     * @param book
     * @return
     */
    @Override
    public int deleteOneBook(Book book) {
        Book entity = new Book();
        entity.setId(book.getId());
        entity.setIsDeleted(1);
        entity.setGmtModified(TimeUtil.getTime());
        return bookMapper.updateById(entity);
    }

    /**
     * 修改一本书的信息
     *
     * @param book
     * @return
     */
    @Override
    public int updOneBook(Book book) {
        Book entity = new Book();
        entity.setId(book.getId());
        entity.setPicture(book.getPicture());
        entity.setName(book.getName());
        entity.setIntroduce(book.getIntroduce());
        entity.setPublish(book.getPublish());
        entity.setAuth(book.getAuth());
        entity.setPrice(book.getPrice());
        entity.setGmtModified(TimeUtil.getTime());
        return bookMapper.updateById(entity);
    }
}

 BookMapper

@Mapper
public interface BookMapper extends BaseMapper<Book> {
}

 BookMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.czy.booktest02.demos.mapper.BookMapper">


</mapper>

 Because we have integrated mybatis-plus, and the project is also a normal crud operation, so BookMapper.xml basically does not write any sql statement, and I will make up for the fun function in the later stage.

In this way, the back-end interface is developed, and I will start another page to write the front-end later.

Guess you like

Origin blog.csdn.net/weixin_46511995/article/details/130210762