<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一個 SpringBoot 項目都有哪些東西?

          共 4243字,需瀏覽 9分鐘

           ·

          2020-11-04 10:46

          注意文末有最新Java實戰(zhàn)項目面試題



          另外,雙11了,今天開始,限量秒殺

          1核2G,1年62元,3年200元,限時秒殺

          1核2G,1年62元,3年200元,限時秒殺

          1核2G,1年62元,3年200元,限時秒殺


          作者:不一樣的科技宅?

          來源:juejin.im/post/6844904083942277127

          前言

          建立一個全新的項目,或者把舊的龐大的項目,進行拆分成多個項目。在建立新的項目中,經(jīng)常需要做一些重復的工作,比如說拷貝一下常用的工具類,通用代碼等等。

          所以就可以做一個基礎的項目方便使用,在經(jīng)歷新項目的時候,直接在基礎項目上進行簡單配置就可以開發(fā)業(yè)務代碼了。

          基礎項目該包含哪些東西。

          • Swagger在線接口文檔。

          • CodeGenerator 代碼生成器。

          • 統(tǒng)一返回。

          • 通用的分頁對象。

          • 常用工具類。

          • 全局異常攔截。

          • 錯誤枚舉。

          • 自定義異常。

          • 多環(huán)境配置文件。

          • Maven多環(huán)境配置。

          • 日志配置。

          • JenkinsFile。

          ?

          可以在評論區(qū)進行補充

          ?

          Swagger

          寫接口文檔通常是一件比較頭疼的事情,然而swagger就用是用來幫我們解決這個問題的。可以在線生成接口文檔,并且可以在頁面上進行測試。

          可以非常清楚的顯示,請求數(shù)據(jù)已經(jīng)響應數(shù)據(jù)。當然這一切都需要在代碼中進行配置。

          「注意的點:接口文檔只能在測試/開發(fā)環(huán)境開啟,其他環(huán)境請關閉。」

          常用的Swagger注解

          • @Api用于Controller

          • @ApiOperation用于Controller內(nèi)的方法。

          • @ApiResponses用于標識接口返回數(shù)據(jù)的類型。

          • @ApiModel用于標識類的名稱

          • @ApiModelProperty用于標識屬性的名稱

          案例

          @RestController??
          @Api(tags?=?"用戶")??
          @AllArgsConstructor??
          @RequestMapping("/user")??
          public?class?UserController?{??
          ??
          ????private?IUserService?userService;??
          ??
          ????/**??
          ?????*?獲取用戶列表??
          ?????*?@param?listUserForm?表單數(shù)據(jù)??
          ?????*?@return?用戶列表??
          ?????*/??
          ????@ApiOperation("獲取用戶列表")??
          ????@GetMapping("/listUser")??
          ????@ApiResponses(??
          ????????????@ApiResponse(code?=?200,?message?=?"操作成功",?response?=?UserVo.class)??
          ????)??
          ????public?ResultVo?listUser(@Validated?ListUserForm?listUserForm){??
          ????????return?ResultVoUtil.success(userService.listUser(listUserForm));??
          ????}??
          ??
          }??
          ?
          @Data??
          @ApiModel("獲取用戶列表需要的表單數(shù)據(jù)")??
          @EqualsAndHashCode(callSuper?=?false)??
          public?class?ListUserForm?extends?PageForm?{??
          ??
          ????/**??
          ?????*?用戶狀態(tài)??
          ?????*/??
          ????@ApiModelProperty("用戶狀態(tài)")??
          ????@NotEmpty(message?=?"用戶狀態(tài)不能為空")??
          ????@Range(min?=??-1?,?max?=?1?,?message?=?"用戶狀態(tài)有誤")??
          ????private?String?status;??
          ??
          }??

          對應的swagger的配置可以查看基礎項目內(nèi)的SwaggerConfiguration.java.

          CodeGenerator代碼生成器。

          mybatis_plus代碼生成器可以幫我們生成entity,service,serviceImpl,mapper,mapper.xml。省去了建立一大堆實體類的麻煩。

          由于配置太長這里就不貼出來了,對應的CodeGenerator的配置可以查看基礎項目內(nèi)的CodeGenerator.java.


          常用的封裝

          統(tǒng)一返回 ResultVo

          將所有的接口的響應數(shù)據(jù)的格式進行統(tǒng)一。

          @Data??
          @ApiModel("固定返回格式")??
          public?class?ResultVo?{??
          ??
          ????/**??
          ?????*?錯誤碼??
          ?????*/??
          ????@ApiModelProperty("錯誤碼")??
          ????private?Integer?code;??
          ??
          ????/**??
          ?????*?提示信息??
          ?????*/??
          ????@ApiModelProperty("提示信息")??
          ????private?String?message;??
          ??
          ????/**??
          ?????*?具體的內(nèi)容??
          ?????*/??
          ????@ApiModelProperty("響應數(shù)據(jù)")??
          ????private?Object?data;??
          ??
          }??

          抽象表單 BaseForm

          public?abstract?class?BaseForm?{??
          ??
          ????/**??
          ?????*?獲取實例??
          ?????*?@return?返回實體類??
          ?????*/??
          ????public?abstract?T?buildEntity();??
          ??
          }??

          有小伙伴可能有疑問了,這個類有啥用呢。先看一下,下面的代碼。

          /**??
          ?*?添加用戶??
          ?*?@param?userForm?表單數(shù)據(jù)??
          ?*?@return?true?或者?false??
          ?*/??
          @Override??
          public?boolean?addUser(AddUserForm?userForm)?{??
          ????User?user?=?new?User();??
          ????user.setNickname(userForm.getNickname());??
          ????user.setBirthday(userForm.getBirthday());??
          ????user.setUsername(userForm.getUsername());??
          ????user.setPassword(userForm.getPassword());??
          ????return?save(user);??
          }??

          重構一下,感覺清爽了一些。

          /**??
          ?*?添加用戶??
          ?*?@param?userForm?表單數(shù)據(jù)??
          ?*?@return?true?或者?false??
          ?*/??
          @Override??
          public?boolean?addUser(AddUserForm?userForm)?{??
          ????User?user?=?new?User();??
          ????BeanUtils.copyProperties(this,user);??
          ????return?save(user);??
          }??
          ?

          使用BaseForm進行重構 AddUserForm 繼承 BaseForm并重寫buildEntity

          @Data??
          @EqualsAndHashCode(callSuper?=?false)??
          public?class?AddUserForm?extends?BaseForm?{??
          ??
          ????/**??
          ?????*?昵稱??
          ?????*/??
          ????private?String?nickname;??
          ??
          ????/**??
          ?????*?生日??
          ?????*/??
          ????private?Date?birthday;??
          ??
          ????/**??
          ?????*?用戶名??
          ?????*/??
          ????private?String?username;??
          ??
          ????/**??
          ?????*?密碼??
          ?????*/??
          ????private?String?password;??
          ??
          ????/**??
          ?????*?構造實體??
          ?????*?@return?實體對象??
          ?????*/??
          ????@Override??
          ????public?User?buildEntity()?{??
          ????????User?user?=?new?User();??
          ????????BeanUtils.copyProperties(this,user);??
          ????????return?user;??
          ????}??
          }??
          /**??
          ?*?添加用戶??
          ?*?@param?userForm?表單數(shù)據(jù)??
          ?*?@return?true?或者?false??
          ?*/??
          @Override??
          public?boolean?addUser(AddUserForm?userForm)?{??
          ????return?save(userForm.buildEntity());??
          }??

          上面的代碼有沒有種似曾相識的感覺,很多情況都是將接受到的參數(shù),轉(zhuǎn)變成對應的實體類然后「保存」或者「更新」

          所以對于這類的form可以繼承baseform并實現(xiàn)buildEntity()這樣可以更加符合面向?qū)ο螅?code style>service不需要關心form如何轉(zhuǎn)變成entity,只需要在使用的時候調(diào)用buildEntity()即可,尤其是在form?->?entity相對復雜的時候,這樣做可以減少service內(nèi)的代碼。讓代碼邏輯看起來更加清晰。


          通用的分頁對象

          涉及到查詢的時候,絕大多數(shù)都需要用到分頁,所以說封裝分頁對象就很有必要。可以注意下?PageForm.calcCurrent()PageVo.setCurrentAndSize()PageVo.setTotal()這個幾個方法。

          PageForm

          @Data??
          @ApiModel(value?=?"分頁數(shù)據(jù)",?description?=?"分頁需要的表單數(shù)據(jù)")??
          public?class?PageForm>{??
          ??
          ????/**??
          ?????*?頁碼??
          ?????*/??
          ????@ApiModelProperty(value?=?"頁碼?從第一頁開始?1")??
          ????@Min(value?=?1,?message?=?"頁碼輸入有誤")??
          ????private?Integer?current;??
          ??
          ????/**??
          ?????*?每頁顯示的數(shù)量??
          ?????*/??
          ????@ApiModelProperty(value?=?"每頁顯示的數(shù)量?范圍在1~100")??
          ????@Range(min?=?1,?max?=?100,?message?=?"每頁顯示的數(shù)量輸入有誤")??
          ????private?Integer?size;??
          ??
          ????/**??
          ?????*?計算當前頁?,方便mysql?進行分頁查詢??
          ?????*?@return?返回?pageForm??
          ?????*/??
          ????@ApiModelProperty(hidden?=?true)??
          ????public?T?calcCurrent(){??
          ????????current?=?(current?-?1?)?*?size;??
          ????????return?(T)?this;??
          ????}??
          }??

          PageVo

          @Data??
          public?class?PageVo?{??
          ????/**??
          ?????*?分頁數(shù)據(jù)??
          ?????*/??
          ????@ApiModelProperty(value?=?"分頁數(shù)據(jù)")??
          ????private?List?records;??
          ????/**??
          ?????*?總條數(shù)??
          ?????*/??
          ????@ApiModelProperty(value?=?"總條數(shù)")??
          ????private?Integer?total;??
          ??
          ????/**??
          ?????*?總頁數(shù)??
          ?????*/??
          ????@ApiModelProperty(value?=?"總頁數(shù)")??
          ????private?Integer?pages;??
          ??
          ????/**??
          ?????*?當前頁??
          ?????*/??
          ????@ApiModelProperty(value?=?"當前頁")??
          ????private?Integer?current;??
          ??
          ????/**??
          ?????*?查詢數(shù)量??
          ?????*/??
          ????@ApiModelProperty(value?=?"查詢數(shù)量")??
          ????private?Integer?size;??
          ??
          ????/**??
          ?????*?設置當前頁和每頁顯示的數(shù)量??
          ?????*?@param?pageForm?分頁表單??
          ?????*?@return?返回分頁信息??
          ?????*/??
          ????@ApiModelProperty(hidden?=?true)??
          ????public?PageVo?setCurrentAndSize(PageForm?pageForm){??
          ????????BeanUtils.copyProperties(pageForm,this);??
          ????????return?this;??
          ????}??
          ??
          ????/**??
          ?????*?設置總記錄數(shù)??
          ?????*?@param?total?總記錄數(shù)??
          ?????*/??
          ????@ApiModelProperty(hidden?=?true)??
          ????public?void?setTotal(Integer?total)?{??
          ????????this.total?=?total;??
          ????????this.setPages(this.total?%?this.size?>?0???this.total?/?this.size?+?1?:?this.total?/?this.size);??
          ????}??
          }??

          案例

          ListUserForm
          @Data??
          @ApiModel("獲取用戶列表需要的表單數(shù)據(jù)")??
          @EqualsAndHashCode(callSuper?=?false)??
          public?class?ListUserForm?extends?PageForm?{??
          ??
          ????/**??
          ?????*?用戶狀態(tài)??
          ?????*/??
          ????@ApiModelProperty("用戶狀態(tài)")??
          ????@NotEmpty(message?=?"用戶狀態(tài)不能為空")??
          ????@Range(min?=??-1?,?max?=?1?,?message?=?"用戶狀態(tài)有誤")??
          ????private?String?status;??
          ??
          }??
          UserServiceImpl
          /**??
          ?*?獲取用戶列表??
          ?*?@param?listUserForm?表單數(shù)據(jù)??
          ?*?@return?用戶列表??
          ?*/??
          @Override??
          public?PageVo?listUser(ListUserForm?listUserForm)?{??
          ????PageVo?pageVo?=?new?PageVo().setCurrentAndSize(listUserForm);??
          ????pageVo.setTotal(countUser(listUserForm.getStatus()));??
          ????pageVo.setRecords(userMapper.listUser(listUserForm.calcCurrent()));??
          ????return?pageVo;??
          }??
          ??
          /**??
          ?*?獲取用戶數(shù)量??
          ?*?@param?status?狀態(tài)??
          ?*?@return?用戶數(shù)量??
          ?*/??
          private?Integer?countUser(String?status){??
          ????return?count(new?QueryWrapper().eq("status",status));??
          }??
          UserController
          /**??
          ?*?獲取用戶列表??
          ?*?@param?listUserForm?表單數(shù)據(jù)??
          ?*?@return?用戶列表??
          ?*/??
          @ApiOperation("獲取用戶列表")??
          @GetMapping("/listUser")??
          @ApiResponses(??
          ????????@ApiResponse(code?=?200,?message?=?"操作成功",?response?=?UserVo.class)??
          )??
          public?ResultVo?listUser(@Validated?ListUserForm?listUserForm){??
          ????return?ResultVoUtil.success(userService.listUser(listUserForm));??
          }??

          注意的點
          • PageVo在實例化的時候需要設置「當前頁」「每頁顯示的數(shù)量」?可以調(diào)用setCurrentAndSize()完成。

          • 進行分頁查詢的時候,需要計算偏移量。listUserForm.calcCurrent()

          為什么要計算偏移量呢?

          • 假如查詢第1頁每頁顯示10條記錄,前端傳遞過來的參數(shù)是current=1&&size=10,這個時候limit 1,10沒有問題。

          • 假如查詢第2頁每頁顯示10條記錄,前端傳遞過來的參數(shù)是current=2&&size=10,這個時候limit 2,10就有問題,實際應該是limit 10,10calcCurrent()的作用就是如此

          為什么不用MybatisPlus自帶的分頁插件呢?

          ?

          自帶的分頁查詢在大量數(shù)據(jù)下,會出現(xiàn)性能問題。

          ?

          常用工具類

          常用工具類可以根據(jù)自己的開發(fā)習慣引入。


          異常處理

          異常處理的大致流程主要如下。

          • 異常信息拋出 ->?ControllerAdvice?進行捕獲格式化輸出內(nèi)容

          • 手動拋出CustomException并傳入ReulstEnum?——> 進行捕獲錯誤信息輸出錯誤信息。

          自定義異常

          @Data??
          @EqualsAndHashCode(callSuper?=?false)??
          public?class?CustomException?extends?RuntimeException?{??
          ??
          ????/**??
          ?????*?狀態(tài)碼??
          ?????*/??
          ????private?final?Integer?code;??
          ??
          ????/**??
          ?????*?方法名稱??
          ?????*/??
          ????private?final?String?method;??
          ??
          ??
          ????/**??
          ?????*?自定義異常??
          ?????*??
          ?????*?@param?resultEnum?返回枚舉對象??
          ?????*?@param?method?????方法??
          ?????*/??
          ????public?CustomException(ResultEnum?resultEnum,?String?method)?{??
          ????????super(resultEnum.getMsg());??
          ????????this.code?=?resultEnum.getCode();??
          ????????this.method?=?method;??
          ????}??
          ??
          ????/**??
          ?????*?@param?code????狀態(tài)碼??
          ?????*?@param?message?錯誤信息??
          ?????*?@param?method??方法??
          ?????*/??
          ????public?CustomException(Integer?code,?String?message,?String?method)?{??
          ????????super(message);??
          ????????this.code?=?code;??
          ????????this.method?=?method;??
          ????}??
          ??
          }??

          錯誤信息枚舉

          根據(jù)業(yè)務進行添加。

          @Getter??
          public?enum?ResultEnum?{??
          ??
          ????/**??
          ?????*?未知異常??
          ?????*/??
          ????UNKNOWN_EXCEPTION(100,?"未知異常"),??
          ??
          ????/**??
          ?????*?添加失敗??
          ?????*/??
          ????ADD_ERROR(103,?"添加失敗"),??
          ??
          ????/**??
          ?????*?更新失敗??
          ?????*/??
          ????UPDATE_ERROR(104,?"更新失敗"),??
          ??
          ????/**??
          ?????*?刪除失敗??
          ?????*/??
          ????DELETE_ERROR(105,?"刪除失敗"),??
          ??
          ????/**??
          ?????*?查找失敗??
          ?????*/??
          ????GET_ERROR(106,?"查找失敗"),??
          ??
          ????;??
          ??
          ????private?Integer?code;??
          ??
          ????private?String?msg;??
          ??
          ????ResultEnum(Integer?code,?String?msg)?{??
          ????????this.code?=?code;??
          ????????this.msg?=?msg;??
          ????}??
          ??
          ????/**??
          ?????*?通過狀態(tài)碼獲取枚舉對象??
          ?????*?@param?code?狀態(tài)碼??
          ?????*?@return?枚舉對象??
          ?????*/??
          ????public?static?ResultEnum?getByCode(int?code){??
          ????????for?(ResultEnum?resultEnum?:?ResultEnum.values())?{??
          ????????????if(code?==?resultEnum.getCode()){??
          ????????????????return?resultEnum;??
          ????????????}??
          ????????}??
          ????????return?null;??
          ????}??
          ??
          }??

          全局異常攔截

          全局異常攔截是使用@ControllerAdvice進行實現(xiàn),常用的異常攔截配置可以查看 GlobalExceptionHandling。

          @Slf4j??
          @RestControllerAdvice??
          public?class?GlobalExceptionHandling?{??
          ??
          ????/**??
          ?????*?自定義異常??
          ?????*/??
          ????@ExceptionHandler(value?=?CustomException.class)??
          ????public?ResultVo?processException(CustomException?e)?{??
          ????????log.error("位置:{}?->?錯誤信息:{}",?e.getMethod()?,e.getLocalizedMessage());??
          ????????return?ResultVoUtil.error(Objects.requireNonNull(ResultEnum.getByCode(e.getCode())));??
          ????}??
          ??
          ????/**??
          ?????*?通用異常??
          ?????*/??
          ????@ResponseStatus(HttpStatus.OK)??
          ????@ExceptionHandler(Exception.class)??
          ????public?ResultVo?exception(Exception?e)?{??
          ????????e.printStackTrace();??
          ????????return?ResultVoUtil.error(ResultEnum.UNKNOWN_EXCEPTION);??
          ????}??
          }??

          案例

          Controller
          /**??
          ?*?刪除用戶??
          ?*?@param?id?用戶編號??
          ?*?@return?成功或者失敗??
          ?*/??
          @ApiOperation("刪除用戶")??
          @DeleteMapping("/deleteUser/{id}")??
          public?ResultVo?deleteUser(@PathVariable("id")?String?id){??
          ????userService.deleteUser(id);??
          ????return?ResultVoUtil.success();??
          }??
          Service
          /**??
          ?*?刪除用戶??
          ?*?@param?id?id??
          ?*/??
          @Override??
          public?void?deleteUser(String?id)?{??
          ????//?如果刪除失敗拋出異常。?--?演示而已不推薦這樣干??
          ????if(!removeById(id)){??
          ????????throw?new?CustomException(ResultEnum.DELETE_ERROR,?MethodUtil.getLineInfo());??
          ????}??
          }??
          結果

          「將報錯代碼所在的文件第多少行都打印出來。方便排查。」

          注意的點

          所有手動拋出的錯誤信息,都應在錯誤信息枚舉ResultEnum進行統(tǒng)一維護。不同的業(yè)務使用不同的錯誤碼。方便在報錯時進行分辨。快速定位問題。


          多環(huán)境配置

          SpringBoot多環(huán)境配置

          對于一個項目來講基本都4有個環(huán)境dev,test,pre,prod,對于SpringBoot項目多建立幾個配置文件就可以了。

          然后啟動的時候可以通過配置spring.profiles.active?來選擇啟動的環(huán)境。

          java?-jar?BasicProject.jar?--spring.profiles.active=prod??

          Maven多環(huán)境配置

          假如想在打包的時候動態(tài)指定環(huán)境,這個時候就需要借助Maven的xml來實現(xiàn)。

          配置XML
          ??
          ??
          ??????
          ??????????
          ????????dev??
          ??????????
          ????????????true??
          ????????
          ??
          ??????????
          ????????????dev??
          ????????
          ??
          ????
          ??
          ??????
          ??????????
          ????????test??
          ??????????
          ????????????test??
          ????????
          ??
          ????
          ??
          ??????
          ??????????
          ????????pre??
          ??????????
          ????????????pre??
          ????????
          ??
          ????
          ??
          ??????
          ??????????
          ????????prod??
          ??????????
          ????????????prod??
          ????????
          ??
          ????
          ??
          ??
          更改application.yml
          spring:??
          ??profiles:??
          ????#?選擇環(huán)境??
          ????active:?@activatedProperties@??
          使用案例
          mvn?clean?package?-P?prod??
          mvn?clean?package?-P?pre??
          mvn?clean?package?-P?test??

          打包完可以解壓開查看application.yml?會發(fā)現(xiàn)spring.profiles.active=@activatedProperties@?發(fā)生了改變。


          日志配置

          采用logback日志配置,參考

          https://gitee.com/huangxunhui/basic_project/blob/master/src/main/resources/logback-spring.xml

          JenkinsFile

          JenkinsFile肯定顧名思義是給jenkins用的。主要是配置項目根據(jù)如何進行構建并發(fā)布到不同的環(huán)境。需要去了解pipeline語法,以及如何配置jenkins

          結尾

          如果覺得對你有幫助,可以隨手點個在看哦,謝謝。

          ---END---
          文末福利



          瀏覽 48
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品久久久久久久免费 | 国产之级淫秽 | 无码免费视频在线观看 | 无码系列亚洲精品国产A√现线 | 深爱五月丁香 |