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

          一個(gè) SpringBoot 項(xiàng)目該包含哪些?

          共 3975字,需瀏覽 8分鐘

           ·

          2020-11-21 04:23

          程序員的成長(zhǎng)之路
          互聯(lián)網(wǎng)/程序員/技術(shù)/資料共享?
          關(guān)注


          閱讀本文大概需要 9?分鐘。

          來(lái)自:https://juejin.cn/post/6844904083942277127

          前言

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

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

          • Swagger在線接口文檔。

          • CodeGenerator 代碼生成器。

          • 統(tǒng)一返回。

          • 通用的分頁(yè)對(duì)象。

          • 常用工具類(lèi)。

          • 全局異常攔截。

          • 錯(cuò)誤枚舉。

          • 自定義異常。

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

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

          • 日志配置。

          • JenkinsFile。

          可以在評(píng)論區(qū)進(jìn)行補(bǔ)充

          Swagger

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

          常用的Swagger注解

          • @Api用于Controller

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

          • @ApiResponses用于標(biāo)識(shí)接口返回?cái)?shù)據(jù)的類(lèi)型。

          • @ApiModel用于標(biāo)識(shí)類(lèi)的名稱(chēng)

          • @ApiModelProperty用于標(biāo)識(shí)屬性的名稱(chēng)

          案例

          @RestController
          @Api(tags?=?"用戶(hù)")
          @AllArgsConstructor
          @RequestMapping("/user")
          public?class?UserController?{

          ????private?IUserService?userService;

          ????/**
          ?????*?獲取用戶(hù)列表
          ?????*?@param?listUserForm?表單數(shù)據(jù)
          ?????*?@return?用戶(hù)列表
          ?????*/

          ????@ApiOperation("獲取用戶(hù)列表")
          ????@GetMapping("/listUser")
          ????@ApiResponses(
          ????????????@ApiResponse(code?=?200,?message?=?"操作成功",?response?=?UserVo.class)
          ????)
          ????public?ResultVo?listUser(@Validated?ListUserForm?listUserForm){
          ????????return?ResultVoUtil.success(userService.listUser(listUserForm));
          ????}

          }
          復(fù)制代碼
          @Data
          @ApiModel("獲取用戶(hù)列表需要的表單數(shù)據(jù)")
          @EqualsAndHashCode(callSuper?=?false)
          public?class?ListUserForm?extends?PageForm<ListUserForm>?{

          ????/**
          ?????*?用戶(hù)狀態(tài)
          ?????*/

          ????@ApiModelProperty("用戶(hù)狀態(tài)")
          ????@NotEmpty(message?=?"用戶(hù)狀態(tài)不能為空")
          ????@Range(min?=??-1?,?max?=?1?,?message?=?"用戶(hù)狀態(tài)有誤")
          ????private?String?status;

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

          CodeGenerator代碼生成器。

          mybatis_plus代碼生成器可以幫我們生成entity,service,serviceImpl,mapper,mapper.xml。省去了建立一大堆實(shí)體類(lèi)的麻煩。
          由于配置太長(zhǎng)這里就不貼出來(lái)了,對(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?{

          ????/**
          ?????*?錯(cuò)誤碼
          ?????*/

          ????@ApiModelProperty("錯(cuò)誤碼")
          ????private?Integer?code;

          ????/**
          ?????*?提示信息
          ?????*/

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

          ????/**
          ?????*?具體的內(nèi)容
          ?????*/

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

          }
          復(fù)制代碼

          抽象表單 BaseForm

          public?abstract?class?BaseForm<T>?{

          ????/**
          ?????*?獲取實(shí)例
          ?????*?@return?返回實(shí)體類(lèi)
          ?????*/

          ????public?abstract?T?buildEntity();

          }
          復(fù)制代碼
          有小伙伴可能有疑問(wèn)了,這個(gè)類(lèi)有啥用呢。先看一下,下面的代碼。
          ????/**
          ?????*?添加用戶(hù)
          ?????*?@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);
          ????}
          復(fù)制代碼
          重構(gòu)一下,感覺(jué)清爽了一些。
          /**
          ?*?添加用戶(hù)
          ?*?@param?userForm?表單數(shù)據(jù)
          ?*?@return?true?或者?false
          ?*/

          @Override
          public?boolean?addUser(AddUserForm?userForm)?{
          ????User?user?=?new?User();
          ????BeanUtils.copyProperties(this,user);
          ????return?save(user);
          }
          復(fù)制代碼
          使用BaseForm進(jìn)行重構(gòu) AddUserForm 繼承 BaseForm并重寫(xiě)buildEntity
          @Data
          @EqualsAndHashCode(callSuper?=?false)
          public?class?AddUserForm?extends?BaseForm<User>?{

          ????/**
          ?????*?昵稱(chēng)
          ?????*/

          ????private?String?nickname;

          ????/**
          ?????*?生日
          ?????*/

          ????private?Date?birthday;

          ????/**
          ?????*?用戶(hù)名
          ?????*/

          ????private?String?username;

          ????/**
          ?????*?密碼
          ?????*/

          ????private?String?password;

          ????/**
          ?????*?構(gòu)造實(shí)體
          ?????*?@return?實(shí)體對(duì)象
          ?????*/

          ????@Override
          ????public?User?buildEntity()?{
          ????????User?user?=?new?User();
          ????????BeanUtils.copyProperties(this,user);
          ????????return?user;
          ????}
          }
          復(fù)制代碼
          /**
          ?*?添加用戶(hù)
          ?*?@param?userForm?表單數(shù)據(jù)
          ?*?@return?true?或者?false
          ?*/

          @Override
          public?boolean?addUser(AddUserForm?userForm)?{
          ????return?save(userForm.buildEntity());
          }
          復(fù)制代碼
          上面的代碼有沒(méi)有種似曾相識(shí)的感覺(jué),很多情況都是將接受到的參數(shù),轉(zhuǎn)變成對(duì)應(yīng)的實(shí)體類(lèi)然后保存或者更新
          所以對(duì)于這類(lèi)的form可以繼承baseform并實(shí)現(xiàn)buildEntity()這樣可以更加符合面向?qū)ο螅?code style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: inherit;word-break: break-word;border-radius: 4px;overflow-x: auto;background: rgb(248, 248, 248);color: rgb(233, 105, 0);padding: 2px 4px;line-height: inherit;overflow-wrap: break-word;margin-right: 2px;margin-left: 2px;">service不需要關(guān)心form如何轉(zhuǎn)變成entity,只需要在使用的時(shí)候調(diào)用buildEntity()即可,尤其是在form?->?entity相對(duì)復(fù)雜的時(shí)候,這樣做可以減少service內(nèi)的代碼。讓代碼邏輯看起來(lái)更加清晰。

          通用的分頁(yè)對(duì)象

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

          PageForm

          @Data
          @ApiModel(value?=?"分頁(yè)數(shù)據(jù)",?description?=?"分頁(yè)需要的表單數(shù)據(jù)")
          public?class?PageForm<T?extends?PageForm>{

          ????/**
          ?????*?頁(yè)碼
          ?????*/

          ????@ApiModelProperty(value?=?"頁(yè)碼?從第一頁(yè)開(kāi)始?1")
          ????@Min(value?=?1,?message?=?"頁(yè)碼輸入有誤")
          ????private?Integer?current;

          ????/**
          ?????*?每頁(yè)顯示的數(shù)量
          ?????*/

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

          ????/**
          ?????*?計(jì)算當(dāng)前頁(yè)?,方便mysql?進(jìn)行分頁(yè)查詢(xún)
          ?????*?@return?返回?pageForm
          ?????*/

          ????@ApiModelProperty(hidden?=?true)
          ????public?T?calcCurrent(){
          ????????current?=?(current?-?1?)?*?size;
          ????????return?(T)?this;
          ????}
          }
          復(fù)制代碼

          PageVo

          @Data
          public?class?PageVo<T>?{
          ????/**
          ?????*?分頁(yè)數(shù)據(jù)
          ?????*/

          ????@ApiModelProperty(value?=?"分頁(yè)數(shù)據(jù)")
          ????private?List?records;
          ????/**
          ?????*?總條數(shù)
          ?????*/

          ????@ApiModelProperty(value?=?"總條數(shù)")
          ????private?Integer?total;

          ????/**
          ?????*?總頁(yè)數(shù)
          ?????*/

          ????@ApiModelProperty(value?=?"總頁(yè)數(shù)")
          ????private?Integer?pages;

          ????/**
          ?????*?當(dāng)前頁(yè)
          ?????*/

          ????@ApiModelProperty(value?=?"當(dāng)前頁(yè)")
          ????private?Integer?current;

          ????/**
          ?????*?查詢(xún)數(shù)量
          ?????*/

          ????@ApiModelProperty(value?=?"查詢(xún)數(shù)量")
          ????private?Integer?size;

          ????/**
          ?????*?設(shè)置當(dāng)前頁(yè)和每頁(yè)顯示的數(shù)量
          ?????*?@param?pageForm?分頁(yè)表單
          ?????*?@return?返回分頁(yè)信息
          ?????*/

          ????@ApiModelProperty(hidden?=?true)
          ????public?PageVo?setCurrentAndSize(PageForm?pageForm){
          ????????BeanUtils.copyProperties(pageForm,this);
          ????????return?this;
          ????}

          ????/**
          ?????*?設(shè)置總記錄數(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);
          ????}
          }
          復(fù)制代碼

          案例

          ListUserForm
          @Data
          @ApiModel("獲取用戶(hù)列表需要的表單數(shù)據(jù)")
          @EqualsAndHashCode(callSuper?=?false)
          public?class?ListUserForm?extends?PageForm<ListUserForm>?{

          ????/**
          ?????*?用戶(hù)狀態(tài)
          ?????*/

          ????@ApiModelProperty("用戶(hù)狀態(tài)")
          ????@NotEmpty(message?=?"用戶(hù)狀態(tài)不能為空")
          ????@Range(min?=??-1?,?max?=?1?,?message?=?"用戶(hù)狀態(tài)有誤")
          ????private?String?status;

          }
          復(fù)制代碼
          UserServiceImpl
          /**
          ?*?獲取用戶(hù)列表
          ?*?@param?listUserForm?表單數(shù)據(jù)
          ?*?@return?用戶(hù)列表
          ?*/

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

          /**
          ?*?獲取用戶(hù)數(shù)量
          ?*?@param?status?狀態(tài)
          ?*?@return?用戶(hù)數(shù)量
          ?*/

          private?Integer?countUser(String?status){
          ????return?count(new?QueryWrapper().eq("status",status));
          }
          復(fù)制代碼
          UserController
          /**
          ?*?獲取用戶(hù)列表
          ?*?@param?listUserForm?表單數(shù)據(jù)
          ?*?@return?用戶(hù)列表
          ?*/

          @ApiOperation("獲取用戶(hù)列表")
          @GetMapping("/listUser")
          @ApiResponses(
          ????????@ApiResponse(code?=?200,?message?=?"操作成功",?response?=?UserVo.class)
          )
          public?ResultVo?listUser(@Validated?ListUserForm?listUserForm){
          ????return?ResultVoUtil.success(userService.listUser(listUserForm));
          }
          復(fù)制代碼
          注意的點(diǎn)
          • PageVo在實(shí)例化的時(shí)候需要設(shè)置當(dāng)前頁(yè)每頁(yè)顯示的數(shù)量?可以調(diào)用setCurrentAndSize()完成。

          • 進(jìn)行分頁(yè)查詢(xún)的時(shí)候,需要計(jì)算偏移量。listUserForm.calcCurrent()

          為什么要計(jì)算偏移量呢?
          • 假如查詢(xún)第1頁(yè)每頁(yè)顯示10條記錄,前端傳遞過(guò)來(lái)的參數(shù)是current=1&&size=10,這個(gè)時(shí)候limit 1,10沒(méi)有問(wèn)題。

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

          為什么不用MybatisPlus自帶的分頁(yè)插件呢?
          自帶的分頁(yè)查詢(xún)?cè)诖罅繑?shù)據(jù)下,會(huì)出現(xiàn)性能問(wèn)題。

          常用工具類(lèi)

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

          異常處理

          異常處理的大致流程主要如下。
          • 異常信息拋出 ->?ControllerAdvice?進(jìn)行捕獲格式化輸出內(nèi)容

          • 手動(dòng)拋出CustomException并傳入ReulstEnum?——> 進(jìn)行捕獲錯(cuò)誤信息輸出錯(cuò)誤信息。

          自定義異常

          @Data
          @EqualsAndHashCode(callSuper?=?false)
          public?class?CustomException?extends?RuntimeException?{

          ????/**
          ?????*?狀態(tài)碼
          ?????*/

          ????private?final?Integer?code;

          ????/**
          ?????*?方法名稱(chēng)
          ?????*/

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


          ????/**
          ?????*?自定義異常
          ?????*
          ?????*?@param?resultEnum?返回枚舉對(duì)象
          ?????*?@param?method?????方法
          ?????*/

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

          ????/**
          ?????*?@param?code????狀態(tài)碼
          ?????*?@param?message?錯(cuò)誤信息
          ?????*?@param?method??方法
          ?????*/

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

          }
          復(fù)制代碼

          錯(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;
          ????}

          ????/**
          ?????*?通過(guò)狀態(tài)碼獲取枚舉對(duì)象
          ?????*?@param?code?狀態(tài)碼
          ?????*?@return?枚舉對(duì)象
          ?????*/

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

          }
          復(fù)制代碼

          全局異常攔截

          全局異常攔截是使用@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);
          ????}
          }
          復(fù)制代碼

          案例

          Controller
          /**
          ?*?刪除用戶(hù)
          ?*?@param?id?用戶(hù)編號(hào)
          ?*?@return?成功或者失敗
          ?*/

          @ApiOperation("刪除用戶(hù)")
          @DeleteMapping("/deleteUser/{id}")
          public?ResultVo?deleteUser(@PathVariable("id")?String?id){
          ????userService.deleteUser(id);
          ????return?ResultVoUtil.success();
          }
          復(fù)制代碼
          Service
          /**
          ?*?刪除用戶(hù)
          ?*?@param?id?id
          ?*/

          @Override
          public?void?deleteUser(String?id)?{
          ????//?如果刪除失敗拋出異常。?--?演示而已不推薦這樣干
          ????if(!removeById(id)){
          ????????throw?new?CustomException(ResultEnum.DELETE_ERROR,?MethodUtil.getLineInfo());
          ????}
          }
          復(fù)制代碼
          結(jié)果
          將報(bào)錯(cuò)代碼所在的文件第多少行都打印出來(lái)。方便排查。
          注意的點(diǎn)
          所有手動(dòng)拋出的錯(cuò)誤信息,都應(yīng)在錯(cuò)誤信息枚舉ResultEnum進(jìn)行統(tǒng)一維護(hù)。不同的業(yè)務(wù)使用不同的錯(cuò)誤碼。方便在報(bào)錯(cuò)時(shí)進(jìn)行分辨。快速定位問(wèn)題。

          多環(huán)境配置

          SpringBoot多環(huán)境配置

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

          Maven多環(huán)境配置

          假如想在打包的時(shí)候動(dòng)態(tài)指定環(huán)境,這個(gè)時(shí)候就需要借助Maven的xml來(lái)實(shí)現(xiàn)。
          配置XML

          <profiles>
          ????<profile>
          ????????
          ????????<id>devid>
          ????????<activation>
          ????????????<activeByDefault>trueactiveByDefault>
          ????????activation>
          ????????<properties>
          ????????????<activatedProperties>devactivatedProperties>
          ????????properties>
          ????profile>
          ????<profile>
          ????????
          ????????<id>testid>
          ????????<properties>
          ????????????<activatedProperties>testactivatedProperties>
          ????????properties>
          ????profile>
          ????<profile>
          ????????
          ????????<id>preid>
          ????????<properties>
          ????????????<activatedProperties>preactivatedProperties>
          ????????properties>
          ????profile>
          ????<profile>
          ????????
          ????????<id>prodid>
          ????????<properties>
          ????????????<activatedProperties>prodactivatedProperties>
          ????????properties>
          ????profile>
          profiles>
          復(fù)制代碼
          更改application.yml
          spring:
          ??profiles:
          ????#?選擇環(huán)境
          ????active:?@activatedProperties@
          復(fù)制代碼
          使用案例
          mvn?clean?package?-P?prod
          mvn?clean?package?-P?pre
          mvn?clean?package?-P?test
          復(fù)制代碼
          打包完可以解壓開(kāi)查看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語(yǔ)法,以及如何配置jenkins。

          代碼地址

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


          別忘記點(diǎn)個(gè)在看,咱們下篇見(jiàn)
          每天進(jìn)步一點(diǎn)點(diǎn)
          慢一點(diǎn)才能更快

          推薦閱讀:

          為什么有些大公司技術(shù)卻弱爆了?

          GET 請(qǐng)求能傳圖片嗎?

          5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹(shù)莓派,等等。在公眾號(hào)內(nèi)回復(fù)「2048」,即可免費(fèi)獲取!!

          微信掃描二維碼,關(guān)注我的公眾號(hào)

          朕已閱?

          瀏覽 40
          點(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>
                  一级片电影网站 | 亚洲国产麻豆视频 | 婷婷天网站 | 国产高清视频在线观看 | 亚洲综合在线人妻 |