springboot網站開發02-接入持久層框架mybatisPlus!經過上一小節內容分享,我們的項目嵌套模式框架搭建好了,下面就是開始編輯具體的業務代碼了,我們使用到了持久層框架是mybatisPlus插件。下面是一些具體的植入框架的操作步驟。
第一步,在Pom.xml加入參數,讓maven幫我們管理插件的依賴包。
<?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"><parent><artifactId>blog</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>blog-framework</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--lombk--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--junit--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--SpringSecurity啟動器-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-security</artifactId>-->
<!-- </dependency>--><!--redis依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--fastjson依賴--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><!--jwt依賴--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency><!--mybatisPlus依賴--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></dependency><!--mysql數據庫驅動--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--阿里云OSS--><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId></dependency><!--AOP--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId></dependency></dependencies></project>
這是完整的依賴包參數配置,因為我們不可能只是僅僅需要mybatisPlus,肯定還需要其他的依賴 ,比如Lombk-實體類注解包,數據庫mysql底層連接池mysql-connector-java等。還有json格式轉化插件fastjson。
加好了參數后點擊右側的菜單欄,點擊按鈕,幫助我們下載依賴代碼插件。
?
這個是我們公共子模塊的里面的文件夾名字,每一個都有各自的作用。
第一個config里面存放了一些配置對象類。比如mybatisPlus的配置類,比如webConfig完成了跨域請求的設置,已經json格式的封裝。
?
package com.blog.config;import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {// 設置允許跨域的路徑registry.addMapping("/**")// 設置允許跨域請求的域名.allowedOriginPatterns("*")// 是否允許cookie.allowCredentials(true)// 設置允許的請求方式.allowedMethods("GET", "POST", "DELETE", "PUT")// 設置允許的header屬性.allowedHeaders("*")// 跨域允許時間.maxAge(3600);}@Bean//使用@Bean注入fastJsonHttpMessageConvertpublic HttpMessageConverter fastJsonHttpMessageConverters() {//1.需要定義一個Convert轉換消息的對象FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();FastJsonConfig fastJsonConfig = new FastJsonConfig();fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");SerializeConfig.globalInstance.put(Long.class, ToStringSerializer.instance);fastJsonConfig.setSerializeConfig(SerializeConfig.globalInstance);fastConverter.setFastJsonConfig(fastJsonConfig);HttpMessageConverter<?> converter = fastConverter;return converter;}@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(fastJsonHttpMessageConverters());}}
?這個代碼就是WebConfig配置類內容了,寫的注解很詳細,不再一一介紹了。
package com.blog.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configurationpublic class MbatisPlusConfig {/*** 3.4.0之后版本* @return*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return mybatisPlusInterceptor;}}
這個就是mybatisPlus配置類內容,我們里面配置了一下關于分頁管理的功能。
package com.blog.constants;/*** 常量定義的工具實體類*/
public class SystemConstants {/*** 文章是草稿狀態,默認值為1*/public static final int ARTICLE_STATUS_DRAFT = 1;/*** 文章是正常發布狀態,默認值為0*/public static final int ARTICEL_STATUS_NORMAL = 0;/*** 頁面當前的頁碼,默認初始值為1*/public static final int PAGE_NUMBER = 1;/*** 頁面當前的list容量,默認初始值為10*/public static final int PAGE_SIZE = 10;/*** 狀態碼是正常的,默認值為0*/public static final String STATUS_NORMAL = "0";/*** 友鏈狀態碼正常的 默認值為0*/public static final String LINK_STATUS_NORMAL = "0";
}
?以上是關于系統內使用到了一些常量定義,實體類。我們封裝成這樣的常量后,使用起來就便于代碼的協調統一了。一處修改,其他地方調用了都會跟著也一起變化了,省事,效率高。
這個是分開設計的思想,entity里面寫的實體類,是對應數據庫內數據表的,但是實際傳遞給頁面前端渲染的數據,經常會遇到(個別屬性值的傳遞)。我們就會在額外定義一個專門用于前端渲染使用的實體類對象(Map-Model)(view-modle)-頁面模型。區別于數據庫表模型。
這樣設計的優勢是,后端服務器在響應給前端頁面接口的數據時傳遞返回過去的數據信息會減少一些不必要的內存占用。畢竟網絡帶寬傳輸是有限制的,傳輸的精簡一些,渲染起來會快,而且響應速度快,客戶體驗就會好一點。這是站在客戶體驗的角度這樣設計的。實際開發中也的確是這樣設計的。
題外話:如果你是有多個終端,比如安卓,蘋果,平板,電腦,小程序等,甚至公司會要求你單獨創建對應的文件夾,不同終端存放不同的實體類模型。以此來區別開對待數據渲染的任務。
?以下代碼是文章(新聞文章)實體類,里面有一個邏輯刪除的標志。大家注意一下。
package com.blog.domain.entity;import java.util.Date;import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;/*** 文章表(Article)表實體類** @author makejava* @since 2023-05-16 10:37:43*/
@SuppressWarnings("serial")
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("sg_article")
@Accessors(chain = true)
public class Article {@TableIdprivate Long id;//標題private String title;//文章內容private String content;//文章摘要private String summary;//所屬分類idprivate Long categoryId;//分類名字@TableField(exist = false)private String categoryName;//縮略圖private String thumbnail;//是否置頂(0否,1是)private String isTop;//狀態(0已發布,1草稿)private String status;//訪問量private Long viewCount;//是否允許評論 1是,0否private String isComment;private Long createBy;private Date createTime;private Long updateBy;private Date updateTime;//刪除標志(0代表未刪除,1代表已刪除)@TableLogic(value = "0",delval = "1")private Integer delFlag;}
配合著給大家展示一個前端渲染新聞文章的實體類內容,這個ArticleDetailVo對象,用于前端新聞列表的渲染使用,因為列表頁面,其實并不會讓用戶看見具體的新聞內容,所以里面不需要content(詳情屬性字段)
package com.blog.domain.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
public class ArticleDetailVo {private Long id;//標題private String title;//文章摘要private String summary;//文章內容private String content;//所屬分類idprivate Long categoryId;//所屬分類名字private String categoryName;//縮略圖private String thumbnail;//訪問量private Long viewCount;private Date createTime;
}
如圖,前端列表頁渲染使用的頁面模型對象是不需要這個屬性值的。
?核心思想就是渲染需要什么屬性,我們就封裝什么屬性,追求的極簡主義。一個多余的也不封裝。
比如前端頁面有一個熱點新聞欄目列表,里面只需要2個屬性值:title(標題)和vieCount(瀏覽量)
這個HotArticleVo頁面模型就是專門封裝起來給熱門新聞列表使用的一個實體對象。
package com.blog.domain.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageVo {//列表對象封裝的對象集合private List rows;//一共有多少條數據private Long total;
}
?我們為了便于做分頁處理,封裝了一個頁面對象,它里面2個值,一個是封裝好了將來要遍歷循環的集合對象,一個是總共多少條數據。
package com.blog.domain;import com.blog.enums.AppHttpCodeEnum;import java.io.Serializable;public class ResponseResult<T> implements Serializable {private Integer code;private String msg;private T data;public ResponseResult() {this.code = AppHttpCodeEnum.SUCCESS.getCode();this.msg = AppHttpCodeEnum.SUCCESS.getMsg();}public ResponseResult(Integer code, T data) {this.code = code;this.data = data;}public ResponseResult(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public ResponseResult(Integer code, String msg) {this.code = code;this.msg = msg;}public static ResponseResult errorResult(int code, String msg) {ResponseResult result = new ResponseResult();return result.error(code, msg);}public static ResponseResult okResult() {ResponseResult result = new ResponseResult();return result;}public static ResponseResult okResult(int code, String msg) {ResponseResult result = new ResponseResult();return result.ok(code, null, msg);}public static ResponseResult okResult(Object data) {ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getMsg());if (data != null) {result.setData(data);}return result;}public static ResponseResult errorResult(AppHttpCodeEnum enums) {return setAppHttpCodeEnum(enums, enums.getMsg());}public static ResponseResult errorResult(AppHttpCodeEnum enums, String msg) {return setAppHttpCodeEnum(enums, msg);}public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums) {return okResult(enums.getCode(), enums.getMsg());}private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String msg) {return okResult(enums.getCode(), msg);}public ResponseResult<?> error(Integer code, String msg) {this.code = code;this.msg = msg;return this;}public ResponseResult<?> ok(Integer code, T data) {this.code = code;this.data = data;return this;}public ResponseResult<?> ok(Integer code, T data, String msg) {this.code = code;this.data = data;this.msg = msg;return this;}public ResponseResult<?> ok(T data) {this.data = data;return this;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public T getData() {return data;}public void setData(T data) {this.data = data;}
}
這個是一個頁面回傳(響應請求,攜帶數據返回給前端的實體類工具類),里面主要有三個屬性,
private Integer code;//響應的狀態碼, private String msg;//響應的描述信息 private T data;//響應的具體數據信息。是一個泛型。
package com.blog.enums;public enum AppHttpCodeEnum {// 成功SUCCESS(200,"操作成功"),// 登錄NEED_LOGIN(401,"需要登錄后操作"),NO_OPERATOR_AUTH(403,"無權限操作"),SYSTEM_ERROR(500,"出現錯誤"),USERNAME_EXIST(501,"用戶名已存在"),PHONENUMBER_EXIST(502,"手機號已存在"), EMAIL_EXIST(503, "郵箱已存在"),REQUIRE_USERNAME(504, "必需填寫用戶名"),LOGIN_ERROR(505,"用戶名或密碼錯誤");int code;String msg;AppHttpCodeEnum(int code, String errorMessage){this.code = code;this.msg = errorMessage;}public int getCode() {return code;}public String getMsg() {return msg;}
}
為了節省時間提升效率,我們專門封裝了一個來做關于前端請求反饋的枚舉類型對象。enum(枚舉)。
這2個,大家最為熟悉,之前學習SSM的時候,經常使用,一個是持久層接口,一個是業務層接口,里面嵌套了一個業務層接口實現類。不過多介紹了。
?
package com.blog.utils;import com.blog.domain.entity.Article;
import com.blog.domain.vo.HotArticleVo;
import com.fasterxml.jackson.databind.util.BeanUtil;
import org.springframework.beans.BeanUtils;import java.util.List;
import java.util.stream.Collectors;public class BeanCopyUtils {private BeanCopyUtils() {}public static <V> V copyBean(Object source,Class<V> vClass){//創建目標對象V result = null;try {result = vClass.newInstance();//copy對象屬性BeanUtils.copyProperties(source,result);} catch (Exception e) {e.printStackTrace();}//返回對象return result;}public static <O,V> List<V> copyBeanList(List<O> list, Class<V> vClass){return list.stream().map(o -> copyBean(o, vClass)).collect(Collectors.toList());}}
這個是一個用于數據過濾(抽取數據集合)的工具類。可以幫助我們完成一些數據集合的二次過濾抽取。達到我們想要的效果。我們不可能總是一遍又一遍的去反復查詢數據庫信息,有些業務,我們只需要查詢一次,就可以反復從集合中抽取我們想要的信息就行了。可以節省服務器的cpu資源和內存資源。回頭 抽時間,專門做一期分享,講這個數據抽取,它用了是stream流的模式操作的,現在有些公司喜歡使用流操作。其實背后底層還是原始的,只是流操作看上去代碼較為簡潔而已。
server:port: 7777
spring:datasource:url: jdbc:mysql://localhost:3306/sg_blog?characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword:driver-class-name: com.mysql.cj.jdbc.Driverservlet:multipart:max-file-size: 2MBmax-request-size: 5MB
mybatis-plus:configuration:# 日志log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:logic-delete-field: delFlaglogic-delete-value: 1logic-not-delete-value: 0id-type: auto
這個是前端項目模塊的springboot啟動配置文件信息。里面有服務器接口,數據源參數,我的本地數據庫是沒有設置密碼的,所以我那里是空白,不需要輸入。還設置好了mybatisPlus的配置信息。全局配置里有一個邏輯刪除的配置。默認是0表示未刪除,1代表已刪除。
為了節省時間,提升效率,我們使用了一個插件EasyCode.它可以幫助我們自動把數據表,映射為項目內的實體類,包括業務層,持久層,都會自動創建好的。我們僅僅需要告訴它存儲路徑。
?
如圖,你選擇好,模塊(存儲到哪個項目下面去!我們肯定是存在公共模塊下面啊,前端,后端都要用到這個代碼的。)后面的Tempalte模塊勾選,我們不選controller(控制器),控制器我們在前端項目里自己寫的,我們只需要EasyCode插件幫助我們寫好基礎的東西就行了,比如持久層,業務層,實體類。持久層實現類。
持久層實現類具體如何實現業務邏輯,還是需要我們自己后面完善的,它只是做一個基礎的架構而已。并不會真正的達到人工智能的效果。還是離不開程序員的思維+操作。?
后面會單獨出一期講解這個EasyCode插件如何使用的教程。
走到這一步,基本上,項目的骨架填充,就已經完成一大半了。下一個小節,我們以首頁查詢新新聞分類為案例,展示一下,如何使用mybatisPlus實現具體的業務邏輯操作。?