SpringBoot整合jwt和mybatis-plus的腳手架項目

近期給公司弄了個腳手架項目,打算之後後臺開發就用這個了, 求star~html

點擊跳轉到github地址前端

概述

Volcano是一個基於springboot後臺開發簡易腳手架。能實現看成一個單獨項目或者做爲微服務的一個節點進行快速開發和部署。java

項目結構

javasea-volcano 父類, 用於springcloud和springboot的版本管控, maven插件, 倉庫統一管控等.git

|--javasea-volcano-base: 測試類和相關業務配置, 依賴common項目中的組件,開發的時候在該項目的基礎上添加添加業務代碼便可。github

|--javasea-volcano-common:經常使用組件和工具類web

項目環境

中間件 版本 備註
JDK 1.8+ JDK1.8及以上
MySQL 5.6+ 5.6及以上
Redis 3.2+

基本功能

參考包com.zhirui.lmwy.wms.demo下的配置redis

參數校驗

JSR校驗

spring-boot-starter-web已經默認集成了JSR303校驗,只須要直接使用註解校驗便可。

參考測試類: com.zhirui.lmwy.wms.demo.web.controller.TestCheckParamControllerspring

手動校驗

Assert類定義了不知足條件後快速斷言的方式,能夠在校驗參數中使用。shell

還能夠採用Spring的Assert進行校驗數據庫

//第一個參數爲false則拋出IllegalArgumentException異常
Assert.isTrue(concurrentConsumers > 0, "'concurrentConsumers' value must be at least 1 (one)");
Assert.isTrue(!this.exclusive || concurrentConsumers == 1,"When the consumer is exclusive, the concurrency must be 1");

也能夠採用Optional進行校驗

ZOrder order = this.getOrderByOrderNum(orderNum);
Optional.ofNullable(order).filter(o -> {
    return null != o && (0 == o.getStatus() || 3 == o.getStatus() || 9 == o.getStatus());
}).orElseThrow(() -> new ParamException("獲取數據異常,訂單號有誤或者訂單狀態異常!"));
還能夠經過guava的Preconditions類來進行參數檢查。有須要請自行百度。

參數轉換

參考測試類:TestDateConverterAndJson

URL方式傳值到後端轉換

URL傳參到後端包括 以下三種方式傳參:

@GetMapping("testDateConverter")
public Student testDateConverter(@RequestParam Student student){...}

@GetMapping("testDateConverter")
public Student testDateConverter(Student student){...}

@GetMapping("testDateConverter/{id}")
public Student testDateConverter(@PathVariable Integer id){...}

com.zhirui.lmwy.common.converter包下定義了不少轉換類:

  • StringToDateConverter

    若是實體屬性是Date,經過該轉換器將String轉Date類型。效果和日期屬性上的註解@DatetimeFormat相同。可是啓用該轉換器的時候,實體屬性上的註解@DatetimeFormat再也不生效。

  • StringToDoubleConverter

    若是實體屬性是Double,經過該轉換器將String轉Double類型。

  • StringToIntegerConverter

    若是實體屬性是Integer,經過該轉換器將String轉Integer類型。

請求體方式傳值到後端轉換

請求體方式傳參到後端 包括以下方式:

@PostMapping("testDateConverter2")
public Student testDateConverter2(@RequestBody Student student){...}

com.zhirui.lmwy.common.json.jackson包下定義了JSON的序列化和反序列化方式:

  • deserializer 包下的序列化類

    在@RequestBody接參時候,會調用該包中的序列化類將JSON轉換成實體接參。

  • serializer 包下的序列化類

    用於後端傳值給前端。

後端傳值給前端

com.zhirui.lmwy.common.json.jackson.serializer包下的定義了序列化類 。

在Controller類上添加註解@ResponseBody或者@RestController,那麼後端傳值給前端是JSON方式。

若是是返回值是對象或者集合,會用序列化類進行參數類型轉換。

以下列子中,Student中的兩個屬性日期會轉換成serializer 定義的格式「yyyy-MM-dd HH:mm:ss」。

序列化類`JacksonDateSerializer 的做用至關於在屬性上添加了@JsonFormat(pattern="yyyy-MM-dd") ,實現將Date類型轉換成String,可是添加JacksonDateSerializer @JsonFormat(pattern="yyyy-MM-dd")`失效。
@PostMapping("testDateConverter2")
    public Student testDateConverter2(@RequestBody Student student){
        System.out.println(student);
        Student s = new Student();
        s.setBirth(new Date());
        s.setCreateTime(LocalDateTime.now());
        return s;
    }

異常處理

com.zhirui.lmwy.common.exception.impl中定義了三大類異常:

BusinessException: 通用業務異常
ParamException:參數校驗異常
AuthenticationException:認證失敗異常

Exceptions類定義了快捷拋出異常的一些通用方法,在須要拋出異常時請不要去throw new XXXException(),而是用Exceptions類的方法進行操做。

已經定義了全局異常處理器GlobalExceptionHandler對各類異常能夠進行處理,請不要在controller和service中try..catch

返回值處理

controller的返回前端使用ResultModel類進行封裝,裏面有codemsgdata等字段。

各類場景下的ResultModel返回:

//插入後返回方式, msg:插入成功;插入失敗
    public ResultModel resultInsert(){
        boolean flag = false;
        return ResultModel.resultInsert(flag);
    }

    //更新後返回方式, msg:更新成功;更新失敗
    public ResultModel resultUpdate(){
        boolean flag = false;
        return ResultModel.resultUpdate(flag);
    }

    //刪除後返回方式, msg:刪除成功;刪除失敗
    public ResultModel resultDelete(){
        boolean flag = false;
        return ResultModel.resultDelete(flag);
    }

    //刪除後返回方式, msg:操做成功;操做失敗
    public ResultModel result(){
        boolean flag = false;
        return ResultModel.result(flag);
    }

    //認證失敗返回方式, msg:認證信息異常
    public ResultModel errorTokenMsg(){
        boolean flag = false;
        //若是msg參數爲null,那麼是默認的msg:認證信息異常
        return ResultModel.errorTokenMsg(null);
    }

推薦優先上面的放回方式,若是不能知足,還可使用以下通用的失敗成功的返回方式:

ResultModel.error();  //失敗返回方式
ResultModel.ok();       //成功返回方式

AOP 日誌輸出

  1. 添加座標
<!-- AOP -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- console彩色日誌 -->
<dependency>
    <groupId>org.fusesource.jansi</groupId>
    <artifactId>jansi</artifactId>
    <version>1.18</version>
</dependency>
  1. 定義AOP類實現彩色日誌輸出

參考:com.zhirui.lmwy.common.aop.LogAop

集成 絲襪哥

在common項目中集成了swagger

  1. pom中添加註解
<!-- swagger start -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- swagger end -->
  1. 添加配置

    兩個配置類:

    com.zhirui.lmwy.common.swagger.SwaggerConfiguration

    com.zhirui.lmwy.common.swagger.SwaggerProperties

  2. 設置自定義顯示參數

    在base項目的application.yaml中添加以下配置進行設置:

swagger:
  #  open: true              #是否開啓swagger,在生產環境下須要關閉
  protocol: http          #協議,http或https
  base-package: com.zhirui.lmwy.wms   #必定要寫對,會在這個路徑下掃描controller定義
  title: volcano-base項目
  version: 1.0
  description: volcano-base項目絲襪哥測試
  1. 在controller和model中使用swagger

    controller類中使用參考:com.zhirui.lmwy.wms.demo.web.controller.TestCurdController

    model類中使用參考:com.zhirui.lmwy.wms.demo.web.entity.User

  2. 經過swagger進行http請求

集成 mybatis-plus(下文中稱爲MP)

ORM框架使用 mybatis-plus,簡便了CURD操做
  1. 添加pom

    <!-- mybatis-plus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.2.0</version>
            </dependency>
            <!-- 代碼生成器  start -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-generator</artifactId>
                <version>3.2.0</version>
            </dependency>
            <!-- 代碼生成器須要的引擎模板 -->
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity-engine-core</artifactId>
                <version>2.0</version>
            </dependency>
            <!-- 代碼生成器  end -->
  2. 在yml中進行配置

    mybatis-plus:
      mapper-locations: classpath:mapper/**/*.xml
      global-config:
        db-config:
          id-type: AUTO  #主鍵自增加
  3. 添加配置類配置

    下列代碼中使用了租戶模式,若是隻是單純須要添加分頁插件,只須要以下方式便可:

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        return paginationInterceptor;
    }
    /** 分頁插件: 實現物理分頁 */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        ArrayList<ISqlParser> iSqlParsers = new ArrayList<>();
        TenantSqlParser tenantSqlParser = new TenantSqlParser();
        tenantSqlParser.setTenantHandler(new TenantHandler() {
            @Override
            public Expression getTenantId(boolean where) {
                return new StringValue(tenantId);
            }
    
            @Override
            public String getTenantIdColumn() {
                //指定表中的租戶列
                return "tenant_id";
            }
            @Override
            public boolean doTableFilter(String tableName) {
                return false;
            }
        });
        iSqlParsers.add(tenantSqlParser);
        paginationInterceptor.setSqlParserList(iSqlParsers);
        return paginationInterceptor;
    }

經過MP進行CRUD操做

參考測試類和官網com.zhirui.lmwy.wms.demo.web.controller.TestCurdController

代碼生成器

採用了MP的代碼生成器,實現了兩個代碼生成器。

javasea-volcano-base項目的 src/test/java目錄的 com.zhirui.lmwy.wms包下,按照註釋修改成本身須要的配置運行便可。看我的習慣,推薦用 PrimaryCodeGenerator
  • SencondCodeGenerator

    經過數據庫表生成基本的entity,mapper,controller和service類等基本類。

  • PrimaryCodeGenerator

    SencondCodeGenerator 功能的基礎上,controller,entity中生成swagger的註解。controller、service生成經常使用的crud方法。

集成redis

  1. 添加pom座標
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. yml中進行配置
spring:
    redis:
      host: 127.0.0.1
      port: 6379
      password: zhirui888
      timeout: 2000
      database: 6
      lettuce:
        pool:
          max-active: 8
          max-wait: 1
          max-idle: 8
          min-idle: 0
  1. 配置類中進行配置

    • 定義redis的RedisTemplate

      詳見:com.zhirui.lmwy.common.redis.RedisTemplateConfig
    • 開啓springcache

      詳見:com.zhirui.lmwy.common.redis.RedisCacheConfig
    • redis工具類

      詳見:com.zhirui.lmwy.common.redis.RedisUtils

集成 JWT

添加jwt座標

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
    <scope>compile</scope>
</dependency>

yml中配置jwt

custom:
    jwt:
      header: token
      secret: 666666          #密碼,用於生成簽名
      issuer: volcano         #簽發人
      subject: volcano-jwt    #主題
      audience: web           #簽發的目標
      expire-minutes: 20      #過時時間
    interceptor:
      jwt:
        exclude:
          path: /swagger-resources/**,/api-docs/**,/v2/api-docs/**,/login,/verificationCode,/doc/**,/error/**,/docs,/test/**
      permission:
        exclude:
          path: /swagger-resources/**,/api-docs/**,/v2/api-docs/**,/adminLogin,/sysLogin,/login.html,/verificationCode,/doc/**,/error/**,/docs
      token-timeout:
        exclude:
          path: /swagger-resources/**,/api-docs/**,/v2/api-docs/**,/docs

添加登錄接口

登錄後會將token信息保存到redis

詳見登錄controller:com.zhirui.lmwy.wms.security.controller.LoginController

添加jwt攔截器

攔截到請求後會進行校驗,校驗方式以下:

// 驗證token是否有效
Jws<Claims> jws = JwtUtil.verify(token);

token未過時且合法的才能校驗經過,不然拋出401異常。

詳見jwt攔截器:com.zhirui.lmwy.wms.security.interceptor.JwtInterceptor

在swagger進行token測試

  1. 執行登錄操做,token見返回值中

返回值爲:

{
  "code": 200,
  "msg": "操做成功",
  "data": {
    "loginSysUser": {
      "id": "1",
      "userName": "admin"
    },
    "token": "eyJjdHkiOiJjdHkiLCJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ2b2xjYW5vLWp3dCIsImF1ZCI6IndlYiIsImlzcyI6InZvbGNhbm8iLCJleHAiOjE1Njg3MTI0MDcsImlhdCI6MTU2ODcxMDYwNywianRpIjoiNDM4NjMwMDAwOTlmNDFkNDk1Y2FlOWVkNWUzNDZhOTgifQ.wVZOx-J2knqUxdnRjRXZqr2nf1S-Qwmap2-0nGXJDXM"
  },
  "time": "2019-09-17 16:56:51"
}
  1. 點擊 Authorize按鈕

  1. 將token設置到value中,後面絲襪哥全部的請求都會帶一個叫作「Authorization」的請求頭。

    在jwt攔截器JwtInterceptor中會獲取該請求頭進行校驗。

項目啓動和部署

單獨做爲項目使用

javasea-volcano默認是一個獨立的springboot項目,能夠直接啓動javasea-volcano-base項目,在base項目的基礎上,直接編寫業務代碼便可。

集成到現有的springcloud中

  1. 啓用bootstrap.yml的配置(放開註釋)

    #spring:
    #  cloud:
    #    config:
    #      uri: ${WMS_CONFIG_SERVER_URL}
    #      name: zhirui-lmwy2-wms${WMS_DEVELOPER_NAME:}
    #      profile: ${config.profile:dev}
    #
  2. base項目的pom中開啓對應eureka client的座標,啓動類WmsApplication經過註解@EnableDiscoveryClient啓用eureka client。

    <!-- springboot 1.X -->
    <!--<dependency>-->
       <!--<groupId>org.springframework.cloud</groupId>-->
       <!--<artifactId>spring-cloud-starter-eureka</artifactId>-->
    <!--</dependency>-->
    <!-- springboot 2.X -->
    <!--<dependency>-->
       <!--<groupId>org.springframework.cloud</groupId>-->
       <!--<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
    <!--</dependency>-->
  3. IDE中配置vm參數,使用已經已經存在的eureka註冊中心配置中心

    在IDE中配置VM參數只能是做爲測試,若是須要部署後生效,那麼須要配置到服務器的環境變量或者在啓動的java -jar後添加配置。以後我會添加關於服務部署的文章。
    -Dmultipart-location=D:/wms/temp
    -DDiskLocation=D:/wms/
    -DWMS_CONFIG_SERVER_URL=http://192.168.1.230:8861
    -DWMS_EUREKA_SERVER_URL=http://192.168.1.230:8090/eureka/
    -DWMS_DEVELOPER_NAME=-longxiaonan
    -Dconfig.profile=dev

Maven方式打包

mvn clean package -Dmaven.test.skip=true
相關文章
相關標籤/搜索