首页 文章 精选 留言 我的

精选列表

搜索[路径追踪],共10008篇文章
优秀的个人博客,低调大师

Android平台的10款开源任务管理和时间追踪应用

现代生活需求的压力有时候会把人压倒。即使是一个十分有组织能力的人或许也会需要数字工具来跟踪个人和专业的会议以及最后期限。 如果你参加了今年的 All Things Open,可能已经看到了 Opensource.com 的 Jason Baker 和 Jen Wike Huger 谈论了关于开源生产力的黑客,这是一个关于开源工具和提高生产力入门的一个很好的开始。 要加入到 Jason 和 Jen 开始的对话,我想与你分享 10 个 Android 手机上的应用程序,它们可以帮助你把时间组织起来,记录你在任务上花费的时间,并确保你不会错过最后的期限。所有的应用程序都是开源的,可以从 F-Droid 存储库中获取,所以大家不妨尝试一下,然后看看它们是否满足你的需求。 Mirakel Mirakel 是一个具有现代用户界面的任务管理应用程序,并支持在这样的程序中可能需要的每种格式。在 Mirakel 的基本层面,它支持多个列表,这被称为 “元列表”。 创建单个任务会有很多选项,包括截止时间、提醒、进度跟踪、标签、注释、子任务和文件附件,所有这些都包括任务条目的一部分。 在项目的 F-Droid 页面上,与 Taskwarrior 和 CalDAV 的同步主要被列为关键功能,但在应用程序本身,同步功能被标记为 buggy,所以如果同步对你很重要,请注意,这种体验可能无法正常工作。 OpenTasks OpenTasks 和这个列表中的其他许多条目一样,是一个很好的任务管理工具,用于通过各种设置创建单独的任务。它在创建任务时支持各种各样的字段,范围从诸如名称和描述的基本事物到更复杂的项目,例如选择任务是私有的,公共的还是机密的。 设置 OpenTasks 与其他替代方案的最大不同是它在应用程序的主屏幕上使用标签。这些标签能让你快速查看即将到期的任务、即将开始的任务、按优先级排序的任务以及按当前完成进度排序的任务。许多其他的应用程序也能完成这样的工作,但使用 OpenTasks 可以快速访问这些列表。 Pomodoro Tasks 如果你是番茄工作法的粉丝,又或者只是想尝试一下,Pomodoro Tasks 正是为你而生的。在 F-Droid 存储库中的两个 Pomodoro 应用程序中,它是具有更好的用户体验和设计的那个。但是,它仍然是一个较旧的应用程序,所以其设计与其他许多现代 Android 应用程序相比,是有点过时。尽管如此,它运行良好,允许用户将他们的手机变成一个番茄钟计时器。 Simple Deadlines Simple Deadlines 关注任务的完成。可用于创建任务的字段是非常简单的,只有 “标签”,“组” 和截止日期。这个应用程序的一个主要优势是在概览界面上明确的显示截止日期倒计时。此倒计时显示项目到期的天数,剩余天数显示在随着截止时间变近而更改颜色的框中。根据截止日期有多远,今天或明天到期的任务为红色,即将到期的任务为橙色,黄色,绿色或蓝色。 Simpletask Cloudless 对于更多以文本为中心的用户,Simpletask Cloudless 使用 todo.txt 格式创建条目。列表是通过用 @符号为任务中的单词加前缀而创建的,并且通过使用 + 符号作为前缀来创建标签。到期日期设置为使用 due: YYYY-MM-DD。因为底层数据存储在一个简单的文本文件中,与其他 todo.txt 兼容的应用程序共享任务列表是很容易的。 Simply Do Simply Do 是此列表中最基本的应用程序。它支持列表和列表项的创建。只需输入项目的名称而无需其他更多内容。每个列表项目有两个状态 — 正在进行或完成时删除。长按一个项目可以选择为高优先级任务添加一个星,但除此之外,Simply Do 是非常简单的。对于寻找一个极简的待办事项列表的用户,这个应用程序可能是一个不错的选择。 TasClock 一个简单的定时器应用程序,TasClock 提供了一种方法来跟踪一个任务花费了多少时间。每个任务只有一个名称,因此任务不能包含额外的描述性数据,但对于基本任务 TasClocks 是足够好的。也可以让计时器同时运行多个项目,但应用程序不提供所有花在任务上的时间的详细报告。TasClock 最严密的特性是每个任务的详细视图,用户可通过长按列表中的任务来访问它。 Tasks 另一个坚实的任务管理器,Tasks 有一个优秀的功能集。你可以为每个单独的任务分配截止日期和优先级。也可以将任务隐藏到某个日期,这样,远在将来的任务不会因为提前显示在任务列表中而 “淹没” 你。Tasks 有一个简单的计时器选项,用于向任务条目添加其预计持续时间和已经花费的时间。 Timesheet Timesheet 可以跟踪处理各种任务所花费的时间。你可以将单个任务插入可计时或不可计时的状态。可从任务列表中选择任务启动 Timesheet 的时间跟踪工具,但只能有一个活动任务处于活动状态,因此在设置任务时需要考虑这一点。 该应用程序有每日和每周概述模式,显示花费在每个任务的时间量。可以将时间表中的数据导出为 CSV 文件,以便在其他程序中使用。 To-Do List 作为隐私保护应用项目的一部分开发的应用之一,To-Do List 采用现代设计,同时注重尊重你的隐私。该应用程序只需要运行所需的绝对最小权限,在这种情况下即是开机自启的权限。To-Do List 支持多个待办事项列表,为每个待办事项分配截止日期,并启用提醒。该应用程序有一个日历视图,它提供了一个很好的方式来查看即将到期的截止日期。 本文作者:佚名 来源:51CTO

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

Spring Security 实现 antMatchers 配置路径的动态获取

1. 为什么要实现动态的获取antMatchers 配置的数据 这两天由于公司项目的需求,对 spring security 的应用过程中需要实现动态的获取 antMatchers ,permitAll ,hasAnyRole ,hasIpAddress 等这些原本通过硬编码的方式配置的数据。为了让每一个业务服务不用再去处理权限验证等这些和业务无关的逻辑,而是只专注于它所负责的业务,就要将认证、授权统一的放在 API 网关层去处理。但是每个不同的业务服务有的接口需要认证后才能访问,有的接口是不需要认证就可以访问的,有的接口可能是需要某些权限、角色才可以访问。这样依赖 API 网关就必须知道并且能够区分出来每个业务服务的接口哪些是需要认证后才可以访问的,那些接口是不需要经过认证就可以访问的。 为了实现这个功能 spring security 提供的 antMatchers 函数硬编码的方式就不适用了。而是应该提供一个管理端,每个业务服务把他们这些个性化的接口通过管理端去进行配置,统一的存储起来,spring security 在获取这些数据的时候从统一的存储中来获取这些数据。基于这个需求前提我来考虑如何实现这个功能。配套视频讲解地址 :http://www.iqiyi.com/w_19s456x5b5.html?pltfm=11&pos=title&flashvars=videoIsFromQidan%3Ditemviewclk_a#vfrm=5-6-0-1 2. 从 Spring Security 框架中找到适合实现该功能的切入点 想要找个框架的切入点必须对框架如何工作,源码要熟悉,不然很难找到一个合适的切入点。有点见缝插针的意思,首先就需要找到一个适合“插针”的位置。 2.1FilterSecurityInterceptor FilterSecurityInterceptor 过滤器是 Spring Security 过滤器链条中的最后一个过滤器,它的任务是来最终决定一个请求是否可以被允许访问。 org.springframework.security.web.access.intercept.FilterSecurityInterceptor#invoke 函数源码:这个函数中做了调用下一个过滤器的操作,也就是这行代码fi.getChain().doFilter(fi.getRequest(), fi.getResponse()) 。因为FilterSecurityInterceptor 是Security 过滤器链条中的最后一个过滤器,再去调用下一个过滤器就是调用原始过滤器链条中的下一个过滤器了,这也就意味着请求是被允许访问的。但是在调用下一个过滤器之前还有一行代码 ,InterceptorStatusToken token = super.beforeInvocation(fi); 这一行代码就会决定本次请求是否会被放行。 public void invoke(FilterInvocation fi) throws IOException, ServletException { if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null) && observeOncePerRequest) { // filter already applied to this request and user wants us to observe // once-per-request handling, so don't re-do security checking fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } else { // first time this request being called, so perform security checking if (fi.getRequest() != null) { fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE); } InterceptorStatusToken token = super.beforeInvocation(fi); try { fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.finallyInvocation(token); } super.afterInvocation(token, null); } } org.springframework.security.access.intercept.AbstractSecurityInterceptor#beforeInvocation 函数源码:这个函数做的事情大致是对这次请求是禁止访问还是允许访问进行投票,如果投票都通过的话就允许访问,如果有一票反对就会禁止访问抛出异常结束后续处理流程。投票的依据就是通过这行代码 Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource().getAttributes(object); 获取到的。这行代码也就是我实现功能的切入点。它先获取了一个SecurityMetadataSource 对象,然后通过这个对象获取了投票的依据。 我的思路就是自定义SecurityMetadataSource 类的子类,来替换掉FilterSecurityInterceptor 中的SecurityMetadataSource 实例。 protected InterceptorStatusToken beforeInvocation(Object object) { Assert.notNull(object, "Object was null"); final boolean debug = logger.isDebugEnabled(); if (!getSecureObjectClass().isAssignableFrom(object.getClass())) { throw new IllegalArgumentException( "Security invocation attempted for object " + object.getClass().getName() + " but AbstractSecurityInterceptor only configured to support secure objects of type: " + getSecureObjectClass()); } Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource() .getAttributes(object); if (attributes == null || attributes.isEmpty()) { if (rejectPublicInvocations) { throw new IllegalArgumentException( "Secure object invocation " + object + " was denied as public invocations are not allowed via this interceptor. " + "This indicates a configuration error because the " + "rejectPublicInvocations property is set to 'true'"); } if (debug) { logger.debug("Public object - authentication not attempted"); } publishEvent(new PublicInvocationEvent(object)); return null; // no further work post-invocation } if (debug) { logger.debug("Secure object: " + object + "; Attributes: " + attributes); } if (SecurityContextHolder.getContext().getAuthentication() == null) { credentialsNotFound(messages.getMessage( "AbstractSecurityInterceptor.authenticationNotFound", "An Authentication object was not found in the SecurityContext"), object, attributes); } Authentication authenticated = authenticateIfRequired(); // Attempt authorization try { this.accessDecisionManager.decide(authenticated, object, attributes); } catch (AccessDeniedException accessDeniedException) { publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated, accessDeniedException)); throw accessDeniedException; } if (debug) { logger.debug("Authorization successful"); } if (publishAuthorizationSuccess) { publishEvent(new AuthorizedEvent(object, attributes, authenticated)); } // Attempt to run as a different user Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attributes); if (runAs == null) { if (debug) { logger.debug("RunAsManager did not change Authentication object"); } // no further work post-invocation return new InterceptorStatusToken(SecurityContextHolder.getContext(), false, attributes, object); } else { if (debug) { logger.debug("Switching to RunAs Authentication: " + runAs); } SecurityContext origCtx = SecurityContextHolder.getContext(); SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext()); SecurityContextHolder.getContext().setAuthentication(runAs); // need to revert to token.Authenticated post-invocation return new InterceptorStatusToken(origCtx, true, attributes, object); } } 2.2替换FilterSecurityInterceptor 中的SecurityMetadataSource 实例 我的目的是替换掉FilterSecurityInterceptor 中的SecurityMetadataSource 实例 , 而不是去替换掉原有的 FilterSecurityInterceptor , 如果要替换掉原有的FilterSecurityInterceptor 那么工作量就变大了,所以替换掉原有的FilterSecurityInterceptor 并不是一个好的选择。首先我需要找到FilterSecurityInterceptor 对象是在什么时候被实例化的。通过使用代码搜索找到 FilterSecurityInterceptor 的实例化位置:org.springframework.security.config.annotation.web.configurers.AbstractInterceptUrlConfigurer#createFilterSecurityInterceptor , 也是在这个函数中SecurityMetadataSource 对象被设置。 private FilterSecurityInterceptor createFilterSecurityInterceptor(H http, FilterInvocationSecurityMetadataSource metadataSource, AuthenticationManager authenticationManager) throws Exception { FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor(); securityInterceptor.setSecurityMetadataSource(metadataSource); securityInterceptor.setAccessDecisionManager(getAccessDecisionManager(http)); securityInterceptor.setAuthenticationManager(authenticationManager); securityInterceptor.afterPropertiesSet(); return securityInterceptor; } createFilterSecurityInterceptor 函数被调用的位置在 :org.springframework.security.config.annotation.web.configurers.AbstractInterceptUrlConfigurer#configure 。这里关键的一行代码是 :securityInterceptor = postProcess(securityInterceptor); @Override public void configure(H http) throws Exception { FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http); if (metadataSource == null) { return; } FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor( http, metadataSource, http.getSharedObject(AuthenticationManager.class)); if (filterSecurityInterceptorOncePerRequest != null) { securityInterceptor .setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest); } securityInterceptor = postProcess(securityInterceptor); http.addFilter(securityInterceptor); http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor); } org.springframework.security.config.annotation.SecurityConfigurerAdapter#postProcess 函数作用 :这个函数中使用了一个objectPostProcessor 成员变量去调用了 postProcess 函数。objectPostProcessor 成员变量默认是org.springframework.security.config.annotation.SecurityConfigurerAdapter.CompositeObjectPostProcessor 的实现类。 protected <T> T postProcess(T object) { return (T) this.objectPostProcessor.postProcess(object); } org.springframework.security.config.annotation.SecurityConfigurerAdapter.CompositeObjectPostProcessor#postProcess 函数源码:这个类的 postProcess 函数中获取到了多个 ObjectPostProcessor 对象,循环的进行调用。看到这里我就找到解决我的问题的方法了,我提供一个 ObjectPostProcessor 实例对象添加到这个ObjectPostProcessor 对象的列表中,然后在我自定义的ObjectPostProcessor 对象中就可以获取到原始的FilterSecurityInterceptor 对象,然后对它进行操作,替换掉原有的SecurityMetadataSource 对象。 public Object postProcess(Object object) { for (ObjectPostProcessor opp : postProcessors) { Class<?> oppClass = opp.getClass(); Class<?> oppType = GenericTypeResolver.resolveTypeArgument(oppClass, ObjectPostProcessor.class); if (oppType == null || oppType.isAssignableFrom(object.getClass())) { object = opp.postProcess(object); } } return object; } 我进行替换SecurityMetadataSource 操作的代码 : package org.hepeng.commons.spring.security.web; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; /** * @author he peng */ public class CustomizeSecurityMetadataSourceObjectPostProcessor implements ObjectPostProcessor<FilterSecurityInterceptor> { private SecurityConfigAttributeLoader securityConfigAttributeLoader; public CustomizeSecurityMetadataSourceObjectPostProcessor(SecurityConfigAttributeLoader securityConfigAttributeLoader) { this.securityConfigAttributeLoader = securityConfigAttributeLoader; } @Override public <O extends FilterSecurityInterceptor> O postProcess(O object) { FilterSecurityInterceptor interceptor = object; CustomizeConfigSourceFilterInvocationSecurityMetadataSource metadataSource = new CustomizeConfigSourceFilterInvocationSecurityMetadataSource( interceptor.obtainSecurityMetadataSource() , securityConfigAttributeLoader); interceptor.setSecurityMetadataSource(metadataSource); return (O) interceptor; } } 2.3 重写自定义 SecurityMetadataSource 中的org.springframework.security.access.SecurityMetadataSource#getAttributes 函数 org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer#createMetadataSource 函数在实例化FilterSecurityInterceptor 对象之前被调用。Spring Security 默认提供了ExpressionBasedFilterInvocationSecurityMetadataSource 的实例。我的思路是模仿这个类中getAttributes 函数的实现。看了这个类的源码后发现这个类中没有重写getAttributes 函数,而是使用父类DefaultFilterInvocationSecurityMetadataSource 的 getAttributes 函数。 @Override final ExpressionBasedFilterInvocationSecurityMetadataSource createMetadataSource( H http) { LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = REGISTRY .createRequestMap(); if (requestMap.isEmpty()) { throw new IllegalStateException( "At least one mapping is required (i.e. authorizeRequests().anyRequest().authenticated())"); } return new ExpressionBasedFilterInvocationSecurityMetadataSource(requestMap, getExpressionHandler(http)); } org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource#getAttributes 源码:这就去操作了requestMap 这个成员变量 , 这个成员变量的类型是 :Map<RequestMatcher, Collection<ConfigAttribute>> 。并且这个成员变量的值是在ExpressionBasedFilterInvocationSecurityMetadataSource 对象的构造函数中进行传递给父类的。 public Collection<ConfigAttribute> getAttributes(Object object) { final HttpServletRequest request = ((FilterInvocation) object).getRequest(); for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap .entrySet()) { if (entry.getKey().matches(request)) { return entry.getValue(); } } return null; } ExpressionBasedFilterInvocationSecurityMetadataSource 源码:在构造函数中就通过processMap 函数完成了父类构造函数所需参数的创建。关键就是这个org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource#processMap 函数。 我也需要调用这个 processMap 函数,但是这个函数是 private 的没法直接调用, 所以只能是通过反射的方式调用。 public ExpressionBasedFilterInvocationSecurityMetadataSource( LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap, SecurityExpressionHandler<FilterInvocation> expressionHandler) { super(processMap(requestMap, expressionHandler.getExpressionParser())); Assert.notNull(expressionHandler, "A non-null SecurityExpressionHandler is required"); } private static LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> processMap( LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap, ExpressionParser parser) { Assert.notNull(parser, "SecurityExpressionHandler returned a null parser object"); LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestToExpressionAttributesMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>( requestMap); for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : requestMap .entrySet()) { RequestMatcher request = entry.getKey(); Assert.isTrue(entry.getValue().size() == 1, "Expected a single expression attribute for " + request); ArrayList<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(1); String expression = entry.getValue().toArray(new ConfigAttribute[1])[0] .getAttribute(); logger.debug("Adding web access control expression '" + expression + "', for " + request); AbstractVariableEvaluationContextPostProcessor postProcessor = createPostProcessor( request); try { attributes.add(new WebExpressionConfigAttribute( parser.parseExpression(expression), postProcessor)); } catch (ParseException e) { throw new IllegalArgumentException( "Failed to parse expression '" + expression + "'"); } requestToExpressionAttributesMap.put(request, attributes); } return requestToExpressionAttributesMap; } 我自定义的SecurityMetadataSource 源码 : package org.hepeng.commons.spring.security.web; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.joor.Reflect; import org.springframework.expression.ExpressionParser; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.expression.SecurityExpressionHandler; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource; import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource; import org.springframework.security.web.util.matcher.RequestMatcher; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; /** * @author he peng */ public class CustomizeConfigSourceFilterInvocationSecurityMetadataSource extends DefaultFilterInvocationSecurityMetadataSource { private static final Reflect REFLECT = Reflect.on(ExpressionBasedFilterInvocationSecurityMetadataSource.class); private SecurityMetadataSource delegate; private SecurityConfigAttributeLoader metadataSourceLoader; private ExpressionParser expressionParser; public CustomizeConfigSourceFilterInvocationSecurityMetadataSource( SecurityMetadataSource delegate , SecurityConfigAttributeLoader metadataSourceLoader) { super(new LinkedHashMap<>()); this.delegate = delegate; this.metadataSourceLoader = metadataSourceLoader; copyDelegateRequestMap(); } private void copyDelegateRequestMap() { Reflect reflect = Reflect.on(this); reflect.set("requestMap" , getDelegateRequestMap()); } private LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> getDelegateRequestMap() { Reflect reflect = Reflect.on(this.delegate); return reflect.field("requestMap").get(); } @Override public Collection<ConfigAttribute> getAttributes(Object object) { final HttpServletRequest request = ((FilterInvocation) object).getRequest(); Collection<ConfigAttribute> configAttributes = new ArrayList<>(); LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = this.metadataSourceLoader.loadConfigAttribute(request); if (MapUtils.isEmpty(requestMap)) { configAttributes.addAll(this.delegate.getAttributes(object)); return configAttributes; } if (Objects.isNull(this.expressionParser)) { SecurityExpressionHandler securityExpressionHandler = GlobalSecurityExpressionHandlerCacheObjectPostProcessor.getSecurityExpressionHandler(); if (Objects.isNull(securityExpressionHandler)) { throw new NullPointerException(SecurityExpressionHandler.class.getName() + " is null"); } this.expressionParser = securityExpressionHandler.getExpressionParser(); } LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> webExpressionRequestMap = REFLECT.call("processMap" , requestMap , this.expressionParser).get(); for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : webExpressionRequestMap.entrySet()) { if (entry.getKey().matches(request)) { configAttributes.addAll(entry.getValue()); break; } } if (CollectionUtils.isEmpty(configAttributes)) { configAttributes.addAll(this.delegate.getAttributes(object)); } return configAttributes; } } 为了实现解耦的目的我定义了一个SecurityConfigAttributeLoader 接口 , 这个接口负责从任何指定的地方去读取配置数据。关于该功能的代码我都发布到了 maven 中央仓库中 , 坐标是 : <dependency> <groupId>org.hepeng</groupId> <artifactId>hp-java-commons</artifactId> <version>1.1.3</version> </dependency> 使用的时候只需要一行简单的配置代码 , 还有提供一个SecurityConfigAttributeLoader 接口的实现,配置代码 :org.hepeng.commons.spring.security.web.CustomizeSecurityConfigAttributeSourceConfigurer#public static <T extends ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry> T enable(T configurer) , 这个配置方式会从 Spring 的容器中去寻找一个SecurityConfigAttributeLoader 实例对象。

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

机器学习:入门方法与学习路径 (附资料)

◆◆◆ 1. 引言 也许你和这个叫『机器学习』的家伙一点也不熟,但是你举起iphone手机拍照的时候,早已习惯它帮你框出人脸;也自然而然点开今日头条推给你的新闻;也习惯逛淘宝点了找相似之后货比三家;亦或喜闻乐见微软的年龄识别网站结果刷爆朋友圈。恩,这些功能的核心算法就是机器学习领域的内容。 套用一下大神们对机器学习的定义,机器学习研究的是计算机怎样模拟人类的学习行为,以获取新的知识或技能,并重新组织已有的知识结构使之不断改善自身。简单一点说,就是计算机从数据中学习出规律和模式,以应用在新数据上做预测的任务。近年来互联网数据大爆炸,数据的丰富度和覆盖面远远超出人工可以观察和总结的范畴,而机器学习的算法能指引计算机在海量数据中,挖掘出有用的价值,也使得无数学习者为之着迷。 但是越说越觉得机器学习有距离感,云里雾里高深莫测,我们不是专家,但

资源下载

更多资源
腾讯云软件源

腾讯云软件源

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

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应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册