0%

Linux目录结构:

image

/: 根目录,一般根目录下只存放目录,不要存放文件,/etc、/bin、/dev、/lib、/sbin应该和根目录放置在一个分区中

/bin:/usr/bin: 可执行二进制文件的目录,如常用的命令ls、tar、mv、cat等。

/boot: 放置linux系统启动时用到的一些文件。/boot/vmlinuz为linux的内核文件,以及/boot/gurb。建议单独分区,分区大小100M即可

/dev:存放linux系统下的设备文件,访问该目录下某个文件,相当于访问某个设备,常用的是挂载光驱mount /dev/cdrom /mnt。

/etc:系统配置文件存放的目录,不建议在此目录下存放可执行文件,重要的配置文件有/etc/inittab、/etc/fstab、/etc/init.d、/etc/X11、/etc/sysconfig、/etc/xinetd.d修改配置文件之前记得备份。
注:/etc/X11存放与x windows有关的设置。

/home:系统默认的用户家目录,新增用户账号时,用户的家目录都存放在此目录下,表示当前用户的家目录,test表示用户test的家目录。建议单独分区,并设置较大的磁盘空间,方便用户存放数据

/lib:/usr/lib:/usr/local/lib:系统使用的函数库的目录,程序在执行过程中,需要调用一些额外的参数时需要函数库的协助,比较重要的目录为/lib/modules。

Read more »

目录操作:

  • 创建目录:
1
mkdir $HOME/testFolder
  • 切换目录:

使用 cd 命令切换目录

1
cd $HOME/testFolder

使用 cd ../ 命令切换到上一级目录

1
cd ../
  • 移动目录

使用 mv 命令移动目录

1
mv $HOME/testFolder /var/tmp
  • 删除目录

使用 rm -rf 命令删除目录

1
rm -rf /var/tmp/testFolder
  • 查看目录下的文件

使用 ls 命令查看 /etc
目录下所有文件和文件夹

1
ls /etc
Read more »

在jdk1.5中引入枚举这个小功能,这个功能虽然用的不多,但是却给我们的开发带来很多便利,我们
今天来看看java的枚举是个什么样子。

枚举的主要操作方法

1
2
3
4
5
6
7
8
protected Enum(String name,int ordinal)  //接受枚举的名称和枚举的常量创建枚举对象  
protected final Object clone()throws CloneNotSupportedException //克隆枚举对象
public final int compareTo(E o) //比较枚举与指定对象的顺序
public final boolean equals(Object other) //比较两个枚举对象
public final int hashCode() //返回枚举常量的哈希码
public final String name() //返回枚举类的名称
public final int ordinal() //返回枚举常量的序号
public static <T extends Enum<T>> T valueOf(Class<T> enum Type,String name) //返回带指定名称的指定枚举类型的枚举常量

先定义一个枚举,用enum关键字

1
2
3
4
5
6
7
8
/**
* 定义枚举
* @author mingshan
*
*/
public enum EnumTest {
MON, TUE, WED, THU, FRI, SAT, SUN;
}

这里将星期定义为枚举类型,但没有赋值,既然已经定义好了,那么就先测试一下吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
* 枚举测试
* @author mingshan
*
*/
public class Test {

public static void main(String[] args) {

//遍历枚举
for(EnumTest e : EnumTest.values()) {
System.out.println(e.toString());
}

System.out.println("我是分割线------");


//switch 操作
EnumTest fri = EnumTest.FRI;

switch(fri){
case MON :
System.out.println("今天是星期一"); break;
case FRI :
System.out.println("今天是星期五"); break;
default :
System.out.println("-----"); break;
}

//返回
System.out.println(fri.getDeclaringClass());

//利用compareTo进行比较
switch (fri.compareTo(EnumTest.SAT)) {
case -1:
System.out.println("之前");
break;
case 1:
System.out.println("之后");
break;
default:
break;
}
}
}

我们可以遍历枚举,用java的foreach进行遍历,调用枚举的values方法获取定义的枚举列表,但当
我们编写自定义enum时,却不包含values这个方法,这个方法是当我门编译文件时,编译器自动帮我
们加上的。枚举还可以进行switch操作,可以对获取的枚举进行判断。利用compareTo函数进行比较两个
枚举的顺序

Read more »

在java多态中,引用与对象可以是不同的类型,如:

1
2
A b=new B();

运用多态时,引用类型可以是实际对象类型的父类,即实际对象类型已经是一个比较具体的类,而引用类型则是一个比较抽象的类,任何extends过声明引用类型的对象都可以赋值给这个引用变量,这样就可以做出类似动态数组的东西,如下:

1
2
3
4
5
6
7
Animal[] a=new Animal[2];
a[0]=new Dog();
a[1]=new Cat();
for(int i=0;i<a.length;i++){
a[i].eat();
}

a数组里面可以放任何Animal的子类对象,调用的时候可以把子类都当作Animal来操作,实际上调用的是子类的方法,是不是很好玩呢→_→

当然,多态的应用很广泛呢,参数和返回类型也可以多态,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Vet{
public void giveShot(Anmial a){

a.makeNoise();
}
}

class Pet{
public void a(){
Vet v=new Vet();
Dog dog=new Dog();
Cat cat=new Cat();
v.giveShot(dog);
v.giveShot(cat);
}

}

giveShot会接受任何Animal的子类的对象实例,根据传入的参数不同,会调用不同对象的方法。

在利用hibernate写通用DAO层时需要获取泛型的类型,比如我在写hql的update语句时需要获取泛型的实体类,由于泛型有擦除机制,所以与需要在运行过程中获取泛型的类型产生了矛盾。此时需要利用反射机制来实现此功能,下面来看一个小例子。

首先建一个实体类Dog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.io.Serializable;

public class Dog implements Serializable {
private static final long serialVersionUID = 8108340856807454651L;
private int age;
private String name;

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
Read more »

最近在做一个简单的问答网站,首页的内容需要根据用户关注的话题和关注的问题等来展示最新的动态信息,刚开始的时候我想数据库表的设计是关键。

这里涉及到两个概念 推模式(push)拉模式(pull),这里有两篇大神分享的知识 新浪微博架构和FEED架构分析–人人架构_paper0023_新浪博客微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨,讲解的比较清楚

简单来说,什么是推,什么是拉呢?

  1. 推模式是一个用户发表了一条动态,那么后台就遍历关注该用户的所有用户,向他们的feed中推送一条动态
  2. 拉模式与推模式相反,当用户刷新首页时,后台会遍历该用户关注的用户的动态信息,并将动态信息压入到该用户的feed中

简单介绍完推拉模式后,下面就要考虑数据库表该怎么设计了,我采用的是最简单的推模式,毕竟新手嘛,先掌握实现流程。


首先设计feed表,这里我设计一个feed表来存储推送的信息,该表主要有以下几个字段

  • id 自增id
  • suid 推送者uid
  • ruid 接收者uid
  • item_id 推送的信息id
  • type 推送信息类型
  • add_time 推送时间

这是我感觉很简单的feed表,毕竟我那个问答站推送类型不是太多,当然还需要为这个表设计索引哦。
设计完数据库表后,下面该考虑后台推送逻辑和代码如何实现以及前台首页如何渲染feed流信息。


后台我用的是PHP的ThinkPHP框架,新手表示该框架很好用,用该框架可以快速实现的我的想法,我感觉这一点还是很好的。首先在推送类型的选择中我选择了以下几种推送类型

  • 当一个话题下有新话题发起时,推送给关注该话题的用户
  • 当一个问题有回答时,推送给关注该问题的用户
  • 当一个话题的问题有新回答时,推送给关注该话题的用户

上面推送过程中会产生大量的重复信息,所以需要在推送时对推送信息进行过滤,以避免重复的推送信息出现。代码就是当上面的推送类型产生时,将信息写入到feed表中,这里并没有对推送用户进行筛选(对推送用户的筛选可以降低数据库的压力)。

前台渲染的话需要对信息进行排序整合,并对每一条动态信息进行标记,以便在模板渲染时匹配对应的模板。
我写的简单部分整合代码,需要对信息进行遍历整合(这里没写)

 //如果推送类型 为a  则代表推送信息类型为  用户关注的话题有关的问题或关注的问题产生的回答
 $aid=$val['item_id'];
 /**根据回答id获取获取与此回答有关的信息**/
 //获取推送人的uid
 $suid=$val['suid'];
 //获取当前用户对回答的赞同状态
 $upvote_status=$this->getUpvoteStatusByAid($aid, $uid);
//获取feed流 回答信息
 $a_info_all=$this->getFeedAnswerInfo($aid);
 $question_id=$a_info_all[0]['question_id'];
 //根据问题id获取与此问题相关的话题信息
 $tinfo_a=D('Topic')->getFeedTopicByQuestion($question_id);
 //将话题信息追加到回答信息数组中
 $a_info_all[0]['topic']= $tinfo_a;
 //将当前用户对回答的赞同状态最佳到信息数组中
 $a_info_all[0]['upvote_status']=$upvote_status;
 //将整理后的信息添加到feed数组中,并做一个标记 a,以便在模板中判断解析
 $arr_fd['answer']=$a_info_all;
 $arr_fd['feed_flag']='a';
 $feed_return_arr[]=  $arr_fd;

这里 $feed_return_arr[]是一个三维数组,在模板渲染的时候要注意一下。

Read more »

我在利用uploadify插件上传文件时发现java后台获取不到当前用户的session值,即当前的用户的session保存的信息失效,导致拦截器将上传请求拦截,这里的拦截器主要对登录的信息进行拦截验证,正因为此原因,导致上传文件失败,后来在利用firebug查找请求的时候,发现uploadify插件会自动生成一个新的session,导致原来的session失效,解决方法是将jsessionid通过url传到后台,这样后台就能识别当前session,问题也就解决了。代码如下:

1
2
3
4
5
6
$("#uploadify").uploadify({
debug : false,
swf : CTPPATH+'/admin/static/uploadify/js/uploadify.swf', //swf文件路径
method : 'get', // 提交方式
uploader : CTPPATH+'/processUpload.ado;jsessionid=${pageContext.session.id}', // 服务器端处理该上传请求的程序(servlet, struts2-Action) )};

代码中有许多属性这里没有贴出来,这里主要看uploader属性,uploader属性为CTPPATH+’/processUpload.ado;jsessionid=${pageContext.session.id}’,即在请求url中附上
;jsessionid=${pageContext.session.id},这样上传就没问题了。

网站的消息推送功能应用很广泛,比如论坛,问答网站等等都需要推送消息,那么采用什么样的推送方式更加便捷,更加节省服务器资源呢,这个需要根据网站的流量和规模来决定,因为long polling是我最先接触到的,我就来谈谈它吧。

长轮询初看像是轮流查询的意思,其实不是,它是客户端通过ajax发出请求,然后客户端挂起,等待服务器端响应,服务器端会检测有无新消息,如果有消息,服务器端会将新消息推送给客户端,结束本次请求,如果在有效请求期内没有新消息出现,那么会一直检测有无新消息出现。连接会保持一段时间周期直到数据或状态改变或者时间过期,通过这种机制来减少无效的客户端和服务器间的交互。

虽然长轮循比传统的轮询性能会有些提高,但在服务器端数据变化非常频繁的情况下,两者的性能并不能差多少,因为都是客户端先请求,服务器再响应,只是两者服务器端响应的机制不同。
下面来说说代码,服务器端我用的是php,客户端用的是jQuery

服务器端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* @desc ajax长轮询 来获取通知消息信息
* @return 通知信息数量>o
*/
public function longPolling() {
if(!$_GET['timed']) exit();
date_default_timezone_set("PRC");
session_write_close(); //防止session访问互斥问题
set_time_limit(0);//无限请求超时时间
$timed = $_GET['timed'];
while (true) {
sleep(3); // 休眠3秒
//判断有无新通知出现
$no_count=D('Notifications')->getNotificationsCount($this->uid);
if ($no_count>0) {
$responseTime = time();
// 返回数据信息,请求时间、返回数据时间、耗时
$content=array(
'result' =>$no_count,
'reponse_time' =>$responseTime,
'request_time' =>$timed,
'use_time' =>($responseTime - $timed)
);
echo $this->ajaxReturn($content);
exit();
} else { // 模拟没有数据变化,将休眠 hold住连接
sleep(13);
exit();
}
}
}

Read more »

在php中有一个函数可以将数组转化为json数据存储格式,这个函数就是json_encode
但在使用这个函数时转化的格式不一致,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//关联二位数组
$a2=array(
'1'=>array('name'=>'john','age'=>'32'),
'2'=>array('name'=>'tom','age'=>'22')
);
$json2=json_encode($a2);
echo $json2."<br>"; //{"1":{"name":"john","age":"32"},"2":{"name":"tom","age":"22"}}
//索引二维数组
$a3=array(
array('name'=>'zz','age'=>'31'),
array('name'=>'we','AGE'=>'12')
);
$json3=json_encode($a3);
echo $json3."<br>";//[{"name":"zz","age":"31"},{"name":"we","AGE":"12"}]

关联二维数组和索引二维数组转化为json数据格式不同,这时在前台用js解析json的时候就有差别

  • 对于关联数组生成的json数据格式 ,在前台直接用js的eval()将其转化为json对象,然后根据{key:value}取值
  • 对于索引数组生成的json数据格式,用js的eval()转为json对象后,由于[]代表数组格式,所以遇到[]还是按照数组取值,遇到{key:value}这种形式的按照对象取值就行了

当数组维数多的时候需要根据转换后的json数据格式用js进行相应的解析,避免出错。

最近做的网站的一个下载功能出现了问题,在firefox浏览器以及360浏览器下下载均正常,也能将中文正常转换,但在IE浏览器下却出现了问题,当点击下载链接的时候,后台直接报错:
2017-03-17_113722.png
后台我怎么兼容也不能解决问题,我下载的部分java代码:

QQ图片20170317113901.png

进过我仔细查找,发现我前台通过get方式提交的文件名包含一下字符,导致浏览器解析url不一致,所以需要将url通过javascript进行转码,即用encodeURIComponent函数进行编码,代码如下

1
2
<a href="javascript:location.href='${pageContext.request.contextPath}/download.do?realname='+encodeURIComponent('${file_list.real_name}')+'&filename='+encodeURIComponent('${file_list.file_name}');" class="file-name">${file_list.file_name}</a>

通过将文件名编码之后就能解决问题了