京淘项目Day18

本文详细介绍了Dubbo框架的负载均衡策略,包括hash一致性、挑选访问压力最小的服务器、随机访问及轮询策略。同时,深入探讨了Dubbo的通讯原理及其与Zookeeper的集成。此外,还提供了京淘项目中单点登录功能的实现步骤,涵盖用户注册、登录、信息回显及退出操作。
摘要由CSDN通过智能技术生成

1.Dubbo负载均衡说明

1.1 zk数据存储结构

在这里插入图片描述

1.2 Dubbo通讯原理

通讯协议: dubbo协议(tcp-ip)
说明: dubbo协议将TCP-IP协议进行封装.
在这里插入图片描述

Dubbo框架中使用dubbo协议建立了链接,之后通过IP:20880等端口进行通讯,与LinuxIP地址无关.
在这里插入图片描述

1.3 Dubbo负载均衡策略

1.3.1 hash一致性原则

根据IP:port进行hash运算,之后绑定固定的提供者进行访问.
效果: 以后消费者与服务提供者进行了绑定.
在这里插入图片描述

1.3.2 挑选访问压力最小的

说明:挑选当前服务器压力较小的进行访问.
在这里插入图片描述

1.3.3 随机访问

说明:如果什么都不配置,则采用随机算法.
在这里插入图片描述

1.3.4 轮询策略

在这里插入图片描述

1.3 简述什么是客户端负载均衡/集中式负载均衡

1).什么是集中式的负载均衡 (nginx)
特点:
1).用户访问服务器时,自己不清楚访问的真实的服务器到底是谁,由nginx服务器动态的反向代理实现.
2).统一由负载均衡服务器进行负载. 问题 负载均衡服务器访问压力高.

客户端负载均衡
1).消费者在访问服务提供者时清楚的了解 到底应该访问哪台服务器.
2).由于每个客户端都进行负载均衡.相当于将压力均匀的分配给客户端.访问压力低.

核心: 1).nginx一般只负责反向代理
2).在微服务框架中 几乎都是客户端负载均衡服务器.

2.京淘项目改造

2.1导入jar包

 <!--引入dubbo配置 -->
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.2 添加接口

说明:在jt-common中添加dubbo接口
在这里插入图片描述

2.3 构建服务提供者(JT-SSO)

2.3.1 编辑提供者Service实现类

在这里插入图片描述

2.3.2 编辑YML配置文件

server:
  port: 8093
  servlet:
    context-path: /
spring:
  datasource:
    #引入druid数据源   导入数据源的包
    #type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    #url: jdbc:mysql://192.168.126.129:8066/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: root

mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true

logging:
level:
com.jt.mapper: debug

#关于Dubbo配置
dubbo:
scan:
basePackages: com.jt #指定dubbo的包路径
application: #应用名称
name: provider-user #一个接口对应一个服务名称
registry:
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协议
name: dubbo #使用dubbo协议(tcp-ip) web-controller直接调用sso-Service
port: 20880 #每一个服务都有自己特定的端口 不能重复.

  • 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

2.4 构建服务消费者(JT-WEB)

2.4.1 编辑UserController

在这里插入图片描述

2.4.2 编辑YML配置文件

server:
  port: 8092    
spring:     #定义springmvc视图解析器
  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp

#配置dubbo
dubbo:
scan:
basePackages: com.jt
application:
name: consumer-web #定义消费者名称
registry: #注册中心地址
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3. 实现单点登录业务功能

3.1 完成用户注册

3.1.1 业务分析

1).url地址
在这里插入图片描述
2).页面JS
在这里插入图片描述

$.ajax({
			type : "POST",
			url : "/user/doRegister",
			contentType : "application/x-www-form-urlencoded; charset=utf-8",
			data : {password:_password,username:_username,phone:_phone},
			dataType : 'json',
			success : function(result) {
				if(result.status == "200"){
					// 注册成功,去登录页
					showMessage('注册成功,请登录!');
					verc();
					$("#registsubmit").removeAttr("disabled").removeClass()
							.addClass("btn-img btn-regist");
					isSubmit = false;
					return;
				}else{
					showMessage('注册失败,请联系管理员!');
					//alert('注册失败,请重新注册!   ' + result.data );
				}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

分析返回值:返回SysResult对象

3.1.2 编辑UserController

/**
     * 业务说明:完成用户数据入库操作
     * 1.url地址: http://www.jt.com/user/doRegister
     * 2.参数问题: {password:_password,username:_username,phone:_phone},
     * 3.返回值结果: SysResult对象
     */
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">"/doRegister"</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@ResponseBody</span>
<span class="token keyword">public</span> SysResult <span class="token function">doRegister</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token comment">//service 第三方接口. 直接rpc调用访问jt-sso中的实现类</span>
    userService<span class="token punctuation">.</span><span class="token function">saveUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> SysResult<span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

3.1.3 编辑UserService

package com.jt.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;

@Service //注意使用Dubbo的注解
public class DubboUserServiceImpl implements DubboUserService{ //alt+shift+p

<span class="token annotation punctuation">@Autowired</span>
<span class="token keyword">private</span> UserMapper userMapper<span class="token punctuation">;</span>

<span class="token comment">/**
 * 1.密码加密
 * 2.邮箱使用手机代替
 * @param user
 */</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">saveUser</span><span class="token punctuation">(</span>User user<span class="token punctuation">)</span> <span class="token punctuation">{</span>

    String md5Password <span class="token operator">=</span> DigestUtils<span class="token punctuation">.</span><span class="token function">md5DigestAsHex</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span><span class="token function">getPassword</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getBytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    user<span class="token punctuation">.</span><span class="token function">setPassword</span><span class="token punctuation">(</span>md5Password<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setEmail</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span><span class="token function">getPhone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    userMapper<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 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

3.2 用户登录实现

3.2.1 用户登录要求

如果用户在www.jt.com中完成完成了登录操作.则用户在其他的京淘项目的子系统中都可以实现免密登录.
在这里插入图片描述

3.2.2 SSO介绍

单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是目前比较流行的 [1]

在这里插入图片描述
实现步骤:
1.当用户输入用户名和密码之后点击提交按钮.将数据传给JT-WEB服务器.
2.JT-WEB利用RPC方式访问JT-SSO 校验数据是否有效.
3.如果校验的数据准备无误,之后将用户信息保存到Redis中. key 使用uuid, value使用userJSON. 并且设定7天超时.
4.JT-SSO 将服务器数据返回给JT-WEB服务器.(如果用户名和密码错误的则返回为null即可).
5.JT-WEB服务器将数据保存到Cookie中.(要求实现Cookie共享).

3.2.3 用户登录页面分析

1).页面URL分析
在这里插入图片描述

2).页面参数分析
在这里插入图片描述
3).页面JS分析
在这里插入图片描述

3.2.4 编辑UserController

/**
     * 1.url地址:http://www.jt.com/user/doLogin?r=0.04360522021726099
     * 2.参数:  {username:_username,password:_password},
     * 3.返回值结果:  SysResult
     *
     * 需求1:  将cookie名称为 "JT_TICKET"数据输出到浏览器中,要求7天超时.
     * 并且实现"jt.com"数据共享
     *
     * Cookie特点:
     *  1.浏览器中只能查看当前网址下的Cookie信息
     *  2.doMain 表示cookie共享的策略
     *    doMain:www.jd.com   当前的Cookie数据只能在当前域名中使用
     *    doMain:.jd.com      当前Cookie是共享的可以在域名为jd.com结尾的域名中共享.
     *
     *  * * */
    @RequestMapping("/doLogin")
    @ResponseBody
    public SysResult doLogin(User user, HttpServletResponse response){
    <span class="token comment">//完成用户登录操作 之后获取ticket密钥信息</span>
    String ticket <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">doLogin</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span>ticket<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token comment">//如果为null,则说明用户名或密码有问题</span>
        <span class="token keyword">return</span> SysResult<span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">//1.创建Cookie对象</span>
    Cookie cookie <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Cookie</span><span class="token punctuation">(</span><span class="token string">"JT_TICKET"</span><span class="token punctuation">,</span>ticket<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//2.设定cookie存活的时间   value=-1  当用户关闭会话时,cookie删除</span>
    <span class="token comment">//2.设定cookie存活的时间   value= 0  立即删除cookie</span>
    <span class="token comment">//2.设定cookie存活的时间   value= &gt;0 设定cookie超时时间</span>
    cookie<span class="token punctuation">.</span><span class="token function">setMaxAge</span><span class="token punctuation">(</span><span class="token number">7</span><span class="token operator">*</span><span class="token number">24</span><span class="token operator">*</span><span class="token number">60</span><span class="token operator">*</span><span class="token number">60</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//3.在jt.com的域名中实现数据共享.</span>
    cookie<span class="token punctuation">.</span><span class="token function">setDomain</span><span class="token punctuation">(</span><span class="token string">"jt.com"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    cookie<span class="token punctuation">.</span><span class="token function">setPath</span><span class="token punctuation">(</span><span class="token string">"/"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//一般情况下都是/</span>
    <span class="token comment">//4.将数据保存到浏览器中</span>
    response<span class="token punctuation">.</span><span class="token function">addCookie</span><span class="token punctuation">(</span>cookie<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> SysResult<span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 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

3.2.5 编辑UserService

/**
     * 目的: 校验用户信息是否有效并且实现单点登录操作.
     * 步骤:
     *      1.校验用户名和密码是否正确(密码明文转化为密文)
     *      2.查询数据库检查是否有结果
     *      3.如果有结果,则动态生成TICKET信息(uuid),将user对象转化为JSON
     *      4.将数据保存到redis中,并且设定超时时间.
     *      5.返回当前用户登录的密钥.
     *
     * @param user
     * @return
     */
    @Override
    public String doLogin(User user) {
        String passwork = user.getPassword();
        String md5Pass = DigestUtils.md5DigestAsHex(passwork.getBytes());
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername())
                    .eq("password", md5Pass);
        //获取的是用户的全部记录 (包含涉密信息)
        User userDB = userMapper.selectOne(queryWrapper);
        //校验数据是否有效
        if( userDB == null){
            //用户名和密码错误
            return null;
        }
    <span class="token comment">//如果程序执行到这里,说明用户名和密码正确的. 开启单点登录流程</span>
    String ticket <span class="token operator">=</span> UUID<span class="token punctuation">.</span><span class="token function">randomUUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                        <span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token string">"-"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//脱敏处理 余额/密码/手机号/家庭地址</span>
    userDB<span class="token punctuation">.</span><span class="token function">setPassword</span><span class="token punctuation">(</span><span class="token string">"123456你信不???"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    String userJSON <span class="token operator">=</span> ObjectMapperUtil<span class="token punctuation">.</span><span class="token function">toJSON</span><span class="token punctuation">(</span>userDB<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//操作时保证原子性</span>
    jedisCluster<span class="token punctuation">.</span><span class="token function">setex</span><span class="token punctuation">(</span>ticket<span class="token punctuation">,</span> <span class="token number">7</span><span class="token operator">*</span><span class="token number">24</span><span class="token operator">*</span><span class="token number">60</span><span class="token operator">*</span><span class="token number">60</span><span class="token punctuation">,</span> userJSON<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> ticket<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 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

3.2.6 页面效果测试

在这里插入图片描述

3.3 实现用户信息回显

3.3.1 业务需求

说明:当用户登录成功之后,需要在顶部实现数据的回显. 根据ticket获取用户用户的JSON信息.
在这里插入图片描述

3.3.2 编辑页面JS

var TT = JT = {
	checkLogin : function(){
	    //获取指定名称的cookie
		var _ticket = $.cookie("JT_TICKET");
		if(!_ticket){
			return ; //如果数据为null则直接return
		}
		//当dataType类型为jsonp时,jQuery就会自动在请求链接上增加一个callback的参数
		$.ajax({
			url : "http://sso.jt.com/user/query/" + _ticket,
			dataType : "jsonp",
			type : "GET",
			success : function(data){
				if(data.status == 200){
					//把json串转化为js对象
					var _data = JSON.parse(data.data);
					var html =_data.username+",欢迎来到京淘!<a href=\"http://www.jt.com/user/logout.html\" class=\"link-logout\">[退出]</a>";
					$("#loginbar").html(html);
				}
			}
		});
	}
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

3.3.3 编辑JT-SSO中的UserController

 /**
     * 完成回显用户名称
     * url地址: http://sso.jt.com/user/query/494fcc9ac98e49bc98baffd6d8fc6802?callback=jsonp1597999688824&_=1597999688872
     * 参数:  ticket信息
     * 返回值: SysResult对象(userJSON)
     * */
    @RequestMapping("/query/{ticket}")
    public JSONPObject  findUserByTicket(@PathVariable String ticket,String callback){
    String userJSON <span class="token operator">=</span> jedisCluster<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>ticket<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>StringUtils<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span>userJSON<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token comment">//ticket有误.返回错误信息即可</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">JSONPObject</span><span class="token punctuation">(</span>callback<span class="token punctuation">,</span> SysResult<span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">JSONPObject</span><span class="token punctuation">(</span>callback<span class="token punctuation">,</span> SysResult<span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span>userJSON<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

作业

完成用户退出操作.将操作Cookie的方法封装为API简化调用流程.

                                </div><div data-report-view="{&quot;mod&quot;:&quot;1585297308_001&quot;,&quot;dest&quot;:&quot;https://blog.csdn.net/qq_16804847/article/details/108141807&quot;,&quot;extend1&quot;:&quot;pc&quot;,&quot;ab&quot;:&quot;new&quot;}"><div></div></div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e0530931f4.css" rel="stylesheet">
                            </div>
weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值