$total_performance = array_column($data, 'total_performance');
array_multisort($total_performance, SORT_DESC, $data);
TortoiseGit与在线代码托管仓库使用说明
- 在在线代码托管仓库 github、码云或者自建托管仓库gitlab中先创建一个仓库(项目),这里名为GitTest。
- 在在线托管仓库的个人设置里面,设置SSH公钥。大致的步骤如下图所示,但是公钥的生成请看第 3. 点。
- ssh-rsa公钥的生成方法需要用到TortoiseGit的工具进行生成。SSH公钥由TortoiseGit生成,在C:Program FilesTortoiseGitbin 目录下双击puttygen.exe,点击Generate后在空白区域移动鼠标使ssh-rsa生成,然后点击 Save private key按钮,将公钥保存成ppk后缀的文件。如下图所示:
- 在你要做项目的位置右键点击Git 克隆
会出现如下界面,其中URL写的是你仓库的SSH地址,目录就是你要工作的目录,可以再次选择。加载Putty秘钥选择刚才的秘钥。
以码云为例,点击仓库右上角的克隆(clone)(其他托管仓库可能叫法有所不同),找到SSH,填进去即可。
- 在以上工作都准备完毕后,会首次进行一个同步,以你仓库的命名创建一个文件夹,这个就是你之后的工作目录,比如GitTest是我在码云上创建的仓库,那么文件夹就叫GitTest,以后这就是我的工作目录。
【托管仓库】
【本地】
- 进入工作目录,显示隐藏的项目,可以发现存在一个.git的隐藏目录,就代表此目录与git相关。
- 新建一个文件,1111.txt,输入内容“这里是测试1号文件”,鼠标右键点击【Git提交】,具体情况如下图所示:
- 勾选1111.txt,日志信息需要手动输入,比如改了哪些内容。
这里首先要明确一个概念,【本地仓库】与【远程仓库】,本地仓库就是在电脑上建立的仓库,远程仓库就是指在线托管仓库(如:github、码云、gitlab等)。
TortoiseGit软件这里“提交”的意思是发送给本地仓库,“推送”的意思是发送给远程仓库。“提交并推送”的意思是提交给本地仓库并推送给远程仓库。如果你选择了提交,提交完成后还会还会再次询问是否进行推送,所以这里是分为两步执行的。
这里已【提交并推送】成功,打开码云看看是否提交成功吧!如下图所示:码云中GitTest仓库已出现1个文件,1111.txt(大家不用管我提交了几次,几个分支,这些都是之前做测试用的)
打开文件查看:(确保内容为一致)
- 再创建一个2222.txt文件,内容输入“第二个测试文件”,再按之前的方法提交一次,如下界面所示:
10.查看码云上的GitTest代码仓库,如下图所示:
11.修改1111.txt的内容,在末尾加入一部分内容,在点击Git提交按钮,进入到如下界面,如图所示:
右键可以选择与基础版本比较,可以对比与上一个版本的内容改了哪些,如下图所示:
确定没问题后点击“提交并推送”。
12.在码云GitTest仓库里,找到1111.txt打开,查看内容已更新
13.【如何删除】直接在本地删除后提交并推送即可完成,比如我删除2222.txt,然后按照之前的步骤右键点击“Git提交”。然后紧接着看到的文件是缺失状态,勾选2222.txt文件,日志信息写删除的原因,点击“提交并推送”,如下图所示:
14.删除了2222.txt后查看码云上的GitTest仓库,会看到只剩下1111.txt,另外一个已经不见。如下图所示:
15.【可能提交失败的原因】要知道,在做上述任何操作的情况下,如果只有1个人,当然百分之百会提交成功,但是如果有多个人在协作开发,可能别人已经修改过某些文件。无论与你操作的文件是否相撞,你都无法提交成功。
16.【解决冲突之,在线仓库多了我本地没有的文件】我在码云上新建一个文件,命名为“如何解决冲突.txt”,如下图所示:
然后在本地工作目录新建一个3333.txt,如下所示:
右键点击提交,如下图所示:
很显然,直接报错,这个时候如果不解决冲突,则是死活也提交不上去的。所以这个时候得右键点击“同步”按钮。
然后点击拉取:
可以看到,文件已经被拉取下来了,这也叫意味着解决了冲突。如下图所示:
同步下来后界面不要关,接着点击推送,就可以将文件推送上去。也就是一拉一推
17.【解决冲突之,别人修改的文件与我修改的文件撞车】首先我在码云上编辑3333.txt,加入内容“在线添加了此内容”,如下图所示:
然后在本地我也修改了3333.txt中的内容,叫“这是本地添加的内容”。必须先点击提交确定是否有冲突,再点击同步,如下图所示:
按照正常操作,这时点击“拉取”按钮,但是由于双方都修改了内容,自然是不可能拉取成功的。这个时候,需要鼠标右键编辑冲突,如下图所示:
右键点击“编辑冲突”
把上面的内容复制到下面去拼接一下,当然正常的情况不允许直接用这个文本编辑器去编辑,而是去【对比】。对比哪些地方需要修改,用真正的编辑器去编辑处理,我这里直接
Ctrl+S ,点击标记为已解决
如果你不慎将上面的面板关闭了,自己用编辑器编辑完内容,那可以从以下方面解决冲突:
选择该文件,点击确定,可以解锁该文件
这个时候你点击右键,不再有“Git同步”选项,只能点击“Git提交”选项,如下图所示:
查看码云,如下图所示:
18.【分支】在你没创建任何分支前,一般都有个默认主分支,命名为“master”。我在码云中创建了一个cat分支,cat分支与master默认分支一样,都属于常规分支,唯一不同的是Master一般可以设为保护分支,由一个人进行审核。如下图所示:
在创建的时候,这个新创建的cat分支会将原master分支中的所有文件同步一份过去,但是之后对于提交到cat分支的和master分支的不同文件,两个分支之间并不会同步,应先提交到自己分支,再请求合并。
在本地目录GitTest文件夹中创建一个新文件“cat分支新文件.txt”,如下所示:
鼠标右键点击“Git提交”,只是这个时候有点不一样,需要在上方勾选“新建分支”,然后输入cat作为本地仓库的cat分支。
提交并推送,就会出现如下所示界面,取消推送所有分支的勾选
点击确定按钮(这时候会出现提交失败,很正常啊,因为之前都处于master分支,当然要先同步一下cat分支。提交失败的时候不要关闭窗口,直接点击“拉取”按钮,拉取后又说有冲突,不要关闭窗口,直接点击“解决”按钮,解决完又提示可以提交,不要关闭窗口,直接再点击“提交”按钮。总之要临机应变),看看码云上的cat分支的情况,如下图所示:
Java注解与反射的使用
打开 Eclipse,新建 Java 项目“注解与反射”,在 src 下右键并建立包 “注解与反射”,在包下右键并建立 Annotation (注解)文件,名称为“ItAnnotation”。
注解与反射调用
ItAnnotation.java 文件
package 注解与反射;
public @interface ItAnnotation {
}
以上就是一个注解文件。然后再新建一个 class 文件,取名为“TestAnnotation”
TestAnnotation.java 文件
public class TestAnnotation {
public static void main(String[] args) {
}
}
然后在类的上方加上 “@ItAnnotation”,并在 main 方法中检查注解是否存在。我们知道java代码编译后其实是一个以 class 文件存放。检查的方法就是
TestAnnotation.class.isAnnotationPresent(ItAnnotation.class)
如图所示:
如果 TestAnnotation 方法上方存在该注解则进行下一步操作,获取该方法指定类型的注解,代码如下:
ItAnnotation annotation = (ItAnnotation)TestAnnotation.class.getAnnotation(ItAnnotation.class);
然后打印输出 annotation 查看究竟,如图所示:
实际上什么都没有打印,这是为什么呢?我们切换到 ItAnnotation.java 文件,给注解添加一个元注解。我们知道“元”这个字往往是这个意思,注解的注解就是元注解,专门给注解服务的注解。
在注解的上方添加一个 @Retention(RetentionPolicy.RUNTIME)
表示修饰下方的注解始终不会丢弃,运行期间也保留该注解。如图所示:
现在再次运行,就会打印出:@注解与反射.ItAnnotation()
这边引出了个概念,@Retention(RetentionPolicy.RUNTIME)
的意思是运行时不丢弃,也就是说注解是会被丢弃的,那么注解到底在什么时候会被丢弃呢?其实还有另外两个关于 @Retention 元注解的生命周期分别如下:
RetentionPolicy.SOURCE 编译阶段就丢弃,不会生成在 class 文件里
RetentionPolicy.CLASS 在生成 class 文件的时候,会保留在 class 文件里
现在对 @Retention 元注解有一点概念了,那么还有其他的元注解么?有,接下来接触的就是 @Target,它的作用是他修饰的注解可以用在什么地方,也就是可以在哪个代码块区域的上方使用。如果不加 @Target 的话就是任何地方都可以用。
ElementType.TYPE: 用于类、接口、枚举(TYPE实际上是 class 的父级)
ElementType.FIELD:
ElementType.METHOD 用于方法
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE
ElementType.PACKAGE
切换回 ItAnnotation.java 文件,试着加上 @Target(ElementType.METHOD)
第二个元注解,如图所示:
然后切换回“TestAnnotation.java” 文件你会发现 IDE 报错了,把 “@ItAnnotation” 移动到 main 方法上方,错误就消失了。那是因为 ElementType.METHOD 只能用于方法。
我们将 @Target 进行修改,让它能够多选,一般来讲多选都是在括号里面加个大括号,改为 @Target({ElementType.METHOD,ElementType.TYPE})
,这样就可以同时用于类和方法上。
为注解增加一些属性
其实这个注解很像接口,我们在里面定义的相当于抽象方法。定义一个 String name()
,记住 Ctrl+S 保存代码。代码如下:
ItAnnotation.java 文件
......
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItAnnotation {
String name(); //增加一个字符串的属性
}
切换回 “TestAnnotation.java” 可以发现两个 @ItAnnotation 均报错,我们先删除main方法上方的注解,然后在注解后方加上括号填入属性值: @ItAnnotation(name = "小明")
,最后在这个文件 main 方法中之前通过 ItAnnotation annotation 获取的对象调用该方法:annotation.name()
,如下图所示:
TestAnnotation.java 文件
再次运行,控制台会输出“小明”。
有1种特殊的情况,可以在注解中省去属性名称并直接赋值。我们切换回 “ItAnnotation.java” 文件将 String name()
改为 String value()
,点击保存,再在“TestAnnotation.java”文件中,将注解中的值保留,前面的属性去除:@ItAnnotation("小明")
,然后将annotation.name()
改为 annotation.value()
再次运行,发现依然可以输出“小明”,这个情况是特殊的,当你定义的抽象方法为 value() 时,且只有1个的情况下,注解中可以省略属性名并直接赋值。
在拥有多个抽象方法(同时包含 value())时,直接赋值会报错,但在其他方法拥有默认值的情况下不会。切换回 “ItAnnotation.java” 文件,将抽象方法改为 String name default "小明";
,下方在加个 String value();
,完整代码如下:
ItAnnotation.java 文件
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItAnnotation {
String name() default "小明";
String value();
}
TestAnnotation.java 文件
@ItAnnotation("ABC")
public class TestAnnotation {
public static void main(String[] args) {
//检查指定的类上方的注解是否存在
if (TestAnnotation.class.isAnnotationPresent(ItAnnotation.class)) {
//获取 ItAnnotation 类型的注解
ItAnnotation annotation = (ItAnnotation)TestAnnotation.class.getAnnotation(ItAnnotation.class);
System.out.println(annotation.name());
System.out.println(annotation.value());
}
}
}
以上代码不会报错,再次运行,输出 name 的默认值(小明)与value的值(ABC)。
关于使用 jsonp 读取本地 json 文件
本来写了个前端手机网页版,并很快运用到后端。但是由于前端需要单独打包作为模板示范,所以打算写个 json 文件作为配置文件模拟服务器数据进行加载。
json 原本如下:
{
"music_list":[{
0: [{
"name": "简单爱",
"singer": "周杰伦",
"src": "xxxx"
}],
1: [{
"name": "Lemon",
"singer": "米津玄師",
"src": "xxxx"
}]
}]
}
当然,使用jQuery的 $.getJSON 得到的结论如下:
很明显,这是一个跨域的问题,如果要解决,就要将其放到服务器里面吗?比如查看者需要在本地搭建一个 localhost,用这种方式启动,我还不如直接将后端打包得了。于是我查到了一个非正式的协议 jsonp,原理完全和ajax不一样,但jquery 也封装了进去。
不过,这里可以参考jsonp的方法做一些简单的处理。操作如下:
先写一个function 作为 callback 函数。
type里面指定类型为 js,问好后面加个 callback 可简写为 cb,并填写对应的函数名。
然后 json 文件里面写成js的函数形式 也就是这个function名要与上面的一致,里面再加上 json 的标准格式
于是出现如下一幕:
ThinkPHP5 的 header 设置 Content-Type 注意事项
在 function 末尾加上 exit(0);可以使之生效
header("Accept-Ranges: bytes"); //请求范围的度量单位
header("Content-Disposition: filename=" . $file_name ); //文件名
header("Cache-Control: public, max-age=31536000"); //控制缓存
header("Content-Type: audio/mpeg"); //类型
header('Content-Length: ' . $file_size); //文件大小
header('Last-Modified: '.gmdate('D, d M Y H:i:s',time())." GMT"); //上次修改时间
header('Expires: '.gmdate('D, d M Y H:i:s', time() + 3600*24*60)." GMT"); //到期时间
header("Pragma: Pragma"); //使用缓存