鸡啄?/title><link>http://www.cckinglong.com/</link><description>关注互联网、数码、软件开发和编程入门的IT博客</description><generator>RainbowSoft Studio Z-Blog 1.8 Walle Build 100427</generator><language>zh-CN</language><copyright>Copyright © 2011-2017 鸡啄? 版权所?</copyright><pubDate>Tue, 26 Mar 2019 08:46:49 +0800</pubDate><item><title>鸡啄米开始承接项目啦a@b.com (鸡啄?http://www.cckinglong.com/software/772.htmlMon, 25 Mar 2019 16:59:37 +0800http://www.cckinglong.com/software/772.html      鸡啄米的各位朋友,久违了?/p>

      因为近些年确实比较忙,所以博客更新频率有所下降。看到有人问是不是出什么事情了,在此回答,确实木有,多谢大家关心?/p>

      目前鸡啄米的团队在正常开发之余,还尚有精力可以承接外部项目。大家如果有系统要开发可以找鸡啄米哦,无论是C/S架构还是B/S架构,我们都可以搞定?/p>

      欢迎前来洽谈合作,名额有限?/p>

      邮箱:jizhuomi@126.com

      QQ?312565270

]]>
软件开?/category>http://www.cckinglong.com/software/772.html#commenthttp://www.cckinglong.com/http://www.cckinglong.com/feed.asp?cmt=772http://www.cckinglong.com/cmd.asp?act=tb&id=772&key=a8de8094小白照样读懂的VLAN原理讲解a@b.com (鸡啄?http://www.cckinglong.com/software/771.htmlThu, 12 Jul 2018 19:34:04 +0800http://www.cckinglong.com/software/771.html为什么需要VLAN

1. 什么是VLAN?

VLAN(Virtual LAN),翻译成中文?ldquo;虚拟局域网”。LAN可以是由少数几台家用计算机构成的网络,也可以是数以百计的计算机构成的企业网络。VLAN所指的LAN特指使用路由器分割的网络——也就是广播域?/p>

在此让我们先复习一下广播域的概念。广播域,指的是广播?目标MAC地址全部?)所能传递到的范围,亦即能够直接通信的范围。严格地说,并不仅仅是广播帧,多播帧(Multicast Frame)和目标不明的单播?Unknown Unicast Frame)也能在同一个广播域中畅行无阻?/p>

本来,二层交换机只能构建单一的广播域,不过使用VLAN功能后,它能够将网络分割成多个广播域?/p>

2.未分割广播域?hellip;…

那么,为什么需要分割广播域?那是因为,如果仅有一个广播域,有可能会影响到网络整体的传输性能。具体原因,请参看附图加深理解?/p>

图中,是一个由5台二层交换机(交换??)连接了大量客户机构成的网络。假设这时,计算机A需要与计算机B通信。在基于以太网的通信中,必须在数据帧中指定目标MAC地址才能正常通信,因此计算机A必须先广?ldquo;ARP请求(ARP Request)信息”,来尝试获取计算机B的MAC地址?/p>

交换?收到广播?ARP请求)后,会将它转发给除接收端口外的其他所有端口,也就是Flooding了。接着,交换机2收到广播帧后也会Flooding。交换机3??也还会Flooding。最终ARP请求会被转发到同一网络中的所有客户机上?/p>

请大家注意一下,这个ARP请求原本是为了获得计算机B的MAC地址而发出的。也就是说:只要计算机B能收到就万事大吉了。可是事实上,数据帧却传遍整个网络,导致所有的计算机都收到了它。如此一来,一方面广播信息消耗了网络整体的带宽,另一方面,收到广播信息的计算机还要消耗一部分CPU时间来对它进行处理。造成了网络带宽和CPU运算能力的大量无谓消耗?/p>

3. 广播信息是那么经常发出的?

读到这里,您也许会问:广播信息真是那么频繁出现的?

答案是:是的!实际上广播帧会非常频繁地出现。利用TCP/IP协议栈通信时,除了前面出现的ARP外,还有可能需要发出DHCP、RIP等很多其他类型的广播信息?/p>

ARP广播,是在需要与其他主机通信时发出的。当客户机请求DHCP服务器分配IP地址时,就必须发出DHCP的广播。而使用RIP作为路由协议时,每隔30秒路由器都会对邻近的其他路由器广播一次路由信息。RIP以外的其他路由协议使用多播传输路由信息,这也会被交换机转?Flooding)。除了TCP/IP以外,NetBEUI、IPX和Apple Talk等协议也经常需要用到广播。例如在Windows下双击打开“网络计算?rdquo;时就会发出广?多播)信息?Windows XP除外……)

总之,广播就在我们身边。下面是一些常见的广播通信?/p>

(1)ARP请求:建立IP地址和MAC地址的映射关系?/p>

(2)RIP:一种路由协议?/p>

(3)DHCP:用于自动设定IP地址的协议?/p>

(4)NetBEUI:Windows下使用的网络协议?/p>

(5)IPX:NovellNetware使用的网络协议?/p>

(6)Apple Talk:苹果公司的Macintosh计算机使用的网络协议?/p>

如果整个网络只有一个广播域,那么一旦发出广播信息,就会传遍整个网络,并且对网络中的主机带来额外的负担。因此,在设计LAN时,需要注意如何才能有效地分割广播域?/p>

4.广播域的分割与VLAN的必要?/p>

分割广播域时,一般都必须使用到路由器。使用路由器后,可以以路由器上的网络接口(LAN Interface)为单位分割广播域?/p>

但是,通常情况下路由器上不会有太多的网络接口,其数目多??个左右。随着宽带连接的普及,宽带路由?或者叫IP共享?变得较为常见,但是需要注意的是,它们上面虽然带着多个(一般为4个左?连接LAN一侧的网络接口,但那实际上是路由器内置的交换机,并不能分割广播域?/p>

况且使用路由器分割广播域的话,所能分割的个数完全取决于路由器的网络接口个数,使得用户无法自由地根据实际需要分割广播域?/p>

与路由器相比,二层交换机一般带有多个网络接口。因此如果能使用它分割广播域,那么无疑运用上的灵活性会大大提高?/p>

用于在二层交换机上分割广播域的技术,就是VLAN。通过利用VLAN,我们可以自由设计广播域的构成,提高网络设计的自由度?/p>

实现VLAN的机?/strong>

1. 实现VLAN的机?/p>

在理解了“为什么需要VLAN”之后,接下来让我们来了解一下交换机是如何使用VLAN分割广播域的?/p>

首先,在一台未设置任何VLAN的二层交换机上,任何广播帧都会被转发给除接收端口外的所有其他端?Flooding)。例如,计算机A发送广播信息后,会被转发给端口2???/p>

这时,如果在交换机上生成红、蓝两个VLAN;同时设置端口1?属于红色VLAN、端??属于蓝色VLAN。再从A发出广播帧的话,交换机就只会把它转发给同属于一个VLAN的其他端?mdash;—也就是同属于红色VLAN的端?,不会再转发给属于蓝色VLAN的端口?/p>

同样,C发送广播信息时,只会被转发给其他属于蓝色VLAN的端口,不会被转发给属于红色VLAN的端口?/p>

就这样,VLAN通过限制广播帧转发的范围分割了广播域。上图中为了便于说明,以红、蓝两色识别不同的VLAN,在实际使用中则是用“VLAN ID”来区分的?/p>

2.直观地描述VLAN

如果要更为直观地描述VLAN的话,我们可以把它理解为将一台交换机在逻辑上分割成了数台交换机。在一台交换机上生成红、蓝两个VLAN,也可以看作是将一台交换机换做一红一蓝两台虚拟的交换机?/p>

在红、蓝两个VLAN之外生成新的VLAN时,可以想象成又添加了新的交换机?/p>

但是,VLAN生成的逻辑上的交换机是互不相通的。因此,在交换机上设置VLAN后,如果未做其他处理,VLAN间是无法通信的?/p>

明明接在同一台交换机上,但却偏偏无法通信——这个事实也许让人难以接受。但它既是VLAN方便易用的特征,又是使VLAN令人难以理解的原因?/p>

3. 需要VLAN间通信时怎么?/p>

那么,当我们需要在不同的VLAN间通信时又该如何是好呢?

请大家再次回忆一下:VLAN是广播域。而通常两个广播域之间由路由器连接,广播域之间来往的数据包都是由路由器中继的。因此,VLAN间的通信也需要路由器提供中继服务,这被称?ldquo;VLAN间路?rdquo;?/p>

VLAN间路由,可以使用普通的路由器,也可以使用三层交换机。其中的具体内容,等有机会再细说吧。在这里希望大家先记住不同VLAN间互相通信时需要用到路由功能?/p>

VLAN的访问链?Access Link)

1.交换机的端口类型

交换机的端口,可以分为以下两种:

(1)访问链接(Access Link)

(2)汇聚链接(Trunk Link)

接下来就让我们来依次学习这两种不同端口的特征。这一讲,首先学习“访问链接”?/p>

2.访问链接

访问链接,指的是“只属于一个VLAN,且仅向该VLAN转发数据?rdquo;的端口。在大多数情况下,访问链接所连的是客户机?/p>

通常设置VLAN的顺序是?/p>

(1)生成VLAN

(2)设定访问链接(决定各端口属于哪一个VLAN)

设定访问链接的手法,可以是事先固定的、也可以是根据所连的计算机而动态改变设定。前者被称为“静态VLAN”、后者自然就?ldquo;动态VLAN”了?/p>

?静态VLAN——基于端口

静态VLAN又被称为基于端口的VLAN(PortBased VLAN)。顾名思义,就是明确指定各端口属于哪个VLAN的设定方法?/p>

由于需要一个个端口地指定,因此当网络中的计算机数目超过一定数?比如数百?后,设定操作就会变得烦杂无比。并且,客户机每次变更所连端口,都必须同时更改该端口所属VLAN的设?mdash;—这显然不适合那些需要频繁改变拓补结构的网络?/p>

?动态VLAN

另一方面,动态VLAN则是根据每个端口所连的计算机,随时改变端口所属的VLAN。这就可以避免上述的更改设定之类的操作。动态VLAN可以大致分为3类:

(1)基于MAC地址的VLAN(MAC Based VLAN)

(2)基于子网的VLAN(Subnet Based VLAN)

(3)基于用户的VLAN(User Based VLAN)

其间的差异,主要在于根据OSI参照模型哪一层的信息决定端口所属的VLAN?/p>

?基于MAC地址的VLAN

基于MAC地址的VLAN,就是通过查询并记录端口所连计算机上网卡的MAC地址来决定端口的所属。假定有一个MAC地址“A”被交换机设定为属于VLAN “10”,那么不论MAC地址?ldquo;A”的这台计算机连在交换机哪个端口,该端口都会被划分到VLAN 10中去。计算机连在端口1时,端口1属于VLAN 10;而计算机连在端口2时,则是端口2属于VLAN 10?/p>

由于是基于MAC地址决定所属VLAN的,因此可以理解为这是一种在OSI的第二层设定访问链接的办法?/p>

但是,基于MAC地址的VLAN,在设定时必须调查所连接的所有计算机的MAC地址并加以登录。而且如果计算机交换了网卡,还是需要更改设定?/p>

?基于IP地址的VLAN

基于子网的VLAN,则是通过所连计算机的IP地址,来决定端口所属VLAN的。不像基于MAC地址的VLAN,即使计算机因为交换了网卡或是其他原因导致MAC地址改变,只要它的IP地址不变,就仍可以加入原先设定的VLAN?/p>

因此,与基于MAC地址的VLAN相比,能够更为简便地改变网络结构。IP地址是OSI参照模型中第三层的信息,所以我们可以理解为基于子网的VLAN是一种在OSI的第三层设定访问链接的方法?/p>

基于用户的VLAN,则是根据交换机各端口所连的计算机上当前登录的用户,来决定该端口属于哪个VLAN。这里的用户识别信息,一般是计算机操作系统登录的用户,比如可以是Windows域中使用的用户名。这些用户名信息,属于OSI第四层以上的信息?/p>

总的来说,决定端口所属VLAN时利用的信息在OSI中的层面越高,就越适于构建灵活多变的网络?/p>

VLAN的汇聚链?Trunk Link)

1.需要设置跨越多台交换机的VLAN?hellip;…

到此为止,我们学习的都是使用单台交换机设置VLAN时的情况。那么,如果需要设置跨越多台交换机的VLAN时又如何?

在规划企业级网络时,很有可能会遇到隶属于同一部门的用户分散在同一座建筑物中的不同楼层的情况,这时可能就需要考虑到如何跨越多台交换机设置VLAN的问题了。假设有如下图所示的网络,且需要将不同楼层的A、C和B、D设置为同一个VLAN?/p>

这时最关键的就?ldquo;交换?和交换机2该如何连接才好呢?”

最简单的方法,自然是在交换机1和交换机2上各设一个红、蓝VLAN专用的接口并互联了?/p>

但是,这个办法从扩展性和管理效率来看都不好。例如,在现有网络基础上再新建VLAN时,为了让这个VLAN能够互通,就需要在交换机间连接新的网线。建筑物楼层间的纵向布线是比较麻烦的,一般不能由基层管理人员随意进行。并且,VLAN越多,楼层间(严格地说是交换机?互联所需的端口也越来越多,交换机端口的利用效率低是对资源的一种浪费、也限制了网络的扩展?/p>

为了避免这种低效率的连接方式,人们想办法让交换机间互联的网线集中到一根上,这时使用的就是汇聚链接(Trunk Link)?/p>

2.何谓汇聚链接?

汇聚链接(Trunk Link)指的是能够转发多个不同VLAN的通信的端口?/p>

汇聚链路上流通的数据帧,都被附加了用于识别分属于哪个VLAN的特殊信息?/p>

现在再让我们回过头来考虑一下刚才那个网络如果采用汇聚链路又会如何呢?用户只需要简单地将交换机间互联的端口设定为汇聚链接就可以了。这时使用的网线还是普通的UTP线,而不是什么其他的特殊布线。图例中是交换机间互联,因此需要用交叉线来连接?/p>

接下来,让我们具体看看汇聚链接是如何实现跨越交换机间的VLAN的?/p>

A发送的数据帧从交换?经过汇聚链路到达交换?时,在数据帧上附加了表示属于红色VLAN的标记?/p>

交换?收到数据帧后,经过检查VLAN标识发现这个数据帧是属于红色VLAN的,因此去除标记后根据需要将复原的数据帧只转发给其他属于红色VLAN的端口。这时的转送,是指经过确认目标MAC地址并与MAC地址列表比对后只转发给目标MAC地址所连的端口。只有当数据帧是一个广播帧、多播帧或是目标不明的帧时,它才会被转发到所有属于红色VLAN的端口?/p>

蓝色VLAN发送数据帧时的情形也与此相同?/p>

通过汇聚链路时附加的VLAN识别信息,有可能支持标准?ldquo;IEEE 802.1Q”协议,也可能是Cisco产品独有?ldquo;ISL(Inter Switch Link)”。如果交换机支持这些规格,那么用户就能够高效率地构筑横跨多台交换机的VLAN?/p>

另外,汇聚链路上流通着多个VLAN的数据,自然负载较重。因此,在设定汇聚链接时,有一个前提就是必须支?00Mbps以上的传输速度?/p>

另外,默认条件下,汇聚链接会转发交换机上存在的所有VLAN的数据。换一个角度看,可以认为汇聚链?端口)同时属于交换机上所有的VLAN。由于实际应用中很可能并不需要转发所有VLAN的数据,因此为了减轻交换机的负载、也为了减少对带宽的浪费,我们可以通过用户设定限制能够经由汇聚链路互联的VLAN?/p>

关于IEEE 802.1Q和ISL的具体内容,将在下一讲中提到?/p>

3.访问链接的总结

综上所述,设定访问链接的手法有静态VLAN和动态VLAN两种,其中动态VLAN又可以继续细分成几个小类?/p>

其中基于子网的VLAN和基于用户的VLAN有可能是网络设备厂商使用独有的协议实现的,不同厂商的设备之间互联有可能出现兼容性问?因此在选择交换机时,一定要注意事先确认?/p>

下表总结了静态VLAN和动态VLAN的相关信息?/p>

种类解说

静态VLAN(基于端口的VLAN)将交换机的各端口固定指派给VLAN

动态VLAN基于MAC地址的VLAN根据各端口所连计算机的MAC地址设定

基于子网的VLAN根据各端口所连计算机的IP地址设定

基于用户的VLAN根据端口所连计算机上登录用户设?/p>

VLAN的汇聚方?mdash;—IEEE802.1Q与ISL

1.汇聚方式

在交换机的汇聚链接上,可以通过对数据帧附加VLAN信息,构建跨越多台交换机的VLAN?/p>

附加VLAN信息的方法,最具有代表性的有:

(1)IEEE 802.1Q

(2)ISL

现在就让我们看看这两种协议分别如何对数据帧附加VLAN信息?/p>

2.IEEE 802.1Q

IEEE 802.1Q,俗?ldquo;Dot One Q”,是经过IEEE认证的对数据帧附加VLAN识别信息的协议?/p>

在此,请大家先回忆一下以太网数据帧的标准格式?/p>

IEEE 802.1Q所附加的VLAN识别信息,位于数据帧?ldquo;发送源MAC地址”?ldquo;类别?rdquo;(Type Field)之间。具体内容为2字节的TPID(Tag Protocol IDentifier)?字节的TCI(Tag Control Information),共?字节?/p>

在数据帧中添加了4字节的内容,那么CRC值自然也会有所变化。这时数据帧上的CRC是插入TPID、TCI后,对包括它们在内的整个数据帧重新计算后所得的值?/p>

而当数据帧离开汇聚链路时,TPID和TCI会被去除,这时还会进行一次CRC的重新计算?/p>

TPID字段在以太网报文中所处位置与不带VLAN Tag的报文中协议类型字段所处位置相同。TPID的值固定为0x8100,它标示网络帧承载的802.1Q类型,交换机通过它来确定数据帧内附加了基于IEEE 802.1Q的VLAN信息。而实质上的VLAN ID,是TCI中的12位元。由于总共?2位,因此最多可供识?096个VLAN?/p>

基于IEEE 802.1Q附加的VLAN信息,就像在传递物品时附加的标签。因此,它也被称?ldquo;标签型VLAN”(Tagging VLAN)?/p>

3.ISL(Inter Switch Link)

ISL,是Cisco产品支持的一种与IEEE 802.1Q类似的、用于在汇聚链路上附加VLAN信息的协议?/p>

使用ISL后,每个数据帧头部都会被附加26字节?ldquo;ISL包头(ISL Header)”,并且在帧尾带上通过对包括ISL包头在内的整个数据帧进行计算后得到的4字节CRC值。换而言之,就是总共增加?0字节的信息?/p>

在使用ISL的环境下,当数据帧离开汇聚链路时,只要简单地去除ISL包头和新CRC就可以了。由于原先的数据帧及其CRC都被完整保留,因此无需重新计算CRC?/p>

ISL有如用ISL包头和新CRC将原数据帧整个包裹起来,因此也被称为“封装型VLAN”(Encapsulated VLAN)?/p>

需要注意的是,不论是IEEE802.1Q?ldquo;Tagging VLAN”,还是ISL?ldquo;Encapsulated VLAN”,都不是很严密的称谓。不同的书籍与参考资料中,上述词语有可能被混合使用,因此需要大家在学习时格外注意?/p>

并且由于ISL是Cisco独有的协议,因此只能用于Cisco网络设备之间的互联?/p>

VLAN间路?/strong>

1.VLAN间路由的必要?/p>

根据目前为止学习的知识,我们已经知道两台计算机即使连接在同一台交换机上,只要所属的VLAN不同就无法直接通信。接下来我们将要学习的就是如何在不同的VLAN间进行路由,使分属不同VLAN的主机能够互相通信?/p>

首先,先来复习一下为什么不同VLAN间不通过路由就无法通信。在LAN内的通信,必须在数据帧头中指定通信目标的MAC地址。而为了获取MAC地址,TCP/IP协议下使用的是ARP。ARP解析MAC地址的方法,则是通过广播。也就是说,如果广播报文无法到达,那么就无从解析MAC地址,亦即无法直接通信?/p>

计算机分属不同的VLAN,也就意味着分属不同的广播域,自然收不到彼此的广播报文。因此,属于不同VLAN的计算机之间无法直接互相通信。为了能够在VLAN间通信,需要利用OSI参照模型中更高一?mdash;—网络层的信息(IP地址)来进行路由。关于路由的具体内容,以后有机会再详细解说吧?/p>

路由功能,一般主要由路由器提供。但在今天的局域网里,我们也经常利用带有路由功能的交换?mdash;—三层交换?Layer 3 Switch)来实现。接下来就让我们分别看看使用路由器和三层交换机进行VLAN间路由时的情况?/p>

2.使用路由器进行VLAN间路?/p>

在使用路由器进行VLAN间路由时,与构建横跨多台交换机的VLAN时的情况类似,我们还是会遇到“该如何连接路由器与交换机”这个问题。路由器和交换机的接线方式,大致有以下两种:

(1)将路由器与交换机上的每个VLAN分别连接

(2)不论VLAN有多少个,路由器与交换机都只用一条网线连?/p>

最容易想到的,当然还是“把路由器和交换机以VLAN为单位分别用网线连接”了。将交换机上用于和路由器互联的每个端口设为访问链?Access Link),然后分别用网线与路由器上的独立端口互联。如下图所示,交换机上?个VLAN,那么就需要在交换机上预留2个端口用于与路由器互?路由器上同样需要有2个端?两者之间用2条网线分别连接?/p>

如果采用这个办法,大家应该不难想象它的扩展性很成问题。每增加一个新的VLAN,都需要消耗路由器的端口和交换机上的访问链接,而且还需要重新布设一条网线。而路由器,通常不会带有太多LAN接口的。新建VLAN时,为了对应增加的VLAN所需的端口,就必须将路由器升级成带有多个LAN接口的高端产品,这部分成本、还有重新布线所带来的开销,都使得这种接线法成为一种不受欢迎的办法?/p>

那么,第二种办法“不论VLAN数目多少,都只用一条网线连接路由器与交换机”?当使用一条网线连接路由器与交换机、进行VLAN间路由时,需要用到汇聚链接?/p>

具体实现过程为:首先将用于连接路由器的交换机端口设为汇聚链接(Trunk Link),而路由器上的端口也必须支持汇聚链路。双方用于汇聚链路的协议自然也必须相同。接着在路由器上定义对应各个VLAN?ldquo;子接?rdquo;(Sub Interface)。尽管实际与交换机连接的物理端口只有一个,但在理论上我们可以把它分割为多个虚拟端口?/p>

VLAN将交换机从逻辑上分割成了多台,因而用于VLAN间路由的路由器,也必须拥有分别对应各个VLAN的虚拟接口?/p>

采用这种方法的话,即使之后在交换机上新建VLAN,仍只需要一条网线连接交换机和路由器。用户只需要在路由器上新设一个对应新VLAN的子接口就可以了。与前面的方法相比,扩展性要强得多,也不用担心需要升级LAN接口数不足的路由器或是重新布线?/p>

3.同一VLAN内的通信

接下来,我们继续学习使用汇聚链路连接交换机与路由器时,VLAN间路由是如何进行的。如下图所示,为各台计算机以及路由器的子接口设定IP地址?/p>

红色VLAN(VLAN ID=1)的网络地址?92.168.1.0/24,蓝色VLAN(VLAN ID=2)的网络地址?92.168.2.0/24。各计算机的MAC地址分别为A/B/C/D,路由器汇聚链接端口的MAC地址为R。交换机通过对各端口所连计算机MAC地址的学习,生成如下的MAC地址列表?/p>

首先考虑计算机A与同一VLAN内的计算机B之间通信时的情形?/p>

计算机A发出ARP请求信息,请求解析B的MAC地址。交换机收到数据帧后,检索MAC地址列表中与收信端口同属一个VLAN的表项。结果发现,计算机B连接在端?上,于是交换机将数据帧转发给端口2,最终计算机B收到该帧。收发信双方同属一个VLAN之内的通信,一切处理均在交换机内完成?/p>

4.不同VLAN间的通信

接下来是这一讲的核心内容,不同VLAN间的通信。让我们来考虑一下计算机A与计算机C之间通信时的情况?/p>

计算机A从通信目标的IP地址(192.168.2.1)得出C与本机不属于同一个网段。因此会向设定的默认网关(DefaultGateway,GW)转发数据帧。在发送数据帧之前,需要先用ARP获取路由器的MAC地址?/p>

得到路由器的MAC地址R后,接下来就是按图中所示的步骤发送往C去的数据帧。①的数据帧中,目标MAC地址是路由器的地址R、但内含的目标IP地址仍是最终要通信的对象C的地址。这一部分的内容,涉及到局域网内经过路由器转发时的通信步骤,有机会再详细解说吧?/p>

交换机在端口1上收到①的数据帧后,检索MAC地址列表中与端口1同属一个VLAN的表项。由于汇聚链路会被看作属于所有的VLAN,因此这时交换机的端?也属于被参照对象。这样交换机就知道往MAC地址R发送数据帧,需要经过端?转发?/p>

从端?发送数据帧时,由于它是汇聚链接,因此会被附加上VLAN识别信息。由于原先是来自红色VLAN的数据帧,因此如图中②所示,会被加上红色VLAN的识别信息后进入汇聚链路。路由器收到②的数据帧后,确认其VLAN识别信息,由于它是属于红色VLAN的数据帧,因此交由负责红色VLAN的子接口接收?/p>

接着,根据路由器内部的路由表,判断该向哪里中继?/p>

由于目标网络192.168.2.0/24是蓝色VLAN,,且该网络通过子接口与路由器直连,因此只要从负责蓝色VLAN的子接口转发就可以了。这时,数据帧的目标MAC地址被改写成计算机C的目标地址;并且由于需要经过汇聚链路转发,因此被附加了属于蓝色VLAN的识别信息。这就是图中③的数据帧?/p>

交换机收到③的数据帧后,根据VLAN标识信息从MAC地址列表中检索属于蓝色VLAN的表项。由于通信目标——计算机C连接在端?上、且端口3为普通的访问链接,因此交换机会将数据帧去除VLAN识别信息?数据帧④)转发给端?,最终计算机C才能成功地收到这个数据帧?/p>

进行VLAN间通信时,即使通信双方都连接在同一台交换机上,也必须经过:“发送方——交换?mdash;—路由?mdash;—交换?mdash;—接收?rdquo;这样一个流程?/p>

三层交换?/strong>

1.使用路由器进行VLAN间路由时的问?/p>

现在,我们知道只要能提供VLAN间路由,就能够使分属不同VLAN的计算机互相通信。但是,如果使用路由器进行VLAN间路由的话,随着VLAN之间流量的不断增加,很可能导致路由器成为整个网络的瓶颈?/p>

交换机使用被称为ASIC(ApplicationSpecified Integrated Circuit)的专用硬件芯片处理数据帧的交换操作,在很多机型上都能实现以缆线速度(Wired Speed)交换。而路由器,则基本上是基于软件处理的。即使以缆线速度接收到数据包,也无法在不限速的条件下转发出去,因此会成为速度瓶颈。就VLAN间路由而言,流量会集中到路由器和交换机互联的汇聚链路部分,这一部分尤其特别容易成为速度瓶颈。并且从硬件上看,由于需要分别设置路由器和交换机,在一些空间狭小的环境里可能连设置的场所都成问题?/p>

2.三层交换?Layer 3 Switch)

为了解决上述问题,三层交换机应运而生。三层交换机,本质上就是“带有路由功能?二层)交换?rdquo;。路由属于OSI参照模型中第三层网络层的功能,因此带有第三层路由功能的交换机才被称为“三层交换?rdquo;?/p>

关于三层交换机的内部结构,可以参照下面的简图?/p>

在一台本体内,分别设置了交换机模块和路由器模?而内置的路由模块与交换模块相同,使用ASIC硬件处理路由。因此,与传统的路由器相比,可以实现高速路由。并且,路由与交换模块是汇聚链接的,由于是内部连接,可以确保相当大的带宽?/p>

?使用三层交换机进行VLAN间路?VLAN内通信)

在三层交换机内部数据究竟是怎样传播的呢?基本上,它和使用汇聚链路连接路由器与交换机时的情形相同?/p>

假设有如下图所示的4台计算机与三层交换机互联。当使用路由器连接时,一般需要在LAN接口上设置对应各VLAN的子接口;而三层交换机则是在内部生?ldquo;VLAN接口”(VLAN Interface)。VLAN接口,是用于各VLAN收发数据的接口?注:在Cisco的Catalyst系列交换机上,VLAN Interface被称为SVI——Switched Virtual Interface)

为了与使用路由器进行VLAN间路由对比,让我们同样来考虑一下计算机A与计算机B之间通信时的情况。首先是目标地址为B的数据帧被发到交换机;通过检索同一VLAN的MAC地址列表发现计算机B连在交换机的端口2?因此将数据帧转发给端??/p>

?使用三层交换机进行VLAN间路?VLAN间通信)

接下来设想一下计算机A与计算机C间通信时的情形。针对目标IP地址,计算机A可以判断出通信对象不属于同一个网络,因此向默认网关发送数?Frame 1)?/p>

交换机通过检索MAC地址列表后,经由内部汇聚链接,将数据帧转发给路由模块。在通过内部汇聚链路时,数据帧被附加了属于红色VLAN的VLAN识别信息(Frame 2)?/p>

路由模块在收到数据帧时,先由数据帧附加的VLAN识别信息分辨出它属于红色VLAN,据此判断由红色VLAN接口负责接收并进行路由处理。因为目标网?92.168.2.0/24是直连路由器的网络、且对应蓝色VLAN;因此,接下来就会从蓝色VLAN接口经由内部汇聚链路转发回交换模块。在通过汇聚链路时,这次数据帧被附加上属于蓝色VLAN的识别信?Frame 3)?/p>

交换机收到这个帧后,检索蓝色VLAN的MAC地址列表,确认需要将它转发给端口3。由于端?是通常的访问链接,因此转发前会先将VLAN识别信息去除(Frame 4)。最终,计算机C成功地收到交换机转发来的数据帧?/p>

整体的流程,与使用外部路由器时的情况十分相似——都需要经?ldquo;发送方→交换模块→路由模块→交换模块→接收?rdquo;?/p>

加速VLAN间通信的手?/strong>

1.?Flow)

根据到此为止的学习,我们已经知道VLAN间路由,必须经过外部的路由器或是三层交换机的内置路由模块。但是,有时并不是所有的数据都需要经过路由器(或路由模??/p>

例如,使用FTP(File Transfer Protocol)传输容量为数MB以上的较大的文件时,由于MTU的限制,IP协议会将数据分割成小块后传输、并在接收方重新组合。这些被分割的数据,“发送的目标”是完全相同的。发送目标相同,也就意味着同样的目标IP地址、目标端口号(注:特别强调一下,这里指的是TCP/UDP端口)。自然,源IP地址、源端口号也应该相同。这样一连串的数据流被称?ldquo;?rdquo;(Flow)?/p>

只要将流最初的数据正确地路由以后,后继的数据理应也会被同样地路由?/p>

据此,后继的数据不再需要路由器进行路由处理;通过省略反复进行的路由操作,可以进一步提高VLAN间路由的速度?/p>

2.加速VLAN间路由的机制

接下来,让我们具体考虑一下该如何使用三层交换机进行高速VLAN间路由?/p>

首先,整个流的第一块数据,照常由交换机转发→路由器路?rarr;再次由交换机转发到目标所连端口。这时,将第一块数据路由的结果记录到缓存里保存下来。需要记录的信息有:

(1)目标IP地址

(2)源IP地址

(3)目标TCP/UDP端口?/p>

(4)源TCP/UDP端口?/p>

(5)接收端口?交换?

(6)转发端口?交换?

(7)转发目标MAC地址

等等?/p>

同一个流的第二块以后的数据到达交换机后,直接通过查询先前保存在缓存中的信息查?ldquo;转发端口?rdquo;后就可以转发给目标所连端口了?/p>

这样一来,就不需要再一次次经由内部路由模块中继,而仅凭交换机内部的缓存信息就足以判断应该转发的端口?/p>

这时,交换机会对数据帧进行由路由器中继时相似的处理,例如改写MAC地址、IP包头中的TTL和Check Sum校验码信息等?/p>

通过在交换机上缓存路由结果,实现了以缆线速度(Wired Speed)接收发送方传输来数据的数据、并且能够全速路由、转发给接收方?/p>

需要注意的是,类似的加速VLAN间路由的手法多由各厂商独有的技术所实现,并且该功能的称谓也因厂商而异。例如,在Cisco的Catalyst系列交换机上,这种功能被称为“多层交换”(Multi Layer Switching)。另外,除了三层交换机的内部路由模块,外部路由器中的某些机型也支持类似的高速VLAN间路由机制?/p>

传统型路由器存在的意?/strong>

1.路由器的必要?/p>

三层交换机的价格,在问世之初非常昂贵,但是现在它们的价格已经下降了许多。目前国外一些廉价机型的售价,折合成人民币后仅为一万多元,而且还在继续下降中?/p>

既然三层交换机能够提供比传统型路由器更为高速的路由处理,那么网络中还有使用路由器的必要?

答案是:“?rdquo;?/p>

使用路由器的必要性,主要表现在以下几个方面:

(1)用于与WAN连接

三层交换机终究是“交换?rdquo;。也就是说,绝大多数机型只配有LAN(以太?接口。在少数高端交换机上也有用于连接WAN的串行接口或是ATM接口,但在大多数情况下,连接WAN还是需要用到路由器?/p>

(2)保证网络安全

在三层交换机上,通过数据包过滤也能确保一定程度的网络安全。但是使用路由器所提供的各种网络安全功能,用户可以构建更为安全可靠的网络?/p>

路由器提供的网络安全功能中,除了最基本的数据包过滤功能外,还能基于IPSec构建VPN(VirtualPrivate Network)、利用RADIUS进行用户认证等等?/p>

(3)支持除TCP/IP以外的异构网络架?/p>

尽管TCP/IP已经成为当前网络协议架构的主流,但还有不少网络利用Novell Netware下的IPX/SPX或Macintosh下的AppleTalk等网络协议。三层交换机中,除了部分高端机型外基本上还只支持TCP/IP。因此,在需要使用除TCP/IP之外其他网络协议的环境下,路由器还是必不可少的?/p>

注:在少数高端交换机上,也能支持上述路由器的功能。例如Cisco的Catalyst 6500系列,就可以选择与WAN连接的接口模?还有可选的基于IPSec实现VPN的模?并且也能支持TCP/IP以外的其他网络协议?/p>

2.路由器和交换机配合构建LAN的实?/p>

下面让我们来看一个路由器和交换机搭配构建LAN的实例?/p>

利用在各楼层配置的二层交换机定义VLAN,连接TCP/IP客户计算机。各楼层间的VLAN间通信,利用三层交换机的高速路由加以实现。如果网络环境要求高可靠性,还可以考虑冗余配置三层交换机?/p>

与WAN的连接,则通过带有各种网络接口的路由器进行。并且,通过路由器的数据包过滤和VPN等功能实现网络安全。此外,使用路由器还能支持Novell Netware等TCP/IP之外的网络?/p>

只有在充分掌握了二层、三层交换机以及传统路由器的基础上,才能做到物竞其用,构筑出高效率、高性价比的网络?/p>

使用VLAN设计局域网

1.使用VLAN设计局域网的特?/p>

通过使用VLAN构建局域网,用户能够不受物理链路的限制而自由地分割广播域?/p>

另外,通过先前提到的路由器与三层交换机提供的VLAN间路由,能够适应灵活多变的网络构成?/p>

但是,由于利用VLAN容易导致网络构成复杂化,因此也会造成整个网络的组成难以把握?/p>

可以这样说,在利用VLAN时,除了?ldquo;网络构成灵活多变”这个优点外,还搭配着“网络构成复杂?rdquo;这个缺点?/p>

下面,就让我们来看看具体的实例?/p>

2.不使用VLAN的局域网中网络构成的改变

假设有如图所示的?台路由器?台交换机构成?ldquo;不使用VLAN构建”的网络?/p>

图中的路由器,带?个LAN接口。左侧的网络?92.168.1.0/24,右侧是192.168.2.0/24?/p>

现在如果想将192.168.1.0/24这个网络上的计算机A转移?92.168.2.0/24上去,就需要改变物理连接、将A接到右侧的交换机上?/p>

并且,当需要新增一个地址?92.168.3.0/24的网络时,还要在路由器上再占用一个LAN接口并添置一台交换机。而由于这台路由器上只带了2个LAN接口,因此为了新增网络还必须将路由器升级为带?个以上LAN接口的产品?/p>

3.使用VLAN的局域网中网络构成的改变

接下来再假设有一个由1台路由器?台交换机构成?ldquo;使用VLAN”的局域网。交换机与交换机、交换机与路由器之间均为汇聚链路;并且假设192.168.1.0/24对应红色VLAN?92.168.2.0/24对应蓝色VLAN?/p>

需要将连接在交换机1?92.168.1.0/24这个网段的计算机A转属192.168.2.0/24时,无需更改物理布线。只要在交换机上生成蓝色VLAN,然后将计算机A所连的端口1加入到蓝色VLAN中去,使它成为访问链接即可?/p>

然后,根据需要设定计算机A的IP地址、默认网关等信息就可以了。如果IP地址相关的设定是由DHCP获取的,那么在客户机方面无需进行任何设定修改,就可以在不同网段间移动?/p>

利用VLAN后,我们可以在免于改动任何物理布线的前提下,自由进行网络的逻辑设计。如果所处的工作环境恰恰需要经常改变网络布局,那么利用VLAN的优势就非常明显了?/p>

并且,当需要新增一个地址?92.168.3.0/24的网段时,也只需要在交换机上新建一个对?92.168.3.0/24的VLAN,并将所需的端口加入它的访问链路就可以了?/p>

如果网络环境中还需要利用外部路由器,则只要在路由器的汇聚端口上新增一个子接口的设定就可以完成全部操作,而不需要消耗更多的物理接口(LAN接口)。要使用的是三层交换机内部的路由模块,则只需要新设一个VLAN接口即可?/p>

网络环境的成长,往往是难以预测的,很可能经常会出现需要分割现有网络或是增加新网络的情况。而充分活用VLAN后,就可以轻易地解决这些问题?/p>

4.利用VLAN而导致的网络结构复杂?/p>

虽然利用VLAN可以灵活地构建网络,但是同时,它也带来了网络结构复杂化的问题?/p>

特别是由于数据流纵横交错,一旦发生故障时,准确定位并排除故障会比较困难?/p>

为了便于理解数据流向的复杂化,假设有下图所示的网络。计算机A向计算机C发送数据时,数据流的整体走向如下:

计算机A→交换?→路由?rarr;交换?→交换?→计算机C

首先计算机A向交换机1送出数据(?,其后数据被转发给路由器(?进行VLAN间路由。路由后的数据,再从汇聚链路返回交换?(?。由于通信目标计算机C并不直连在交换机1上,因此还需要经过汇聚链路转发到交换?(?。在交换?上,数据最终被转发到C所连的端口2上,这才完成整个流程(??/p>

在这个例子中,仅?台交换机构成网络,其数据流已经如此复杂,如果构建横跨多台交换机的VLAN的话,每个数据流的流向显然会更加难以把握?/p>

5. 网络的逻辑结构与物理结?/p>

为了对应日渐复杂化的数据流,管理员需要从“逻辑结构”?ldquo;物理结构”两方面入手,把握好网络的现状?/p>

物理结构,指的是从物理层和数据链路层观察到的网络的现状,表示了网络的物理布线形态和VLAN的设定等等?/p>

而逻辑结构,则表示从网络层以上的层面观察到的网络结构。下面我们就试着以路由器为中心分析一个IP网络的逻辑结构?/p>

还是先前的那个例子,描绘了布线形态和VLAN设定?ldquo;物理结构”如下图所示?/p>

分析这个物理结构并转换成以路由器为中心的逻辑结构后,会得到如下的逻辑结构图。当我们需要进行路由或是数据包过滤的设定时,都必须在逻辑结构的基础上进行?/p>

把握这两种网络结构图的区别是十分重要的,特别是在VLAN和三层交换机大行其道的现代企业级网络当中?/p>]]>软件开?/category>http://www.cckinglong.com/software/771.html#commenthttp://www.cckinglong.com/http://www.cckinglong.com/feed.asp?cmt=771http://www.cckinglong.com/cmd.asp?act=tb&id=771&key=c0a9ef08SSH电商项目实战之十:商品类基本模块的搭?/title><author>a@b.com (鸡啄?</author><link>http://www.cckinglong.com/software/770.html</link><pubDate>Wed, 07 Mar 2018 08:41:55 +0800</pubDate><guid>http://www.cckinglong.com/software/770.html</guid><description><![CDATA[<p>      前面我们完成了与商品类别相关的业务逻辑,接下来我们开始做具体商品部分?/p><p>  <span style="font-size: medium;"><strong>1. 数据库建表并映射Model</strong></span></p><p>  首先我们在数据库中新建一张表,然后使用逆向工程将表映射成Model类,表如下:</p><div class="codeText"><div class="codeHead">SQL代码</div><ol start="1" class="dp-sql"> <li class="alt"><span><span>/*=============================*/    </span></span></li> <li><span>/* <span class="keyword">Table</span><span>: 商品表结?nbsp;           */    </span></span></li> <li class="alt"><span>/*=============================*/    </span></li> <li><span><span class="keyword">create</span><span> </span><span class="keyword">table</span><span> product    </span></span></li> <li class="alt"><span>(    </span></li> <li><span>   /* 商品编号,自动增长 */    </span></li> <li class="alt"><span>   id                  <span class="keyword">int</span><span> </span><span class="keyword">primary</span><span> </span><span class="keyword">key</span><span> </span><span class="op">not</span><span> </span><span class="op">null</span><span> auto_increment,    </span></span></li> <li><span>   /* 商品名称 */    </span></li> <li class="alt"><span>   <span class="keyword">name</span><span>                </span><span class="keyword">varchar</span><span>(20),    </span></span></li> <li><span>   /* 商品价格 */    </span></li> <li class="alt"><span>   price               <span class="keyword">decimal</span><span>(8,2),    </span></span></li> <li><span>   /* 商品图片 */    </span></li> <li class="alt"><span>   pic                 <span class="keyword">varchar</span><span>(200),    </span></span></li> <li><span>   /* 商品简单介?nbsp;*/    </span></li> <li class="alt"><span>   remark              longtext,    </span></li> <li><span>   /* 商品详细介绍 */    </span></li> <li class="alt"><span>   xremark             longtext,    </span></li> <li><span>   /* 商品生产日期 */    </span></li> <li class="alt"><span>   <span class="keyword">date</span><span>                </span><span class="keyword">timestamp</span><span> </span><span class="keyword">default</span><span> </span><span class="func">CURRENT_TIMESTAMP</span><span>,    </span></span></li> <li><span>   /* 是否为推荐商?推荐商品才有可能显示在商城首?nbsp;*/    </span></li> <li class="alt"><span>   commend             bool,    </span></li> <li><span>   /* 是否为有效商?有效商品才有可能显示在商城首?nbsp;*/    </span></li> <li class="alt"><span>   <span class="keyword">open</span><span>                bool,    </span></span></li> <li><span>   /* 商品所在的类别编号*/    </span></li> <li class="alt"><span>   cid                  <span class="keyword">int</span><span>,    </span></span></li> <li><span>   <span class="keyword">constraint</span><span> cid_FK </span><span class="keyword">foreign</span><span> </span><span class="keyword">key</span><span>(cid) </span><span class="keyword">references</span><span> category(id)    </span></span></li> <li class="alt"><span>);    </span></li></ol></div><p>  使用逆向工程映射为Model类就不赘述了,前面有提到如何使用逆向工程生成Model?/p><p> <span style="font-size: medium;"><strong> 2. 完成商品类的Service层和Action的架?/strong></span></p><p>  <strong>2.1 商品类的Service层架?/strong></p><p>  与前面category一样,product也得有个service来操作与商品相关的业务逻辑,所以我们得写一个ProductService和ProductServiceImpl的架构出来,具体如下?/p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="comment">//ProductService接口继承BaseService<Product>  </span><span>  </span></span></li> <li><span><span class="keyword">public</span><span> </span><span class="keyword">interface</span><span> ProductService </span><span class="keyword">extends</span><span> BaseService<Product> {    </span></span></li> <li class="alt"><span>        </span></li> <li><span>}    </span></li> <li class="alt"><span>    </span></li> <li><span><span class="comment">//ProductServiceImpl实现类继承BaseServiceImpl<Product>,并实现上面的ProductService接口  </span><span>  </span></span></li> <li class="alt"><span><span class="annotation">@Service</span><span>(</span><span class="string">"productService"</span><span>)    </span></span></li> <li><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> ProductServiceImpl </span><span class="keyword">extends</span><span> BaseServiceImpl<Product> </span><span class="keyword">implements</span><span> ProductService {    </span></span></li> <li class="alt"><span>    </span></li> <li><span>}    </span></li></ol></div><p>  <strong>2.2 商品类的Action架构</strong></p><p>  首先得完善一下BaseAction中关于Service层的注解</p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="annotation">@Controller</span><span>(</span><span class="string">"baseAction"</span><span>)    </span></span></li> <li><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> BaseAction<T> </span><span class="keyword">extends</span><span> ActionSupport </span><span class="keyword">implements</span><span> RequestAware,SessionAware,ApplicationAware,ModelDriven<T> {    </span></span></li> <li><span>    </span></li> <li class="alt"><span>    <span class="annotation">@Resource</span><span>    </span></span></li> <li><span>    <span class="keyword">protected</span><span> ProductService productService;    </span></span></li> <li class="alt"><span>    </span></li> <li><span>        <span class="comment">//其他代码省略,还是原来的代码……    </span><span>  </span></span></li> <li class="alt"><span>}  </span></li></ol></div><p>  然后我们写一个ProductAction继承该方法:</p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> ProductAction </span><span class="keyword">extends</span><span> BaseAction<Product> {    </span></span></li> <li><span>        </span></li> <li class="alt"><span>}    </span></li></ol></div><p>  至此,关于商品的后台架构就基本搭建好了,接下来就是完善里面的具体功能和业务逻辑了?/p><p>  <span style="font-size: medium;"><strong>3. 完成前台的基本结?/strong></span></p><p>  前台的基本结构和商品类的一样,我们看一下已经完成的商品类的前台都有哪些文件?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160510214952052.png" alt="SSH电商项目实战之十:商品类基本模块的搭? /></p><p>  我们先根据其商品类的前台文件,拷贝一份到product文件夹中,然后我们再做相应的修改。先来分析一下流程:首先index.jsp到aindex.jsp显示左侧菜单栏,当点击类别管理时,进入category/query.jsp页面右侧显示所有商品类别信息,搜索和删除功能均在此页面,不需要弹出新的窗口,添加弹出save.jsp窗口,更新弹出update.jsp窗口。当点击商品管理的时候,进入product/query.jsp页面右侧显示所有商品信息,搜索和删除功能均在此页面完成,添加和更新分别弹出save.jsp和update.jsp。接下来我们把各个页面的框架搭建好,然后往相应的部分填东西即可?/p><p>  首先在aindex.jsp中添加如下代码:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160510215734655.png" width="600" height="281" alt="SSH电商项目实战之十:商品类基本模块的搭? /></p><p>  接下来,我们完成query.jsp的框架:</p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span>%@ page </span><span class="attribute">language</span><span>=</span><span class="attribute-value">"java"</span><span> </span><span class="attribute">import</span><span>=</span><span class="attribute-value">"java.util.*"</span><span> </span><span class="attribute">pageEncoding</span><span>=</span><span class="attribute-value">"UTF-8"</span><span>%</span><span class="tag">></span><span>    </span></span></li> <li><span><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"<span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"><</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"><</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span>%@ include </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"/public/head.jspf"</span><span> %</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">style</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/css"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        body {    </span></li> <li><span>            margin: 1px;    </span></li> <li class="alt"><span>        }    </span></li> <li><span>        .searchbox {    </span></li> <li class="alt"><span>          margin: -3;    </span></li> <li><span>        }    </span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">style</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        $(function(){    </span></li> <li><span>            $('#dg').datagrid({       </span></li> <li class="alt"><span>                //url地址改为请求productAction中的queryJoinCategory方法    </span></li> <li><span>                url:'product_queryJoinCategory.action',    </span></li> <li class="alt"><span>                loadMsg:'Loading......',    </span></li> <li><span>                queryParams:{name:''},//这里参数改成name,参数值为空,表示我们要显示所有商品,后台是根据商品name属性查询的    </span></li> <li class="alt"><span>                //width:300,    </span></li> <li><span>                fitColumns:true,    </span></li> <li class="alt"><span>                striped:true,    </span></li> <li><span>                nowrap:true,    </span></li> <li class="alt"><span>                singleSelect:false,    </span></li> <li><span>                pagination:true,    </span></li> <li class="alt"><span>                pageSize:5,    </span></li> <li><span>                pageList:[5,10,15,20],    </span></li> <li class="alt"><span>                idField:'id',//指定id为标识字段,在删除,更新的时候有用,如果配置此字段,在翻页时,换页不会影响选中的项    </span></li> <li><span>                    </span></li> <li class="alt"><span>                //toolbar定义添加、删除、更新按钮以及搜索框    </span></li> <li><span>                toolbar: [{    </span></li> <li class="alt"><span>                    iconCls: 'icon-add',    </span></li> <li><span>                    text:'添加商品',    </span></li> <li class="alt"><span>                    handler: function(){    </span></li> <li><span>                        //添加触发代码    </span></li> <li class="alt"><span>                    }    </span></li> <li><span>                 },'-',{    </span></li> <li class="alt"><span>                    iconCls: 'icon-edit',    </span></li> <li><span>                    text:'更新商品',    </span></li> <li class="alt"><span>                    handler: function(){    </span></li> <li><span>                                            //添加触发代码    </span></li> <li class="alt"><span>                    }    </span></li> <li><span>                 },'-',{    </span></li> <li class="alt"><span>                    iconCls: 'icon-remove',    </span></li> <li><span>                     text:'删除商品',    </span></li> <li class="alt"><span>                    handler: function(){    </span></li> <li><span>                        //添加触发代码                        </span></li> <li class="alt"><span>                    }    </span></li> <li><span>                },'-',{ //查询按钮不是LinkButton,它有语法,但是也支持解析HTML标签    </span></li> <li class="alt"><span>                    text:"<span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">'ss'</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">'serach'</span><span> </span><span class="tag">/></span><span>"    </span></span></li> <li><span>                }],    </span></li> <li class="alt"><span>                rowStyler: function(index,row){    </span></li> <li><span>                    console.info("index" + index + "," + row)    </span></li> <li class="alt"><span>                    if(index % <span class="attribute">2</span><span> == 0) {    </span></span></li> <li><span>                        return 'background-color:#fff;';    </span></li> <li class="alt"><span>                    } else {    </span></li> <li><span>                        return 'background-color:#c4e1e1;';    </span></li> <li class="alt"><span>                    }    </span></li> <li><span>                        </span></li> <li class="alt"><span>                 },    </span></li> <li><span>                frozenColumns:[[    </span></li> <li class="alt"><span>                     {field:'checkbox',checkbox:true},    </span></li> <li><span>                    {field:'id',title:'商品编号',width:100}       </span></li> <li class="alt"><span>                 ]],    </span></li> <li><span>                columns:[[                         </span></li> <li class="alt"><span>                    {field:'name',title:'商品名称',width:100},        </span></li> <li><span>                    {field:'price',title:'商品价格',width:100},    </span></li> <li class="alt"><span>                    {field:'remark',title:'简单描?,width:100},    </span></li> <li><span>                    {field:'xremark',title:'详细描述',width:100},    </span></li> <li class="alt"><span>                    {field:'date',title:'上架时间',width:100},    </span></li> <li><span>                    {field:'commend',title:'推荐商品',width:100,      </span></li> <li class="alt"><span>                        formatter: function(value,row,index){    </span></li> <li><span>                            if(value) {    </span></li> <li class="alt"><span>                                return "<span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">'checkbox'</span><span> </span><span class="attribute">checked</span><span>=</span><span class="attribute-value">'checked'</span><span> </span><span class="attribute">disabled</span><span>=</span><span class="attribute-value">'true'</span><span>";    </span></span></li> <li><span>                            } else {    </span></li> <li class="alt"><span>                                return "<span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">'checkbox'</span><span> </span><span class="attribute">disabled</span><span>=</span><span class="attribute-value">'true'</span><span>";    </span></span></li> <li><span>                            }    </span></li> <li class="alt"><span>                         }    </span></li> <li><span>                    },    </span></li> <li class="alt"><span>                    {field:'open',title:'有效商品',width:100,      </span></li> <li><span>                        formatter: function(value,row,index){    </span></li> <li class="alt"><span>                            if(value) {    </span></li> <li><span>                                return "<span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">'checkbox'</span><span> </span><span class="attribute">checked</span><span>=</span><span class="attribute-value">'checked'</span><span> </span><span class="attribute">disabled</span><span>=</span><span class="attribute-value">'true'</span><span>";    </span></span></li> <li class="alt"><span>                            } else {    </span></li> <li><span>                                return "<span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">'checkbox'</span><span> </span><span class="attribute">disabled</span><span>=</span><span class="attribute-value">'true'</span><span>";    </span></span></li> <li class="alt"><span>                            }    </span></li> <li><span>                        }    </span></li> <li class="alt"><span>                     },    </span></li> <li><span>                    {field:'category.type',title:'所属商品类?,width:200, //category.type是商品类?nbsp;   </span></li> <li class="alt"><span>                        formatter: function(value,row,index){    </span></li> <li><span>                            if(row.category != null && row.category.type != null) {    </span></li> <li class="alt"><span>                                return row.category.type; //如果商品类别不为空,返回商品类别    </span></li> <li><span>                            } else {    </span></li> <li class="alt"><span>                                return "此商品暂时未分类";    </span></li> <li><span>                            }    </span></li> <li class="alt"><span>                         }      </span></li> <li><span>                    }    </span></li> <li class="alt"><span>                ]]        </span></li> <li><span>            });     </span></li> <li class="alt"><span>            //把普通的文本框转化为查询搜索文本?nbsp;   </span></li> <li><span>            $('#ss').searchbox({     </span></li> <li class="alt"><span>                //触发查询事件    </span></li> <li><span>                 searcher:function(value,name){ //value表示输入的?nbsp;   </span></li> <li class="alt"><span>                    //添加触发代码    </span></li> <li><span>                },     </span></li> <li class="alt"><span>                prompt:'请输入搜索关键字'     </span></li> <li><span>            });     </span></li> <li class="alt"><span>        });    </span></li> <li><span>    <span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>  <span class="tag"></</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li><span>      </span></li> <li class="alt"><span>  <span class="tag"><</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">table</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dg"</span><span class="tag">></span><span class="tag"></</span><span class="tag-name">table</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        </span></li> <li><span>  <span class="tag"></</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li></ol></div><p>  接下来我们完成productAction中的queryJoinCategory方法,在这之前,先要完成service部分,我们都是先从底层慢慢往上开发的?/p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="comment">//ProductService接口  </span><span>  </span></span></li> <li><span><span class="keyword">public</span><span> </span><span class="keyword">interface</span><span> ProductService </span><span class="keyword">extends</span><span> BaseService<Product> {    </span></span></li> <li class="alt"><span>        </span></li> <li><span>    <span class="comment">//查询商品信息,级联类?nbsp; </span><span>  </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> List<Product> queryJoinCategory(String type, </span><span class="keyword">int</span><span> page, </span><span class="keyword">int</span><span> size); </span><span class="comment">//使用商品的名称查?nbsp; </span><span>  </span></span></li> <li><span>    <span class="comment">//根据关键字查询总记录数  </span><span>  </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> Long getCount(String type);    </span></span></li> <li><span>}    </span></li> <li class="alt"><span>    </span></li> <li><span><span class="annotation">@SuppressWarnings</span><span>(</span><span class="string">"unchecked"</span><span>)    </span></span></li> <li class="alt"><span><span class="annotation">@Service</span><span>(</span><span class="string">"productService"</span><span>)    </span></span></li> <li><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> ProductServiceImpl </span><span class="keyword">extends</span><span> BaseServiceImpl<Product> </span><span class="keyword">implements</span><span> ProductService {    </span></span></li> <li class="alt"><span>    </span></li> <li><span>    <span class="annotation">@Override</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> List<Product> queryJoinCategory(String name, </span><span class="keyword">int</span><span> page, </span><span class="keyword">int</span><span> size) {    </span></span></li> <li><span>        String hql = <span class="string">"from Product p left join fetch p.category where p.name like :name"</span><span>;    </span></span></li> <li class="alt"><span>        <span class="keyword">return</span><span> getSession().createQuery(hql)    </span></span></li> <li><span>                .setString(<span class="string">"name"</span><span>, </span><span class="string">"%"</span><span> + name + </span><span class="string">"%"</span><span>)    </span></span></li> <li class="alt"><span>                .setFirstResult((page-<span class="number">1</span><span>) * size) </span><span class="comment">//从第几个开始显?nbsp; </span><span>  </span></span></li> <li><span>                .setMaxResults(size) <span class="comment">//显示几个  </span><span>  </span></span></li> <li class="alt"><span>                .list();    </span></li> <li><span>    }    </span></li> <li class="alt"><span>        </span></li> <li><span>    <span class="annotation">@Override</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> Long getCount(String name) {    </span></span></li> <li><span>        String hql = <span class="string">"select count(p) from Product p where p.name like :name"</span><span>;    </span></span></li> <li class="alt"><span>        <span class="keyword">return</span><span> (Long) getSession().createQuery(hql)    </span></span></li> <li><span>            .setString(<span class="string">"name"</span><span>, </span><span class="string">"%"</span><span> + name + </span><span class="string">"%"</span><span>)    </span></span></li> <li class="alt"><span>            .uniqueResult(); <span class="comment">//返回一条记?总记录数  </span><span>  </span></span></li> <li><span>    }    </span></li> <li class="alt"><span>    </span></li> <li><span>}    </span></li></ol></div><p>  下面可以完成productAction中的queryJoinCategory方法了:</p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="annotation">@Controller</span><span>(</span><span class="string">"productAction"</span><span>)    </span></span></li> <li><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> ProductAction </span><span class="keyword">extends</span><span> BaseAction<Product> {    </span></span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="keyword">public</span><span> String queryJoinCategory() {    </span></span></li> <li><span>        System.out.println(<span class="string">"name:"</span><span> + model.getName());    </span></span></li> <li class="alt"><span>        System.out.println(<span class="string">"page?quot;</span><span> + page);    </span></span></li> <li><span>        System.out.println(<span class="string">"rows?quot;</span><span> + rows);    </span></span></li> <li class="alt"><span>            </span></li> <li><span>        <span class="comment">//用来存储分页的数?nbsp; </span><span>  </span></span></li> <li class="alt"><span>        pageMap = <span class="keyword">new</span><span> HashMap<String, Object>();    </span></span></li> <li><span>            </span></li> <li class="alt"><span>        <span class="comment">//根据关键字和分页的参数查询相应的数据  </span><span>  </span></span></li> <li><span>        List<Product> productList = productService.queryJoinCategory(model.getName(), page, rows);    </span></li> <li class="alt"><span>        pageMap.put(<span class="string">"rows"</span><span>, productList); </span><span class="comment">//存储为JSON格式  </span><span>  </span></span></li> <li><span>        <span class="comment">//根据关键字查询总记录数  </span><span>  </span></span></li> <li class="alt"><span>        Long total = productService.getCount(model.getName());    </span></li> <li><span><span class="comment">//      System.out.println(total);  </span><span>  </span></span></li> <li class="alt"><span>        pageMap.put(<span class="string">"total"</span><span>, total); </span><span class="comment">//存储为JSON格式  </span><span>  </span></span></li> <li><span>        <span class="keyword">return</span><span> </span><span class="string">"jsonMap"</span><span>;    </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>    </span></li> <li class="alt"><span>}    </span></li></ol></div><p>  接下来在struts.xml中进行配置,跟之前的商品类一样的流程,到这里可以看出,开发好了一个,下面一个就快了?/p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span class="tag-name">action</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"product_*"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"productAction"</span><span> </span><span class="attribute">method</span><span>=</span><span class="attribute-value">"{1}"</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"jsonMap"</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"json"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">param</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"root"</span><span class="tag">></span><span>pageMap</span><span class="tag"></</span><span class="tag-name">param</span><span class="tag">></span><span>    </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">param</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"excludeProperties"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>            <span class="comments"><!-- rows[0].category.account --></span><span>    </span></span></li> <li><span>            <span class="comments"><!-- 把所有account过滤掉,否则会出现懒加载问题,该部分下面截图 --></span><span>             </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">param</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">action</span><span class="tag">></span><span>    </span></span></li></ol></div><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160510232107192.png" width="600" height="45" alt="SSH电商项目实战之十:商品类基本模块的搭? /></p><p>  这样后台程序写好了,然后开启tomcat,测试一下,当我们点击左侧菜单栏的商品管理时,会弹出右边如下窗口?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160510230756250.png" width="600" height="233" alt="SSH电商项目实战之十:商品类基本模块的搭? /></p><p>  这样我们就完成了商品管理窗口的框架了?/p><p> </p>]]></description><category>软件开?/category><comments>http://www.cckinglong.com/software/770.html#comment</comments><wfw:comment>http://www.cckinglong.com/</wfw:comment><wfw:commentRss>http://www.cckinglong.com/feed.asp?cmt=770</wfw:commentRss><trackback:ping>http://www.cckinglong.com/cmd.asp?act=tb&id=770&key=2398712e</trackback:ping></item><item><title>SSH电商项目实战之九:添加和更新商品类别功能的实?/title><author>a@b.com (鸡啄?</author><link>http://www.cckinglong.com/software/769.html</link><pubDate>Tue, 24 Oct 2017 14:14:05 +0800</pubDate><guid>http://www.cckinglong.com/software/769.html</guid><description><![CDATA[<p>  上一节我们做完了查询和删除商品的功能,这一节我们做一下添加和更新商品的功能?/p><p>  <span style="font-size: medium;"><strong>1. 添加商品类别</strong></span></p><p>  <strong>1.1 添加类别的UI设计</strong></p><p>  我们先说一下思路:首先当用户点击“添加商品”时,我们应该弹出一?ldquo;添加商品”的UI窗口(注意这里不是跳转到新的jsp,EasyUI只有一个页面),弹出这?ldquo;添加商品”的窗口后,应该锁住它父类的所有窗口(即点击其他地方无效,只能操作添加商品的窗口),等用户填好了信息后,在新弹出来的窗口上点击“添加”后,将请求发送给struts2,然后struts2拿到请求你参数,从数据库中执行添加动作,这样后台操作完成,同时前台那边要刷新一下当前页面,重新显示所有商品?/p><p>  我们查看EasyUI的文档,发现新建一个窗口有两种方法,要么使用标签创建,要么使用js创建,我们这里使用js创建,但是需要一?lt;div>盒子,如下:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160509095158085.png" alt="SSH电商项目实战之九:添加和更新商品类别功能的实? /></p><p>  另外,我们创建的新的窗口不需要最小化,最大化,但是要锁屏。所以这些属性都在div中设置好,这里要注意的就是锁屏的功能,因?lt;div>放的地方不同,锁住的屏幕范围也不同,我们要锁住全屏,所以要?lt;div>放到aindex.jsp中,应为aindex.jsp中产生了query.jsp的内容(包括添加按钮),query.jsp中产生了save.jsp的内容(就是我们要显示的添加窗口UI),所以弹出窗口后,我们要把aindex.jsp的范围都锁住,所?lt;div>应该放到aindex.jsp中,具体实现如下?/p><p>  在aindex.jsp?lt;body>中新添加一?lt;div></p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"win"</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"collapsible:false,minimizable:false,maximizable:false,modal:true"</span><span class="tag">></span><span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>     </span></span></li></ol></div><p>  然后我们完善query.jsp中添加类别的部分?/p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"> <li class="alt"><span><span>{    </span></span></li> <li><span>    iconCls: <span class="string">'icon-add'</span><span>,    </span></span></li> <li class="alt"><span>    text:<span class="string">'添加类别'</span><span>,    </span></span></li> <li><span>    handler: <span class="keyword">function</span><span>(){    </span></span></li> <li class="alt"><span>        parent.$(<span class="string">"#win"</span><span>).window({ </span><span class="comment">//因为<div>放在了aindex.jsp中,所以这里创建窗口要先调用parent  </span><span>  </span></span></li> <li><span>            title:<span class="string">"添加类别"</span><span>,    </span></span></li> <li class="alt"><span>            width:350,    </span></li> <li><span>            height:150,    </span></li> <li class="alt"><span>            content:<span class="string">'<iframe src="send_category_save.action" frameborder="0" width="100%" height="100%"/>'</span><span>    </span></span></li> <li><span>        });    </span></li> <li class="alt"><span>    }    </span></li> <li><span>}    </span></li></ol></div><p>  从上面的添加类别代码中可以看出,添加后的UI,我们引入WEB-INF/category目录下的save.jsp文件中的内容,接下来我们完成save.jsp?/p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span>%@ page </span><span class="attribute">language</span><span>=</span><span class="attribute-value">"java"</span><span> </span><span class="attribute">import</span><span>=</span><span class="attribute-value">"java.util.*"</span><span> </span><span class="attribute">pageEncoding</span><span>=</span><span class="attribute-value">"UTF-8"</span><span>%</span><span class="tag">></span><span>      </span></span></li> <li><span><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"<span class="tag">></span><span>      </span></span></li> <li class="alt"><span><span class="tag"><</span><span class="tag-name">html</span><span class="tag">></span><span>      </span></span></li> <li><span>  <span class="tag"><</span><span class="tag-name">head</span><span class="tag">></span><span>      </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span>%@ include </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"/public/head.jspf"</span><span> %</span><span class="tag">></span><span>      </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">style</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/css"</span><span class="tag">></span><span>      </span></span></li> <li class="alt"><span>        form div {      </span></li> <li><span>            margin:5px;      </span></li> <li class="alt"><span>        }      </span></li> <li><span>    <span class="tag"></</span><span class="tag-name">style</span><span class="tag">></span><span>      </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span class="tag">></span><span>      </span></span></li> <li><span>        $(function(){      </span></li> <li class="alt"><span>            $("input[<span class="attribute">name</span><span>=</span><span class="attribute-value">type</span><span>]").validatebox({ //这里?ldquo;类别名称”的验证功能,如果用户没填好就提交的话,会有提?nbsp;     </span></span></li> <li><span>                required:true,      </span></li> <li class="alt"><span>                missingMessage:'请输入类别名? //提示的内?nbsp;     </span></li> <li><span>            });           </span></li> <li class="alt"><span>      </span></li> <li><span>                    //对管理员的下拉列表框进行远程加载      </span></li> <li class="alt"><span>                    $("#cc").combobox({         </span></li> <li><span>                        //将请求发送给accountAction中的query方法处理,这里需要将处理好的数据返回到这边来显示?nbsp;,所以后台需要将数据打包成json格式发过?nbsp;     </span></li> <li class="alt"><span>                        url:'account_query.action',        </span></li> <li><span>                        valueField:'id',          </span></li> <li class="alt"><span>                        textField:'login', //我们下拉列表中显示的是管理员的登录名      </span></li> <li><span>                        panelHeight:'auto', //自适应高度      </span></li> <li class="alt"><span>                        panelWidth:120,//下拉列表是两个组件组成的      </span></li> <li><span>                        width:120, //要同时设置两个宽度才?nbsp;     </span></li> <li class="alt"><span>                        editable:false //下拉框不允许编辑      </span></li> <li><span>                     });      </span></li> <li class="alt"><span>      </span></li> <li><span>            //窗体弹出默认是禁用验证,因为刚弹出的窗口,用户还没填就显示的话,太丑      </span></li> <li class="alt"><span>            $("#ff").form("disableValidation");      </span></li> <li><span>            //注册button的事件。即当用户点?ldquo;添加”的时候做的事      </span></li> <li class="alt"><span>            $("#btn").click(function(){      </span></li> <li><span>                //开启验?nbsp;     </span></li> <li class="alt"><span>                $("#ff").form("enableValidation");      </span></li> <li><span>                //如果验证成功,则提交数据      </span></li> <li class="alt"><span>                if($("#ff").form("validate")) {      </span></li> <li><span>                    //调用submit方法提交数据      </span></li> <li class="alt"><span>                    $("#ff").form('submit', {      </span></li> <li><span>                        url: 'category_save.action', //将请求提交给categoryAction中的save方法处理      </span></li> <li class="alt"><span>                        success: function(){ //成功?nbsp;     </span></li> <li><span>                            //如果成功了,关闭当前窗口      </span></li> <li class="alt"><span>                            parent.$("#win").window("close");      </span></li> <li><span>                            //刷新页面,刚刚添加的就显示出来了?nbsp;     </span></li> <li class="alt"><span>                                                        //获取aindex--<span class="tag">></span><span>iframe--</span><span class="tag">></span><span>datagrid      </span></span></li> <li><span>                            parent.$("iframe[<span class="attribute">title</span><span>=</span><span class="attribute-value">'类别管理'</span><span>]").get(0).contentWindow.$("#dg").datagrid("reload");      </span></span></li> <li class="alt"><span>                        }      </span></li> <li><span>                    });      </span></li> <li class="alt"><span>                }      </span></li> <li><span>            });      </span></li> <li class="alt"><span>        });      </span></li> <li><span>    <span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span>      </span></span></li> <li class="alt"><span>  <span class="tag"></</span><span class="tag-name">head</span><span class="tag">></span><span>      </span></span></li> <li><span>        </span></li> <li class="alt"><span>  <span class="tag"><</span><span class="tag-name">body</span><span class="tag">></span><span>      </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">form</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"ff"</span><span> </span><span class="attribute">method</span><span>=</span><span class="attribute-value">"post"</span><span class="tag">></span><span>         </span></span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">div</span><span class="tag">></span><span>         </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">label</span><span> </span><span class="attribute">for</span><span>=</span><span class="attribute-value">"name"</span><span class="tag">></span><span>商品名称:</span><span class="tag"></</span><span class="tag-name">label</span><span class="tag">></span><span> </span><span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"type"</span><span> </span><span class="tag">/></span><span>         </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>         </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">div</span><span class="tag">></span><span>      </span></span></li> <li class="alt"><span>                <span class="tag"><</span><span class="tag-name">label</span><span class="tag">></span><span>所属管理员?/span><span class="tag"></</span><span class="tag-name">label</span><span class="tag">></span><span>       </span></span></li> <li><span>                <span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"cc"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"account.id"</span><span class="tag">/></span><span>      </span></span></li> <li class="alt"><span>            <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>      </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">div</span><span class="tag">></span><span>         </span></span></li> <li class="alt"><span>            <span class="tag"><</span><span class="tag-name">label</span><span> </span><span class="attribute">for</span><span>=</span><span class="attribute-value">"hot"</span><span class="tag">></span><span>热点:</span><span class="tag"></</span><span class="tag-name">label</span><span class="tag">></span><span>         </span></span></li> <li><span>                ?span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"radio"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"hot"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span> </span><span class="tag">/></span><span>       </span></span></li> <li class="alt"><span>                ?nbsp;<span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"radio"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"hot"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span> </span><span class="tag">/></span><span>      </span></span></li> <li><span>        <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>        </span></span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">div</span><span class="tag">></span><span>      </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">a</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"btn"</span><span> </span><span class="attribute">href</span><span>=</span><span class="attribute-value">"#"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"easyui-linkbutton"</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"iconCls:'icon-add'"</span><span class="tag">></span><span>添加</span><span class="tag"></</span><span class="tag-name">a</span><span class="tag">></span><span>        </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>        </span></span></li> <li><span>    <span class="tag"></</span><span class="tag-name">form</span><span class="tag">></span><span>         </span></span></li> <li class="alt"><span>  <span class="tag"></</span><span class="tag-name">body</span><span class="tag">></span><span>      </span></span></li> <li><span><span class="tag"></</span><span class="tag-name">html</span><span class="tag">></span></span></li></ol></div><p>  前台的显示以及发送请求都做完了,接下来就是做后台的程序了?/p><p>  <strong>1.2 添加类别的逻辑实现</strong></p><p>  前台会把数据发送给categoryAction中的save方法去执行,所以我们去写Action就行了,因为后台只需要将类别添加进数据库,不需要向前台返回数据,所以比较简单,直接写好action就行了:</p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="annotation">@Controller</span><span>(</span><span class="string">"categoryAction"</span><span>)    </span></span></li> <li><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> CategoryAction </span><span class="keyword">extends</span><span> BaseAction<Category> {    </span></span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="comment">//省略其他代码……  </span><span>  </span></span></li> <li><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> save() {    </span></span></li> <li class="alt"><span>        System.out.println(model);    </span></li> <li><span>        categoryService.save(model);    </span></li> <li class="alt"><span>    }    </span></li> <li><span>    </span></li> <li class="alt"><span>}    </span></li></ol></div><p>  这样数据就存入数据库了,完了后,前台那边刷新显示,就能将新添加的商品类别显示出来了,我们看一?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160511212557944.png" width="600" height="278" alt="SSH电商项目实战之九:添加和更新商品类别功能的实? /></p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160511212734837.png" style="text-align: start;" width="600" height="259" alt="SSH电商项目实战之九:添加和更新商品类别功能的实? /></p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160509101443157.png" alt="SSH电商项目实战之九:添加和更新商品类别功能的实? style="text-align: start;" /></p><p>  添加商品类别这一块我们就做完了。下面做更新商品类别那块?/p><p>  <span style="font-size: medium;"><strong>2. 更新商品类别</strong></span></p><p>  <strong>2.1 更新类别的UI设计</strong></p><p>  更新商品类别的思路和上面的添加的基本相同,首先也是弹出一个UI窗口,然后用户填好数据发送给后台,后台更新数据库,前台再刷新显示。我们仍然采用上面的方法创建一个UI窗口?lt;div>盒子不用改动什么,我们需要做的就是在query.jsp中完善更“更新类别”部分的代码:</p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"> <li class="alt"><span><span>{    </span></span></li> <li><span>    iconCls: <span class="string">'icon-edit'</span><span>,    </span></span></li> <li class="alt"><span>    text:<span class="string">'更新类别'</span><span>,    </span></span></li> <li><span>    handler: <span class="keyword">function</span><span>(){    </span></span></li> <li class="alt"><span>        <span class="comment">//判断是否有选中行记录,使用getSelections获取选中的所有行  </span><span>  </span></span></li> <li><span>        <span class="keyword">var</span><span> rows = $(</span><span class="string">"#dg"</span><span>).datagrid(</span><span class="string">"getSelections"</span><span>);    </span></span></li> <li class="alt"><span>        <span class="keyword">if</span><span>(rows.length == 0) {    </span></span></li> <li><span>            <span class="comment">//弹出提示信息  </span><span>  </span></span></li> <li class="alt"><span>            $.messager.show({ <span class="comment">//语法类似于java中的静态方法,直接对象调用  </span><span>  </span></span></li> <li><span>                title:<span class="string">'错误提示'</span><span>,    </span></span></li> <li class="alt"><span>                msg:<span class="string">'至少要选择一条记?</span><span>,    </span></span></li> <li><span>                timeout:2000,    </span></li> <li class="alt"><span>                showType:<span class="string">'slide'</span><span>,    </span></span></li> <li><span>            });    </span></li> <li class="alt"><span>        }<span class="keyword">else</span><span> </span><span class="keyword">if</span><span>(rows.length != 1) {    </span></span></li> <li><span>            <span class="comment">//弹出提示信息  </span><span>  </span></span></li> <li class="alt"><span>            $.messager.show({ <span class="comment">//语法类似于java中的静态方法,直接对象调用  </span><span>  </span></span></li> <li><span>                title:<span class="string">'错误提示'</span><span>,    </span></span></li> <li class="alt"><span>                msg:<span class="string">'每次只能更新一条记?</span><span>,    </span></span></li> <li><span>                timeout:2000,    </span></li> <li class="alt"><span>                showType:<span class="string">'slide'</span><span>,    </span></span></li> <li><span>            });    </span></li> <li class="alt"><span>        } <span class="keyword">else</span><span>{    </span></span></li> <li><span>            <span class="comment">//1. 弹出更新的页?nbsp; </span><span>  </span></span></li> <li class="alt"><span>            parent.$(<span class="string">"#win"</span><span>).window({    </span></span></li> <li><span>                title:<span class="string">"添加类别"</span><span>,    </span></span></li> <li class="alt"><span>                width:350,    </span></li> <li><span>                height:250,    </span></li> <li class="alt"><span>                content:<span class="string">'<iframe src="send_category_update.action" frameborder="0" width="100%" height="100%"/>'</span><span>    </span></span></li> <li><span>            });    </span></li> <li class="alt"><span>            <span class="comment">//2.   </span><span>  </span></span></li> <li><span>        }    </span></li> <li class="alt"><span>    }    </span></li> <li><span>}    </span></li></ol></div><p>  我们分析一下上面的js代码:首先获取用户勾选要更新的行,如果没有选中则提示用户至少需要选中一项纪录去更新,如果选中的不止一条纪录,也得提示用户每次只能更新一条纪录。当这些判断都结束后,保证了用户勾选了一条纪录,那么我们开始创建新的UI窗口了,这里还是跟上面一样,引入WEB-INF/category目录下的update.jsp页面的内容,我们来看下update.jsp页面内容?/p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span>%@ page </span><span class="attribute">language</span><span>=</span><span class="attribute-value">"java"</span><span> </span><span class="attribute">import</span><span>=</span><span class="attribute-value">"java.util.*"</span><span> </span><span class="attribute">pageEncoding</span><span>=</span><span class="attribute-value">"UTF-8"</span><span>%</span><span class="tag">></span><span>    </span></span></li> <li><span><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"<span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"><</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"><</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span>%@ include </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"/public/head.jspf"</span><span> %</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">style</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/css"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        form div {    </span></li> <li><span>            margin:5px;    </span></li> <li class="alt"><span>        }    </span></li> <li><span>    <span class="tag"></</span><span class="tag-name">style</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span class="tag">></span><span>    </span></span></li> <li><span>        $(function(){    </span></li> <li class="alt"><span>            //iframe中的datagrid对象    </span></li> <li><span>            var <span class="attribute">dg</span><span> = </span><span class="attribute-value">parent</span><span>.$("iframe[</span><span class="attribute">title</span><span>=</span><span class="attribute-value">'类别管理'</span><span>]").get(0).contentWindow.$("#dg");    </span></span></li> <li class="alt"><span>                </span></li> <li><span>            //对管理员的下拉列表框进行远程加载    </span></li> <li class="alt"><span>            $("#cc").combobox({       </span></li> <li><span>                //将请求发送给accountAction中的query方法处理,这里需要将处理好的数据返回到这边来显示?nbsp;,所以后台需要将数据打包成json格式发过?nbsp;   </span></li> <li class="alt"><span>                url:'account_query.action',      </span></li> <li><span>                valueField:'id',        </span></li> <li class="alt"><span>                textField:'login', //我们下拉列表中显示的是管理员的登录名    </span></li> <li><span>                panelHeight:'auto', //自适应高度    </span></li> <li class="alt"><span>                panelWidth:120,//下拉列表是两个组件组成的    </span></li> <li><span>                width:120, //要同时设置两个宽度才?nbsp;   </span></li> <li class="alt"><span>                editable:false //下拉框不允许编辑    </span></li> <li><span>             });      </span></li> <li class="alt"><span>                </span></li> <li><span>            // 完成数据的回显,更新时,用户肯定先选择了要更新的那一行,首先我们得拿到那一?nbsp;   </span></li> <li class="alt"><span>            var <span class="attribute">rows</span><span> = </span><span class="attribute-value">dg</span><span>.datagrid("getSelections");    </span></span></li> <li><span>            //将拿到的那一行对应的数据字段加载到表单里,实现回?nbsp;   </span></li> <li class="alt"><span>            $("#ff").form('load',{    </span></li> <li><span>                id:rows[0].id,    </span></li> <li class="alt"><span>                type:rows[0].type,    </span></li> <li><span>                    hot:rows[0].hot,    </span></li> <li class="alt"><span>                'account.id':rows[0].account.id //EasyUI不支持account.id这种点操作,所以要加个引号    </span></li> <li><span>            });    </span></li> <li class="alt"><span>    </span></li> <li><span>            //回显完了数据后,设置一下验证功?nbsp;   </span></li> <li class="alt"><span>            $("input[<span class="attribute">name</span><span>=</span><span class="attribute-value">type</span><span>]").validatebox({    </span></span></li> <li><span>                required:true,    </span></li> <li class="alt"><span>                missingMessage:'请输入类别名?    </span></li> <li><span>            });         </span></li> <li class="alt"><span>            //窗体弹出默认时禁用验?nbsp;   </span></li> <li><span>            $("#ff").form("disableValidation");    </span></li> <li class="alt"><span>            //注册button的事?nbsp;   </span></li> <li><span>            $("#btn").click(function(){    </span></li> <li class="alt"><span>                //开启验?nbsp;   </span></li> <li><span>                $("#ff").form("enableValidation");    </span></li> <li class="alt"><span>                //如果验证成功,则提交数据    </span></li> <li><span>                if($("#ff").form("validate")) {    </span></li> <li class="alt"><span>                    //调用submit方法提交数据    </span></li> <li><span>                    $("#ff").form('submit', {    </span></li> <li class="alt"><span>                        url: 'category_update.action', //提交时将请求传给categoryAction的update方法执行    </span></li> <li><span>                        success: function(){    </span></li> <li class="alt"><span>                            //如果成功了,关闭当前窗口,并刷新页面    </span></li> <li><span>                            parent.$("#win").window("close");    </span></li> <li class="alt"><span>                            dg.datagrid("reload");    </span></li> <li><span>                        }    </span></li> <li class="alt"><span>                    });    </span></li> <li><span>                }    </span></li> <li class="alt"><span>            });    </span></li> <li><span>        });    </span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"></</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>      </span></li> <li><span>  <span class="tag"><</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span class="tag-name">form</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"ff"</span><span> </span><span class="attribute">method</span><span>=</span><span class="attribute-value">"post"</span><span class="tag">></span><span>       </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>            <span class="tag"><</span><span class="tag-name">label</span><span> </span><span class="attribute">for</span><span>=</span><span class="attribute-value">"name"</span><span class="tag">></span><span>类别名称:</span><span class="tag"></</span><span class="tag-name">label</span><span class="tag">></span><span> </span><span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"type"</span><span> </span><span class="tag">/></span><span>       </span></span></li> <li><span>        <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">label</span><span> </span><span class="attribute">for</span><span>=</span><span class="attribute-value">"hot"</span><span class="tag">></span><span>热点:</span><span class="tag"></</span><span class="tag-name">label</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>                ?span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"radio"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"hot"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span> </span><span class="tag">/></span><span>     </span></span></li> <li><span>                ?span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"radio"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"hot"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"false"</span><span> </span><span class="tag">/></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>      </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>            <span class="tag"><</span><span class="tag-name">label</span><span> </span><span class="attribute">for</span><span>=</span><span class="attribute-value">"account"</span><span class="tag">></span><span>所属管理员:</span><span class="tag"></</span><span class="tag-name">label</span><span class="tag">></span><span>    </span></span></li> <li><span>             <span class="comments"><!-- 下拉列表我们采用远程加载的方法加载管理员数据 --></span><span>    </span></span></li> <li class="alt"><span>             <span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"cc"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"account.id"</span><span> </span><span class="tag">/></span><span>    </span></span></li> <li><span>        <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">div</span><span class="tag">></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">a</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"btn"</span><span> </span><span class="attribute">href</span><span>=</span><span class="attribute-value">"#"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"easyui-linkbutton"</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"iconCls:'icon-edit'"</span><span class="tag">></span><span>更新</span><span class="tag"></</span><span class="tag-name">a</span><span class="tag">></span><span>      </span></span></li> <li class="alt"><span>            <span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"hidden"</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"id"</span><span> </span><span class="tag">/></span><span>    </span></span></li> <li><span>        <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>  `    </span></span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">form</span><span class="tag">></span><span>       </span></span></li> <li><span>  <span class="tag"></</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li></ol></div><p>  更新与添加不同的地方在于,首先得数据回显,然后还有个下拉列表显示管理员数据,因为所属管理员也要更新。我们看看上面的代码,首先使用远程加载的方法加载管理员数据,先向后台发送一个请求,后台accountAction的query方法处理完后,管理员数据打包成json格式返回回来,这样就能拿到管理员数据了,拿到后,就可以进行数据的回显了。我们看一下后台的程序?/p><p>  <strong>2.2 更新类别的逻辑实现</strong></p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="annotation">@Controller</span><span>(</span><span class="string">"baseAction"</span><span>)    </span></span></li> <li><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> BaseAction<T> </span><span class="keyword">extends</span><span> ActionSupport </span><span class="keyword">implements</span><span> RequestAware,SessionAware,ApplicationAware,ModelDriven<T> {    </span></span></li> <li><span>    </span></li> <li class="alt"><span>    <span class="comment">//用来装有将要被打包成json格式返回给前台的数据,下面要实现get方法  </span><span>  </span></span></li> <li><span>    <span class="keyword">protected</span><span> List<T> jsonList = </span><span class="keyword">null</span><span>;    </span></span></li> <li class="alt"><span>    <span class="comment">//省略其他方法……  </span><span>  </span></span></li> <li><span>        </span></li> <li class="alt"><span>}    </span></li> <li><span>    </span></li> <li class="alt"><span><span class="comment">//AccountAction  </span><span>  </span></span></li> <li><span><span class="annotation">@Controller</span><span>(</span><span class="string">"accountAction"</span><span>)    </span></span></li> <li class="alt"><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> AccountAction </span><span class="keyword">extends</span><span> BaseAction<Account> {    </span></span></li> <li class="alt"><span>        </span></li> <li><span>    <span class="keyword">public</span><span> String query() {    </span></span></li> <li class="alt"><span>        jsonList = accountService.query();    </span></li> <li><span>        <span class="keyword">return</span><span> </span><span class="string">"jsonList"</span><span>;    </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>    </span></li> <li class="alt"><span>}    </span></li></ol></div><p>  接下来我们配置一下struts.xml文件?/p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span class="tag-name">action</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"account_*"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"accountAction"</span><span> </span><span class="attribute">method</span><span>=</span><span class="attribute-value">"{1}"</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"jsonList"</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"json"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">param</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"root"</span><span class="tag">></span><span>jsonList</span><span class="tag"></</span><span class="tag-name">param</span><span class="tag">></span><span>    </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">param</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"excludeProperties"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>            <span class="comments"><!-- [0].pass, [1].pass --></span><span>    </span></span></li> <li><span>            <span class="comments"><!-- 正则表达式显示有bug,我下面截个?nbsp;--></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">param</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">action</span><span class="tag">></span><span>    </span></span></li></ol></div><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160509105831494.png" alt="SSH电商项目实战之九:添加和更新商品类别功能的实? /></p><p>       完成回显后,就是更新操作了,当然也有验证的功能,和添加一样的,更新操作将请求传给categoryAction的update方法执行,比较简单:</p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="annotation">@Controller</span><span>(</span><span class="string">"categoryAction"</span><span>)    </span></span></li> <li><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> CategoryAction </span><span class="keyword">extends</span><span> BaseAction<Category> {    </span></span></li> <li><span>    <span class="comment">//省略其他方法……  </span><span>  </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> update() {    </span></span></li> <li><span>        System.out.println(model);    </span></li> <li class="alt"><span>        categoryService.update(model);    </span></li> <li><span>    }    </span></li> <li class="alt"><span>}    </span></li></ol></div><p>  到此,我们完成了商品类别的添加和更新操作?/p><p> </p>]]></description><category>软件开?/category><comments>http://www.cckinglong.com/software/769.html#comment</comments><wfw:comment>http://www.cckinglong.com/</wfw:comment><wfw:commentRss>http://www.cckinglong.com/feed.asp?cmt=769</wfw:commentRss><trackback:ping>http://www.cckinglong.com/cmd.asp?act=tb&id=769&key=ba59295b</trackback:ping></item><item><title>SSH电商项目实战之八:查询和删除商品类别功能的实?/title><author>a@b.com (鸡啄?</author><link>http://www.cckinglong.com/software/768.html</link><pubDate>Wed, 11 Oct 2017 09:18:20 +0800</pubDate><guid>http://www.cckinglong.com/software/768.html</guid><description><![CDATA[<p>  上一节我们完成了使用DataGrid显示所有商品信息,这节我们开始添加几个功能:添加、更新、删除和查询。首先我们实现下前台的显示,然后再做后台获取数据?/p><p>  <span style="font-size: medium;"><strong>1. 添加、更新、删除和查询功能的前台实?/strong></span></p><p>  DataGrid控件里有个toolbar属性,是添加工具栏的,我们可以在toolbar属性中添加这些按钮来实现相应的功能。先看一下官方文档对toolbar的定义:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160508101650902.png" width="600" height="334" alt="SSH电商项目实战之八:查询和删除商品类别功能的实? /></p><p>  我们使用数组的方式定义工具栏,在query.jsp页面中新添加如下代码?/p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span>%@ page </span><span class="attribute">language</span><span>=</span><span class="attribute-value">"java"</span><span> </span><span class="attribute">import</span><span>=</span><span class="attribute-value">"java.util.*"</span><span> </span><span class="attribute">pageEncoding</span><span>=</span><span class="attribute-value">"UTF-8"</span><span>%</span><span class="tag">></span><span>    </span></span></li> <li><span><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"<span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"><</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"><</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span>%@ include </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"/public/head.jspf"</span><span> %</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">style</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/css"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        body {    </span></li> <li><span>            margin: 1px;    </span></li> <li class="alt"><span>        }    </span></li> <li><span>                .searchbox {    </span></li> <li class="alt"><span>                        margin: -3;    </span></li> <li><span>                }    </span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">style</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        $(function(){    </span></li> <li><span>            $('#dg').datagrid({       </span></li> <li class="alt"><span>                //url地址改为请求categoryAction    </span></li> <li><span>                url:'category_queryJoinAccount.action',    </span></li> <li class="alt"><span>    </span></li> <li><span>                singleSelect:false, //如果为真,只允许单行显示,全选功能失?nbsp;   </span></li> <li class="alt"><span>                //设置分页    </span></li> <li><span>                pagination:true,    </span></li> <li class="alt"><span>                //设置每页显示的记录数,默认是10?nbsp;   </span></li> <li><span>                pageSize:5,    </span></li> <li class="alt"><span>                //设置可选的每页记录数,供用户选择,默认是10,20,30,40...    </span></li> <li><span>                pageList:[5,10,15,20],    </span></li> <li class="alt"><span>                idField:'id',//指定id为标识字段,在删除,更新的时候有用,如果配置此字段,在翻页时,换页不会影响选中的项    </span></li> <li><span>    </span></li> <li class="alt"><span>                     /*********************添加的代?**********************/    </span></li> <li><span>                toolbar: [{    </span></li> <li class="alt"><span>                    iconCls: 'icon-add',    </span></li> <li><span>                    text:'添加类别',    </span></li> <li class="alt"><span>                    handler: function(){    </span></li> <li><span>                        alert('--加添类别--');    </span></li> <li class="alt"><span>                    }    </span></li> <li><span>                },'-',{    </span></li> <li class="alt"><span>                    iconCls: 'icon-edit',    </span></li> <li><span>                    text:'更新类别',    </span></li> <li class="alt"><span>                    handler: function(){    </span></li> <li><span>                        alert('--更新类别--');    </span></li> <li class="alt"><span>                    }    </span></li> <li><span>                },'-',{    </span></li> <li class="alt"><span>                    iconCls: 'icon-remove',    </span></li> <li><span>                    text:'删除类别',    </span></li> <li class="alt"><span>                    handler: function(){    </span></li> <li><span>                        //判断是否有选中行记录,使用getSelections获取选中的所有行    </span></li> <li class="alt"><span>                        var <span class="attribute">rows</span><span> = $("#dg").datagrid("getSelections");    </span></span></li> <li><span>                        //返回被选中的行,如果没有任何行被选中,则返回空数?nbsp;   </span></li> <li class="alt"><span>                        if(<span class="attribute">rows.length</span><span> == 0) {    </span></span></li> <li><span>                            //弹出提示信息    </span></li> <li class="alt"><span>                            $.messager.show({ //语法类似于java中的静态方法,直接对象调用    </span></li> <li><span>                                title:'错误提示',    </span></li> <li class="alt"><span>                                msg:'至少要选择一条记?,    </span></li> <li><span>                                timeout:2000,    </span></li> <li class="alt"><span>                                showType:'slide',    </span></li> <li><span>                            });    </span></li> <li class="alt"><span>                        } else {    </span></li> <li><span>                            //提示是否确认删除,如果确认则执行删除的逻辑    </span></li> <li class="alt"><span>                            $.messager.confirm('删除的确认对话框', '您确定要删除此项吗?', function(r){    </span></li> <li><span>                                if (r){    </span></li> <li class="alt"><span>                                // 退出操?    </span></li> <li><span>                                    alert("--删除操作--")    </span></li> <li class="alt"><span>                                }    </span></li> <li><span>                            });    </span></li> <li class="alt"><span>                        }                           </span></li> <li><span>                    }    </span></li> <li class="alt"><span>                 },'-',{ //查询按钮不是LinkButton,它有语法,但是也支持解析HTML标签    </span></li> <li><span>                     text:"<span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">'ss'</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">'serach'</span><span> </span><span class="tag">/></span><span>"    </span></span></li> <li class="alt"><span>                 }],    </span></li> <li><span>                   </span></li> <li class="alt"><span>                //把普通的文本框转化为查询搜索文本?nbsp;   </span></li> <li><span>                $('#ss').searchbox({     </span></li> <li class="alt"><span>                    //触发查询事件    </span></li> <li><span>                    searcher:function(value,name){ //value表示输入的?nbsp;   </span></li> <li class="alt"><span>                                           //查询操作    </span></li> <li><span>                    },     </span></li> <li class="alt"><span>                    prompt:'请输入搜索关键字' //默认的显?nbsp;   </span></li> <li><span>                });     </span></li> <li class="alt"><span>               /*********************************************************************/    </span></li> <li><span>    </span></li> <li class="alt"><span>        });    </span></li> <li><span>    <span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>  <span class="tag"></</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li><span>      </span></li> <li class="alt"><span>  <span class="tag"><</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">table</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dg"</span><span class="tag">></span><span class="tag"></</span><span class="tag-name">table</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>  <span class="tag"></</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li><span><span class="tag"></</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li></ol></div><p>  这样我们就搭好了添加、更新、删除和查询的前台框架了,现在可以在前台显示了,后台没有数据过来,只是弹出个提示框,不过显示功能已经完成,看一下效果:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160508103319475.png" width="600" height="296" alt="SSH电商项目实战之八:查询和删除商品类别功能的实? /></p><p>  接下来我们逐个来完成相应的功能?/p><p>  <span style="font-size: medium;"><strong>2. DataGrid类别查询的实?/strong></span></p><p>  查询的实现是最简单的,在搜素框中输入关键字,然后将关键字作为参数传给action,然后Service从数据库中拿出数据,打包成json格式传到前台来显示即可,这个过程跟前面显示所有商品信息是一样的,我们只需要在上面jsp中添加搜索部分的代码即可,其他不用改变,添加的代码如下:</p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"> <li class="alt"><span><span class="comment">//把普通的文本框转化为查询搜索文本?nbsp; </span><span>  </span></span></li> <li><span>$(<span class="string">'#ss'</span><span>).searchbox({     </span></span></li> <li class="alt"><span>    <span class="comment">//触发查询事件  </span><span>  </span></span></li> <li><span>    searcher:<span class="keyword">function</span><span>(value,name){ </span><span class="comment">//value表示输入的?nbsp; </span><span>  </span></span></li> <li class="alt"><span>        <span class="comment">//alert(value + "," + name)  </span><span>  </span></span></li> <li><span>        <span class="comment">//获取当前查询的关键字,通过DataGrid加载相应的信息,使用load加载和显示第一页的所有行?nbsp; </span><span>  </span></span></li> <li class="alt"><span>        <span class="comment">//如果指定了参数,它将取代'queryParams'属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法会向上面url指定的action去发送请求,从服务器加载新数据?nbsp; </span><span>  </span></span></li> <li><span>        $(<span class="string">'#dg'</span><span>).datagrid(</span><span class="string">'load'</span><span>,{    </span></span></li> <li class="alt"><span>            type: value    </span></li> <li><span>        });    </span></li> <li class="alt"><span>    </span></li> <li><span>    },     </span></li> <li class="alt"><span>    prompt:<span class="string">'请输入搜索关键字'</span><span>     </span></span></li> <li><span>});     </span></li></ol></div><p>  load方法可以加载显示第一页的所有行,它有个参数,如果指定了,就会去带上么的queryParams,否则默认传递上面的queryParams指定的参数,我们在这里将type设置成value的值,即用户输入的查询关键字,然后传到action,后台根据用户输入的value在数据库中查找,并返回给前台。执行结果如下:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160508104755868.png" width="600" height="239" alt="SSH电商项目实战之八:查询和删除商品类别功能的实? /></p><p>  这样我便完成了搜索的功能了,比较简单?/p><p>  <span style="font-size: medium;"><strong>3. DataGrid类别删除的实?/strong></span></p><p>  现在我们来实现删除功能,从上面的jsp中可以看出,删除前判断用户有没有选中某条记录,如果没有则给用户一个提示,如果有选中,则弹出窗口让用户确认,如果为真,则执行删除功能。有个细节要注意下,如果想要一次性删除多条记录,那么上面的singleSelect属性要设置成false?/p><p>  首先,我们把上面query.jsp中删除部分的代码补充完,见下面:</p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"> <li class="alt"><span><span>{    </span></span></li> <li><span>    iconCls: <span class="string">'icon-remove'</span><span>,    </span></span></li> <li class="alt"><span>    text:<span class="string">'删除类别'</span><span>,    </span></span></li> <li><span>    handler: <span class="keyword">function</span><span>(){    </span></span></li> <li class="alt"><span>        <span class="comment">//判断是否有选中行记录,使用getSelections获取选中的所有行  </span><span>  </span></span></li> <li><span>        <span class="keyword">var</span><span> rows = $(</span><span class="string">"#dg"</span><span>).datagrid(</span><span class="string">"getSelections"</span><span>);    </span></span></li> <li class="alt"><span>        <span class="comment">//返回被选中的行,如果没有任何行被选中,则返回空数?nbsp; </span><span>  </span></span></li> <li><span>        <span class="keyword">if</span><span>(rows.length == 0) {    </span></span></li> <li class="alt"><span>            <span class="comment">//弹出提示信息  </span><span>  </span></span></li> <li><span>            $.messager.show({ <span class="comment">//语法类似于java中的静态方法,直接对象调用  </span><span>  </span></span></li> <li class="alt"><span>                title:<span class="string">'错误提示'</span><span>,    </span></span></li> <li><span>                msg:<span class="string">'至少要选择一条记?</span><span>,    </span></span></li> <li class="alt"><span>                timeout:2000,    </span></li> <li><span>                showType:<span class="string">'slide'</span><span>,    </span></span></li> <li class="alt"><span>            });    </span></li> <li><span>        } <span class="keyword">else</span><span> {    </span></span></li> <li class="alt"><span>            <span class="comment">//提示是否确认删除,如果确认则执行删除的逻辑  </span><span>  </span></span></li> <li><span>            $.messager.confirm(<span class="string">'删除的确认对话框'</span><span>, </span><span class="string">'您确定要删除此项吗?'</span><span>, </span><span class="keyword">function</span><span>(r){    </span></span></li> <li class="alt"><span>                <span class="keyword">if</span><span> (r){    </span></span></li> <li><span>                    <span class="comment">//1. 从获取的记录中获取相应的的id,拼接id的值,然后发送后?,2,3,4  </span><span>  </span></span></li> <li class="alt"><span>                    <span class="keyword">var</span><span> ids = </span><span class="string">""</span><span>;    </span></span></li> <li><span>                    <span class="keyword">for</span><span>(</span><span class="keyword">var</span><span> i = 0; i < rows.length; i ++) {    </span></span></li> <li class="alt"><span>                        ids += rows[i].id + <span class="string">","</span><span>;    </span></span></li> <li><span>                    }    </span></li> <li class="alt"><span>                    ids = ids.substr(0, ids.lastIndexOf(<span class="string">","</span><span>));    </span></span></li> <li><span>                    <span class="comment">//2. 发送ajax请求  </span><span>  </span></span></li> <li class="alt"><span>                    $.post(<span class="string">"category_deleteByIds.action"</span><span>,{ids:ids},</span><span class="keyword">function</span><span>(result){    </span></span></li> <li><span>                        <span class="keyword">if</span><span>(result == </span><span class="string">"true"</span><span>) {    </span></span></li> <li class="alt"><span>                                                <span class="comment">//将刚刚选中的记录删除,要不然会影响后面更新的操?nbsp; </span><span>  </span></span></li> <li><span>                                                $(<span class="string">"#dg"</span><span>).datagrid(</span><span class="string">"uncheckAll"</span><span>);    </span></span></li> <li class="alt"><span>                            <span class="comment">//刷新当前页,查询的时候我们用的是load,刷新第一页,reload是刷新当前页  </span><span>  </span></span></li> <li><span>                            $(<span class="string">"#dg"</span><span>).datagrid(</span><span class="string">"reload"</span><span>);</span><span class="comment">//不带参数默认为上面的queryParams  </span><span>  </span></span></li> <li class="alt"><span>                        } <span class="keyword">else</span><span> {    </span></span></li> <li><span>                            $.messager.show({     </span></li> <li class="alt"><span>                                title:<span class="string">'删除异常'</span><span>,    </span></span></li> <li><span>                                msg:<span class="string">'删除失败,请检查操?</span><span>,    </span></span></li> <li class="alt"><span>                                timeout:2000,    </span></li> <li><span>                                showType:<span class="string">'slide'</span><span>,    </span></span></li> <li class="alt"><span>                            });    </span></li> <li><span>                        }    </span></li> <li class="alt"><span>                    },<span class="string">"text"</span><span>);    </span></span></li> <li><span>                }    </span></li> <li class="alt"><span>            });    </span></li> <li><span>        }                           </span></li> <li class="alt"><span>    }    </span></li> <li><span>}    </span></li></ol></div><p>  如果用户选择删除,首先会弹出一个对话框,当用户确定要删除后,我们首先要获取用户所勾选的商品的id,将这些id拼接成一个字符串,然后向后台发送ajax请求?.post中的第一个参数是发送到那个action,第二个参数是发送的参数,第三个参数是回调函数,即删除成功后执行该函数里面的方法,该函数的参数result是从后台传过来的,第四个参数可有可无,是返回数据的类型。我们重点看?.post中的内容,当后台返回一?quot;true"表示删除成功了,那么我们调用DataGrid里面的reload方法重新刷新页面,reload和前面查询时用的load是一样的,不同的地方在于reload刷新后停留在当前页面,而load则显示第一页?/p><p>  好了,前台页面部分写好了,接下来完成后台的相应方法,首先在categoryService中添加deleteByIds方法,并在其实现类categoryServceImpl中实现该方法?/p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="comment">//categoryService接口  </span><span>  </span></span></li> <li><span><span class="keyword">public</span><span> </span><span class="keyword">interface</span><span> CategoryService </span><span class="keyword">extends</span><span> BaseService<Category> {    </span></span></li> <li class="alt"><span>    <span class="comment">//查询类别信息,级联管理员  </span><span>  </span></span></li> <li><span>    <span class="keyword">public</span><span> List<Category> queryJoinAccount(String type, </span><span class="keyword">int</span><span> page, </span><span class="keyword">int</span><span> size); </span><span class="comment">//使用类别的名称查?nbsp; </span><span>  </span></span></li> <li class="alt"><span>    <span class="comment">//根据关键字查询总记录数  </span><span>  </span></span></li> <li><span>    <span class="keyword">public</span><span> Long getCount(String type);    </span></span></li> <li class="alt"><span>    <span class="comment">//根据ids删除多条记录  </span><span>  </span></span></li> <li><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> deleteByIds(String ids);    </span></span></li> <li class="alt"><span>}    </span></li> <li><span>    </span></li> <li class="alt"><span><span class="comment">//categoryServiceImpl实现?nbsp; </span><span>  </span></span></li> <li><span><span class="annotation">@SuppressWarnings</span><span>(</span><span class="string">"unchecked"</span><span>)    </span></span></li> <li class="alt"><span><span class="annotation">@Service</span><span>(</span><span class="string">"categoryService"</span><span>)    </span></span></li> <li><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> CategoryServiceImpl </span><span class="keyword">extends</span><span> BaseServiceImpl<Category> </span><span class="keyword">implements</span><span> CategoryService {    </span></span></li> <li class="alt"><span>    </span></li> <li><span>    <span class="comment">//其他方法省略不写?hellip;…可以参照前面的相应章节内?nbsp; </span><span>  </span></span></li> <li class="alt"><span>    </span></li> <li><span>    <span class="annotation">@Override</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> deleteByIds(String ids) {    </span></span></li> <li><span>        String hql = <span class="string">"delete from Category c where c.id in ("</span><span> + ids + </span><span class="string">")"</span><span>;    </span></span></li> <li class="alt"><span>        getSession().createQuery(hql).executeUpdate();    </span></li> <li><span>    }    </span></li> <li class="alt"><span>}    </span></li></ol></div><p>  写好了Service部分,接下来开始写Action部分了。因为我们要获取前台传进来的ids数据,所以在action中得有一个实现了get和set方法的变量来接收这个数据,另外,我们要将结果传给前台,前面章节中我们做级联查询的时候,使用的方法是struts把查询的结果数据打包成json格式传给前台,所以需要一个Map,然后将通过配置文件中的配置,将Map转换成json格式。这里我们传到前台的数据比较简单,入股删除成功我们传一?quot;true"即可,所以不用打包成json格式,我们通过流的方法去传送,道理和前面的一样,首相我们得有一个流的对象去保存这个"true"的字节,然后通过配置,将这个对象通过流传到前台。这两个对象我们还是写在BaseAction中,如下?/p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="annotation">@Controller</span><span>(</span><span class="string">"baseAction"</span><span>)    </span></span></li> <li><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> BaseAction<T> </span><span class="keyword">extends</span><span> ActionSupport </span><span class="keyword">implements</span><span> RequestAware,SessionAware,ApplicationAware,ModelDriven<T> {    </span></span></li> <li><span>    </span></li> <li class="alt"><span>    <span class="comment">//获取要删除的ids,要有get和set方法  </span><span>  </span></span></li> <li><span>    <span class="comment">//流是用来想前台返回数据的,这个数据是让struts获取的,然后通过流的形式传到前台,所以实现get方法即可  </span><span>  </span></span></li> <li class="alt"><span>    <span class="keyword">protected</span><span> String ids;    </span></span></li> <li><span>    <span class="keyword">protected</span><span> InputStream inputStream;    </span></span></li> <li class="alt"><span>            </span></li> <li><span>        <span class="comment">//下面省略……  </span><span>  </span></span></li> <li class="alt"><span>}    </span></li></ol></div><p>  对应的CategoryAction中的方法如下?/p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="annotation">@Controller</span><span>(</span><span class="string">"categoryAction"</span><span>)    </span></span></li> <li><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> CategoryAction </span><span class="keyword">extends</span><span> BaseAction<Category> {    </span></span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="keyword">public</span><span> String queryJoinAccount() {    </span></span></li> <li><span>                <span class="comment">//?hellip;…  </span><span>  </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="keyword">public</span><span> String deleteByIds() {    </span></span></li> <li><span>        System.out.println(ids);    </span></li> <li class="alt"><span>        categoryService.deleteByIds(ids);    </span></li> <li><span>        <span class="comment">//如果删除成功就会往下执行,我们?quot;true"以流的形式传给前?nbsp; </span><span>  </span></span></li> <li class="alt"><span>        inputStream = <span class="keyword">new</span><span> ByteArrayInputStream(</span><span class="string">"true"</span><span>.getBytes()); </span><span class="comment">//?quot;true"的字节存到流inputStream?nbsp; </span><span>  </span></span></li> <li><span>        <span class="keyword">return</span><span> </span><span class="string">"stream"</span><span>;    </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>}    </span></li></ol></div><p>  接下来看struts.xml中相应的配置?/p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span class="tag-name">struts</span><span class="tag">></span><span>    </span></span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="tag"><</span><span class="tag-name">constant</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"struts.devMode"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span> </span><span class="tag">/></span><span>    </span></span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="tag"><</span><span class="tag-name">package</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"shop"</span><span> </span><span class="attribute">extends</span><span>=</span><span class="attribute-value">"json-default"</span><span class="tag">></span><span class="comments"><!-- jason-default继承了struts-default --></span><span>    </span></span></li> <li><span>        </span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">global-results</span><span class="tag">></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"aindex"</span><span class="tag">></span><span>/WEB-INF/main/aindex.jsp</span><span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">global-results</span><span class="tag">></span><span>    </span></span></li> <li><span>    </span></li> <li class="alt"><span>        <span class="comments"><!-- class对应的是Spring中配置该Action的id值,因为要交给Spring管理 --></span><span>    </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">action</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"category_*"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"categoryAction"</span><span> </span><span class="attribute">method</span><span>=</span><span class="attribute-value">"{1}"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>            <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"jsonMap"</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"json"</span><span class="tag">></span><span>    </span></span></li> <li><span>                <span class="comments"><!-- ?nbsp;--></span><span>    </span></span></li> <li class="alt"><span>            <span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"stream"</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"stream"</span><span class="tag">></span><span> </span><span class="comments"><!-- 以stream的形式,type为stream --></span><span>    </span></span></li> <li class="alt"><span>                <span class="tag"><</span><span class="tag-name">param</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"inputName"</span><span class="tag">></span><span>inputStream</span><span class="tag"></</span><span class="tag-name">param</span><span class="tag">></span><span> </span><span class="comments"><!-- imputStream中有要传的数?nbsp;--></span><span>    </span></span></li> <li><span>             <span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">action</span><span class="tag">></span><span>    </span></span></li> <li><span>            </span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">action</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"account_*"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"accountAction"</span><span> </span><span class="attribute">method</span><span>=</span><span class="attribute-value">"{1}"</span><span class="tag">></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"index"</span><span class="tag">></span><span>/index.jsp</span><span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">action</span><span class="tag">></span><span>    </span></span></li> <li><span>            </span></li> <li class="alt"><span>        <span class="comments"><!-- 用来完成系统 请求转发的action,所有的请求都交给execute--></span><span>    </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">action</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"send_*_*"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"sendAction"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>            <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"send"</span><span class="tag">></span><span>/WEB-INF/{1}/{2}.jsp</span><span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li><span>        <span class="tag"></</span><span class="tag-name">action</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">package</span><span class="tag">></span><span>    </span></span></li> <li><span>    </span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">struts</span><span class="tag">></span><span>   </span></span></li></ol></div><p>  这样我们就做好了删除的操作了,看一下效果:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160508150956670.png" width="600" height="260" alt="SSH电商项目实战之八:查询和删除商品类别功能的实? /></p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160508151059629.png" style="text-align: start;" width="600" height="231" alt="SSH电商项目实战之八:查询和删除商品类别功能的实? /></p><p>  测试成功,我们也可以一次性选择多项去删除,至此,删除功能做完了?/p>]]></description><category>软件开?/category><comments>http://www.cckinglong.com/software/768.html#comment</comments><wfw:comment>http://www.cckinglong.com/</wfw:comment><wfw:commentRss>http://www.cckinglong.com/feed.asp?cmt=768</wfw:commentRss><trackback:ping>http://www.cckinglong.com/cmd.asp?act=tb&id=768&key=f8b5b906</trackback:ping></item><item><title>SSH电商项目实战之七:Struts2和Json的整?/title><author>a@b.com (鸡啄?</author><link>http://www.cckinglong.com/software/767.html</link><pubDate>Wed, 27 Sep 2017 09:12:47 +0800</pubDate><guid>http://www.cckinglong.com/software/767.html</guid><description><![CDATA[<p>  上一节我们完成了DataGrid显示jason数据,但是没有和后台联系在一起,只是单纯地显示了我们自己弄的json数据,这一节我们将json和Struts2整合,打通EasyUI和Struts2之间的交互?/p><p>  <span style="font-size: medium;"><strong>1. json环境的搭?/strong></span></p><p>  json环境搭建很简单,导入json的jar包即可,如下?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160506215356091.png" alt="SSH电商项目实战之七:Struts2和Json的整? /></p><p>  (注:json-lib-2.4的jar包下载地址?a rel="nofollow" target="_blank">http://download.csdn.net/detail/eson_15/9514985</a> ?/p><p>  <span style="font-size: medium;"><strong>2. 完善Action</strong></span></p><p>  在DataGrid控件中有个属性是url,可以指定请求数据的url地址,在上一节我们将这个地址直接设置成了一个具体的json文件,这里我们将这个url设置成一个action,如url:'category_queryJoinAccount.action',表示会去请求categoryAction的queryJoinAccount方法(文章最后会给出query.jsp的代码)。所以我们需要去完成categoryAction中的queryJoinAccount方法?/p><p>  在Struts2和json整合前,我们先看一下之前显示一次json数据都发了哪些请求:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160507000025532.png" alt="SSH电商项目实战之七:Struts2和Json的整? /></p><p>  因为type是Category类的一个属性,我们在BaseAction中已经实现了ModelDriven<Category>接口,所以这个type会被封装到model中,我们不需要管它,可以通过model来获取,但是EasyUI自动发过来的page和rows参数我们需要自己获取了,所以我们可以在BaseModel中增加两个成员变量page和rows并实现get和set方法,最后还要考虑一点,这些参数都获得了后,我们根据这些参数去数据库中查询数据,那么我们查出来的数据放到哪呢?而且还要打包成json格式发到前台才能被DataGrid显示。我们先不考虑将查询到的数据如何打包成json格式,我们先考虑把这些数据放到一个地方,很自然的想到了使用Map,因为json格式的数据就是key-value形式的。想到这里,我们继续完善BaseAction?/p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="annotation">@Controller</span><span>(</span><span class="string">"baseAction"</span><span>)    </span></span></li> <li><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> BaseAction<T> </span><span class="keyword">extends</span><span> ActionSupport </span><span class="keyword">implements</span><span> RequestAware,SessionAware,ApplicationAware,ModelDriven<T> {    </span></span></li> <li><span>    </span></li> <li class="alt"><span>    <span class="comment">//page和rows和分页有关,pageMap存放查询的数据,然后打包成json格式用的  </span><span>  </span></span></li> <li><span>    <span class="comment">//page和rows实现get和set方法,pageMap只需要实现get方法即可,因为pageMap不是接收前台参数的,是让struts获取?nbsp; </span><span>  </span></span></li> <li class="alt"><span>    <span class="keyword">protected</span><span> Integer page;    </span></span></li> <li><span>    <span class="keyword">protected</span><span> Integer rows;    </span></span></li> <li class="alt"><span>    <span class="keyword">protected</span><span> Map<String, Object> pageMap = </span><span class="keyword">null</span><span>;</span><span class="comment">//让不同的Action自己去实?nbsp; </span><span>  </span></span></li> <li><span>        <span class="comment">//省略get和set方法……  </span><span>  </span></span></li> <li class="alt"><span>        </span></li> <li><span>    <span class="comment">/******************* 下面还是原来BaseAction部分 *************************/</span><span>    </span></span></li> <li class="alt"><span>    <span class="comment">//service对象  </span><span>  </span></span></li> <li><span>    <span class="annotation">@Resource</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">protected</span><span> CategoryService categoryService;    </span></span></li> <li><span>    <span class="annotation">@Resource</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">protected</span><span> AccountService accountService;    </span></span></li> <li><span>    </span></li> <li class="alt"><span>    <span class="comment">//域对?nbsp; </span><span>  </span></span></li> <li><span>    <span class="keyword">protected</span><span> Map<String, Object> request;    </span></span></li> <li class="alt"><span>    <span class="keyword">protected</span><span> Map<String, Object> session;    </span></span></li> <li><span>    <span class="keyword">protected</span><span> Map<String, Object> application;    </span></span></li> <li class="alt"><span>            </span></li> <li><span>    <span class="annotation">@Override</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setApplication(Map<String, Object> application) {    </span></span></li> <li><span>        <span class="keyword">this</span><span>.application = application;    </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>    <span class="annotation">@Override</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setSession(Map<String, Object> session) {    </span></span></li> <li><span>        <span class="keyword">this</span><span>.session = session;    </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>    <span class="annotation">@Override</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> </span><span class="keyword">void</span><span> setRequest(Map<String, Object> request) {    </span></span></li> <li><span>        <span class="keyword">this</span><span>.request = request;    </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="comment">//ModelDriven  </span><span>  </span></span></li> <li><span>    <span class="keyword">protected</span><span> T model;    </span></span></li> <li class="alt"><span>    <span class="annotation">@Override</span><span>    </span></span></li> <li><span>    <span class="keyword">public</span><span> T getModel() {    </span></span></li> <li class="alt"><span>        ParameterizedType type = (ParameterizedType)<span class="keyword">this</span><span>.getClass().getGenericSuperclass();    </span></span></li> <li><span>        Class clazz = (Class)type.getActualTypeArguments()[<span class="number">0</span><span>];    </span></span></li> <li class="alt"><span>        <span class="keyword">try</span><span> {    </span></span></li> <li><span>            model = (T)clazz.newInstance();    </span></li> <li class="alt"><span>        } <span class="keyword">catch</span><span> (Exception e) {    </span></span></li> <li><span>            <span class="keyword">throw</span><span> </span><span class="keyword">new</span><span> RuntimeException(e);    </span></span></li> <li class="alt"><span>        }       </span></li> <li><span>        <span class="keyword">return</span><span> model;    </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>}    </span></li></ol></div><p>  好,完善了BaseCategory后,我们可以写categoryAction中的queryJoinAccount方法了,我们将categoryAction中原来的方法全删掉,因为那些都是之前搭建环境时候测试用的,都不用了,现在真正开始项目代码了?/p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="annotation">@Controller</span><span>(</span><span class="string">"categoryAction"</span><span>)    </span></span></li> <li><span><span class="annotation">@Scope</span><span>(</span><span class="string">"prototype"</span><span>)    </span></span></li> <li class="alt"><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> CategoryAction </span><span class="keyword">extends</span><span> BaseAction<Category> {    </span></span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="keyword">public</span><span> String queryJoinAccount() {    </span></span></li> <li><span>    </span></li> <li class="alt"><span>        <span class="comment">//用来存储分页的数?nbsp; </span><span>  </span></span></li> <li><span>        pageMap = <span class="keyword">new</span><span> HashMap<String, Object>();    </span></span></li> <li class="alt"><span>            </span></li> <li><span>        <span class="comment">//根据关键字和分页的参数查询相应的数据。这个方法我们在Service中写过了,当时完成级联查?nbsp; </span><span>  </span></span></li> <li class="alt"><span>        List<Category> categoryList = categoryService.queryJoinAccount(model.getType(), page, rows);    </span></li> <li><span>        pageMap.put(<span class="string">"rows"</span><span>, categoryList); </span><span class="comment">//存储为JSON格式,从上一节的json文件可以看出,一个key是total,一个key是rows,这里先把rows存放?nbsp; </span><span>  </span></span></li> <li class="alt"><span>        <span class="comment">//根据关键字查询总记录数  </span><span>  </span></span></li> <li><span>        Long total = categoryService.getCount(model.getType()); <span class="comment">//这个方法没写,我们等会儿去Service层完善一?nbsp; </span><span>  </span></span></li> <li class="alt"><span><span class="comment">//      System.out.println(total);  </span><span>  </span></span></li> <li><span>        pageMap.put(<span class="string">"total"</span><span>, total); </span><span class="comment">//存储为JSON格式,再把total存放?nbsp; </span><span>  </span></span></li> <li class="alt"><span>    </span></li> <li><span>        <span class="keyword">return</span><span> </span><span class="string">"jsonMap"</span><span>;    </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>}    </span></li></ol></div><p>  这样Action我们就写好了,现在Action拿到前台传来的参数,然后根据参数查询了指定type的总记录数,以及指定type的所有商品,并且按照json中指定的key(即total和rows)进行存放,放在HashMap中了,之后只要将这个HashMap中的数据打包成json格式发送到前台就可以被DataGrid显示了。我们先把这个HashMap放这,先去完善了Service层的代码后,再来打包这个HashMap中的数据?/p><p>  <span style="font-size: medium;"><strong>3. 完善categoryService</strong></span></p><p>  从上面的categoryAction中可知,需要在categoryService中增加一个getCount方法,并且要在具体实现类中实现好,实现如下:</p><div class="codeText"><div class="codeHead">Java代码</div><ol start="1" class="dp-j"> <li class="alt"><span><span class="comment">//CategoryService接口  </span><span>  </span></span></li> <li><span><span class="keyword">public</span><span> </span><span class="keyword">interface</span><span> CategoryService </span><span class="keyword">extends</span><span> BaseService<Category> {    </span></span></li> <li class="alt"><span>    <span class="comment">//查询类别信息,级联管理员  </span><span>  </span></span></li> <li><span>    <span class="keyword">public</span><span> List<Category> queryJoinAccount(String type, </span><span class="keyword">int</span><span> page, </span><span class="keyword">int</span><span> size); </span><span class="comment">//使用类别的名称查?nbsp; </span><span>  </span></span></li> <li class="alt"><span>    <span class="comment">//根据关键字查询总记录数  </span><span>  </span></span></li> <li><span>    <span class="keyword">public</span><span> Long getCount(String type);    </span></span></li> <li class="alt"><span>}    </span></li> <li><span>    </span></li> <li class="alt"><span><span class="comment">//CategoryServiceImpl实现?nbsp; </span><span>  </span></span></li> <li><span><span class="annotation">@SuppressWarnings</span><span>(</span><span class="string">"unchecked"</span><span>)    </span></span></li> <li class="alt"><span><span class="annotation">@Service</span><span>(</span><span class="string">"categoryService"</span><span>)    </span></span></li> <li><span><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> CategoryServiceImpl </span><span class="keyword">extends</span><span> BaseServiceImpl<Category> </span><span class="keyword">implements</span><span> CategoryService {    </span></span></li> <li class="alt"><span>    </span></li> <li><span>    <span class="annotation">@Override</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> List<Category> queryJoinAccount(String type, </span><span class="keyword">int</span><span> page, </span><span class="keyword">int</span><span> size) {    </span></span></li> <li><span>        String hql = <span class="string">"from Category c left join fetch c.account where c.type like :type"</span><span>;    </span></span></li> <li class="alt"><span>        <span class="keyword">return</span><span> getSession().createQuery(hql)    </span></span></li> <li><span>                .setString(<span class="string">"type"</span><span>, </span><span class="string">"%"</span><span> + type + </span><span class="string">"%"</span><span>)    </span></span></li> <li class="alt"><span>                .setFirstResult((page-<span class="number">1</span><span>) * size) </span><span class="comment">//从第几个开始显?nbsp; </span><span>  </span></span></li> <li><span>                .setMaxResults(size) <span class="comment">//显示几个  </span><span>  </span></span></li> <li class="alt"><span>                .list();    </span></li> <li><span>    }    </span></li> <li class="alt"><span>    </span></li> <li><span>    <span class="annotation">@Override</span><span>    </span></span></li> <li class="alt"><span>    <span class="keyword">public</span><span> Long getCount(String type) {    </span></span></li> <li><span>        String hql = <span class="string">"select count(c) from Category c where c.type like :type"</span><span>;    </span></span></li> <li class="alt"><span>        <span class="keyword">return</span><span> (Long) getSession().createQuery(hql)    </span></span></li> <li><span>            .setString(<span class="string">"type"</span><span>, </span><span class="string">"%"</span><span> + type + </span><span class="string">"%"</span><span>)    </span></span></li> <li class="alt"><span>            .uniqueResult(); <span class="comment">//返回一条记?总记录数  </span><span>  </span></span></li> <li><span>    }    </span></li> <li class="alt"><span>}    </span></li></ol></div><p>  到现在为止,这个数据库中数据的获取这条路就打通了,前面两步完成了从前?->数据?->取数据,接下来就开始打包HashMap中存放的数据,然后发给前台了?/p><p>  <span style="font-size: medium;"><strong>4. 配置struts.xml</strong></span></p><p>  在struts.xml中通过配置就可以完成对指定数据的打包,我们先看一下struts.xml中的配置?/p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span class="tag-name">struts</span><span class="tag">></span><span>    </span></span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="tag"><</span><span class="tag-name">constant</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"struts.devMode"</span><span> </span><span class="attribute">value</span><span>=</span><span class="attribute-value">"true"</span><span> </span><span class="tag">/></span><span>    </span></span></li> <li><span>        </span></li> <li class="alt"><span>    <span class="tag"><</span><span class="tag-name">package</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"shop"</span><span> </span><span class="attribute">extends</span><span>=</span><span class="attribute-value">"json-default"</span><span class="tag">></span><span class="comments"><!-- jason-default继承了struts-default --></span><span>    </span></span></li> <li><span>        </span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">global-results</span><span class="tag">></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"aindex"</span><span class="tag">></span><span>/WEB-INF/main/aindex.jsp</span><span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">global-results</span><span class="tag">></span><span>    </span></span></li> <li><span>    </span></li> <li class="alt"><span>        <span class="comments"><!-- class对应的是Spring中配置该Action的id值,因为要交给Spring管理 --></span><span>    </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">action</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"category_*"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"categoryAction"</span><span> </span><span class="attribute">method</span><span>=</span><span class="attribute-value">"{1}"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>            <span class="comments"><!-- 必须要先添加json包,然后上面继承json-default --></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"jsonMap"</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"json"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>                <span class="comments"><!-- 要转换成json对象的数?nbsp;--></span><span>    </span></span></li> <li><span>                <span class="tag"><</span><span class="tag-name">param</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"root"</span><span class="tag">></span><span>pageMap</span><span class="tag"></</span><span class="tag-name">param</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>                <!-- 配置黑名单,过滤不需要的选项 ,支持正则表达式    </span></li> <li><span>                json格式:{total:3,rows:[{account:{id:2,login:"user",name:"客服A",pass:"user"},hot:true,id:3,…}]}    </span></li> <li class="alt"><span>                --<span class="tag">></span><span>    </span></span></li> <li><span>                <span class="tag"><</span><span class="tag-name">param</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"excludeProperties"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>                    <span class="comments"><!-- rows[0].account.pass--></span><span>    </span></span></li> <li><span>                                        <span class="comments"><!-- 这里显示不了正则表达式, CSDN的一个bug,我接个图放下面 --></span><span>    </span></span></li> <li class="alt"><span>                <span class="tag"></</span><span class="tag-name">param</span><span class="tag">></span><span>    </span></span></li> <li><span>            <span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">action</span><span class="tag">></span><span>    </span></span></li> <li><span>            </span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">action</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"account_*"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"accountAction"</span><span> </span><span class="attribute">method</span><span>=</span><span class="attribute-value">"{1}"</span><span class="tag">></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"index"</span><span class="tag">></span><span>/index.jsp</span><span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"></</span><span class="tag-name">action</span><span class="tag">></span><span>    </span></span></li> <li><span>            </span></li> <li class="alt"><span>        <span class="comments"><!-- 用来完成系统 请求转发的action,所有的请求都交给execute--></span><span>    </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">action</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"send_*_*"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"sendAction"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>            <span class="tag"><</span><span class="tag-name">result</span><span> </span><span class="attribute">name</span><span>=</span><span class="attribute-value">"send"</span><span class="tag">></span><span>/WEB-INF/{1}/{2}.jsp</span><span class="tag"></</span><span class="tag-name">result</span><span class="tag">></span><span>    </span></span></li> <li><span>        <span class="tag"></</span><span class="tag-name">action</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">package</span><span class="tag">></span><span>    </span></span></li> <li><span>    </span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">struts</span><span class="tag">></span><span>    </span></span></li></ol></div><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160506235402701.png" alt="SSH电商项目实战之七:Struts2和Json的整? /></p><p>  从上面的配置可以看出,首先package要继承json-default,因为json-default继承了struts-default,因为在json的jar包里有个struts2-json-plugin-2.3.24.1.jar,打开即可看到里面有个struts-plugin.xml,打开即可看到json-default是继承了struts-default?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160507000224276.png" width="600" height="369" alt="SSH电商项目实战之七:Struts2和Json的整? /></p><p>  接下来我配置<result>,name是刚刚action返回的字符串,type一定要配成json。然后就是result中的参数了,首先必须要配的就是name为root的参数,这个参数要配成刚刚需要转换的HashMap对象,即我们定义的pageMap,有了这个参数的配置,struts才会将pageMap中的数据打包成json格式。然后就是配置黑名单,黑名单的意思就是告诉struts在打包的时候,哪些字段不需要打包,比如管理员密码之类的信息,由上面注释中的jason格式可以看出rows[0].account.pass表示密码字段,但是数据肯定不止一条,所以我们得用正则表达式来表示,这样所有密码都不会被打包到json中?/p><p>  <span style="font-size: medium;"><strong>5. 修改query.jsp内容</strong></span></p><p>  到此,我们已经将数据打包成了json格式了,接下来我们完善一下前台query.jsp的内容就可以让DataGrid正确显示了:</p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span>%@ page </span><span class="attribute">language</span><span>=</span><span class="attribute-value">"java"</span><span> </span><span class="attribute">import</span><span>=</span><span class="attribute-value">"java.util.*"</span><span> </span><span class="attribute">pageEncoding</span><span>=</span><span class="attribute-value">"UTF-8"</span><span>%</span><span class="tag">></span><span>    </span></span></li> <li><span><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"<span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"><</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"><</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span>%@ include </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"/public/head.jspf"</span><span> %</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        $(function(){    </span></li> <li><span>            $('#dg').datagrid({       </span></li> <li class="alt"><span>                //url地址改为请求categoryAction    </span></li> <li><span>                url:'category_queryJoinAccount.action',    </span></li> <li class="alt"><span>                loadMsg:'Loading......',    </span></li> <li><span>                queryParams:{type:''},//type参数,这里不需要传具体的type,因为我们要显示所有的    </span></li> <li class="alt"><span>                //width:300,    </span></li> <li><span>                fitColumns:true,    </span></li> <li class="alt"><span>                striped:true,    </span></li> <li><span>                nowrap:true,    </span></li> <li class="alt"><span>                singleSelect:true,    </span></li> <li><span>                pagination:true,    </span></li> <li class="alt"><span>                rowStyler: function(index,row){    </span></li> <li><span>                    console.info("index" + index + "," + row)    </span></li> <li class="alt"><span>                    if(index % <span class="attribute">2</span><span> == 0) {    </span></span></li> <li><span>                        return 'background-color:#fff;';    </span></li> <li class="alt"><span>                    } else {    </span></li> <li><span>                        return 'background-color:#ff0;';    </span></li> <li class="alt"><span>                    }    </span></li> <li><span>                        </span></li> <li class="alt"><span>                },          </span></li> <li><span>                frozenColumns:[[    </span></li> <li class="alt"><span>                    {field:'checkbox',checkbox:true},    </span></li> <li><span>                    {field:'id',title:'编号',width:200}    //这里的field字段要和json数据中的一?nbsp;                </span></li> <li class="alt"><span>                ]],    </span></li> <li><span>                columns:[[                         </span></li> <li class="alt"><span>                    {field:'type',title:'类别名称',width:100, //字段type    </span></li> <li><span>                        formatter: function(value,row,index){    </span></li> <li class="alt"><span>                            return "<span class="tag"><</span><span class="tag-name">span</span><span> </span><span class="attribute">title</span><span>=</span><span class="attribute-value">" + value + "</span><span class="tag">></span><span>" + value + "</span><span class="tag"></</span><span class="tag-name">span</span><span class="tag">></span><span>";    </span></span></li> <li><span>                        }    </span></li> <li class="alt"><span>                    },        </span></li> <li><span>                    {field:'hot',title:'热卖',width:100,  //字段hot    </span></li> <li class="alt"><span>                        formatter: function(value,row,index){    </span></li> <li><span>                            if(value) { //如果是hot,该值为true,value是boolean型变?nbsp;   </span></li> <li class="alt"><span>                                return "<span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">'checkbox'</span><span> </span><span class="attribute">checked</span><span>=</span><span class="attribute-value">'checked'</span><span> </span><span class="attribute">disabled</span><span>=</span><span class="attribute-value">'true'</span><span>"; //勾?nbsp;   </span></span></li> <li><span>                            } else {    </span></li> <li class="alt"><span>                                return "<span class="tag"><</span><span class="tag-name">input</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">'checkbox'</span><span> </span><span class="attribute">disable</span><span>=</span><span class="attribute-value">'true'</span><span>"; //不勾?nbsp;   </span></span></li> <li><span>                            }    </span></li> <li class="alt"><span>                        }    </span></li> <li><span>                    },    </span></li> <li class="alt"><span>                    {field:'account.login',title:'所属管理员',width:200, //account.login管理员登录名    </span></li> <li><span>                        formatter: function(value,row,index){    </span></li> <li class="alt"><span>                            if(row.account != null && row.account.login != null) {    </span></li> <li><span>                                return row.account.login; //如果登录名不为空,显示登录名    </span></li> <li class="alt"><span>                            } else {    </span></li> <li><span>                                return "此类别没有管理员";    </span></li> <li class="alt"><span>                            }    </span></li> <li><span>                    }       </span></li> <li class="alt"><span>                    }    </span></li> <li><span>                ]]        </span></li> <li class="alt"><span>            });     </span></li> <li><span>        });    </span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"></</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>      </span></li> <li><span>  <span class="tag"><</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span class="tag-name">table</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dg"</span><span class="tag">></span><span class="tag"></</span><span class="tag-name">table</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"></</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li></ol></div><p>  <span style="font-size: medium;"><strong>6.  测试显示结果</strong></span></p><p>  最后我们测试一下DataGrid的显示结果,如下?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160507000536723.png" width="600" height="258" alt="SSH电商项目实战之七:Struts2和Json的整? /></p><p>  到这里,我们成功整合了Struts2和json,现在可以和前台传输json格式的数据了?/p><p> </p><p> </p>]]></description><category>软件开?/category><comments>http://www.cckinglong.com/software/767.html#comment</comments><wfw:comment>http://www.cckinglong.com/</wfw:comment><wfw:commentRss>http://www.cckinglong.com/feed.asp?cmt=767</wfw:commentRss><trackback:ping>http://www.cckinglong.com/cmd.asp?act=tb&id=767&key=d3fa2df2</trackback:ping></item><item><title>长文:内容产业的赢家与输?/title><author>a@b.com (鸡啄?</author><link>http://www.cckinglong.com/internet/766.html</link><pubDate>Wed, 20 Sep 2017 10:36:58 +0800</pubDate><guid>http://www.cckinglong.com/internet/766.html</guid><description><![CDATA[<p>  <span style="font-size: medium;"><strong>一</strong></span></p><p>  自微信公?2年开始以来,一波内容创业兴起?/p><p>  在内容创业大潮的推动下,涌现出了一些被称为“头部”的大号。有些大号是从博客迁移而来,有些大号则本身就一直是机构媒体或成名大V,还有些大号,在若干年前根本籍籍无名?/p><p>  从零到年入百万千万,估值动辄上亿,当然是赢家,还是不小的赢家?/p><p>  但对于产业来说,基于我一向的“渠道为王 内容为本”的观点,一个内容生产源,比起平台渠道,影响力还是弱很多?/p><p>  所以,本篇着重谈的,依然是渠?平台类的赢家。(以图文为主,视音频类容我再思考思考,再码一篇)</p><p>  <span style="font-size: medium;"><strong>?/strong></span></p><p>  第一个大赢家:今日头条?/p><p>  今日头条创建?2?月,五年的时间,当下估值已进入百亿美元俱乐部,2017年收入过一百五十亿人民币,应无悬念?/p><p>  今日头条的早期崛起,和内容创业关系并不是太大?/p><p>  2014?月,今日头条宣布完成1亿美金融资,估?亿。这个新闻引起了整个媒体圈的关注,也引发了后来的所谓版权争议。但在当时,内容创业虽已悄然起步,不过谈不上是什么风口。我们基金曾经以100万人民币估值的价格,还投资了一个号。在今天,是很难找到这种估值项目的?/p><p>  但今日头条后来更为彪悍的发展,与内容创业就颇有关系了。因为大多数内容创业者,即便重心在微信公号上,依然会在头条同步更新?/p><p>  这给头条带来了巨大的内容数量,对应的,也就带来了巨大的广告位数量?/p><p>  <span style="font-size: medium;"><strong>?/strong></span></p><p>  插播?/p><p>  观察一个以广告为主要收入模式的内容生意?ldquo;广告位数?rdquo;是一个非常重要的研判指标?/p><p>  一般意义上所谓的媒体——也就是一个内容生产端——通常会被判定?ldquo;体量有限”。体量有限的原因就在于,它的广告位是有限的?/p><p>  广告依附于内容之上,但内容数量存在天花板后,广告收入就一定会存在天花板。而要提升内容数量,对于内容生产型的媒体来说,这就意味着提高成本?/p><p>  这就是为什么传统媒体大多都?ldquo;集团式生?rdquo;的原因,一个组织办了好多媒体,商业上,就是想提升广告位数量?/p><p>  不过内容平台就和内容生产端不同:它的内容存在两个特点?、相对于一个独立的生产端,数量极其巨大?、成本非常低?/p><p>  互联网的几个做出巨大生意的内容平台,都是这样的。从桌面的门户到搜索;从移动的内容聚合APP到社会化媒体?/p><p>  它们的广告位数量甚至可以?ldquo;无穷”来表达,只要天下依然有生产内容的人。一茬一茬的韭菜,一波一波的羊毛,取之不尽用之不竭?/p><p>  这段插播其实是很简单的媒体商业入门知识,但有鉴于至今还有人认为“内容为王”,必须写出来以正视听?/p><p>  <span style="font-size: medium;"><strong>?/strong></span></p><p>  头条并不是继承门户的衣钵,虽然它看上去和门户有点像。而且它当年起家的时候,主要的竞品也都是门户做的,比如搜狐的新闻客户端。至今,主掌腾讯门户的OMG(网络媒体事业群)还是把今日头条视为最重要的竞争对手之一?/p><p>  但本质上,张一鸣接过的,是李彦宏的旗帜?/p><p>  一个很表象的证据就是,今日头条并不想设置总编辑这种岗位(后来出于某些原因设置了),但门户恐怕组建团队的第一件事就是锚定一个总编辑?/p><p>  你知道百度(不是百度新闻这种业务线)的总编辑是谁么?(笑)</p><p>  核心关键词是:匹配?/p><p>  百度的方式是用户发起一个关键字,然后进行相关内容匹配?/p><p>  头条的方式是挖掘用户的属性指标,推送内容进行匹配?/p><p>  一个是拉取(pull)一个是推送(push),但只是由于时代原因造成的技术使用不同。根子上,都是与用户兴趣匹配加载内容?/p><p>  <span style="font-size: medium;"><strong>?/strong></span></p><p>  头条的崛起,当然有主观努力、战术使用得当之类的原因——任何一个产品崛起都离不开自身努力。但我还是想讲一讲大势?/p><p>  头条占了很大的移动互联网的便宜?/p><p>  百度搜索和移动互联网小屏是不匹配的。在桌面,百度是最大的流量入口,真的没有之一。但在移动小屏,这个力量被消解了?/p><p>  百度作为流量入口,一家就掌握了中国整个互联网营销盘子?-3成的投放费用。对于甲方而言,我称之?ldquo;枢纽式投?rdquo;。移动小屏消解了它的力量,等同于部分释放出这一大笔投放费用。而百度一年营收数百亿人民币,即便是点零头,也够一个startup公司吃了?/p><p>  甲方的一部分预算流向了公号,直接和内容生产端对接,另外有一部分,就在寻找新的枢纽式投放。在腾讯整个广告体系还没有搭载起来之前,这个枢纽,内容聚合类APP是一个不错的选择?/p><p>  头条准确地掌握住了这个大势,而另外一个内容APP,搜狐新闻,虽然是最早达到装机过亿的,显然战略判断失误,没有继续深耕?/p><p>  到了头条的第五个年头,也就是今年,正如当年百度在第五个年头创建百度知道(2005?月)一样,头条推出了自己的问答产品:悟空问答?/p><p>  这个产品遭到了业内至少是口头上的阻击,包括知乎和微博。而这一变化,也可以让我们观察到,今日头条的对手,已经不再是当年叫喊着版权的内容生产端(媒体),也不完全是诸家门户的聚合新闻APP?/p><p>  它的敌人更多了?/p><p>  <span style="font-size: medium;"><strong>?/strong></span></p><p>  第二个赢家:新浪微博?/p><p>  微博?9年开始内测运营,到现在已经八年。与头条不同,这是一个横跨桌面到移动阶段的产品:微博一开始还是很重视桌面表现的,现在应该说几乎所有力量都在移动上?/p><p>  微博当下市值已经超越了它的老师:twitter?/p><p>  微博从初创到繁荣到衰落又到繁荣,充分证明了一点,内容平台的核心要务是信息整合。微博盛于海量的第三方信息供给,衰于信息过于嘈杂,又盛于部落化后信息相对有效的分拣与触达。这里面也包括对营销信息的控制?/p><p>  微博分为两个阶段,中间大致以2013年为分割线?/p><p>  第一个阶段,超级大V策略。在这个阶段中,几乎所有人都看好微博,甚至喊出“围观改变中国”这类不乏天真的口号?/p><p>  第二个阶段,部落化策略,也就是扶持中小V。这个阶段微博努力下沉,并开始收编或整肃第三方营销势力。但这个阶段刚开始非常艰难,以至于在北上广很多会议论坛,都会听到“现在没人用微?rdquo;了之类的说法?/p><p>  我和大多数评论者不同,第一个阶段我看空第二阶段我看多。而空翻多的一个重要原因,在于一个指标?/p><p>  与前文所提及的广告位数量一样,这个指标也是观察一个以广告为主要收入模型的内容业态的关键数据:广告主数量?/p><p>  12年四季度的时候,曹国伟在披露微博数据时提到,后者的广告主数量是80?mdash;—嗯,真的,没少写个零?/p><p>  时至今日,已经坐拥数十万广告主,是非常标准的“小生意的大故?rdquo;?/p><p>  <span style="font-size: medium;"><strong>?/strong></span></p><p>  微博的传播模型是一个很混杂的方式。它既有用户到用户的所谓社会化传播,也有微博运营方自己做的所谓主题议程设置。你很难说微博场域里是中心化的,也不能简单地一刀切下去说这是去中心化的?/p><p>  脱胎于新浪这样的门户,其实微博无法摆脱骨子里媒体公司的基因。所以对微博正确的描述是:社会化媒体(social media),而不是社交网络(social network)。可以说,本文说论述的四大赢家中,最接近媒体的,是微博?/p><p>  头条上的内容来自于外部内容抓?同步,以及,直接在头条平台上推送(或自行同步其它平台帐号)。后者被称之为头条号。头条号目前总量已经达到80万的规模,其中有八成,属于江湖意义上?ldquo;自媒?rdquo;——一般理解为正统传统媒体开设的媒体帐号?/p><p>  微博就与此非常不同。微博几乎没有来自第三方同步或抓取的内容。几乎所有的微博用户,都在微博上生产、传播内容。故而微博很少碰到所谓版权争议的问题?/p><p>  也正因为此,微博视自己为一个内容生产部门,对头条的同步越来越不能忍。才会有最近两天发生的一次昏招。这个匪夷所思的对用户著作权的权利主张,其背后动因就在于,广告是附着于内容上的。微博大概以为,打掉了头条(包括悟空问答)对微博的同步,可能会减少后者可卖的广告位吧?/p><p>  直至今日,微博还是有很强的从新浪传承过来的内容思维的影子,而不是如头条、百度那般,骨子里认为自己是一家技术公司。其实微信公号平台方也从来不认为自己是一家内容公司,虽然表象上如微博般,也是海量的第三方在平台上生产内容?/p><p>  <span style="font-size: medium;"><strong>?/strong></span></p><p>  第三个大赢家:腾讯?/p><p>  的确,类似朋友圈广告、广点通之类,和WXG(微信事业群)关系不大,也的确OMG还在苦苦寻找自己的存在感,但我说的是腾讯,一个整体的腾讯?/p><p>  腾讯主要的收入依然在游戏上,所以它的市值飙升和内容赢家是否有关联还不好讲。依然看一下广告的表现?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20170920103019.jpg" alt="长文:内容产业的赢家与输? /></p><p>  这张表格能够清晰地反映出,广告占整个腾讯收入盘子的比重在逐年上升?/p><p>  同时,我们也能从两栏同比增幅中注意到,腾讯广告收入的增长相当快,跑过整个腾讯收入大盘?/p><p>  那么,腾讯广告收入发力在哪里呢?</p><p>  <span style="font-size: medium;"><strong>?/strong></span></p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20170920103045.jpg" alt="长文:内容产业的赢家与输? /></p><p>  这张表统计的是腾讯两个业务(游戏和广告)?014年Q1?017年Q2的逐季表现?/p><p>  首先我们能看到的是,游戏在腾讯整体收入的占比最近五个季度已经长期低?成?017年现象级游戏王者荣耀的耀眼表现,使得Q1游戏占比阻换了一直下滑的占比,但到了二季度,度过广告行业营收最惨淡的Q1之后,占比重新回落?/p><p>  15年开始的历个季度,广告单季度同比增幅非常可观。细查下来,腾讯广告两翼,其效果广告?017年略调了统计口径,改名为社交及其它广告)同比增幅超越其品牌广告(2017年略调了统计口径,改名为媒体广告)?/p><p>  而效果广告,主要的构成部分就是朋友圈广告、微信公号上的广点通等?/p><p>  2013年开始酝?4年正式兴起的内容创业,公号数量从十万级到百万级到今天的千万级,为广点通广告提供了大量的可售卖广告位置。而微信用户对朋友圈的粘着?mdash;—按照腾讯科技企鹅智酷的说法,朋友圈力压点对点通讯,是微信头号使用频率的功?mdash;—也使得朋友圈广告得以大卖?/p><p>  所谓的品牌广告,腾讯官方说法是主要反映来自移动端平台(如腾讯新闻)、腾讯视频等收入。也就是说,这个部分,的确可以基本对标今日头条。整?016年,收入也过百亿?017年调整口径后,被定义为媒体广告收入(主要包括新闻、视频及音乐的广告位产生的收入),上半年也已经斩?5亿余人民币,而广告行业一般下半年高于上半年,全年收入过一百五十亿也应无疑问?/p><p>  这样的成绩单,说腾讯要提防今日头条倒也没差,但要说被头条压制,显然属于杞人忧天了?/p><p>  腾讯,理所当然的,是内容行业里的大赢家?/p><p>  <span style="font-size: medium;"><strong>?/strong></span></p><p>  第四个大赢家:阿里?/p><p>  与类亚马逊的京东所不同的是,阿里本质上的业务并不是零售,而是广告(商家的营销费用)。号称免费的淘宝靠帮助商家推广获取利润,品牌扎堆的天猫,则是抽取交易佣金?/p><p>  京东的交易量(GMV)越大,并不一定会形成利润,因为它是差价模式,有进货成本。但阿里系GMV越大,自身的收入也就越高,GMV到达一定规模后,足以形成利润?/p><p>  但阿里这?ldquo;虚拟商业地产”的模式,伴随着移动兴起的小屏化后,面临严峻的考验:推荐位营销位广告位相对PC端还要不够用。如果应对不当,将会导致极速推高平台上商家的营销成本,使得所有商家进入囚徒困境,最终整个生态崩盘?/p><p>  阿里的应对方式是:引入广告化的内容,一方面增强用户粘度,一方面创造无穷多的广告位置?/p><p>  淘宝达人登场,发展到极盛时,有百万之众?/p><p>  <span style="font-size: medium;"><strong>十一</strong></span></p><p>  早期的所谓内容生产极其简单,被称为双列清单:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20170920103126.jpg" alt="长文:内容产业的赢家与输? /></p><p>  一句话+若干个商品图片,就可以抽佣。前提是,达人清晰这里的游戏规则:哪些商品转化率高、佣金高。据称有年入可达数百万?/p><p>  但这些内容非常轻,而且制作者通常会偏向于所谓爆款。这使得淘系流量依然会向头部商品聚焦,无法对平台上大部分商家形成普惠式的流量供给?/p><p>  阿里开始改变策略?/p><p>  <span style="font-size: medium;"><strong>十二</strong></span></p><p>  有必要略微介绍一下淘系内容生态?/p><p>  今天你打开手机淘宝,与其说是打开了一个网络购物应用,不如说是打开了一本消费类电子刊物。这个刊物的内容相当庞杂海量,天量级内容?ldquo;精品购物指南”?/p><p>  首屏所出现?ldquo;淘宝头条”,理所当然的是一种内容,或可定位成消费领域的今日头条?/p><p>  但往下的类似有好货、必买清单、男神范(如果是女生打开淘宝,看到的是爱逛街)等等,都是它的内容板块。只不过淘宝头条的内容偏“资讯”类,而这些板块的内容?ldquo;导购”类。佣金结算方式前者以CPC为主,后者以CPS为主?/p><p>  这些内容按照阿里的定义,被称?ldquo;公域内容”?/p><p>  而底部导航的第二个按?ldquo;微淘”,所指向的,被称?ldquo;私域内容”。公域和私域内容所产生的佣金,结算方式并不相同?/p><p>  之所以前者被称为公域内容,是因为内容生产者所进行的内容生产,是有固定格式的,且用户也是根据算法匹配的。而后者的私域内容,生产格式并不强调,用户也是因为关注了某个内容源(可能就是个商铺,也可能是一个内容生产者)才会被这些内容触达?/p><p>  与消费密切相关的内容,大部分情况下,并没有太强的时效性。一篇对某皮衣进行介绍的文字,有可能?ldquo;有好?rdquo;或?ldquo;必买清单”之类的板块中有长达半年的曝光期,换而言之,内容生产者可以指望这篇文章长达半年的佣金获取。这是淘系内容,与其它内容平台非常不同的地方?/p><p>  <span style="font-size: medium;"><strong>十三</strong></span></p><p>  阿里的策略调整在于两个方面:</p><p>  1、鼓励有一定篇幅的内容生产(当然也包括视频、直播),一句话加一堆商品照片的双列清单在今天已经很少见了?/p><p>  2、在公域内容里的佣金计算上做了大刀阔斧的调整。一份CPS,扣除阿里系提走?成,剩下?成,内容生产者只能立刻获得其中的10%(也就是整个CPS?%),还有9成(相当?3%)被置入资金池,由阿里进行动态分配。大致上,就是对所谓好内容但可能转化不高进行扶持?/p><p>  阿里于今年启动daren.taobao.com,中文名字叫阿里创作平台。号称要在三年里投入100亿来扶持内容?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20170920103154.jpg" alt="长文:内容产业的赢家与输? /></p><p>  请注意上方的频道投稿?/p><p>  基于身份标签——官方根据具体情况,赋予不同的标签,比如图文类、短视频类、主播类(不开店)、红人类(开店的)、淘女郎(一般背后有经纪公司)等等。据说,这种身份标签高达上百?mdash;—内容生产者可以申请相应的频道开通,并针对性地进行写作。比如投?ldquo;有好?rdquo;频道,内容就有可能出现手淘首页的有好货板块。但频道投稿有非常严格的格式要求,不是像微信公号那样,想怎么写就怎么写,想怎么排版就怎么排版?/p><p>  另外商家也可以发布V任务,由内容生产者去申领,其结算方式以CPM为主?/p><p>  当下,月入过十万的生产者,已经超过1500?mdash;—其实这个数字并不算太低。微信公号月入过十万的,又有多少呢?</p><p>  而对于阿里来说,内容有效缓解了整个淘系营销资源紧缺,商家囚徒困境的局面。我个人认为,最新一季财报的亮眼表现,其背后,与内容是分不开的?/p><p>  <span style="font-size: medium;"><strong>十四</strong></span></p><p>  有赢家就有输家?/p><p>  百度是当仁不让的输家之一,在贴吧事件之后魏则西事件之前,百度的财务表现就出了问题。我专门写过《这两年百度发生了什么》分析它13?4?5年的状况?/p><p>  百度更冤的一件事是:多少公号狗拿着百度写(pin)稿子,营销收入赚得盆满钵满,却和百度一点关系都没有?/p><p>  百度还有机会么?</p><p>  我不知道?/p><p>  <span style="font-size: medium;"><strong>十五</strong></span></p><p>  有个小公司,我看有机会?/p><p>  这家小公司的创始人叫徐达内,公司名字叫新榜,一向是?B的生意,估值最近在一轮华人、华盖投完后,也快近十亿人民币了——比起上面的赢家输家,当然还是小公司?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20170920103222.jpg" alt="长文:内容产业的赢家与输? /></p><p>  这张图反映了?C?B的不同。做2C的,做得好的,可以万古流芳,?B就比较默默无闻了?/p><p>  徐达内出身媒体人,对万古流芳这种事很看重?/p><p>  于是,他决定启动一?C的项目。原来想?ldquo;见识”,不巧正好和另外一家也是华人文化基金投资的华尔街见闻做的一个产品撞名,所以现在改名叫“微见”?/p><p>  这个产品的核心就是汇聚一帮喜欢扯淡的kol们,对各种新闻、文章进行评头论足。用户主要是去看他们评头论足的?/p><p>  如果你知道徐达内早年写过媒体札记这件事的话,你会看到这个事在微见里的影子的?/p><p> 转自:微信公众号 扯淡?/p>]]></description><category>IT互联?/category><comments>http://www.cckinglong.com/internet/766.html#comment</comments><wfw:comment>http://www.cckinglong.com/</wfw:comment><wfw:commentRss>http://www.cckinglong.com/feed.asp?cmt=766</wfw:commentRss><trackback:ping>http://www.cckinglong.com/cmd.asp?act=tb&id=766&key=83824101</trackback:ping></item><item><title>SSH电商项目实战之六:基于DataGrid的数据显?/title><author>a@b.com (鸡啄?</author><link>http://www.cckinglong.com/software/765.html</link><pubDate>Tue, 19 Sep 2017 08:54:19 +0800</pubDate><guid>http://www.cckinglong.com/software/765.html</guid><description><![CDATA[<p>  EasyUI中DataGrid以表格形式展示数据,并提供了丰富的选择、排序、分组和编辑数据的功能支持。DataGrid的设计用于缩短开发时间,并且使开发人员不需要具备特定的知识。它是轻量级的且功能丰富。单元格合并、多列标题、冻结列和页脚只是其中的一小部分功能?/p><p>  <span style="font-size: medium;"><strong>1. 回顾一下第4节内?/strong></span></p><p>  在第4节中,我们使用EasyUI搭建好了左侧菜单栏,并且通过点击菜单选项在右边弹出对应的选项卡。这节我们来使用DataGrid把右边的选项卡部分做好。先看一下第4节中最后的aindex.jsp文件(也可参见第4节中的内容)?/p><p style="text-align: center;"><img rel="nofollow" src="http://img.blog.csdn.net/20160506164649701" width="600" height="668" alt="" /></p><p>  <span style="font-size: medium;"><strong>2. 创建DataGrid控件的几种方?/strong></span></p><p>  DataGrid显示数据是json格式的,所以我们首先要把从后台获取到的数据打包成Jason格式,然后传到前台来让DataGrid来显示,这一节我们先不从后台获取数据,先自己准备一?json文件,里面有ison格式的数据,然后我们来让DataGird显示,先把显示功能做好,再请求后台数据?/p><p>  我们先从EasyUI的参考文档中看一下DataGrid显示的格式是什么样的,如下图所示:</p><p style="text-align: center;"><img rel="nofollow" src="http://img.blog.csdn.net/20160506173210502" width="600" height="453" alt="" /></p><p>  我们沿着参考文档往下看,我们发现DataGrid空间是通过<table>来创建的,有三种创建方式?/p><p>  第一种:从现有的表格元素创建DataGrid,在HTML中定义列、行和数据?/p><p style="text-align: center;"><img rel="nofollow" src="http://img.blog.csdn.net/20160506174815336" width="600" height="256" alt="" /></p><p>  第二种:通过<table>标签创建DataGrid控件。在表格内使?lt;th>标签定义列?/p><p style="text-align: center;"><img rel="nofollow" src="http://img.blog.csdn.net/20160506174930658" width="600" height="180" alt="" /></p><p>  第三种:使用Javascript去创建DataGrid控件?/p><p style="text-align: center;"><img rel="nofollow" src="http://img.blog.csdn.net/20160506175122364" width="600" height="182" alt="" /></p><p>  我们采取第三种,用js去创建DataGrid控件,首先我们得先准备一个存储了json格式数据的文件,在WebRoot/jquery-easyui-1.3.5/demo/datagrid/下面有几个json文件,我们选择一个datagrid_data1.json,拷贝到WebRoot目录下,修改一下参数,等会我们要来显示这个json文件里的数据。如下:</p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"> <li class="alt"><span><span>{</span><span class="string">"total"</span><span>:10,</span><span class="string">"rows"</span><span>:[    </span></span></li> <li><span>    {<span class="string">"code"</span><span>:</span><span class="string">"FI-SW-01"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Koi"</span><span>,</span><span class="string">"price"</span><span>:10.00},    </span></span></li> <li class="alt"><span>    {<span class="string">"code"</span><span>:</span><span class="string">"K9-DL-01"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Dalmation"</span><span>,</span><span class="string">"price"</span><span>:12.00},    </span></span></li> <li><span>    {<span class="string">"code"</span><span>:</span><span class="string">"RP-SN-01"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Rattlesnake"</span><span>,</span><span class="string">"price"</span><span>:12.00},    </span></span></li> <li class="alt"><span>    {<span class="string">"code"</span><span>:</span><span class="string">"RP-LI-02"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Iguana"</span><span>,</span><span class="string">"price"</span><span>:12.00},    </span></span></li> <li><span>    {<span class="string">"code"</span><span>:</span><span class="string">"FL-DSH-01"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Manx"</span><span>,</span><span class="string">"price"</span><span>:12.00},    </span></span></li> <li class="alt"><span>    {<span class="string">"code"</span><span>:</span><span class="string">"FL-DSH-01"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Manx"</span><span>,</span><span class="string">"price"</span><span>:12.00},    </span></span></li> <li><span>    {<span class="string">"code"</span><span>:</span><span class="string">"FL-DLH-02"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Persian"</span><span>,</span><span class="string">"price"</span><span>:12.00},    </span></span></li> <li class="alt"><span>    {<span class="string">"code"</span><span>:</span><span class="string">"FL-DLH-02"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Persian"</span><span>,</span><span class="string">"price"</span><span>:12.00},    </span></span></li> <li><span>    {<span class="string">"code"</span><span>:</span><span class="string">"AV-CB-01"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Amazon Parrot"</span><span>,</span><span class="string">"price"</span><span>:92.00},    </span></span></li> <li class="alt"><span>    {<span class="string">"code"</span><span>:</span><span class="string">"AV-CB-03"</span><span>,</span><span class="string">"productname"</span><span>:</span><span class="string">"Amazon Parrot"</span><span>,</span><span class="string">"price"</span><span>:92.00}    </span></span></li> <li><span>]}    </span></li></ol></div><p>  我们可以看到,json数据格式是:"key1": value1, "key2":value2。每个value里面又可以是数组,数组中保存新的Jason数据?/p><p>  有了json文件,我们接下来就可以设计DataGrid控件了,整个DataGrid都是在query.jsp中设计的,因为要显示的内容就是query.jsp中的内容。我们来看看query.jsp页面?/p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span>%@ page </span><span class="attribute">language</span><span>=</span><span class="attribute-value">"java"</span><span> </span><span class="attribute">import</span><span>=</span><span class="attribute-value">"java.util.*"</span><span> </span><span class="attribute">pageEncoding</span><span>=</span><span class="attribute-value">"UTF-8"</span><span>%</span><span class="tag">></span><span>    </span></span></li> <li><span><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"<span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"><</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"><</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span>%@ include </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"/public/head.jspf"</span><span> %</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        $(function(){    </span></li> <li><span>            $('#dg').datagrid({       </span></li> <li class="alt"><span>                //请求数据的url地址,后面会改成请求我们自己的url    </span></li> <li><span>                url:'datagrid_data.json',    </span></li> <li class="alt"><span>                loadMsg:'Loading......',    </span></li> <li><span>                queryParams:{type:''},//参数    </span></li> <li class="alt"><span>                //width:300,    </span></li> <li><span>                fitColumns:true,//水平自动展开,如果设置此属性,则不会有水平滚动条,演示冻结列时,该参数不要设置    </span></li> <li class="alt"><span>                //显示斑马?nbsp;   </span></li> <li><span>                striped:true,    </span></li> <li class="alt"><span>                //当数据多的时候不换行    </span></li> <li><span>                nowrap:true,    </span></li> <li class="alt"><span>                singleSelect:true, //如果为真,只允许单行显示,全显功能失?nbsp;   </span></li> <li><span>                //设置分页    </span></li> <li class="alt"><span>                pagination:true,    </span></li> <li><span>                rowStyler: function(index,row){    </span></li> <li class="alt"><span>                    console.info("index" + index + "," + row)    </span></li> <li><span>                    if(index % <span class="attribute">2</span><span> == 0) {    </span></span></li> <li class="alt"><span>                        return 'background-color:#fff;';    </span></li> <li><span>                    } else {    </span></li> <li class="alt"><span>                        return 'background-color:#ff0;';    </span></li> <li><span>                    }    </span></li> <li class="alt"><span>                        </span></li> <li><span>                },    </span></li> <li class="alt"><span>                //同列属性,但是这些列将会冻结在左侧,大小不会改变,当宽度大于250时,会显示滚动条,但是冻结的列不在滚动条?nbsp;   </span></li> <li><span>                frozenColumns:[[    </span></li> <li class="alt"><span>                    {field:'checkbox',checkbox:true},    </span></li> <li><span>                    {field:'code',title:'编号',width:200}                     </span></li> <li class="alt"><span>                ]],    </span></li> <li><span>                //配置datagrid的列字段     </span></li> <li class="alt"><span>                //field:列字段的名称,与json的key捆绑    </span></li> <li><span>                //title:列标题,是显示给人看的    </span></li> <li class="alt"><span>                columns:[[                         </span></li> <li><span>                    {field:'productname',title:'类别名称',width:100,    </span></li> <li class="alt"><span>                        //用来格式化当前列的值,返回的是最终的数据    </span></li> <li><span>                        formatter: function(value,row,index){    </span></li> <li class="alt"><span>                        return "<span class="tag"><</span><span class="tag-name">span</span><span> </span><span class="attribute">title</span><span>=</span><span class="attribute-value">" + value + "</span><span class="tag">></span><span>" + value + "</span><span class="tag"></</span><span class="tag-name">span</span><span class="tag">></span><span>";    </span></span></li> <li><span>                    }    </span></li> <li class="alt"><span>                },        </span></li> <li><span>                    {field:'price',title:'价格',width:100,    </span></li> <li class="alt"><span>                    styler: function(value,row,index){    </span></li> <li><span>                        //设置当前单元格的样式,返回的字符串直接交?nbsp;style属?nbsp;   </span></li> <li class="alt"><span>                        //console.info("val:" + value + ",row:" + row + ",index:" + index)    </span></li> <li><span>                        if (value <span class="tag"><</span><span> </span><span class="tag-name">20</span><span>){    </span></span></li> <li class="alt"><span>                            return 'color:red;';    </span></li> <li><span>                        }    </span></li> <li class="alt"><span>                    }       </span></li> <li><span>                    }    </span></li> <li class="alt"><span>                ]]        </span></li> <li><span>            });     </span></li> <li class="alt"><span>        });    </span></li> <li><span>    <span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>  <span class="tag"></</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li><span>      </span></li> <li class="alt"><span>  <span class="tag"><</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">table</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"dg"</span><span class="tag">></span><span class="tag"></</span><span class="tag-name">table</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>  <span class="tag"></</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li><span><span class="tag"></</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li></ol></div><p>  <span style="font-size: medium;"><strong>3. DataGrid控件的属?/strong></span></p><p>  我们可以看到,使用js去创建DataGrid控件的话,只要一?lt;table>标签即可,主要都是在js中完成。DataGrid的控件很强大,这里我们主要做一下基本的显示,更多其他的功能可以参照EasyUI的开发文档。我们现在针对上面的query.jsp文件做一下分析:</p><p>  首先DataGrid控件有两种属性:一个是DataGrid属性,还有一个是列属性。顾名思义,DataGrid属性是给整个DataGrid控件添加的属性,而列属性是针对某一列的。每中属性有很多,这里只做了一些基本的常用的属性?/p><p>  DataGrid属性里最重要的是columns属性,它是一个数组,可以创建多列,见下面的截图:</p><p style="text-align: center;"><img rel="nofollow" src="http://img.blog.csdn.net/20160506183422933" width="600" height="113" alt="" /></p><p>  我们来看下columns属性中有哪些细节:</p><p style="text-align: center;"><img rel="nofollow" src="http://img.blog.csdn.net/20160506183922486" width="600" height="340" alt="" /></p><p>  列属性中,field表示字段名称,对应与json数据的key,然后title是要显示给用户看的标题,见query.jsp文件中,还有其他一些基本属性可以参照EasyUI文档。列属性中比较重要的也比较常用的两个属性是formatter和styler,分别是用来格式化当前列的值和设置单元格样式的,我们主要来看一下这两个属性:</p><p style="text-align: center;"><img rel="nofollow" src="http://img.blog.csdn.net/20160506184205475" width="600" height="367" alt="" /></p><p>  我们具体来分析一下上面query.jsp中的columns属性中,如何使用这两个列属性的?/p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"> <li class="alt"><span><span>{field:</span><span class="string">'productname'</span><span>,title:</span><span class="string">'类别名称'</span><span>,width:100,    </span></span></li> <li><span>    <span class="comment">//用来格式化当前列的值,返回的是最终的数据  </span><span>  </span></span></li> <li class="alt"><span>    formatter: <span class="keyword">function</span><span>(value,row,index){    </span></span></li> <li><span>        <span class="keyword">return</span><span> </span><span class="string">"<span title="</span><span> + value + </span><span class="string">">"</span><span> + value + </span><span class="string">"</span>"</span><span>;</span><span class="comment">//设置为鼠标放上去显示value?nbsp; </span><span>  </span></span></li> <li class="alt"><span>    }    </span></li> <li><span>},        </span></li> <li class="alt"><span>{field:<span class="string">'price'</span><span>,title:</span><span class="string">'价格'</span><span>,width:100,    </span></span></li> <li><span>    styler: <span class="keyword">function</span><span>(value,row,index){    </span></span></li> <li class="alt"><span>        <span class="comment">//设置当前单元格的样式,返回的字符串直接交?nbsp;style属?nbsp; </span><span>  </span></span></li> <li><span>            <span class="comment">//console.info("val:" + value + ",row:" + row + ",index:" + index)  </span><span>  </span></span></li> <li class="alt"><span>        <span class="keyword">if</span><span> (value < 20){ </span><span class="comment">//如果value值小?0  </span><span>  </span></span></li> <li><span>            <span class="keyword">return</span><span> </span><span class="string">'color:red;'</span><span>; </span><span class="comment">//将value值显示为红色  </span><span>  </span></span></li> <li class="alt"><span>        }    </span></li> <li><span>    }       </span></li> <li class="alt"><span>}    </span></li></ol></div><p>  然后我们再看看DataGrid控件的一些属性:</p><p>  url表示要显示的数据来源,这里设置成datagrid_data.json表示数据来源是这个json文件,放在WebRoot目录下了?/p><p>  loadMsg表示加载数据过程中显示的信息?/p><p>  queryParams表示传给后台的参数,在这里用不到,因为我们目前还没有和后台关联上,只是显示一个json文件,后面会用到?/p><p>  fitColums设置为true后表示水平自动展开,自适应网格的宽度,如此设置,水平方向就不会有滚动条了,也不用设置宽度了?/p><p>  width是宽度,如果数据过长显示不下,水平方向就会出现滚动条?/p><p>  striped设置为true后表示显示斑马线,这是一个显示样式,试一下便知;</p><p>  nowrap设置为true后表示当数据多的时候不换行,否则某一行数据多的时候会换行,会比较难看?/p><p>  pagination设置为true后表示开启分页功能;</p><p>  singleSelect设置为true时,只允许勾选单行,全选功能失效,主要用于最前面一列的复选框?/p><p>  frozenColums是为了设置冻结列,在frozenColums中设置的列,不会改变大小。里面如果设置了{field:'checkbox',checkbox:true},表示这是个复选框列,给用户勾选用的,如果设置了上面的singleSelect,那么只能选择一项,不能全选;</p><p>  rowStyler是设置所有行的样式的,两个参数为行索引和行,上面设置的是偶数行是白色,奇数行是黄色?/p><p>  等等……还有其他DataGrid控件的属性,可以参考EasyUI的技术文档,在这里就不一一解说了?/p><p>  <span style="font-size: medium;"><strong>4. DataGrid数据显示的效?/strong></span></p><p>  好了,完成了query.jsp后,我们重启tomcat,然后进入到后台,点击左侧菜单栏的类别管理,就会在右边出现一个类别管理的选项卡,然后就会显示我们指定的json数据,这个Jason数据是我们自己放在WebRoot目录下的,后面我们将会把json和struts整合,动态的获取从后台传过来的json数据?/p><div style="text-align: center;"><img rel="nofollow" src="http://img.blog.csdn.net/20160506213127894" width="600" height="141" alt="" /></div>]]></description><category>软件开?/category><comments>http://www.cckinglong.com/software/765.html#comment</comments><wfw:comment>http://www.cckinglong.com/</wfw:comment><wfw:commentRss>http://www.cckinglong.com/feed.asp?cmt=765</wfw:commentRss><trackback:ping>http://www.cckinglong.com/cmd.asp?act=tb&id=765&key=33675b20</trackback:ping></item><item><title>SSH电商项目实战之五:完成数据库的级联查询和分页a@b.com (鸡啄?http://www.cckinglong.com/software/764.htmlWed, 13 Sep 2017 08:53:38 +0800http://www.cckinglong.com/software/764.html  上一节我们完成了EasyUI菜单的实现。这一节我们主要来写一下CategoryServiceImpl实现类,完成数据库的级联查询。一般项目从后往前做,先做service(我们没有抽取Dao,最后再抽取),做完了再做上面层?/p>

  在写之前,先看一下数据库中的表的情况?/p>

SQL代码
  1. drop database if exists shop;    
  2. /*创建数据库,并设置编?/    
  3. create database shop default character set utf8;    
  4.     
  5. use shop;    
  6. /*删除管理员表*/    
  7. drop table if exists account;    
  8. /*删除商品类别?/    
  9. drop table if exists category;    
  10.     
  11. /*============================*/    
  12. /*      Table:管理员表结?nbsp;                      */    
  13. /*============================*/    
  14. create table account    
  15. (    
  16.     /* 管理员编号,自动增长 */    
  17.     id int primary key not null auto_increment,    
  18.     /* 管理员登录名 */    
  19.     login varchar(20),    
  20.     /* 管理员姓?nbsp;*/    
  21.     name varchar(20),    
  22.     /* 管理员密?nbsp;*/    
  23.     pass varchar(20)    
  24. );    
  25.     
  26. /*============================*/    
  27. /*     Table:商品类别表结构                      */    
  28. /*============================*/    
  29. create table category    
  30. (    
  31.    /* 类别编号,自动增?nbsp;*/    
  32.    id  int primary key not null auto_increment,    
  33.    /* 类别名称 */    
  34.    type varchar(20),    
  35.    /* 类别是否为热点类别,热点类别才有可能显示在首?/    
  36.    hot  bool default false,    
  37.    /* 外键,此类别由哪位管理员管理 */    
  38.    account_id int,    
  39.    constraint aid_FK foreign key(account_id) references account(id)    
  40. );    

  主要有两张表,商品类别表和管理员表,并且商品类别表中提供了一个外键关联管理员表。也就是商品和管理员是多对一的关系。现在我们开始编写查询商品的类别信息,需要级联管理员?/p>

  1. 实现级联查询方法

  首先在CategoryService接口中定义该方法?/p>

Java代码
  1. public interface CategoryService extends BaseService<Category> {    
  2.     //查询类别信息,级联管理员    
  3.     public List<Category> queryJoinAccount(String type); //使用类别的名称查?nbsp;   
  4. }   

  然后我们在CategoryService的实现类CategoryServiceImpl中实现这个方法:

Java代码
  1. @Service("categoryService")    
  2. public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {    
  3.     
  4.     @Override    
  5.     public List<Category> queryJoinAccount(String type) {    
  6.         String hql = "from Category c where c.type like :type";    
  7.         return getSession().createQuery(hql)    
  8.                 .setString("type""%" + type + "%").list();    
  9.     }    
  10. }    

  在两个Model中我们配一下关联注解:

Java代码
  1. //Category类中    
  2. @ManyToOne(fetch = FetchType.EAGER)    
  3. @JoinColumn(name = "account_id")    
  4. public Account getAccount() {    
  5.     return this.account;    
  6. }    
  7. //Account类中    
  8. @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "account")    
  9. public Set<Category> getCategories() {    
  10.     return this.categories;    
  11. }    

  然后我们在测试类中测试一下:

Java代码
  1. @RunWith(SpringJUnit4ClassRunner.class)    
  2. @ContextConfiguration(locations="classpath:beans.xml")    
  3. public class CategoryServiceImplTest {    
  4.     
  5.     @Resource    
  6.     private CategoryService categoryService;    
  7.         
  8.     @Test    
  9.      public void testQueryJoinAccount() {    
  10.         for(Category c : categoryService.queryJoinAccount("")) {    
  11.              System.out.println(c);    
  12.              System.out.println(c.getAccount());    
  13.         }    
  14.     }    
  15. }    

  2. 级联查询存在的问?/strong>

  我们看一下控制台的输出可以看出,它发了不止一条SQL语句,但是我们明明只查询了一次,为什么会发这么多语句呢?这就是常见的1+N问题。所谓的1+N问题,就是首先发出一条语句查询当前对象,然后发出N条语句查询关联对象,因此效率变得很低。这里就两个对象,如果有更多的对象,那效率就会大打折扣了,我们该如何解决这个问题呢?

  可能大家会想到将fetch设置生FetchType.LAZY就不会发多条语句了,但是这肯定不行,因为设置成LAZY后,我们就拿不到Account对象了,比较好的解决方法是我们自己写hql语句,使用join fetch。具体看修改后的CategoryServiceImpl实现类:

Java代码
  1. @Service("categoryService")    
  2. public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {    
  3.     
  4.     @Override    
  5.     public List<Category> queryJoinAccount(String type) {    
  6.         String hql = "from Category c left join fetch c.account where c.type like :type";    
  7.         return getSession().createQuery(hql)    
  8.                 .setString("type""%" + type + "%").list();    
  9.     }    
  10. }    

  left join表示关联Account一起查询,fetch表示将Account对象加到Category中去,这样就只会发一条SQL语句了,并且返回的Category中也包含了Account对象了?/p>

  3. 完成分页功能

  Hibernate中的分页很简单,只需要调用两个方法setFirstResult和setMaxResults即可:我们修改一下CategoryService接口和它的实现类CategoryServiceImpl?/p>

Java代码
  1. //CategoryService    
  2. public interface CategoryService extends BaseService<Category> {    
  3.     //查询类别信息,级联管理员    
  4.     public List<Category> queryJoinAccount(String type, int page, int size); //并实现分?nbsp;   
  5. }    
  6.     
  7. //CategoryServiceImpl    
  8. @Service("categoryService")    
  9. public class CategoryServiceImpl extends BaseServiceImpl<Category> implements CategoryService {    
  10.     
  11.     @Override    
  12.     public List<Category> queryJoinAccount(String type, int page, int size) {    
  13.         String hql = "from Category c left join fetch c.account where c.type like :type";    
  14.         return getSession().createQuery(hql)    
  15.                 .setString("type""%" + type + "%")    
  16.                 .setFirstResult((page-1) * size) //从第几个开始显?nbsp;   
  17.                 .setMaxResults(size) //显示几个    
  18.                 .list();    
  19.     }    
  20. }    

  我们在测试类中测试一下:

Java代码
  1. @RunWith(SpringJUnit4ClassRunner.class)    
  2. @ContextConfiguration(locations="classpath:beans.xml")    
  3. public class CategoryServiceImplTest {    
  4.     
  5.     @Resource    
  6.     private CategoryService categoryService;    
  7.     
  8.     @Test    
  9.     public void testQueryJoinAccount() {    
  10.         for(Category c : categoryService.queryJoinAccount("",1,2)) { //显示第一页,每页2条数?nbsp;   
  11.             System.out.println(c + "," + c.getAccount());    
  12.         }    
  13.     }    
  14. }    

  为此,我们写完了Service的方法了,完成了对商品类别的级联查询和分页功能?/p>]]>软件开?/category>http://www.cckinglong.com/software/764.html#commenthttp://www.cckinglong.com/http://www.cckinglong.com/feed.asp?cmt=764http://www.cckinglong.com/cmd.asp?act=tb&id=764&key=07866ec7SSH电商项目实战之四:EasyUI菜单的实?/title><author>a@b.com (鸡啄?</author><link>http://www.cckinglong.com/software/763.html</link><pubDate>Mon, 11 Sep 2017 08:40:59 +0800</pubDate><guid>http://www.cckinglong.com/software/763.html</guid><description><![CDATA[<p>  上一节我们使用EasyUI搭建了后台页面的框架,这一节我们主要使用EasyUI技术简单实现后台菜单,先将简单功能做出来,后期再继续丰富。(<a rel="nofollow" target="_blank">EasyUI下载地址</a>?/p><p>  <span style="font-size: medium;"><strong>1. 实现左侧菜单</strong></span></p><p>  首先看一下效果图?/p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160504222956558.png" width="600" height="393" alt="SSH电商项目实战之四:EasyUI菜单的实? /></p><p>  我们可以点击“基本操作”?ldquo;其他操作”来切换菜单选项,在具体的选项内,点击不同的连接,会在右侧显示出来。我们先把左边的菜单做出来?/p><p>  左侧菜单内容主要有两个:“类别管理”?ldquo;商品管理”。我们知道,上一节中,在aindex.jsp中应将后台页面的框架搭建好了,那么现在我们只要做好这两个超链接,然后放到aindex.jsp中相应的div中即可。所以我们先在WebRoot文件夹下新建一个temp.jsp文件作为临时开发文件,因为在这里写jsp可以直接测出来,等效果可以后,再将内容复制到aindex.jsp中的相应位置?/p><p>  temp.jsp页面如下?/p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span>%@ page </span><span class="attribute">language</span><span>=</span><span class="attribute-value">"java"</span><span> </span><span class="attribute">import</span><span>=</span><span class="attribute-value">"java.util.*"</span><span> </span><span class="attribute">pageEncoding</span><span>=</span><span class="attribute-value">"UTF-8"</span><span>%</span><span class="tag">></span><span>    </span></span></li> <li><span><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"<span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"><</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"><</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span>%@ include </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"/public/head.jspf"</span><span> %</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">style</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/css"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        #menu {    </span></li> <li><span>            width:200px;    </span></li> <li class="alt"><span>            /*border:1px solid red;*/    </span></li> <li><span>        }    </span></li> <li class="alt"><span>        #menu ul {    </span></li> <li><span>            list-style: none;    </span></li> <li class="alt"><span>            padding: 0px;    </span></li> <li><span>            margin: 0px;    </span></li> <li class="alt"><span>        }    </span></li> <li><span>        #menu ul li {    </span></li> <li class="alt"><span>            border-bottom: 1px solid #fff;    </span></li> <li><span>                </span></li> <li class="alt"><span>        }    </span></li> <li><span>        #menu ul li a {    </span></li> <li class="alt"><span>            /*先将a标签转换为块级元素,才能设置宽和内间?/    </span></li> <li><span>            display: block;    </span></li> <li class="alt"><span>            background-color: #00a6ac;    </span></li> <li><span>            color: #fff;    </span></li> <li class="alt"><span>            padding: 5px;    </span></li> <li><span>            text-decoration: none;    </span></li> <li class="alt"><span>        }    </span></li> <li><span>        #menu ul li a:hover {    </span></li> <li class="alt"><span>            background-color: #008792;    </span></li> <li><span>        }    </span></li> <li class="alt"><span>            </span></li> <li><span>    <span class="tag"></</span><span class="tag-name">style</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>  <span class="tag"></</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li><span>      </span></li> <li class="alt"><span>  <span class="tag"><</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"menu"</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">ul</span><span class="tag">></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">li</span><span class="tag">></span><span class="tag"><</span><span class="tag-name">a</span><span> </span><span class="attribute">href</span><span>=</span><span class="attribute-value">"#"</span><span class="tag">></span><span>类别管理</span><span class="tag"></</span><span class="tag-name">a</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>            <span class="tag"><</span><span class="tag-name">li</span><span class="tag">></span><span class="tag"><</span><span class="tag-name">a</span><span> </span><span class="attribute">href</span><span>=</span><span class="attribute-value">"#"</span><span class="tag">></span><span>商品管理</span><span class="tag"></</span><span class="tag-name">a</span><span class="tag">></span><span>    </span></span></li> <li><span>        <span class="tag"></</span><span class="tag-name">ul</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>    </span></span></li> <li><span>  <span class="tag"></</span><span class="tag-name">body</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li></ol></div><p>  temp.jsp中只做了两个链接,用li封装起来并放到div中,上面css是给这两个链接设置样式的,然后我们开启tomcat,测试一下效果如下:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160504224002915.png" alt="SSH电商项目实战之四:EasyUI菜单的实? /></p><p>  做好了这两个超链接后,我们将封装两个超链接的ul拷贝到aindex.jsp中的左侧菜单内容显示位置,并简要的修改,如下:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160504224818410.png" width="600" height="295" alt="SSH电商项目实战之四:EasyUI菜单的实? /></p><p>  css部分直接考到aindex.jsp的head标签里即可。看上面那个a标签,里面是title属性,并不是href,因为我们不是跳转到新的页面,因为EasyUI就这一个页面,我们要让点击后的显示放到右边的tab选项卡那里,所以我们先把跳转的action写在title属性里,后面再改。接下来,我们要通过点击类别管理,在右边的选项卡中弹出具体类容的功能?/p><p>  <span style="font-size: medium;"><strong>2. 实现右侧tab选项?/strong></span></p><p>  实现点击左边菜单栏弹出右边选项卡的功能,需要加入js代码了。使用EasyUI的思路是:首先点击超链接,拿到这个超链接的名字,因为弹出来的选项卡标题应该和这个超链接的名字一样的,比?ldquo;类别管理”;然后判断改名字的选项卡是否已经存在,如果存在则显示,如果不存在则创建,并显示要显示的内容。我们来看下js部分的代码:</p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span class="tag">></span><span>    </span></span></li> <li><span>    $(function(){    </span></li> <li class="alt"><span>        $("a[title]").click(function(){    </span></li> <li><span>            var <span class="attribute">text</span><span> = $(this).text();    </span></span></li> <li class="alt"><span>            var <span class="attribute">href</span><span> = $(this).attr("title");    </span></span></li> <li><span>            //判断当前右边是否已有相应的tab    </span></li> <li class="alt"><span>            if($("#tt").tabs("exists", text)) {    </span></li> <li><span>                $("#tt").tabs("select", text);    </span></li> <li class="alt"><span>            } else {    </span></li> <li><span>                //如果没有则创建一个新的tab,否则切换到当前tag    </span></li> <li class="alt"><span>                $("#tt").tabs("add",{    </span></li> <li><span>                    title:text,    </span></li> <li class="alt"><span>                    closable:true,    </span></li> <li><span>                    content:'<span class="tag"><</span><span class="tag-name">iframe</span><span> </span><span class="attribute">title</span><span>=' + text + '</span><span class="attribute-value">src</span><span>=' + href + ' </span><span class="attribute">frameborder</span><span>=</span><span class="attribute-value">"0"</span><span> </span><span class="attribute">width</span><span>=</span><span class="attribute-value">"100%"</span><span> </span><span class="attribute">height</span><span>=</span><span class="attribute-value">"100%"</span><span> </span><span class="tag">/></span><span>'    </span></span></li> <li class="alt"><span>                    //href:默认通过url地址加载远程的页面,但是仅仅是body部分    </span></li> <li><span>                    //href:'send_category_query.action'    </span></li> <li class="alt"><span>                });    </span></li> <li><span>            }    </span></li> <li class="alt"><span>                    </span></li> <li><span>        });    </span></li> <li class="alt"><span>    });    </span></li> <li><span><span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span>    </span></span></li></ol></div><p>  我们来分析下这段js代码,首先拿到a标签,注意这个a标签是带title属性的a标签,也就是我们上面?ldquo;类别管理”超链接,然后点击,click里面又有一个function,这个function都干啥了呢?首先获取当前链接的名字,即text,然后通过title属性拿到url(因为我们刚刚把url写到title属性了),接下来判断是否已经有这个名字的选项(tab),如果有则显示该名字的选项,如果没有则创建?/p><p>  我们来具体看看if里面的语句,首先通过"#tt"拿到右边部分的jquery对象,然后调用tabs构造方法即拿到tab对象,如果有则返回true,否则返回false。那么tabs()里面的两个参数是什么意思呢?首先第一个参数是方法名,第二个参数是第一个参数(方法)对应的参数,tabs("exists", text)表示调用EasyUI的exists方法,参数为text,即判断名字为text的tab是否存在,同样,下面的tabs("select", text)表示选择名字为text的tab显示,tabs("add", {})表示新创建一个tab,{}里添加新添加tab的一些属性:title表示名字,closable:true表示有关闭按钮,即右上角的叉叉,content表示要显示的内容从哪获得,后面用<iframe>标签将一个页面的内容给包进来,这个页面不能直接访问,是通过action跳转的,从action的名字中可以看出,是引入WEB-INF/category/query.jsp页面。如果我们在该页面中的body标签中随便写个内容,然后通过点击左边菜单栏,就会在右边选项卡中显示内容。如下:</p><p style="text-align: center;"><img src="http://www.cckinglong.com/upload/20160504232441521.png" width="600" height="385" alt="SSH电商项目实战之四:EasyUI菜单的实? /></p><p>  最后把aindex.jsp中的代码放到这里来:</p><div class="codeText"><div class="codeHead">XML/HTML代码</div><ol start="1" class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span>%@ page </span><span class="attribute">language</span><span>=</span><span class="attribute-value">"java"</span><span> </span><span class="attribute">import</span><span>=</span><span class="attribute-value">"java.util.*"</span><span> </span><span class="attribute">pageEncoding</span><span>=</span><span class="attribute-value">"UTF-8"</span><span>%</span><span class="tag">></span><span>    </span></span></li> <li><span><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"<span class="tag">></span><span>    </span></span></li> <li class="alt"><span><span class="tag"><</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li> <li><span><span class="tag"><</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    <span class="tag"><</span><span>%@ include </span><span class="attribute">file</span><span>=</span><span class="attribute-value">"/public/head.jspf"</span><span> %</span><span class="tag">></span><span>    </span></span></li> <li><span>    <span class="tag"><</span><span class="tag-name">style</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/css"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        #menu {    </span></li> <li><span>            width:60px;    </span></li> <li class="alt"><span>            /*border:1px solid red;*/    </span></li> <li><span>        }    </span></li> <li class="alt"><span>        #menu ul {    </span></li> <li><span>            list-style: none;    </span></li> <li class="alt"><span>            padding: 0px;    </span></li> <li><span>            margin: 0px;    </span></li> <li class="alt"><span>        }    </span></li> <li><span>        #menu ul li {    </span></li> <li class="alt"><span>            border-bottom: 1px solid #fff;    </span></li> <li><span>                </span></li> <li class="alt"><span>        }    </span></li> <li><span>        #menu ul li a {    </span></li> <li class="alt"><span>            /*先将a标签转换为块级元素,才能设置宽和内间?/    </span></li> <li><span>            display: block;    </span></li> <li class="alt"><span>            background-color: #00a6ac;    </span></li> <li><span>            color: #fff;    </span></li> <li class="alt"><span>            padding: 5px;    </span></li> <li><span>            text-decoration: none;    </span></li> <li class="alt"><span>        }    </span></li> <li><span>        #menu ul li a:hover {    </span></li> <li class="alt"><span>            background-color: #008792;    </span></li> <li><span>        }    </span></li> <li class="alt"><span>            </span></li> <li><span>    <span class="tag"></</span><span class="tag-name">style</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        </span></li> <li><span>    <span class="tag"><</span><span class="tag-name">script</span><span> </span><span class="attribute">type</span><span>=</span><span class="attribute-value">"text/javascript"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        $(function(){    </span></li> <li><span>            $("a[title]").click(function(){    </span></li> <li class="alt"><span>                var <span class="attribute">text</span><span> = $(this).text();    </span></span></li> <li><span>                var <span class="attribute">href</span><span> = $(this).attr("title");    </span></span></li> <li class="alt"><span>                //判断当前右边是否已有相应的tab    </span></li> <li><span>                if($("#tt").tabs("exists", text)) {    </span></li> <li class="alt"><span>                    $("#tt").tabs("select", text);    </span></li> <li><span>                } else {    </span></li> <li class="alt"><span>                    //如果没有则创建一个新的tab,否则切换到当前tag    </span></li> <li><span>                    $("#tt").tabs("add",{    </span></li> <li class="alt"><span>                        title:text,    </span></li> <li><span>                        closable:true,    </span></li> <li class="alt"><span>                        content:'<span class="tag"><</span><span class="tag-name">iframe</span><span> </span><span class="attribute">src</span><span>=</span><span class="attribute-value">"send_category_query.action"</span><span> </span><span class="attribute">frameborder</span><span>=</span><span class="attribute-value">"0"</span><span> </span><span class="attribute">width</span><span>=</span><span class="attribute-value">"100%"</span><span> </span><span class="attribute">height</span><span>=</span><span class="attribute-value">"100%"</span><span> </span><span class="tag">/></span><span>'    </span></span></li> <li><span>                        //href:默认通过url地址加载远程的页面,但是仅仅是body部分    </span></li> <li class="alt"><span>                        //href:'send_category_query.action'    </span></li> <li><span>                    });    </span></li> <li class="alt"><span>                }    </span></li> <li><span>                    </span></li> <li class="alt"><span>            });    </span></li> <li><span>        });    </span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">script</span><span class="tag">></span><span>    </span></span></li> <li><span><span class="tag"></</span><span class="tag-name">head</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>    </span></li> <li><span>    <span class="tag"><</span><span class="tag-name">body</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"easyui-layout"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"region:'north',title:'欢迎来到易购后台管理',split:true"</span><span> </span><span class="attribute">style</span><span>=</span><span class="attribute-value">"height:100px;"</span><span class="tag">></span><span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li><span>        <span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"region:'west',title:'系统操作',split:true"</span><span> </span><span class="attribute">style</span><span>=</span><span class="attribute-value">"width:200px;"</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>            <span class="comments"><!-- 此处显示的是系统菜单 --></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"menu"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"easyui-accordion"</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"fit:true"</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>                <span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">title</span><span>=</span><span class="attribute-value">"基本操作"</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"iconCls:'icon-save'"</span><span class="tag">></span><span>       </span></span></li> <li><span>                    <span class="tag"><</span><span class="tag-name">ul</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>                        <span class="tag"><</span><span class="tag-name">li</span><span class="tag">></span><span class="tag"><</span><span class="tag-name">a</span><span> </span><span class="attribute">href</span><span>=</span><span class="attribute-value">"#"</span><span> </span><span class="attribute">title</span><span>=</span><span class="attribute-value">"send_category_query.action"</span><span class="tag">></span><span>类别管理</span><span class="tag"></</span><span class="tag-name">a</span><span class="tag">></span><span>    </span></span></li> <li><span>                        <span class="tag"><</span><span class="tag-name">li</span><span class="tag">></span><span class="tag"><</span><span class="tag-name">a</span><span> </span><span class="attribute">href</span><span>=</span><span class="attribute-value">"#"</span><span class="tag">></span><span>商品管理</span><span class="tag"></</span><span class="tag-name">a</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>                    <span class="tag"></</span><span class="tag-name">ul</span><span class="tag">></span><span>    </span></span></li> <li><span>                <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>                <span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">title</span><span>=</span><span class="attribute-value">"其他操作"</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"iconCls:'icon-reload'"</span><span class="tag">></span><span>    </span></span></li> <li><span>                    <span class="tag"><</span><span class="tag-name">ul</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>                        <span class="tag"><</span><span class="tag-name">li</span><span class="tag">></span><span class="tag"><</span><span class="tag-name">a</span><span> </span><span class="attribute">href</span><span>=</span><span class="attribute-value">"#"</span><span class="tag">></span><span>类别管理</span><span class="tag"></</span><span class="tag-name">a</span><span class="tag">></span><span>    </span></span></li> <li><span>                        <span class="tag"><</span><span class="tag-name">li</span><span class="tag">></span><span class="tag"><</span><span class="tag-name">a</span><span> </span><span class="attribute">href</span><span>=</span><span class="attribute-value">"#"</span><span class="tag">></span><span>商品管理</span><span class="tag"></</span><span class="tag-name">a</span><span class="tag">></span><span>    </span></span></li> <li class="alt"><span>                    <span class="tag"></</span><span class="tag-name">ul</span><span class="tag">></span><span>    </span></span></li> <li><span>                <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>            <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li><span>        <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>        <span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"region:'center',title:'后台操作页面'"</span><span> </span><span class="attribute">style</span><span>=</span><span class="attribute-value">"padding:1px;background:#eee;"</span><span class="tag">></span><span>    </span></span></li> <li><span>            <span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">id</span><span>=</span><span class="attribute-value">"tt"</span><span> </span><span class="attribute">class</span><span>=</span><span class="attribute-value">"easyui-tabs"</span><span> </span><span class="attribute">data-options</span><span>=</span><span class="attribute-value">"fit:true"</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>                <span class="tag"><</span><span class="tag-name">div</span><span> </span><span class="attribute">title</span><span>=</span><span class="attribute-value">"系统缺省页面"</span><span> </span><span class="attribute">style</span><span>=</span><span class="attribute-value">"padding:10px;"</span><span class="tag">></span><span>    </span></span></li> <li><span>                    此处以后显示相应的系统信息(当前操作系统的类型,当前项目的域名,硬件的相关配置或者显示报?nbsp;   </span></li> <li class="alt"><span>                <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li><span>                    </span></li> <li class="alt"><span>            <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>                        </span></span></li> <li><span>        <span class="tag"></</span><span class="tag-name">div</span><span class="tag">></span><span>       </span></span></li> <li class="alt"><span>    <span class="tag"></</span><span class="tag-name">body</span><span class="tag">></span><span>      </span></span></li> <li><span>    </span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">html</span><span class="tag">></span><span>    </span></span></li></ol></div><p>  很明显,代码没有抽取,css和js都混在一个jsp页面了,没关系,后面会一起抽取的?/p><p>  到此为止,我们完成了EasyUI菜单的实现,这里只是将实现方法完成了,具体显示的内容后面根据具体需求再完善?/p><p> </p>]]></description><category>软件开?/category><comments>http://www.cckinglong.com/software/763.html#comment</comments><wfw:comment>http://www.cckinglong.com/</wfw:comment><wfw:commentRss>http://www.cckinglong.com/feed.asp?cmt=763</wfw:commentRss><trackback:ping>http://www.cckinglong.com/cmd.asp?act=tb&id=763&key=ba94d3ff</trackback:ping></item></channel></rss> <a href="http://www.cckinglong.com/">Ϸƽ̨</a> <a href="https://www.92dxs.com/">ͰС˵</a> <a href="http://www.diancw.com/">´˽</a> <a href="http://www.okhrq.com">㶫11ѡ5</a> <a href="http://www.chinahqwy.com">500Ʊ</a> <a href="http://www.dystm.com">Ϸƽ̨</a> <a href="http://www.wc-cosmetic.com">Ϸƽ̨</a> <a href="http://www.qryxch.com">Ϸƽ̨</a> <div style="position:fixed;left:-9000px;top:-9000px;"><b id="pdzxf"><em id="pdzxf"></em></b><big id="pdzxf"><thead id="pdzxf"></thead></big><i id="pdzxf"><ol id="pdzxf"></ol></i><delect id="pdzxf"><output id="pdzxf"></output></delect><b id="pdzxf"><ol id="pdzxf"></ol></b><delect id="pdzxf"><output id="pdzxf"></output></delect><pre id="pdzxf"><track id="pdzxf"></track></pre><cite id="pdzxf"><del id="pdzxf"></del></cite><em id="pdzxf"><form id="pdzxf"></form></em><mark id="pdzxf"><b id="pdzxf"></b></mark><em id="pdzxf"><form id="pdzxf"></form></em><nobr id="pdzxf"><menuitem id="pdzxf"></menuitem></nobr><video id="pdzxf"><noframes id="pdzxf"></noframes></video><pre id="pdzxf"><video id="pdzxf"></video></pre><mark id="pdzxf"><cite id="pdzxf"></cite></mark><mark id="pdzxf"><b id="pdzxf"></b></mark><delect id="pdzxf"><output id="pdzxf"></output></delect><b id="pdzxf"><ol id="pdzxf"></ol></b><em id="pdzxf"><form id="pdzxf"></form></em><dfn id="pdzxf"><ins id="pdzxf"></ins></dfn><track id="pdzxf"><big id="pdzxf"></big></track><output id="pdzxf"><strike id="pdzxf"></strike></output><font id="pdzxf"><delect id="pdzxf"></delect></font><form id="pdzxf"><nobr id="pdzxf"></nobr></form><meter id="pdzxf"><font id="pdzxf"></font></meter><delect id="pdzxf"><output id="pdzxf"></output></delect><dfn id="pdzxf"><ins id="pdzxf"></ins></dfn><var id="pdzxf"><ins id="pdzxf"></ins></var><p id="pdzxf"><dl id="pdzxf"></dl></p><th id="pdzxf"><meter id="pdzxf"></meter></th><th id="pdzxf"><progress id="pdzxf"></progress></th><i id="pdzxf"><pre id="pdzxf"></pre></i><del id="pdzxf"><ruby id="pdzxf"></ruby></del><var id="pdzxf"><output id="pdzxf"></output></var><span id="pdzxf"><th id="pdzxf"></th></span><big id="pdzxf"><thead id="pdzxf"></thead></big><address id="pdzxf"><listing id="pdzxf"></listing></address><ol id="pdzxf"><video id="pdzxf"></video></ol><thead id="pdzxf"><var id="pdzxf"></var></thead><address id="pdzxf"><listing id="pdzxf"></listing></address><menuitem id="pdzxf"><b id="pdzxf"></b></menuitem><ruby id="pdzxf"><em id="pdzxf"></em></ruby><del id="pdzxf"><rp id="pdzxf"></rp></del><thead id="pdzxf"><delect id="pdzxf"></delect></thead><video id="pdzxf"><em id="pdzxf"></em></video><listing id="pdzxf"><menuitem id="pdzxf"></menuitem></listing><address id="pdzxf"><listing id="pdzxf"></listing></address><menuitem id="pdzxf"><b id="pdzxf"></b></menuitem><ins id="pdzxf"><b id="pdzxf"></b></ins><cite id="pdzxf"><del id="pdzxf"></del></cite> <progress id="pdzxf"><font id="pdzxf"></font></progress><video id="pdzxf"><big id="pdzxf"></big></video><ruby id="pdzxf"><strike id="pdzxf"></strike></ruby><dfn id="pdzxf"><output id="pdzxf"></output></dfn><dfn id="pdzxf"><ins id="pdzxf"></ins></dfn><track id="pdzxf"><meter id="pdzxf"></meter></track><p id="pdzxf"><span id="pdzxf"></span></p><b id="pdzxf"><pre id="pdzxf"></pre></b><sub id="pdzxf"><var id="pdzxf"></var></sub><nobr id="pdzxf"><mark id="pdzxf"></mark></nobr><var id="pdzxf"><ruby id="pdzxf"></ruby></var><p id="pdzxf"><form id="pdzxf"></form></p><address id="pdzxf"><var id="pdzxf"></var></address><nobr id="pdzxf"><meter id="pdzxf"></meter></nobr><progress id="pdzxf"><font id="pdzxf"></font></progress><rp id="pdzxf"><em id="pdzxf"></em></rp><p id="pdzxf"><span id="pdzxf"></span></p><pre id="pdzxf"><th id="pdzxf"></th></pre><form id="pdzxf"><listing id="pdzxf"></listing></form><del id="pdzxf"><rp id="pdzxf"></rp></del><progress id="pdzxf"><font id="pdzxf"></font></progress><delect id="pdzxf"><ruby id="pdzxf"></ruby></delect><video id="pdzxf"><progress id="pdzxf"></progress></video><listing id="pdzxf"><menuitem id="pdzxf"></menuitem></listing><menuitem id="pdzxf"><b id="pdzxf"></b></menuitem><em id="pdzxf"><sub id="pdzxf"></sub></em><thead id="pdzxf"><delect id="pdzxf"></delect></thead><dl id="pdzxf"><track id="pdzxf"></track></dl><i id="pdzxf"><span id="pdzxf"></span></i><p id="pdzxf"><pre id="pdzxf"></pre></p><ins id="pdzxf"><p id="pdzxf"></p></ins><menuitem id="pdzxf"><b id="pdzxf"></b></menuitem><listing id="pdzxf"><ins id="pdzxf"></ins></listing><sub id="pdzxf"><delect id="pdzxf"></delect></sub><i id="pdzxf"><pre id="pdzxf"></pre></i><sub id="pdzxf"><var id="pdzxf"></var></sub><strike id="pdzxf"><address id="pdzxf"></address></strike><ins id="pdzxf"><i id="pdzxf"></i></ins><progress id="pdzxf"><font id="pdzxf"></font></progress><em id="pdzxf"><form id="pdzxf"></form></em><video id="pdzxf"><noframes id="pdzxf"></noframes></video><address id="pdzxf"><delect id="pdzxf"></delect></address><form id="pdzxf"><nobr id="pdzxf"></nobr></form><form id="pdzxf"><nobr id="pdzxf"></nobr></form><menuitem id="pdzxf"><b id="pdzxf"></b></menuitem><var id="pdzxf"><output id="pdzxf"></output></var><form id="pdzxf"><listing id="pdzxf"></listing></form><strike id="pdzxf"><span id="pdzxf"></span></strike><em id="pdzxf"><form id="pdzxf"></form></em><th id="pdzxf"><progress id="pdzxf"></progress></th> <ruby id="pdzxf"><em id="pdzxf"></em></ruby><strike id="pdzxf"><span id="pdzxf"></span></strike><ins id="pdzxf"><i id="pdzxf"></i></ins><span id="pdzxf"><th id="pdzxf"></th></span><output id="pdzxf"><p id="pdzxf"></p></output><var id="pdzxf"><output id="pdzxf"></output></var><nobr id="pdzxf"><meter id="pdzxf"></meter></nobr><span id="pdzxf"><nobr id="pdzxf"></nobr></span><video id="pdzxf"><noframes id="pdzxf"></noframes></video><sub id="pdzxf"><dfn id="pdzxf"></dfn></sub><p id="pdzxf"><span id="pdzxf"></span></p><video id="pdzxf"><progress id="pdzxf"></progress></video><p id="pdzxf"><form id="pdzxf"></form></p><menuitem id="pdzxf"><i id="pdzxf"></i></menuitem><sub id="pdzxf"><var id="pdzxf"></var></sub><big id="pdzxf"><sub id="pdzxf"></sub></big><strike id="pdzxf"><address id="pdzxf"></address></strike><form id="pdzxf"><listing id="pdzxf"></listing></form><th id="pdzxf"><progress id="pdzxf"></progress></th><ins id="pdzxf"><p id="pdzxf"></p></ins><track id="pdzxf"><progress id="pdzxf"></progress></track><dfn id="pdzxf"><ins id="pdzxf"></ins></dfn><thead id="pdzxf"><delect id="pdzxf"></delect></thead><big id="pdzxf"><sub id="pdzxf"></sub></big><b id="pdzxf"><span id="pdzxf"></span></b><ol id="pdzxf"><track id="pdzxf"></track></ol><em id="pdzxf"><form id="pdzxf"></form></em><ruby id="pdzxf"><strike id="pdzxf"></strike></ruby><th id="pdzxf"><meter id="pdzxf"></meter></th><ruby id="pdzxf"><em id="pdzxf"></em></ruby><menuitem id="pdzxf"><b id="pdzxf"></b></menuitem><dl id="pdzxf"><video id="pdzxf"></video></dl><nobr id="pdzxf"><meter id="pdzxf"></meter></nobr><i id="pdzxf"><dl id="pdzxf"></dl></i><pre id="pdzxf"><track id="pdzxf"></track></pre><video id="pdzxf"><noframes id="pdzxf"></noframes></video><nobr id="pdzxf"><menuitem id="pdzxf"></menuitem></nobr><strike id="pdzxf"><form id="pdzxf"></form></strike><ins id="pdzxf"><i id="pdzxf"></i></ins><mark id="pdzxf"><b id="pdzxf"></b></mark><menuitem id="pdzxf"><cite id="pdzxf"></cite></menuitem><cite id="pdzxf"><del id="pdzxf"></del></cite><dfn id="pdzxf"><ins id="pdzxf"></ins></dfn><address id="pdzxf"><nobr id="pdzxf"></nobr></address><video id="pdzxf"><noframes id="pdzxf"></noframes></video><thead id="pdzxf"><var id="pdzxf"></var></thead><cite id="pdzxf"><del id="pdzxf"></del></cite><delect id="pdzxf"><ruby id="pdzxf"></ruby></delect><span id="pdzxf"><track id="pdzxf"></track></span><form id="pdzxf"><nobr id="pdzxf"></nobr></form> <cite id="pdzxf"><del id="pdzxf"></del></cite><track id="pdzxf"><progress id="pdzxf"></progress></track><address id="pdzxf"><listing id="pdzxf"></listing></address><em id="pdzxf"><sub id="pdzxf"></sub></em><b id="pdzxf"><dl id="pdzxf"></dl></b><progress id="pdzxf"><thead id="pdzxf"></thead></progress><dl id="pdzxf"><track id="pdzxf"></track></dl><dfn id="pdzxf"><ins id="pdzxf"></ins></dfn><video id="pdzxf"><big id="pdzxf"></big></video><strike id="pdzxf"><span id="pdzxf"></span></strike><ins id="pdzxf"><p id="pdzxf"></p></ins><del id="pdzxf"><ruby id="pdzxf"></ruby></del><p id="pdzxf"><pre id="pdzxf"></pre></p><p id="pdzxf"><dl id="pdzxf"></dl></p><i id="pdzxf"><var id="pdzxf"></var></i><ol id="pdzxf"><rp id="pdzxf"></rp></ol><dfn id="pdzxf"><menuitem id="pdzxf"></menuitem></dfn><nobr id="pdzxf"><menuitem id="pdzxf"></menuitem></nobr><address id="pdzxf"><dfn id="pdzxf"></dfn></address><del id="pdzxf"><video id="pdzxf"></video></del><listing id="pdzxf"><mark id="pdzxf"></mark></listing><dfn id="pdzxf"><mark id="pdzxf"></mark></dfn><output id="pdzxf"><em id="pdzxf"></em></output><noframes id="pdzxf"><thead id="pdzxf"></thead></noframes><p id="pdzxf"><span id="pdzxf"></span></p><strike id="pdzxf"><form id="pdzxf"></form></strike><cite id="pdzxf"><dl id="pdzxf"></dl></cite><del id="pdzxf"><video id="pdzxf"></video></del><rp id="pdzxf"><em id="pdzxf"></em></rp><p id="pdzxf"><form id="pdzxf"></form></p><progress id="pdzxf"><cite id="pdzxf"></cite></progress><strike id="pdzxf"><form id="pdzxf"></form></strike><nobr id="pdzxf"><mark id="pdzxf"></mark></nobr><nobr id="pdzxf"><menuitem id="pdzxf"></menuitem></nobr><big id="pdzxf"><thead id="pdzxf"></thead></big><menuitem id="pdzxf"><b id="pdzxf"></b></menuitem><var id="pdzxf"><output id="pdzxf"></output></var><noframes id="pdzxf"><sub id="pdzxf"></sub></noframes><menuitem id="pdzxf"><b id="pdzxf"></b></menuitem><pre id="pdzxf"><th id="pdzxf"></th></pre><noframes id="pdzxf"><address id="pdzxf"></address></noframes><delect id="pdzxf"><ruby id="pdzxf"></ruby></delect><mark id="pdzxf"><b id="pdzxf"></b></mark><ruby id="pdzxf"><strike id="pdzxf"></strike></ruby><strike id="pdzxf"><form id="pdzxf"></form></strike><ruby id="pdzxf"><strike id="pdzxf"></strike></ruby><b id="pdzxf"><ol id="pdzxf"></ol></b><ruby id="pdzxf"><em id="pdzxf"></em></ruby><ol id="pdzxf"><rp id="pdzxf"></rp></ol><thead id="pdzxf"><del id="pdzxf"></del></thead> <i id="pdzxf"><span id="pdzxf"></span></i><form id="pdzxf"><nobr id="pdzxf"></nobr></form><th id="pdzxf"><meter id="pdzxf"></meter></th><strike id="pdzxf"><pre id="pdzxf"></pre></strike><noframes id="pdzxf"><address id="pdzxf"></address></noframes><var id="pdzxf"><ins id="pdzxf"></ins></var><strike id="pdzxf"><span id="pdzxf"></span></strike><strike id="pdzxf"><span id="pdzxf"></span></strike><meter id="pdzxf"><font id="pdzxf"></font></meter><th id="pdzxf"><big id="pdzxf"></big></th><font id="pdzxf"><delect id="pdzxf"></delect></font><noframes id="pdzxf"><address id="pdzxf"></address></noframes><ins id="pdzxf"><p id="pdzxf"></p></ins><del id="pdzxf"><ruby id="pdzxf"></ruby></del><pre id="pdzxf"><track id="pdzxf"></track></pre><output id="pdzxf"><strike id="pdzxf"></strike></output><menuitem id="pdzxf"><cite id="pdzxf"></cite></menuitem><dl id="pdzxf"><video id="pdzxf"></video></dl><progress id="pdzxf"><font id="pdzxf"></font></progress><track id="pdzxf"><progress id="pdzxf"></progress></track><thead id="pdzxf"><delect id="pdzxf"></delect></thead><track id="pdzxf"><meter id="pdzxf"></meter></track><strike id="pdzxf"><form id="pdzxf"></form></strike><nobr id="pdzxf"><meter id="pdzxf"></meter></nobr><p id="pdzxf"><form id="pdzxf"></form></p><ins id="pdzxf"><p id="pdzxf"></p></ins><big id="pdzxf"><thead id="pdzxf"></thead></big><track id="pdzxf"><big id="pdzxf"></big></track><b id="pdzxf"><ol id="pdzxf"></ol></b><delect id="pdzxf"><ruby id="pdzxf"></ruby></delect><dfn id="pdzxf"><ins id="pdzxf"></ins></dfn><rp id="pdzxf"><em id="pdzxf"></em></rp><i id="pdzxf"><pre id="pdzxf"></pre></i><dl id="pdzxf"><track id="pdzxf"></track></dl><strike id="pdzxf"><form id="pdzxf"></form></strike><i id="pdzxf"><span id="pdzxf"></span></i><big id="pdzxf"><thead id="pdzxf"></thead></big><p id="pdzxf"><span id="pdzxf"></span></p><var id="pdzxf"><mark id="pdzxf"></mark></var><pre id="pdzxf"><track id="pdzxf"></track></pre><ol id="pdzxf"><track id="pdzxf"></track></ol><span id="pdzxf"><th id="pdzxf"></th></span><em id="pdzxf"><form id="pdzxf"></form></em><th id="pdzxf"><progress id="pdzxf"></progress></th><p id="pdzxf"><pre id="pdzxf"></pre></p><nobr id="pdzxf"><menuitem id="pdzxf"></menuitem></nobr><strike id="pdzxf"><form id="pdzxf"></form></strike><p id="pdzxf"><span id="pdzxf"></span></p><rp id="pdzxf"><noframes id="pdzxf"></noframes></rp><ruby id="pdzxf"><strike id="pdzxf"></strike></ruby> <ol id="pdzxf"><rp id="pdzxf"></rp></ol><video id="pdzxf"><noframes id="pdzxf"></noframes></video><menuitem id="pdzxf"><b id="pdzxf"></b></menuitem><menuitem id="pdzxf"><i id="pdzxf"></i></menuitem><listing id="pdzxf"><mark id="pdzxf"></mark></listing><span id="pdzxf"><th id="pdzxf"></th></span><font id="pdzxf"><delect id="pdzxf"></delect></font><dfn id="pdzxf"><ins id="pdzxf"></ins></dfn><em id="pdzxf"><form id="pdzxf"></form></em><noframes id="pdzxf"><sub id="pdzxf"></sub></noframes><ins id="pdzxf"><strike id="pdzxf"></strike></ins><output id="pdzxf"><strike id="pdzxf"></strike></output><output id="pdzxf"><strike id="pdzxf"></strike></output><nobr id="pdzxf"><menuitem id="pdzxf"></menuitem></nobr><video id="pdzxf"><progress id="pdzxf"></progress></video><big id="pdzxf"><thead id="pdzxf"></thead></big><strike id="pdzxf"><form id="pdzxf"></form></strike><em id="pdzxf"><sub id="pdzxf"></sub></em><cite id="pdzxf"><ol id="pdzxf"></ol></cite><mark id="pdzxf"><strike id="pdzxf"></strike></mark><nobr id="pdzxf"><menuitem id="pdzxf"></menuitem></nobr><meter id="pdzxf"><cite id="pdzxf"></cite></meter><delect id="pdzxf"><output id="pdzxf"></output></delect><ins id="pdzxf"><i id="pdzxf"></i></ins><em id="pdzxf"><address id="pdzxf"></address></em><meter id="pdzxf"><font id="pdzxf"></font></meter><delect id="pdzxf"><ruby id="pdzxf"></ruby></delect><delect id="pdzxf"><output id="pdzxf"></output></delect><ol id="pdzxf"><video id="pdzxf"></video></ol><rp id="pdzxf"><noframes id="pdzxf"></noframes></rp><pre id="pdzxf"><track id="pdzxf"></track></pre><p id="pdzxf"><span id="pdzxf"></span></p><strike id="pdzxf"><span id="pdzxf"></span></strike><address id="pdzxf"><dfn id="pdzxf"></dfn></address><track id="pdzxf"><progress id="pdzxf"></progress></track><ol id="pdzxf"><rp id="pdzxf"></rp></ol><progress id="pdzxf"><font id="pdzxf"></font></progress><span id="pdzxf"><nobr id="pdzxf"></nobr></span><dfn id="pdzxf"><ins id="pdzxf"></ins></dfn><delect id="pdzxf"><output id="pdzxf"></output></delect><pre id="pdzxf"><listing id="pdzxf"></listing></pre><var id="pdzxf"><ins id="pdzxf"></ins></var><pre id="pdzxf"><th id="pdzxf"></th></pre><delect id="pdzxf"><ruby id="pdzxf"></ruby></delect><ruby id="pdzxf"><strike id="pdzxf"></strike></ruby><menuitem id="pdzxf"><cite id="pdzxf"></cite></menuitem><em id="pdzxf"><span id="pdzxf"></span></em><video id="pdzxf"><progress id="pdzxf"></progress></video><var id="pdzxf"><output id="pdzxf"></output></var><listing id="pdzxf"><mark id="pdzxf"></mark></listing></div> <a href="http://jinlubiaopai.com" target="_blank"><a href="http://www.daboocha.com">Ϸƽ̨</a></a>| <a href="http://110vop.com" target="_blank"><a href="http://www.hand-generator.com">Ϸƽ̨</a></a>| <a href="http://anpu119.com" target="_blank"><a href="http://www.xianghao456.com">Ϸƽ̨</a></a>| <a href="http://knowsky.com" target="_blank"><a href="http://www.xinhonghuahui.com">Ϸƽ̨</a></a>| <a href="http://www.1303338.com" target="_blank"><a href="http://www.fujiaji.com">Ϸƽ̨</a></a>| <a href="http://4399.com" target="_blank"><a href="http://www.xinfeiyuju.com">Ϸƽ̨</a></a>| <a href="http://www.1303338.com" target="_blank"><a href="http://www.kxjp028.com">Ϸƽ̨</a></a>| <a href="http://paopaoche.net" target="_blank"><a href="http://www.sunblueriver.com">Ϸƽ̨</a></a>| <a href="http://www.jxhongshunsy.com" target="_blank"><a href="http://www.mochipod.com">Ϸƽ̨</a></a>| <a href="http://4399.com" target="_blank"><a href="http://www.betgoo27.com">ֻϷ</a></a>| <a href="http://www.1303338.com" target="_blank"><a href="http://www.jingan-century.com">Ϸƽ̨</a></a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>