[项目练手笔记-谷粒商城(SpringCloud Alibaba+vue前后端分离)]day02+day03 nacos,gateway的使用、前端入门学习

[项目练手笔记-谷粒商城(SpringCloud Alibaba+vue前后端分离)]day02+day03 nacos,gateway的使用、前端入门学习

结合SpringCloud Alibaba我们最终的技术搭配方案:
SpringCloud Alibaba Nacos:注册中心(服务发现/注册)
SpringCloud Alibaba Nacos:配置中心(动态配置管理)
SpringCloud Ribbon:负载均衡
SpringCloud Feign:声明式HTTP客户端(调用远程服务)
SpringCloud Alibaba Sentinel:服务容错(限流、降级、熔断)
SpringCloud Gateway: API网关(webflux 编程模式)
SpringCloud Sleuth:调用链监控
SpringCloud Alibaba Seata:原Fescar,即分布式事务解决方案

一、SpringCloud Alibaba Nacos的使用

1.在common模块中导入依赖

阿里巴巴统一依赖管理

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

nacos服务注册于配置中心

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

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

2.注册微服务

在application.yml中将对应的微服务注册到nacos中

  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  application:
    name: gulimall-coupon #注册的名字

3.添加注册发现注解

在主方法上添加@EnableDiscoveryClient

二、OpenFeign的远程调用

1.引入依赖

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

2.编写远程调用接口

为了方便起见,建立一个feign包专门用来存放远程调用接口

接口要声明调用哪个接口的哪个请求

//要被调用的controller的方法
@RequestMapping("/member/list")
public R memberFeign() {
    CouponEntity couponEntity = new CouponEntity();
    couponEntity.setCouponName("满100-99");
    return R.ok().put("coupons", Arrays.asList(couponEntity));
}
//feign接口,表明要调用的是微服务gulimall-coupon中的/coupon/coupon/member/list路径下的memberFeign方法
@FeignClient(value = "gulimall-coupon")
public interface CouponFeignService {
    @RequestMapping("/coupon/coupon/member/list")
    public R memberFeign() ;
}
@RestController
@RequestMapping("member/member")
public class MemberController {
    @Autowired
    private MemberService memberService;
    @Resource
    private CouponFeignService couponFeignService;

    @RequestMapping("/coupons")
    public R memberCoupon() {
        R coupons = couponFeignService.memberFeign();
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setUsername("小三");
        return R.ok().put("member",memberEntity).put("coupons",coupons.get("coupons"));
    }

3.配置主方法

@EnableFeignClients(basePackages="com.xiaoxiao.gulimall.member.feign")

访问localhost:8000/member/member/coupons,验证远程调用了

在这里插入图片描述

三、Nacos作为服务配置中心

nacos作为配置中心都在我以前的学习笔记中有,笔记地址

1.引入依赖

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

2.创建bootstrap.yml

bootstrap.yml作为全局配置,优先级高于application.yml,可以在其中配置注册配置地址,其余配置从nacos配置中心拉取

spring:
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        namespace: 36cbae64-6c6a-443a-87d3-f4ade9651be8 #命名空间
        ext-config:
          - dataId: datasource.yml
            group: dev
            refresh: true
          - dataId: mybatis.yml
            group: dev
            refresh: true
          - dataId: other.yml
            group: dev
            refresh: true
        group: dev
  application:
    name: gulimall-coupon

3.自动刷新

只需要在调用的controller上加上@RefreshScope即可

注,不知道为什么nacos总是有一些莫名其妙的问题,比如加了@RefreshScope一直刷新也没有更新配置,如果遇到了,网上也搜不到解决方案,建议重启,可能就好了

四、GateWay作为API网关

1.nacos配置

使用nacos作为配置中心,在nacos配置设置进行命名空间隔离,分组,创建yml

2.配置bootstrap.yml

spring:
  application:
    name: gulimall-gateway
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        namespace: c2a660b0-5796-46f1-9c18-7686e3fb4c83

3.配置application.yml

配置路由规则

spring:
  application:
    name: gulimall-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        - id: baidu_route
          uri: http://www.baidu.com
          predicates:
            - Query=url,baidu
        - id: qq_route
          uri: http://www.qq.com
          predicates:
            - Query=url,qq
server:
  port: 88

4.测试

测试输入localhost:88/hello?url=qq,能否跳转到QQ,这里是跳转到了qq的/hello

五、前端开发入门

1.ES6入门

ECMAScript是浏览器脚本语言的规范,而javascript则是规范的具体实现

1.let声明变量

shift+! 快速生成html规范

  • 特性1:let较var严格,不能跨域
        /*
        特性1:
        var定义的变量可以跨域
        let定义的变量不能跨域,与域要求严格
        */
        {
            var a = 1;
            let b = 2;

        }
        console.log(a); //输出1
        console.log(b); //报错,因为跨域
        
  • 特性2:var能声明多次,let只能声明一次
        /*
        特性2:
        var可以多次定义的同一个变量
        let只能同一个变量一次
        */
        var m = 1;
        var m = 2;
        let b = 2;
        let b = 3;
        console.log(a); //输出2
        console.log(b); //报错,因为多次赋值
  • 特性3: var会变量提升,let不会变量提升
        /*
        特性3:
        var会变量提升
        let不会变量提升
        */
        console.log(m); //输出undifined
        var m = 1;
        let b = 2;
        console.log(b); //报错,提示未定义b

2.const声明常量

const定义的变量是常量,无法进行修改,且必须初始化

3.解构表达式

1.数组解构
        //1.数组解构
        let arr=[1,2,3];
        
        let [x,y,z] = arr;
        console.log(x,y,z);
2.对象解构
        //2.对象解构
        const person = {
            name: "xiaoxiao",
            age: 21,
            language: ['java', 'js', 'php']

        }
        //解构对,将解构的name赋值给bbb
        const {name:bbb, age, language} = person;
        console.log(bbb, age, language);

4.字符串

1.字符方法
        let str = "hello.vue";
        console.log(str.startsWith("hello"));//true
        console.log(str.endsWith("vue"));//true
        console.log(str.includes("e"));//true
        console.log(str.includes("llo"));//true
2.字符串模板
        let ss = `
        <div>
            <span>helloword<span>
            <div>
            
        `
        console.log(ss);
3.${}的使用

${}可以放在字符串中,可以插入变量或者js表达式,函数返回值

        let age = 10;
        console.log(`我今年${age}岁了`);//我今年10岁了
        console.log(`我今年${age+15}岁了`);//我今年25岁了

5.函数优化

1.函数默认值
        //函数默认值
        function fun1(a,b=1) {
            console.log(a+b);
        }
        fun1(10);//11
        fun1(10,10);//20
2.不定参数

不定参数用来表示不确定参数个数,形如…变量名,…加上一个具名参数标识符组成。
具名参数只能放在参数列表的最后,并且有且只有一个不定参数

        //不定参数
        function fun2(...values) {
            console.log(values.length);
        }
        fun2(1, 2)//2
        fun2(1, 2, 3, 4) //4
3.箭头函数

和lamda表达式类似

        //箭头函数
        var print = obj=>console.log(obj);	//函数方法体就是console.log(obj),参数是obj
        print("hello");


        var sum1 = (a,b)=>a+b;
        console.log(sum1(10,20));//30

        var sum2 = (a,b)=> {
            let c = a+b;
            return c+a;
        }
        console.log(sum2(10,20));//40

箭头函数+解构表达式

        const person = {
            name: "xiaoxiao",
            age: 21,
            language: ['java', 'js', 'php']

        }

        var hello=({name})=>console.log("hello"+name);
        hello(person)//helloxiaoxiao

6.对象优化

1.输出对象
        const person = {
            name: "xiaoxiao",
            age: 21,
            language: ['java', 'js', 'php']

        }

        console.log(Object.keys(person));//输出对象的键
        console.log(Object.values(person));//输出对象的值
        console.log(Object.entries(person));//输出对象的键值对
2.合成对象
        const target = {
            a:1
        }

        const source1 = {
            b:1
        }
        const source2 = {
            c:1
        }
        Object.assign(target,source1,source2);
        console.log(target);
3.对象函数简写
        //3) 、对象的函数属性简写
        let person3 = {
            name:"xiaoxiao",
            //以前:
            eat:
                function (food) {
                    console.log(this.name +"在吃"+ food);
                },
            //莆头还数this不能使用,对象.属性
            eat2: food => console.log(person3.name +"在吃"+ food),
            eat3(food) {
                console.log(this.name +"在吃"+ food);
            }
        }
        person3.eat("香蕉");
        person3.eat2("苹果");
        person3.eat3("橘子");
4.对象运算符扩展
        // 1、拷贝对象(深拷贝)
        let p1 = { name: "Aamy", age: 15 }
        let someone = {...p1}
        console.log(someone) // { nane: "Amy", age: 15 }
        // 2、含并对象
        let age1 = { age: 15 }
        let name1 = { name: " Amy" }
        let p2 = { name: "zhangsan" }
        p2 = { ...age1, ...name1 }
        console.log(p2);

7.map与reduce

        //数组中新增了map和reduce方法。
        //map():接收一个经数,将原数组中的所有元素用这个团数处理后放入新数组返回。
        let arr = ['1', '20', '-5', '3'];
        // arr=arr.map(item) => (
        //return item * 2
        //});
        arr = arr.map(item => iten * 2);
        console.log(arr);
        /*reduce()为数组中的每一个元素依次执行回调题数,不包括数组中被删除或从未被赋值的元素,
        //[2, 40, -10, 6]
        //arr . reduce(callback, [initialValue]) 
        1、previousValue(上次调用回调返回的值, 或者是提供的初始值(initialValue))
        2、currentValue(数组中当前被处理的元素)
        3、index(当前元素在数组中的索引)
        4、array(调用reduce 的数组) */
        let result = arr.reduce((a, b) => {
            console.log("上一次处理后: " + a);
            console.log("当前正在处理; " + b);
            return a + b;
        }, 100);
        console.log(result)

8.promise优化异步操作

        function get(url, data) {
            return new Promise((resolve, reject) => {
                $.ajax({
                    url: url,
                    data: data,
                    success: function (data) {
                        resolve(data);
                    },
                    error: function (err) {
                        reject(err)
                    }
                })
            });
        }

        get("mock/user.json")
            .then((data) => {
                console.log("用户查询成功: ", data)
                return get(`mock/user_corse_${data.id}.json`);
            })
            .then((data) => {
                console.log("课程查询成功:", data)
                return get(`mock/corse_score_${data.id}.json`);
            })
            .then((data) => {
                console.log("课程成绩查询成功:", data)
            })
            .catch((err) => {
                console.log("出现异常", err)
            });

如果出现异常:

已拦截跨源请求:同源策略禁止读取位于 file:///D:/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E8%B0%B7%E7%B2%92%E5%95%86%E5%9F%8E/%E5%89%8D%E7%AB%AF%E5%9F%BA%E7%A1%80/mock/user.json?callback=jQuery34106058175736353101_1594216378693&_=1594216378694 的远程资源。(原因:CORS 请求不是 http)。

说明没有使用Live server运行,使用的是在浏览器打开

在这里插入图片描述

9.模块化

使用export导出要使用的对象,变量,函数,使用import来调用

2.vue入门

1.安装

npm init -y
npm install vue

2.引入vue

    <script src="./node_modules/vue/dist/vue.js"></script>

3.基本语法

1.声明式渲染
    <div id="test">
        <input type="text">
        <h1>{{name}},我成功了!</h1>
    </div>

    <script src="./node_modules/vue/dist/vue.min.js"></script>

    <script>
        //声明式渲染
        let vm = new Vue({
            el: "#test",
            data: {
                name: "天才",
                num: 10
            }
        });
2.双向绑定
    <div id="test">
        <input type="text" v-model="num">
        <h1>{{name}},我成功了!有{{num}}正在围观</h1>
    </div>

    <script src="./node_modules/vue/dist/vue.min.js"></script>

    <script>
        //声明式渲染
        let vm = new Vue({
            el: "#test",
            data: {
                name: "天才",
                num: 10
            }
        });

        //双向绑定,模型和视图一起变化

在这里插入图片描述

3.事件处理
    <div id="test">
        <input type="text" v-model="num">
        <!-- 点击num+1,这个是事件处理 -->
        <button v-on:click="num++">围观</button>
        <h1>{{name}},我成功了!有{{num}}正在围观</h1>
    </div>

    <script src="./node_modules/vue/dist/vue.min.js"></script>

    <script>
        //声明式渲染
        let vm = new Vue({
            el: "#test",
            data: {
                name: "天才",
                num: 10
            }
        });

        //双向绑定,模型和视图一起变化
4.总结

el:绑定数据

data:封装数据

methods:封装方法

1、创建vue实例,关联页面的模板,将自己的数据(data) 渲染到关联的模板,响应式的
2、指令来简化对dom的一些操作。
3、声明方法来做更复杂的操作。methods可以封装方法

安装vue语法插件vue2 snippets

安装chrome插件vue.js devtools

4.基本指令

1.v-text,v-html

注意{{}}插值是给标签体内部绑定值

    <div id=test>
        {{msg}},加载有延时,未渲染的时候会加载出{{}}
        <br>
        <span v-html="msg"></span><br>
        <span v-text="msg"></span>
    </div>
    <script src="../node_modules/vue/dist/vue.min.js"></script>
    <script>
        new Vue({
            el: "#test",
            data: {
                msg: "<h1>helloword</h1>"
            }
        })
    </script>

在这里插入图片描述

2.v-bind

给html标签的属性绑定值

    <div id=test>
        <a v-bind:href="link">百度</a><br>
        <span v-bind:class="{active:isActived,'text-danger':isError}"
        v-bind:style="{color:color1}">你好</span>
    </div>
    <script src="../node_modules/vue/dist/vue.min.js"></script>
    <script>
        new Vue({
            el: "#test",
            data: {
                link: "http://www.baidu.com",
                isActived: true,
                isError: true,
                color1: 'red'
            }
        })
    </script>

在这里插入图片描述

3.v-model
    <!--表单项,自定义组件-->
    <div id="app">
        精通的语言:
        <input type="checkbox" v-model="language" value="Java"> java<br />
        <input type="checkbox" v-model="language" value="PHP"> PHP<br />
        <input type="checkbox" v-model="language" value="Python"> Python<br />
        选中了{{language.join(",")}}
    </div>
    <script src="../node_modules/vue/dist/vue.js"></script>
    <script>
        let vm = new Vue({
            el: "#app",
            data: {
                language: []
            }
        })
    </script>

在这里插入图片描述

4.v-on
<!-- 完整语法 -->
<a v-on:click="doSomething"></a>
<!-- 缩写 -->
<a @click="doSomething"></a>
<!-- 阻止事件冒泡 -->
<a @click.stop="doSomething"></a>
<!-- 阻止事件默认行为 -->
<a @click.prevent="doSomething"></a>
<!-- 点击一次行为 -->
<a @click.once="doSomething"></a>


<!-- 键盘按键行为 -->
<a @keyup.up="doSomething"></a>
<!-- 组合按键行为 -->
<a @click.ctrl="doSomething"></a>

5.模块化开发

1.安装webpack

全局安装webpack

npm install webpack -g
2.安装vue脚手架

全局安装vue脚手架

npm install -g @vue/cli-init
3.初始化vue项目
vue init webpack appname: vue脚手架使用webpack模块初始化一个appname项目
4.运行
cd appname
npm run dev

版权声明:本文为qq_41522089原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。