Spring Boot + MyBatis + Druid + Redis + Thymeleaf 整合小结

2023-06-02,,

Spring Boot + MyBatis + Druid + Redis + Thymeleaf 整合小结

这两天闲着没事想利用**Spring Boot**加上阿里的开源数据连接池**Druid**搭建个简单的框架,主要是想了解一下**Druid**的可视化数据监控,无奈水平受限只能一边 Google 一边 整合,后来发现网上的一些整合资源太差强人意,于是我想把我得一些整合思路分享出来,供大家浏览,哪里不合适希望可以提出来,一起进步!

特别感谢一下我的朋友 [@码农界的苦逼猿](https://blog.csdn.net/qq_38011415)

开始

环境:jdk1.8,idea, maven 3.5.0

1、项目结构:

2、pom.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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>org.yliu</groupId>
<artifactId>mui</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>mui</name>
<description>org.yliu.mui</description> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/>
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</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>1.3.2</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.4</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

到了这一步,项目的基本依赖就算结束了。

3、在这个Demo项目中我用的是application.properties,可根据个人喜好改为application.yml

# 访问端口
server.port=2088 # 数据库配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.name=demo
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.initialSize=1
spring.datasource.minIdle=3
spring.datasource.maxActive=20
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=30000
spring.datasource.validationQuery=select 'x'
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.filters=stat,wall,slf4j
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.useGlobalDataSourceStat=true # redis 配置
spring.redis.port=6379
spring.redis.host=127.0.0.1
spring.redis.password=123456 # thymeleaf 配置
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
spring.thymeleaf.check-template-location=true
spring.thymeleaf.encoding=UTF-8 # 日志相关
logging.pattern.console=%d --> %msg%n
# 此处配置sql打印
logging.pattern.level=org.yliu.mui.mapper: debug

4、数据库创建sql我就不放出来了,可随意创建数据进行测试

5、创建好表数据 可以使用 mybatis generator 自动生成代码,

  假设我有一张 **User** 表,那么生成的相关文件为:

对应数据库的实体:

package org.yliu.mui.pojo.po;

import java.util.Date;

public class MallUserPo {
private Integer id; private String guid; private String avatars; private String openId; private String userName; private Integer sex; private String phone; private String targetPhone; private Date createTime; private Date updateTime; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getGuid() {
return guid;
} public void setGuid(String guid) {
this.guid = guid == null ? null : guid.trim();
} public String getAvatars() {
return avatars;
} public void setAvatars(String avatars) {
this.avatars = avatars == null ? null : avatars.trim();
} public String getOpenId() {
return openId;
} public void setOpenId(String openId) {
this.openId = openId == null ? null : openId.trim();
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName == null ? null : userName.trim();
} public Integer getSex() {
return sex;
} public void setSex(Integer sex) {
this.sex = sex;
} public String getPhone() {
return phone;
} public void setPhone(String phone) {
this.phone = phone == null ? null : phone.trim();
} public String getTargetPhone() {
return targetPhone;
} public void setTargetPhone(String targetPhone) {
this.targetPhone = targetPhone == null ? null : targetPhone.trim();
} public Date getCreateTime() {
return createTime;
} public void setCreateTime(Date createTime) {
this.createTime = createTime;
} public Date getUpdateTime() {
return updateTime;
} public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

持久层接口:

package org.yliu.mui.mapper;

import org.yliu.mui.pojo.po.MallUserPo;
import org.yliu.mui.pojo.po.MallUserPoExample;
import java.util.List;
import org.apache.ibatis.annotations.Param; public interface MallUserPoMapper {
int countByExample(MallUserPoExample example); int deleteByExample(MallUserPoExample example); int deleteByPrimaryKey(Integer id); int insert(MallUserPo record); int insertSelective(MallUserPo record); List<MallUserPo> selectByExample(MallUserPoExample example); MallUserPo selectByPrimaryKey(Integer id); int updateByExampleSelective(@Param("record") MallUserPo record, @Param("example") MallUserPoExample example); int updateByExample(@Param("record") MallUserPo record, @Param("example") MallUserPoExample example); int updateByPrimaryKeySelective(MallUserPo record); int updateByPrimaryKey(MallUserPo record);
}

映射文件:

<?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="org.yliu.mui.mapper.MallUserPoMapper" >
<resultMap id="BaseResultMap" type="org.yliu.mui.pojo.po.MallUserPo" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="guid" property="guid" jdbcType="VARCHAR" />
<result column="avatars" property="avatars" jdbcType="VARCHAR" />
<result column="open_id" property="openId" jdbcType="VARCHAR" />
<result column="user_name" property="userName" jdbcType="VARCHAR" />
<result column="sex" property="sex" jdbcType="INTEGER" />
<result column="phone" property="phone" jdbcType="VARCHAR" />
<result column="target_phone" property="targetPhone" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
</resultMap>
<sql id="Example_Where_Clause" >
<where >
<foreach collection="oredCriteria" item="criteria" separator="or" >
<if test="criteria.valid" >
<trim prefix="(" suffix=")" prefixOverrides="and" >
<foreach collection="criteria.criteria" item="criterion" >
<choose >
<when test="criterion.noValue" >
and ${criterion.condition}
</when>
<when test="criterion.singleValue" >
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue" >
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue" >
and ${criterion.condition}
<foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," >
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause" >
<where >
<foreach collection="example.oredCriteria" item="criteria" separator="or" >
<if test="criteria.valid" >
<trim prefix="(" suffix=")" prefixOverrides="and" >
<foreach collection="criteria.criteria" item="criterion" >
<choose >
<when test="criterion.noValue" >
and ${criterion.condition}
</when>
<when test="criterion.singleValue" >
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue" >
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue" >
and ${criterion.condition}
<foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," >
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List" >
id, guid, avatars, open_id, user_name, sex, phone, target_phone, create_time, update_time
</sql>
<select id="selectByExample" resultMap="BaseResultMap" parameterType="org.yliu.mui.pojo.po.MallUserPoExample" >
select
<if test="distinct" >
distinct
</if>
<include refid="Base_Column_List" />
from mall_user
<if test="_parameter != null" >
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null" >
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from mall_user
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from mall_user
where id = #{id,jdbcType=INTEGER}
</delete>
<delete id="deleteByExample" parameterType="org.yliu.mui.pojo.po.MallUserPoExample" >
delete from mall_user
<if test="_parameter != null" >
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="org.yliu.mui.pojo.po.MallUserPo" >
insert into mall_user (id, guid, avatars,
open_id, user_name, sex,
phone, target_phone, create_time,
update_time)
values (#{id,jdbcType=INTEGER}, #{guid,jdbcType=VARCHAR}, #{avatars,jdbcType=VARCHAR},
#{openId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}, #{sex,jdbcType=INTEGER},
#{phone,jdbcType=VARCHAR}, #{targetPhone,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP},
#{updateTime,jdbcType=TIMESTAMP})
</insert>
<insert id="insertSelective" parameterType="org.yliu.mui.pojo.po.MallUserPo" >
insert into mall_user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="guid != null" >
guid,
</if>
<if test="avatars != null" >
avatars,
</if>
<if test="openId != null" >
open_id,
</if>
<if test="userName != null" >
user_name,
</if>
<if test="sex != null" >
sex,
</if>
<if test="phone != null" >
phone,
</if>
<if test="targetPhone != null" >
target_phone,
</if>
<if test="createTime != null" >
create_time,
</if>
<if test="updateTime != null" >
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="guid != null" >
#{guid,jdbcType=VARCHAR},
</if>
<if test="avatars != null" >
#{avatars,jdbcType=VARCHAR},
</if>
<if test="openId != null" >
#{openId,jdbcType=VARCHAR},
</if>
<if test="userName != null" >
#{userName,jdbcType=VARCHAR},
</if>
<if test="sex != null" >
#{sex,jdbcType=INTEGER},
</if>
<if test="phone != null" >
#{phone,jdbcType=VARCHAR},
</if>
<if test="targetPhone != null" >
#{targetPhone,jdbcType=VARCHAR},
</if>
<if test="createTime != null" >
#{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null" >
#{updateTime,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="org.yliu.mui.pojo.po.MallUserPoExample" resultType="java.lang.Integer" >
select count(*) from mall_user
<if test="_parameter != null" >
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map" >
update mall_user
<set >
<if test="record.id != null" >
id = #{record.id,jdbcType=INTEGER},
</if>
<if test="record.guid != null" >
guid = #{record.guid,jdbcType=VARCHAR},
</if>
<if test="record.avatars != null" >
avatars = #{record.avatars,jdbcType=VARCHAR},
</if>
<if test="record.openId != null" >
open_id = #{record.openId,jdbcType=VARCHAR},
</if>
<if test="record.userName != null" >
user_name = #{record.userName,jdbcType=VARCHAR},
</if>
<if test="record.sex != null" >
sex = #{record.sex,jdbcType=INTEGER},
</if>
<if test="record.phone != null" >
phone = #{record.phone,jdbcType=VARCHAR},
</if>
<if test="record.targetPhone != null" >
target_phone = #{record.targetPhone,jdbcType=VARCHAR},
</if>
<if test="record.createTime != null" >
create_time = #{record.createTime,jdbcType=TIMESTAMP},
</if>
<if test="record.updateTime != null" >
update_time = #{record.updateTime,jdbcType=TIMESTAMP},
</if>
</set>
<if test="_parameter != null" >
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map" >
update mall_user
set id = #{record.id,jdbcType=INTEGER},
guid = #{record.guid,jdbcType=VARCHAR},
avatars = #{record.avatars,jdbcType=VARCHAR},
open_id = #{record.openId,jdbcType=VARCHAR},
user_name = #{record.userName,jdbcType=VARCHAR},
sex = #{record.sex,jdbcType=INTEGER},
phone = #{record.phone,jdbcType=VARCHAR},
target_phone = #{record.targetPhone,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=TIMESTAMP},
update_time = #{record.updateTime,jdbcType=TIMESTAMP}
<if test="_parameter != null" >
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="org.yliu.mui.pojo.po.MallUserPo" >
update mall_user
<set >
<if test="guid != null" >
guid = #{guid,jdbcType=VARCHAR},
</if>
<if test="avatars != null" >
avatars = #{avatars,jdbcType=VARCHAR},
</if>
<if test="openId != null" >
open_id = #{openId,jdbcType=VARCHAR},
</if>
<if test="userName != null" >
user_name = #{userName,jdbcType=VARCHAR},
</if>
<if test="sex != null" >
sex = #{sex,jdbcType=INTEGER},
</if>
<if test="phone != null" >
phone = #{phone,jdbcType=VARCHAR},
</if>
<if test="targetPhone != null" >
target_phone = #{targetPhone,jdbcType=VARCHAR},
</if>
<if test="createTime != null" >
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null" >
update_time = #{updateTime,jdbcType=TIMESTAMP},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="org.yliu.mui.pojo.po.MallUserPo" >
update mall_user
set guid = #{guid,jdbcType=VARCHAR},
avatars = #{avatars,jdbcType=VARCHAR},
open_id = #{openId,jdbcType=VARCHAR},
user_name = #{userName,jdbcType=VARCHAR},
sex = #{sex,jdbcType=INTEGER},
phone = #{phone,jdbcType=VARCHAR},
target_phone = #{targetPhone,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=TIMESTAMP},
update_time = #{updateTime,jdbcType=TIMESTAMP}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>

到了这一步和MyBatis整合完成了一半了,下面完成下一半。

6、首先需要配置Druid连接池

package org.yliu.mui.config;

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import javax.servlet.Filter;
import javax.servlet.Servlet; /**
* Druid连接池配置
*/
@Configuration
public class DruidConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(DruidConfiguration.class); /**
* 访问路径及用户名、密码
*/
@Bean
public ServletRegistrationBean<Servlet> druidConfig() {
LOGGER.info("init Druid Servlet Configuration ");
final ServletRegistrationBean<Servlet> srb = new ServletRegistrationBean<Servlet>();
srb.setServlet(new StatViewServlet());
srb.addUrlMappings("/druid/*");
srb.addInitParameter("loginUsername", "admin");
srb.addInitParameter("loginPassword", "admin");
return srb;
} /**
* 配置过滤器
*/
@Bean
public FilterRegistrationBean filterRegistrationBean() {
final FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<Filter>();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}

7、配置完连接池,下面为持久层相关配置(分页插件也在此类配置)

package org.yliu.mui.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.yliu.mui.properties.DBProperties; import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties; /**
* 持久层相关配置
*/
@Configuration
public class SessionFactoryConfig { private static final Logger LOGGER = LoggerFactory.getLogger(SessionFactoryConfig.class); private final DBProperties db; @Autowired
public SessionFactoryConfig(DBProperties db) {
this.db = db;
} /**
* 创建数据源
*/
@Bean
@Primary
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(db.getUrl());
datasource.setUsername(db.getUsername());
datasource.setPassword(db.getPassword());
datasource.setDriverClassName(db.getDriverClassName());
datasource.setInitialSize(db.getInitialSize());
datasource.setMinIdle(db.getMinIdle());
datasource.setMaxActive(db.getMaxActive());
datasource.setMaxWait(db.getMaxWait());
datasource.setTimeBetweenEvictionRunsMillis(db.getTimeBetweenEvictionRunsMillis());
datasource.setMinEvictableIdleTimeMillis(db.getMinEvictableIdleTimeMillis());
datasource.setValidationQuery(db.getValidationQuery());
datasource.setTestOnReturn(db.isTestOnReturn());
datasource.setPoolPreparedStatements(db.isPoolPreparedStatements());
datasource.setMaxPoolPreparedStatementPerConnectionSize(db.getMaxPoolPreparedStatementPerConnectionSize());
datasource.setUseGlobalDataSourceStat(db.isUseGlobalDataSourceStat());
try {
datasource.setFilters(db.getFilters());
} catch (SQLException e) {
LOGGER.info("druid configuration initialization filter: " + e);
}
datasource.setConnectionProperties(db.getConnectionProperties());
return datasource;
} /**
* 配置分页插件
*/
@Bean(name = "pageInterceptor")
public PageInterceptor pageHelperConfig() {
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("reasonable", "true");
properties.setProperty("supportMethodsArguments", "true");
properties.setProperty("returnPageInfo", "check");
properties.setProperty("params", "count=countSql");
pageInterceptor.setProperties(properties);
return pageInterceptor;
} /**
* 配置mybatis
*/
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(
@Qualifier("dataSource") final DataSource dataSource,
@Qualifier("pageInterceptor") final PageInterceptor pageInterceptor) throws Exception {
final SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
sqlSessionFactory.setDataSource(dataSource);
final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
resolver.getResources("classpath*:mapper/**/*.xml");
sqlSessionFactory.setMapperLocations(resolver.getResources("classpath*:mapper/**/*.xml"));
// 具体参考自己设置,参考 xml 参数说明或源码注释
sqlSessionFactory.setPlugins(new Interceptor[]{pageInterceptor});
return sqlSessionFactory.getObject();
}
}

这里需要说明一下的是,DBProperties 类是对应 application.properties 配置文件中的数据库相关配置属性


DBProperties.java :

package org.yliu.mui.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource; @Configuration
@ConfigurationProperties(prefix = "spring.datasource")
public class DBProperties {
private String url;
private String username;
private String password;
private String driverClassName;
private int initialSize;
private int minIdle;
private int maxActive;
private int maxWait;
private int timeBetweenEvictionRunsMillis;
private int minEvictableIdleTimeMillis;
private String validationQuery;
private boolean testWhileIdle;
private boolean testOnBorrow;
private boolean testOnReturn;
private boolean poolPreparedStatements;
private int maxPoolPreparedStatementPerConnectionSize;
private String filters;
private String connectionProperties;
private boolean useGlobalDataSourceStat; public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getDriverClassName() {
return driverClassName;
} public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
} public int getInitialSize() {
return initialSize;
} public void setInitialSize(int initialSize) {
this.initialSize = initialSize;
} public int getMinIdle() {
return minIdle;
} public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
} public int getMaxActive() {
return maxActive;
} public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
} public int getMaxWait() {
return maxWait;
} public void setMaxWait(int maxWait) {
this.maxWait = maxWait;
} public int getTimeBetweenEvictionRunsMillis() {
return timeBetweenEvictionRunsMillis;
} public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
} public int getMinEvictableIdleTimeMillis() {
return minEvictableIdleTimeMillis;
} public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
} public String getValidationQuery() {
return validationQuery;
} public void setValidationQuery(String validationQuery) {
this.validationQuery = validationQuery;
} public boolean isTestWhileIdle() {
return testWhileIdle;
} public void setTestWhileIdle(boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
} public boolean isTestOnBorrow() {
return testOnBorrow;
} public void setTestOnBorrow(boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
} public boolean isTestOnReturn() {
return testOnReturn;
} public void setTestOnReturn(boolean testOnReturn) {
this.testOnReturn = testOnReturn;
} public boolean isPoolPreparedStatements() {
return poolPreparedStatements;
} public void setPoolPreparedStatements(boolean poolPreparedStatements) {
this.poolPreparedStatements = poolPreparedStatements;
} public int getMaxPoolPreparedStatementPerConnectionSize() {
return maxPoolPreparedStatementPerConnectionSize;
} public void setMaxPoolPreparedStatementPerConnectionSize(int maxPoolPreparedStatementPerConnectionSize) {
this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;
} public String getFilters() {
return filters;
} public void setFilters(String filters) {
this.filters = filters;
} public String getConnectionProperties() {
return connectionProperties;
} public void setConnectionProperties(String connectionProperties) {
this.connectionProperties = connectionProperties;
} public boolean isUseGlobalDataSourceStat() {
return useGlobalDataSourceStat;
} public void setUseGlobalDataSourceStat(boolean useGlobalDataSourceStat) {
this.useGlobalDataSourceStat = useGlobalDataSourceStat;
}
}

8、配置完这些,小伙伴不要心急,还有一项重要的配置,那就是扫描 mapper 接口!!!

package org.yliu.mui.config;

import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* 扫描Mybatis接口
*/
@Configuration
// 在持久层相关配置成功注入后加载
@AutoConfigureAfter(SessionFactoryConfig.class)
public class MyBatisMapperScannerConfig {
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
// 需要扫描的包路径
mapperScannerConfigurer.setBasePackage("org.yliu.mui.mapper");
return mapperScannerConfigurer;
}
}

如果不写扫描配置类,也可以在Spring Boot 入口类main方法上加入 @MapperScan("XX.XXX.mapper")注解进行扫描,个人习惯。

9、redis:(redis这里我没有选用 Spring 提供的 RedisTemplate,还是习惯 jedis )

package org.yliu.mui.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig; /**
* Redis配置
*/
@Configuration
// RedisProperties 为Spring内部默认提供的关于redis配置的属性绑定类
@AutoConfigureAfter(RedisProperties.class)
public class RedisConfig { private static final Logger LOGGER = LoggerFactory.getLogger(RedisConfig.class); private final RedisProperties redisProperties; @Autowired
public RedisConfig(RedisProperties redisProperties) {
this.redisProperties = redisProperties;
} @Bean
public JedisPool redisPoolFactory(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
int port = redisProperties.getPort();
String host = redisProperties.getHost();
int timeout = 2000;
String password = redisProperties.getPassword();
JedisPool jedisPool = new JedisPool(jedisPoolConfig,host,port,timeout,password);
LOGGER.info("JedisPool注入成功!");
LOGGER.info("redis地址:" + host + ":" + port);
return jedisPool;
} }

我封装了一个 JedisClient 的接口,方面操作和后期增加新命令。

package org.yliu.mui.redis;

import java.util.List;

public interface JedisClient {
String set(String key, String value); String get(String key); Boolean exists(String key); Long expire(String key, int seconds); Long ttl(String key); Long incr(String key); Long hset(String key, String field, String value); String hget(String key, String field); Long hdel(String key, String... field); Boolean hexists(String key, String field); List<String> hvals(String key); Long del(String key);
}

JedisClient 实现类

package org.yliu.mui.redis.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.yliu.mui.redis.JedisClient;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool; import java.util.List; /**
* Redis实现
*/
@Configuration
public class JedisClientPool implements JedisClient { private final JedisPool jedisPool; @Autowired
public JedisClientPool(JedisPool jedisPool) {
this.jedisPool = jedisPool;
} @Override
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String result = jedis.set(key, value);
jedis.close();
return result;
} @Override
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
} @Override
public Boolean exists(String key) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.exists(key);
jedis.close();
return result;
} @Override
public Long expire(String key, int seconds) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.expire(key, seconds);
jedis.close();
return result;
} @Override
public Long ttl(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.ttl(key);
jedis.close();
return result;
} @Override
public Long incr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.incr(key);
jedis.close();
return result;
} @Override
public Long hset(String key, String field, String value) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hset(key, field, value);
jedis.close();
return result;
} @Override
public String hget(String key, String field) {
Jedis jedis = jedisPool.getResource();
String result = jedis.hget(key, field);
jedis.close();
return result;
} @Override
public Long hdel(String key, String... field) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hdel(key, field);
jedis.close();
return result;
} @Override
public Boolean hexists(String key, String field) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.hexists(key, field);
jedis.close();
return result;
} @Override
public List<String> hvals(String key) {
Jedis jedis = jedisPool.getResource();
List<String> result = jedis.hvals(key);
jedis.close();
return result;
} @Override
public Long del(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.del(key);
jedis.close();
return result;
}
}

至此,整合完毕。。。

结果如何?

我分别贴上 ControllerUserServiceUserServiceImpl 这里不一一细说了。

Controller :

package org.yliu.mui.controller;

import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.yliu.mui.pojo.po.MallUserPo;
import org.yliu.mui.pojo.response.ResponseData;
import org.yliu.mui.service.MallUserService; @RestController
public class DemoController { private final MallUserService mallUserService; @Autowired
public DemoController(MallUserService userService) {
this.mallUserService = userService;
} @RequestMapping("/get/user/all")
ResponseData<PageInfo<MallUserPo>> getUserAll() {
return ResponseData.success("success", mallUserService.findAll());
}
}

UserService

package org.yliu.mui.service;

import com.github.pagehelper.PageInfo;
import org.yliu.mui.pojo.po.MallUserPo; public interface MallUserService {
// 使用分页插件提供的PageInfo包装一下结果集
PageInfo<MallUserPo> findAll();
}

UserServiceImpl :

package org.yliu.mui.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.yliu.mui.mapper.MallUserPoMapper;
import org.yliu.mui.pojo.po.MallUserPo;
import org.yliu.mui.pojo.po.MallUserPoExample;
import org.yliu.mui.redis.JedisClient;
import org.yliu.mui.service.MallUserService; import java.util.Date;
import java.util.List;
import java.util.UUID; @Service
public class MallUserServiceImpl implements MallUserService { private final MallUserPoMapper userMapper;
// 注入Jedis接口用来操作缓存
private final JedisClient jedisClient; @Autowired
public MallUserServiceImpl(MallUserPoMapper userMapper, JedisClient jedisClient) {
this.userMapper = userMapper;
this.jedisClient = jedisClient;
} @Override
public PageInfo<MallUserPo> findAll() {
PageHelper.startPage(0, 20);
MallUserPoExample userExample = new MallUserPoExample();
List<MallUserPo> mallUserPos = userMapper.selectByExample(userExample);
// 测试Jedis是否正常
jedisClient.set("user_info", JSON.toJSONString(mallUserPos));
return new PageInfo<>(mallUserPos);
}
}

ok,到了这里可以把项目启动了,run......

项目运行成功后 输入 http://127.0.0.1:2088/druid

如果阿里的Druid连接池监控登录页面会呈现在你电脑屏幕上,恭喜~ 输入用户名、密码,去登录尝鲜吧。

下一步就是测试 持久层 和 redis 了

访问 http://127.0.0.1:2088/get/user/all

如果响应数据 带有 分页信息的json数据的话,恭喜你~整合已经完成了。

再看redis:

OK,一切正常。

注意:如果中间出现什么问题的话,不要着急,有点耐心,仔细排除一下错误。

可以在下方留言,积极讨论

可以关注微信个人公众号对我私信(下方二维码

Spring Boot + MyBatis + Druid + Redis + Thymeleaf 整合小结的相关教程结束。

《Spring Boot + MyBatis + Druid + Redis + Thymeleaf 整合小结.doc》

下载本文的Word格式文档,以方便收藏与打印。