首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

菜鸟学习shiro之用数据库作为Realm的认证源实现登录,角色身份的判定和权限验证3

Maven的的依赖和第一篇是一样的副本直接用 上两篇讲的无论是内部类的封装领域还是配置文件的认证源,这篇开始讲最关心的数据库作为境界的认证源 这里使用的是四郎给我们提供的另一个内置的类JdbcRealm这个是连接数据库的一个内部类,话不多说了,具体的代码如下: import com.alibaba.druid.pool.DruidDataSource; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.realm.jdbc.JdbcRealm; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.subject.Subject; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class JdbcRealmTest { DruidDataSource druidDataSource = new DruidDataSource(); { druidDataSource.setUrl("jdbc:mysql://localhost:3306/test"); druidDataSource.setUsername("root"); druidDataSource.setPassword("root"); } @Test public void testAuthenticationTest() { // 设置内置的jdbc JdbcRealm jdbcRealm = new JdbcRealm(); jdbcRealm.setDataSource(druidDataSource); // 权限数据的开关 jdbcRealm.setPermissionsLookupEnabled(true); String sql = "select password from test_user where username = ?"; jdbcRealm.setAuthenticationQuery(sql); String roleSql = "select role_name from test_user_role where user_name = ?"; jdbcRealm.setUserRolesQuery(roleSql); // 1.构建SecurityManager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(jdbcRealm); // 2.主体提交认证请求 SecurityUtils.setSecurityManager(defaultSecurityManager); Subject subject = SecurityUtils.getSubject(); // 这个是需要认证的信息 UsernamePasswordToken token = new UsernamePasswordToken("xiaoming","654321"); subject.login(token); System.out.println("isAuthenticated="+subject.isAuthenticated()); //subject.logout(); /*subject.checkRole("admin"); subject.checkPermission("user:select");*/ subject.checkRole("user"); } } 具体的数据库文件: / * Navicat Premium数据传输 源服务器:根源服务器类型:MySQL的的源服务器版本:50722 源主机:本地主机:3306 源架构:测试 目标服务器类型:MySQL的的目标服务器版本:50722 文件编码:65001 日期:28/07/2018 08:18:03 * / SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; - ---------------------------- - roles_permissions的表结构- ------------ --- ------------- DROP TABLE IF EXISTS`coole_permissions`; CREATE TABLE`colces_permissions`( `id` int(11)NOT NULL AUTO_INCREMENT, `role_name` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, `permission` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, PRIMARY KEY(`id`)使用BTREE )ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic; - ---------------------------- - roles_permissions的记录- ------------- --- ------------ 插入`roles_permissions` VALUES(1,'admin','user:select'); SET FOREIGN_KEY_CHECKS = 1; -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------ / * Navicat Premium数据传输 源服务器:根源服务器类型:MySQL的的源服务器版本:50722 源主机:本地主机:3306 源架构:测试 目标服务器类型:MySQL的的目标服务器版本:50722 文件编码:65001 日期:28/07/2018 08:18:17 * / SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; - ---------------------------- - test_user的表结构- ------------ --- ------------- DROP TABLE IF EXISTS`test_user`; CREATE TABLE`test_user`( `username` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, `password` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL )ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT =动态; - ---------------------------- - test_user的记录- ------------- --- ------------ 插入`test_user` VALUES('xiaoming','654321'); SET FOREIGN_KEY_CHECKS = 1; -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------------- / * Navicat Premium数据传输 源服务器:根源服务器类型:MySQL的的源服务器版本:50722 源主机:本地主机:3306 源架构:测试 目标服务器类型:MySQL的的目标服务器版本:50722 文件编码:65001 日期:28/07/2018 08:18:26 * / SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; - ---------------------------- - test_user_role的表结构- ------------ --- ------------- DROP TABLE IF EXISTS`test_user_role`; CREATE TABLE`test_user_role`( `user_name` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, `role_name` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL )ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT =动态; - ---------------------------- - test_user_role的记录 - ------------- --- ------------ 插入`test_user_role` VALUES('xiaoming','user'); SET FOREIGN_KEY_CHECKS = 1; -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ---------------- / * Navicat Premium数据传输 源服务器:根源 服务器类型:MySQL的 源服务器版本:50722 源主机:本地主机:3306 源架构:测试 目标服务器类型:MySQL的 目标服务器版本:50722 文件编码:65001 日期:28/07/2018 08:18:32 * / SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; - ---------------------------- - user_roles的表结构 - ------------ ---------------- DROP TABLE IF EXISTS`user_roles`; CREATE TABLE`user_roles` (`id` int(11)NOT NULL AUTO_INCREMENT, `username` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, `role_name` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, PRIMARY KEY(`id`)使用BTREE )ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic; - ---------------------------- - user_roles的记录 - ------------- --------------- INSERT INTO`user_roles` VALUES(1,'Mark','admin'); SET FOREIGN_KEY_CHECKS = 1; -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------ / * Navicat Premium数据传输 源服务器:根源 服务器类型:MySQL 源服务器版本:50722 源主机:localhost:3306 源架构:测试 目标服务器类型:MySQL 目标服务器版本:50722 文件编码:65001 日期:28/07/2018 08:18:41 * / SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; - ---------------------------- - 用户表结构- ------------ ---- ------------ DROP TABLE IF EXISTS`users`; CREATE TABLE`user`(`id` int(11)NOT NULL AUTO_INCREMENT, `username` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, `password` varchar(255)CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, PRIMARY KEY(`id`)使用BTREE )ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic; - ---------------------------- - 用户记录- ------------- ---- ----------- 插入`users` VALUES(1,'Mark','123456'); SET FOREIGN_KEY_CHECKS = 1; 执行流程和前两篇一样。

优秀的个人博客,低调大师

(7)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- 利用Polly+AOP+依赖注入封装的降级框架

创建简单的熔断降级框架 要达到的目标是:参与降级的方法参数要一样,当HelloAsync执行出错的时候执行HelloFallBackAsync方法。 public class Person { [HystrixCommand("HelloFallBackAsync")] public virtual async Task<string> HelloAsync(string name) { Console.WriteLine("hello"+name); return "ok"; } public async Task<string> HelloFallBackAsync(string name) { Console.WriteLine("执行失败"+name); return "fail"; }} 1、编写 HystrixCommandAttribute using AspectCore.DynamicProxy; using System; using System.Threading.Tasks; namespace hystrixtest1 { //限制这个特性只能标注到方法上 [AttributeUsage(AttributeTargets.Method)] public class HystrixCommandAttribute : AbstractInterceptorAttribute { public HystrixCommandAttribute(string fallBackMethod) { this.FallBackMethod = fallBackMethod; } public string FallBackMethod { get; set; } public override async Task Invoke(AspectContext context, AspectDelegate next) { try { await next(context);//执行被拦截的方法 } catch (Exception ex) { //context.ServiceMethod被拦截的方法。context.ServiceMethod.DeclaringType被拦截方法所在的类 //context.Implementation实际执行的对象p //context.Parameters方法参数值 //如果执行失败,则执行FallBackMethod //调用降级方法 //1.调用降级的方法(根据对象获取类,从类获取方法) var fallBackMethod = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod); //2.调用降级的方法 Object fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters); //3.把降级方法的返回值返回 context.ReturnValue = fallBackResult; } } } } 2、编写类 public class Person//需要public类 { [HystrixCommand(nameof(HelloFallBackAsync))] public virtual async Task<string> HelloAsync(string name)//需要是虚方法 { Console.WriteLine("hello"+name); String s = null; // s.ToString(); return "ok"; } public async Task<string> HelloFallBackAsync(string name) { Console.WriteLine("执行失败"+name); return "fail"; } [HystrixCommand(nameof(AddFall))] public virtual int Add(int i,int j) { String s = null; //s.ToArray(); return i + j; } public int AddFall(int i, int j) { return 0; } } 3、创建代理对象 ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder(); using (IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build()) { Person p = proxyGenerator.CreateClassProxy<Person>(); Console.WriteLine(p.HelloAsync("yzk").Result); Console.WriteLine(p.Add(1, 2)); } 上面的代码还支持多次降级,方法上标注[HystrixCommand]并且virtual即可: public class Person//需要public类 { [HystrixCommand(nameof(Hello1FallBackAsync))] public virtual async Task<string> HelloAsync(string name)//需要是虚方法 { Console.WriteLine("hello" + name); String s = null; s.ToString(); return "ok"; } [HystrixCommand(nameof(Hello2FallBackAsync))] public virtual async Task<string> Hello1FallBackAsync(string name) { Console.WriteLine("Hello降级1" + name); String s = null; s.ToString(); return "fail_1"; } public virtual async Task<string> Hello2FallBackAsync(string name) { Console.WriteLine("Hello降级2" + name); return "fail_2"; } [HystrixCommand(nameof(AddFall))] public virtual int Add(int i, int j) { String s = null; s.ToString(); return i + j; } public int AddFall(int i, int j) { return 0; } } 细化框架 上面明白了了原理,然后直接展示写好的更复杂的HystrixCommandAttribute,讲解代码。 这是杨中科老师维护的开源项目 github最新地址 https://github.com/yangzhongke/RuPeng.HystrixCore Nuget地址:https://www.nuget.org/packages/RuPeng.HystrixCore 重试:MaxRetryTimes表示最多重试几次,如果为0则不重试,RetryIntervalMilliseconds 表示重试间隔的毫秒数; 熔断:EnableCircuitBreaker是否启用熔断,ExceptionsAllowedBeforeBreaking表示熔断前出现允许错误几次,MillisecondsOfBreak表示熔断多长时间(毫秒); 超时:TimeOutMilliseconds执行超过多少毫秒则认为超时(0表示不检测超时) 缓存:CacheTTLMilliseconds 缓存多少毫秒(0 表示不缓存),用“类名+方法名+所有参数值ToString拼接”做缓存Key(唯一的要求就是参数的类型ToString对于不同对象一定要不一样)。 用到了缓存组件:Install-Package Microsoft.Extensions.Caching.Memory using System; using AspectCore.DynamicProxy; using System.Threading.Tasks; using Polly; namespace RuPeng.HystrixCore { [AttributeUsage(AttributeTargets.Method)] public class HystrixCommandAttribute : AbstractInterceptorAttribute { /// <summary> /// 最多重试几次,如果为0则不重试 /// </summary> public int MaxRetryTimes { get; set; } = 0; /// <summary> /// 重试间隔的毫秒数 /// </summary> public int RetryIntervalMilliseconds { get; set; } = 100; /// <summary> /// 是否启用熔断 /// </summary> public bool EnableCircuitBreaker { get; set; } = false; /// <summary> /// 熔断前出现允许错误几次 /// </summary> public int ExceptionsAllowedBeforeBreaking { get; set; } = 3; /// <summary> /// 熔断多长时间(毫秒) /// </summary> public int MillisecondsOfBreak { get; set; } = 1000; /// <summary> /// 执行超过多少毫秒则认为超时(0表示不检测超时) /// </summary> public int TimeOutMilliseconds { get; set; } = 0; /// <summary> /// 缓存多少毫秒(0表示不缓存),用“类名+方法名+所有参数ToString拼接”做缓存Key /// </summary> public int CacheTTLMilliseconds { get; set; } = 0; //由于CircuitBreaker要求同一段代码必须共享同一个Policy对象。 //而方法上标注的Attribute 对于这个方法来讲就是唯一的对象,一个方法对应一个方法上标注的Attribute对象。 //一般我们熔断控制是针对一个方法,一个方法无论是通过几个 Person 对象调用,无论是谁调用,只要全局出现ExceptionsAllowedBeforeBreaking次错误,就会熔断,这是框架的实现,你如果认为不合理,自己改去。 //我们在Attribute上声明一个Policy的成员变量,这样一个方法就对应一个Policy对象。 private Policy policy; private static readonly Microsoft.Extensions.Caching.Memory.IMemoryCache memoryCache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions()); /// <summary> /// /// </summary> /// <param name="fallBackMethod">降级的方法名</param> public HystrixCommandAttribute(string fallBackMethod) { this.FallBackMethod = fallBackMethod; } public string FallBackMethod { get; set; } public override async Task Invoke(AspectContext context, AspectDelegate next) { //一个HystrixCommand中保持一个policy对象即可 //其实主要是CircuitBreaker要求对于同一段代码要共享一个policy对象 //根据反射原理,同一个方法就对应一个HystrixCommandAttribute,无论几次调用, //而不同方法对应不同的HystrixCommandAttribute对象,天然的一个policy对象共享 //因为同一个方法共享一个policy,因此这个CircuitBreaker是针对所有请求的。 //Attribute也不会在运行时再去改变属性的值,共享同一个policy对象也没问题 lock (this)//因为Invoke可能是并发调用,因此要确保policy赋值的线程安全 { if (policy == null) { policy = Policy.NoOpAsync();//创建一个空的Policy if (EnableCircuitBreaker) //先保证熔断 { policy = policy.WrapAsync(Policy.Handle<Exception>().CircuitBreakerAsync(ExceptionsAllowedBeforeBreaking, TimeSpan.FromMilliseconds(MillisecondsOfBreak))); } if (TimeOutMilliseconds > 0) //控制是否超时 { policy = policy.WrapAsync(Policy.TimeoutAsync(() => TimeSpan.FromMilliseconds(TimeOutMilliseconds), Polly.Timeout.TimeoutStrategy.Pessimistic)); } if (MaxRetryTimes > 0) //如果出错等待MaxRetryTimes时间在执行 { policy = policy.WrapAsync(Policy.Handle<Exception>().WaitAndRetryAsync(MaxRetryTimes, i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds))); } Policy policyFallBack = Policy .Handle<Exception>() //出错了报错 如果出错就尝试调用降级方法 .FallbackAsync(async (ctx, t) => { //这里拿到的就是ExecuteAsync(ctx => next(context), pollyCtx);这里传的 pollyCtx AspectContext aspectContext = (AspectContext)ctx["aspectContext"]; var fallBackMethod = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod); Object fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters); //不能如下这样,因为这是闭包相关,如果这样写第二次调用Invoke的时候context指向的 //还是第一次的对象,所以要通过Polly的上下文来传递AspectContext //context.ReturnValue = fallBackResult; aspectContext.ReturnValue = fallBackResult; }, async (ex, t) => { }); policy = policyFallBack.WrapAsync(policy); } } //把本地调用的AspectContext传递给Polly,主要给FallbackAsync中使用,避免闭包的坑 Context pollyCtx = new Context();//Context是polly中通过Execute给FallBack、Execute等回调方法传上下文对象使用的 pollyCtx["aspectContext"] = context;//context是aspectCore的上下文 //Install-Package Microsoft.Extensions.Caching.Memory if (CacheTTLMilliseconds > 0) { //用类名+方法名+参数的下划线连接起来作为缓存key string cacheKey = "HystrixMethodCacheManager_Key_" + context.ServiceMethod.DeclaringType + "." + context.ServiceMethod + string.Join("_", context.Parameters); //尝试去缓存中获取。如果找到了,则直接用缓存中的值做返回值 if (memoryCache.TryGetValue(cacheKey, out var cacheValue)) { context.ReturnValue = cacheValue; } else { //如果缓存中没有,则执行实际被拦截的方法 await policy.ExecuteAsync(ctx => next(context), pollyCtx); //存入缓存中 using (var cacheEntry = memoryCache.CreateEntry(cacheKey)) { cacheEntry.Value = context.ReturnValue;//返回值放入缓存 cacheEntry.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMilliseconds(CacheTTLMilliseconds); } } } else//如果没有启用缓存,就直接执行业务方法 { await policy.ExecuteAsync(ctx => next(context), pollyCtx); } } } } 框架不是万能的,不用过度框架,过度框架带来的复杂度陡增,从人人喜欢变成人人恐惧。 结合asp.net core依赖注入 在asp.net core项目中,可以借助于asp.net core的依赖注入,简化代理类对象的注入,不用再自己调用ProxyGeneratorBuilder 进行代理类对象的注入了。 Install-Package AspectCore.Extensions.DependencyInjection 修改Startup.cs的ConfigureServices方法,把返回值从void改为IServiceProvider using AspectCore.Extensions.DependencyInjection; public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddSingleton<Person>(); return services.BuildAspectCoreServiceProvider(); } 其 中 services.AddSingleton<Person>(); 表 示 把Person注 入 。 BuildAspectCoreServiceProvider是让aspectcore接管注入。 在Controller中就可以通过构造函数进行依赖注入了: public class ValuesController : Controller { private Person p; public ValuesController(Person p) { this.p = p; } } 通过反射扫描所有Service类,只要类中有标记了CustomInterceptorAttribute的方法都算作服务实现类。为了避免一下子扫描所有类,所以 RegisterServices 还是手动指定从哪个程序集中加载。 public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc(); RegisterServices(this.GetType().Assembly, services); return services.BuildAspectCoreServiceProvider(); } private static void RegisterServices(Assembly asm, IServiceCollection services) { //遍历程序集中的所有public类型 foreach (Type type in asm.GetExportedTypes()) { //判断类中是否有标注了CustomInterceptorAttribute的方法 bool hasCustomInterceptorAttr = type.GetMethods().Any(m => m.GetCustomAttribute(typeof(CustomInterceptorAttribute)) != null); if (hasCustomInterceptorAttr) { services.AddSingleton(type); } } } 注:此文章是我看杨中科老师的.Net Core微服务第二版和.Net Core微服务第二版课件整理出来的 现在的努力只是为了更好的将来,将来你一定不会后悔你现在的努力。一起加油吧!!! C#/.NetCore技术交流群:608188505欢迎加群交流 如果您认为这篇文章还不错或者有所收获,您可以点击右下角的【推荐】按钮精神支持,因为这种支持是我继续写作,分享的最大动力!

优秀的个人博客,低调大师

【案例学习】传统应用程序上云的经典案例,欧洲两家领军企业的落地实践

(一)法国兴业银行:有状态的传统应用程序也可以容器化 基本背景 法国兴业银行(Société Générale)是一家拥有153年历史的法国跨国银行,这家银行坚信技术和创新是丰富客户体验和推动经济发展的关键因素。几年前,该银行启动了一个项目,该项目定义了它们的下一代应用程序平台,就是在2020年前将其应用程序的80%上传至云端运行。法国兴业银行选择了Docker企业版(Docker EE)作为其应用程序的基础平台,并在15个月前开始与之合作。今年在DockerCon欧洲大会上,DevOps架构师Stephan Dechoux 和中间件专家Thomas Boussardon分享了他们将Docker企业版(Docker EE)集成到法国兴业银行IT系统的经历。 技术概况 法国兴业银行拥有多种应用程序组合,其中包括许多不同类型的应用程序,如传统

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 68)——Cocoa Touch设计模式及应用之响应者链与触摸事件

应用与用户进行交互,依赖于各种各样的事件。事件响应者对象是可以响应事件并对其进行处理的对象,响应者链是由一系列链接在一起的响应者组成的。响应者链在事件处理中是非常重要的,响应者链可以把用户事件路由给正确的对象。 响应者对象与响应链 UIResponder是所有响应者对象的基类,它不仅为事件处理,而且也为常见的响应者行为定义编程接口。UIApplication、UIView(及其子类,包括UIWindow)和UIViewController(及其子类)都直接或间接地继承自UIResponder类。 第一响应者是应用程序中当前负责接收触摸事件的响应者对象(通常是一个UIView对象)。UIWindow对象以消息的形式将事件发送给第一响应者,使其有机会首先处理事件。如果第一响应者没有进行处理,系统就将事件(通过消息)传递给响应者链中的下一个响应者,看看它是否可以进行处理。 响应者链是一系列链接在一起的响应者对象,它允许响应者对象将处理事件的责任传递给其他更高级别的对象。随着应用程序寻找能够处理事件的对象,事件就在响应者链中向上传递。响应者链由一系列“下一个响应者”组成。 1.第一响应者将事件传递给它的视图控制器(如果有的话),然后是它的父视图。 2.类似地,视图层次中的每个后续视图都首先传递给它的视图控制器(如果有的话),然后是它的父视图。 3.最上层的容器视图将事件传递给UIWindow对象。 4.UIWindow对象将事件传递给UIApplication单例对象。 触摸事件 触摸(UITouch)对象表示屏幕上的一个触摸事件,访问触摸是通过UIEvent对象传递给事件响应者对象的。触摸对象有时间和空间两方面。 1.时间方面 时间方面信息称为阶段(phase),表示触摸是否刚刚开始、是否正在移动或处于静止状态,以及何时结束,也就是手指何时从屏幕抬起。 在给定的触摸阶段中,如果发生新的触摸动作或已有的触摸动作发生变化,则应用程序就会发送这些消息。 当一个或多个手指触碰屏幕时,发送touchesBegan:withEvent:消息。 当一个或多个手指在屏幕上移动时,发送touchesMoved:withEvent:消息。 当一个或多个手指离开屏幕时,发送touchesEnded:withEvent:消息。 2.空间方面 触摸点对象还包括当前在视图或窗口中的位置信息,以及之前的位置信息(如果有的话)。下面的方法是可以获得触摸点所在窗口或视图中的位置。 func locationInView(_ view:UIView?) -> CGPoint 获得前一个触摸点所在窗口或视图中的位置信息: func previousLocationInView(_view: UIView?) -> CGPoint 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1749103,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 71)——Swift与C/C++混合编程之数据类型映射

如果引入必要的头文件,在Objective-C语言中可以使用C数据类型。而在Swift语言中是不能直接使用C数据类型,苹果公司为Swift语言提供与C语言相对应数据类型。这些类型主要包括:C语言基本数据类型和指针类型。 C语言基本数据类型 如表所述是Swift数据类型与C语言基本数据类型对应关系表。 Swift语言中的这些数据类型与Swift原生的数据类型一样都,本质上都是结构体类型。我们可以他们的构造函数创建这些数据类型的实例。示例代码如下: 1 2 3 4 5 6 7 8 9 10 varintSwift= 80 //int varintNumber=NSNumber( int :CInt(intSwift)) //unsignedchar varunsignedCharNumber=NSNumber(unsignedChar:CUnsignedChar(intSwift)) //unsignedint varunsignedIntNumber=NSNumber(unsignedInt:CUnsignedInt(intSwift)) 变量intSwift所存储80是Int类型。代码中CInt(intSwift)是实例化CInt类型,它实现了将Int类型转化为C语言int类型,在Swift中使用CInt表示。 代码中CUnsignedChar(intSwift)是将Int类型转化为C语言unsigned char类型,在Swift中使用CUnsignedChar表示。 代码中的CUnsignedInt(intSwift))是将Int类型转化为C语言unsigned int类型,在Swift中使用CUnsignedInt表示。 C语言指针类型 如表所述是Swift数据类型与C语言指针数据类型对应关系表。 从表可见针对C语言多样的指针形式,Swift主要通过提供了三种不安全的泛型指针类型:UnsafePointer<T>、UnsafeMutablePointer<T>和AutoreleasingUnsafeMutablePointer<T>。T是泛型占位符,表示不同的数据类型。另外,还有COpaquePointer类型是Swift中无法表示的C指针类型。 下面我们分别介绍一下。 1.UnsafePointer<T> UnsafePointer<T>是一个比较常用的常量指针类型,这种指针对象需要程序员自己手动管理内存,即需要自己申请和释放内存。它一般是由其他的指针创建。它的主要的构造函数有: init(_ other: COpaquePointer)。通过COpaquePointer类型指针创建。 init<U>(_ from: UnsafeMutablePointer<U>)。通过UnsafeMutablePointer类型指针创建。 init<U>(_ from: UnsafePointer<U>)。通过UnsafePointer类型指针创建。 UnsafePointer<T>主要的属性: memory。只读属性,它能够访问指针指向的内容。 UnsafePointer<T>主要的方法: successor() -> UnsafePointer<T>。获得指针指向的下一个内存地址的内容。 predecessor() -> UnsafePointer<T>。获得指针指向的上一个内存地址的内容。 2. UnsafeMutablePointer<T> UnsafeMutablePointer<T>是一个比较常用的可变指针类型,这种指针对象需要程序员自己手动管理内存,自己负责申请和释放内存。可变指针可以由其他的指针创建,也可以可变指针通过alloc(_:)方法申请内存空间,再调用initialize(_:)方法初始化指针指向数值。当指针对象释放时候需要调用destroy()方法销毁指针指向对象,它是initialize(_:)方法的反向操作,他们两个方法在代码中应该成对出现的。最后还要调用dealloc(_:)方法释放指针指向的内存空间,它是alloc(_:)方法的反向操作,这两个方法在代码中也应该成对出现。 3. AutoreleasingUnsafeMutablePointer<T> AutoreleasingUnsafeMutablePointer<T>被称为自动释放指针,在方法或函数中声明为该类型的参数,是输入输出类型的,在调用方法或函数过程中,参数先首先被拷贝到一个无所有权的缓冲区,在方法或函数内使用的这个缓冲区,当方法或函数返回时,缓冲区数据重新写回到参数。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1749110,如需转载请自行联系原作者

优秀的个人博客,低调大师

Hadoop概念学习系列之再谈hadoop集群里的本地模式、伪分布模式和全分布模式(三十七)

能看懂博主我此博文,相信你已经有了一定基础了。 对于本地模式、伪分布模式和全分布模式的概念,这里,我不多赘述。太多资料和博客,随便在网上一搜就好。 比如《hadoop实战 第二版》陆嘉恒老师等。 我这里呢,是再次挖掘深入。 我们知道,如伪分布模式或全分布式模式,里有着很多的java进程(这个,可用jps查看)。有过动手试验的都知道, 这两种模式,速度明显比本地模式要快,为什么呢? 答:原因在于,本地独立模式将每个单独任务执行的信息都打印在屏幕上,而在伪分布模式和全分布式模式下,这些信息只被写入在运行主机的日志文件中。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/6092384.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

用户登录
用户注册