穀粒商城–分散式基礎篇P28~P101(完結)

穀粒商城–分散式基礎篇P28~P101(完結)

前面1-27節主要是環境配置特別難,後面的28~101節主要是前端編寫的程式碼較多以及後台的CRUD操作比較多。因為內容很多,所以我是根據自己想學的點進行相應學習,故前端我直接跳過了,前端程式碼用的別人完整的。主要學習點集中在後台三級目錄、庫表設計、OSS以及程式碼規範的相關學習了。

Fork程式碼://gitee.com/empirefree/GuliMall

(個人建議學後端的只用renren-fast-vue前端程式碼,後端程式碼除開CRUD的操作,其餘都自己敲)

csdn
csdn
csdn
csdn
csdn


@

🔥1.商品服務

1.1 商品樹形圖(Lambda8程式碼實現)
  • 排序類:id,parentId,sort(權重)、List(自定義添加)

  • 組裝邏輯:先獲取所有商品,然後再獲取第一級商品,遞歸併排序找到所有子商品。程式碼如下

請添加圖片描述

1.2 網關配置

​ 前端為了統一管理,全部向網關發起訪問。所以驗證碼、後續數據獲取埠都需要修改。修改邏輯如下:

  1. 原始驗證碼地址://localhost:8080/renren-fast/captcha.jpg
  2. 前端發起訪問的地址://localhost:88/api/captcha.jpg
  3. 經過Gateway從nacos映射與路徑轉換://localhost:8080/renrenfast/captcha.jpg(前面的8080路徑是從nacos中找到的renrenfast埠,後面路徑是gateway轉換的路徑)

GateWay請求攔截與轉換

spring:
  cloud:
    gateway:
      routes:
        - id: product_route
          uri: lb://gulimall-product
          predicates:
            - Path=/api/product/**
          filters:
            - RewritePath=/api/(?<segment>.*),/$\{segment}

        - id: third_party_route
          uri: lb://gulimall-third-party
          predicates:
            - Path=/api/thirdparty/**
          filters:
            - RewritePath=/api/thirdparty/(?<segment>.*),/thirdparty/$\{segment}

        - id: member_route
          uri: lb://gulimall-member
          predicates:
            - Path=/api/member/**
          filters:
            - RewritePath=/api/(?<segment>.*),/$\{segment}

        - id: ware_route
          uri: lb://gulimall-ware
          predicates:
            - Path=/api/ware/**
          filters:
            - RewritePath=/api/(?<segment>.*),/$\{segment}

        - id: admin_route
          uri: lb://renren-fast
          predicates:
            - Path=/api/**
          filters:
            - RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}
1.3 阿里雲oss

​ 官網給的oss的dependency無法導入,應該使用如下dependency

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
        </dependency>

​ 另外,共有2種上傳文件方式

  1. client->server->oss(不推薦但很常見):伺服器處理上傳
  2. server返回policy
1.4 獲取商品id完整路徑

​ 針對上面給的商品樹,給出某個id獲取根id到這個id路徑

請添加圖片描述

🔥2.程式碼規範環境

JSR303、全局異常處理、全局統一返回、全局跨域處理、VO與TO與PO劃分

2.1.JSR303

​ 就是入參的校驗註解,極大簡化了對於前端入參的程式碼判斷

	/**
	 * 為空的數據就不查詢了
	 */
	@JsonInclude(JsonInclude.Include.NON_EMPTY)
	/**
	 * 表中不存在
	 */
	@TableField(exist = false)

2.2.全局異常處理與統一返回

​ 在正常前後端分離項目中,前端對於參數的要求有個規範,所以無論正確還是錯誤程式碼,後端都需要有個全局參數的返回

package com.empirefree.gulimall.product.exception;

import com.empirefree.common.exception.BizCodeEnum;
import com.empirefree.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.support.WebExchangeBindException;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>Title: MallExceptionControllerAdvice</p>
 * Description:集中處理所有異常
 * date:2020/6/1 21:19
 */
@Slf4j
@RestControllerAdvice(basePackages = "com.empirefree.gulimall.product.controller")
public class MallExceptionControllerAdvice {


	@ExceptionHandler(value = {WebExchangeBindException.class})
	public R handleVaildException(WebExchangeBindException e) {
		log.error("數據校驗出現問題{},異常類型:{}", e.getMessage(), e.getClass());
		BindingResult bindingResult = e.getBindingResult();

		Map<String, String> errorMap = new HashMap<>();
		bindingResult.getFieldErrors().forEach((fieldError) -> {
			// 錯誤欄位 、 錯誤提示
			errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
		});
		return R.error(BizCodeEnum.VAILD_EXCEPTION.getCode(), BizCodeEnum.VAILD_EXCEPTION.getMsg()).put("data", errorMap);
	}

	@ExceptionHandler(value = Throwable.class)
	public R handleException(Throwable throwable) {

		log.error("錯誤:", throwable);
		return R.error(BizCodeEnum.UNKNOW_EXCEPTION.getCode(), BizCodeEnum.UNKNOW_EXCEPTION.getMsg());
	}
}
2.3.全局跨域處理

​ 由於前端統一訪問gateway網關,所以gateway需要配置允許跨域

package com.empirefree.gulimall.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@Configuration
public class GulimallCorsConfiguration {

    @Bean
    public CorsWebFilter corsWebFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //1、配置跨域
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.setAllowCredentials(true);

        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsWebFilter(source);
    }
}

2.4.VO、TO

​ 由於入參出參數據與dao層差距很大,所以需要自定義一些參數,結合程式碼賦值完成參數傳遞

	BeanUtils.copyProperties(group, attrVo);

(我用的比較多的就是XXrequest、XXresponse、XXDTO、XXVO)

🔥3.總結

​ 老師後端講得很多東西雖然都是一句話帶過,但是其實真的很重要,而且我覺得需要有針對性學習,個人感覺效率高點

  • 分散式相關內容:nacos,gateway,feign
  • 後端相關內容:oss,樹形商品,商品路徑,全局處理(異常、跨域、統一處理),程式碼規範(JSR303,VO|DTO|DO)
  • 資料庫相關內容:庫表的設計(重要:個人感覺對提高後端開發有啟迪性作用)
  • 伺服器相關內容:docker(還只是停留在使用階段,自己還需要提高)

書山有路勤為徑,學海無涯苦作舟。程式設計師不僅要懂程式碼,更要懂生活,關注我,一起進步。

請添加圖片描述