# drunkard
**Repository Path**: moris_java/drunkard
## Basic Information
- **Project Name**: drunkard
- **Description**: drunkard: 英[ˈdrʌŋkəd] 美[ˈdrʌŋkərd] 酒鬼; 醉鬼;
醉酒状态下,可以忘却很多烦恼,倒是很羡慕那些 酒鬼们,每天都可以忘记好多事情。再者与同道中的人喝起来酒越喝越暖,也可以说 酒逢知己千杯少吧,中华古文化中对酒可以说有很多名人名句。信手拈来的有曹孟德对酒当歌,人生几何这样的焦虑;也有东坡先生 明月几时有?把酒问青天怀情;再有杜牧先生的 借问酒家何处有,牧童遥指杏花村的念酒。
以前听说魏晋时期的 竹林七贤 中有两人嗜酒如命 嵇康、刘伶,小时候还见到酒的品牌就以这两人名字命名的,甚是觉得好玩不得了。
言归正传,一直依赖,自己就想做一套后台管理系统,在此期间主要前端参考的开源项目 RuoYi,谁让自己前端知识储备不够,实在是写不出来那样的效果,没办法,只能抄。
本项目是基于SpringBoot开发的脚手架模块,已经集成 MyBatis 作为持久层组件,为了方便提供两种不同的主键生成策略,一种是利用 Redis ;另一种是利用数据库自身的ID策略,两种方式各有差异,主要针对不同的场景。
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: https://gitee.com/rothschil
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 8
- **Created**: 2021-11-29
- **Last Updated**: 2021-11-29
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
- [1. 项目简介](#1-项目简介)
- [1.1. 友情关联](#11-友情关联)
- [1.2. 概述](#12-概述)
- [1.3. 项目结构](#13-项目结构)
- [1.4. 技术选型](#14-技术选型)
- [1.4.1. 自动生成实体等文件](#141-自动生成实体等文件)
- [1.4.2. 分页](#142-分页)
- [1.5. 测试策略](#15-测试策略)
- [1.6. 技术架构](#16-技术架构)
- [1.7. 部署架构](#17-部署架构)
- [1.8. 外部依赖](#18-外部依赖)
- [2. 内置功能](#2-内置功能)
- [2.1. Springboot集成JPA,开箱即用](#21-springboot集成jpa开箱即用)
- [2.1.1. gradle文件](#211-gradle文件)
- [2.1.2. 自定义Repository工厂类](#212-自定义repository工厂类)
- [2.1.3. 抽象实体基类](#213-抽象实体基类)
- [2.1.4. 抽象Service基类](#214-抽象service基类)
- [2.1.5. 如何使用?](#215-如何使用)
- [2.1.5.1. 继承实体基类](#2151-继承实体基类)
- [2.1.5.2. 继承repository基类](#2152-继承repository基类)
- [2.1.5.3. 继承Service基类](#2153-继承service基类)
- [2.1.5.4. 启动类](#2154-启动类)
- [2.1.6. 源码地址,如果觉得对你有帮助,请Star](#216-源码地址如果觉得对你有帮助请star)
- [2.2. 自动刷新MybatisXML](#22-自动刷新mybatisxml)
- [2.2.1. 配置文件](#221-配置文件)
- [2.2.2. 关键步骤](#222-关键步骤)
- [2.2.3. 源码地址,如果觉得对你有帮助,请Star](#223-源码地址如果觉得对你有帮助请star)
- [2.3. 手写爬虫获取国家统计局行政区划数据](#23-手写爬虫获取国家统计局行政区划数据)
- [2.3.1. 依赖包](#231-依赖包)
- [2.3.2. 核心实现代码](#232-核心实现代码)
- [2.3.3. 单元测试](#233-单元测试)
- [2.3.4. 打开浏览器](#234-打开浏览器)
- [2.3.5. 源码地址,如果觉得对你有帮助,请Star](#235-源码地址如果觉得对你有帮助请star)
- [2.4. 集成ip2region离线IP地名映射](#24-集成ip2region离线ip地名映射)
- [2.4.1. 打开浏览器](#241-打开浏览器)
- [2.4.2. 源码地址,如果觉得对你有帮助,请Star](#242-源码地址如果觉得对你有帮助请star)
- [2.5. Http响应内容统一封装](#25-http响应内容统一封装)
- [2.5.1. 消息体](#251-消息体)
- [2.5.1.1. 正常响应](#2511-正常响应)
- [2.5.1.2. 异常响应](#2512-异常响应)
- [2.5.2. 拦截器](#252-拦截器)
- [2.5.2.1. Annoation注解](#2521-annoation注解)
- [2.5.2.2. 拦截器](#2522-拦截器)
- [2.5.2.3. 全局异常](#2523-全局异常)
- [2.5.3. 例子](#253-例子)
- [2.5.4. 源码地址,如果觉得对你有帮助,请Star](#254-源码地址如果觉得对你有帮助请star)
- [2.6. 集成OAuth2](#26-集成oauth2)
- [2.7. 集成数据校验](#27-集成数据校验)
- [3. FAQ](#3-faq)
# 1. 项目简介
















## 1.1. 友情关联
[简书-首页](https://www.jianshu.com/u/72ee6146c91a):平常写的内容都在上面

[Gitee首页](https://gitee.com/rothschil/):Gitee首页

[Git.IO首页](https://rothschil.github.io/):Git.IO首页

[Github首页](https://github.com/rothschil):Github首页

[CSDN](https://blog.csdn.net/rothchil):CSDN首页

[Weathertop](https://github.com/king-angmar/weathertop):其他开源的部分,已停止维护

## 1.2. 概述
`drunkard: 英[ˈdrʌŋkəd] 美[ˈdrʌŋkərd] 酒鬼; 醉鬼;`
醉酒状态下,可以忘却很多烦恼,倒是很羡慕那些 `酒鬼`们,每天都可以忘记好多事情。再者与同道中的人`喝`起来酒越喝越暖,也可以说 `酒逢知己千杯少`吧,中华古文化中对`酒`可以说有很多名人名句。信手拈来的有曹孟德`对酒当歌,人生几何`这样的焦虑;也有东坡先生 `明月几时有?把酒问青天`怀情;再有杜牧先生的 `借问酒家何处有,牧童遥指杏花村`的念`酒`。
以前听说魏晋时期的 `竹林七贤` 中有两人嗜酒如命 `嵇康`、`刘伶`,小时候还见到酒的品牌就以这两人名字命名的,甚是觉得好玩不得了。
言归正传,一直依赖,自己就想做一套后台管理系统,在此期间主要前端参考的开源项目 `RuoYi`,谁让自己前端知识储备不够,实在是写不出来那样的效果,没办法,只能抄。
本项目是基于SpringBoot开发的脚手架模块,已经集成 `MyBatis` 作为持久层组件,为了方便提供两种不同的主键生成策略,一种是利用 `Redis` ;另一种是利用数据库自身的ID策略,两种方式各有差异,主要针对不同的场景。
同时本人也将日常学习的一些材料也整理出来,放到 [github.io](https://rothschil.github.io/) 的个人网站上,希望对大家有帮助。
- 
## 1.3. 项目结构
~~~
|-- akkad-base ------------基包
| |-- base-utils ------------通用工具包
| |-- persistence-jpa ------------基于JPA封装持久层
| |-- persistence-mybatis ------------基于MyBatis封装持久层
| | |-- mybatis-base ------------Mybatis抽象基类封装
| | | |-- resources ------------
| | | | |-- conf ------------Mybatis自动刷新配置路径
| | |-- mybatis-no-pk ------------依赖DB主键版本
| | |-- mybatis-pk-redis ------------依赖Redis生成主键的版本
|-- akkad-springboot ------------springboot集成开源组件
| | |-- springboot-dist-lock ------------分布式锁例子
| | |-- springboot-dist-trans ------------分布式事物
| | |-- springboot-elasticsearch ------------集成ES
| | |-- springboot-jwt ------------JWT示例
| | |-- springboot-mq ------------集成消息MQ组件
| | |-- springboot-nosql ------------集成oauth2的版本
|-- akkad-war3 ------------常用的示例
| | |-- war3-area ------------获取行政区域的版本
| | |-- war3-dior ------------获取行政区域的版本
| | | |-- dior-thumbnailator ------------利用thumbnailator 编辑图片
| | |-- war3-infi ------------集成RuoYi 实现通用管理后台
| | |-- war3-moon ------------集成Mybatis扫描文件
| | |-- war3-oauth2 ------------集成oauth2的版本
| | |-- war3-sky ------------集成JPA的样例
|-- README.md
|-- LICENSE
~~~
## 1.4. 技术选型
SpringBoot、Gradle、Jnuit、MySQL、JDK8+
### 1.4.1. 自动生成实体等文件
在 `build.gradle` 文件中加上`generator`依赖,在 `mybatisGenerator` 中指定`generatorConfig.xml` 文件的位置,剩下一些数据库连接以及配置项,都在配置文件`generatorConfig.xml`中指定即可,方便又实用。
- gradle文件
~~~gradle
plugins {
id "com.arenagod.gradle.MybatisGenerator" version "1.4"
}
configurations {
mybatisGenerator
}
mybatisGenerator {
verbose = true
configFile = 'src/main/resources/generator/generatorConfig.xml'
}
~~~
- generatorConfig.xml文件
这里我将数据库配置信息独立出来在另外一个文件,即`generator.properties`,`table` 节点自定义,可以一次性写个表。
~~~xml
~~~
- generator.properties文件
指定数据库驱动路径以及数据库URL、用户名、密码等即可
~~~properties
jdbc.driverLocation=G:\\Devp_Repository\\Jar\\mysql-connector-java-5.1.46.jar
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.connectionURL=jdbc:mysql://localhost:3306/addbook?characterEncoding=utf8&useSSL=true
jdbc.userId=root
jdbc.password=123456
targetProject=D:/data
targetPackage=xyz.wongs.drunkard.domain.addbook
// Generator
generator.targetProject=src/main/java
~~~
最后就是执行阶段,两种方式,我使用的`maven`插件命令方式来执行,直接双击。

### 1.4.2. 分页
分页组件是继承开源**com.github.pagehelper**
`Gradle` 集成的使用下面的
```gradle
compile group: 'com.github.pagehelper', name: 'pagehelper-spring-boot-starter', version: '${Last Version}'
```
`Maven` 使用这个:
~~~xml
com.github.pagehelper
pagehelper-spring-boot-starter
${Last Version}
~~~
在应用中PageHelper.startPage即可,后面需要紧跟着持久层语句,否则分页失效
~~~java
public PageInfo selectPage(PaginationInfo pgInfo, T t) {
PageHelper.startPage(pgInfo.getPageNum(), pgInfo.getPageSize());
List lt = getMapper().getList(t);
PageInfo pageInfo = new PageInfo(lt);
return pageInfo;
}
~~~
## 1.5. 测试策略
测试类型 | 代码目录 | 测试内容
-- | -- | -- |
单元测试 | src/test/java | 包含核心领域模型(包含领域对象和Factory类)的测试
组件测试 | src/componentTest/java | 用于测试一些核心的组件级对象,比如Repository
API测试 | src/apiTest/java | 模拟客户端调用API
## 1.6. 技术架构
## 1.7. 部署架构
## 1.8. 外部依赖
项目运行时所依赖的外部集成方;
# 2. 内置功能
## 2.1. Springboot集成JPA,开箱即用
不知为什么在以前的一段时间内,我特别喜欢用 `JPA` ,它给我印象就是小巧灵便,为我省去了很多不必要的编码,带给我不一样的代码输出效率,因为业务在垂直划分过程中都相对来说封闭,要求在编码过程中相对来说实体关联没有那么复杂,而且项目本身的交付周期特别短,我就选择 `JPA` 作为我们某个特定项目的专用持久层框架,当然 `JPA` 自身的优势就不说啦。
项目架构目的就是为了高质量、低成本、更便捷的交付,也是我那段时间里秉承的思路。
下面言归正传,我们用我之前项目在springboot集成 `JPA` 来做一个演示。
### 2.1.1. gradle文件
`build.gradle` 中引入 `spring-boot-starter-data-jpa` 依赖,注意版本。
~~~gradle
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.4.1'
~~~
### 2.1.2. 自定义Repository工厂类
`JPA` 默认工厂类 `JpaRepositoryFactoryBean` ,并不能满足我们实际要求,比如我们想在插入或者修改的适合做些事情,默认工厂类就不会支持,所以我们重写一个自己的,继承 `JpaRepositoryFactoryBean`即可。

继承后重写 `createRepositoryFactory` 方法,指定我们自己的,这里我用一个内静态类来,这个内部类 `BaseRepositoryFactory` 也需要继承 `JpaRepositoryFactory` 工厂,此处我们指定自己真实的工厂类实现 `BaseRepositoryImpl`。
~~~java
@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new BaseRepositoryFactory(entityManager);
}
private static class BaseRepositoryFactory extends JpaRepositoryFactory{
private final EntityManager em;
public BaseRepositoryFactory(EntityManager em) {
super(em);
this.em = em;
}
@Override
protected JpaRepositoryImplementation, ?> getTargetRepository(RepositoryInformation information, EntityManager entityManager) {
return new BaseRepositoryImpl((Class) information.getDomainType(), em);
}
/**
* 设置具体的实现类的class
* @param metadata
* @return
*/
@Override
protected Class> getRepositoryBaseClass(RepositoryMetadata metadata) {
return BaseRepositoryImpl.class;
}
}
~~~
下面就可以在我们自己的类做我们的自己事情,同时我们实现类中抽象出来一个接口暴露对外,这个接口定义我们需要共用的方法,具体实现我们额外实现。这样设计有个好处,就是耦合度降低,扩展方便。

- 抽象接口
~~~java
@NoRepositoryBean
@Transactional(readOnly=true,rollbackFor = Exception.class)
public interface BaseRepository extends JpaRepository {
/**
* 根据主键删除
*
* @param ids
*/
void delete(ID[] ids);
/**
*
* @param sql
* @return
*/
List