博客之QQ登录功能(一)
流程图
上图spring social 封装了1-8步需要的工作
1、新建包和书写配置文件
public class QQProperties {//App唯一标 识private String appId = "100550231";private String appSecret = "69b6ab57b22f3c2fe6a6149274e3295e";//QQ供应商private String providerId = "callback.do";//拦截器拦截的请求private String filterProcessesUrl = "/qqLogin";//get set 方法//...
}
@ConfigurationProperties(prefix = "blog.security")
public class BlogSecurityProperties {private QQProperties qqProperties = new QQProperties();//get set...
}
@Configuration
//让我们的配置生效
@EnableConfigurationProperties (BlogSecurityProperties.class)
public class BlogSecurityConfig {}
2、获取QQ用户信息
package com.zzz.blog.social.qq.api;public interface QQ {//返回一个QQ的用户信息QQUserInfo getUserInfo();
}
package com.zzz.blog.social.qq.api;import org.springframework.social.oauth2.AbstractOAuth2ApiBinding;public class QQImpl extends AbstractOAuth2ApiBinding implements QQ{private static final String URL_GET_USERINFO = "https://graph.qq.com/user/get_user_info?oauth_consumer_key=%s&openid=%s";//外界赋值private String appId;//用户的唯一 标识,urlprivate String openId;private ObjectMapper objectMapper = new ObjectMapper();@Overridepublic QQUserInfo getUserInfo() {// TODO Auto-generated method stubreturn null;}}
package com.zzz.blog.social.qq.api;public class QQUserInfo {private String is_lost;private String province;private String city;private String year;private String constellation;private String ret;private String msg;private String nickname;private String figureurl;private String figureurl_1;private String figureurl_2;private String figureurl_qq_1;private String figureurl_qq_2;private String figureurl_qq;private String figureurl_type;private String gender_type;private String gender;private String is_yellow_vip;private String vip;private String yellow_vip_level;private String level;private String is_yellow_year_vip;private String openId;//get/set...
}
修改代码:
//获取用户信息@Overridepublic QQUserInfo getUserInfo() {//拼接参数String url = String.format(URL_GET_USERINFO, appId, openId);//发送请求String result = getRestTemplate().getForObject(url, String.class);//处理返回值QQUserInfo userInfo = null;try {userInfo = objectMapper.readValue(result, QQUserInfo.class);userInfo. setOpenId(openId);} catch (JsonProcessingException e) {throw new RuntimeException(" 获取用户信息失败!");}return userInfo;}
3、如何获得OpenId以及AppId
public class QQImpl extends AbstractOAuth2ApiBinding implements QQ{private static final String URL_GET_USERINFO = "https://graph.qq.com/user/get_user_info?pauth_consumer_key=%s&openid=%s";private static final String URL_GET_OPENID = "https://graph.qq.com/oauth2.0/me?access_token=%s";//外界赋值private String appId;//用户的唯一 标识,urlprivate String openId;private ObjectMapper objectMapper = new ObjectMapper();public QQImpl(String accessToken, String appId) {//自动拼接一个参数super(accessToken, TokenStrategy.ACCESS_TOKEN_PARAMETER) ;//赋值appid this.appId = appId;//赋值openid//通过url获得openid//拼接参数String url = String.format(URL_GET_OPENID, accessToken);//发送请求String result = getRestTemplate().getForObject(url, String.class);//处理返回值//callback( {"client_ id":"100550231", ”openid":"CDF1A28F8698E326D173DE17437FB098"} );result = StringUtils.replace(result, "callback( ","");result = StringUtils.replace(result, " );","");//{"client_ id": "100550231","openid": "CDF1A28F8698E326D173DE17437FB098"}OpenId id = null;try {id = objectMapper.readValue(result, OpenId.class);} catch (JsonProcessingException e) {throw new RuntimeException( "获取OpenId失败! ! ");}//赋值openidthis.openId = id.getOpenid();}//获取用户信息@Overridepublic QQUserInfo getUserInfo() {...}}
package com.zzz.blog.social.qq.api;public class OpenId {private String client_id;private String openid;//get/set
}
4、完成QQOAuth2Template
package com.zzz.blog.social.qq.template;import ...public class QQOAuth2Template extends OAuth2Template{public QQOAuth2Template(String clientId, String clientSecret, String authorizeUrl, String accessTokenUrl) {super(clientId, clientSecret, authorizeUrl, accessTokenUrl);//使clientId、clientSecret可以拼接到一起setUseParametersForClientAuthentication(true);}//添加text/html@Overrideprotected RestTemplate createRestTemplate() {RestTemplate template = super.createRestTemplate();template.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));return template;}//把请求的格式按照qq的标准,做了一些自定义信息 自己处理请求 按&分割字符,分割后如下//access_token=FE04***** *****************CCE2 items[0]//expires_in=7776000 item[0]//refresh_token=88E4********* **************BE14 item[1]@Overrideprotected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) {String responseStr = getRestTemplate().postForObject(accessTokenUrl, parameters, String.class);//StringUtils.split只切割了一次,坑String[] items = StringUtils.split(responseStr, "&");String[] item = StringUtils.split(items[1], "&");String access_token =StringUtils.replace(items[0], "access_token=", "");Long expires_in = new Long(StringUtils.replace(item[0], "expires_in=", ""));String refresh_token = StringUtils.replace(item[1], "refresh_token=", "");return new AccessGrant(access_token, null, refresh_token, expires_in);}}
5、完成QQAdapter与ServiceProvider
package com.zzz.blog.social.qq.connection;import ...public class QQAdapter implements ApiAdapter<QQ>{@Overridepublic boolean test(QQ api) {// 始终为truereturn true;}@Overridepublic void setConnectionValues(QQ api, ConnectionValues values) {//获取userinfoQQUserInfo userInfo = api. getUserInfo();//获取用户名称values.setDisplayName(userInfo.getNickname());//获取头像values.setImageUrl(userInfo.getFigureurl_qq_1());//获取个人主页values.setProfileUrl(null);//openid,用户在服务商中的唯一标识values.setProviderUserId(userInfo.getOpenId());}@Overridepublic UserProfile fetchUserProfile(QQ api) {// TODO Auto-generated method stubreturn null;}@Overridepublic void updateStatus(QQ api, String message) {// TODO Auto-generated method stub}}
package com.zzz.blog.social.qq.connection;import ...public class QQServiceProvider extends AbstractOAuth2ServiceProvider<QQ>{//将用户导向认证服务器中的ur1地址,用户在该地址上进行授权private static final String URL_AUTHORIZE = "https://graph.qq.com/oauth2.0/authorize";//在获取令牌的时候,需要访问的urlprivate static final String URL_ACCESSTOEKN = "https://graph.qq.com/oauth2.0/token";private String appId;//1-6public QQServiceProvider(String appId,String appSecret) {super(new QQOAuth2Template(appId, appSecret, URL_AUTHORIZE, URL_ACCESSTOEKN));this.appId = appId;}//7-8@Overridepublic QQ getApi(String accessToken) {// TODO Auto-generated method stubreturn new QQImpl(accessToken, appId);}}
6、完成QQConfig与ConnectionFactory
package com.zzz.blog.social.qq.connection;import ...public class QQConnectionFactory extends OAuth2ConnectionFactory<QQ>{public QQConnectionFactory(String providerId, String appId,String appSecret) {super(providerId, new QQServiceProvider(appId, appSecret), new QQAdapter());}}
package com.zzz.blog.social.qq.config;import ...@Configuration
@EnableSocial
@Order(2)
public class QQConfig extends SocialConfigurerAdapter{@Autowiredprivate BlogSecurityProperties blogSecurityProperties;//添加qq创建connection的工厂@Overridepublic void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer,Environment environment) {QQProperties qqConfig = blogSecurityProperties.getQqProperties();QQConnectionFactory qqConnectionFactory = new QQConnectionFactory(qqConfig.getProviderId(), qqConfig.getAppId(), qqConfig.getAppSecret());connectionFactoryConfigurer.addConnectionFactory(qqConnectionFactory);}//获取登陆人@Overridepublic UserIdSource getUserIdSource() {return new AuthenticationNameUserIdSource();}}
7、创建表以及创建操作表的类JdbcUsersConnectionRepository
package com.zzz.blog.social.qq.config;import ...@Configuration
@EnableSocial
@Order(1)
public class SocialConfig extends SocialConfigurerAdapter{@Autowiredprivate DataSource dataSource;//登录之后,直接将QQ的数据保存在数据库@Overridepublic UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());return repository;} //改变拦截的请求//在注册的过程中,拿到了这个SpringSocial中的信息//业务完成之后,把用户的id传给了SpringSocial//打开ConnectController
}
找到socailJDBC表格式,在数据库中执行sql
8、改变拦截的请求
package com.zzz.blog.social.qq.config;import ...public class ZZZSpringSocialConfigurer extends SpringSocialConfigurer{private String filterProcessesUrl;public ZZZSpringSocialConfigurer(String filterProcessesUrl) {this.filterProcessesUrl = filterProcessesUrl;}//将默认的拦截改为qqLogin@Overrideprotected <T> T postProcess(T object) {//获得filterSocialAuthenticationFilter filter = (SocialAuthenticationFilter)super.postProcess(object);//设置字段filter.setFilterProcessesUrl(filterProcessesUrl);return (T) filter;}}
//改变拦截的请求 /auth -> /qqLogin@Beanpublic SpringSocialConfigurer zzzSocialSecurityConfig() {String filterProcessesUrl = blogSecurityProperties.getQqProperties().getFilterProcessesUrl();ZZZSpringSocialConfigurer zzzSpringSocialConfigurer = new ZZZSpringSocialConfigurer(filterProcessesUrl);return zzzSpringSocialConfigurer;}
9、将Social中的配置生效到SpringSecurity中
在SocialConfig类中添加代码
//在注册的过程中,拿到了这个SpringSocial中的信息//业务完成之后,把用户的id传给了SpringSocial@Beanpublic ProviderSignInUtils providerSignInUtils() {return new ProviderSignInUtils(connectionFactoryLocator, getUsersConnectionRepository(connectionFactoryLocator));}//打开ConnectController@Beanpublic ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator,ConnectionRepository connectionRepository) {return new ConnectController(connectionFactoryLocator, connectionRepository);}
添加apply配置socialconfig
package com.zzz.blog.config;import ...//安全配置类
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{//SpringSecurity加密方法返回值@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Autowiredprivate SpringSocialConfigurer zzzSocialSecurityConfig;//做拦截@Overrideprotected void configure(HttpSecurity http) throws Exception {// 请求授权http.formLogin().and().authorizeRequests()//授权放行.antMatchers("/*.html").permitAll()//所有请求.anyRequest()//都需要身份认证.authenticated().and()//43、使用Layer打开select-mood子页面并配置SpringSecurity允许Iframe嵌入页面 .headers().frameOptions().disable().and()//跨站请求伪造的防护.csrf().disable()//添加我们所写的spring social配置.apply(zzzSocialSecurityConfig);}}
10、创建Visitor实体并实现SocialUserDetailsService接口查找Visitor
package com.zzz.blog.domain;import ...@Entity
public class Visitor {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;private String password;private String image;protected Visitor() {}public Visitor(Long id, String username, String password, String image) {super();this.id = id;this.username = username;this.password = password;this.image = image;}//get/set
}
package com.zzz.blog.repository;import ...public interface VisitorRepository extends CrudRepository<Visitor, Long>{}
@Component
public class SocialVisitorServiceImpl implements SocialUserDetailsService{@Autowiredprivate VisitorRepository visitorRepository;@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException {//根据userId查找访客Optional<Visitor> optional = visitorRepository.findById(new Long(userId));Visitor visitor = optional.get();if (visitor == null) {throw new UsernameNotFoundException(userId);}return new SocialUser(visitor.getUsername(), passwordEncoder.encode(visitor.getPassword()), true, true, true, true, AuthorityUtils.commaSeparatedStringToAuthorityList("VISITOR"));}}
11、实现ConnectionSignUp接口添加Visitor
package com.zzz.blog.social.qq.signup;import ...@Component
public class DemoConnectionSignUp implements ConnectionSignUp{@Autowiredprivate VisitorService visitorService;//根据社交用户的信息,创建一个Visitor并返回唯一标识@Overridepublic String execute(Connection<?> connection) {Visitor visitor = new Visitor(null, connection.getDisplayName(), "123456", connection.getImageUrl());visitor = visitorService.saveVisitory(visitor);return visitor.getId().toString();}}
package com.zzz.blog.service;import ...@Service
public interface VisitorService {Visitor saveVisitory(Visitor visitor);}
package com.zzz.blog.service;import ...@Service
public interface VisitorService {Visitor saveVisitory(Visitor visitor);}
package com.zzz.blog.service;import ...@Component
public class VisitorServiceImpl implements VisitorService{@Autowiredprivate VisitorRepository visitorRepository;@Overridepublic Visitor saveVisitory(Visitor visitor) {return visitorRepository.save(visitor);}}
SocialConfig添加setConnectionSignUp执行方法
@Autowiredprivate ConnectionSignUp connectionSignUp;//登录之后,直接将QQ的数据保存在数据库@Overridepublic UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());repository.setConnectionSignUp(connectionSignUp);return repository;}
12、测试QQ登录
application.properties添加代码如下(修改端口):
server.port=80
login.html修改超链接代码如下:
<a href="/qqLogin/callback.do" class="login100-social-item bg2"><i class="fa fa-qq"></i></a>
修改C:\Windows\System32\drivers\etc\hosts文件
127.0.0.1 www.pinzhi365.com
这是别人提供的测试地址。我们也可以到QQ互联官网https://connect.qq.com/上注册用户,创建应用。
其中回调地址的写法:网站地址/拦截器拦截的路径/服务提供商。
创建完修改QQProperties类上的对应配置即可。
测试通过,控制台打印了添加visitor数据的sql。
相关文章:
博客之QQ登录功能(一)
流程图 上图spring social 封装了1-8步需要的工作 1、新建包和书写配置文件 public class QQProperties {//App唯一标 识private String appId "100550231";private String appSecret "69b6ab57b22f3c2fe6a6149274e3295e";//QQ供应商private String…...
Redis多机数据库实现
Redis多机数据库实现 为《Redis设计与实现》笔记 复制 客户端可以使用SLAVEOF命令将指定服务器设置为该服务器的主服务器 127.0.0.1:12345> SLAVEOF 127.0.0.1 6379127.0.0.1:6379将被设置为127.0.0.1:123456的主服务器 旧版复制功能的实现 Redis的复制功能分为同步&a…...
Leangoo领歌 -敏捷任务管理软件,任务管理更轻松更透明
任务管理,简单易懂,就是对任务进行管理。那怎么可以更好进行任务管理呢?怎么样样可以让任务进度可视化,一目了然呢?有效的管理可以让我们事半功倍。 接下来我们看一下如何借助任务管理软件高效的做任务管理。 首先…...
go的iris框架进行本地资源映射到服务端
我这里使用的是HandleDirapi,有其他的请补充 package mainimport ("github.com/kataras/iris/v12" )type Hello struct{Status int json:"status"Message string json:"message" }func main(){app : iris.New()//第一个api:相当于首页app.Get(&q…...
代码随想录day46|139. 单词拆分
139. 单词拆分 class Solution:def wordBreak(self, s: str, wordDict: List[str]) -> bool:dp [False]*(len(s)1)dp[0]Truefor i in range(len(s)1):for j in wordDict:if i>len(j) and (s[i-len(j):i] in wordDict) and dp[i-len(j)]:dp[i] Truereturn dp[len(s)]多…...
MATLAB实现函数拟合
目录 一.理论知识 1.拟合与插值的区别 2.几何意义 3.误差分析 二.操作实现 1.数据准备 2.使用cftool——拟合工具箱 三.函数拟合典例 四.代码扩展 一.理论知识 1.拟合与插值的区别 通俗的说,插值的本质是根据现有离散点的信息创建出更多的离散点…...
vue优化首屏加载时间优化-cdn引入第三方包
前言 为什么要进行首屏加载优化,因为随着我们静态资源和第三方包和代码增加,压缩之后包会越来越大 随着网络的影响,在我们第一输入url请求资源时候,网络阻塞,加载时间长,用户体验不好 仔细观察后就会发现…...
lv4 嵌入式开发-3 标准IO的读写
目录 1 标准I/O – 读写流 2 标准I/O – 按字符输入 3 标准I/O – 按字符输出 4 标准I/O – 思考和练习 5 标准I/O – 按行输入 6 标准I/O – 按行输出 7 标准I/O – 思考和练习 1 标准I/O – 读写流 流支持不同的读写方式: 读写一个字符:fgetc()/fputc()一…...
iOS UIDevice设备信息
识别设备和操作系统 //获得共享设备实例 open class var current: UIDevice { get }//识别设备的名称 open var name: String { get } // e.g. "My iPhone"//设备类型 open var model: String { get } // e.g. "iPhone", "iPod touch"//本地化设…...
SLAM ORB-SLAM2(2)编译安装
SLAM ORB-SLAM2(2)编译安装 1. 软件包依赖安装2. 依赖安装2.1. Eigen2.2. Pangolin2.3. OpenCV3. ORB-SLAM23.1. 源码下载3.2. 文件修改3.3. 扩大交换空间3.4. 编译1. 软件包依赖安装 以一个纯净的ubuntu20.04桌面版为例 1.首先设置软件源为清华源 2.安装必要依赖 sudo ap…...
第11节-PhotoShop基础课程-索套工具
文章目录 前言1.索套工具 选中后按Ctrl 可以移动2.加,减,交叉 shift alt 2.多边形索套工具 手动首尾相连 或者双击空地1.单击绘制直线选区2.双击结束绘制3.加,减,交叉4. delete可以删除节点 3.磁性索套工具1.沿着边缘自动吸附2.可…...
Json字符串内容比较-超实用版
背景 之前有类似接口diff对比,数据对比的测试需求,涉及到json格式的数据对比,调研了几个大神们分享的代码,选了一个最符合自己需求的研究了下。 说明 这个对比方法,支持JsonObject和JsonArray类型的数据对比&#x…...
Redis系列之客户端Redisson
概述 官方推荐的客户端,支持Redis单实例、Redis哨兵、Redis Cluster、Redis master-slave等各种部署架构。 GitHub, 功能: 分布式锁 分布式锁 使用Redisson提供的分布式锁的一个最常见场景,应用部署为多个节点,然…...
centos 端口被占用的快速排查方式
问题笔记 centos 端口被占用的快速排查方式 centos 端口被占用的快速排查方式 这里说一个我刚刚遇到的问题,解决步骤用来记录,方便以后自己查询。 nginx配置完index.html测试文件,发现一直显示的404页面。 我跑到服务器上想重启一下nginx …...
Java“牵手”淘宝商品列表数据,关键词搜索淘宝商品数据接口,淘宝API申请指南
淘宝商城是一个网上购物平台,售卖各类商品,包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取淘宝商品列表和商品详情页面数据,您可以通过开放平台的接口或者直接访问淘宝商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…...
OpenEuler/CentOS如何修改密码策略
密码策略文件: /etc/pam.d/system-auth 找到行: password requisite pam_pwquality.so try_first_pass local_users_only 为保证安全,可以将这一行注释掉,添加一行,最后结果如下: #password …...
# Spring MVC与RESTful API:如何设计高效的Web接口
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
Scrum敏捷模式的优势点、实践经验及适用企业
Scrum敏捷模式是一种灵活、适应性强的开发方法,其核心理念是以短周期、高频率的方式进行项目开发,确保团队能够快速响应变化。 Scrum包含三个角色:产品负责人(Product Owner)、Scrum Master和开发团队(Tea…...
【C++杂货铺】探索stack和queue的底层实现
文章目录 一、stack的介绍和使用1.1 stack的介绍1.2 stack的使用1.2.1 最小栈1.2.2 栈的压入、弹出序列1.2.3 逆波兰表达式求值1.2.4 用栈实现队列 二、queue的介绍和使用2.1 queue的介绍2.2 queue的使用2.2.1 二叉树的层序遍历 三、模拟实现3.1 stack模拟实现3.2 queue模拟实现…...
“系统的UI”——SystemUI
SystemUI的实现 以StatusBar为例,来分析下Android系统具体是如何实现它们的。 相关代码分为两部分,即: Service部分 代码路径:frameworks/base/services/java/com/android/server。 应用部分 代码路径:frameworks…...
类和对象:构造函数,析构函数与拷贝构造函数
1.类的6个默认成员函数 如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器…...
谈谈Java的特点和优点以及选择Java的原因
 如果面试官问你:请你说说Java的特点和优点,为什么要选择Java?你该怎么回答? 得分点 Java的特点 Java与C的区别 Java的优点标准回答 Java是一门非常纯粹的面向对象的编程语言,它吸收了C语言的各种优…...
消息队列(MQ)面试
目录 讲一讲MQ 面试官: 在你之前的项目中,你是否使用过消息队列(MQ)?能详细介绍一下你在项目中如何使用MQ吗? 在用户和用户之间的多对多聊天通信中如何使用,请具体来讲一下。 那你可以讲一下消息的确认…...
无涯教程-JavaScript - COUPNUM函数
描述 COUPNUM函数返回结算日和到期日之间应付的息票数量,四舍五入到最接近的整数。 语法 COUPNUM (settlement, maturity, frequency, [basis])争论 Argument描述Required/OptionalSettlement 证券的结算日期。 证券结算日期是指在发行日期之后将证券交易给买方的日期。 Re…...
上海控安携汽车网络安全新研产品出席AUTOSEMO“恒以致远,共创共赢”主题研讨会
8月31日,AUTOSEMO“恒以致远,共创共赢”主题研讨会在天津成功召开。本次大会由中国汽车工业协会软件分会中国汽车基础软件生态标委会(简称:AUTOSEMO)与天津市西青区人民政府联合主办。现场汇聚了100余位来自产学研政企…...
小程序引入高德/百度地图坐标系详解
小程序引入高德/百度地图坐标系详解 官网最近更新时间:最后更新时间: 2021年08月17日 高德官网之在原生小程序中使用的常见问题 链接 目前在小程序中使用 高德地图只支持以下功能 :地址描述、POI和实时天气数据 小结:从高德api中获取数…...
英诺森 “供应链智能数据平台”荣获“科技进步奖”
近日,2023年中国物流与采购联合会科学技术奖正式公布,该奖项经国家科技部批准,在国家科学技术奖励工作办公室登记备案,是我国物流行业最具影响力的奖项之一。 英诺森联合客户申报的科技项目“英诺森供应链智能数据平台”…...
kafka 3.5 主题分区的Follower创建Fetcher线程从Leader拉取数据源码
Kakfa集群有主题,每一个主题下又有很多分区,为了保证防止丢失数据,在分区下分Leader副本和Follower副本,而kafka的某个分区的Leader和Follower数据如何同步呢?下面就是讲解的这个 首先要知道,Follower的数据…...
Golang web 项目中实现自定义 recovery 中间件
为什么需要实现自定义 recovery 中间件? 在 Golang 的 Web 项目中,自定义 recovery 中间件是一种常见的做法,用于捕获并处理应用程序的运行时错误,以避免整个应用程序崩溃并返回对应格式的响应数据。 很多三方 web 框架…...
Direct3D绘制旋转立方体例程
初始化文件见Direct3D的初始化_direct3dcreate9_寂寂寂寂寂蝶丶的博客-CSDN博客 D3DPractice.cpp #include <windows.h> #include "d3dUtility.h" #include <d3dx9math.h>IDirect3DDevice9* Device NULL; IDirect3DVertexBuffer9* VB NULL; IDirect3…...
濮阳网站建设883664/吸引客人的产品宣传句子
Gauge 量规 显示范围内的值的视图。 struct Gauge<Label, CurrentValueLabel, BoundsLabel, MarkedValueLabels> where Label : View, CurrentValueLabel : View, BoundsLabel : View, MarkedValueLabels : View使用教程 量规表明了当前水平与最终值差距 目前官方没有给出…...
中央农村工作会议2023原文/成都网站快速排名优化
范围、利益相关者和目标 为我省科技创新团队提供平台 为省和国家相关部门提供相关数据以及提高管理效率 促进我省创信事业的发展 利益相关者分析 院长 希望项目可以简化员工的工作方式,优化管理,促进我省的科技创新发展 政府工作人员 希望得到领导的认可…...
wordpress 添加文章/推广app拿返佣的平台
说起沟通科技,也许一般人会觉得很陌生,毕竟这家成立于2000年的高新企业,前几年一直比较沉寂,在默默无闻地做着前期的铺垫工作,但对于应用软件和远程接入这些相关的行业而言,从2005年开始,沟通科…...
铜仁市网站建设情况/网络营销的模式有哪些?
【题解】 我们可以发现每次修改之后叶子结点到根的路径最多分为两段:一段白色或者黑色,上面接另一段灰色的。二分倍增找到分界点,然后更新答案即可。 check的时候只需要判断当前节点对应的叶子结点的区间是否全部为同一种颜色,用树…...
wordpress电影影视主题/独立站seo推广
英文对话是要加引号的,而且是双引号和单引号的使用方法与中文一样的用法,接下来小编在这里给大家带来,我们一起来看看吧!引号分单引号(singlequotationmarks)和双引号(doublequotationmarks)。单引号只用在一个直接引语中所含有的另一个直接引语上。1、表…...
我是一条龙怎么停更了/seo排名赚
来源:33IQ 1,pink 2,化学老师 3,编程师 4,生物老师 初一看,AC!仔细一看,不是搞编程的,是生物老师。。。 然后一想,A不是腺嘌呤吗,那就是林原咯&a…...