当前位置:   article > 正文

前后端分离开发-vue_drf vue开发

drf vue开发

一、项目架构的变化过程

1.1 单体应用
  • 前后端分离(后端单体)

在这里插入图片描述

  • 前后端不分离

在这里插入图片描述

1.2 集群部署
  • 前后端分离(后端集群部署)

在这里插入图片描述

  • 前后端部分离—集群部署

在这里插入图片描述

1.3 微服务架构
  • 前后端分离(后端微服务架构)

在这里插入图片描述

  • 前后端不分离

在这里插入图片描述

二、前后端分离

前后端分离开发:将项目的视图显示和数据处理进行分离(分离开发、分离部署),目的是提升开发效率、降低对后端服务器的访问压力。

前后端分离开发技术:

  • 前端:
    • html、js、ajax — 繁琐
    • jquery+ajax --------- DOM操作
    • vue+axios ------------ MVVM 数据绑定实现渲染
  • 后端:
    • servlet+jdbc
    • SSM
    • SpringBoot整合SSM
2.1 前端技术体系

文档:01-web前端技术体系.md
链接:http://note.youdao.com/noteshare?id=6c4f94c22e0d4ccca2636073f68f2542&sub=AD5058272EE5402295981FEFED39FDA3

2.2 MVVM思想

文档:03-MVVM模式.md
链接:http://note.youdao.com/noteshare?id=8d812ecad7434aaf22e647125ad2bd0d&sub=3187F722F0FB4ACA8DC6CB8E5A5526DA

三、vue基础入门

3.1 vue是什么?

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

vue是一个基于MVVM思想的前端框架,主要用于完成数据的渲染

3.2 vue怎么用?

一个JS框架引入的方式有三种:

  • npm安装使用
  • 在线引用cdn
  • 本地引入(js下载并存放到我们自己的web项目中,然后在页面使用)
  • 在线CND

    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    
    <!-- 生产环境版本,优化了尺寸和速度 -->
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 本地引入

    • 现在vue.js文件
    • 在我们的html文件中引用
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8" />
    		<title></title>
    	</head>
    	<body>
    		
    	</body>
    	<script type="text/javascript" src="js/vue.js" ></script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
3.3 vue入门案例
  • 案例

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8" />
    		<title></title>
    	</head>
    	<body>
    		<div id="container">
    			<!--Mustache语法-->
    			<p>{{str}}</p>
    			<input type="text" v-model="str" />
    		</div>
    
    	</body>
    	<script type="text/javascript" src="js/vue.js" ></script>
    	<script type="text/javascript">
    		
    		var vm = new Vue({
    			el:"#container",
    			data:{
    				str:"千锋教育"
    			}
    		});
    		
    	</script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

四、vue基本使用

4.1 vue实例

每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的;vue实例实现了数据与视图(HTML标签)的绑定,因此对于vue实例而言必不可少的两个部分:

  • html标签
  • 数据:vue实例中的data指定渲染的数据,数据可以是各种类型,但必须满足JSON对象格式
4.2 vue声明周期

在这里插入图片描述

4.3 模板语法
  • 插值:将vue实例中的数据(data)绑定到html模板中

    • 文本:{{attrName}} – Mustache语法

    • 标签属性绑定 v-bind

      <input v-bind:type="inputType" v-bind:name="inputName"/>
      
      • 1
    • 原始HTML

      <div v-html="htmlstr"></div>
      
      • 1
    • 支持JS表达式

      <p>{{number+1}}</p>
      <P>{{gender=='M'?'男':'女'}}</P>
      <p>{{ message.split('').reverse().join('') }}</p>
      <p>{{ 'http://'+message}}</p>
      
      • 1
      • 2
      • 3
      • 4
  • vue指令 v-开头的表达式

    • 指令

      • v-once 只挂载一次

      • v-bind 属性绑定数据

      • v-html 显示原始html

      • v-model 实现表单组件的双向绑定

        <input type="text" v-model:value="message"/>
        <input type="text" v-model="message"/>
        
        • 1
        • 2
      • v-on 绑定事件 触发执行vue实例中methods选项定义的js函数

    • 参数

    • 动态参数

      <input type="text" v-bind:[aaa]="inputName"/>
      
      • 1
  • 缩写

    • v-bind: ----> :
    • v-on:---->@
4.4 计算属性和侦听器
  • 计算属性:一个属性的值是通过对现有属性进行计算得到,现有属性值的改变会触发这个属性值的改变

    <body >
        <div id="container">
            str1:<input v-model="str1"/><br />
            str2:<input v-model="str2"/><br />
            <p>{{str3}}</p>
        </div>
    </body>
    <script type="text/javascript" src="js/vue.js" ></script>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#container",
            data:{
                str1:"千锋",
                str2:"武汉"
            },
            computed:{
                //相当于‘get方法’ 需要有返回值
                str3:function(){
                    return this.str1+this.str2;
                }
            }
        });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 侦听器:监听的属性值发生变化就会触发函数的执行

    <body >
        <div id="container">
            str1:<input v-model="str1"/><br />
        </div>
    </body>
    <script type="text/javascript" src="js/vue.js" ></script>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#container",
            data:{
                str1:"千锋"
            },
            watch:{
                str1:function(val){
                    console.log("str1:---"+val);
                }
            }
        });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
4.5Class 与 Style 绑定
  • CSS绑定

    <head>
        <meta charset="utf-8" />
        <title></title>
        <style type="text/css">
            .style1{color:red;}
            .style2{color:blue;}
            .style3{border:1px deepskyblue solid;border-radius: 5px;}
        </style>
    </head>
    <body >
        <div id="container">
            
            <div :class="{'style1':isShowColor,'style3':isShowBorder}" style="width: 100px; height: 100px;"> {{str}} </div>
            
            <div :class="[s1,s3]" style="width: 100px; height: 100px;">{{str}}</div>
            
            <div :class="[isRed?s1:s2,s3]" style="width: 100px; height: 100px;">{{str}}</div>
            
    <div :class="[isShowColor?s1:'',s3]" style="width: 100px; height: 100px;"> {{str}} </div>
            
    <div :class="[{'style1':isShowColor},s3]" style="width: 100px; height: 100px;">{{str}}</div>
        </div>
        
    </body>
    <script type="text/javascript" src="js/vue.js" ></script>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#container",
            data:{
                str:"千锋教育",
                s1:"style1",
                s2:"style2",
                s3:"style3",
                isShowColor:true,
                isShowBorder:true,
                isRed:false
            }
        });
    
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
4.6 添加与列表渲染
  • 条件渲染

    • v-if
    • v-show
  • 列表渲染

    • v-for
4.7 事件处理
4.7.1 事件监听
  • vue引用中事件触发的函数定义在vue实例的method选项中

  • 使用 v-on|@实现事件的监听

  • 案例:

    <body >
        <div id="container">
            <input type="button" value="测试按钮1" @click="test1"/>
        </div>
    </body>
    <script type="text/javascript" src="js/vue.js" ></script>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#container",
            data:{},
            methods:{
                test1:function(){
                    alert(1);
                }
            }
        });
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
4.7.2 获取事件对象
  • 在js函数中定义event参数

  • 案例:通过event对象实现传值

    <body >
        <div id="container">
            <input type="button" value="测试按钮1" :data-bid="bookId" data-haha="bb" @click="test1"/>
        </div>
    </body>
    <script type="text/javascript" src="js/vue.js" ></script>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#container",
            data:{
                bookId:101
            },
            methods:{
                test1:function(event){
                    //事件对象:触发函数执行的事件
                    console.log(event);
                    console.log(event.srcElement.dataset.bid);
                }
            }
        });
    
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 案例:通过参数传值

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8" />
    		<title></title>
    	</head>
    	<body >
    		<div id="container">
    			<h1 v-if="awesome === 'M'">if --- Vue is awesome!</h1>
    			<h1 v-show="awesome === 'M'">show --- Vue is awesome!</h1>
    
    			<table style="width:100%; border: 1px;" border="1" cellspacing="0">
    				<tr>
    					<th>序号</th>
    					<th>图书编号</th>
    					<th>名称</th>
    					<th>作者</th>
    					<th>价格</th>
    					<th>操作</th>
    				</tr>
    				<tr v-for="book,index in books">
    					<td>{{index+1}}</td>
    					<td>{{book.bookId}}</td>
    					<td>{{book.bookName}}</td>
    					<td>{{book.bookAuthor}}</td>
    					<td>{{book.bookPrice}}</td>
    					<td>
    			<input type="button" value="删除" :data-bookid="book.bookId" @click="doDel"/>
    			<input type="button" value="修改"  @click="doUpdate(book.bookId,$event)"/>
    					</td>
    				</tr>
    			</table>
    
    		</div>
    	</body>
    	<script type="text/javascript" src="js/vue.js" ></script>
    	<script type="text/javascript">
    		var vm = new Vue({
    			el:"#container",
    			data:{
    				awesome:"F",
    				books:[
    					{
    						bookId:1001,
    						bookName:"Java",
    						bookAuthor:"张三",
    						bookPrice:22.22
    					},
    					{
    						bookId:1002,
    						bookName:"Python",
    						bookAuthor:"张三",
    						bookPrice:22.22
    					},
    					{
    						bookId:1003,
    						bookName:"HTML5",
    						bookAuthor:"张三",
    						bookPrice:22.22
    					},
    					{
    						bookId:1004,
    						bookName:"vue",
    						bookAuthor:"张三",
    						bookPrice:22.22
    					}
    				]
    			},
    			methods:{
    				doDel:function(event){
    					var bid = event.srcElement.dataset.bookid;
    					console.log(bid);
    				},
    				doUpdate:function(bid,event){
    					console.log(event);
    					console.log("修改--"+bid);
    				}
    			}
    		});
    		
    	</script>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
4.7.3 事件修饰符
  • stop 阻止事件冒泡
  • self 限定自身触发事件(子标签不能触发)
  • once 限定事件只能被触发一次
  • prevent 消除标签的默认事件
4.7.4 按键修饰符
  • 实例:

    <body >
        <div id="container">
            <input type="text" v-model="str" @keyup.enter="test"/>
        </div>
    </body>
    <script type="text/javascript" src="js/vue.js" ></script>
    <script type="text/javascript">
        var vm = new Vue({
            el:"#container",
            data:{
                str:""
            },
            methods:{
                test:function(){
                    location.href="https://www.baidu.com/s?wd="+this.str;
                }
            }
        });
    
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 常见按键修饰符

    • .enter
    • .tab
    • .delete (捕获“删除”和“退格”键)
    • .esc
    • .space
    • .up
    • .down
    • .left
    • .right
4.7.5 系统修饰符
  • .ctrl
  • .alt
  • .shift
  • .meta
4.8 表单输入绑定
  • 输入组件与数据的双向绑定

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8" />
    		<title></title>
    	</head>
    	<body >
    		<div id="container">
    			<p>帐号:<input type="text" v-model="user.userName"/></p>
    			<p>密码:<input type="password" v-model="user.userPwd"/></p>
    			<p>
    				性别:<input type="radio" v-model="user.userGender" value="M"/><input type="radio" v-model="user.userGender" value="F"/></p>
    			<p>
    				爱好:<input type="checkbox" value="篮球" v-model="user.hobbies"/>篮球
    				<input type="checkbox" value="足球" v-model="user.hobbies"/>足球
    				<input type="checkbox" value="羽毛球" v-model="user.hobbies"/>羽毛球
    				<input type="checkbox" value="溜溜球" v-model="user.hobbies"/>溜溜球
    			</p>
    			<p>
    				城市:<select v-model="user.city">
    						<option value="北京">北京</option>
    						<option value="上海">上海</option>
    						<option value="广州">广州</option>
    						<option value="深圳">深圳</option>
    						<option value="武汉">武汉</option>
    				</select>
    			</p>
    			<p>
    				交友宣言:
    				<textarea v-model="user.desc"></textarea>
    			</p>
    			<p>
    				<input type="button" value="提交" @click="doSubmit"/>
    			</p>
    		</div>
    	</body>
    	<script type="text/javascript" src="js/vue.js" ></script>
    	<script type="text/javascript">
    		
    		var vm = new Vue({
    			el:"#container",
    			data:{
    				user:{
    					userName:"admin",
    					userPwd:"123456",
    					userGender:"M",
    					hobbies:["足球","羽毛球"],
    					city:"武汉",
    					desc:"wahaha"
    				}
    			},
    			methods:{
    				doSubmit:function(){
    					console.log("----~~~~----");
    					console.log(vm.user);
    				}
    			}
    		});
    	</script>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

五、vue案例

5.1 接口规范
接口名称在线音乐搜索
功能描述
请求URLhttp://47.96.11.185:9999/music/search
请求方式GET | POST
参数s string [必须] 搜索关键字
limit int [可选] 返回搜索结果的行数(默认10)
type int [可选] 搜索类型(1 单曲,10 … ,100 …)
offset int [可选] 从搜索结果第几条开始返回(默认0)
返回结果code 查询结果状态 200 表示查询成功
result 查询结果 包含搜索的音节结果集和总条数
songs 音乐结果集
songCount 总条数
结果示例:

六、组件

组件,将通用的HTML\CSS\JS模块进行封装

好处:实现复用

6.1 组件基本使用
6.1.1 注册组件

Vue.component(“组件名称”,{组件模版});

  • mystyle.css

    body{padding: 0px;margin: 0px;}
    .navbarDiv{background: #009688;padding: 12px 25px;}
    .navbarDiv .titleLabel{
        color: white;font-family: "微软雅黑";font-size: 18px;font-weight: bold;
    }
    .navbarDiv button{
    	border: none;border-radius: 3px;background: #009688;
    	color: white;margin-left: 15px;padding: 5px 10px;
    }
    .navbarDiv button:hover{background: white;color: #009688;}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • mycomponents.js

    Vue.component("navbar",{
    	template:`<div class="navbarDiv">
    				<label class="titleLabel">千锋教育</label>
    				<button @click="goHome">首页</button>
    				<button @click="goJava">Java</button>
    				<button @click="goPython">Python</button>
    				<button @click="goHtml5">HTML5</button>
    				<button @click="goAbout">关于我们</button>
    			</div>`,
    	methods:{
    		goHome:function (){
    			console.log("~~~goHome");
    		},
    		goJava:function (){
    			console.log("~~~goJava");
    		},
    		goPython:function (){
    			console.log("~~~goPython");
    		},
    		goHtml5:function (){
    			console.log("~~~goHtml5");
    		},
    		goAbout:function (){
    			console.log("~~~goAbout");
    		}
    	}
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
6.1.2 使用组件
  • html

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    		<link rel="stylesheet" href="css/mystyle.css" />
    	</head>
    	<body>
    		<div id="container">
    			<navbar></navbar>
    		</div>
    		<script type="text/javascript" src="js/vue.js" ></script>
    		<script type="text/javascript" src="js/mycomponents.js" ></script>
    		<script type="text/javascript">
    			var vm = new Vue({
    				el:"#container"
    			});
    		</script>
    	</body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
6.1.3 组件中的事件处理
  • 组件模版中的事件所触发的JS函数直接定义在组件中(methods)
6.1.4 组件中的数据
  • 在组件中的data中定义组件使用的数据,data的数据时通过函数返回的数据集

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dwyf2Mzg-1600321940807)(imgs/1598517992174.png)]

6.2 组件间的通信

父与子:组件需要在vue实例中来使用,vue实例称为组件的父容器,组件则是vue实例的子组件

6.2.1 父传子
  • 通过子组件定义props完成传值

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IjjfsYDc-1600321940808)(imgs/1598518725542.png)]

6.2.2 子传父
  • 通过子组件触发绑定在子组件上的自定义事件从而调用父组件中函数

    在这里插入图片描述

6.3 组件插槽使用
6.3.1 简单插槽使用
  • 在组件中使用slot定义一个插槽

    Vue.component("navbar",{
    	template:`<div class="navbarDiv">
    				<slot></slot>
    				<button @click="goHome">首页</button>
    				<button @click="goJava">Java</button>
    				<button @click="goPython">Python</button>
    				<button @click="goHtml5">HTML5</button>
    				<button @click="goAbout">关于我们</button>
    				<button @click="childMethod">Go</button>
    			</div>`
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 在调用组件时,可以在自定义组件中添加子标签,子标签就会被插入的插槽的位置

    <div id="container">
        <navbar>
            <label>千锋武汉</label>
            <label>Java2002</label>
        </navbar>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
6.3.2 具名插槽

当组件中的插槽数量>1时,需要给插槽取名字,我们可以将组件中的HTML元素插入到指定的插槽

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<div id="container">
			<mybanner>
				<template slot="s1">
					<label>从前有座山</label>
					<label>山里有座庙</label>
				</template>
				<template slot="s2">
					<img src="img/logo.png" height="30"/>
				</template>
			</mybanner>
		</div>
		<script type="text/javascript" src="js/vue.js" ></script>
		<script type="text/javascript">
			Vue.component("mybanner",{
				template:`<div style="height:100px; background:deepskyblue">
							<slot name="s1"></slot>
							<hr/>
							<slot name="s2"></slot>
						</div>`
			});
			
			var vm = new Vue({
				el:"#container",
				data:{
					value1:3
				}
			});
		</script>
	</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
6.3.3 插槽作用域
  • 通过在模版中的slot-scope属性可以获取插槽上绑定的属性

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    	</head>
    	<body>
    		<div id="container">
    			<mybanner>
    				<template slot="s1" slot-scope="data">
    					<label>{{data.attr1}}</label>
    					<label>{{data.attr2}}</label>
    				</template>
    				<template slot="s2">
    					<img src="img/logo.png" height="30"/>
    				</template>
    			</mybanner>
    		</div>
    		<script type="text/javascript" src="js/vue.js" ></script>
    		<script type="text/javascript">
    			Vue.component("mybanner",{
    				template:`<div style="height:100px; background:deepskyblue">
    							<slot name="s1" v-bind:attr1="user" v-bind:attr2="book"></slot>
    							<hr/>
    							<slot name="s2"></slot>
    						</div>`,
    				data:function(){
    					return {
    						user:{
    							id:1,
    							name:"zhangsan"
    						},
    						book:{
    							bid:101,
    							bname:"Java"
    						}
    					};
    				}
    			});
    			
    			var vm = new Vue({
    				el:"#container",
    				data:{
    					value1:3
    				}
    			});
    		</script>
    	</body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

七、axios

vue实现数据渲染,但是不具备与服务器的通信能力;在项目开发中我们需要通过ajax实现通信:

  • 原生ajax 繁琐
  • jQuery ajax 笨重
  • axios 简洁、高效的异步通信,对RESTful的良好支持
7.1 介绍

axios 是对ajax的封装的js库(js文件),实现前后端之间的异步交互

7.2 简单使用
  • 在html中引入axios的js库

    • npm

    • cdn

      <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
      
      • 1
    • 离线引用

      • 下载
      • 引用
  • 简单使用案例

7.3 axios请求
get请求
axios.get("url",{params:{s:"抖音热歌",limit:15}}).then(function(res){
    //回调函数   res.data 是 响应的数据
}).catch(function(e){
    //异常处理函数
});
  • 1
  • 2
  • 3
  • 4
  • 5
post请求
//参数传递默认使用 body 传递,在控制器中需要通过@RequestBody接收数据
axios.post("url",{bookId:1001,bookName:"Java"}).then(function(res){
    //
});
  • 1
  • 2
  • 3
  • 4
@RestController
@RequestMapping("/axios")
@CrossOrigin
public class AxiosController {

    @RequestMapping("/get")
    public Book getBook(@RequestBody Book book){
        System.out.println("--------------get");
        return new Book();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
axios请求
axios({
    method: 'post',
    url: 'http://localhost:8080/axios/get',
    data: {
        bookId:101,
        bookName:"Java"
    },
    params:{
        s:"抖音热歌"
    },
    headers:{
		token:"AAAA"
    }
}).then(function(res){
    //回调函数
}).catch(function(e){
    //异常处理
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
@RestController
@RequestMapping("/axios")
@CrossOrigin
public class AxiosController {

    @RequestMapping("/get")
    public Book getBook(@RequestBody Book book, 
                        @RequestParam String s, 
                        @RequestHeader String token){
        System.out.println("--------------get");
        return new Book();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
合并执行多个异步请求
function getUserAccount() {
  return axios.get('/user/12345');
}

function getUserPermissions() {
  return axios.get('/user/12345/permissions');
}

axios.all([getUserAccount(), getUserPermissions()])
   .then(axios.spread(function (acct, perms) {
    // 两个请求现在都执行完成
}));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
7.4 axios请求方式

axios对RESTful URL设计风格有很好的支持

  • axios.get(url[, config]) 查询操作

  • axios.delete(url[, config]) 删除操作

  • axios.options(url[, config]) 浏览器向服务器发送请求预检

  • axios.post(url[, data[, config]]) 添加操作

  • axios.put(url[, data[, config]]) 修改操作

7.5 axios请求参数
{
   // `url` 是用于请求的服务器 URL
  url: '/user',

  // `method` 是创建请求时使用的方法
  method: 'get', // default

  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  transformRequest: [function (data, headers) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // `headers` 是即将被发送的自定义请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // `params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params: {
    ID: 12345
  },

   // `paramsSerializer` 是一个负责 `params` 序列化的函数
  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  paramsSerializer: function(params) {
    return Qs.stringify(params, {arrayFormat: 'brackets'})
  },

  // `data` 是作为请求主体被发送的数据
  // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  // - Node 专属: Stream
  data: {
    firstName: 'Fred'
  },

  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout: 1000,

   // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false, // default

  // `adapter` 允许自定义处理请求,以使测试更轻松
  // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
  adapter: function (config) {
    /* ... */
  },

 // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
  // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },

   // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'json', // default

  // `responseEncoding` indicates encoding to use for decoding responses
  // Note: Ignored for `responseType` of 'stream' or client-side requests
  responseEncoding: 'utf8', // default

   // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
  xsrfCookieName: 'XSRF-TOKEN', // default

  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
  xsrfHeaderName: 'X-XSRF-TOKEN', // default

   // `onUploadProgress` 允许为上传处理进度事件
  onUploadProgress: function (progressEvent) {
    // Do whatever you want with the native progress event
  },

  // `onDownloadProgress` 允许为下载处理进度事件
  onDownloadProgress: function (progressEvent) {
    // 对原生进度事件的处理
  },

   // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength: 2000,

  // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
  validateStatus: function (status) {
    return status >= 200 && status < 300; // default
  },

  // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
  // 如果设置为0,将不会 follow 任何重定向
  maxRedirects: 5, // default

  // `socketPath` defines a UNIX Socket to be used in node.js.
  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.
  // Only either `socketPath` or `proxy` can be specified.
  // If both are specified, `socketPath` is used.
  socketPath: null, // default

  // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
  // `keepAlive` 默认没有启用
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),

  // 'proxy' 定义代理服务器的主机名称和端口
  // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
  // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
  proxy: {
    host: '127.0.0.1',
    port: 9000,
    auth: {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  },

  // `cancelToken` 指定用于取消请求的 cancel token
  // (查看后面的 Cancellation 这节了解更多)
  cancelToken: new CancelToken(function (cancel) {
  })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
7.6 axios响应对象
{
  // `data` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},

   // `config` 是为请求提供的配置信息
  config: {},
 // 'request'
  // `request` is the request that generated this response
  // It is the last ClientRequest instance in node.js (in redirects)
  // and an XMLHttpRequest instance the browser
  request: {}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
7.7 箭头函数
  • 原始写法

    axios.get("http://47.96.116.68:9999/music/search",{params:{s:'抖音热歌',limit:'15'}}).then(function(res){
        console.log(res.data);
        vm.musics = res.data.result.songs;
    });
    
    • 1
    • 2
    • 3
    • 4
  • 箭头函数

    axios.get("http://47.96.116.68:9999/music/search",{params:{s:'抖音热歌',limit:'15'}}).then((res)=>{
        console.log(res.data);
        this.musics = res.data.result.songs;
    });
    
    • 1
    • 2
    • 3
    • 4

八、RESTful

Representational State Transfer,表述性状态传递

RESTful 就是遵守REST规则的url设计规范

8.1 REST规则
  • 每个请求的URL代表服务端的唯一资源

    101   Java
    102   C++
    
    传统的URL设计(不符合REST规范,同一个url可以删除多个图书)
       http://localhost:8080/book/delete?id=101
       http://localhost:8080/book/delete?id=102
       
    REST风格的URL设计
       http://localhost:8080/book/delete/101
       http://localhost:8080/book/delete/102
       
       http://localhost:8080/book/get/101
       http://localhost:8080/book/get/102
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 不同的操作使用不同的请求方式

    删除操作
    	http://localhost:8080/book/101   	[delete]
    	
    查询操作
    	http://localhost:8080/book/101		[get]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • get 查询
    • delete 删除
    • put 修改
    • post 添加
  • 资源的表现形式是以JSON/XML形式

    • @ResponseBody
    • @RestController
  • 客户端与接口之间的交互式无状态的(HTTP协议)(session就不可用)

8.2 RESTful风格案例
@RestController
@RequestMapping("/book")
public class BookController {

    @Resource
    private BookService bookService;

    @RequestMapping(value = "/list",method = RequestMethod.GET)
    public List<Book> listBook(){
        System.out.println("----------------list");
        return bookService.listBooks();
    }

    //  http://localhost:8080/book/101
    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    public Book getBook(@PathVariable("id") int bookId){
        System.out.println("----------------get");
        return new Book();
    }

    //  http://localhost:8080/book/101
    @RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
    public ResultVO deleteBook(@PathVariable("id") int bookId){
        System.out.println("----------------delete");
        return new ResultVO();
    }

    //  http://localhost:8080/book/101
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    public ResultVO saveBook(@RequestBody Book book){
        System.out.println("----------------add");
        return new ResultVO();
    }

    //  http://localhost:8080/book/101
    @RequestMapping(value = "/{id}",method = RequestMethod.PUT)
    public ResultVO updateBook(@RequestBody Book book){
        System.out.println("----------------update");
        return new ResultVO();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

九、Swagger2

9.1 介绍

swagger2是一个用于生成服务器接口说明规范性文档、同时能够完成对接口的测试的工具(框架)

  • 作用:
    • 生成接口文档
    • 测试接口
  • Swagger组件
    • Springfox swagger2 用于扫描服务器接口
    • Springfox swagger UI 用于生成可视化的说明文档
9.2 SpringBoot整合swagger2
  • 添加依赖

    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 配置

    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
    
        @Bean
        public Docket getDocket(){
            //Docket对象用于设置接口说明信息
            Docket docket = new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(getApiInfo())   //设置说明文档的“封面”信息
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.qfedu.springboot.demo2.controllers"))  //指定扫描接口的范围
                    .paths(PathSelectors.any())
                    .build();
            return docket;
        }
    
        public ApiInfo getApiInfo(){
            ApiInfoBuilder builder = new ApiInfoBuilder()
                    .title("微分销管理平台接口说明文档")          //设置标题
                    .description("这是api接口说明文档的描述信息")
                    .version("2.0.1")
                    .contact(new Contact("阿龙","http://www.qfedu.com","haha@hehe.com"));
                    
            ApiInfo apiInfo = builder.build();
            return apiInfo;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  • 启动应用,访问api文档

    • http://localhost:8080/swagger-ui.html
9.3 swagger注解

为了生成更为规范的api文档,swagger提供了响应的注解

  • @Api 类注解,说明当前控制器类的作用

    @RestController
    @RequestMapping("/book")
    @Api(tags = "图书信息接口")
    public class BookController {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • @ApiOperation 方法注解,对接口的功能进行描述

    • value 功能说明
    • notes 辅助说明
    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    @ApiOperation(value = "根据ID查询图书信息", notes = "辅助说明")
    public Book getBook(@PathVariable("id") int bookId){
        System.out.println("----------------get");
        return new Book();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y5L8jrYj-1600321940812)(imgs/1598597326303.png)]

  • @ApiImplicitParam 方法注解,用于对接口的参数进行说明

    • name 参数key
    • value 参数说明
    • required 是否必须
    • dataType 参数类型
    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    @ApiOperation(value = "根据ID查询图书信息", notes = "辅助说明")
    @ApiImplicitParam(name = "id", value = "要查询的图书的id",required = true, dataType = "int")
    public Book getBook(@PathVariable("id") int bookId){
        System.out.println("----------------get");
        return new Book();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gqtS1Pp3-1600321940813)(imgs/1598597690065.png)]

  • @ApiImplicitParams方法注解,用于多参数接口的参数说明

    @RequestMapping(value = "/get",method = RequestMethod.GET)
    @ApiImplicitParams({
        @ApiImplicitParam(name = "bookId", value = "要查询的图书的id",required = true, dataType = "int"),
        @ApiImplicitParam(name = "bookName", value = "要查询的图书的名称",required = true, dataType = "string")
    })
    public Book getBook(int bookId,String bookName){
        System.out.println("----------------get111");
        return new Book();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gqMNOYzv-1600321940816)(imgs/1598598029709.png)]

  • @ApiModel 类注解

  • @ApiModelProperty 属性注解

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    @ApiModel(value = "图书对象",description = "包含图书信息的实体对象")
    public class Book {
        @ApiModelProperty(value = "图书ID",dataType = "int",required = true)
        private int bookId;
        @ApiModelProperty(value = "图书名称",dataType = "string",required = true)
        private String bookName;
        private String bookAuthor;
        private double bookPrice;
        private String bookImg;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LcDaqDM3-1600321940817)(imgs/1598598433351.png)]

  • @ApiIgnore方法注解,用在接口方法前,用于声明忽略此接口的说明

十、前后端分离用户认证

前后端分离开发,前端和服务端之间是无状态请求,每次请求都会创建一个新的session,因此不能使用session来实现用户认证。

10.1 基于认证中心的解决方案

使用redis构建一个“公共session”

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7wySrPNe-1600321940819)(imgs/1598600431686.png)]

10.2 基于JWT的解决方案

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rXg79dsq-1600321940820)(imgs/1598602683550.png)]

10.3 JWT

Json Web Token 就是一种token字符串的生成规则

> [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BI1CkfES-1600321940822)(imgs/1598603469061.png)]

  • 导入jwt依赖

    <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.10.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
        <scope>runtime</scope>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 生成token

     //生成token
    String token = Jwts.builder()
        .setSubject(userName)   //设置用户信息
        .setId("101")            //设置用户ID
        .setIssuedAt(new Date()) //设置token的创建时间
        .setExpiration(new Date(System.currentTimeMillis() + 30 * 60000))  //设置过期时间
        .signWith(SignatureAlgorithm.HS256, "QFedu123")
        .compact();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 认证token

    package com.qfedu.jwtserver.controller;
    
    import com.qfedu.jwtserver.beans.Goods;
    import com.qfedu.jwtserver.vo.ResultVO;
    import io.jsonwebtoken.Claims;
    import io.jsonwebtoken.Jws;
    import io.jsonwebtoken.JwtParser;
    import io.jsonwebtoken.Jwts;
    import org.springframework.web.bind.annotation.*;
    
    import javax.xml.transform.Result;
    import java.util.*;
    
    @RestController
    @RequestMapping("/goods")
    @CrossOrigin
    public class GoodsController {
    
        @RequestMapping(value = "/list",method = RequestMethod.GET)
        public ResultVO listGoods(@RequestHeader(required = false) String token){
           if (token == null){
                return new ResultVO(1,"请先登录!");
           }else{
               //验证token
               try {
                   JwtParser parser = Jwts.parser();
                   parser.setSigningKey("QFedu123");
                   Jws<Claims> jws = parser.parseClaimsJws(token);
                   //获取的解析的token中的用户名
                   String username = jws.getBody().getSubject();
    
                   ArrayList<Goods> goodsList = new ArrayList<>();
                   goodsList.add(new Goods("10001", "Java"));
                   goodsList.add(new Goods("10002", "C++"));
                   goodsList.add(new Goods("10003", "Python"));
                   return new ResultVO(0,"success",goodsList);
               }catch (Exception e){
                   return new ResultVO(1,"请重新登录!");
               }
           }
        }
    
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

`java
package com.qfedu.jwtserver.controller;

import com.qfedu.jwtserver.beans.Goods;
import com.qfedu.jwtserver.vo.ResultVO;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import org.springframework.web.bind.annotation.*;

import javax.xml.transform.Result;
import java.util.*;

@RestController
@RequestMapping("/goods")
@CrossOrigin
public class GoodsController {

  @RequestMapping(value = "/list",method = RequestMethod.GET)
  public ResultVO listGoods(@RequestHeader(required = false) String token){
     if (token == null){
          return new ResultVO(1,"请先登录!");
     }else{
         //验证token
         try {
             JwtParser parser = Jwts.parser();
             parser.setSigningKey("QFedu123");
             Jws<Claims> jws = parser.parseClaimsJws(token);
             //获取的解析的token中的用户名
             String username = jws.getBody().getSubject();

             ArrayList<Goods> goodsList = new ArrayList<>();
             goodsList.add(new Goods("10001", "Java"));
             goodsList.add(new Goods("10002", "C++"));
             goodsList.add(new Goods("10003", "Python"));
             return new ResultVO(0,"success",goodsList);
         }catch (Exception e){
             return new ResultVO(1,"请重新登录!");
         }
     }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

}



  • 1
  • 2
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/220975?site
推荐阅读
相关标签
  

闽ICP备14008679号