spring家族的springboot就像航天界冒出的SpaceX,降本增效提质。
hello world 即将成为 hello space。
1.springboot go
1.1 快速搭建springboot项目工程(就类似vue的vue-cli脚手架),next据需选配。
1.2 开箱即用
1.3 springboot go !
1.4 profile 环境切换
或者:
1.5 logback日志(会先于springboot配置文件的加载)
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logback</contextName>
<!--输出到控制台 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss:SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--过滤 INFO-->
<level>INFO</level>
<!--匹配到就禁止-->
<onMatch>ACCEPT</onMatch>
<!--没有匹配到就允许-->
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{HH:mm:ss:SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!--滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径 -->
<fileNamePattern>/data/log/demo/logs/demo.%d{yyyyMMddHH}.log</fileNamePattern>
</rollingPolicy>
</appender>
<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>%d{HH:mm:ss:SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!--滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径 -->
<fileNamePattern>/data/log/demo/logs/demo.error.%d{yyyyMMddHH}.log</fileNamePattern>
</rollingPolicy>
</appender>
<root level="info">
<appender-ref ref="console"/>
<appender-ref ref="fileLog"/>
<appender-ref ref="fileErrorLog"/>
</root>
<logger name="com.example.demo.mapper" level="DEBUG"/>
</configuration>
2.springboot + mybatis
2.1 maven pom引入mybatis依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<druid-version>1.1.22</druid-version>
<mybatis.version>3.5.0</mybatis.version>
<mybatis-spring.version>2.0.0</mybatis-spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql datasource-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid-version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<!--page helper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2.2 yml 文件配置:
#server
server:
port: 8100
servlet:
context-path: /demo
#spring
spring:
application:
name: demo
#datasource
datasource:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.2.9:3306/demo? characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: demo
password: demo123
druid:
initial-size: 2
min-idle: 2
max-active: 20
max-wait: 60000
remove-abandoned: true
remove-abandoned-timeout: 60
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
min-evictable-idle-time-millis: 30000
validation-query: select 1
test-on-return: true
test-while-idle: true
test-on-borrow: true
# 打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据 http://localhost:8100/demo/druid/index.html
# admin/admin
useGlobalDataSourceStat: true
#mybatis
mybatis:
mapper-locations: classpath:mapping/*.xml
type-aliases-package: com.example.demo.entity.domain
#pagehelper
pagehelper:
helper-dialect: mysql
reasonable: false
support-methods-arguments: true
params: count=countSql
2.3 扫描mapper映射为DAO
2.4 数据库建表,使用mybatis-generator反向工程自动生成
domain, mapping, mapper (查看官网教程或私信索要工具类)
创建Domain基类
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
import java.util.Date;
@Slf4j
@Data
public class Domain implements Serializable {
protected Integer id;
protected Date createTime;
protected Date updateTime;
protected Byte delFlag;
}
修改自动生成的User 集成自Domain基类
public class User extends Domain {
private String account;
private String password;
}
创建BaseMapper
import com.example.demo.domain.Domain;
import com.github.pagehelper.Page;
import org.apache.ibatis.annotations.Param;
public interface BaseMapper<T extends Domain> {
String PO_KEY = "po";
int deleteByPrimaryKey(Integer id);
int insert(T record);
int insertSelective(T record);
T selectByPrimaryKey(Integer id);
int updateByPrimaryKey(T record);
int updateByPrimaryKeySelective(T record);
Page<T> queryByExample(@Param(PO_KEY) T record);
}
修改UserMapper 集成 BaseMapper
import com.example.demo.domain.User;
import org.apache.ibatis.annotations.Param;
public interface UserMapper extends BaseMapper<User> {
User queryUserByAccount(@Param("account") String account);
}
追加扩展UserMapping功能
2.5 service层
BaseService
import com.example.demo.po.PagerRequest;
import com.github.pagehelper.Page;
import java.util.List;
public interface BaseService<T> {
int insert(T record);
int insertSelective(T record);
int deleteByPrimaryKey(Integer id);
int updateByPrimaryKey(T record);
int updateByPrimaryKeySelective(T record);
T selectByPrimaryKey(Integer id);
Page<T> selectByPage(PagerRequest pagerRequest);
List<T> queryByExample(T record);
}
BaseServiceImpl
import com.example.demo.domain.Domain;
import com.example.demo.mapper.BaseMapper;
import com.example.demo.po.PagerRequest;
import com.example.demo.service.BaseService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.ParameterizedType;
import java.util.List;
@Slf4j
public abstract class BaseServiceImpl<T extends Domain> implements BaseService<T> {
@Autowired
private BaseMapper<T> baseMapper;
private Class<T> domain;
public BaseServiceImpl() {
ParameterizedType parameterizedType = ((ParameterizedType) getClass().getGenericSuperclass());
domain = (Class<T>) parameterizedType.getActualTypeArguments()[0];
}
@Transactional(rollbackFor = Exception.class)
@Override
public int insert(T record){
return this.baseMapper.insert(record);
}
@Transactional(rollbackFor = Exception.class)
@Override
public int insertSelective(T record){
return this.baseMapper.insertSelective(record);
}
@Transactional(rollbackFor = Exception.class)
@Override
public int deleteByPrimaryKey(Integer id){
return this.baseMapper.deleteByPrimaryKey(id);
}
@Transactional(rollbackFor = Exception.class)
@Override
public int updateByPrimaryKey(T record){
return this.baseMapper.updateByPrimaryKey(record);
}
@Transactional(rollbackFor = Exception.class)
@Override
public int updateByPrimaryKeySelective(T record){
return this.baseMapper.updateByPrimaryKeySelective(record);
}
@Override
public T selectByPrimaryKey(Integer id){
return this.baseMapper.selectByPrimaryKey(id);
}
@Override
public Page<T> selectByPage(PagerRequest pagerRequest){
try {
PageHelper.startPage(pagerRequest.getPageNum(), pagerRequest.getPageSize());
PageHelper.orderBy(pagerRequest.getOrderBy());
T example = domain.newInstance();
// 查询参数封装转换 (如分页查询User, 创建UserRequest extends PagerRequest,
// UserRequest中的查询参数与User对应的属性保持一致)
BeanUtils.copyProperties(pagerRequest, example);
// 在对应的mapping中覆写queryByExample方法
return this.baseMapper.queryByExample(example);
} catch (Exception e) {
log.error("异常信息:{}", e.getMessage());
throw new RuntimeException("查询参数异常", e);
}
}
@Override
public List<T> queryByExample(T record){
return this.baseMapper.queryByExample(record);
}
}
分页查询参数PagerRequest
@Data
public class PagerRequest {
private int pageNum = 1; // mybatis pagerHelper从0开始
private int pageSize = 10; // 默认10条记录
private String orderBy = "id desc"; // 默认按id降序
}
@EqualsAndHashCode(callSuper = true)
@Data
public class UserRequest extends PagerRequest {
private String account;
}
UserService
import com.example.demo.domain.User;
public interface UserService extends BaseService<User> {
User queryUserByAccount(String account);
}
UserServiceImpl
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User queryUserByAccount(String account) {
return userMapper.queryUserByAccount(account);
}
}
BaseService中方法不满足时,可在UserService中扩展实现方法
原本想整理springboot + ORM, mybatis 及 JPA一起搞了的,发现篇幅太长了不宜读,JPA且待下回分享。
相关文章
暂无评论...