如何基于|如何基于 Docker 快速搭建 Springboot + Mysql + Redis 项目
[TOC]
前言
有时候我们需要快速启动一些项目,但是环境往往折腾了好久,因此弄一个可以重用的快速搭建的教程,docker
简直就是这方面的神器,Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。
本教程基于的前提条件:
- 机器已经安装配置好
JDK1.8
,并且环境变量已经配置成功 Maven
已经配置好,IDEA
中项目使用的默认Maven
也配置成功- 本地机器安装好
Docker
- 顺便提一句,我用
navicat
作为数据库可视化操作工具
项目目录
├── src :源代码
|├── main
||├── java
|||├── com.aphysia.springbootdemo
||||├── config:配置
|||||├── RedisConfig:redis配置
||||├── constant:常量
|||||├── RedisConfig:redis常量
||||├── controller:控制器
||||├── mapper:数据库操作接口
||||├── model:实体类
||||├── service:逻辑处理层,包括接口以及实现类
|||||├── impl:接口实现类
||||├──util:工具类
|||||├── RedisUtil:redis工具类
||||├──SpringdemoApplication:启动类
||├── resource
|||├── mapper 数据库操作sql
|||├── application.yml:全局配置类
|||├── user.sql: 初始化mysql
|├──test: 测试类
├── pom.xml :项目maven依赖关系
整体的目录如下:
文章图片
搭建项目 1. docker安装启动mysql以及redis
1.1 安装mysql 查询
mysql
最新的镜像:docker search mysql
拉取最新的
mysql
版本docker pull mysql:latest
启动
mysql
,用户名root
,密码123456
docker run -itd --name mysql-test -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
可以通过
docker ps
查看是否安装成功% docker ps
CONTAINER IDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
574d30f17868mysql"docker-entrypoint.s…"14 months agoUp 2 days0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql-test
文章图片
1.2 安装redis 查询
redis
的镜像docker search redis
拉取
redis
的最新镜像% docker pull redis:latest
latest: Pulling from library/redis
eff15d958d66: Pull complete
1aca8391092b: Pull complete
06e460b3ba1b: Pull complete
def49df025c0: Pull complete
646c72a19e83: Pull complete
db2c789841df: Pull complete
Digest: sha256:619af14d3a95c30759a1978da1b2ce375504f1af70ff9eea2a8e35febc45d747
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
docker images
可以查看我们安装了哪些镜像,可以看到其实我之前也安装过redis
的镜像:% docker images
REPOSITORYTAGIMAGE IDCREATEDSIZE
redislatest40c68ed3a4d23 days ago113MB
redis84c5f6e03bf014 months ago104MB
mysqllateste1d7dc9731da14 months ago544MB
docker/getting-startedlatest1f32459ef03816 months ago26.8MB
让我们启动一下
redis
的容器:% docker run -itd --name redis-test -p 6379:6379 redis
7267e14faf93a0e416c39eeaaf51705dc4b6dc3507a68733c20a2609ade6dcd6
可以看到
docker
里面现在有redis
和mysql
两个容器在跑了:文章图片
2. 初始化数据库
主要是创建数据库以及测试使用的数据表,初始化数据库的语句:
drop database IF EXISTS test;
CREATE DATABASE test;
use test;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT "",
`age` int(11) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES (1, '李四', 11);
INSERT INTO `user` VALUES (2, '王五', 11);
初始化数据如下:
文章图片
3.创建项目
在IDEA中,File --> New --> Project --> Spring Initializr(选择JDK 8):
文章图片
点击
Next
:文章图片
选择
Web
下面的Spring Web
,SQL
下面的 JDBC API
,Mybatis
,NoSQL
下的Redis
,也可以不选,直接在pom
文件里自己加入即可:文章图片
一路点
Next
,最后Finish
,创建好之后,记得更新一下Maven
,安装依赖包。4.初始化代码
4.1 全局配置文件以及启动类 全局配置文件
application.yml
:server:
port: 8081
spring:
#数据库连接配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&useSSL=false
username: root
password: 123456
redis:
host: 127.0.0.1## redis所在的服务器IP
port: 6379
##密码,我这里没有设置,所以不填
password:
## 设置最大连接数,0为无限
pool:
max-active: 8
min-idle: 0
max-idle: 8
max-wait: -1
#mybatis的相关配置
mybatis:
#mapper配置文件
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.aphysia.spingbootdemo.model
#开启驼峰命名
configuration:
map-underscore-to-camel-case: true
logging:
level:
root: debug
启动类
SpringdemoApplication
:import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.aphysia.springdemo.mapper")
public class SpringdemoApplication {public static void main(String[] args) {
SpringApplication.run(SpringdemoApplication.class, args);
}}
4.2 实体类 与数据库中user表对应的实体类
User.java
:package com.aphysia.springdemo.model;
public class User {
int id;
String name;
int age;
public int getId() {
return id;
}public void setId(int id) {
this.id = id;
}public String getName() {
return name;
}public void setName(String name) {
this.name = name;
}public int getAge() {
return age;
}public void setAge(int age) {
this.age = age;
}
}
4.3 Redis工具类
Redis
配置类RedisConfig
:package com.aphysia.springdemo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {@Autowired
private RedisTemplate redisTemplate;
@Bean
public RedisTemplate redisTemplateInit() {
//设置序列化Key的实例化对象
redisTemplate.setKeySerializer(new StringRedisSerializer());
//设置序列化Value的实例化对象
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
}
Redis
常量类 RedisConstant
:package com.aphysia.springdemo.constant;
public class RedisConstant {
public static String ALL_USER_KEY = "allUser";
}
Redis
工具类 RedisUtil
:package com.aphysia.springdemo.util;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
@Component
public class RedisUtil {
@Resource
private RedisTemplate redisTemplate;
public void setRedisTemplate(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}/**
* 指定缓存失效时间
*
* @param key键
* @param time 时间(秒)
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete((Collection) CollectionUtils.arrayToList(key));
}
}
}//============================String=============================/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}/**
* 普通缓存放入
*
* @param key键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}}/**
* 普通缓存放入并设置时间
*
* @param key键
* @param value 值
* @param time时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}/**
* 递增
*
* @param key键
* @param delta 要增加几(大于0)
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}/**
* 递减
*
* @param key键
* @param delta 要减少几(小于0)
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}//================================Map=================================/**
* HashGet
*
* @param key键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public Map
4.4 Mysql 数据库操作 数据库的
sql
文件UserMapper.xml
SELECT * FROM user
update user set age=age+1 where id =#{id}
【如何基于|如何基于 Docker 快速搭建 Springboot + Mysql + Redis 项目】对应的
mapper
接口UserMapper.java
package com.aphysia.springdemo.mapper;
import com.aphysia.springdemo.model.User;
import java.util.List;
public interface UserMapper {
List getAllUsers();
int updateUserAge(Integer id);
}
4.5 Service层 先定义一个操作
User
的接口类UserService
,包含两个方法,查询所有的user
以及更新user
的年龄:package com.aphysia.springdemo.service;
import com.aphysia.springdemo.model.User;
import java.util.List;
public interface UserService {
public List getAllUsers();
public void updateUserAge();
}
接口实现类
UserServiceImpl
,为了证实Redis可用,我们查询所有的用户的时候,加入了Redis缓存,优先从Redis中加载数据:package com.aphysia.springdemo.service.impl;
import com.aphysia.springdemo.constant.RedisConstant;
import com.aphysia.springdemo.mapper.UserMapper;
import com.aphysia.springdemo.model.User;
import com.aphysia.springdemo.service.UserService;
import com.aphysia.springdemo.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
@Service("userService")
public class UserServiceImpl implements UserService {@Resource
UserMapper userMapper;
@Autowired
RedisUtil redisUtil;
@Override
public List getAllUsers() {
List users = (List) redisUtil.get(RedisConstant.ALL_USER_KEY);
if(CollectionUtils.isEmpty(users)){
users = userMapper.getAllUsers();
redisUtil.set(RedisConstant.ALL_USER_KEY,users);
}
return users;
}@Override
@Transactional
public void updateUserAge() {
redisUtil.del(RedisConstant.ALL_USER_KEY);
userMapper.updateUserAge(1);
userMapper.updateUserAge(2);
}
}
4.6 Controller 控制层 增加一个测试层
TestController
:package com.aphysia.springdemo.controller;
import com.aphysia.springdemo.model.User;
import com.aphysia.springdemo.service.UserService;
import com.aphysia.springdemo.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
public class TestController {@Autowired
UserService userService;
@RequestMapping("/getUserList")
@ResponseBody
public List getUserList() {
return userService.getAllUsers();
}@RequestMapping("/update")
@ResponseBody
public int update() {
userService.updateUserAge();
return 1;
}
}
4.7 pom依赖
4.0.0 org.springframework.boot
spring-boot-starter-parent
2.5.6
com.aphysia
springdemo
0.0.1-SNAPSHOT
springdemo
Demo project for Spring Boot 1.8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
mysql
mysql-connector-java
runtime
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.0
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-maven-plugin
测试 启动项目,输入链接:http://localhost:8081/getUser...,可以获取到所有的
user
:文章图片
我们更新一下所有的用户年龄,调用
http://localhost:8081/update
,返回1
文章图片
再次访问
http://localhost:8081/getUserList
,可以看到年龄全部都变成12
:文章图片
怎么知道
Redis
生效了呢?最好就是debug
,或者直接看控制台,我们已经开启了debug
级别的日志:文章图片
还有一种方式,下载
Redis-desktop-manager
,可以直接可视化查看:文章图片
至此,一个
demo
项目就完成了,可以每次copy
出来初始化使用。【作者简介】:
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使缓慢,驰而不息。个人写作方向:
Java源码解析
,JDBC
,Mybatis
,Spring
,redis
,分布式
,剑指Offer
,LeetCode
等,认真写好每一篇文章,不喜欢标题党,不喜欢花里胡哨,大多写系列文章,不能保证我写的都完全正确,但是我保证所写的均经过实践或者查找资料。遗漏或者错误之处,还望指正。剑指Offer全部题解PDF
2020年我写了什么?
开源编程笔记
推荐阅读
- Docker应用:容器间通信与Mariadb数据库主从复制
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- 如何寻找情感问答App的分析切入点
- 基于微信小程序带后端ssm接口小区物业管理平台设计
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus使用queryWrapper如何实现复杂查询
- 基于|基于 antd 风格的 element-table + pagination 的二次封装
- 如何在Mac中的文件选择框中打开系统隐藏文件夹
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- java中如何实现重建二叉树