谷粒商城基础

maven环境配置

settings配置文件

 <profiles>
   <profile>
        <id>jdk-1.8</id>
        <activation>
            <activeByDefault>true</activeByDefault>
            <jdk>1.8</jdk>
        </activation>
        <properties>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
        </properties>
    </profile>
 <profiles>


<mirrors>
   <mirror>
       <id>nexus-aliyun</id>
       <mirrorOf>centeral</mirrorOf>
       <name>Nexus aliyun</name>
       <url>https://maven.aliyun.com/nexus/content/groups/public</url>
   </mirror>
</mirrors>

git提交代码排除无用文件

在总项目的.gitignore目录配置

项目地址

https://gitee.com/lds-pjy/gulimall.git

nacos

1注册中心步骤

1.导入依赖

     <!--总文件进行版本控制,后续导入的组件无需再引入版本号-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


        <!--服务注册/发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

2.在.properties中配置nacos地址和服务名称

spring.application.name=renren-fast

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

3.在启动类使用@EnableDiscoveryClient注解开启服务注册与发现

@EnableDiscoveryClient
@SpringBootApplication
public class GulimallCouponApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallCouponApplication.class, args);
    }

}

4.启动nacos客户端(双击starup.cmd)

页面输入 :http://127.0.0.1:8848/nacos(默认账号密码:nacos,nacos)

5.给服务起名字

spring:
  application:
    name: gulimall-coupon

服务列表注册成功

2.配置中心

1.引入依赖

        <!--配置中心来做配置管理-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

2.编写bootstrap.properties文件(这个文件会比.properties文件先加载)

spring.application.name=gulimall-coupon

spring.cloud.nacos.config.server-addr=127.0.0.1:8848

3.配置

4.测试成功

5.配置动态获取并刷新配置(controller类添加@RefreshScope注解)

6.如果配置中心和当前应用文件都配置了相同的项,优先使用配置中心的配置

3.细节

命名空间:用来做配置隔离的

默认是public空间,所有新增的配置默认都是在public空间

应用场景:环境隔离

应用场景:微服务相互隔离:每个服务使用自己的命名空间

可以直接克隆配置到不同的命名空间

配置集

一组相关或者不相关的集合叫做配置集:比如说yml文件有超多的配置,合起来就叫做配置集

配置集ID

对于idea来说,配置文件名称就是配置id

对于nacos来说,Data ID就是配置集id

配置分组

默认所有的配置集都属于:DEFAULT_GROUP

例子:双十一用1111组,618 用618组

修改bootstrap文件使用1111在

同时加载多个配置集

微服务任何配置信息、配置文件都可以放在nacos中

只需要在bootrap.properties说明加载配置中心哪些配置文件即可

配置中心有的优先使用配置中心的

步骤

openfeign

1.引入依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2.编写一个接口,告诉SpringCloud这个接口需要调用远程服务

@FeignClient("gulimall-coupon"):远程接口所属的服务名称

@RequestMapping("/coupon/coupon/member/list") 别调用方法的全路径名
public R membercoupons();   被调用的方法

3.启动类添加@EnableFeignClients注解

basePackages = "com.atguigu.gulimall.member.feign":自动扫描这个包下标注了@FeignClient注解的接口

4.调用成功

被调用方法

    //controller上还有个@RequestMapping("coupon/coupon")路径

    @RequestMapping("/member/list")
    public R membercoupons(){
        CouponEntity couponEntity = new CouponEntity();
        couponEntity.setCouponName("满100减10");
        return R.ok().put("coupons",Arrays.asList(couponEntity));
    }

调用方法

    @Autowired
    CouponFeignService couponFeignService;


    @RequestMapping("/coupons")
    public R test(){
      MemberEntity memberEntity = new MemberEntity();
      memberEntity.setNickname("张三");

      R membercoupons = couponFeignService.membercoupons();
      return R.ok().put("member",memberEntity).put("coupons",membercoupons.get("coupons"));   
    }

成功调用

网关(Gateway)

简介

核心规则

当请求到达网关,网关先通过断言(Predicate)判断请求是不是符合某个路由(Route)规则,符合了就按照这个路由规则把它路由到指定的地方,但要去这些地方就要经过一系列的过滤器(filter)过滤

网关不需要数据源相关(排除数据源)

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

yml路由规则配置(小试牛刀)

spring:
  cloud:
    gateway:
      routes:
        - id: baidu_route             #唯一id
          uri: https://www.baidu.com  #需要去访问的url
          predicates:                 #断言规则
            - Query=url,baidu
# 当请求的url满足断言(predicates)规则: url路径包含baidu的时候。就路由去访问uri后面的地址       

        - id: qq_route
          uri: https://www.qq.com
          predicates:
            - Query=url,qq
# 当请求的url满足断言(predicates)规则: url路径包含qq的时候。就路由去访问uri后面的地址  

三级分类

网关把所有请求都路由给renren-fast处理

spring:
  cloud:
    gateway:
      routes:
        - id: admin_route
          uri: lb://renren-fast   #lb:负载均衡 满足断言规则就负载均衡到renren-fast服务
          predicates:
            - Path:/api/**           #前端发起的所有请求,只要带有api前缀都默认发送到renren-fast服务
          filters:                   #过滤器
            - RewritePath=/api/{?<segment>.*},/renren-fast/$\{segment} #把/api/{?<segment>.*}重写成/renren-fast/$\{segment}路径
  # 当请求的url满足断言(predicates)规则: 请求带api/**。就路由去uri的地址,并且把地址重写成   /renren-fast/$\{segment}

跨域

OPTIONS预检请求,还未正式的进行登录

跨域流程

解决跨域

方案一

把前端项目和后端项目都部署到nginx服务器,静态请求就直接代理给前端项目。后端                请求代理给网关,同意访问nginx的域名。实际项目中用这种方案有点麻烦。

方案二

因为路径都是由网关统一转发的,所以配置到网关里面

使用springboot的CorsWebFilter

@Configuration
public class GulimallCorsConfiguration {

    @Bean
    public CorsWebFilter corsWebFilter(){
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //配置跨域
            //允许哪些头进行跨域
        corsConfiguration.addAllowedHeader("*");
            //允许哪些请求方式进行跨域:GET,POST...
        corsConfiguration.addAllowedMethod("*");
            //允许哪些请求来源跨域
        corsConfiguration.addAllowedOrigin("*");
            //是否允许携带cookie
        corsConfiguration.setAllowCredentials(true);

        //所有路径都需要跨域请求
        source.registerCorsConfiguration("/**",corsConfiguration);
        return new CorsWebFilter(source);
    }
}

mybatis-plus逻辑删除

第一步:配置全局的逻辑删除规则(3.1.1后可省略)

mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0

第二步:配置逻辑删除的组件bean(3.1.1后可省略)

第三步:给Bean加上逻辑删除注解

    /**
	 * 是否显示[0-不显示,1显示]
	 */
	@TableLogic(value = "1",delval = "0")
	private Integer showStatus;

JSR303数据校验

实体字段校验 @NotNull、@NotEmpty、@NotBlank(区别)

@NotNull

不能为 null,但可以为 empty,一般用在 Integer 类型的基本数据类型的非空校验上,而且被其标注的字段可以使用 @size、@Max、@Min 对字段数值进行大小的控制

.@NotEmpty

不能为 null,且长度必须大于 0,一般用在集合类上或者数组上

@NotBlank

只能作用在接收的 String 类型上,注意是只能,不能为 null,而且调用 trim() 后,长度必须大于 0即:必须有实际字符

注意:

注意在使用 @NotBlank 等注解时,一定要和 @valid 一起使用,否则 @NotBlank 不起作用。

@NotBlank
private String name;

@RequestMapping("/save")
public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand/*,BindingResult result*/){


一个 BigDecimal 的字段使用字段校验标签应该为 @NotNull。
在使用 @Length 一般用在 String 类型上可对字段数值进行最大长度限制的控制。
在使用 @Range 一般用在 Integer 类型上可对字段数值进行大小范围的控制。

例子:

1.String name = null;

@NotNull: false
@NotEmpty:false 
@NotBlank:false

2.String name = "";

@NotNull:true
@NotEmpty: false
@NotBlank: false

3.String name = "(空格)";

@NotNull: true
@NotEmpty: true
@NotBlank: false

4.String name = "Hello World!";

@NotNull: true
@NotEmpty:true
@NotBlank:true

使用步骤

1)、给Bean添加校验注解:javax.validation.constraints,并定义自己的message提示

@NotBlank(message = "品牌名必须提交")

2)、Controller开启校验功能@Valid

3)、给校验的bean后紧跟一个BindingResult,就可以获取到校验的结果

@RequestMapping("/save")
    //@RequiresPermissions("product:brand:save")
    public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand,BindingResult result){
        if(result.hasErrors()){
            Map<String,String> map = new HashMap<>();
            //1、获取校验的错误结果
            result.getFieldErrors().forEach((item)->{
                //FieldError 获取到错误提示
                String message = item.getDefaultMessage();
                //获取错误的属性的名字
                String field = item.getField();
                map.put(field,message);
            });

            return R.error(400,"提交的数据不合法").put("data",map);
        }else {

        }

        brandService.save(brand);


        return R.ok();
    }

统一异常处理 (@RestControllerAdvice)

@Slf4j
@RestControllerAdvice(basePackages = "com.atguigu.gulimall.product.controller")
public class GulimallExceptionControllerAdvice {


    /*
        能精确捕捉到的异常就走这个方法捕获,不能精确的走下面大方法捕获
     */
    @ExceptionHandler(value= MethodArgumentNotValidException.class)
    public R handleVaildException(MethodArgumentNotValidException 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(BizCodeEnume.VAILD_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",errorMap);
    }

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

        log.error("错误:",throwable);
        return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
    }
}

错误码定义

枚举类定义

/***
 * 错误码和错误信息定义类
 * 1. 错误码定义规则为5为数字
 * 2. 前两位表示业务场景,最后三位表示错误码。例如:100001。10:通用 001:系统未知异常
 * 3. 维护错误码后需要维护错误描述,将他们定义为枚举形式
 * 错误码列表:
 *  10: 通用
 *      001:参数格式校验
 *  11: 商品
 *  12: 订单
 *  13: 购物车
 *  14: 物流
 */
public enum BizCodeEnume {
    UNKNOW_EXCEPTION(10000,"系统未知异常"),
    VAILD_EXCEPTION(10001,"参数格式校验失败");

    private final int code;
    private final String msg;
    BizCodeEnume(int code,String msg){
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

spu与sku

spu:比如小米八

sku:小米八的64G,128G,黑色,白色等具体维度

同一个spu下的多个sku:共享商品介绍、规格与包装

表设计

属性表

属性分组表

属性分组中间表

商品属性值表

spu信息表

总览

@JsonInclude注解

@JsonInclude(JsonInclude.Include.NON_EMPTY):为空的时候不返回给前端

@TableField注解

@TableField(exist = false):标注该字段非数据库字段

mybatis-puls分页插件

@Configuration
@EnableTransactionManagement //开启事务
@MapperScan("com.atguigu.gulimall.product.dao")
public class MyBatisConfig {

    //引入分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
         paginationInterceptor.setOverflow(true);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInterceptor.setLimit(1000);
        return paginationInterceptor;
    }
}

分页代码

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String key = params.get("key").toString();

        QueryWrapper<BrandEntity> wrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(key)){
            wrapper.like("name",key).or().eq("bran_id",key);
        }

        IPage<BrandEntity> page = this.page(
                new Query<BrandEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

@PathVariable和@RequestParam区别

总的来说:
@pathvariable 接收url路径上的参数
@RequestParam 接收参数请求的params

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值