SpringBoot 多模块开发 笔记(一)

  • 多模块开发 简易版
  1. dao 层 也可以说是 Mapper 层
  2. web 层 将 controller 放在这一层 还有 统一返回类型 和 自定义异常 也在放在这里 启动类也放在这里
  3. model 层 也就是 数据对象 比如常见的 User 类
  4. server 层 业务逻辑层 或者说 service 层更好

创建步骤

  1. 创建一个正常的 Springboot 项目
  2. 删除 src 目录 和 不需要的 mvn 文件
  3. 修改 pom.xml
    1. 值得注意的是新版 idea 创建 Springboot 项目强制使用 jdk 17 这里使用的 解决办法就是 正常使用jdk17 创建项目创建完成后再在pom.xml中修改回来
    2. 解决办法不止 一种可以自行搜索
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
    </parent>
    <groupId>com.codervibe</groupId>
    <artifactId>springbootmultimodule</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springbootmultimodule</name>
    <description>springbootmultimodule</description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <!-- 修改打包方式为 pom -->
    <packaging>pom</packaging>
    <!--指定子模块-->
    <modules>
        <module>dao</module>
        <module>web</module>
        <module>server</module>
        <module>model</module>
    </modules>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>
  1. 依次创建 所需的 子模块 dao controller server model
  2. 将 这些模块的 打包方式改为 jar 并将 父模块改为 项目所在的模块
  3. 依赖关系 也就是将 到模块加入到 server 模块的pom.xml 中依次类推
    1. server 模块 依赖于 dao 模块
    2. controller 模块依赖于 server 模块
    3. dao server controller 三个子模块 均依赖于 model 模块
  • 父模块 添加的依赖 比如 mybatis 会同步到 子模块中
  1. 创建一个简易的 controller
java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {
    Logger logger = LoggerFactory.getLogger(UserController.class);

    @GetMapping("/list")
    public R list() {
        List<User> userList = new ArrayList<>();
        userList.add(new User(1, "孙悟空", "1111", "94df@f4m2.com.cn", new Date(), "1"));
        userList.add(new User(2, "金蝉子", "1111", "461b@91y35u.xyz", new Date(), "1"));
        userList.add(new User(3, "鲁班七号", "11111", "6959@687kyp.com", new Date(), "1"));
        userList.add(new User(4, "鲁班大师", "11111", "fa57@196bmfgq.com.cn", new Date(), "1"));
        userList.add(new User(5, "安其拉", "111111", "88ac@o23wg.com", new Date(), "1"));
        logger.info("用户列表 :" + userList.toString());
        return R.ok().data("userItems", userList).message("用户列表");
    }
}
  1. 添加 application.yaml
yml 复制代码
spring:
  application:
    name: springbootmultimodule
  jackson:
    date-format:yyyy-MM-dd HH:mm:ss
    time-zone=GMT+8
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3307/vue_login?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true
    username: root
    password: admin
server:
  port: 5767
  undertow:
    io-threads: 16
    worker-threads: 256
    buffer-size: 1024
    direct-buffers: true
  servlet:
    context-path: /springbootmultimodule
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.codervibe.springbootmultimodule.model


logging:
  level:
    root: info
    com.codervibe.springbootmultimodule: info
    com.codervibe.springbootmultimodule.mapper: debug
  file:
    path: ./log/
  1. 现在 添加 service的部分 包括 接口 和接口的实现
java 复制代码
package com.codervibe.server.service;


import com.codervibe.model.User;

import java.util.List;

public interface UserService {
    /**
     * 查询所有用户信息
     *
     * @return boolean
     */
     List<User> selectUserAll();
    /**
     * 添加用户信息列表
     * @return  boolean
     */
    void addList(List<User> userList);
}
java 复制代码
package com.codervibe.server.Impl;

import com.codervibe.mapper.UserMapper;
import com.codervibe.model.User;
import com.codervibe.server.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Service("UserService")
public class UserServiceImpl implements UserService {
    Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    @Resource
    private UserMapper userMapper;

    /**
     * 查询所有用户信息
     *
     * @return userList
     */
    @Override
    public List<User> selectUserAll() {

        logger.info(userMapper.selectUserAll().toString());
        logger.info("即将返回数据");
        return userMapper.selectUserAll();
    }
    /**
     * 添加用户信息列表
     *
     * @param userList
     * @return boolean
     */
    @Override
    public void addList(List<User> userList) {
        for (User user : userList) {
            userMapper.addList(user);
        }
    }
}
  1. 修改 controller 类的 方法 并依赖注入 service
java 复制代码
package com.codervibe.web.controller;


import com.codervibe.model.User;
import com.codervibe.server.service.UserService;
import com.codervibe.web.common.response.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

@RestController
@RequestMapping("/user")
public class UserController {
    Logger logger = LoggerFactory.getLogger(UserController.class);

    @Resource
    private UserService userService;


    @GetMapping("/list")
    public R list() {
        logger.info("用户列表 :" + userService.selectUserAll().toString());
        return R.ok().data("userItems", userService.selectUserAll()).message("用户列表");
    }

    @GetMapping("/addList")
    public R addList() {
        List<User> userList = new ArrayList<>();
        userList.add(new User(1, "孙悟空", "1111", "94df@f4m2.com.cn", new Date(), "1"));
        userList.add(new User(2, "金蝉子", "1111", "461b@91y35u.xyz", new Date(), "1"));
        userList.add(new User(3, "鲁班七号", "11111", "6959@687kyp.com", new Date(), "1"));
        userList.add(new User(4, "鲁班大师", "11111", "fa57@196bmfgq.com.cn", new Date(), "1"));
        userList.add(new User(5, "安其拉", "111111", "88ac@o23wg.com", new Date(), "1"));

        Map<String, Object> map = new HashMap<>();
        try {
            userService.addList(userList);
        } catch (Exception e) {
            e.printStackTrace();
            map.put("fali", false);
            map.put("message", "用户注册失败" + e.getMessage());
            return R.error().data(map);
        }
        map.put("success", true);
        map.put("message", "用户注册成功");
        return R.ok().data(map);
    }
}
  1. 添加 dao 层 的 Mapper 以及 xml 实现
java 复制代码
package com.codervibe.mapper;

import com.codervibe.model.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;

import java.util.List;

@Mapper
@Component
public interface UserMapper {
    /**
     * 查询所有用户信息
     * @return
     */
    List<User> selectUserAll();
    /**
     * 添加用户信息列表
     * @return  boolean
     */
    boolean addList(User user);
}
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.codervibe.mapper.UserMapper">
    <insert id="addList" parameterType="com.codervibe.model.User" useGeneratedKeys="true" keyProperty="id">
        insert into user(username,password,email,createTime,role) values (#{username}, #{password},#{email}, #{createTime}, #{role})
    </insert>
    <select id="selectUserAll" resultType="com.codervibe.model.User" >
        select * from user
    </select>
</mapper>
  1. 此时启动 就应用就会报错 这是因为 由于分模块导致没有扫描到其他包 需要在启动类上添加 注解 以扩大 扫描范围
java 复制代码
package com.codervibe.web;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackages = {"com.codervibe"})
@MapperScan({"com.codervibe.mapper"})
public class WebApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }

}
  1. 代码中用到的自定义返回类型
java 复制代码
package com.codervibe.web.common.response;

import lombok.Data;

import java.util.HashMap;
import java.util.Map;

@Data
public class R {
    private Boolean success;
    private Integer code;
    private String message;
    private Map<String, Object> data = new HashMap<>();

    // 构造器私有
    private R() {
    }

    // 通用返回成功
    public static R ok() {
        R r = new R();
        r.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
        r.setCode(ResultCodeEnum.SUCCESS.getCode());
        r.setMessage(ResultCodeEnum.SUCCESS.getMessage());
        return r;
    }

    // 通用返回失败,未知错误
    public static R error() {
        R r = new R();
        r.setSuccess(ResultCodeEnum.UNKNOWN_ERROR.getSuccess());
        r.setCode(ResultCodeEnum.UNKNOWN_ERROR.getCode());
        r.setMessage(ResultCodeEnum.UNKNOWN_ERROR.getMessage());
        return r;
    }

    // 设置结果,形参为结果枚举
    public static R setResult(ResultCodeEnum result) {
        R r = new R();
        r.setSuccess(result.getSuccess());
        r.setCode(result.getCode());
        r.setMessage(result.getMessage());
        return r;
    }

    /**
     * ------------使用链式编程,返回类本身-----------
     **/

    // 自定义返回数据
    public R data(Map<String, Object> map) {
        this.setData(map);
        return this;
    }

    // 通用设置data
    public R data(String key, Object value) {
        this.data.put(key, value);
        return this;
    }

    // 自定义状态信息
    public R message(String message) {
        this.setMessage(message);
        return this;
    }

    // 自定义状态码
    public R code(Integer code) {
        this.setCode(code);
        return this;
    }

    // 自定义返回结果
    public R success(Boolean success) {
        this.setSuccess(success);
        return this;
    }

}
java 复制代码
package com.codervibe.web.common.response;

import lombok.Getter;

@Getter
public enum ResultCodeEnum {
    SUCCESS(true,20000,"成功"),
    UNKNOWN_ERROR(false,20001,"未知错误"),
    PARAM_ERROR(false,20002,"参数错误"),
    NULL_POINT(false,20003,"空指针错误"),
    HTTP_CLIENT_ERROR(false,20004,"客户端错误")
    ;
    private  Boolean success;
    private  Integer code;
    private  String message;
    ResultCodeEnum(boolean success,Integer code,String message){
        this.success =success;
        this.code = code;
        this.message =message;
    }
}