简介
工作5年了,现在自我定义是一个产品的研发经理,去年公司老板要每个人拿着自己的PPT在他面前做年终总结,我其中有一条是今年要写一套技术博客文集 then just do it。接下来的一系列的文章是以我现在带的一个项目为基础,从新开始一个后台管理类型的项目(QiYuAdmin–后台管理系统)为推动力来完成,里面有很多东西需要我去注意和学习的地方,太多。
成果
登录
![]()
首页
技术架构
这篇文章主要的内容就是搭建项目的基础架构
- SpringBoot 1.5.1
- Mybatis 3.3.8
- Thymeleaf 3.0
- BootStrap 3
- SpringBoot和Druid集成
- SpringBoot、通用Mapper集成和分页插件集成
- 自己封装的基础接口BaseService
- Maven3.3.9、intellij idea2016、MySQL、Tomcat
基于Maven创建SpringBoot项目
解释一下以上几个模块的作用
* qiyu-framework-web:Metronic框架和一些插件
* qiyu-framework-core:整个项目的核心模块
* qiyu-amin-web:qyAdmin所有的页面和自定义静态资源
* qiyu-admin-auth:权限模块
SpringBoot集成Druid
源码网上搜索一大堆,还是贴出来吧
Application.properties配置:
# DataSource settings
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driverClassName = com.mysql.jdbc.Driver
#连接池的配置信息
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
Bean配置:
import com.alibaba.druid.pool.DruidDataSource;
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.beans.factory.annotation.Value;
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 org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* alibaba druid数据库连接池
*
* @author zhangqing
* @date 2017年02月25日
*/
@Configuration
public class DruidDBConfig {
private Logger logger = LoggerFactory.getLogger(DruidDBConfig.class);
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
@Bean(initMethod = "init", destroyMethod = "close") //声明其为Bean实例
@Primary //在同样的DataSource中,首先使用被标注的DataSource
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
//configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
logger.error("druid configuration initialization filter", e);
}
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean reg = new ServletRegistrationBean();
reg.setServlet(new StatViewServlet());
reg.addUrlMappings("/druid/*");
reg.addInitParameter("allow", "127.0.0.1"); //白名单
reg.addInitParameter("deny",""); //黑名单
reg.addInitParameter("loginUsername", "admin");
reg.addInitParameter("loginPassword", "admin");
return reg;
}
@Bean public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
SpringBoot集成Mybatis
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Properties;
/**
* MyBatis基础配置
*/
@Configuration
@EnableTransactionManagement
public class MyBatisConfig implements TransactionManagementConfigurer {
@Resource
DataSource dataSource;
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean() {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setTypeAliasesPackage("com.qiyu.admin.*.model");
//分页插件
PageHelper pageHelper = new PageHelper();
Properties properties = new Properties();
properties.setProperty("reasonable", "true");
properties.setProperty("supportMethodsArguments", "true");
properties.setProperty("returnPageInfo", "check");
properties.setProperty("params", "count=countSql");
pageHelper.setProperties(properties);
//添加插件
bean.setPlugins(new Interceptor[]{pageHelper});
//添加XML目录
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
bean.setMapperLocations(resolver.getResources("classpath*:mapper/*Mapper.xml"));
return bean.getObject();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DataSourceTransactionManager(dataSource);
}
}
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
import java.util.Properties;
/**
* MyBatis扫描接口,使用的tk.mybatis.spring.mapper.MapperScannerConfigurer,
*/
@Configuration
//注意,由于MapperScannerConfigurer执行的比较早,所以必须有下面的注解
@AutoConfigureAfter(MyBatisConfig.class)
public class MyBatisMapperScannerConfig {
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
mapperScannerConfigurer.setBasePackage("com.qiyu.admin.*.mapper");
Properties properties = new Properties();
properties.setProperty("mappers", "com.qiyu.framework.base.BaseMapper");
properties.setProperty("notEmpty", "false");
properties.setProperty("IDENTITY", "MYSQL");
mapperScannerConfigurer.setProperties(properties);
return mapperScannerConfigurer;
}
}
封装的基础接口BaseService
这个是自己封装的接口,没啥技术含量就是为了方便
import com.qiyu.framework.util.PagedResult;
import java.util.List;
/**
*
* 基础接口
* @author zhangqing
* @date 2016年09月02日
*/
public interface BaseService<T extends BaseModel>{
/**
*
* 增加一个实体,增加所有字段
* @param pojo
* @return 返回实体类
*/
public T insert(T pojo) throws Exception;
/**
*
* 增加一个实体,只会增加不是null的字段
* @param pojo
* @return 返回实体类
*/
public T insertSelective(T pojo)throws Exception;
/**
* 根据主键进行更新一个实体类,更新所有字段
* @param pojo
* @return 修改成功状态
*/
public T updateByPrimaryKey(T pojo)throws Exception;
/**
* 根据主键进行更新一个实体类,只会更新不是null的字段
* @param pojo
* @return
*/
public T updateByPrimaryKeySelective(T pojo)throws Exception;
/**
* 根据实体类中字段不为null的条件进行删除,条件全部使用=号and条件
* @param key
* @return
*/
public int delete(T key)throws Exception;
/**
* 通过主键进行删除,这里最多只会删除一条数据
* 单个字段做主键时,可以直接写主键的值
* 联合主键时,key可以是实体类,也可以是Map
* @param key
* @return
*/
public int deleteByPrimaryKey(Object key)throws Exception;
/**
* 根据主键的集合批量删除数据
* @param keys
* @return 是否删除成功
*/
public boolean deleteByPrimaryKeyList(List<String> keys)throws Exception;
/**
* 根据实体类不为null的字段进行查询集合,条件全部使用=号and条件
* @param pojo
* @return
*/
public List<T> select(T pojo)throws Exception;
/**
* 根据实体类不为null的字段查询总数,条件全部使用=号and条件
* @param pojo
* @return
*/
public int selectCount(T pojo)throws Exception;
/**
* 根据主键进行查询,必须保证结果唯一
* 单个字段做主键时,可以直接写主键的值
* 联合主键时,key可以是实体类,也可以是Map
* @param key
* @return
*/
public T selectByPrimaryKey(Object key)throws Exception;
/**
* 查询所有实体集合
* @return
*/
public List<T> selectAll()throws Exception;
/**
* 查询分页
* @param pageNo
* @param pageSize
* @param pojo
* @return
*/
public PagedResult<T> findPageList(Integer pageNo, Integer pageSize, T pojo)throws Exception;
尝试的小白
第一篇先写到这里,写的比较粗糙,源码先不分享了,现在还是一个半成品,后续我将把用户、部门的增删改查功能做出来之后分享到github上,希望大家一起学习。