致敬2016

契子

2016已经与我告别,春运的尾声已经开始到来,在这个时刻,看着寥寥的灯火,不得不感慨,有时候很多事并不是你想象的那么顺利,回望2016,梳理下过去写下的日记,就可以发现我一直在寻找的路上
,关于自我的生活,关于性格,关于旅行,关于技术,都有留下了我匆忙的气息,在2016年很多事斗能反映我面对就业的思考和实践,2016是我踏上社会,认识自我的一年,是我对自我定位的一年,
是我从游戏到平静思考自己需要什么的一年,关于生活,也许我还有思考好未来的路,但是当下的路我知道无论如何都得一个人走,未来星光灿烂,我的梦想是平凡之中实现自我关于生活,工作,读书写作和技术转变的新的突破
我知道也能感受到我心中的波澜不惊,但是我不想在自我的世界再继续构造下去,所以这个不仅是对过去的一个总结,也是衔接未来一个见证,我不想也不要继续追寻不切实际的梦,脚踏实地,做回真正的自我

生活

过去属于死神,未来属于你自己,雪莱的话语道出了我对未来生活的一种向上的搏斗精神,无论生活给予了你什么,你都必须付出同样的价值才能得到你想要得到的生活,以前总是追问自己为什么而活,我想现在的状态更多的是再谋生,
生活,为生存而活着,而不是为了其他,爱情,事业,生活,这也许是对生活的一种诠释,也许我没有发现美的眼睛,但是我却有想去发现的持着和冷静,拖着沉重的行李箱走出大学的校门,那一刻,心里是多么想念大学的时光,也许用怀念更加合适,但我心中却没有伤感,因为我知道这一刻我需要为自己生存而活着,租房,找工作,找兼职,找一切能够活下去的工作,困难是有的,但是如果你一直都不想长大,那就是不干面对生活的人,我心中鞭策我不要当懦夫,托盘沉重的山珍菜肴在我看来就是嘲笑我懦弱的小人儿,我使出浑身的力气去坚持,去努力,队长的尖酸刻薄,工人之间的嘲笑,在我看来,这就是最真实的生活
繁华的霓虹灯之下的生活,不是腐败,而是艰辛,以前去菜馆的时候没有体会到过这种生活,我想这也是我的历练吧,如果生活顺风顺水,那还有什么意义,生活就是再不断尝试中试着成长。
以前总是心里想着家人多么的幸苦,但是你不去体验过是说不出这种感觉的,文学也是,没有真正去体验过书中的生活是很难真正的体味其中的精髓的,阅历在我看来就是一个人不断尝试不同的人生得来的赏赐。
2016给予我最好的礼物就是能够让我不再好高骛远,虽说达不到脚踏实地,但是却对自己走进社会,融入社会有了更加深切的体会,流水线的苦闷并不可怕,可怕的是我没有再其中学到任何我以后需要的一点技能,我想这才是我离开的理由,当然客服的投诉和被骂,语言上的欠缺是我的一大弱点,作为打工的,我需要对我所雇用的公司企业负责,他给予我多少回报,我就应该想方设法去帮助他获得相应的回报,也许我仅仅是一个客服,但是我需要对老板负责,对顾客负责,这就是生意兴隆的原因,每个人都为了自我的生存或者说为了家庭而去谋生,我想我该为自我的付出得到相应的回报。
2016不仅让我踏入了社会,也让我明白,一分耕耘,一分收获。当你在路上的时候不要停下你前进的脚步,未来并不遥远。

性格

一个人性格的培育需要对每件事情都有一个很好的认识,特别是对自我的一个定位,把握自我需要把自身的潜力挖掘出来,实现自我的价值提升,性格塑造,我对自我的性格有时候也会思考,我需要什么样的性格,朋友对我说,我很有亲和力,其实我一点都没感觉得到,做早点的小哥和我说,你很像我的一个朋友,很容易亲近,每次都给我多一点早点,而我却不知道自己有什么样的性格,我想要的性格是当机立断,而不是未雨绸缪,对么一件事都精确的计算,即使是上班,认真对待每一个人而不是仅仅是过客,对每一件事都需要经过自我的思考,而不是人云亦云,最大的转变也许是工作之后更加开朗一些,喜欢找一些人一起,而不是再是孤独一个人,写作,看书,旅行。性格也许还会变吧,当我改变的时候请告诉我,你要的性格,我马上改。

旅行

2016也许是我最近几年去的地方最多的一年啦,以前也是很喜欢到处走走,看不一样的风景,遇到不一样的人,说不一样的话,这是对的,从年前的四季如春的广州到寒风刺骨的南京,也算是走了不同的城市,走过苏州,无锡,扬州,武汉,常州,也算是比较有见底的,无论是人文还是地理多少也有点印象,走过的路不回头,而我更喜欢的是到处走走,而不是一直扎堆去风景景区,这样能过够吃到更多的好吃的东西,看到更多不一样的风景,虽然现在已经很多没有以前那样,为旅游而旅游,
但是过往总让我做更好的判断,而不是局限于一点,一座城市不仅仅要看高楼大夏,城市建设,交通运输,还有深入到底层的小巷去感受不同阶层,不同人们的生活。
在无锡锡山古镇,斑驳的城墙下,我们同学一起在这座小镇憩息,整齐划一的小镇弥漫着浓重的古江南的气息,具有江南特有的建筑风格,让人眼前一亮,穿梭在不同的巷子里却不会迷失自我,让我也有一丝羡慕在这里生活的人们,也许累了在这种环境休息一下是一个不错的主意,无锡水浒城,太湖的水养育了这座城市,坐公交离开的时候可以看到这座城市的现代化,烟花依旧让这座城市有不一样的活力,
在苏州观前街前,我在山水环绕的小城踏着碎步游走在狭小的里弄,昏暗的路灯映射出那刹那的繁华,江南古今都是富庶的地带,沿着京杭大运河的足迹去探索历史的回音,虽然国庆还没到,但是街边的小吃多了起来,人也渐渐多了起来,看着人们匆匆的旅行,我作为一个路人,陌生的脸孔让我觉得我也不属于这座城,上有天堂,下有苏杭,苏州的美,在我看来是静谧的,柔和的,沿着山塘街的古朴的街道延伸,看着河里摇曳的船只,繁华不再,现在更多的是游人匆匆,也许我就是那游人,站在小船上,轻舟已过历史的沉浮,再下一站继续前行。
南京,六朝古都,也算是我继续停留的一座城市,从一座城市的地铁命名就可以知道不同的文化区域,玄武门,中华门,夫子庙,这些都是推介一游的地方,我却在金陵迷失了我自我,在我看来这座城市并不是一天两天就可以游玩的,在这个假期我又抽时间慢慢的去游览了一次,对南京的各个区域有了更多的了解吧,以前认识一个南审的陌生人,让我对南京有了最初的印象。。。后面还是写一个文章吧

python做简单的增删改查

python的框架

django是python的一个快速开发网站的一个框架,在我工作工程中使用,简单的配置网上很多,下面我要说的是django的一个最基本的应用,增上该查,网上的例子很多,
我自己也总结一下,python的这个框架和java相比具有很明显的特点,很轻便,没java那么重,可以快速的开发博客和基本的管理应用,当然逻辑业务还是需要自己去写的
下面是我对python的一些基本理解吧首先是连接数据库,这里可以链接多个数据库很容易实现多库存储,当然也可以使用缓存,这个以后再提,下面菜市场完成对django的理解

##django的增删改查
首先是数据库的orm的持久化设计
···python
class Organization(generic.BO):
“””
组织单位
“””
indexweight = 1
code = models.CharField(
(“organ code”),max_length=const.DB_CHAR_NAME20,blank=True,null=True)
name = models.CharField(
(“organ name”),max_length=const.DB_CHAR_NAME120)
short = models.CharField(
(“short name”),max_length=const.DB_CHAR_NAME20,blank=True,null=True)
pinyin = models.CharField(
(“pinyin”),max_length=const.DB_CHAR_NAME120,blank=True,null=True)
status = models.BooleanField(
(“in use”),default=True)

tax_num = models.CharField(_("tax num"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
tax_address = models.CharField(_("tax address"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
tax_account = models.CharField(_("tax account"),max_length=const.DB_CHAR_NAME_80,blank=True,null=True)

represent = models.CharField(_("representative "),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
address = models.CharField(_("address"),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
zipcode = models.CharField(_("zipcode"),max_length=const.DB_CHAR_CODE_8,blank=True,null=True)
fax = models.CharField(_("fax"),max_length=const.DB_CHAR_NAME_20,blank=True,null=True)
contacts = models.CharField(_("contacts"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
phone = models.CharField(_("phone"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
website = models.CharField(_("website"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
email = models.CharField(_("email"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
lic_code = models.CharField(_("license code"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
cer_code = models.CharField(_("certificate code"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
license = models.FileField(_("business license"),blank=True,null=True,upload_to='organ')
certificate = models.FileField(_("organization code certificate"),blank=True,null=True,upload_to='organ')
weight = models.IntegerField(_("weight"),default=9)

class Meta:
    verbose_name = _('organization')
    verbose_name_plural = _('organization')

class OrgUnit(generic.BO):
“””
组织单元
“””
UNITLEVEL = (
(1,
(‘BRANCH’)),
(2,(‘DEPARTMENT’)),
(3,
(‘OFFICE’)),
(4,(‘TEAM’)),
(5,
(‘COMMITTEE’))
)
index_weight = 2
parent = models.ForeignKey(‘self’,verbosename=(“parent”),null=True,blank=True)
organization = models.ForeignKey(Organization,verbosename = (‘organization’),null=True,blank=True)
code = models.CharField(_(“code”),max_length=const.DB_CHAR_CODE8,blank=True,null=True)
name = models.CharField(
(“name”),max_length=const.DB_CHAR_NAME120)
short = models.CharField(
(“short name”),max_length=const.DB_CHAR_NAME20,blank=True,null=True)
pinyin = models.CharField(
(“pinyin”),max_length=const.DB_CHAR_NAME_120,blank=True,null=True)
unittype = models.IntegerField((“type”),choices=UNITLEVEL,default=2)
status = models.BooleanField(
(“in use”),default=True)
virtual = models.BooleanField((“is virtual”),default=False)
fax = models.CharField(
(“fax”),max_length=const.DB_CHAR_NAME20,blank=True,null=True)
phone = models.CharField(
(“phone”),max_length=const.DB_CHAR_NAME40,blank=True,null=True)
contacts = models.CharField(
(“contacts”),max_length=const.DB_CHAR_NAME40,blank=True,null=True)
email = models.CharField(
(“email”),max_length=const.DB_CHAR_NAME40,blank=True,null=True)
weight = models.IntegerField(
(“weight”),default=99)

class Meta:
    verbose_name = _('org unit')
    verbose_name_plural = _('org unit')

···
然后是对数据进行增删改查

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
46
47
48
49
50
ef add_department(request):
"""
部门添加/修改
"""
data = dict()
id = request.POST.get('department_id')
name = request.POST.get('department_name')
depart_type=request.POST.get('department_type')
try:
# 0 新增
if id == '0':
department = Department()
# 其他:编辑
else:
department = Department.objects.get(pk=id)
department.name = name
department.depart_type=depart_type
department.save()
data['is_succ'] = True
except Department.DoesNotExist:
data['is_succ'] = False
data['msg'] = '未查询到指定部门'
except Exception as e:
data['is_succ'] = False
data['msg'] = e.message
return HttpResponse(json.dumps(data), mimetype='application/json')
@transaction.atomic
@login_required
def del_department(request):
"""删除部门"""
data = dict()
id = request.POST.get('department_id')
try:
UserInfo.objects.filter(position__department_id=id).delete()
Position.objects.filter(department_id=id).delete()
Department.objects.filter(pk=id).delete()
data['is_succ'] = True
except Exception as e:
data['is_succ'] = False
data['msg'] = e.message
return HttpResponse(json.dumps(data), mimetype='application/json')

最后要配置的是路由转发
就是接口的使用和前端做交互,简单明了的mvc设计

##总结
基本的流程就是这样,其实python的增删改查简化和封装了很多细节的东西,让开发者更加关注的是业务逻辑,在两个星期的学习中也遇到了很多的问题,以后我会好好总结和归纳,然后整理,只有不断的学习,才能够继续
前进

我走在前进的路上

##启示
拖着笨重的行李箱,踏上公交,然后在我视线里把学校最后的一点倒影抹去,我正式和大学说再见,没有伤感,只有不舍和对前路的锲而不舍
有时候就是这样,当你真正结束你正在进行的状态的时候就会有很多的感悟,我们一直在探索自己的路,前方是什么,我们需要掌握什么才能
够继续走下去 ,这无关过去,展望未来我们需要更多的勇气,列车的进站让我知道我即将和生活了三年的小城告别,下一站也许就是永别

##天黑之前点蜡烛
心心念念来到一个新的地方,南京,不知道心里有多么不愿意,我和我室友走下动车那一刻,我知道社会已经在我的脚底印下我的痕迹,
在车站仰望天空,这里的夜色和淮北的一样让我感觉不到我心中的渴望,我一直在路上,开始在地铁的出站口停留,搜索着需要到哪里去落脚,ieee的
我走在前面,行李箱那笨重的喘息让我知道我还在旅途,在为生活而开始奔波,有时候我会想,我又没有准备好迎接挑战,迎接不确定的明天。

##我在用心去生活
我走在大街查看两边的招聘信息,浏览赶集上形形色色的招聘,开始试着打陌生的应聘电话,从自信满满到我该做什么,我能做什么,我除了编程我还能做什么,最后我
去了大酒店做临时服务员,我端着我双手刚可以承载的菜盘子,我知道这个我做不来,但是我不想因为这个而放弃,我试着坚持,在这个大酒店继续修行,领工的刁难和一位叔叔的关心
让我感到无论在哪里,都有你的一席之地,无论多么困难,我都需要走下去,对每一份工作我都需要认真的去完成,不会就学习,在这个过程中,我看到了一个不对生活妥协的毅力,
我知道这个很重要,从酒店出来,我感受到了底层的人们生活的不容易,并不是所有人都能在困苦中依然思考着每一件事,他们只是对这个生活的麻木的生活,熟悉的操作,以至于对生活没有
认识,在过着自己局限的生活,我知道我不想也不要这样一直都这样的下去,所以我选择了离开,然后继续前行

##生活并不像我想的那么好
和室友一起去了一个电脑店,开始了第二份不太容易的工作,看着瘪瘪的钱包,我们知道我们必须快速的找到工作,无论是不是真正的好工作,只要能够生活,先积累一点经验
我不想就这样铩羽而归,我需要对这次的决定负责,不仅仅因为欠了一屁股债,还有对家人负责,不要总是在家人的呵护下成长,所以我需要尽快找到属于自己的工作,养活自己让自己在这座古城活下去
也许这个不是太容易,生活不会咀嚼吃对生活向往的人,我也不例外。我需要规划自己的生活,不仅仅是工作还有生活各个方面,最终我们在早上高峰的地铁对生活做了一个了结。我不知道未来会怎样,但是
我知道我现在需要继续向前,即使遍体鳞伤,生活还是需要继续,既然选择了就要风雨兼程,我一直相信,天无绝人之路,我最后找到了一个不算太好的工作,只为了继续前进,学习和生活本身就不会是你想怎样就怎样
当你明白你需要什么的时候,未来就会有希望。

##总结,
这一个月的找工作和生活让我明白了只要不断学习才能够去博取更好的生活,只要风雨兼程,未来会更加美好

synchronized和java.util.concurrent.locks.Lock的异同

相同点

主要相同点:Lock能完成synchronized所实现的所有功能

不同点

主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,
而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,
例如,它的tryLock方法可以非阻塞方式去拿锁

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadTest {
/**
* @param args
*/
private int j;
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadTest tt = new ThreadTest();
for(int i=0;i<2;i++)
{
new Thread(tt.new Adder()).start();
new Thread(tt.new Subtractor()).start();
}
}
private class Subtractor implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j--=" + j--);
//这里抛异常了,锁能释放吗?
}*/
lock.lock();
try
{
System.out.println("j--=" + j--);
}finally
{
lock.unlock();
}
}
}
}
private class Adder implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j++=" + j++);
}*/
lock.lock();
try
{
System.out.println("j++=" + j++);
}finally
{
lock.unlock();
}
}
}
}
}

使用synchronized实现同步的过程中更多的是取决于机器给予的结果,而使用lock()能够更好的去管理线程,显式地调用线程去完成不一样的同步,这样能够提高和工作效率,当然还有其他方面的知识点,这是我关于线程的初步了解,还可以使用线程框架更加简洁的去封装和实现同样的功能,这都是关于线程安全方面的问题了,在就是我对这两个词的了解和使用

关于ArraryList和Vector的区别

ArraryList的优点和缺点

 ArrayList 是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,随机插入、随机删除效率低。

Vector的优势和缺点

Vector 是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现。但是ArrayList是非线程安全的,而Vector是线程安全

ArraryList和Vector的区别

这两个类都实现了List接口(List接口继承了Collection接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,
这是HashSet之类的集合的最大不同处,HashSet之类的集合不可以按索引号去检索其中的元素,也不允许有重复的元素(本来题目问的与hashset没有任何关系,
1)同步性:

Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
(2)数据增长:
ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍,而ArrayList的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的1.5倍)。ArrayList与Vector都可以设置初始的空间大小,Vector还可以设置增长的空间大小,而ArrayList没有提供设置增长空间的方法。
总结:即Vector增长原来的一倍,ArrayList增加原来的0.5倍。

其他方面

对序列化支持不同
ArrayList支持序列化,而Vector不支持;即ArrayList有实现java.io.Serializable接口,而Vector没有实现该接口。
构造函数个数不同
ArrayList有3个构造函数,而Vector有4个构造函数。Vector除了包括和ArrayList类似的3个构造函数之外,另外的一个构造函数可以指定容量增加系数。

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
public void ensureCapacity(int minCapacity) {
// 将“修改统计数”+1
modCount++;
int oldCapacity = elementData.length;
// 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1”
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
private void ensureCapacityHelper(int minCapacity) {
int oldCapacity = elementData.length;
// 当Vector的容量不足以容纳当前的全部元素,增加容量大小。
// 若 容量增量系数>0(即capacityIncrement>0),则将容量增大当capacityIncrement
// 否则,将容量增大一倍。
if (minCapacity > oldCapacity) {
Object[] oldData = elementData;
int newCapacity = (capacityIncrement > 0) ?
(oldCapacity + capacityIncrement) : (oldCapacity * 2);
if (newCapacity < minCapacity) {
newCapacity = minCapacity;
}
elementData = Arrays.copyOf(elementData, newCapacity);
}
}

总结

通过对两个集合类的源码分析对栈和队列的插入方式和查找方式有了进一步的了解,我们学习不仅仅需要知其然,还要懂得去深入去了解和分析源码,实现更好的效果,节约资源和开发途径,重要的是用有限的资源去实现更大的产出,实现代码的效率和结果的分析与判断,这是基于自己的分析还有其他方面的观察,只有深入理解和发展自己的架构思想,才能够在紧急的情况下游刃有余,找到合理的方法去解决遇到的问题

json学习和前端交互

##json的定义
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。(摘自维基百科)

##后端和前端的分离
使用json可以更好的去传输和接收数据,并使用了ajax的更新方式,在进行交互之前,首先需要做的准备是对服务器进行配置,然后进行一步一步的交互,我试着从前端请求到后端相应的思路去书写这篇博客
首先书写前端的界面,这里要写的是用户的管理,使用的是json的包装,效果如下用户管理页面
而是用的是包装类。代码如下

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<script type="text/javascript">
$(function(){
$('#dg').datagrid({
//url地址改为请求categoryAction
url:'user_queryJoinForder.action',
loadMsg:'Loading......',
queryParams:{name:''},//这里不需要传具体的name,因为我们要显示所有的
//width:300,
fitColumns:true,//水平自动展开,如果设置此属性,则不会有水平滚动条,演示冻结列时,该参数不要设置
//显示斑马线
striped:true,
//当数据多的时候不换行
nowrap:true,
singleSelect:false, //如果为真,只允许单行显示,全显功能失效
//设置分页
pagination:true,
//设置每页显示的记录数,默认是10个
pageSize:5,
//设置可选的每页记录数,供用户选择,默认是10,20,30,40...
pageList:[5,10,15,20],
idField:'id',//指定id为标识字段,在删除,更新的时候有用,如果配置此字段,在翻页时,换页不会影响选中的项
//toolbar定义添加、删除、更新按钮以及搜索框
toolbar: [{
iconCls: 'icon-add',
text:'添加用户',
handler: function(){
parent.$("#win").window({
title:"添加用户",
width:650,
height:600,
content:'<iframe src="send_user_save.action" frameborder="0" width="100%" height="100%"/>'
});
}
},'-',{
iconCls: 'icon-edit',
text:'更新用户',
handler: function(){
//判断是否有选中行记录,使用getSelections获取选中的所有行
var rows = $("#dg").datagrid("getSelections");
if(rows.length == 0) {
//弹出提示信息
$.messager.show({ //语法类似于java中的静态方法,直接对象调用
title:'错误提示',
msg:'至少要选择一条记录',
timeout:2000,
showType:'slide',
});
}else if(rows.length != 1) {
//弹出提示信息
$.messager.show({ //语法类似于java中的静态方法,直接对象调用
title:'错误提示',
msg:'每次只能更新一条记录',
timeout:2000,
showType:'slide',
});
} else{
//1. 弹出更新的页面
parent.$("#win").window({
title:"更新用户",
width:650,
height:600,
content:'<iframe src="send_user_update.action" frameborder="0" width="100%" height="100%"/>'
});
}
}
},'-',{
iconCls: 'icon-remove',
text:'删除用户',
handler: function(){
//判断是否有选中行记录,使用getSelections获取选中的所有行
var rows = $("#dg").datagrid("getSelections");
//返回被选中的行,如果没有任何行被选中,则返回空数组
if(rows.length == 0) {
//弹出提示信息
$.messager.show({ //语法类似于java中的静态方法,直接对象调用
title:'错误提示',
msg:'至少要选择一条记录',
timeout:2000,
showType:'slide',
});
} else {
//提示是否确认删除,如果确认则执行删除的逻辑
$.messager.confirm('删除的确认对话框', '您确定要删除此项吗?', function(r){
if (r){
//1. 从获取的记录中获取相应的的id,拼接id的值,然后发送后台1,2,3,4
var ids = "";
for(var i = 0; i < rows.length; i ++) {
ids += rows[i].id + ",";
}
ids = ids.substr(0, ids.lastIndexOf(","));
//2. 发送ajax请求
$.post("user_deleteByIds.action",{ids:ids},function(result){
if(result == "true") {
//将刚刚选中的记录删除,要不然会影响后面更新的操作
$("#dg").datagrid("uncheckAll");
//刷新当前页,查询的时候我们用的是load,刷新第一页,reload是刷新当前页
$("#dg").datagrid("reload");//不带参数默认为上面的queryParams
} else {
$.messager.show({
title:'删除异常',
msg:'删除失败,请检查操作',
timeout:2000,
showType:'slide',
});
}
},"text");
}
});
}
}
},'-',{
text:"<input id='ss' name='serach' />"
}],
rowStyler: function(index,row){
console.info("index" + index + "," + row)
if(index % 2 == 0) {
return 'background-color:#fff;';
} else {
return 'background-color:#c4e1e1;';
}
},
frozenColumns:[[
{field:'checkbox',checkbox:true},
{field:'id',title:'用户编号',width:100}
]],
columns:[[
{field:'name',title:'用户名',width:200}, //
{field:'login',title:'账号',width:100},
{field:'pass',title:'密码',width:100},
{field:'sex',title:'性别',width:100},
{field:'phone',title:'手机号码',width:100},
{field:'email',title:'邮箱',width:100},
]]
});
//把普通的文本框转化为查询搜索文本框
$('#ss').searchbox({
//触发查询事件
searcher:function(value,name){ //value表示输入的值
//alert(value + "," + name)
//获取当前查询的关键字,通过DataGrid加载相应的信息,使用load加载和显示第一页的所有行。
//如果指定了参数,它将取代'queryParams'属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法会向上面url指定的action去发送请求,从服务器加载新数据。
$('#dg').datagrid('load',{
name: value
});
},
prompt:'请输入搜索关键字'
});
});
</script>

这里使用的是javascript的对象json的键值对应的封装方式,然后打包进行数据跳转,这样能够使用ajax进行对象的更新,减少操作和效率
这样就把前端的数据給封装到一个json对象中,然后在struts中使用拦截器把关于json和关键字来进行数据获取,转移给后端的action主要配置在参考的以为大神博客里有,这里只是简单的说明下思路,后面我会给出波博客的地址
然后就是后端的处理,在这里我学会了简单的数据处理,只要把数据封装之后为json然后进行转换,就可以实现,这样我开始的时候在这里测试之后才进行数据库的连接,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
//用来存储分页的数据
pageMap = new HashMap<String, Object>();
//根据关键字和分页的参数查询相应的数据
List<User> user = userService.queryJoinForder(model.getName(), page, rows);
pageMap.put("rows", user); //存储为JSON格式
//根据关键字查询总记录数
Long total = userService.getCount(model.getName());
// System.out.println(total);
pageMap.put("total", total); //存储为JSON格式
return "jsonMap";
}

这样就能把前端的数据传输到后端的action中,这样继续把数据传输给数据库进行操作,返回需要的数据就完成了所有的交互,这是使用了ssh的一种简单的交互过程,以前我所做的都是使用servlet的getAttrute函数直接获取属性值,这样虽然能够更加准确的去拿取数据,但是在servlet中却是存在了多个操作并发而产生数据丢失的不安全的实例,当然最主要的还是不能进行日记和数据操作的透明度,使运维和后期开发增加困难,所以我选用了ssh的学习框架,这个框架能够避免很多并发的使用问题,这也是我后期需要学习和认真总结的一些内容吧,这样我这里的学习就告一段落了,虽然在这里参考了很多别人的内容,但是确实学到了不少东西,关于懒加载,关于对基本数据的抽取,关于数据库的大小,和对jvm的一些知识,虽然只是一点点,但是我想我会有更好的方向去学习和奋斗啦。

总结

这个是这半个月的小总结吧,即是我深造的一些感悟,也是我对框架的新的理解,以前一直在探索如何去实现客户给予的功能,现在通过博客的学习,我知道我关注的不仅是业务本身,还需要考虑运维和后期的扩展需求,还需要在选择上兼顾安全的使用,而不是运行出来就完事,这样是不能够真正的去成长的,一个软件的周期不仅仅是开发出来那么简单,要使软件有更强的生命力,我们必须赋予更高的安全性和更好的体验,客户服务至上,我们不仅在提供技术,还有服务,更有我们关于软件尽善尽美的心

关于hashmap和hashtable

##关于hashmap和hashtable的区别
1,hashmap是单线程的,线程不安全,而hashtable是多线程的,而且在源码的方法中都加入了synchronized进行关于线程安全方面的处理,但是这个hash table是1.5以前的,现在都是使用hashmap来替换hashmap,当然在这个过程中发现现在有一个更好的类接口方法,那就是ConcurrentHashMap。它提供了hashmap的基本功能,但是在实际的场景还需要考虑其他因素,所以这个在下一篇博客会好好的剖析下。为何不使用hashtable那是因为hashtable效率底下,在并发的情况下很容易产生可能会进入阻塞或轮询状态。降低了用户体验。
2,hashmap null 值(key和value都可以)。Hashtable不允许 null 值(key 和 value 都不可以)。这个在应用场景中的关于数据的填写会产生一些不确定的因素,毕竟这个需要根据用户的需求的添加,而不是强制的去让用户去选择,这也是选择使用不同框架的原因吧。

1
2
3
4
5
Hashtable table = new Hashtable();
table.put("a-key", "a-value");
table.put("b-key", "b-value");
table.put("c-key", "c-value");
table.put("c-key",null);

结果:
Exception in thread “main” java.lang.NullPointerException
at java.util.Hashtable.put(Hashtable.java:399)
at com.darkmi.sandbox.HashtableTest.main(HashtableTest.java:20)

3.遍历方式的不同,hashtable是使用的是Enumeration,而hashmap使用iterator遍历方式
4。hashmap在多线程的状态下遍历不稳定,有时候会打印出异常,有时候出现正常值的情况,在网上看了一个源码,是因为
一般我们声明HashMap时,使用的都是默认的构造方法:HashMap,看了代码你会发现,它还有其它的构造方法:HashMap(int initialCapacity, float loadFactor),其中参数initialCapacity为初始容 量,loadFactor为加载因子,而之前我们看到的threshold = (int)(capacity * loadFactor); 如果在默认情况下,一个HashMap的容量为16,加载因子为0.75,那么阀值就是12,所以在往HashMap中put的值到达12时,它将自动扩 容两倍,如果两个线程同时遇到HashMap的大小达到12的倍数时,就很有可能会出现在将oldTable转移到newTable的过程中遇到问题,从 而导致最终的HashMap的值存储异常。,而所给出的代码是在两个线程的作用下才需要这样,所以对于一些基本的数据都是用的是hashmap而如果要跨平台,分布式的开发应用需要使用ConcurrentHashMap来保证线程的安全,防止丢失用户数据,这个是作为我们开发行业提供确切的服务所需要的严谨的态度,而且要把可控性把握在自己手里,而不是在机器。下面是我学习这个方面的一个例子吧

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
package hashmaptest;
import java.util.HashMap;
public class MainClass {
public static final HashMap<String, String> firstHashMap=new HashMap<String, String>();
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(){
public void run(){
for(int i=0;i<25;i++){
firstHashMap.put(String.valueOf(i),String.valueOf(i));
}
}
};
Thread t2=new Thread(){
public void run(){
for(int j=0;j<25;j++){
firstHashMap.put(String.valueOf(j),String.valueOf(j));
}
}
};
t1.start();
t2.start();
Thread.currentThread().sleep(1000);
for(int l=0;l<50;l++){
//如果key和value不同,说明在两个线程put的过程中出现异常。
if(!String.valueOf(l).equals(firstHashMap.get(String.valueOf(l)))){
System.err.println(String.valueOf(l)+":"+firstHashMap.get(String.valueOf(l)));
}
}
}
}

结果输出的有时是稳定的:
25:null
有时确实1:null
2:null
25:null
这就体现了hashmap在多线程的不稳定性,所以这个hashmap在单线程的情况下使用,多线程使用ConcurrentHashMap,为何使用这个类呢,如果只是仅仅为了线程安全而放弃更好的性能这是不值得的,使用了锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。这样就像是一个线程池那样灵活的去使用线程,提高了效率,还能够保证了安全,在以后的设计中我应该更偏向于安全和用户体验。

##总结
通过一个问题去深入的去看代码,和看下别人的博客怎么去解决问题,这也许就是发现问题,提出问题,想办法去解决问题,付出的不仅仅是时间,还有就是思考的过程,也许现在还是在别人的思想中转,,但是这就是让我以后少走这个错误,让我的开发更贴近于用户的需要,提供更好的服务,服务源于技术,而服务对象源于用户。技术改变世界,还改变自我,加油

,