SpringBoot(MyBatisPlus+Druid+Thymeleaf实现CRUD)

整个工程文件结构

在这里插入图片描述

核心步骤

我们把核心步骤分为环境搭建和功能实现两部分
环境搭建
1、创建maven项目
2、pom.xml中添加所需依赖
3、编写SpringBoot的核心配置文件(在其中配置数据源和mapper核心文件的位置)
4、编写MyBatisPlus配置类(扫描mapper接口所在的包,将其加入容器)
5、编写SpringMVC的配置类(配置主页)
6、编写SpringBoot的启动类


功能实现
主要就是三层架构的搭建
1、编写前端控制器的代码,完成请求的匹配
2、实现Service层代码
3、Service调用了mapper接口,编写mapper.xml中对数据库进行的crud操作
4、编写前端页面(请求页面 & 返回页面)



具体实现

基本环境搭建

  • 创建maven工程
    使用命令创建maven工程即可

  • pom.xml中添加所需依赖

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>
  • 编写SpringBoot的核心配置文件(在其中配置数据源和mapper核心文件的位置)
spring:
  # 配置视图解析器
  thymeleaf:
    prefix: classpath:/templates/views/
    suffix: .html
  # 配置数据源
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://192.168.200.100:3306/ssm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
      username: root
      password: ******

mybatis-plus:
  # 配置mapper路径
  mapper-locations: classpath*:/mapper/*.xml
  # 配置model所在的路径
  type-aliases-package: com.dean.model
  • 编写MyBatisPlus配置类(扫描mapper接口所在的包,将其加入容器)
@Configuration
@MapperScan("com.dean.mapper")
public class MybatisConfig {
}
  • 编写SpringMVC的配置类(配置主页)
@Configuration
public class WebConfig implements WebMvcConfigurer {

    //配置主页
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
    }
}

  • 编写SpringBoot的启动类
@SpringBootApplication
public class InitApplication {
    public static void main(String[] args) {
        SpringApplication.run(InitApplication.class,args);
    }
}

写到这里可以测试一下:确保数据库等链接正确
如果连接正确,控制台的输出信息中将含有以下语句
在这里插入图片描述

具体实现

  • 编写前端控制器的代码,完成请求的匹配
    controller层代码如下所示:
@Controller
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService;

    //功能1:查询所有用户
    //请求url:/user/list
    //返回视图:user.html
    @RequestMapping("/list")
    public String findAll(Model model) throws Exception {
        List<User> users=userService.findAll();
       // users.forEach(System.out::println);
        model.addAttribute("users",users);
        return "user";
    }

    //功能2:新增用户
    //请求url:/user/add
    //返回视图:user.html
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    public String addUser(User user) throws Exception{
        user.setId(UUID.randomUUID().toString());
        userService.addUser(user);
        return "redirect:/user/list";   //重定向到findAll函数
    }

    //功能3:修改用户
    //step1:
    //  根据用户id查询用户
    //  请求url:/user/findById (ajax请求,无返回视图)
    @RequestMapping("findById")
    @ResponseBody
    public User findById(String id) throws Exception
    {
        User user=userService.findById(id);
        return user;
    }
    //step2:
    //  动态更新用户信息
    //  请求url:/user/update
    //  返回视图:user.html
    @RequestMapping(value = "update",method = RequestMethod.POST)
    public String updateUser(User user) throws Exception
    {
        userService.updateUser(user);
        return "redirect:/user/list";
    }

    //功能4:删除用户
    //请求url:/user/del?id=xxxxx
    //返回视图:user.html
    @RequestMapping("del")
    public String deleteById(String id) throws Exception {
        userService.deleteById(id);
        return "redirect:/user/list";
    }
}
  • 2、实现Service层代码
    service层代码如下所示
@Service
public class UserServiceIm implements UserService {
    @Resource
    private UserMapper mapper;
    //功能1:查询所有
    @Override
    public List<User> findAll() throws Exception {
        return mapper.findAll();
    }

    //功能2:新增用户
    @Override
    public void addUser(User user) throws Exception {
        mapper.addUser(user);
    }

    //功能3:更新用户
    //  step1:根据id查询需要更改的用户
    @Override
    public User findById(String id) throws Exception {
        return mapper.findById(id);
    }
    //  step2:更新用户数据
    @Override
    public void updateUser(User user) throws Exception {
        mapper.updateUser(user);
    }

    //功能4:根据id删除用户
    @Override
    public void deleteById(String id) throws Exception {
        mapper.deleteById(id);
    }
}

  • 3、Service调用了mapper接口,编写mapper.xml中对数据库进行的crud操作
    Mapper接口代码如下:
public interface UserMapper {
    List<User> findAll();

    void addUser(User user);

    User findById(String id);

    void updateUser(User user);

    void deleteById(String id);
}

Mapper的核心文件Mapper.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.dean.mapper.UserMapper">
    <resultMap id="baseMap" type="com.dean.model.User">
        <id property="id" column="ID"></id>
        <result property="name" column="NAME"></result>
        <result property="age" column="AGE"></result>
        <result property="birth" column="BIRTH"></result>
    </resultMap>

    <!--功能1: 查询所有-->
    <select id="findAll" resultMap="baseMap">
        select * from t_user
    </select>

    <!--功能2:新增用户-->
    <insert id="addUser" parameterType="com.dean.model.User">
        insert into t_user
        values
        (#{id},#{name},#{age},#{birth})
    </insert>

    <!--功能3:更新用户(step1:根据id查找用户)-->
    <select id="findById" resultMap="baseMap" parameterType="string">
        select * from t_user
        where
        id=#{id}
    </select>
    <!--功能3:更新用户(step2:动态更新用户信息)-->
    <update id="updateUser" parameterType="com.dean.model.User">
        update t_user
        <set>
            <if test="name!=null">
                name=#{name},
            </if>
            <if test="age!=null">
                age=#{age},
            </if>
            <if test="birth!=null">
                birth=#{birth},
            </if>
        </set>
        where id=#{id}
    </update>

    <!--功能4:根据id删除用户-->
    <delete id="deleteById" parameterType="string">
        delete from t_user
        where id=#{id}
    </delete>
</mapper>
  • 4、编写前端页面(请求页面 & 返回页面)
    因为在前端页面中用到了jquery,所以需要去yml文件中配置一下静态资源路径
    在这里插入图片描述
    请求页面(主页)
<!DOCTYPE html>
<!--Thymeleaf的头部标签-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<p>
    <h1> <a th:href="@{/user/list}">findAll</a> </h1>
</p>
</body>
</html>

返回页面(user.html)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .tab{
            width:500px;
            margin: 100px auto;
            text-align: center;
        }
        .tab td{
            border-bottom: 3px solid black;
            padding: 5px 0;
        }
    </style>
    <script th:src="@{/static/jquery-2.1.1.js}"></script>
</head>
<body>
<h1 align="center">用户数据:</h1>
<!--查询所有用户生成的表格-->
<table class="tab">
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Age</th>
            <th>Birth</th>
        </tr>
    </thead>
    <tbody th:each="its,iterStat:${users}">
        <tr>
            <td th:text="${its.id}"></td>
            <td th:text="${its.name}"></td>
            <td th:text="${its.age}"></td>
            <td th:text="${its.birth}"></td>
            <td>
                <button th:onclick="findById([[${its.id}]])">find</button>
            </td>
            <td>
                <a th:href="@{/user/del(id=${its.id})}">del</a>
            </td>
        </tr>
    </tbody>
</table>
<!--form表单新增用户-->
<hr>
<div class="addUser">
    <form th:action="@{/user/add}" method="post">
        <p>
            <label for="name">Name:</label>
            <input type="text" id="name" name="name">
        </p>
        <p>
            <label for="age">Age:</label>
            <input type="number" id="age" name="age">
        </p>
        <p>
            <label for="birth">Birth:</label>
            <input type="date" id="birth" name="birth">
        </p>
        <p>
            <input type="submit" value="add">
        </p>
    </form>
</div>
<!--功能3:修改用户-->
<hr>
<div class="updateUser">
    <form th:action="@{/user/update}" method="post">
        <p>
<!--            <input type="hidden" class="user-id" name="id"> &lt;!&ndash;隐藏域 在页面上看不见&ndash;&gt;-->
            <input type="text" class="user-id" readonly name="id" style="color: gray">
            <input type="text" class="user-name" name="name">
            <input type="number" class="user-age" name="age">
            <input type="date" class="user-birth" name="birth">
            <input type="submit" value="update">
        </p>
    </form>
</div>
<script>
    function findById(id) {
        $.getJSON(
            "/user/findById?id="+id,
            function (data) {
                $(".updateUser .user-id").val(data.id)
                $(".updateUser .user-name").val(data.name)
                $(".updateUser .user-age").val(data.age)
                $(".updateUser .user-birth").val(data.birth)
            }
        )
    }
</script>
</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现读写分离可以利用 SpringBootMybatisPlus 和 Druid 进行配置。下面是一个简单的实现过程: 1. 添加 MybatisPlus 和 Druid 的 Maven 依赖。 ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency> ``` 2. 在配置文件中添加 Druid 数据源相关配置。 ```yaml spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/db_name?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource druid: initialSize: 5 maxActive: 10 minIdle: 5 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 filters: stat,wall,log4j connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 ``` 3. 配置 MybatisPlus 的多数据源功能。 ```java @Configuration public class DataSourceConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource.master") public DataSource masterDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix = "spring.datasource.slave") public DataSource slaveDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean public DynamicDataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource, @Qualifier("slaveDataSource") DataSource slaveDataSource) { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceType.MASTER.getType(), masterDataSource); targetDataSources.put(DataSourceType.SLAVE.getType(), slaveDataSource); return new DynamicDataSource(masterDataSource, targetDataSources); } } ``` 4. 创建一个 DataSourceHolder 类,用于保存当前线程的数据源类型。 ```java public class DataSourceHolder { private static final ThreadLocal<String> HOLDER = new ThreadLocal<>(); public static String getDataSource() { return HOLDER.get(); } public static void setDataSource(String dataSource) { HOLDER.set(dataSource); } public static void clearDataSource() { HOLDER.remove(); } } ``` 5. 创建一个枚举类型 DataSourceType,用于表示数据源类型。 ```java public enum DataSourceType { MASTER("master"), SLAVE("slave"); private final String type; DataSourceType(String type) { this.type = type; } public String getType() { return type; } } ``` 6. 创建一个 DynamicDataSource 类,继承 AbstractRoutingDataSource,用于动态切换数据源。 ```java public class DynamicDataSource extends AbstractRoutingDataSource { private final Map<Object, Object> targetDataSources; public DynamicDataSource(DataSource defaultDataSource, Map<Object, Object> targetDataSources) { super.setDefaultTargetDataSource(defaultDataSource); this.targetDataSources = targetDataSources; super.setTargetDataSources(targetDataSources); super.afterPropertiesSet(); } @Override protected Object determineCurrentLookupKey() { return DataSourceHolder.getDataSource(); } @Override public void setTargetDataSources(Map<Object, Object> targetDataSources) { this.targetDataSources.putAll(targetDataSources); super.setTargetDataSources(this.targetDataSources); super.afterPropertiesSet(); } @Override public void addTargetDataSource(Object key, Object dataSource) { this.targetDataSources.put(key, dataSource); super.setTargetDataSources(this.targetDataSources); super.afterPropertiesSet(); } } ``` 7. 创建一个 AopDataSourceConfig 类,用于配置切面,实现动态切换数据源。 ```java @Configuration public class AopDataSourceConfig { @Bean public DataSourceAspect dataSourceAspect() { return new DataSourceAspect(); } } ``` ```java @Aspect public class DataSourceAspect { @Pointcut("@annotation(com.example.demo.annotation.Master) " + "|| execution(* com.example.demo.service..*.select*(..)) " + "|| execution(* com.example.demo.service..*.get*(..)) " + "|| execution(* com.example.demo.service..*.query*(..)) " + "|| execution(* com.example.demo.service..*.find*(..)) " + "|| execution(* com.example.demo.service..*.count*(..))") public void read() { } @Pointcut("execution(* com.example.demo.service..*.insert*(..)) " + "|| execution(* com.example.demo.service..*.update*(..)) " + "|| execution(* com.example.demo.service..*.delete*(..))") public void write() { } @Around("read()") public Object read(ProceedingJoinPoint joinPoint) throws Throwable { try { DataSourceHolder.setDataSource(DataSourceType.SLAVE.getType()); return joinPoint.proceed(); } finally { DataSourceHolder.clearDataSource(); } } @Around("write()") public Object write(ProceedingJoinPoint joinPoint) throws Throwable { try { DataSourceHolder.setDataSource(DataSourceType.MASTER.getType()); return joinPoint.proceed(); } finally { DataSourceHolder.clearDataSource(); } } } ``` 8. 在 Service 层的方法上使用 @Master 注解,表示强制使用主库。 ```java @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Override @Master public boolean save(User user) { return super.save(user); } } ``` 这样就实现了读写分离功能。需要注意的是,在使用 MybatisPlus 进行 CRUD 操作时,需要使用对应的 Service 方法,例如 selectList、selectPage、insert、updateById、deleteById,而不是直接调用 Mapper 方法。否则,数据源切换将不会生效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值