<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>

          一份 Spring Boot 項(xiàng)目搭建模板

          共 3380字,需瀏覽 7分鐘

           ·

          2020-11-01 02:27

          作者:不一樣的科技宅?

          來源:juejin.im/post/6844904083942277127

          前言

          建立一個(gè)全新的項(xiàng)目,或者把舊的龐大的項(xiàng)目,進(jìn)行拆分成多個(gè)項(xiàng)目。在建立新的項(xiàng)目中,經(jīng)常需要做一些重復(fù)的工作,比如說拷貝一下常用的工具類,通用代碼等等。所以就可以做一個(gè)基礎(chǔ)的項(xiàng)目方便使用,在經(jīng)歷新項(xiàng)目的時(shí)候,直接在基礎(chǔ)項(xiàng)目上進(jìn)行簡(jiǎn)單配置就可以開發(fā)業(yè)務(wù)代碼了。

          基礎(chǔ)項(xiàng)目該包含哪些東西。

          • Swagger在線接口文檔。
          • CodeGenerator 代碼生成器。
          • 統(tǒng)一返回。
          • 通用的分頁對(duì)象。
          • 常用工具類。
          • 全局異常攔截。
          • 錯(cuò)誤枚舉。
          • 自定義異常。
          • 多環(huán)境配置文件。
          • Maven多環(huán)境配置。
          • 日志配置。
          • JenkinsFile。

          下面我們分別看下:

          Swagger

          寫接口文檔通常是一件比較頭疼的事情,然而swagger就用是用來幫我們解決這個(gè)問題的。可以在線生成接口文檔,并且可以在頁面上進(jìn)行測(cè)試。可以非常清楚的顯示,請(qǐng)求數(shù)據(jù)已經(jīng)響應(yīng)數(shù)據(jù)。當(dāng)然這一切都需要在代碼中進(jìn)行配置。注意的點(diǎn):接口文檔只能在測(cè)試/開發(fā)環(huán)境開啟,其他環(huán)境請(qǐng)關(guān)閉。

          常用的Swagger注解

          • @Api用于Controller`
          • @ApiOperation用于Controller內(nèi)的方法。`
          • @ApiResponses用于標(biāo)識(shí)接口返回?cái)?shù)據(jù)的類型。`
          • @ApiModel用于標(biāo)識(shí)類的名稱`
          • @ApiModelProperty用于標(biāo)識(shí)屬性的名稱`

          案例

          @RestController
          @Api(tags?=?"用戶")
          @AllArgsConstructor
          @RequestMapping("/user")
          public?class?UserController?{
          ????private?IUserService?userService;

          ????
          ????@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?{
          ????
          ????@ApiModelProperty("用戶狀態(tài)")
          ????@NotEmpty(message?=?"用戶狀態(tài)不能為空")
          ????@Range(min?=?-1?,?max?=?1?,?message?=?"用戶狀態(tài)有誤")
          ????private?String?status;

          }

          對(duì)應(yīng)的swagger的配置可以查看基礎(chǔ)項(xiàng)目?jī)?nèi)的SwaggerConfiguration.java.

          CodeGenerator代碼生成器。

          mybatis_plus代碼生成器可以幫我們生成

          entity,service,serviceImpl,mapper,mapper.xml。省去了建立一大堆實(shí)體類的麻煩。

          由于配置太長(zhǎng)這里就不貼出來了,對(duì)應(yīng)的CodeGenerator的配置可以查看基礎(chǔ)項(xiàng)目?jī)?nèi)的CodeGenerator.java.

          常用的封裝

          統(tǒng)一返回 ResultVo

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

          @Data
          @ApiModel("固定返回格式")
          public?class?ResultVo?{
          ????
          ????@ApiModelProperty("錯(cuò)誤碼")
          ????private?Integer?code;

          ????
          ????@ApiModelProperty("提示信息")
          ????private?String?message;

          ????
          ????@ApiModelProperty("響應(yīng)數(shù)據(jù)")
          ????private?Object?data;

          }

          抽象表單 BaseForm

          public?abstract?class?BaseForm?{
          ????
          ????public?abstract?T?buildEntity();

          }

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

          @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);
          ????}

          重構(gòu)一下,感覺清爽了一些。

          @Override
          public?boolean?addUser(AddUserForm?userForm)?{
          ????User?user?=?new?User();
          ????BeanUtils.copyProperties(this,user);
          ????return?save(user);
          }

          使用BaseForm進(jìn)行重構(gòu) AddUserForm 繼承 BaseForm并重寫buildEntity

          @Data
          @EqualsAndHashCode(callSuper?=?false)
          public?class?AddUserForm?extends?BaseForm?{
          ????
          ????private?String?nickname;

          ????private?Date?birthday;
          ????
          ????private?String?username;
          ????
          ????private?String?password;

          ????
          ????@Override
          ????public?User?buildEntity()?{
          ????????User?user?=?new?User();
          ????????BeanUtils.copyProperties(this,user);
          ????????return?user;
          ????}
          }
          @Override
          public?boolean?addUser(AddUserForm?userForm)?{
          ????return?save(userForm.buildEntity());
          }

          上面的代碼有沒有種似曾相識(shí)的感覺,很多情況都是將接受到的參數(shù),轉(zhuǎn)變成對(duì)應(yīng)的實(shí)體類然后保存或者更新。所以對(duì)于這類的form可以繼承baseform并實(shí)現(xiàn)buildEntity()這樣可以更加符合面向?qū)ο螅?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">service不需要關(guān)心form如何轉(zhuǎn)變成entity,只需要在使用的時(shí)候調(diào)用buildEntity()即可,尤其是在form ->entity相對(duì)復(fù)雜的時(shí)候,這樣做可以減少service內(nèi)的代碼。讓代碼邏輯看起來更加清晰。

          通用的分頁對(duì)象

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

          PageForm

          @Data
          @ApiModel(value?=?"分頁數(shù)據(jù)",?description?=?"分頁需要的表單數(shù)據(jù)")
          public?class?PageForm>{
          ????
          ????@ApiModelProperty(value?=?"頁碼?從第一頁開始?1")
          ????@Min(value?=?1,?message?=?"頁碼輸入有誤")
          ????private?Integer?current;

          ????
          ????@ApiModelProperty(value?=?"每頁顯示的數(shù)量?范圍在1~100")
          ????@Range(min?=?1,?max?=?100,?message?=?"每頁顯示的數(shù)量輸入有誤")
          ????private?Integer?size;

          ????
          ????@ApiModelProperty(hidden?=?true)
          ????public?T?calcCurrent(){
          ????????current?=?(current?-?1?)?*?size;
          ????????return?(T)?this;
          ????}
          }

          PageVo

          @Data
          public?class?PageVo?{
          ????@ApiModelProperty(value?=?"分頁數(shù)據(jù)")
          ????private?List?records;
          ????@ApiModelProperty(value?=?"總條數(shù)")
          ????private?Integer?total;
          ????@ApiModelProperty(value?=?"總頁數(shù)")
          ????private?Integer?pages;
          ????@ApiModelProperty(value?=?"當(dāng)前頁")
          ????private?Integer?current;
          ????@ApiModelProperty(value?=?"查詢數(shù)量")
          ????private?Integer?size;
          ????@ApiModelProperty(hidden?=?true)
          ????public?PageVo?setCurrentAndSize(PageForm?pageForm){
          ????????BeanUtils.copyProperties(pageForm,this);
          ????????return?this;
          ????}
          ????@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?{
          ????
          ????@ApiModelProperty("用戶狀態(tài)")
          ????@NotEmpty(message?=?"用戶狀態(tài)不能為空")
          ????@Range(min?=?-1?,?max?=?1?,?message?=?"用戶狀態(tài)有誤")
          ????private?String?status;

          }
          UserServiceImpl
          @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;
          }

          private?Integer?countUser(String?status){
          ????return?count(new?QueryWrapper().eq("status",status));
          }
          UserController
          @ApiOperation("獲取用戶列表")
          @GetMapping("/listUser")
          @ApiResponses(
          ????????@ApiResponse(code?=?200,?message?=?"操作成功",?response?=?UserVo.class)
          )
          public?ResultVo?listUser(@Validated?ListUserForm?listUserForm){
          ????return?ResultVoUtil.success(userService.listUser(listUserForm));
          }
          注意的點(diǎn)
          • PageVo在實(shí)例化的時(shí)候需要設(shè)置當(dāng)前頁每頁顯示的數(shù)量 可以調(diào)用setCurrentAndSize()完成。
          • 進(jìn)行分頁查詢的時(shí)候,需要計(jì)算偏移量。listUserForm.calcCurrent()

          為什么要計(jì)算偏移量呢?

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

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

          自帶的分頁查詢?cè)诖罅繑?shù)據(jù)下,會(huì)出現(xiàn)性能問題。

          常用工具類

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

          異常處理

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

          • 異常信息拋出 -> ControllerAdvice 進(jìn)行捕獲格式化輸出內(nèi)容
          • 手動(dòng)拋出CustomException并傳入ReulstEnum ——> 進(jìn)行捕獲錯(cuò)誤信息輸出錯(cuò)誤信息。

          自定義異常

          @Data
          @EqualsAndHashCode(callSuper?=?false)
          public?class?CustomException?extends?RuntimeException?{
          ????
          ????private?final?Integer?code;

          ????
          ????private?final?String?method;

          ????
          ????public?CustomException(ResultEnum?resultEnum,?String?method)?{
          ????????super(resultEnum.getMsg());
          ????????this.code?=?resultEnum.getCode();
          ????????this.method?=?method;
          ????}

          ????
          ????public?CustomException(Integer?code,?String?message,?String?method)?{
          ????????super(message);
          ????????this.code?=?code;
          ????????this.method?=?method;
          ????}

          }

          錯(cuò)誤信息枚舉

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

          @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;
          ????}

          ????
          ????public?static?ResultEnum?getByCode(int?code){
          ????????for?(ResultEnum?resultEnum?:?ResultEnum.values())?{
          ????????????if(code?==?resultEnum.getCode()){
          ????????????????return?resultEnum;
          ????????????}
          ????????}
          ????????return?null;
          ????}

          }

          全局異常攔截

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

          @Slf4j
          @RestControllerAdvice
          public?class?GlobalExceptionHandling?{
          ????
          ????@ExceptionHandler(value?=?CustomException.class)
          ????public?ResultVo?processException(CustomException?e)?{
          ????????log.error("位置:{}?->?錯(cuò)誤信息:{}",?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
          @ApiOperation("刪除用戶")
          @DeleteMapping("/deleteUser/{id}")
          public?ResultVo?deleteUser(@PathVariable("id")?String?id){
          ????userService.deleteUser(id);
          ????return?ResultVoUtil.success();
          }
          Service
          @Override
          public?void?deleteUser(String?id)?{
          ????
          ????if(!removeById(id)){
          ????????throw?new?CustomException(ResultEnum.DELETE_ERROR,?MethodUtil.getLineInfo());
          ????}
          }
          結(jié)果

          將報(bào)錯(cuò)代碼所在的文件第多少行都打印出來。方便排查。

          注意的點(diǎn)

          所有手動(dòng)拋出的錯(cuò)誤信息,都應(yīng)在錯(cuò)誤信息枚舉ResultEnum進(jìn)行統(tǒng)一維護(hù)。不同的業(yè)務(wù)使用不同的錯(cuò)誤碼。方便在報(bào)錯(cuò)時(shí)進(jìn)行分辨。快速定位問題。

          多環(huán)境配置

          SpringBoot多環(huán)境配置

          對(duì)于一個(gè)項(xiàng)目來講基本都4有個(gè)環(huán)境dev,test,pre,prod,對(duì)于SpringBoot項(xiàng)目多建立幾個(gè)配置文件就可以了。然后啟動(dòng)的時(shí)候可以通過配置spring.profiles.active 來選擇啟動(dòng)的環(huán)境。

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

          Maven多環(huán)境配置

          假如想在打包的時(shí)候動(dòng)態(tài)指定環(huán)境,這個(gè)時(shí)候就需要借助Maven的xml來實(shí)現(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 會(huì)發(fā)現(xiàn)spring.profiles.active=@activatedProperties@ 發(fā)生了改變。

          日志配置

          采用logback日志配置

          JenkinsFile

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

          JenkinsFileDemo https://gitee.com/huangxunhui/basic_project/blob/master/Jenkinsfile

          代碼地址

          https://gitee.com/huangxunhui/basic_project.git


          好文章,我在看

          瀏覽 49
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  91CM229 跳蛋购物 突袭做爱 1080P - 美竹玲 | 欧美aaa在线 | 亚洲精品一区二区三区2023年最新 | 高清无码视频在线看 | 先锋资源日韩 |