做者:任務加油站java
原文:toutiao.com/i6861456496740270604mysql
一、技術選型
-
解析器:FastJSON -
開發工具:JDK1.8 、Gradle、IDEA -
技術框架:SpringBoot 2.1.5.RELEASE -
ORM技術:MyBatisPlus3.1.2 -
數據庫:MySQL8.0.21 -
Apache 工具:HttpClient、Lang3 -
Git代碼版本控制 -
Web服務器:undertow -
hutool 國產工具類包 -
lombok 簡化代碼工具 -druid 數據庫鏈接池框架
二、Spring Boot 發展路線簡要描述
-
隨着動態語言的流行 (Ruby、Groovy、Scala、Node.js),Java 的開發顯得格外的笨重:繁多的配置、低下的開發效率、複雜的部署流程以及第三方技術集成難度大。 -
在上述環境下,Spring Boot 應運而生。它使用「習慣優於配置」(項目中存在大量的配置,此外還內置了一個習慣性的配置,讓你無需手動進行配置)的理念讓你的項目快速的運行起來。使用 Spring Boot 很容易建立一個獨立運行(運行 Jar,內嵌 Servlet 容器)準生產級別的基於 Spring 框架的項目,使用 Spring Boot 你能夠不用或者只需不多的 Spring 配置。
三、SpringBoot插件使用
-
spring-boot-devtools 實現熱部署,實際開發過程當中,修改應用的業務邏輯時經常須要重啓應用,這顯得很是繁瑣,下降了開發效率,因此熱部署對於開發來講顯得十分必要了 -
spring-boot-starter-aop 此插件沒什麼好說的了,aop是spring的兩大功能模塊之一,功能很是強大,爲解耦提供了很是優秀的解決方案。如:面向方面編程 -
spring-boot-starter-undertow 與spring boot 內置undertow 插件 -
spring-boot-starter-test 測試工具 -
mybatis-plus-boot-starter 與spring boot整合MyBatisPlus的jar -
spring-boot-configuration-processor 整合SpringBoot配置提示
四、fastJson
阿里JSON解析器,詳細文檔請看官方 https://github.com/alibaba/fastjsongit
五、Hutool
Hutool是一個Java工具包,也只是一個工具包,它幫助咱們簡化每一行代碼,減小每個方法,讓Java語言也能夠「甜甜的」。Hutool最初是我項目中「util」包的一個整理,後來慢慢積累並加入更多非業務相關功能,並普遍學習其它開源項目精髓,通過本身整理修改,最終造成豐富的開源工具集。github
六、Gradle
-
Gradle是一個基於Apache Ant和Apache Maven概念的項目自動化構建開源工具。它使用一種基於Groovy的特定領域語言(DSL)來聲明項目設置,目前也增長了基於Kotlin語言的kotlin-based DSL,拋棄了基於XML的各類繁瑣配置 -
官方 https://gradle.org/ -
不會Gradle的先本身補習一下,好比:安裝Gradle,配置環境變量,一些jar引入如何配置,基本使用怎麼使用
七、工程結構
此工程是經過Kotlin+SpringBoot+MyBatisPlus搭建最簡潔的先後端分離框架 框架升級Java語言SpringBoot+MyBatisPlus3.X+Gradle版本的框架,想學習Kotlin版本的請點擊藍色文章進行下載源代碼。web
八、Gradle配置
plugins {
id 'java'
id 'idea'
}
/**
* 使用Groovy語言語法定義版本號變量
*/
def spring_boot_version = "2.1.5.RELEASE"
def mybatis_plus_version = "3.1.2"
def mysql_version = "8.0.21"
def druid_version = "1.1.23"
def logback_version = "1.2.1"
def fastjson_version = "1.2.73"
def lombok_version = "1.18.12"
def lang_version = "3.4"
def io_version = "2.6"
def guava_version = "18.0"
def hutool_version = "5.3.10"
group = 'com.flong'
version = '0.0.1-SNAPSHOT'
//jdk版本
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
repositories {
//指定阿里雲鏡像
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
mavenLocal()
mavenCentral()
}
/**
* 一、implementation 履行 、compile 編譯
* 二、Gradle使用雙引號可 ${變量}能夠放入引號裏面,單引號是不能夠的。
* 三、Gragle使用lombok須要引入annotationProcessor註解,不然不能使用lombok.
* 四、mybatis-plus3.2.x以上版本引用了Kotlin的支持
* 五、高版本Springboogt在spring-boot-dependencies-2.3.0.RELEASE.pom裏面引入了mysql8.0.2的`<mysql.version>8.0.20</mysql.version>`配置
*/
dependencies {
implementation "org.springframework.boot:spring-boot-starter:${spring_boot_version}"
//排除tomcat使用undertow
compile("org.springframework.boot:spring-boot-starter-web:${spring_boot_version}") {
exclude module: "spring-boot-starter-tomcat"
}
compile "org.springframework.boot:spring-boot-starter-undertow:${spring_boot_version}"
//runtime group: 'mysql', name: 'mysql-connector-java', version: '5.1.42'
compile "org.springframework.boot:spring-boot-devtools:${spring_boot_version}"
compile "org.springframework.boot:spring-boot-configuration-processor:${spring_boot_version}"
compile "org.springframework.boot:spring-boot-starter-test:${spring_boot_version}"
compile "com.baomidou:mybatis-plus-extension:${mybatis_plus_version}"
compile "com.baomidou:mybatis-plus-boot-starter:${mybatis_plus_version}"
compile "mysql:mysql-connector-java:${mysql_version}"
compile "com.alibaba:druid:${druid_version}"
compile "ch.qos.logback:logback-classic:${logback_version}"
compile "com.alibaba:fastjson:${fastjson_version}"
annotationProcessor "org.projectlombok:lombok:${lombok_version}"
compileOnly "org.projectlombok:lombok:${lombok_version}"
//testAnnotationProcessor "org.projectlombok:lombok:${lombok_version}"
//testCompileOnly "org.projectlombok:lombok:${lombok_version}"
compile "org.apache.commons:commons-lang3:${lang_version}"
compile "commons-io:commons-io:${io_version}"
compile "com.google.guava:guava:${guava_version}"
compile "cn.hutool:hutool-all:${hutool_version}"
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
[compileJava, javadoc, compileTestJava]*.options*.encoding = "UTF-8"
九、數據庫SQL腳本
-
-- 建立表字段不建議用is開頭,在我Kotlin+Springboot+MyBatisPlus2.x整合也提到此問題, -
-- 故此整合MyBatisPlus3.x版本,把表的is_deleted字段修改爲del_flag,阿里開發手冊也提到此問題.
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`user_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '用戶Id主鍵,IdWork生成',
`user_name` varchar(255) DEFAULT '' COMMENT '用戶名',
`pass_word` varchar(255) DEFAULT '' COMMENT '密碼',
`del_flag` int(2) unsigned NOT NULL DEFAULT '0' COMMENT '是否刪除,0-不刪除,1-刪除',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
PRIMARY KEY (`user_id`) USING BTREE,
UNIQUE KEY `id` (`id`)USING BTREE
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='用戶表';
十、SpringBoot與MyBatisPlus3整合分頁代碼
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
/**
* 分頁插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
十一、SpringBoot與MyBatisPlus3分頁條件組裝器
package com.flong.springboot.core.util;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.flong.springboot.core.vo.Condition;
import java.lang.reflect.Field;
import java.util.List;
import com.flong.springboot.core.enums.JoinType;
import com.flong.springboot.core.exception.BaseException;
/**
* 將condition數據轉換成wrapper
*/
public class BuildConditionWrapper {
public static <T> QueryWrapper<T> build(List<Condition> conditions, Class<T> clazz) {
//初始化mybatis條件構造器
QueryWrapper wrapper = Wrappers.query();
if (conditions == null || conditions.size() == 0) {
return wrapper;
}
try {
for (int i = 0; i < conditions.size(); i++) {
Condition condition = conditions.get(i);
if (condition.getFieldName() == null) {
throw new BaseException("調用搜索接口時,缺乏關鍵字[fieldName]!");
}
//列名稱
String columnName = getColumnName(condition.getFieldName(), clazz);
if (condition == null || condition.getOperation() == null) {
throw new BaseException("操做符不能爲空!");
}
switch (condition.getOperation()) {
//等於
case EQ:
wrapper.eq(columnName, condition.getValue());
break;
//大於
case GT:
wrapper.gt(columnName, condition.getValue());
break;
//小於
case LT:
wrapper.lt(columnName, condition.getValue());
break;
//不等於
case NEQ:
wrapper.ne(columnName, condition.getValue());
break;
//大於等於
case GTANDEQ:
wrapper.ge(columnName, condition.getValue());
break;
//小於等於
case LTANDEQ:
wrapper.le(columnName, condition.getValue());
break;
case LIKE:
wrapper.like(columnName, condition.getValue());
break;
case ISNULL:
wrapper.isNull(columnName);
break;
case IN:
//value :1,2,3,4,5,6
wrapper.inSql(columnName, condition.getValue());
break;
default:
break;
}
if (condition.getJoinType() == JoinType.OR && i < conditions.size() - 1) {
//下個條件爲or鏈接且非最後一個條件,使用or進行鏈接
wrapper.or();
}
}
return wrapper;
} catch (Exception e) {
throw new BaseException("查詢條件不存在");
}
}
/**
* @Descript 此條件構建包裝器方法是支持多個表組裝成SQL字段的虛擬表,不支持實際存在的表
* @Date 2019/6/21 13:32
* @Author liangjl
*/
public static <T> QueryWrapper<T> buildWarpper(List<Condition> conditions) {
//初始化mybatis條件構造器
QueryWrapper wrapper = Wrappers.query();
if (conditions == null || conditions.size() == 0) {
return wrapper;
}
try {
for (int i = 0; i < conditions.size(); i++) {
Condition condition = conditions.get(i);
if (condition.getFieldName() == null) {
throw new BaseException("調用搜索接口時,缺乏關鍵字[fieldName]!");
}
//列名稱
String columnName = condition.getFieldName();
if (condition == null || condition.getOperation() == null) {
throw new BaseException("操做符不能爲空!");
}
switch (condition.getOperation()) {
//等於
case EQ:
wrapper.eq(columnName, condition.getValue());
break;
//大於
case GT:
wrapper.gt(columnName, condition.getValue());
break;
//小於
case LT:
wrapper.lt(columnName, condition.getValue());
break;
//不等於
case NEQ:
wrapper.ne(columnName, condition.getValue());
break;
//大於等於
case GTANDEQ:
wrapper.ge(columnName, condition.getValue());
break;
//小於等於
case LTANDEQ:
wrapper.le(columnName, condition.getValue());
break;
case LIKE:
wrapper.like(columnName, condition.getValue());
break;
case IN:
//value :1,2,3,4,5,6
wrapper.inSql(columnName, condition.getValue());
break;
default:
break;
}
if (condition.getJoinType() == JoinType.OR && i < conditions.size() - 1) {
//下個條件爲or鏈接且非最後一個條件,使用or進行鏈接
wrapper.or();
}
}
return wrapper;
} catch (Exception e) {
throw new BaseException("查詢條件不存在");
}
}
/***
* @Descript 獲取指定實體Bean的字段屬性
* @Date 2019/6/19 14:51
* @Author liangjl
*/
public static String getColumnName(String fieldName, Class clazz) {
try {
//獲取泛型類型字段
Field field = clazz.getDeclaredField(fieldName);
TableField tableFieldAnno = field.getAnnotation(TableField.class);
String columnName = "";
//獲取對應數據庫字段
if (tableFieldAnno != null && StrUtil.isNotBlank(tableFieldAnno.value())) {
//已定義數據庫字段,取定義值
columnName = tableFieldAnno.value();
} else {
//未指定數據庫字段,默認駝峯轉下劃線
columnName = NamingStrategyUtils.camelToUnderline(field.getName());
}
return columnName;
} catch (NoSuchFieldException e) {
throw new BaseException("查詢條件不存在");
}
}
}
十二、 實體
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.*;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper=false)
@TableName("t_user")
public class User extends Model<User> implements Serializable {
@TableId(type = IdType.ID_WORKER)
private Long userId;
/**
* 用戶名
*/
private String userName;
/**
* 密碼
*/
private String passWord;
/**
* 邏輯刪除(0-未刪除,1-已刪除)
*/
@TableLogic
private String delFlag;
/**
* 建立時間,容許爲空,讓數據庫自動生成便可
*/
private Date createTime;
}
1三、 Mapper
BaseMapper是繼承了mybatisplus底層的代碼spring
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.flong.springboot.modules.entity.User;
public interface UserMapper extends BaseMapper<User> {
}
1四、 Service
ServiceImplr是繼承了mybatisplus底層的代碼sql
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.flong.springboot.modules.entity.User;
import com.flong.springboot.modules.mapper.UserMapper;
import org.springframework.stereotype.Service;
@Service
public class UserService extends ServiceImpl<UserMapper, User> {
}
15 、controller
-
控制層主要實現CURD,增長,修改,查詢,刪除、分頁無大常規操做接口操做 -
用戶分頁,參數有多個使用下標索引進行處理.若是有兩個參數(如用戶名和地址):conditionList[0].fieldName=userName、 conditionList[0].fieldName=address -
查詢是經過反射fieldName進行去獲取表結構userName、address 字段的。 -
未轉碼請求分頁地址: http://localhost:7011/user/page?conditionList[0].fieldName=userName&conditionList[0].operation=LIKE&conditionList[0].value=周 -
已轉碼請求分頁地址: http://localhost:7011/user/page?conditionList[0].fieldName=userName&conditionList[0].operation=LIKE&conditionList[0].value=%E5%91%A8
package com.flong.springboot.modules.controller;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flong.springboot.modules.entity.User;
import com.flong.springboot.modules.mapper.UserMapper;
import com.flong.springboot.modules.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.flong.springboot.core.vo.Conditions;
import com.flong.springboot.core.util.BuildConditionWrapper;
import java.util.List;
/**
* @Author:liangjl
* @Date:2020-08-16
* @Description:用戶控制層
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
/**
* 添加
*/
@RequestMapping("/add")
public void add() {
userMapper.insert(User.builder().userName("周伯通").passWord("123456").build());
}
/**
* 修改
* @param user
*/
@PutMapping("/updateById")
public void updateById(@RequestBody User user) {
userMapper.updateById(user);
}
/**
* 刪除經過多個主鍵Id進行刪除
* @param ids
*/
@DeleteMapping("/deleteByIds")
public void deleteByIds(@RequestBody List<String> ids) {
userMapper.deleteBatchIds(ids);
}
/**
* 經過指定Id進行查詢
*
* @param userId
*/
@GetMapping("/getOne/{userId}")
public void getOne(@PathVariable("userId") Long userId) {
User user = userMapper.selectById(userId);
System.out.println(JSON.toJSON(user));
}
/**
* 用戶分頁,參數有多個使用下標索引進行處理.若是有兩個參數(如用戶名和地址):conditionList[0].fieldName=userName、 conditionList[0].fieldName=address
* 未轉碼請求分頁地址: http://localhost:7011/user/page?conditionList[0].fieldName=userName&conditionList[0].operation=LIKE&conditionList[0].value=周
* 已轉碼請求分頁地址: http://localhost:7011/user/page?conditionList[0].fieldName=userName&conditionList[0].operation=LIKE&conditionList[0].value=%E5%91%A8
* @param page
* @param conditions 條件
* @return
*/
@GetMapping("/page")
public IPage<User> page(Page page, Conditions conditions) {
QueryWrapper<User> build = BuildConditionWrapper.build(conditions.getConditionList(), User.class);
//經過lambda反射找到User實體類的createTime自動進行排序
build.lambda().orderByDesc(User::getCreateTime);
return userService.page(page, build);
}
}
1六、WebCofig工具類統一處理配置
-
消息轉換器,中文亂碼,Long的精度長度問題,時間格式等問題 -
cors 跨域支持 能夠用@CrossOrigin在controller上單獨設置 -
統一處理請求URL攔截器
@Configuration
@ConditionalOnClass(WebMvcConfigurer.class)
@Order(Ordered.HIGHEST_PRECEDENCE)
public class WebConfig implements WebMvcConfigurer {
@Bean
public HttpMessageConverters customConverters() {
//建立fastJson消息轉換器
FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
//建立配置類
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//修改配置返回內容的過濾
fastJsonConfig.setSerializerFeatures(
// 格式化
SerializerFeature.PrettyFormat,
// 可解決long精度丟失 但會有帶來相應的中文問題
//SerializerFeature.BrowserCompatible,
// 消除對同一對象循環引用的問題,默認爲false(若是不配置有可能會進入死循環)
SerializerFeature.DisableCircularReferenceDetect,
// 是否輸出值爲null的字段,默認爲false
SerializerFeature.WriteMapNullValue,
// 字符類型字段若是爲null,輸出爲"",而非null
SerializerFeature.WriteNullStringAsEmpty,
// List字段若是爲null,輸出爲[],而非null
SerializerFeature.WriteNullListAsEmpty
);
// 日期格式
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
// long精度問題
SerializeConfig serializeConfig = SerializeConfig.globalInstance;
serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
serializeConfig.put(Long.class, ToStringSerializer.instance);
serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
fastJsonConfig.setSerializeConfig(serializeConfig);
//處理中文亂碼問題
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastJsonConverter.setSupportedMediaTypes(fastMediaTypes);
fastJsonConverter.setFastJsonConfig(fastJsonConfig);
//將fastjson添加到視圖消息轉換器列表內
return new HttpMessageConverters(fastJsonConverter);
}
/**
* 攔截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//registry.addInterceptor(logInterceptor).addPathPatterns("/**");
//registry.addInterceptor(apiInterceptor).addPathPatterns("/**");
}
/**
* cors 跨域支持 能夠用@CrossOrigin在controller上單獨設置
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//設置容許跨域請求的域名
.allowedOrigins("*")
//設置容許的方法
.allowedMethods("*")
//設置容許的頭信息
.allowedHeaders("*")
//是否容許證書 再也不默認開啓
.allowCredentials(Boolean.TRUE);
}
}
1七、運行結果
-
添加 http://localhost:7011/user/add -
分頁 http://localhost:7011/user/page?conditionList[0].fieldName=userName&conditionList[0].operation=LIKE&conditionList[0].value=%E5%91%A8 -
默認當前current 爲1當前第一頁,size爲10,當前頁能夠顯示10條數據,也能夠根據本身的狀況進行自定義 -
http://localhost:7011/user/page?current=1&size=20&conditionList[0].fieldName=userName&conditionList[0].operation=LIKE&conditionList[0].value=%E5%91%A8
1八、工程代碼與說明
-
1 、以上問題都是根據本身學習實際狀況進行總結整理,除了技術問題查不少網上資料經過進行學習以後梳理。 -
二、 在學習過程當中也遇到不少困難和疑點,若有問題或誤點,望各位老司機多多指出或者提出建議。本人會採納各類好建議和正確方式不斷完善現況,人在成長過程當中的須要優質的養料。 -
三、 導入代碼的時候遇到最多的問題,我想應該是Maven較多,此時不懂maven的童鞋們能夠經過自身狀況,進行網上查資料學習。如經過網上找資料長時間解決不了,或者框架有不明白能夠經過博客留言,在能力範圍內會盡力幫助你們解決問題所在,但願在過程當中一塊兒進步,一塊兒成長。 -
工程代碼在 base 分支 https://github.com/jilongliang/springboot/tree/base
END數據庫
我是武哥,最後給你們 免費分享我寫的 10 萬字 Spring Boot 學習筆記(帶完整目錄)以及對應的源碼 。這是我以前在 CSDN 開的一門課,因此筆記很是詳細完整,我準備將資料分享出來給你們免費學習,相信你們看完必定會有所收穫( 下面有下載方式 )。
能夠看出,我當時備課很是詳細,目錄很是完整,讀者能夠手把手跟着筆記,結合源代碼來學習。如今免費分享出來,有須要的讀者能夠下載學習,就在我公衆號回覆:筆記,就行。apache
若有文章對你有幫助,編程
在看和轉發是對我最大的支持!
關注Java開發寶典
天天學習技術乾貨
點贊是最大的支持
本文分享自微信公衆號 - 武哥聊編程(eson_15)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。