数据专栏

智能大数据搬运工,你想要的我们都有

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

「深度学习福利」大神带你进阶工程师,立即查看>>>
本文主要是研读了资深架构师王概凯Kevin执笔的《架构漫谈》系列的《架构漫谈(一):什么是架构?》的心得感受。王概凯Kevin结合自己多年的架构经验,通过不同的视角,重新审视架构的本质,从而产生一力作《架构漫谈》系列,作者希望能够抛出自己从实践中得出的一些观点,并引发大家的一些思考,欢迎大家沟通讨论。
如需要阅读原文,请关注公众号“聊聊架构”,从历史文章中获取《架构漫谈》系列。
本文内容结构图:

其实一直以来也没有弄明白,架构为何物,自从看了王概凯Kevin执笔的《架构漫谈》系列之后,对此依然还不是那么清晰,但是从中了解到了更重要的是 “架构本质是什么” ,其实一直以来也没有人能够准确清晰的描述架构为何物,100个人中就有100种对架构的理解。如果自认为可以能够准确描述出来何物,那其实你还没有真正理解架构本质。细品《架构漫谈》这一系列吧,等你看完这一系列,会发现王概凯Kevin讲的不只是软件行业的架构,而是面对问题的架构,更有甚者,其背后的思想可以运用到对生活、人生、社会的架构。 其实架构就不是具体物,也不能通过具体的方式表达出来,因为它一开始就不存在,而是源于对问题、效率、改进、欲望等等不断诉求、实现的过程 。
正所谓,道生一,一生二,二生三,三生万物,而架构生于万物的高效协作。


然而,事实是,架构在软件行业诞生N年前就已经存在了,所以对于架构,不应该只限于在软件的角度来看,那其实是不准确,不全面的。我们必须要从源头开始,把架构的概念讨论清楚,只有这样软件行业的架构讨论才有意义。那么为什么会产生架构呢?
以下内容摘自《架构漫谈系列(一):什么是架构?》: 想象一下,在远古早期,每个人都完全独立生活,衣、食、住、行等等全部都自己搞定,整个人类都是独立的个体,不相往来。 为了解决人类的延续的问题,自然而然就有男女群居出现,这个时候就出现了分工了,男性和女性所做的事情就会有一定的分工,比如:男性身体强壮擅于捕猎、女性性情温和善于孕育等 。可是人每天生活的基本需求没有发生变化,还是衣食住行等生活必须品。 面对问题 :人类延续
架构形成 :男女群居、男女分工 然而面对自然灾害,生活遭受灾害不确定性,所以多人分工配合作为生存的整体,力量就显得强大多了,所以也自然的形成了族群:有些人种田厉害,有些人制作工具厉害,有些地方适合产出粮食,有些地方适合产出棉花等,就自然形成了人的分群,地域的分群。 当分工发生后,实际上每个人的生产力都得到了提高,因为做的都是每个人擅长的事情 。 面对问题 :自然灾害、个人生产效率低,生活遭受灾害不确定性
架构形成 :多人族群,角色分工 整个人群的生产力和抵抗环境的能力都得到了增强。为什么呢?因为每个人的能力和时间都是有限的,并且因为人的结构的限制,人同时只能专心做好一件事情,这样不得已就导致了分工的产生。 既然分工发生了,原来由一个人干生存所必需的所有的事情,就变成了很多不同分工的角色合作完成这些事情,这些人必须要通过某些机制合在一起 ,让每个人完成生存所必需的事情,这实际上也导致了交易的发生。 角色分工产生,由于每个人都在干自己擅长的工作,生产力必然会提升。 在每个人都必须自己完成所有生活必须品的生产的时候,是没有架构的(当然在个人来讲,同一时刻只能做有限的事情,在时间上还是可能会产生架构的) 。一旦产生的分工,就把所有的事情,切分成由不同角色的人来完成,最后再通过交易,使得每个个体都拥有生活必须品,而不需要每个个体做所有的事情,只需要每个个体做好自己擅长的事情,并具备一定的交易能力即可。 角色分工产生,生产力提高,更需要具备的是交易能力。只有交易,才能使每个个体拥有生活各方面的必须品。
经过以上四个步骤,这实际上就形成了社会的架构。那么怎么定义架构呢?以上面这个例子为例, 把一个整体(完成人类生存的所有工作)切分成不同的部分(分工),由不同角色来完成这些分工,并通过建立不同部分相互沟通的机制,使得这些部分能够有机的结合为一个整体,并完成这个整体所需要的所有活动,这就是架构。
通过以上的例子,可以归纳出产生架构的五个动力条件: 必须由人执行的工作(不需要人介入,就意味着不需要改造,也就不需要架构了) 每个人的能力有限(每个人都有自己的强项,个人的产出受限于最短板,并且由于人的结构限制,同时只能专注于做好一件事情,比如虽然有两只眼睛,但是只能同时专注于一件事物,有两只手,无法同时做不同的事情。ps. 虽然有少部分人可以左手画圆右手画框,但是不是普遍现象) 每个人的时间有限(为了减少时间的投入,必然会导致把工作分解出去,给擅长于这些工作的角色来完成,见2,从而缩短时间) 人对目标系统有更高的要求(如果满足于现状,也就不需要进行架构了) 目标系统的复杂性使得个人无法完成这个系统,满足条件2,3(如果个人就可以完成系统的提高,也不需要别的人参与,也就不需要架构的涉及,只是工匠,并且一般这个工作对时间的要求也不迫切。当足够熟练之后,也会有一定的架构思考,但考虑更多的是如何提高质量,提高个人的时间效率)
有人可能会挑战说,如果一个人对目标系统进行分解,比如某人建一栋房子,自己采购材料,自己搭建,难道也不算架构嘛? 如果对于时间不敏感的话,是会出现这个情况的,但是在这种情况下,并不必然导致架构的发生。 如果有足够的自觉,以及足够的熟练的话,也会产生架构的思考,因为这样对于提高生产力是有帮助的,可以缩短建造的时间,并会提高房子的质量。事实上建筑的架构就是在长期进行这些活动后,积累下来的实践。
当这5个条件同时成立,一定会产生架构。从这个层面上来说, 架构是人类发展过程中,由懵懵懂懂的,被动的去认识这个世界,变成主动的去认识,并以更高的效率去改造这个世界的方法。
总结一下,架构本质是什么,就是: 根据要解决的问题,对目标系统的边界进行界定。 并对目标系统按某个原则的进行切分。切分的原则,要便于不同的角色,对切分出来的部分,并行或串行开展工作,一般并行才能减少时间。
并对这些切分出来的部分,设立沟通机制。 根据2,使得这些部分之间能够进行有机的联系,合并组装成为一个整体,完成目标系统的所有工作。
同样这个思考可以运用到其他行业架构,比如:企业架构、组织架构、软件架构等等。 每一次架构的变革,都是主动对现有问题的解决,对现有环境的适应 。 架构实际上就是指人们根据自己对世界的认识,为解决某个问题,主动地、有目的地去识别问题,并进行分解、合并,解决这个问题的实践活动。
架构的产出物,自然就是对问题的分析,以及解决问题的方案 :包括拆分的原则以及理由,沟通合并的原则以及理由,以及拆分,拆分出来的各个部分和合并所对应的角色和所需要的核心能力等。
作者:猿码道
链接:https://juejin.im/post/5b36de3df265da59b71385b8
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
项目管理
2018-07-09 12:33:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Confluence 中索引的语言配置。

可以单击编辑后进行修改。


https://www.cwiki.us/display/CONF6ZH/Configuring+Indexing+Language
项目管理
2018-07-09 11:35:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
进入后台后查看快速导航的启用和可以同时查找的数量。
然后进行通过单击右上角的编辑(Edit)按钮进行编辑。

对配置进行配置,启用快速查询和可以同时使用的最大查询数量。

https://www.cwiki.us/display/CONF6ZH/Configuring+Quick+Navigation
项目管理
2018-07-09 10:07:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Confluence 中索引的语言配置。

可以单击编辑后进行修改。


https://www.cwiki.us/display/CONF6ZH/Configuring+Indexing+Language
项目管理
2018-07-09 09:53:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Spring Boot对于如何使用Spring构建应用程序有一个看法:例如它具有常规配置文件的常规位置,以及用于常见管理和监视任务的端点。 Spring Cloud建立在此之上,并添加了一些可能系统中所有组件将使用或偶尔需要的功能。
引导应用程序上下文
一个Spring Cloud应用程序通过创建一个“引导”上下文来进行操作,这个上下文是主应用程序的父上下文。开箱即用,负责从外部源加载配置属性,还解密本地外部配置文件中的属性。这两个上下文共享一个 Environment ,这是任何Spring应用程序的外部属性的来源。Bootstrap属性的优先级高,因此默认情况下不能被本地配置覆盖。
引导上下文使用与主应用程序上下文不同的外部配置约定,因此使用 bootstrap.yml application.yml (或 .properties )代替引导和主上下文的外部配置。例:
bootstrap.yml spring: application: name: foo cloud: config: uri: ${SPRING_CONFIG_URI:http://localhost:8888}
如果您的应用程序需要服务器上的特定于应用程序的配置,那么设置 spring.application.name (在 bootstrap.yml 或 application.yml )中是个好主意。
您可以通过设置 spring.cloud.bootstrap.enabled=false (例如在系统属性中)来完全禁用引导过程。
应用程序上下文层次结构
如果您从 SpringApplication 或 SpringApplicationBuilder 构建应用程序上下文,则将Bootstrap上下文添加为该上下文的父级。这是一个Spring的功能,即子上下文从其父进程继承属性源和配置文件,因此与不使用Spring Cloud Config构建相同上下文相比,“主”应用程序上下文将包含其他属性源。额外的财产来源是: “bootstrap”:如果在Bootstrap上下文中找到任何 PropertySourceLocators ,则可选 CompositePropertySource 显示为高优先级,并且具有非空属性。一个例子是来自Spring Cloud Config服务器的属性。有关如何自定义此属性源的内容的 说明 ,请参阅 下文 。 “applicationConfig:[classpath:bootstrap.yml]”(如果Spring配置文件处于活动状态,则为朋友)。如果您有一个 bootstrap.yml (或属性),那么这些属性用于配置引导上下文,然后在父进程设置时将它们添加到子上下文中。它们的优先级低于 application.yml (或属性)以及作为创建Spring Boot应用程序的过程的正常部分添加到子级的任何其他属性源。有关如何自定义这些属性源的内容的 说明 ,请参阅 下文 。
由于属性源的排序规则,“引导”条目优先,但请注意,这些条目不包含来自 bootstrap.yml 的任何数据,它具有非常低的优先级,但可用于设置默认值。
您可以通过简单地设置您创建的任何 ApplicationContext 的父上下文来扩展上下文层次结构,例如使用自己的界面,或使用 SpringApplicationBuilder 方便方法( parent() , child() 和 sibling() )。引导环境将是您创建自己的最高级祖先的父级。层次结构中的每个上下文都将有自己的“引导”属性源(可能为空),以避免无意中将值从父级升级到其后代。层次结构中的每个上下文(原则上)也可以具有不同的 spring.application.name ,因此如果存在配置服务器,则不同的远程属性源。普通的Spring应用程序上下文行为规则适用于属性解析:子环境中的属性通过名称和属性源名称覆盖父项中的属性(如果子级具有与父级名称相同的属性源,一个来自父母的孩子不包括在孩子中)。
项目管理
2018-07-09 09:48:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
Spring Cloud集成项目有很多,下面我们列举一下和Spring Cloud相关的优秀项目,我们的企业架构中用到了很多的优秀项目,说白了,也是站在巨人的肩膀上去整合的。在学习Spring Cloud之前大家必须了解一下相关项目,希望可以帮助到大家。
Spring Cloud Config
配置管理工具包,让你可以把配置放到远程服务器,集中化管理集群配置,目前支持本地存储、Git以及Subversion。
Spring Cloud Bus
​事件、消息总线,用于在集群(例如,配置变化事件)中传播状态变化,可与Spring Cloud Config联合实现热部署。
Eureka
云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。
Hystrix
熔断器,容错管理工具,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。
Zuul
Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。
Archaius
配置管理API,包含一系列配置管理API,提供动态类型化属性、线程安全配置操作、轮询框架、回调机制等功能。
Consul
封装了Consul操作,consul是一个服务发现与配置工具,与Docker容器可以无缝集成。
Spring Cloud for Cloud Foundry
通过Oauth2协议绑定服务到CloudFoundry,CloudFoundry是VMware推出的开源PaaS云平台。
Spring Cloud Sleuth
日志收集工具包,封装了Dapper和log-based追踪以及Zipkin和HTrace操作,为SpringCloud应用实现了一种分布式追踪解决方案。
Spring Cloud Data Flow
大数据操作工具,作为Spring XD的替代产品,它是一个混合计算模型,结合了流数据与批量数据的处理方式。
Spring Cloud Security
基于spring security的安全工具包,为你的应用程序添加安全控制。
Spring Cloud Zookeeper
操作Zookeeper的工具包,用于使用zookeeper方式的服务发现和配置管理。
Spring Cloud Stream
数据流操作开发包,封装了与Redis,Rabbit、Kafka等发送接收消息。
Spring Cloud CLI
基于 Spring Boot CLI,可以让你以命令行方式快速建立云组件。
Ribbon
提供云端负载均衡,有多种负载均衡策略可供选择,可配合服务发现和断路器使用。
Turbine
Turbine是聚合服务器发送事件流数据的一个工具,用来监控集群下hystrix的metrics情况。
Feign
Feign是一种声明式、模板化的HTTP客户端。
Spring Cloud Task
提供云端计划任务管理、任务调度。
Spring Cloud Connectors
便于云端应用程序在各种PaaS平台连接到后端,如:数据库和消息代理服务。
Spring Cloud Cluster
提供Leadership选举,如:Zookeeper, Redis, Hazelcast, Consul等常见状态模式的抽象和实现。
Spring Cloud Starters
Spring Boot式的启动项目,为Spring Cloud提供开箱即用的依赖管理。
项目管理
2018-07-09 09:44:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
请注意,有关站点的活动信息 在默认情况下是禁用 的。请查看 下面 的说明。
如果这个插件被启用的话,有关站点的全局活动状态将会在你的 Confluence 站点中显示出来。显示的数据包括: 在给定的时间内有多少页面和和博客内容被查看,添加或者更新。 那一个空间是最多访问的空间(最经常查看的)。 那一个空间是最活跃的(最经常编辑的)。 哪些人对系统工具最积极,包括创建和编辑内容。
希望查看你站点的活动: 在屏幕的右上角单击 控制台按钮 ,然后选择 General Configuration 链接。 在管理员界面中选择 全局活动( Global Activity )。管理员界面位于左侧的面板(这个仅在插件被启用后才能显示 - 请查看 下面 的说明)。
屏幕截图:全局活动
10 个最流行的和活动最多的页面/博客页面将会显示出来,同时也为这些页面提供了链接。
备注 Confluence Usage Stats plugin 插件提供了有关你站点的全局活动界面。这个插件的启用在大型站点中将会对站点的性能产生影响。因此这个插件 在默认情况下是禁用 的。有关这个插件对站点性能的应先可以在下面的链接中找到: USGTRK-15 。 Confluence 的系统管理员可以启用这个插件。请注意,启用这个插件将会有可能影响你站点的性能。 这个插件有时候也被成为:Confluence Usage Tracking。 如果你的 Confluence 站点是集群的话,全局活动信息将可能不可用。 在启用后,全局活动将不会显示历史数据。
https://www.cwiki.us/display/CONF6ZH/Viewing+Site+Statistics
项目管理
2018-07-07 03:20:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 希望查看空间的活动情况, Confluence Usage Stats 插件必须在系统中启用。这个插件启用的话将会导致系统的性能问题。针对大型的 Confluence 站点,这个插件 在默认情况下是禁用 的,系统管理员可以启用这个插件(进入 插件(add-ons) ,然后选择 系统插件(System add-ons) ,然后查找 'Confluence Usage Stats' 插件)。 这个插件只在激活的时候收集数据。 如果 你正在使用的是 Confluence Data Center 或者 Confluence 的云服务,空间活动信息状态不可用。 页面的提示并不是唯一的 —— 显示在空间活动页面中的图片包括了所有页面的提示图标,也包括了同一个用户的多次访问。

https://www.cwiki.us/display/CONFLUENCEWIKI/View+Space+Activity
项目管理
2018-07-07 03:15:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
空间活动信息是默认禁用( disabled by default )的。活动(Activity)的标没有显示,如果你的 Confluence Usage Stats 插件没有启用的。请查看 下面 的说明:
如果启用的话,空间活动界面显示了每一个空间的活动状态,这些状态包括有: 在给定的时间内有多少页面和博客页面被查看,添加修改和更新。 那些内容是有最高的查看(查看最多的页面)。 那些内容是最活跃的页面(更新最多的页面)。 那些用户是最活跃的内容贡献/编辑者。
希望查看空间的活动: 进入空间,然后在左侧边栏的下面选择 空间工具(Space Tools) 。 然后选择 活动(Activity)
相关页面: Page History and Page Comparison Views Watch Pages, Spaces and Blogs How do I get more statistics from Confluence?
你将会看到一个图形化的界面,显示了被查看,添加,和编辑的页面和博客页面的数量和在给定时间内的修改趋势。
屏幕截图:空间活动标签
相对于图形显示编辑和查看最多的页面,在最上面显示了 10 个最流行的,最活页的页面(也包括博客页面)。这些内容是通过链接显示的,以列表方式显示:
屏幕截图:最流行的内容,活跃内容和活跃贡献者。
https://www.cwiki.us/display/CONFLUENCEWIKI/View+Space+Activity
项目管理
2018-07-07 03:11:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
在 Confluence 中的 系统信息(System Information) 部分,有一个 修改(Modification) 的选项。在这个选项中列出了自你 Confluence 安装以来,你 Confluence 中所做的所有修改。当你需要将你的 Confluence 升级到新的版本的时候,你会发现这个内容对你非常有帮助,因为你需要将 Confluence 升级后将修改的内容重新再做一次。
希望查看你 Confluence 安装后所做的修改: 在屏幕的右上角单击 控制台按钮 ,然后选择 General Configuration 链接。 在左侧边栏的管理员部分选择 系统信息(System Information) 。 然后往下滚动找到 修改(Modification) 链接。
屏幕截图:Confluence 系统信息界面,显示了你所做的修改
备注 这个修改跟踪不能跟踪 confluence.jar 的修改和任何有关 JRA 的修改。如果你对 Confluence 的类进行类修改,那这些修改不能显示在这部分的跟踪内容中。请查看问题: CONF-20993 来获得更多的信息。

https://www.cwiki.us/display/CONF6ZH/Tracking+Customisations+Made+to+your+Confluence+Installation
项目管理
2018-07-07 03:05:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
最近在做一个课程设计,在线小说网站的设计,以下是课题要求,需要项目练手的童鞋可以试试身手。
由于最近新学了JavaEE,所以采用了jsp+servlet来写,前端部分用了少量的js和jQuery处理,数据库用了MySQL,开发平台是myeclipse。
发布文章时直接插入数据库会没有分段,这里的解决办法是引入第三方工具wangEditor(wangEditor 是一款基于javascript和css开发的html富文本编辑器,开源免费。产品第一版发布于2014年11月。关于该编辑器:http://www.kancloud.cn/wangfupeng/wangeditor2/113961)
首先数据库的设计结构: /* Navicat MySQL Data Transfer Source Server : blog Source Server Version : 50528 Source Host : localhost:3306 Source Database : novel Target Server Type : MYSQL Target Server Version : 50528 File Encoding : 65001 Date: 2016-12-31 16:04:07 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for admin -- ---------------------------- DROP TABLE IF EXISTS `admin`; CREATE TABLE `admin` ( `id` int(11) NOT NULL AUTO_INCREMENT, `adminName` varchar(255) NOT NULL, `adminPassword` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for author -- ---------------------------- DROP TABLE IF EXISTS `author`; CREATE TABLE `author` ( `id` int(11) NOT NULL AUTO_INCREMENT, `authorName` varchar(255) NOT NULL, `authorPassword` varchar(255) NOT NULL, `authorEmail` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for comment -- ---------------------------- DROP TABLE IF EXISTS `comment`; CREATE TABLE `comment` ( `id` int(11) NOT NULL AUTO_INCREMENT, `context` text, `createdTime` datetime DEFAULT NULL, `readerName` varchar(255) DEFAULT NULL, `novelId` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for genre -- ---------------------------- DROP TABLE IF EXISTS `genre`; CREATE TABLE `genre` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `sort` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for novel -- ---------------------------- DROP TABLE IF EXISTS `novel`; CREATE TABLE `novel` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL, `context` text NOT NULL, `createdTime` datetime DEFAULT NULL, `genreId` int(11) DEFAULT NULL, `voteNumber` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=160 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for reader -- ---------------------------- DROP TABLE IF EXISTS `reader`; CREATE TABLE `reader` ( `id` int(11) NOT NULL AUTO_INCREMENT, `readerName` varchar(255) NOT NULL, `readerPassword` varchar(255) NOT NULL, `readerEmail` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;
项目的大致结构如图:
由于功能有点多,这里先介绍后台的实现,管理后台和前台互不交涉。
登录界面
后台主页:
1,小说管理
2,作者管理:
3,增加分类
后台其他导航页面基本雷同,这里不做一一介绍。
后台管理员登录处理代码: public class Admin { Conn conn=new Conn(); /** * 判断登陆用户是否合法 * @param adminName * @param adminPassword * @return * @throws SQLException */ public boolean isExist(String adminName,String adminPassword)throws SQLException{ boolean result=false; AdminInfo ainfo=new AdminInfo(); String sql="select * from admin a where adminName='"+adminName+"'and adminPassword='"+adminPassword+"'"; System.out.println(sql); ResultSet rs=conn.executeQuery(sql); if(rs.next()){ ainfo.setAdminName(rs.getString("adminName")); ainfo.setAdminPassword(rs.getString("adminPassword")); result=true; } conn.close(); return result; } }
小说展示,管理,增加,删除,更新的代码处理: public class Novel { Conn conn=new Conn(); /** * 获取小说列表 * @param keyword * @return * @throws SQLException */ public ListgetList(String keyword)throws SQLException{ List list=new ArrayList(); String sql="select n.*,g.name as genreName from novel n left join genre g on n.genreId=g.id"; if(DataValidator.isNullOrEmpty(keyword)){ sql=sql+ " order by id desc"; }else{ sql=sql+" where n.title like '%"+keyword+"%' order by id desc"; } ResultSet rs=conn.executeQuery(sql); while(rs.next()){ NovelInfo ninfo=new NovelInfo(); ninfo.setId(rs.getInt("Id")); ninfo.setTitle(rs.getString("Title")); ninfo.setContext(rs.getString("Context")); ninfo.setCreatedTime(rs.getDate("CreatedTime")); ninfo.setGenreId(rs.getInt("GenreId")); ninfo.setGenreName(rs.getString("genreName")); ninfo.setVoteNumber(rs.getInt("voteNumber")); list.add(ninfo); } conn.close(); return list; } /** * 获取某分类下的小说列表 * @param classId * @return * @throws SQLException */ public List getListBygenreId(int genreId) throws SQLException{ List list=new ArrayList(); String sql="select n.*,g.name as genreName from novel n left join genre g on n.genreId=g.id" + " where n.genreId="+genreId+" order by id desc"; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ NovelInfo info=new NovelInfo(); info.setId(rs.getInt("Id")); info.setTitle(rs.getString("Title")); info.setContext(rs.getString("Context")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setGenreId(rs.getInt("GenreId")); info.setGenreName(rs.getString("genreName")); info.setVoteNumber(rs.getInt("voteNumber")); list.add(info); } conn.close(); return list; } /** * 根据ID获取小说 * @param id * @return * @throws SQLException */ public NovelInfo getNovelInfo(int id) throws SQLException{ NovelInfo info=new NovelInfo(); String sql="select n.*,g.name as genreName from novel n left join genre g on n.genreId=g.id where n.id="+id+""; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ info.setId(rs.getInt("Id")); info.setTitle(rs.getString("Title")); info.setContext(rs.getString("Context")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setGenreId(rs.getInt("GenreId")); info.setGenreName(rs.getString("genreName")); info.setVoteNumber(rs.getInt("voteNumber")); } conn.close(); return info; } /** * 写入新小说 * * @param info * @return */ public int insert(NovelInfo info){ String sql="insert into novel(title,conText,createdTime,genreId,voteNumber)values"; sql=sql+"('"+info.getTitle()+"','"+info.getContext()+"',now(),'"+info.getGenreId()+"',"+info.getVoteNumber()+")"; int result=0; System.out.println(sql); result=conn.executeUpdate(sql); conn.close(); return result; } /** *更新小说 * @param info * @return */ public int update(NovelInfo info){ String sql="update novel set "+" Title='"+info.getTitle()+"',Context='"+info.getContext()+"'," + "genreId='"+info.getGenreId()+"'where id="+info.getId()+""; int result=0; System.out.println(sql); result=conn.executeUpdate(sql); conn.close(); return result; } /** * 删除小说 * @param id * @return */ public int delete(int id){ String sql="delete from novel where id="+id+""; int result=0; result=conn.executeUpdate(sql); conn.close(); return result; } /** * 增加票数 * @return */ public int addVote(int num){ return 0; } }
小说评论展示,管理,增加,删除,更新的代码处理: public class Comment { Conn conn=new Conn(); /** * 获取评论列表 * @return * @throws SQLException */ public List getList() throws SQLException{ List list=new ArrayList(); String sql="select * from comment order by id desc"; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ CommentInfo info=new CommentInfo(); info.setId(rs.getInt("Id")); info.setContext(rs.getString("Context")); info.setNovelId(rs.getInt("NovelId")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setReaderName(rs.getString("ReaderName")); list.add(info); System.out.print(list); } conn.close(); return list; } /** * * @param classId * @return * @throws SQLException */ public CommentInfo getCommentInfo(int id)throws SQLException{ CommentInfo info=new CommentInfo(); String sql="select * from Comment c where id="+id+""; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ info.setId(rs.getInt("Id")); info.setContext(rs.getString("Context")); info.setNovelId(rs.getInt("NovelId")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setReaderName(rs.getString("ReaderName")); } conn.close(); return info; } /** * 获取某小说下的评论 * @param id * @return * @throws SQLException */ public List getListByNovelId(int novelid) throws SQLException{ List list=new ArrayList(); String sql="select * from comment where novelId="+novelid+" order by id desc"; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ CommentInfo info=new CommentInfo(); info.setId(rs.getInt("Id")); info.setContext(rs.getString("Context")); info.setNovelId(rs.getInt("NovelId")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setReaderName(rs.getString("ReaderName")); list.add(info); } conn.close(); return list; } /** * 插入评论 * @param info * @return */ public int insert(CommentInfo info){ String sql="insert into Comment(Context,CreatedTime,readerName,novelId)values"; sql=sql+"('"+info.getContext()+"',now(),'"+info.getReaderName()+"',"+info.getNovelId()+")"; int result=0; System.out.println(sql); result=conn.executeUpdate(sql); conn.close(); return result; } /** * 更新评论 * @param info * @return */ public int update(CommentInfo info){ String sql="update Comment set "+" Context='"+info.getContext()+"',novelId='"+info.getNovelId()+"'," + "CreatedTime='"+info.getCreatedTime()+"',readerName='"+info.getReaderName()+"' where id="+info.getId()+""; int result=0; System.out.println(sql); result=conn.executeUpdate(sql); conn.close(); return result; } /** * 删除评论 * @param id * @return */ public int delete(int id){ String sql="delete from Comment where id="+id+""; int result=0; result=conn.executeUpdate(sql); System.out.println(sql); conn.close(); return result; } }
小说分类展示,更新,增加,删除的代码处理: public class Genre { Conn conn=new Conn(); /** * 获取分类列表 * @return * @throws SQLException */ public List getList()throws SQLException{ List list=new ArrayList(); String sql="select * from genre order by Sort asc"; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ GenreInfo info=new GenreInfo(); info.setId(rs.getInt("Id")); info.setName(rs.getString("Name")); info.setSort(rs.getInt("Sort")); list.add(info); } conn.close(); return list; } /** * * @param id * @return * @throws SQLException */ public GenreInfo getGenreInfo(int id)throws SQLException{ GenreInfo info=new GenreInfo(); String sql="select * from genre g where id="+id+""; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ info.setId(rs.getInt("Id")); info.setName(rs.getString("Name")); info.setSort(rs.getInt("Sort")); } conn.close(); return info; } /** * 增加分类 * @param info * @return */ public int insert(GenreInfo info){ String sql="insert into genre(Name,Sort) values"; sql=sql+"('"+info.getName()+"','"+info.getSort()+"')"; int result=0; result=conn.executeUpdate(sql); conn.close(); return result; } /** * 更新分类 * * @param info * @return */ public int update(GenreInfo info){ String sql="update genre set "+" Name='"+info.getName()+"',Sort= '"+info.getSort()+"' where id="+info.getId()+""; int result=0; result=conn.executeUpdate(sql); return result; } public int delete(int id){ String sql="delete from genre where id="+id+""; int result=0; result=conn.executeUpdate(sql); conn.close(); return result; } }
前台主要页面展示:
作者发布小说界面:
读者评论界面:
为小说投票,投票功能的前端设计代码: function getElemensByClassName(className){ // 通过class获取 var classArr = new Array(); var tags = document.getElementsByTagName("*"); //获取所有节点 for(var item in tags){ if(tags[item].nodeType == 1){ if(tags[item].getAttribute("class") == className){ classArr.push(tags[item]); //收集class匹配的节点 } } } return classArr; } function delete_FF(element){ // 在FireFox中删除子节点为空的元素 var childs = element.childNodes; for(var i=0;i小说发布的实现细节,引入了wangEditor: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@page import="org.common.*" %> <%@page import="org.model.*" %> <%@page import="org.dal.*" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!-- 发布小说 --> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>小说编辑发布界面</title> <script type="text/javascript" src="js/jquery-1.10.1.js"></script> <link rel="stylesheet" type="text/css" href="css/edit.css"> <link rel="stylesheet" type="text/css" href="css/wangEditor.min.css"> <script type="text/javascript" src="js/wangEditor.min.js"></script> </head> <body> <% request.setCharacterEncoding("utf-8"); Genre cls=new Genre(); List<GenreInfo>list=cls.getList(); Novel novel=new Novel(); NovelInfo ninfo=new NovelInfo(); if("fabu".equals(request.getParameter("action"))) { ninfo.setTitle(request.getParameter("txtTitle")); ninfo.setContext(request.getParameter("content")); ninfo.setGenreId(DataConverter.toInt(request.getParameter("selClass"))); novel.insert(ninfo); out.println("<script>alert('发布成功');</script>"); } %> <div class="header"> <h2>当前位置:小说编辑</h2> </div> <a class="wel">欢迎您:<%=Utilty.readCookie(request, "user")%></a> <div class="context" > <form id="form1" name="form1" method="post" action="novel/novel-edit.jsp?action=fabu" onsubmit="return check(this)"> <table> <tr> <td>小说所属分类:</td> <td> <select name="selClass" id="selClass" style="width:300px;height:30px;"> <% for(GenreInfo cinfo:list){ %> <option value="<%=cinfo.getId() %>"> <%if(cinfo.getId()==ninfo.getId()) %> <%=cinfo.getName() %></option> <% } %> </select> </td> </tr> <tr> <td>小 说 标 题:</td> <td><input type="text" name="txtTitle" id="txtTitle" style="width:500px;height:30px"/></td> </tr> <tr> <td>小 说 内 容:</td> <td style="width:1000px;"><textarea rows="25" name="content" id="content"></textarea> </td> </tr> <tr> <td colspan="2" class="inp"> <input class="submit" type="submit" name="button" id="button" value="提交" style="color:#FFFFFF"/> <input class="submit" type="reset" name="button2" id="button2" value="重置"style="color:#FFFFFF" /> </td> </tr> </table> </form> </div> </body> <script type="text/javascript"> var editor = new wangEditor('content'); editor.config.menus = [ 'bold', 'underline', 'italic', 'strikethrough', 'eraser', 'forecolor', 'bgcolor', '|', 'link', 'unlink', 'table', 'emotion', '|', 'img', 'video', 'location', ]; editor.create(); </script> </html>
由于代码段较多,这里不能一一介绍,这个项目实现起来较简单,童鞋们可以根据设计要求试试身手哦!

源码地址: https://github.com/guodalin8/novel

亲,如果您感觉本文有用,请点个赞再走吧✌(>‿◠)!!
项目管理
2018-07-06 11:01:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
RestTemplate 可以自动配置为使用功能区。要创建负载平衡 RestTemplate 创建 RestTemplate @Bean 并使用 @LoadBalanced 限定符。
警告:通过自动配置不再创建 RestTemplate bean。它必须由单个应用程序创建。 @Configuration public class MyConfiguration { @LoadBalanced @Bean RestTemplate restTemplate() { return new RestTemplate(); } } public class MyClass { @Autowired private RestTemplate restTemplate; public String doOtherStuff() { String results = restTemplate.getForObject("http://stores/stores", String.class); return results; } }
URI需要使用虚拟主机名(即服务名称,而不是主机名)。Ribbon客户端用于创建完整的物理地址。有关 如何设置 RestTemplate 的详细信息,请参阅 RibbonAutoConfiguration 。
重试失败的请求
负载平衡 RestTemplate 可以配置为重试失败的请求。默认情况下,该逻辑被禁用,您可以通过将 Spring重试 添加到应用程序的类路径来启用它。负载平衡 RestTemplate 将符合与重试失败请求相关的一些Ribbon配置值。如果要在类路径中使用Spring重试来禁用重试逻辑,则可以设置 spring.cloud.loadbalancer.retry.enabled=false 。您可以使用的属性是 client.ribbon.MaxAutoRetries , client.ribbon.MaxAutoRetriesNextServer 和 client.ribbon.OkToRetryOnAllOperations 。请参阅 Ribbon文档 ,了解属性的具体内容。
项目管理
2018-07-06 09:42:00
「深度学习福利」大神带你进阶工程师,立即查看>>> 使用不同 URL。 如果你配置了不同的基础 URL 地址或者你站点的访问者使用了不同的 URL 地址来访问你的 Confluence 地址,你有很大概率可能会受到错误信息。 修改上下文地址。 如果你修改了基础 URL 地址的上下文地址,你同时也需要修改下面的配置: 停止 Confluence. 进入 Confluence 安装目录,然后编辑 \conf\server.xml 文件。 在 Context 元素中修改 path 属性,将会影响到你服务器使用的上下文。如果 Confluence 正在运行在 http://www.foobar.com/confluence 路径中,那么 path 的属性应该配置如下:
在这个示例中,我们使用 /confluence 为上下文路径。注意,你不能使用 /resources 为你的上下文路径,因为这个是 Confluence 使用的一个上下文资源路径,如果你设置这个路径的话,将会导致后续的问题。 保存文件。 重启 Confluence 服务器,然后检查使用 http://www.foobar.com/confluence 路径是否能够正常访问 Confluence。 代理(Proxies) 。 如果你的服务器允许在代理服务器的后面,请确定代理的名字与基础 URL 是相同的。例如: proxyName=" foobar.com " proxyPort="443" scheme="https" 。这个将会能够保证你的代理服务器能够想 Confluence 服务器传递正确的数据。有关更多的 Atlassian applications 代理的配置,请参考, 代理服务器配置知识库 中的内容。 这个信息需要添加到 Connector 元素中,这个元素是在 { CONFLUENCE_INSTALLATION}\conf\server.xml 中定义的。
https://www.cwiki.us/display/CONF6ZH/Configuring+the+Server+Base+URL
项目管理
2018-07-09 09:06:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
如果 Confluence 的安装是没有安装在非根目录路径(这个是上下文路径),然后服务器基础 URL 地址应该包括上下文地址。例如,你的 Confluence 正在运行在下面的地址:
http: // www.foobar.com/confluence
然后服务器基础地址应该为:
http: // www.foobar.com/confluence

https://www.cwiki.us/display/CONF6ZH/Configuring+the+Server+Base+URL
项目管理
2018-07-09 09:01:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
服务器基础地址(Server Base URL) 是用户访问 Confluence 的 URL 地址。这个基础的 URL 地址 必须 与你在浏览器中访问 Confluence 中的地址。
Confluence 将会在安装的时候自动侦测基础的 URL,但是如果你的站点 URL 修改了,或者你的 Confluence 设置成了不同的 URL 地址,这个地址与你在上面安装的时候使用的地址不同了,你需要手动你站点的基础 URL 地址进行重新设置。
你需要具有 系统管理员 权限才能进行下面的操作。
希望配置你服务器的基础 URL 地址: 选择 配置图标(cog icon) ,然后在 Confluence 管理员链接下,选择 基本配置(General Configuration) 。 在左侧的面板中选择 基本配置(General Configuration) 。 选择 编辑(Edit )。 在 服务器基础地址(Server Base URL) 文本输入框中输入新的 URL。 选择 保存(Save) 。

https://www.cwiki.us/display/CONF6ZH/Configuring+the+Server+Base+URL
项目管理
2018-07-09 08:54:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
请注意,有关站点的活动信息 在默认情况下是禁用 的。请查看 下面 的说明。
如果这个插件被启用的话,有关站点的全局活动状态将会在你的 Confluence 站点中显示出来。显示的数据包括: 在给定的时间内有多少页面和和博客内容被查看,添加或者更新。 那一个空间是最多访问的空间(最经常查看的)。 那一个空间是最活跃的(最经常编辑的)。 哪些人对系统工具最积极,包括创建和编辑内容。
希望查看你站点的活动: 在屏幕的右上角单击 控制台按钮 ,然后选择 General Configuration 链接。 在管理员界面中选择 全局活动( Global Activity )。管理员界面位于左侧的面板(这个仅在插件被启用后才能显示 - 请查看 下面 的说明)。
屏幕截图:全局活动
10 个最流行的和活动最多的页面/博客页面将会显示出来,同时也为这些页面提供了链接。
备注 Confluence Usage Stats plugin 插件提供了有关你站点的全局活动界面。这个插件的启用在大型站点中将会对站点的性能产生影响。因此这个插件 在默认情况下是禁用 的。有关这个插件对站点性能的应先可以在下面的链接中找到: USGTRK-15 。 Confluence 的系统管理员可以启用这个插件。请注意,启用这个插件将会有可能影响你站点的性能。 这个插件有时候也被成为:Confluence Usage Tracking。 如果你的 Confluence 站点是集群的话,全局活动信息将可能不可用。 在启用后,全局活动将不会显示历史数据。
https://www.cwiki.us/display/CONF6ZH/Viewing+Site+Statistics
项目管理
2018-07-09 08:54:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
awt.toolkit sun.awt.X11.XToolkit
file.encoding.pkg sun.io
java.specification.version 1.8
sun.cpu.isalist
sun.jnu.encoding ANSI_X3.4-1968
com.sun.jndi.ldap.connect.pool.maxsize 0
java.class.path /opt/atlassian/confluence/bin/bootstrap.jar
/opt/atlassian/confluence/bin/tomcat-juli.jar
java.vm.vendor Oracle Corporation
plugin.webresource.javascript.try.catch.wrapping true
sun.arch.data.model 64
sun.font.fontmanager sun.awt.X11FontManager
catalina.useNaming true
java.vendor.url http://java.oracle.com/
user.timezone America/New_York
os.name Linux
java.vm.specification.version 1.8
sun.java.launcher SUN_STANDARD
user.country US
atlassian.org.osgi.framework.bootdelegation.extra org.apache.lucene.*
sun.boot.library.path /opt/atlassian/confluence/jre/lib/amd64
sun.java.command org.apache.catalina.startup.Bootstrap start
sun.cpu.endian little
user.home /home/confluence
user.language en
java.specification.vendor Oracle Corporation
java.naming.factory.url.pkgs org.apache.naming
java.home /opt/atlassian/confluence/jre
ignore.endorsed.dirs
atlassian.plugins.startup.options
com.sun.jndi.ldap.connect.pool.protocol plain ssl
file.separator /
com.sun.jndi.ldap.connect.pool.initsize 1
atlassian.plugins.enable.wait 300
line.separator
java.vm.specification.vendor Oracle Corporation
java.specification.name Java Platform API Specification
java.awt.graphicsenv sun.awt.X11GraphicsEnvironment
java.awt.headless true
package.access sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.
package.definition sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.naming.,org.apache.tomcat.
sun.boot.class.path /opt/atlassian/confluence/jre/lib/resources.jar
/opt/atlassian/confluence/jre/lib/rt.jar
/opt/atlassian/confluence/jre/lib/sunrsasign.jar
/opt/atlassian/confluence/jre/lib/jsse.jar
/opt/atlassian/confluence/jre/lib/jce.jar
/opt/atlassian/confluence/jre/lib/charsets.jar
/opt/atlassian/confluence/jre/lib/jfr.jar
/opt/atlassian/confluence/jre/classes
jdk.tls.ephemeralDHKeySize 2048
server.loader
java.util.logging.config.file /opt/atlassian/confluence/conf/logging.properties
java.protocol.handler.pkgs org.apache.catalina.webresources
sun.management.compiler HotSpot 64-Bit Tiered Compilers
com.sun.jndi.ldap.connect.pool.authentication simple
com.sun.jndi.ldap.connect.pool.prefsize 10
java.runtime.version 1.8.0_162-b12
java.naming.factory.initial org.apache.naming.java.javaURLContextFactory
user.name confluence
path.separator :
common.loader "${catalina.base}/lib"
"${catalina.base}/lib/*.jar"
"${catalina.home}/lib"
"${catalina.home}/lib/*.jar"
os.version 3.14.32-xxxx-grs-ipv6-64
java.endorsed.dirs /opt/atlassian/confluence/jre/lib/endorsed
java.runtime.name Java(TM) SE Runtime Environment
file.encoding ANSI_X3.4-1968
org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE 32768
confluence.context.path
java.vm.name Java HotSpot(TM) 64-Bit Server VM
synchrony.enable.xhr.fallback true
java.vendor.url.bug http://bugreport.sun.com/bugreport/
java.io.tmpdir /opt/atlassian/confluence/temp
tomcat.util.scan.StandardJarScanFilter.jarsToScan log4j-web*.jar,log4j-taglib*.jar,log4javascript*.jar,slf4j-taglib*.jar
catalina.home /opt/atlassian/confluence
com.sun.jndi.ldap.connect.pool.timeout 30000
java.version 1.8.0_162
atlassian.enable.spring.strong.cache.bean.metadata.flush true
tomcat.util.scan.StandardJarScanFilter.jarsToSkip bootstrap.jar,commons-daemon.jar,tomcat-juli.jar,annotations-api.jar,el-api.jar,jsp-api.jar,servlet-api.jar,websocket-api.jar,catalina.jar,catalina-ant.jar,catalina-ha.jar,catalina-storeconfig.jar,catalina-tribes.jar,jasper.jar,jasper-el.jar,ecj-*.jar,tomcat-api.jar,tomcat-util.jar,tomcat-util-scan.jar,tomcat-coyote.jar,tomcat-dbcp.jar,tomcat-jni.jar,tomcat-websocket.jar,tomcat-i18n-en.jar,tomcat-i18n-es.jar,tomcat-i18n-fr.jar,tomcat-i18n-ja.jar,tomcat-juli-adapters.jar,catalina-jmx-remote.jar,catalina-ws.jar,tomcat-jdbc.jar,tools.jar,commons-beanutils*.jar,commons-codec*.jar,commons-collections*.jar,commons-dbcp*.jar,commons-digester*.jar,commons-fileupload*.jar,commons-httpclient*.jar,commons-io*.jar,commons-lang*.jar,commons-logging*.jar,commons-math*.jar,commons-pool*.jar,jstl.jar,taglibs-standard-spec-*.jar,geronimo-spec-jaxrpc*.jar,wsdl4j*.jar,ant.jar,ant-junit*.jar,aspectj*.jar,jmx.jar,h2*.jar,hibernate*.jar,httpclient*.jar,jmx-tools.jar,jta*.jar,log4j*.jar,mail*.jar,slf4j*.jar,xercesImpl.jar,xmlParserAPIs.jar,xml-apis.jar,junit.jar,junit-*.jar,ant-launcher.jar,cobertura-*.jar,asm-*.jar,dom4j-*.jar,icu4j-*.jar,jaxen-*.jar,jdom-*.jar,jetty-*.jar,oro-*.jar,servlet-api-*.jar,tagsoup-*.jar,xmlParserAPIs-*.jar,xom-*.jar
user.dir /opt/atlassian/confluence/bin
atlassian.enable.spring.strong.cache.bean.metadata true
os.arch amd64
java.vm.specification.name Java Virtual Machine Specification
java.awt.printerjob sun.print.PSPrinterJob
sun.os.patch.level unknown
catalina.base /opt/atlassian/confluence
shared.loader
java.util.logging.manager org.apache.juli.ClassLoaderLogManager
java.library.path /usr/java/packages/lib/amd64
/usr/lib64
/lib64
/lib
/usr/lib
java.vendor Oracle Corporation
java.vm.info mixed mode
java.vm.version 25.162-b12
hibernate.bytecode.use_reflection_optimizer true
sun.java2d.opengl true
sun.io.unicode.encoding UnicodeLittle
java.ext.dirs /opt/atlassian/confluence/jre/lib/ext
/usr/java/packages/lib/ext
tomcat.util.buf.StringCache.byte.enabled
java.class.version
true
52.0

https://www.cwiki.us/display/CONF6ZH/Viewing+Site+Statistics
项目管理
2018-07-09 08:53:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
介绍
ping是用来测试目的主机是否可达的一个程序
原理:向目的主机发送ICMP回显请求报文,并等待返回ICMP回显应答 ping客户端:发送回显请求的主机 ping服务端:被ping的主机
大部分TCP/IP实现都在内核中实现ping服务端
ICMP回显请求与应答
报文格式:
标识符:Unix采用进程id作为标识符。用来匹配ICMP回显请求与应答 序号:从0开始,每次回显请求都会+1。用来确认是否有分组丢失、重复、乱序
局域网内ping:
广域网内ping:
观察到出现高延迟和大量分组丢失情况
IP记录路由选项
作为IP首部中的选项字段,最长40字节。用来记录IP报文经过了哪些主机
通过 ping -R ,程序就会记录并使用IP记录路由选项
当经过一个路由器,它记录出口IP地址,当带该选项的回显应答回到源主机(发ping请求的主机),也会记录该主机的入口地址。通过该功能,可以发现实际路由过程中会频繁使用默认路由
IP记录路由选项的报文:
code:IP选项类型。值7代表IP记录路由选项 len:选项总字节长度。值为39 ptr:存放下一个IP地址的位置。初始化值为4,每当加入一个IP,值+4,当值为40时代表已经记录9个IP,空间已满
通过这种方式记录路由过程的问题: 不是所有主机都支持该选项。现在大部分系统都支持 记录的IP有限。由于只有40字节来记录,除开记录元信息的,最多只能记录9个IP
IP记录时间戳选项
作为IP首部中的选项字段,最长40字节。
IP记录时间戳选项的报文:
code:IP选项类型:值0x44代表IP记录时间戳选项 len:选项总字节长度。值为36或40 ptr:存放下一个时间戳的位置 OF:4位溢出字段。当路由器没有空间追加时间戳时,就增加溢出字段的值 FL:4位标志字段。不同标志描述了时间戳部分该记录哪些东西
可用FL:
该方案的问题是: 通常标志3才有意义。标志0功能太弱,标志1会导致只能放4条记录,并且可能都不是自己关心的 标志3中指定了主机,但这些主机的时间戳可能并不准确
项目管理
2018-07-09 03:09:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
这样添加golang就可以保存文件的时候自动格式化代码了
项目管理
2018-07-08 22:07:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
介绍
ICMP通常被认为是IP层的组成部分。它用来传送差错报文以及一些需要注意的信息,通常被IP层、TCP层、UDP层使用,偶尔也被用户层使用
ICMP报文
ICMP报文是放在IP数据报中进行传输
报文格式如下:
类型:有15个值,描述不同类型ICMP报文 代码:类型只是一个粗略描述,代码才是一个具体描述 校验和:是整个ICMP报文的校验和,算法与IP首部校验和算法相同
类型+代码唯一确定了ICMP报文的描述
这几种情况不会产生ICMP差错报文: ICMP差错报文 目的地址是广播地址或多播地址的IP数据报 链路层广播的数据报 不是IP分片的第一片 源地址不是单个主机的数据报
ICMP地址掩码请求与应答
ICMP地址掩码请求用于无盘系统获取自己的子网掩码,与RARP请求获取IP类似
请求和应答的报文格式:
其中标识符和序列号是发送端自定义,这些信息会随应答一起返回。发送端用这两个信息可以将请求和应答匹配起来
通过icmpaddrmask程序向目标地址发送ICMP地址掩码请求,其中140.252.13.63为子网内的广播地址
其中svr4返回的地址是错误的
向本机发送请求
其中响应的子网掩码是收到请求的接口的子网掩码,其中两个IP地址最后都是本机的环回接口处理,所以子网掩码就是127.0.0.1的
ICMP时间戳请求与应答
ICMP时间戳请求返回值是自午夜开始计算的毫秒数,利用ICMP时间戳请求,可以校正本机时间
请求与应答报文格式为:
发起时间戳:请求端填写,然后发送报文 接收时间戳:响应端接收到报文时填写 传送时间戳:响应端发送应答时填写
大部分系统后两者的值是一样的
向主机bsdi发送ICMP时间戳请求
其中有几点值得注意: 接收时间戳与传送时间戳一致 发送时间戳代表本机上的时间戳,可能需要被校准 rtt是请求往返时间,rtt/2约等于请求或应答的传输时间 difference = 接收时间戳 - 发起时间戳 sun主机需要调整本机时间 = 发起时间戳 + difference - rtt/2
ICMP端口不可达差错
当目的端口没有提供访问服务,就会报ICMP端口不可达差错
ICMP不可达报文格式:
ICMP端口不可达差错代码为3
当发送UDP数据报,但目的端口不存在,目的主机返回的报文格式:
产生差错的数据报IP首部:之所以要返回这个信息,是因为只有知道该信息,才能了解IP上层协议是什么(TCP/UDP),如何解析它 UDP首部(TCP类似):UDP首部刚好8字节,只有知道UDP首部,才能获取源端口和目的端口,然后给调用方返回足够的信息
ICMP报文的4.4BSD处理
针对ICMP报文,4.4BSD系统的处理方式:
项目管理
2018-07-08 12:58:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
一:MongoVUE无法创建collections
Mongodb新的存储引擎为wiredTiger ,在这种存储引擎下面,我们用可视化工具MongoVUE是无法看到collection的应该更换为mmapv1引擎
1、删除data文件夹,然后重新创建data
2、紧接着执行mongod --storageEngine mmapv1 --dbpath D:\office\MongoDB\data
二:MongoVUE无法使用用户名密码登录
mongodb的认证机制有2种:SCRAM-SHA-1和MONGODB-CR。3.0之后版本默认为:SCRAM-SHA-1; 2、spring-mongodb默认为:MONGODB-CR,并不支持设置认证方式; 解决方法: 修改mongodb的认证方式即可。
1、查看auth认证方式
use admin
db.system.version.findOne({"_id":"authSchema"})
(返回 { "_id" : "authSchema", "currentVersion" : 3 } currentVersion 3:MONGODB-CR currentVersion 5:SCRAM-SHA-1)
2、删除之前设置的所有用户
db.system.users.remove({})
3、删除原auth认证方式,并设置为MONGODB-CR
db.system.version.remove({})
db.system.version.insert({"_id":"authSchema","currentVersion":3})
4、重新添加admin用户(超级管理员)
use admin
db.createUser({user:"admin",pwd:"admin",roles:[{role:"readWriteAnyDatabase",db:"admin"}]})
5、新建test数据库,并为test数据库设置用户及角色(权限)
use test
db.createUser({user:"test",pwd:"test",roles:[{role:"dbOwner",db:"test"}]})
三:admin库不能查看collections
将角色改为readWriteAnyDatabase
db.updateUser("root",{roles:[{role:"readWriteAnyDatabase",db:"admin"}]})
四:开启用户验证
方式一:在命令行输入mongod --auth --logpath "D:\office\MongoDB\log.mongod.log" --dbpath "D:\office\MongoDB\data" --reinstall
方式二:在命令行输入mongod --dbpath "D:\office\MongoDB\data" --logpath "D:\office\MongoDB\log.mongod.log" --auth
五:关闭用户验证
mongod --logpath "D:\office\MongoDB\log.mongod.log" --dbpath "D:\office\MongoDB\data" --reinstall
七:忘记密码
一旦忘记admin密码 即可关闭用户验证 删除用户 重新创建
六:登录
1:mongo
2:use admin
3:db.auth("root","root")
项目管理
2018-07-08 00:17:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
介绍
RARP用来将MAC地址解析成IP地址 有盘主机的网络配置:启动时,从硬盘中读取IP并配置即可 无盘主机的网络配置:启动时,从网卡拿到MAC地址,再解析成IP地址,并完成配置
RARP分组格式
与ARP分组基本一致,差别在于RARP请求op为3,应答op为4
并且与ARP一致的是,请求是广播,应答是单播
RARP示例
当网络存在RARP服务器时:
RARP服务器会响应sun主机的IP地址,表示这是源MAC地址对应的IP地址
当网络上不存在RARP服务器时:
不断重试
项目管理
2018-07-07 18:44:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
介绍
内核知道IP也无法将数据传送到目的地址,必须知道MAC地址才能传送,所以需要ARP将IP解析为MAC地址
请求流程
DNS将主机名解析为IP地址 用IP地址建立连接 用IP地址发送IP数据包 如果目的主机在本地网络,那么IP数据报可以直接发送过去;如果目的主机在远程网络,那么IP数据报先经过路由到达本地网络的下一站路由器,让它转发 ARP用于将IP地址转换为MAC地址 广播ARP请求到该以太网所有主机 目的主机ARP层收到广播请求,识别出IP地址与自己相同,则回答ARP应答,包含IP地址与MAC地址 收到ARP应答,就可以传送IP数据报 将IP数据报发送到目的主机
ARP高速缓存
为了保证ARP高效运行,每个主机都有ARP高速缓存,存放最近IP地址到MAC地址的映射记录,一般生存时间为20min
ARP分组格式
ARP请求和应答采用相同的分组格式(下图数字单位为字节)
以太网目的地址全为1代表广播地址 帧类型:后面的数据类型,0x0806代表ARP请求或应答 硬件类型:硬件地址的类型,值为1代表以太网MAC地址 协议类型:硬件地址映射的协议地址类型,值为0x0800代表IP地址 硬件地址长度:值为6代表MAC地址长度为6字节 协议地址长度:值为4代表IP地址长度为4字节 op:四个操作类型,值1代表ARP请求,值2代表ARP应答,值3代表RARP请求,值4代表RARP应答
一个ARP请求,会将首部的以太网目的地址填为全1,表示发起一次广播,然后会将请求体中的目的以太网地址填为全0,预留出来让接收端填充
一个ARP相应,会将预留的目的以太网地址填为全0,然后将首部和请求体中的以太网目的地址和以太网源地址进行交换,并且将op改为2,发送回去 ARP请求是一次广播,ARP响应则是向请求源发起的一次单播
ARP示例
一次连接成功的ARP请求、响应
一次连接超时的ARP请求、响应
没有任何ARP以外的报文,并且超时时间指数退避
ARP代理
一个网络向另一个网络发送ARP请求的时候,中间路由器代理响应ARP请求,就叫ARP代理
常用场景是,很多网关设备支持将内网地址映射为公网地址,达到影藏内部网络的作用,这就利用了ARP代理:本来网关的实际IP为内网IP,但是需要提供公网访问IP,这时就需要开启ARP代理功能,接收目的IP为外网IP的ARP请求,并响应内网IP的MAC地址,以便将外网流量转发到内网
免费ARP
免费ARP就是主机发送ARP广播请求查找自己的IP地址。通常在系统在配置网络的时候执行
两个常用场景: 查找网络内是否存在IP冲突的主机。如果发送免费ARP,并且得到响应,说明网络内存在相同IP的主机 通知网络其他主机,本机的IP和MAC地址映射有所改变。如果主机更换网卡,MAC地址会改变,IP可能还是维持原状,这时广播一个免费ARP,可以通知其他主机自己的IP和MAC映射改变了,并让他们的ARP高速缓存及时更新
arp命令
-a显示ARP高速缓存所有内容,-d删除其中一项,-s增加一项内容(默认永久),pus和-s可以让系统开启ARP代理
项目管理
2018-07-07 18:14:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
先看下xml文件,事实上Servlet3.0开始,就可以不用配置xml文件,可以段前声明的方式来完成,看博客中另一篇文章。这里还是暂时使用下xml配置文件: Demo1 index.html index.htm index.jsp default.html default.htm default.jsp RegisterServlet com.demo1.servlet.RegisterServlet RegisterServlet /register.html ErrorServlet com.demo1.servlet.ErrorServlet ErrorServlet /error.html SuccessServlet com.demo1.servlet.SuccessServlet SuccessServlet /success.html TestServlet com.demo1.servlet.TestServlet TestServlet /test.html LoginServlet com.demo1.servlet.LoginServlet LoginServlet /login.html MemberServlet com.demo1.servlet.MemberServlet MemberServlet /member.html
其中 Login.jsp: <%@page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> 登陆页面

欢迎您

用户名:
密码:
还没注册?点击注册吧

注册页面 index.jsp: <%@page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> 注册页面

注册页面

登录名:
密码:
重复密码:
邮箱地址:
您有账号?点击直接登录

该模块中,没有使用数据库,只是简单写了一个类来模仿数据库功能,User.java: package com.demo1.java; import java.util.HashMap; import java.util.Map; public class User { private Map userMap = new HashMap(); private static User user = null; private User(){ userMap.put("韩春", "123456##abcdefg@163.com"); } public static User getInstance(){ if(user == null){ user = new User(); } return user; } public MapgetUserMap(){ return userMap; } }
下面几个为Servet文件:
RegisterServlet.java package com.demo1.servlet; import com.demo1.java.User; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class RegisterServlet extends HttpServlet { public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String userName = req.getParameter("userName"); String password = req.getParameter("password"); String conPassword = req.getParameter("conPassword"); String email = req.getParameter("email"); List errors = new ArrayList(); //装载错误信息 if(!isValidUsername(userName)){ errors.add("用户名为空或者已经存在"); } if(!isValidEmail(email)){ errors.add("无效的邮箱号码"); } if(isValidPassword(password, conPassword)){ errors.add("密码为空或者两次输入不一样"); } if(errors.isEmpty()){ User user = User.getInstance(); Map map = user.getUserMap(); map.put(userName, password+"##"+email); req.getRequestDispatcher("/success.html").forward(req, resp); }else{ req.setAttribute("errors", errors); req.getRequestDispatcher("/error.html").forward(req, resp); } } public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } public boolean isValidUsername(String username){ User user = User.getInstance(); Map map = user.getUserMap(); if(username != null){ //暂时先这样改 这里是有问题的,不能很好地判断 return true; }else{ return false; } } public boolean isValidPassword(String password, String conPassword){ return password == null || conPassword == null || password.length() < 6 || !password.equals(conPassword); } public boolean isValidEmail(String email){ boolean flag = false; if(email == null || "".equals(email)){ flag = false; }else{ flag = email.matches("^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$"); } return flag; } }
错误处理ErrorServlet.java package com.demo1.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ErrorServlet extends HttpServlet { private static final long serialVersionUID = 1l; public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); PrintWriter out = resp.getWriter(); out.println(""); out.println(""); out.println(" 新会员增加失败"); out.println(" "); out.print("

新会员增加失败

"); @SuppressWarnings("unchecked") List list = (List)req.getAttribute("errors"); if(list != null){ for(String str:list){ out.println(str + "
"); } } out.println("返回注册页面 " ); //注意这边的解析!!! out.println(" "); out.println(""); out.flush(); out.close(); } public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } }
注册验证成功 SuccessServlet.java package com.demo1.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class SuccessServlet extends HttpServlet { @SuppressWarnings("unused") private static final long serivalVersionUID = 1L; public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); PrintWriter out = resp.getWriter(); out.println(""); out.println(""); out.println(" 新会员增加成功"); out.println(" "); out.print("

新会员增加成功

"); out.println("返回登陆页面 " ); out.println(" "); out.println(""); out.flush(); out.close(); out.flush(); out.close(); } public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } }
登陆验证 LoginServlet.java package com.demo1.servlet; import java.io.IOException; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.demo1.java.User; public class LoginServlet extends HttpServlet { public static final long serialVervletUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userName = request.getParameter("userName"); String password = request.getParameter("password"); if(checkLogin(userName, password)){ request.getRequestDispatcher("/member.html").forward(request, response); }else{ response.sendRedirect("/Demo1/jsp/front/Login.jsp"); } } public boolean checkLogin(String userName, String password)throws NullPointerException{ User user = User.getInstance(); Map map = user.getUserMap(); if(userName != null && !"".equals(userName) && password != null && !"".equals(password)){ String[] arr = map.get(userName).split("##"); if(arr[0].equals(password)){ return true; } } return false; } }
最后是登陆成功的欢迎界面: package com.demo1.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MemberServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); out.println(""); out.println(""); out.println(" Welcome"); out.println(" "); out.print("

" + request.getParameter("userName")+ " 您好,欢迎您哦" + "

"); out.println(" "); out.println(""); out.flush(); out.close(); } }
注册页面时这样的:


亲,如果您感觉本文有用,请点个赞再走吧✌(>‿◠)!!
项目管理
2018-07-07 15:51:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
awt.toolkit sun.awt.X11.XToolkit
file.encoding.pkg sun.io
java.specification.version 1.8
sun.cpu.isalist
sun.jnu.encoding ANSI_X3.4-1968
com.sun.jndi.ldap.connect.pool.maxsize 0
java.class.path /opt/atlassian/confluence/bin/bootstrap.jar
/opt/atlassian/confluence/bin/tomcat-juli.jar
java.vm.vendor Oracle Corporation
plugin.webresource.javascript.try.catch.wrapping true
sun.arch.data.model 64
sun.font.fontmanager sun.awt.X11FontManager
catalina.useNaming true
java.vendor.url http://java.oracle.com/
user.timezone America/New_York
os.name Linux
java.vm.specification.version 1.8
sun.java.launcher SUN_STANDARD
user.country US
atlassian.org.osgi.framework.bootdelegation.extra org.apache.lucene.*
sun.boot.library.path /opt/atlassian/confluence/jre/lib/amd64
sun.java.command org.apache.catalina.startup.Bootstrap start
sun.cpu.endian little
user.home /home/confluence
user.language en
java.specification.vendor Oracle Corporation
java.naming.factory.url.pkgs org.apache.naming
java.home /opt/atlassian/confluence/jre
ignore.endorsed.dirs
atlassian.plugins.startup.options
com.sun.jndi.ldap.connect.pool.protocol plain ssl
file.separator /
com.sun.jndi.ldap.connect.pool.initsize 1
atlassian.plugins.enable.wait 300
line.separator
java.vm.specification.vendor Oracle Corporation
java.specification.name Java Platform API Specification
java.awt.graphicsenv sun.awt.X11GraphicsEnvironment
java.awt.headless true
package.access sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.
package.definition sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.naming.,org.apache.tomcat.
sun.boot.class.path /opt/atlassian/confluence/jre/lib/resources.jar
/opt/atlassian/confluence/jre/lib/rt.jar
/opt/atlassian/confluence/jre/lib/sunrsasign.jar
/opt/atlassian/confluence/jre/lib/jsse.jar
/opt/atlassian/confluence/jre/lib/jce.jar
/opt/atlassian/confluence/jre/lib/charsets.jar
/opt/atlassian/confluence/jre/lib/jfr.jar
/opt/atlassian/confluence/jre/classes
jdk.tls.ephemeralDHKeySize 2048
server.loader
java.util.logging.config.file /opt/atlassian/confluence/conf/logging.properties
java.protocol.handler.pkgs org.apache.catalina.webresources
sun.management.compiler HotSpot 64-Bit Tiered Compilers
com.sun.jndi.ldap.connect.pool.authentication simple
com.sun.jndi.ldap.connect.pool.prefsize 10
java.runtime.version 1.8.0_162-b12
java.naming.factory.initial org.apache.naming.java.javaURLContextFactory
user.name confluence
path.separator :
common.loader "${catalina.base}/lib"
"${catalina.base}/lib/*.jar"
"${catalina.home}/lib"
"${catalina.home}/lib/*.jar"
os.version 3.14.32-xxxx-grs-ipv6-64
java.endorsed.dirs /opt/atlassian/confluence/jre/lib/endorsed
java.runtime.name Java(TM) SE Runtime Environment
file.encoding ANSI_X3.4-1968
org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE 32768
confluence.context.path
java.vm.name Java HotSpot(TM) 64-Bit Server VM
synchrony.enable.xhr.fallback true
java.vendor.url.bug http://bugreport.sun.com/bugreport/
java.io.tmpdir /opt/atlassian/confluence/temp
tomcat.util.scan.StandardJarScanFilter.jarsToScan log4j-web*.jar,log4j-taglib*.jar,log4javascript*.jar,slf4j-taglib*.jar
catalina.home /opt/atlassian/confluence
com.sun.jndi.ldap.connect.pool.timeout 30000
java.version 1.8.0_162
atlassian.enable.spring.strong.cache.bean.metadata.flush true
tomcat.util.scan.StandardJarScanFilter.jarsToSkip bootstrap.jar,commons-daemon.jar,tomcat-juli.jar,annotations-api.jar,el-api.jar,jsp-api.jar,servlet-api.jar,websocket-api.jar,catalina.jar,catalina-ant.jar,catalina-ha.jar,catalina-storeconfig.jar,catalina-tribes.jar,jasper.jar,jasper-el.jar,ecj-*.jar,tomcat-api.jar,tomcat-util.jar,tomcat-util-scan.jar,tomcat-coyote.jar,tomcat-dbcp.jar,tomcat-jni.jar,tomcat-websocket.jar,tomcat-i18n-en.jar,tomcat-i18n-es.jar,tomcat-i18n-fr.jar,tomcat-i18n-ja.jar,tomcat-juli-adapters.jar,catalina-jmx-remote.jar,catalina-ws.jar,tomcat-jdbc.jar,tools.jar,commons-beanutils*.jar,commons-codec*.jar,commons-collections*.jar,commons-dbcp*.jar,commons-digester*.jar,commons-fileupload*.jar,commons-httpclient*.jar,commons-io*.jar,commons-lang*.jar,commons-logging*.jar,commons-math*.jar,commons-pool*.jar,jstl.jar,taglibs-standard-spec-*.jar,geronimo-spec-jaxrpc*.jar,wsdl4j*.jar,ant.jar,ant-junit*.jar,aspectj*.jar,jmx.jar,h2*.jar,hibernate*.jar,httpclient*.jar,jmx-tools.jar,jta*.jar,log4j*.jar,mail*.jar,slf4j*.jar,xercesImpl.jar,xmlParserAPIs.jar,xml-apis.jar,junit.jar,junit-*.jar,ant-launcher.jar,cobertura-*.jar,asm-*.jar,dom4j-*.jar,icu4j-*.jar,jaxen-*.jar,jdom-*.jar,jetty-*.jar,oro-*.jar,servlet-api-*.jar,tagsoup-*.jar,xmlParserAPIs-*.jar,xom-*.jar
user.dir /opt/atlassian/confluence/bin
atlassian.enable.spring.strong.cache.bean.metadata true
os.arch amd64
java.vm.specification.name Java Virtual Machine Specification
java.awt.printerjob sun.print.PSPrinterJob
sun.os.patch.level unknown
catalina.base /opt/atlassian/confluence
shared.loader
java.util.logging.manager org.apache.juli.ClassLoaderLogManager
java.library.path /usr/java/packages/lib/amd64
/usr/lib64
/lib64
/lib
/usr/lib
java.vendor Oracle Corporation
java.vm.info mixed mode
java.vm.version 25.162-b12
hibernate.bytecode.use_reflection_optimizer true
sun.java2d.opengl true
sun.io.unicode.encoding UnicodeLittle
java.ext.dirs /opt/atlassian/confluence/jre/lib/ext
/usr/java/packages/lib/ext
tomcat.util.buf.StringCache.byte.enabled
java.class.version
true
52.0

https://www.cwiki.us/display/CONF6ZH/Viewing+Site+Statistics
项目管理
2018-07-07 04:50:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
当你添加了内存,设置了代理(proxy)或者修改了 Java 的选项,通常比较难判断系统是否已经按照你的修改进行了配置和启动。这个页面将会帮助你查看 Confluence 站点运行使用的系统属性。
你可以在 系统信息(System Information)界面中扩展系统的属性,这个配置是在 Confluence 的管理员控制台中配置。在查询系统信息之前,你不需要重新启动 Confluence 服务器。
希望查看有关你 Confluence 的系统属性: 在屏幕的右上角单击 控制台按钮 ,然后选择 General Configuration 链接。 在左侧面板中选择 系统信息(System Information) 。 滚动鼠标到下面的 系统属性(System Properties) 部分进行查看。

https://www.cwiki.us/display/CONF6ZH/Viewing+System+Properties
项目管理
2018-07-07 03:31:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
最近公司的微服务maven分模块一个父工程多个子工程
因为子工程依赖父工程,直接对其某个子工程进行maven clean后maven install,,,install失败
提示在本地仓库中,找不到父工程的.jar这个包......
但是当自己去本地仓库找的时候,发现有这个父工程.jar
原来在对maven 聚合工程的单独子工程打包前,,先对父工程 进行maven clean 后maven install.....
大家有遇到这个坑没????
项目管理
2018-07-04 23:22:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
maven依赖


com.github.ulisesbocchio
jasypt-spring-boot-starter
1.8

配置加密参数(可以理解为加密的salt)
jasypt:
encryptor:
password: 123456(这个可以随便设置的,每次设置时数据库的接连驱动要是明文(也就是不加密的,否则运行起来报错))
写一个测试方法,这里直接在单元测试里面来实现给密码加密,得到字符串密码
@Autowired StringEncryptor stringEncryptor;
@Test public void encryptPwd() {
//调用加密方法
String result = stringEncryptor.encrypt("yourpassword"); System.out.println("==================");
System.out.println(result);
//调用解密方法
String test=stringEncryptor.decrypt(result)
System.out.println(test);
System.out.println("==================");
}
把得到的密文写到需要使用到的地方,加密后的字符串需要放到ENC里面,格式如下:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&tinyInt1isBit=false
username: root
password: ENC(4TyrSSgQd2DCHnXVwkdKMQ==)
driver-class-name: com.mysql.jdbc.Driver
通过命令行运行 jasypt-1.9.2.jar 包命令来加密解密:
在jar包所在目录打开命令行,运行如下加密命令:
java -cp jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="root" password=security algorithm=PBEWithMD5AndDES
这里input输入的可以对数据库的用户名进行加密也可以是数据库的密码进行加密
运行结果如下(这种加密每次得到的密文都是不一样的)
使用刚才加密出来的结果进行解密,执行如下解密命令:
java -cp jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI input="i00VogiiZ1FpZR9McY7XNw==" password=security algorithm=PBEWithMD5AndDES
结果如下


项目管理
2018-07-04 23:10:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
yii版本2.0.15
从入口文件开始,首先 定义全局常量 注册composer自动加载器 包含Yii类文件 加载应用配置 引导启动,调用应用主体并配置来处理请求(也就是run方法)
1. 定义全局常量
例如定义是否开启 debug 模式,是调试环境还是正式环境,根据需要可定义自己的常量。 defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev');
2. 注册composer自动加载器
composer自动加载:自动加载扩展类,及扩展类依赖另一个类,有自己的自动加载规则。
3. Yii类文件
注册Yii自动加载器,配置Yii核心类映射表,当用到某类的时候不需要检验该类咯,如果类映射表中有该类就直接引入了,是Yii的一种机制呐,要想预加载类可以配置自己的类别名。例如:urlManager路由解析组件、异常组件、MySQL PDO组件等等。注册依赖注入容器(DI)和服务定位容器。Yii也可以自动加载扩展类,前提是需要符合Composer自动加载规则。
4. 引入应用主体配置文件
配置文件主要配置应用主体属性 /yourpath/config/web.php 都是以数组形式定义的,在当前配置中又分子文件配置,职责划分了。例如数据配置文件、如何加载控制器、临时文件存储地址、邮箱配置文件、参数配置文件等,配置文件发挥着重要作用它会影响整个应用主体行为。
5. 引导启动,应用主体实例化并配置
主要是加载配置,创建应用主体实例,注册错误机制,路由解析到引导程序开始运行应用。处理当前行为前置行为执行当前行为在执行后置行为发送响应。入口脚本接收应用主体传来退出状态并完成请求。
参考文献
Yii2.0权威指南
Yii2.0 源代码
项目管理
2018-07-04 22:10:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
当前一个正在运行的 Confluence 6 实例的内存使用情况


https://www.cwiki.us/display/CONF6ZH/Viewing+System+Information
项目管理
2018-07-04 22:04:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
系统信息界面提供了有关 Confluence 的配置信息和 Confluence 部署的环境信息。
希望对你的系统信息进行查看: 在屏幕的右上角单击 控制台按钮 ,然后选择 General Configuration 链接。 在左侧的面板中选择选择 系统信息(System Information) 。
备注: 便捷的 内存图片( memory graph )能够帮助你查看 Conference 的内存使用情况。 当你在 Confluence 的时候如果出现了错误,你的系统信息能够帮助 Atlassian Support 诊断你遇到的问题。当登录进入 支持请求(support request) 或者 缺陷报告(bug report) 的时候,请尽可能多的提供你安装信息和环境。
https://www.cwiki.us/display/CONF6ZH/Viewing+System+Information
项目管理
2018-07-04 21:54:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
公众平台服务号、订阅号、企业号的相关说明
1、订阅号:主要偏于为用户传达资讯(类似报纸杂志),认证前后都是每天只可以群发一条消息;
2、服务号:主要偏于服务交互(类似银行,114,提供服务查询),认证前后都是每个月可群发4条消息;
3、企业号:主要用于公司内部通讯使用,需要先验证身份才可以关注成功企业号。

温馨提示:
1)如果想简单的发送消息,达到宣传效果,建议可选择订阅号;
2)如果想用公众号获得更多的功能,例如开通微信支付,建议可以选择服务号;
3)如果想用来管理内部企业员工、团队,对内使用,可申请企业号;
4)订阅号可通过微信认证资质审核通过后有一次升级为服务号的入口,升级成功后类型不可再变;
5)服务号不可变更成订阅号。
图例说明:
本文转载自腾讯官方说明: 公众平台服务号、订阅号、企业号的相关说明

亲,如果您感觉本文有用,请点个赞再走吧✌(>‿◠)!!
项目管理
2018-07-04 11:25:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
昨天遇到个读取图片问题,在 ImageIO.read读取大部分图片时候没有问题,可是遇到个别的gif读取就报错了: ArrayIndexOutOfBoundsException

google一番,发现这是jdk6~8历史遗留问题。。。。。。差点翻车了
个别的gif很顽强!
附上链接: https://blog.csdn.net/clive_hua/article/details/77610591 , https://www.jianshu.com/p/18888311fc9e
------------------------------------------华丽的解决分界线------------------------------------
成功读取了gif,嘿嘿。
附上解决代码:
/** * 从博客中获取用于微信分享的图片链接:大小要求300x300 * @param htmlContent * @param id 博客ID * @return */ public static String getImageForWechatShare(String htmlContent, long id) { String originImageUrl = "https://static.oschina.net/uploads/space/2017/0606/104418_CPLl_2733728.png"; if (StringUtils.isNotBlank(htmlContent)) { Document document = Jsoup.parse(htmlContent); Elements elements = document.select("img[src~=(?i)\\.(gif|png|bmp|svg|jpe?g)]"); if (null == elements) { return originImageUrl; } if(elements.size() == 0) { return originImageUrl; } try { for(int i = 0; i < elements.size(); i++) { String imageUrl = elements.get(i).attr("src"); if(GIF.equalsIgnoreCase(ImageUtils.getSuffix(imageUrl))){ return readGif(originImageUrl,imageUrl,id); } HttpClient httpClient = HttpClients.createDefault(); RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(1000).setConnectionRequestTimeout(1000).setSocketTimeout(1000).build(); HttpGet httpGet = new HttpGet(imageUrl); httpGet.setConfig(requestConfig); HttpResponse response = httpClient.execute(httpGet); BufferedImage image = ImageIO.read(response.getEntity().getContent()); if (image.getWidth() > 300 && image.getHeight() > 300) { CacheMgr.set(Blog.CACHE_BLOGS_FIRST_IMAGE,String.valueOf(id),imageUrl); return imageUrl; }else{ return uploadToUp(originImageUrl,imageUrl,id); } } } catch (Exception e) { return originImageUrl; } } return originImageUrl; } /** * 读取gif * * @param originImageUrl osc 300*300 LOGO * @param imageUrl 博客第一张图片 * @param id 博客ID * @return */ public static String readGif(String originImageUrl,String imageUrl,long id) { GifDecoder.GifImage gif = null; try { gif = GifDecoder.read(getImageFromNetByUrl(imageUrl)); System.out.println(String.format("gif url:%s,width:%d,height:%d",imageUrl,gif.getWidth(),gif.getHeight())); } catch (IOException e) { return originImageUrl; } if (gif.getWidth() > 300 && gif.getHeight() > 300) { CacheMgr.set(Blog.CACHE_BLOGS_FIRST_IMAGE,String.valueOf(id),imageUrl); return imageUrl; }else{ return uploadToUp(originImageUrl,imageUrl,id); } } /** * 上传图片至又拍云 * * @param originImageUrl osc 300*300 LOGO * @param imageUrl 博客第一张图片 * @param id 博客ID * @return */ public static String uploadToUp(String originImageUrl,String imageUrl,long id){ try { imageUrl = ImageUtils.ME.upload("wx-share-blog.jpg", getImageFromNetByUrl(imageUrl)); } catch (Exception e) { return originImageUrl; } imageUrl += "!/both/300x300"; CacheMgr.set(Blog.CACHE_BLOGS_FIRST_IMAGE,String.valueOf(id),imageUrl); return imageUrl; } /** * 根据地址获得数据的字节流 * @param strUrl 网络连接地址 * @return */ public static byte[] getImageFromNetByUrl(String strUrl){ try { URL url = new URL(strUrl); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5 * 1000); InputStream inStream = conn.getInputStream(); byte[] btImg = readInputStream(inStream); return btImg; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 从输入流中获取数据 * @param inStream 输入流 * @return * @throws Exception */ public static byte[] readInputStream(InputStream inStream) throws Exception{ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while( (len=inStream.read(buffer)) != -1 ){ outStream.write(buffer, 0, len); } inStream.close(); return outStream.toByteArray(); }
获取图片后缀: public static String getSuffix(String name) { Pattern pat = Pattern.compile("[\\w]+[\\.](" + SUFFIXES + ")");// 正则判断 Matcher mc = pat.matcher(name.toLowerCase());// 条件匹配 String fileName = null; while (mc.find()) { fileName = mc.group();// 截取文件名后缀名 } if (fileName != null) { return fileName.substring(fileName.lastIndexOf(".") + 1); } return null; }
GifDecoder.java代码: import static java.lang.System.arraycopy; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; /* * Copyright 2014 Dhyan Blum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** *

* A decoder capable of processing a GIF data stream to render the graphics * contained in it. This implementation follows the official * GIF * specification. *

* *

* Example usage: *

* *

* *

 * final GifImage gifImage = GifDecoder.read(int[] data); * final int width = gifImage.getWidth(); * final int height = gifImage.getHeight(); * final int frameCount = gifImage.getFrameCount(); * for (int i = 0; i < frameCount; i++) { * final BufferedImage image = gifImage.getFrame(i); * final int delay = gif.getDelay(i); * } * 
* *

* * @author Dhyan Blum * @version 1.09 November 2017 * */ public final class GifDecoder { static final class BitReader { private int bitPos; // Next bit to read private int numBits; // Number of bits to read private int bitMask; // Use to kill unwanted higher bits private byte[] in; // Data array // To avoid costly bounds checks, 'in' needs 2 more 0-bytes at the end private final void init(final byte[] in) { this.in = in; bitPos = 0; } private final int read() { // Byte indices: (bitPos / 8), (bitPos / 8) + 1, (bitPos / 8) + 2 int i = bitPos >>> 3; // Byte = bit / 8 // Bits we'll shift to the right, AND 7 is the same as MODULO 8 final int rBits = bitPos & 7; // Byte 0 to 2, AND to get their unsigned values final int b0 = in[i++] & 0xFF, b1 = in[i++] & 0xFF, b2 = in[i] & 0xFF; // Glue the bytes together, don't do more shifting than necessary final int buf = ((b2 << 8 | b1) << 8 | b0) >>> rBits; bitPos += numBits; return buf & bitMask; // Kill the unwanted higher bits } private final void setNumBits(final int numBits) { this.numBits = numBits; bitMask = (1 << numBits) - 1; } } static final class CodeTable { private final int[][] tbl; // Maps codes to lists of colors private int initTableSize; // Number of colors +2 for CLEAR + EOI private int initCodeSize; // Initial code size private int initCodeLimit; // First code limit private int codeSize; // Current code size, maximum is 12 bits private int nextCode; // Next available code for a new entry private int nextCodeLimit; // Increase codeSize when nextCode == limit private BitReader br; // Notify when code sizes increases public CodeTable() { tbl = new int[4096][1]; } private final int add(final int[] indices) { if (nextCode < 4096) { if (nextCode == nextCodeLimit && codeSize < 12) { codeSize++; // Max code size is 12 br.setNumBits(codeSize); nextCodeLimit = (1 << codeSize) - 1; // 2^codeSize - 1 } tbl[nextCode++] = indices; } return codeSize; } private final int clear() { codeSize = initCodeSize; br.setNumBits(codeSize); nextCodeLimit = initCodeLimit; nextCode = initTableSize; // Don't recreate table, reset pointer return codeSize; } private final void init(final GifFrame fr, final int[] activeColTbl, final BitReader br) { this.br = br; final int numColors = activeColTbl.length; initCodeSize = fr.firstCodeSize; initCodeLimit = (1 << initCodeSize) - 1; // 2^initCodeSize - 1 initTableSize = fr.endOfInfoCode + 1; nextCode = initTableSize; for (int c = numColors - 1; c >= 0; c--) { tbl[c][0] = activeColTbl[c]; // Translated color } // A gap may follow with no colors assigned if numCols < CLEAR tbl[fr.clearCode] = new int[] { fr.clearCode }; // CLEAR tbl[fr.endOfInfoCode] = new int[] { fr.endOfInfoCode }; // EOI // Locate transparent color in code table and set to 0 if (fr.transpColFlag && fr.transpColIndex < numColors) { tbl[fr.transpColIndex][0] = 0; } } } final class GifFrame { // Graphic control extension (optional) // Disposal: 0=NO_ACTION, 1=NO_DISPOSAL, 2=RESTORE_BG, 3=RESTORE_PREV private int disposalMethod; // 0-3 as above, 4-7 undefined private boolean transpColFlag; // 1 Bit private int delay; // Unsigned, LSByte first, n * 1/100 * s private int transpColIndex; // 1 Byte // Image descriptor private int x; // Position on the canvas from the left private int y; // Position on the canvas from the top private int w; // May be smaller than the base image private int h; // May be smaller than the base image private int wh; // width * height private boolean hasLocColTbl; // Has local color table? 1 Bit private boolean interlaceFlag; // Is an interlace image? 1 Bit @SuppressWarnings("unused") private boolean sortFlag; // True if local colors are sorted, 1 Bit private int sizeOfLocColTbl; // Size of the local color table, 3 Bits private int[] localColTbl; // Local color table (optional) // Image data private int firstCodeSize; // LZW minimum code size + 1 for CLEAR & EOI private int clearCode; private int endOfInfoCode; private byte[] data; // Holds LZW encoded data private BufferedImage img; // Full drawn image, not just the frame area } public final class GifImage { public String header; // Bytes 0-5, GIF87a or GIF89a private int w; // Unsigned 16 Bit, least significant byte first private int h; // Unsigned 16 Bit, least significant byte first private int wh; // Image width * image height public boolean hasGlobColTbl; // 1 Bit public int colorResolution; // 3 Bits public boolean sortFlag; // True if global colors are sorted, 1 Bit public int sizeOfGlobColTbl; // 2^(val(3 Bits) + 1), see spec public int bgColIndex; // Background color index, 1 Byte public int pxAspectRatio; // Pixel aspect ratio, 1 Byte public int[] globalColTbl; // Global color table private final List frames = new ArrayList(64); public String appId = ""; // 8 Bytes at in[i+3], usually "NETSCAPE" public String appAuthCode = ""; // 3 Bytes at in[i+11], usually "2.0" public int repetitions = 0; // 0: infinite loop, N: number of loops private BufferedImage img = null; // Currently drawn frame private int[] prevPx = null; // Previous frame's pixels private final BitReader bits = new BitReader(); private final CodeTable codes = new CodeTable(); private Graphics2D g; private final int[] decode(final GifFrame fr, final int[] activeColTbl) { codes.init(fr, activeColTbl, bits); bits.init(fr.data); // Incoming codes final int clearCode = fr.clearCode, endCode = fr.endOfInfoCode; final int[] out = new int[wh]; // Target image pixel array final int[][] tbl = codes.tbl; // Code table int outPos = 0; // Next pixel position in the output image array codes.clear(); // Init code table bits.read(); // Skip leading clear code int code = bits.read(); // Read first code int[] pixels = tbl[code]; // Output pixel for first code arraycopy(pixels, 0, out, outPos, pixels.length); outPos += pixels.length; try { while (true) { final int prevCode = code; code = bits.read(); // Get next code in stream if (code == clearCode) { // After a CLEAR table, there is codes.clear(); // no previous code, we need to read code = bits.read(); // a new one pixels = tbl[code]; // Output pixels arraycopy(pixels, 0, out, outPos, pixels.length); outPos += pixels.length; continue; // Back to the loop with a valid previous code } else if (code == endCode) { break; } final int[] prevVals = tbl[prevCode]; final int[] prevValsAndK = new int[prevVals.length + 1]; arraycopy(prevVals, 0, prevValsAndK, 0, prevVals.length); if (code < codes.nextCode) { // Code table contains code pixels = tbl[code]; // Output pixels arraycopy(pixels, 0, out, outPos, pixels.length); outPos += pixels.length; prevValsAndK[prevVals.length] = tbl[code][0]; // K } else { prevValsAndK[prevVals.length] = prevVals[0]; // K arraycopy(prevValsAndK, 0, out, outPos, prevValsAndK.length); outPos += prevValsAndK.length; } codes.add(prevValsAndK); // Previous indices + K } } catch (final ArrayIndexOutOfBoundsException e) { } return out; } private final int[] deinterlace(final int[] src, final GifFrame fr) { final int w = fr.w, h = fr.h, wh = fr.wh; final int[] dest = new int[src.length]; // Interlaced images are organized in 4 sets of pixel lines final int set2Y = (h + 7) >>> 3; // Line no. = ceil(h/8.0) final int set3Y = set2Y + ((h + 3) >>> 3); // ceil(h-4/8.0) final int set4Y = set3Y + ((h + 1) >>> 2); // ceil(h-2/4.0) // Sets' start indices in source array final int set2 = w * set2Y, set3 = w * set3Y, set4 = w * set4Y; // Line skips in destination array final int w2 = w << 1, w4 = w2 << 1, w8 = w4 << 1; // Group 1 contains every 8th line starting from 0 int from = 0, to = 0; for (; from < set2; from += w, to += w8) { arraycopy(src, from, dest, to, w); } // Group 2 contains every 8th line starting from 4 for (to = w4; from < set3; from += w, to += w8) { arraycopy(src, from, dest, to, w); } // Group 3 contains every 4th line starting from 2 for (to = w2; from < set4; from += w, to += w4) { arraycopy(src, from, dest, to, w); } // Group 4 contains every 2nd line starting from 1 (biggest group) for (to = w; from < wh; from += w, to += w2) { arraycopy(src, from, dest, to, w); } return dest; // All pixel lines have now been rearranged } private final void drawFrame(final GifFrame fr) { // Determine the color table that will be active for this frame final int[] activeColTbl = fr.hasLocColTbl ? fr.localColTbl : globalColTbl; // Get pixels from data stream int[] pixels = decode(fr, activeColTbl); if (fr.interlaceFlag) { pixels = deinterlace(pixels, fr); // Rearrange pixel lines } // Create image of type 2=ARGB for frame area final BufferedImage frame = new BufferedImage(fr.w, fr.h, 2); arraycopy(pixels, 0, ((DataBufferInt) frame.getRaster().getDataBuffer()).getData(), 0, fr.wh); // Draw frame area on top of working image g.drawImage(frame, fr.x, fr.y, null); // Visualize frame boundaries during testing // if (DEBUG_MODE) { // if (prev != null) { // g.setColor(Color.RED); // Previous frame color // g.drawRect(prev.x, prev.y, prev.w - 1, prev.h - 1); // } // g.setColor(Color.GREEN); // New frame color // g.drawRect(fr.x, fr.y, fr.w - 1, fr.h - 1); // } // Keep one copy as "previous frame" in case we need to restore it prevPx = new int[wh]; arraycopy(((DataBufferInt) img.getRaster().getDataBuffer()).getData(), 0, prevPx, 0, wh); // Create another copy for the end user to not expose internal state fr.img = new BufferedImage(w, h, 2); // 2 = ARGB arraycopy(prevPx, 0, ((DataBufferInt) fr.img.getRaster().getDataBuffer()).getData(), 0, wh); // Handle disposal of current frame if (fr.disposalMethod == 2) { // Restore to background color (clear frame area only) g.clearRect(fr.x, fr.y, fr.w, fr.h); } else if (fr.disposalMethod == 3 && prevPx != null) { // Restore previous frame arraycopy(prevPx, 0, ((DataBufferInt) img.getRaster().getDataBuffer()).getData(), 0, wh); } } /** * Returns the background color of the first frame in this GIF image. If * the frame has a local color table, the returned color will be from * that table. If not, the color will be from the global color table. * Returns 0 if there is neither a local nor a global color table. * * @param index * Index of the current frame, 0 to N-1 * @return 32 bit ARGB color in the form 0xAARRGGBB */ public final int getBackgroundColor() { final GifFrame frame = frames.get(0); if (frame.hasLocColTbl) { return frame.localColTbl[bgColIndex]; } else if (hasGlobColTbl) { return globalColTbl[bgColIndex]; } return 0; } /** * If not 0, the delay specifies how many hundredths (1/100) of a second * to wait before displaying the frame after the current frame. * * @param index * Index of the current frame, 0 to N-1 * @return Delay as number of hundredths (1/100) of a second */ public final int getDelay(final int index) { return frames.get(index).delay; } /** * @param index * Index of the frame to return as image, starting from 0. * For incremental calls such as [0, 1, 2, ...] the method's * run time is O(1) as only one frame is drawn per call. For * random access calls such as [7, 12, ...] the run time is * O(N+1) with N being the number of previous frames that * need to be drawn before N+1 can be drawn on top. Once a * frame has been drawn it is being cached and the run time * is more or less O(0) to retrieve it from the list. * @return A BufferedImage for the specified frame. */ public final BufferedImage getFrame(final int index) { if (img == null) { // Init img = new BufferedImage(w, h, 2); // 2 = ARGB g = img.createGraphics(); g.setBackground(new Color(0, true)); // Transparent color } GifFrame fr = frames.get(index); if (fr.img == null) { // Draw all frames until and including the requested frame for (int i = 0; i <= index; i++) { fr = frames.get(i); if (fr.img == null) { drawFrame(fr); } } } return fr.img; } /** * @return The number of frames contained in this GIF image */ public final int getFrameCount() { return frames.size(); } /** * @return The height of the GIF image */ public final int getHeight() { return h; } /** * @return The width of the GIF image */ public final int getWidth() { return w; } } static final boolean DEBUG_MODE = false; /** * @param in * Raw image data as a byte[] array * @return A GifImage object exposing the properties of the GIF image. * @throws IOException * If the image violates the GIF specification or is truncated. */ public static final GifImage read(final byte[] in) throws IOException { final GifDecoder decoder = new GifDecoder(); final GifImage img = decoder.new GifImage(); GifFrame frame = null; // Currently open frame int pos = readHeader(in, img); // Read header, get next byte position pos = readLogicalScreenDescriptor(img, in, pos); if (img.hasGlobColTbl) { img.globalColTbl = new int[img.sizeOfGlobColTbl]; pos = readColTbl(in, img.globalColTbl, pos); } while (pos < in.length) { final int block = in[pos] & 0xFF; switch (block) { case 0x21: // Extension introducer if (pos + 1 >= in.length) { throw new IOException("Unexpected end of file."); } switch (in[pos + 1] & 0xFF) { case 0xFE: // Comment extension pos = readTextExtension(in, pos); break; case 0xFF: // Application extension pos = readAppExt(img, in, pos); break; case 0x01: // Plain text extension frame = null; // End of current frame pos = readTextExtension(in, pos); break; case 0xF9: // Graphic control extension if (frame == null) { frame = decoder.new GifFrame(); img.frames.add(frame); } pos = readGraphicControlExt(frame, in, pos); break; default: throw new IOException("Unknown extension at " + pos); } break; case 0x2C: // Image descriptor if (frame == null) { frame = decoder.new GifFrame(); img.frames.add(frame); } pos = readImgDescr(frame, in, pos); if (frame.hasLocColTbl) { frame.localColTbl = new int[frame.sizeOfLocColTbl]; pos = readColTbl(in, frame.localColTbl, pos); } pos = readImgData(frame, in, pos); frame = null; // End of current frame break; case 0x3B: // GIF Trailer return img; // Found trailer, finished reading. default: // Unknown block. The image is corrupted. Strategies: a) Skip // and wait for a valid block. Experience: It'll get worse. b) // Throw exception. c) Return gracefully if we are almost done // processing. The frames we have so far should be error-free. final double progress = 1.0 * pos / in.length; if (progress < 0.9) { throw new IOException("Unknown block at: " + pos); } pos = in.length; // Exit loop } } return img; } /** * @param is * Image data as input stream. This method will read from the * input stream's current position. It will not reset the * position before reading and won't reset or close the stream * afterwards. Call these methods before and after calling this * method as needed. * @return A GifImage object exposing the properties of the GIF image. * @throws IOException * If an I/O error occurs, the image violates the GIF * specification or the GIF is truncated. */ public static final GifImage read(final InputStream is) throws IOException { final byte[] data = new byte[is.available()]; is.read(data, 0, data.length); return read(data); } /** * @param ext * Empty application extension object * @param in * Raw data * @param i * Index of the first byte of the application extension * @return Index of the first byte after this extension */ static final int readAppExt(final GifImage img, final byte[] in, int i) { img.appId = new String(in, i + 3, 8); // should be "NETSCAPE" img.appAuthCode = new String(in, i + 11, 3); // should be "2.0" i += 14; // Go to sub-block size, it's value should be 3 final int subBlockSize = in[i] & 0xFF; // The only app extension widely used is NETSCAPE, it's got 3 data bytes if (subBlockSize == 3) { // in[i+1] should have value 01, in[i+5] should be block terminator img.repetitions = in[i + 2] & 0xFF | in[i + 3] & 0xFF << 8; // Short return i + 5; } // Skip unknown application extensions while ((in[i] & 0xFF) != 0) { // While sub-block size != 0 i += (in[i] & 0xFF) + 1; // Skip to next sub-block } return i + 1; } /** * @param in * Raw data * @param colors * Pre-initialized target array to store ARGB colors * @param i * Index of the color table's first byte * @return Index of the first byte after the color table */ static final int readColTbl(final byte[] in, final int[] colors, int i) { final int numColors = colors.length; for (int c = 0; c < numColors; c++) { final int a = 0xFF; // Alpha 255 (opaque) final int r = in[i++] & 0xFF; // 1st byte is red final int g = in[i++] & 0xFF; // 2nd byte is green final int b = in[i++] & 0xFF; // 3rd byte is blue colors[c] = ((a << 8 | r) << 8 | g) << 8 | b; } return i; } /** * @param ext * Graphic control extension object * @param in * Raw data * @param i * Index of the extension introducer * @return Index of the first byte after this block */ static final int readGraphicControlExt(final GifFrame fr, final byte[] in, final int i) { fr.disposalMethod = (in[i + 3] & 0b00011100) >>> 2; // Bits 4-2 fr.transpColFlag = (in[i + 3] & 1) == 1; // Bit 0 fr.delay = in[i + 4] & 0xFF | (in[i + 5] & 0xFF) << 8; // 16 bit LSB fr.transpColIndex = in[i + 6] & 0xFF; // Byte 6 return i + 8; // Skipped byte 7 (blockTerminator), as it's always 0x00 } /** * @param in * Raw data * @param img * The GifImage object that is currently read * @return Index of the first byte after this block * @throws IOException * If the GIF header/trailer is missing, incomplete or unknown */ static final int readHeader(final byte[] in, final GifImage img) throws IOException { if (in.length < 6) { // Check first 6 bytes throw new IOException("Image is truncated."); } img.header = new String(in, 0, 6); if (!img.header.equals("GIF87a") && !img.header.equals("GIF89a")) { throw new IOException("Invalid GIF header."); } return 6; } /** * @param fr * The GIF frame to whom this image descriptor belongs * @param in * Raw data * @param i * Index of the first byte of this block, i.e. the minCodeSize * @return */ static final int readImgData(final GifFrame fr, final byte[] in, int i) { final int fileSize = in.length; final int minCodeSize = in[i++] & 0xFF; // Read code size, go to block final int clearCode = 1 << minCodeSize; // CLEAR = 2^minCodeSize fr.firstCodeSize = minCodeSize + 1; // Add 1 bit for CLEAR and EOI fr.clearCode = clearCode; fr.endOfInfoCode = clearCode + 1; final int imgDataSize = readImgDataSize(in, i); final byte[] imgData = new byte[imgDataSize + 2]; int imgDataPos = 0; int subBlockSize = in[i] & 0xFF; while (subBlockSize > 0) { // While block has data try { // Next line may throw exception if sub-block size is fake final int nextSubBlockSizePos = i + subBlockSize + 1; final int nextSubBlockSize = in[nextSubBlockSizePos] & 0xFF; arraycopy(in, i + 1, imgData, imgDataPos, subBlockSize); imgDataPos += subBlockSize; // Move output data position i = nextSubBlockSizePos; // Move to next sub-block size subBlockSize = nextSubBlockSize; } catch (final Exception e) { // Sub-block exceeds file end, only use remaining bytes subBlockSize = fileSize - i - 1; // Remaining bytes arraycopy(in, i + 1, imgData, imgDataPos, subBlockSize); imgDataPos += subBlockSize; // Move output data position i += subBlockSize + 1; // Move to next sub-block size break; } } fr.data = imgData; // Holds LZW encoded data i++; // Skip last sub-block size, should be 0 return i; } static final int readImgDataSize(final byte[] in, int i) { final int fileSize = in.length; int imgDataPos = 0; int subBlockSize = in[i] & 0xFF; while (subBlockSize > 0) { // While block has data try { // Next line may throw exception if sub-block size is fake final int nextSubBlockSizePos = i + subBlockSize + 1; final int nextSubBlockSize = in[nextSubBlockSizePos] & 0xFF; imgDataPos += subBlockSize; // Move output data position i = nextSubBlockSizePos; // Move to next sub-block size subBlockSize = nextSubBlockSize; } catch (final Exception e) { // Sub-block exceeds file end, only use remaining bytes subBlockSize = fileSize - i - 1; // Remaining bytes imgDataPos += subBlockSize; // Move output data position break; } } return imgDataPos; } /** * @param fr * The GIF frame to whom this image descriptor belongs * @param in * Raw data * @param i * Index of the image separator, i.e. the first block byte * @return Index of the first byte after this block */ static final int readImgDescr(final GifFrame fr, final byte[] in, int i) { fr.x = in[++i] & 0xFF | (in[++i] & 0xFF) << 8; // Byte 1-2: left fr.y = in[++i] & 0xFF | (in[++i] & 0xFF) << 8; // Byte 3-4: top fr.w = in[++i] & 0xFF | (in[++i] & 0xFF) << 8; // Byte 5-6: width fr.h = in[++i] & 0xFF | (in[++i] & 0xFF) << 8; // Byte 7-8: height fr.wh = fr.w * fr.h; final byte b = in[++i]; // Byte 9 is a packed byte fr.hasLocColTbl = (b & 0b10000000) >>> 7 == 1; // Bit 7 fr.interlaceFlag = (b & 0b01000000) >>> 6 == 1; // Bit 6 fr.sortFlag = (b & 0b00100000) >>> 5 == 1; // Bit 5 final int colTblSizePower = (b & 7) + 1; // Bits 2-0 fr.sizeOfLocColTbl = 1 << colTblSizePower; // 2^(N+1), As per the spec return ++i; } /** * @param img * @param i * Start index of this block. * @return Index of the first byte after this block. */ static final int readLogicalScreenDescriptor(final GifImage img, final byte[] in, final int i) { img.w = in[i] & 0xFF | (in[i + 1] & 0xFF) << 8; // 16 bit, LSB 1st img.h = in[i + 2] & 0xFF | (in[i + 3] & 0xFF) << 8; // 16 bit img.wh = img.w * img.h; final byte b = in[i + 4]; // Byte 4 is a packed byte img.hasGlobColTbl = (b & 0b10000000) >>> 7 == 1; // Bit 7 final int colResPower = ((b & 0b01110000) >>> 4) + 1; // Bits 6-4 img.colorResolution = 1 << colResPower; // 2^(N+1), As per the spec img.sortFlag = (b & 0b00001000) >>> 3 == 1; // Bit 3 final int globColTblSizePower = (b & 7) + 1; // Bits 0-2 img.sizeOfGlobColTbl = 1 << globColTblSizePower; // 2^(N+1), see spec img.bgColIndex = in[i + 5] & 0xFF; // 1 Byte img.pxAspectRatio = in[i + 6] & 0xFF; // 1 Byte return i + 7; } /** * @param in * Raw data * @param pos * Index of the extension introducer * @return Index of the first byte after this block */ static final int readTextExtension(final byte[] in, final int pos) { int i = pos + 2; // Skip extension introducer and label int subBlockSize = in[i++] & 0xFF; while (subBlockSize != 0 && i < in.length) { i += subBlockSize; subBlockSize = in[i++] & 0xFF; } return i; } }
-----ps:微信分享博客,需要300*300以上的图片。。。闹心
项目管理
2018-07-04 11:07:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
码云、GitHub上有个很方便的功能叫fork,将别人的工程一键复制到自己账号下。这个功能很方便,但有点不足的是,当源项目更新后,你fork的分支并不会一起更新,需要自己手动去更新(并且因为要保留自己修改后的代码,更不可使用强制更新的方法)。
命令行方法
1、在本地装好Git客户端,或者GitHub客户端
2、clone 自己的fork分支到本地,可以直接使用github客户端,clone到本地,如果使用命令行,命令为: git clone git@gitee.com:Agent_ZhenyuanLiu/AllAgent.git
3、增加源分支地址到你项目远程分支列表中(此处是关键),先得将原来的仓库指定为upstream,命令为: git remote add upstream https://github.com/被fork的仓库.git
此处可使用git remote -v查看远程分支列表
4、fetch源分支的新版本到本地 [master]> git fetch upstream
5、合并两个版本的代码 [master]> git merge upstream/master
6、将合并后的代码push到github上去 [master]> git push origin master 官方解决办法: git fetch upstream # Fetches any new changes from the original repository git merge upstream/master # Merges any changes fetched into your working files

GitHub站内操作 打开自己的仓库,进入code下面。 点击new pull request创建。
选择base fork 选择head fork 点击Create pull request,并填写创建信息。

6. 点击Merge pull request 合并从源fork来的代码。
7. 完成。

本文部分内容借鉴自:
http://www.cnblogs.com/zyumeng/p/3442263.html
https://blog.csdn.net/qq1332479771/article/details/56087333
https://help.github.com/articles/fork-a-repo
http://www.shizuwu.cn/post/669.html
http://segmentfault.com/q/1010000000095921
http://my.oschina.net/luffyke/blog/70336

亲,如果您感觉本文有用,请点个赞再走吧✌(>‿◠)!!
项目管理
2018-07-04 09:22:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
temp 目录是由 Java 运行时进行配置的,同时一些 Confluence 的组件将会写入历史文件或者锁定文件到这个目录中。
临时目录位于安装目录下的 /temp 目录中。
希望修改这个目录的位置,重启你的 Java虚拟机(Java Virtual Machine)的时候配置下面的参数:
- Djava.io .tmpdir=/path/to/your/own/temp/directory .
请注意:这个临时目录与 Confluence Home 目录中导出的临时目录是不相同的。请查看上面表格中有关 /temp 的配置来修改你临时目录的配置。

https://www.cwiki.us/display/CONF6ZH/Confluence+Home+and+other+important+directories
项目管理
2018-07-04 00:17:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
介绍
IP是TCP/IP协议栈中最核心的协议,TCP、UDP、ICMP和IGMP都基于IP协议传输数据
IP协议的两个重要特点: 不可靠:不保证IP数据报成功传输到目的地,可靠性由上层保障 无连接:不维护数据报的状态信息。每个数据报都是独立传输,可能A在B之前传输,但是A在B之后到达
IP首部
其中普通IP首部占据20字节,除非包含可选字段,并且IP数据报的长度一定是32位的整数倍 版本号:4位。IPv4的版本号是4 首部长度:4位。代表图中首部占据了多少个32位。4位首部长度说明首部最长为 2^4-1=15 个32位,即60字节 服务类型(TOS):8位。其中3位优先权子字段(已忽略)、4位TOS子字段和1位未用位。4位TOS最多设置其中一个位,如果全0代表一般服务,这4位分别是:最小时延、最大吞吐量、最高可靠性、最小费用。根据不同类型,来选择不同的执行逻辑 总长度:16位。整个IP数据报的总长度,通过首部长度和总长度,可以知道数据内容的起始位置和长度 标识:16位。唯一标识主机发送的数据报,每发送一份报文都会加1 标志:3位。 偏移:13位。 生存时间:8位。数据报最多经过的路由器数 协议:8位。表明是哪个上层协议向IP发送数据,根据这个字段在收到数据报的时候可用正确分用 首部校验和:16位。根据IP首部计算的校验和 选项(如果有):不定长。如有需求,会额外增加的字段,可选
IP路由选择 IP收到上层的数据报,搜索路由表,根据搜索结果并完成发送 IP收到下层网络接口传上来的数据报,check数据报中目的IP是否为本机。如果是,则交给IP首部字段指定的协议模块解析;如果不是,则若本机无路由功能就丢弃数据报,若本机有路由功能则进行路由表搜索和转发
路由表: 目的IP地址:可以是网络地址,也可以是主机地址 下一站路由器的IP地址:直连网络的路由器IP,通过该路由器将数据转发到目的地 标志:一个标志区分目的IP是网络地址还是主机地址;另一个标志区分下一站路由器是真正的路由器还是直连的网络接口 为数据报传输指定一个网络接口
IP路由是逐跳地(hop-by-hop)进行,IP并不知道到达目的地的完整路径,只是通过路由寻找到下一站路由器,如此不断接近终点
IP路由选择过程: 搜索路由表,找到与目标IP完全匹配的条目,将报文发送给该条目的下一站路由器或直连的网络接口 搜索路由表,找到与目标网络号匹配的条目,将报文发送给该条目的下一站路由器或直连的网络接口 搜索路由表,找到“默认”条目,将报文发送给该条目的下一站路由器或直连的网络接口
为每个网络指定一个路由器,可以减少路由表的规模 大部分主机和路由器可以采用“默认”路由条目将数据传送到目的地 逐跳传递过程中,目的IP地址不变化 逐跳传递过程中,链路层数据帧首部的目的地址始终指向下一站链路层的目的地址(mac地址)
子网寻址
子网的目的: 如果网络下直接就是主机号,通常一个网络可用主机号较多,实际用不了这么多,浪费 子网对外只需要暴露网关的IP地址,可用极大减少Internet路由表规模
通常B类地址才划分子网
子网掩码
用来确定IP地址中有多少位是网络号和子网号,有多少位是主机号
有盘主机通常在系统启动的时候,会读取磁盘中的文件来获取IP地址和子网掩码
通过子网掩码可以确定目标地址与本机地址是否在: 其他网络 同一个网络 同一个子网
这个功能也是路由选择中不断进行的步骤
特殊的IP地址
变长子网
当一个子网(如图中子网13)中存在多个网络(如图中SLIP和以太网),就需要通过增加子网的长度,来区分该子网是SLIP子网还是以太网子网。这种改变子网长度,称为变长子网
3-10中各接口IP
项目管理
2018-07-05 23:30:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
针对生产系统中,我们推荐你使用远程监控,这个将不会消耗你远程 Confluence 服务器的资源。
启动远程监控: 添加下面的属性到 setenv.sh / setenv.bat 文件中,端口你可以定义任何你没有使用的端口。
set CATALINA_OPTS= -Dcom.sun.management.jmxremote %CATALINA_OPTS%
set CATALINA_OPTS= -Dcom.sun.management.jmxremote.port= 8099 %CATALINA_OPTS%
确定你将如何保持你远程连接的安全。请 Remote Monitoring and Management 页面来获得更多的信息。
尽管可以在监控的时候禁用安全授权,我们不推荐你在生产环境下配置使用禁用安全授权。 启动 JConsole (你可以在 JDK 安装目录中找到了启动需要的 bin)。 选择 远程进程(Remote Process) 。 输入你的主机名和端口(这个端口是你在配置文件中配置的,这个端口不是你 Confluence 运行的端口)。 单击 连接( Connect )。
请参考 Using JConsole 来获得有关远程监控的更多有用信息。
https://www.cwiki.us/display/CONF6ZH/Live+Monitoring+Using+the+JMX+Interface
项目管理
2018-07-05 22:10:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
你可以使用下面的 Confluence MBeans 来实时查看你 Confluence 实例运行的实时信息。
CacheStatistics
这个 MBean 显示了 Confluence 有关的缓存信息。有关更多的内容请查看 Viewing System Information 页面中的内容。
IndexingStatistics
这个 MBean 显示有关搜索索引的相关信息。这里是一些有用的配置属性。
Flushing 显示当前缓存有没有刷新。 布尔值(True/False)
LastElapsedMilliseconds 上一次进行索引所消耗的时间。 毫秒(Milliseconds)
TaskQueueLength
ReIndexing
显示任务队列中的数量。
确定 Confluence 当前是否在进行重新索引。
整数(Integer)
布尔值(True/False)
SystemInformation
这个 MBean 显示了 Confluence 的版本和已经运行的时间想信息。你也可以通过 Viewing System Information 页面来查看这方面的信息。

DatabaseExampleLatency
显示进行数据库示例查询的延迟时间。
毫秒(Milliseconds)
RequestMetrics
这个 MBean 显示了系统负载和错误页面的相关信息。
AverageExecutionTimeForLastTenRequests 最后 10 个查询执行的平均时间。 毫秒(Milliseconds)
CurrentNumberOfRequestsBeingServed 这个实例已经执行的查询数量。 整数(Integer)
ErrorCount
NumberOfRequestsInLastTenSeconds
Confluence 错误页面的数量。
最后 10 秒内执行的查询数量
整数(Integer)
整数(Integer)
MailServer-SMTPServer
这个 MBean 显示了电子邮件发送和失败的相关信息。针对你安装的 Confluence 实例中的每一个系统中配置的 SMTP 邮件服务器,都会有一个独立的 MBean 显示。

EmailsAttempted
EmailsSent
Confluence 尝试发送的电子邮件数量。
成功发送的电子邮件数量。
Integer
Integer
MailTaskQueue
这个 MBean 显示电子邮件有关的工作情况。
ErrorQueueSize 队列中的错误数量。 整数(Integer)
Flushing 显示状态(例如:flushing 或不是)。 布尔值(True/False)
FlushStarted 操作开始的时间。 时间(Time)
RetryCount
TaskSize
整个操作总计处理已处理的总数。
需要等待发送的电子邮件队列中的消息数量。
整数(Integer)
整数(Integer)
SchedulingStatistics
这个 MBean 显示当前任务有关的信息,已经计划的任务和这些任务上次运行所花费的时间。

AllJobNames
CurrentlyRunningJobNames
显示当前任务有关的信息,已经计划的任务和这些任务上次运行所花费的时间。
显示当前正在执行的计划任务。
字符串(String)
列表(List)

https://www.cwiki.us/display/CONF6ZH/Live+Monitoring+Using+the+JMX+Interface
项目管理
2018-07-05 22:09:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
其他 MBeans
希望监控 Hibernate 和 Hazelcast(仅针对 Confluence 数据中心)你需要在你的 setenv.sh / setenv.bat 文件中添加下面的内容。
set CATALINA_OPTS= -Dconfluence.hazelcast.jmx.enable= true %CATALINA_OPTS%
set CATALINA_OPTS= -Dconfluence.hibernate.jmx.enable= true %CATALINA_OPTS%
这个修改将会让 Hibernate 和 Hazelcast 的 MBeans 在你的 JMX 客户端中可查看。
监控高 CPU 消耗线程
JConsole Top Threads Plugin 插件能够帮你监控当前那个线程消耗了最多的 CPU 时间,你可以在启动的时候添加下面的启动参数来启动这个插件:
JConsole -pluginpath /pathto/ topthreads.jar
https://www.cwiki.us/display/CONF6ZH/Live+Monitoring+Using+the+JMX+Interface
项目管理
2018-07-05 22:09:00
「深度学习福利」大神带你进阶工程师,立即查看>>>
其他 MBeans
希望监控 Hibernate 和 Hazelcast(仅针对 Confluence 数据中心)你需要在你的 setenv.sh / setenv.bat 文件中添加下面的内容。
set CATALINA_OPTS= -Dconfluence.hazelcast.jmx.enable= true %CATALINA_OPTS%
set CATALINA_OPTS= -Dconfluence.hibernate.jmx.enable= true %CATALINA_OPTS%
这个修改将会让 Hibernate 和 Hazelcast 的 MBeans 在你的 JMX 客户端中可查看。
监控高 CPU 消耗线程
JConsole Top Threads Plugin 插件能够帮你监控当前那个线程消耗了最多的 CPU 时间,你可以在启动的时候添加下面的启动参数来启动这个插件:
JConsole -pluginpath /pathto/ topthreads.jar
https://www.cwiki.us/display/CONF6ZH/Live+Monitoring+Using+the+JMX+Interface
项目管理
2018-07-05 22:08:00