科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Spring MVC framework深入总体分析

Spring MVC framework深入总体分析

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

下面列举一下Spring的MVC framework在设计时做出的一些重要的决定,并将之和相关的MVC framework如Webwork2或struts进行对比:

来源:IT专家网 2008年4月7日

关键字: 分析 framework Spring

  • 评论
  • 分享微博
  • 分享邮件
在当今的MVC framework里,似乎Webwork2逐渐成为主流, Webwork2+SpringFramework的组合变得越来越流行。这似乎意味着Spring自带的MVC framework远比Webwork2差,所以大家纷纷用Webwork2来代替。确实,Spring的MVC framework不算是整个Spring的核心部件,但它的威力却超过了很多人的想象。很多人包括xiecc认为Spring的MVC framework是非常优秀的,甚至比Webwork2更优秀。

  下面列举一下Spring的MVC framework在设计时做出的一些重要的决定,并将之和相关的MVC framework如Webwork2或struts进行对比:

  一、 Spring的整个MVC配置是基于IOC容器的

  与struts或webwork2相比,这是一个ms有点奇怪的决定,看一下Spring MVC的配置文件,最先看到的不是action或者form,而是一些有着特定名字的bean,Bean下面的配置是一些简单或有点复杂的属性。我们看到的是机器更容易的数据结构,而不是人更容易理解的元素。

  但是这恰恰是Spring的MVC强大的根源!因为它的配置就是Spring的核心IOC容器的配置,这意味着所有IOC容器的威力都可以在这里展现,我们可以为所欲为地对Spring MVC进行扩展和增强,我们可以完成在其它MVC framwork中很多难以想象的任务。想扩展新的URL映射方式吗?要换一个themeResolver或LocalReolver的实现吗?想在页面中显示新类型的View(比如说RDF,呵呵,一个小秘密:xiecc是研究语义网的,虽然成天不务正业,不写论文,只写八卦)?甚至想直接在Controller里定义AOP吗?这些对Spring的MVC来说都是小菜一碟。

  我没有仔细研究过Webwork2的扩展机制,我知道通过Webwork2的interceptor机制,可以进行很多的扩展,甚至有一个简单简单的IOC容器。但不管它有多强大,提供了多少扩展点。它的威力都很难和真正的IOC容器相比。而struts的plugin功能则是出名的滥,虽然它也提供了plugin机制。

  Spring采用IOC配置的另一个原因是使Spring的MVC与Spring的IOC容器的整合变得非常的容易。Spring提供了与struts与webwork2的整合,但是这样整合都需要在进行间接的包装,感觉总不是很自然。而且还会导致一个概念多个配置,webwork2就需要在Spring里配置bean,再配置自己的xwork文件。想象一下吧,我们的bean直接就是一个controller,直接可以完成MVC的所有任务,这是多少爽的感觉。

  Rod Johnson采用IOC容器来实现的另一个原因是这会减少好多开发工作量。看一下urlMapping吧,它提供的property本身就是一个HashMap,只有配置完成,我们的bean里的数据就自然存在了,哈哈,好爽吧。不用象struts那样解析XML,再把它的内容一项一项地读到HashMap里。

  虽然这样的配置会有点怪异,但假如我们对Spring的IOC容器非常熟悉的话,会发现它非常的亲切,也非常的简单。

  最后是一个简单的小秘密,Spring怎么知道某个bean的配置就是urlMapping?另一个bean的配置就是viewResolver?其实很简单,把所有的bean全部读到内存里,然后通过bean的名字或类型去找就行了。通过名字去找就是简单的getBean方法,通过类型去找则使用了BeanFactoryUtils.beansOfTypeIncludingAncestors的静态方法。

  二、 Spring提供了明确的Model, View概念和相应的数据结构

  在Spring里有一个有趣的数据类型叫做ModelAndView,它只是简单地把要显示的数据和显示的结果封装在一个类里。但是它却提供了明确的MVC概念,尤其是model概念的强化,使程序的逻辑变得更清晰了。

  记得以前在Struts里写程序里的时候,为了显示数据经常自己把东西放到HttpSession或HttpServletRequest里(或set到form里,虽然不太有用),这造成了model概念的模糊,而且也导致了struts与JSP页面的紧耦合。假如我们要替换成Veloctiy,就得另外加一个plugin,因为在velocity里数据是不需要不放到request里的。

  Webwork2里强调的是与Web framework解耦和它的command模式的简单性,因此在它的action里只有简单的get或set方法,假如返回数据,也只是简单地返回一个String.当然这样的实现有它的好处,但是它淡化了model和view的概念。Rod Johnson认为Webwork2里的Action同时包含了Action和Model的职责,这样一个类的职责太多,不是一个很好的设计。当然Jason Carreira不太认同这种观点,因为Action里的model对象完成可以delege给其它对象。但不管怎样,这种争论的根源在于Webwork2里淡化了model, view甚至web的概念。仁者见仁,智者见智,最后的结果还是看个人喜欢好吧。

三、 Spring的Controller是Singleton的,或者是线程不安全的

  和Struts一样,Spring的Controller是Singleton的,这意味着每个request过来,系统都会用原有的instance去处理,这样导致了两个结果:我们不用每次创建Controller,减少了对象创建和垃圾收集的时间;由于只有一个Controller的instance,当多个线程调用它的时候,它里面的instance变量不是线程安全的。

  这也是Webwork2吹嘘的地方,它的每个Action都是线程安全的。因为每过来一个request,它就创建一个Action对象。由于现代JDK垃圾收集功能的效率已经不成问题,所以这种创建完一个对象就扔掉的模式也得到了好多人的认可。Rod Johnson甚至以此为例证明J2EE提供的object pool功能是没多大价值的。

  但是当人们在吹嘘线程安全怎么怎么重要的时候,我想请问有多少人在多少情况下需要考虑线程安全?Rod Johnson在分析EJB的时候也提出过其它问题,并不是没有了EJB的线程安全魔法,世界就会灭亡的,大多数情况下,我们根本不需要考虑线程安全的问题,也不考虑object pool.因为我们大多数情况下不需要保持instance状态。

  至少我写了那么多的struts Action,写了那么多的Spring Controller,几乎没有碰到需要在instance变量保持状态的问题。当然也许是我写的代码不够多,Struts的设计者Craig R. McClanahan曾经说当时他设计struts时有两个条件不成熟:当时没有测试驱动开发的概念;当时JVM的垃圾收集性能太次。假如现在重新设计的话,他也会采用每个request生成一个新对象的设计方法,这样可以解决掉线程安全的问题了。

  四、 Spring不象Webwork2或tapestry那样去隐藏Servlet相关的元素如HttpServletRequest或HttpServletResponse

  这又是一个重要的设计决定。在Webwork2里我们没有HttpServletRequest或者HttpServletResponse,只有getter, setter或ActionContext里数据,这样的结果导致一个干净的Action,一个与Web完全无关的Action,一个可以在任何环境下独立运行的bean.那么Webwork2的这样一个基于Command模式的Action究竟给我们带来了什么?我想主要有两点:

  1、 它使我们的Action可以非常容易地被测试。

  2、 用户可以在Action里添加业务逻辑,并被其它类重用。

  然而仔细跟Spring比较一下,我们就会发现这两点功能所带来的好处其实并不象我们想象的那么显着。Spring的Controller类也可以非常轻松被测试,看一下spring-mock下面的包吧,它提供的MockHttpServletRequest, MockHttpServletResponse还有其它一些类让测试Controller变得异常轻松。再看一下Action里的业务逻辑吧,Jason Carreira曾经说我们可以尽情地在Webwork2的Action里加业务逻辑,因为Action是不依赖于Web的。但是有多少人真正往Action里加业务逻辑的?大多数人都会业务逻辑delegate给另一个Service类或Manager类。因为我们很清楚,往Action里加业务逻辑会使整个体系的分层架构变得不清晰,不管怎样,Web层就是Web层,业务层就是业务层,两者的逻辑混在一起总会带来问题的。而且往Action里加业务逻辑会使用这个Action类变得庞大,Webwork2的Action是每个request都创建实例的,尽管带来的性能影响不太大,但并不表示每次都要把业务逻辑再new出来,业务逻辑在大多数的情况下应该是单例的。

  不把request和response展现给用户当然还会带来功能上的损失,也许一般的场合,用用webwork2提供的接口已经足够了,但有时我们必须要知道request和response才能发挥出更大的威力。比如我以前的一个项目里有一个通过递归动态生成的树状结构的页面,在jsp页面上显示递归是痛苦或不可能的,因此我用response直接write出页面,这在spring里很easy,但在webwork里可能比较难了(偶不敢肯定,偶研究得不够深,也许高手是有办法的)。

五、 Spring提供了不错但不够充分的interceptor机制

  回头看一下struts,它在架构里甚至没有给我们提供hook point的机会,我们没有任何机会加入自己的interceptor.我们只能通过重载struts的RequestProcessor类来进行一点有限的扩展。

  到了Webwork2,似乎interceptor一下子成了整个Framework的核心,除了Action的核心部件,其它所有的东西都是interceptor.它的超强的interceptor功能使们扩展整个架构变得非常方便。有人称这种interceptor为AOP,Jason Carreira则自豪地宣称这个叫做pragamtic AOP.我不认同这是AOP,它只是简单的interceptor机制。但不管如何,它的interceptor确实有强大的功能。

  Spring也提供了它的interceptor机制,它的HandlerInterceptor三个interceptor方法:peHandle, postHandle, afterCompletion.分别对应Controller执行前,Controller执行后和page render之后。虽然大多数情况下已经够用,但是从功能上来说显然它没有Webwork2强大。从AOP的角度来看,它没有提供around interceptor,而只有before与after interceptor.这意味着我们无法在interceptor前后保持状态,最简单的情况假如我们要计算一个Controller的执行时间,我们必须在执行完before后把begintime这个状态保持住,再在after里把它调出来,但是显然这个状态保持会是个问题,我们不能把它放到instance变量里,因为interceptor不是线程安全的。也许通过ThreadLocal可以解决这个问题,但是如此简单的功能要用到这样的方法来处理,显然这个Interceptor本身设计上还是有点问题的。

  六、 Spring提供了MultiActionController,使它可以在一个类里包含多个Action

  这个设计和struts的DispatchAction有点类似,只不过提供了更灵活的机制。当我们的项目变大的时候,把功能类似的方法放到同一个Action里完全值得的!Webwork2缺少这样的机制。假如看一下Spring的源代码,会发现其实实现MultiActionController的工作量相当的少,只不过是用反射机制把解析出来的方法名执行一下就完事了。其实Webwork2也完全可以提供这样的机制。虽然从设计上来说确实不是很优雅,但是它确实很有用。

  七、 Spring提供了更多的选择方式

  看看Spring里提供的Controller吧,它提供了好多不同的Controller类。要生成Wizard吗?要专门用于提交form的Controller吗?要执多个方法的类吗?Spring提供了丰富的子类来扩展这些选择。当然我们还可以很轻松地自己扩展这些功能。

  再看看Spring的ViewResolver吧, 它提供了无数不同类型的ViewResolver.更重要的是我们自定义我们的页面映射方式。看看strtus,看看webwork2,都会存在页面与forward name的一层间接转换,我们必须在配置文件里配置好某个字符串(典型的是success)对应的是那个页面。但是Spring里我们有了更大的自由度,我们可以采用webwork2的策略,也可以采用更简单的策略,如将JSP文件名去掉扩展名的映射方法。也许有人认为这种映射方式很幼稚,但是我觉得它是非常有用的方式,即使在大项目里。

还有新的扩展吗?看看Spring Web Flow吧,它是SpringFramework的子项目。它为一长串的基于页面流的Wizard页面提供了可配置的实现方式。在Spring 1.3里,它将是SpringFramework的一部分。

  八、 Spring的tag

  尽管Spring的tag数量上少得可怜,但它却是精心设计的。它的目标很简单:让美工可以轻松地编辑页面。因为在Spring的页面里Text仍然是Text,checkbox仍然是CheckBox,而不象在struts或webwork2中的Tag.它只是用Springbind对输入内容进行了一下包装。所以尽管页面显示代码上会比Webwork2多,但这绝对是有价值的。

  在接下来的几章里,我会分析一下Spring是如何让我们的Web应用不需要知道ApplicationContext就能够访问IOC容器的,然后会对Spring的设计和执行过程进行简单的源码分析,然后给出几个扩展Spring MVC的方法。

    • 评论
    • 分享微博
    • 分享邮件
    闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾剧懓顪冪€n亜顒㈡い鎰矙閺屻劑鎮㈤崫鍕戙垽鏌i鐕佹疁妤犵偞鐗曡彁妞ゆ巻鍋撳┑陇鍋愮槐鎺楀箛椤撗勭杹闂佸搫鐭夌换婵嗙暦閸洖鐓涘ù锝夋敱閻繘姊绘担鍛婃儓妞ゆ垵鎳橀弻濠囨晲婢跺﹨鎽曢梺鍝勬祫缁辨洟鎮块埀顒勬煟鎼搭垳绉靛ù婊呭仦缁傛帡鎮欓鍌滅槇濠电偛鐗嗛悘婵嬫倶閻樼粯鐓忛柛顐ゅ枑閸婃劗鈧鍠栭…宄邦嚕閹绢喗鏅柛鏇ㄥ幗濠㈡垿姊虹拠鎻掑毐缂傚秴妫欑粋宥夊冀椤撶偟锛涢梺瑙勫礃椤曆囧礃閳ь剙顪冮妶鍡樺蔼闁告柨娴风划娆掔疀濞戞瑢鎷洪柣鐘充航閸斿苯鈻嶉幇鐗堢厵闁告垯鍊栫€氾拷

    婵犵數濮烽弫鍛婃叏閻戣棄鏋侀柛娑橈攻閸欏繘鏌i幋婵愭綗闁逞屽墮閸婂湱绮嬮幒鏂哄亾閿濆簼绨介柛鏃撶畱椤啴濡堕崱妤€娼戦梺绋款儐閹瑰洭寮诲☉銏″亜闂佸灝顑呮禒鎾⒑缁洘鏉归柛瀣尭椤啴濡堕崱妤€娼戦梺绋款儐閹稿墽妲愰幘鎰佸悑闁告粌鍟抽崥顐⑽旈悩闈涗粶闁哥噥鍋夐悘鎺楁煟閻樺弶绌块悘蹇旂懅缁綁鎮欓悜妯锋嫼閻熸粎澧楃敮鎺撶娴煎瓨鐓曢柟鎯ь嚟濞叉挳鏌熼钘夊姢閻撱倖銇勮箛鎾村櫝闁归攱妞藉濠氬磼濮樺崬顤€闂佸憡顨嗗ú鐔风暦婵傜ǹ唯闁靛/鍕弰濠电姷鏁告慨鎾晝閵堝洠鍋撳鐓庡籍鐎规洩缍€缁犳盯寮崒婊呮濠电姷鏁告慨鎾磹缂佹ɑ娅犳繛鎴欏灪閻撴洟鎮楅敐鍐ㄥ濠碘€茬矙閺屾洟宕惰椤忣厾鈧鍠曠划娆愪繆濮濆矈妲归梺閫炲苯澧悽顖ょ節瀵鎮㈤崗鐓庣檮婵犮垼娉涢敃銉モ枔婵犳碍鈷戦柛婵嗗閻忛亶鏌涢悩宕囧⒌妤犵偛鍟オ浼村醇濠靛牆骞愰梻浣呵归張顒傜矙閹惧箍浜归悗锝庡枟閻撶喖骞栧ǎ顒€鈧倕岣块幇顓犵闁告瑥顥㈤鍫熷仼婵犻潧鐗忛惌娆撴偣閹帒濡芥繛鍫ョ畺濮婃椽宕滈幓鎺嶇凹濠电偛寮堕悧鐘诲箖閳ユ枼妲堥柕蹇ョ磿閸橀亶鏌h箛鏇炰粶濠⒀傜矙閹瞼鈧綆鍋嗙粻楣冩煕椤愩倕鏋戦柛濠冨姈閹便劍绻濋崟顓炵闂佺懓鍢查幊鎰垝閻㈢鍋撻敐搴濈凹闁伙絼鍗冲缁樻媴鐟欏嫬浠╅梺鍛婃煥椤戝鐣烽敓鐘茬闁肩⒈鍓氬▓楣冩⒑闂堟稓绠為柛濠冩礋瀹曟﹢鍩€椤掆偓椤啴濡堕崱妤€顫囬梺绋块瀹曨剟鎯冮鍕拻闁稿本鐟ч崝宥夋倵缁楁稑鎳愰惌娆撴煙鐎电ǹ袥闁稿鎸搁~婵嬫偂鎼达紕鐫勯柣搴ゎ潐濞叉垿宕¢崘鑼殾闁告鍊i悢鍏尖拹闁归偊鍠氬▔鍧楁⒒閸屾瑧绐旀繛浣冲洦鍋嬮柛鈩冪☉缁犵娀骞栧ǎ顒€鐏柛娆忕箲閵囧嫰骞掗崱妞惧闂備礁鐤囬~澶愬垂閸ф鏄ラ柕澶嗘櫅楠炪垺淇婇悙鎻掆挃闁告垼顫夌换婵嬫偨闂堟刀鐐烘煕閵婏附銇濋柡浣割儔閺屟囨嚒閵堝懍娌繛锝呮搐閿曨亝淇婇崼鏇炲窛妞ゆ柨鍚嬮锟犳⒒娴e懙褰掝敄閸涙潙纾归柛锔诲幗瀹曞弶绻涢幋娆忕仼妤犵偑鍨烘穱濠囶敍濠垫劕娈紒鐐緲缁夊綊寮婚敐鍡樺劅闁靛骏绲介ˉ婵嗩渻閵堝繐顩柡浣筋嚙椤曪絿鎷犲顔兼倯闂佸壊鍋掗崑鍛搭敁閸ヮ剚鈷掑ù锝呮啞閸熺偤鏌熼幖浣虹暫鐎规洜澧楅幆鏃堚€﹂幋鐐存珨闂備焦瀵х换鍌炈囨禒瀣瀬闁糕剝銇滈埀顒佸笒椤繈顢楁繝鍌氼潬闂備焦妞块崢浠嬨€冮崱娆愬床婵炴垯鍨圭粻濠氭煛婢跺鐏╅柛鏂惧嵆濮婅櫣绮欏▎鎯у壉闂佸湱鎳撳ú顓烆嚕婵犳碍鏅查柛娑变簼椤秴鈹戦悙鍙夘棡闁告梹娲滄竟鏇㈠箮閼恒儮鎷洪梺鍛婄箓鐎氼厼锕㈤幍顔剧<閻庯綆鍋勯悘鎾煕閳哄啫浠辨鐐差儔閺佸啴鍩€椤掆偓椤斿繐鈹戦崶銉ょ盎闂佸搫娲ㄩ崑鐐哄闯濞差亝鐓冮悹鍥嚋閸旂喓绱掓潏銊﹀磳鐎规洘甯掗埢搴ㄥ箣濠靛棭鐎村┑锛勫亼閸婃垿宕濆畝鍕疇婵せ鍋撴鐐叉閻f繈宕熼銈忕床闂備胶绮崝娆忈缚瑜忕划濠囨晝閸屾稓鍘甸梺绋跨箺閸嬫劙寮冲鈧弻娑㈠棘鐠恒劎鍔梺璇″枤閸嬨倕鐣疯ぐ鎺濇晝闁绘ǹ浜惄搴ㄦ⒒娴e憡璐¢柛搴涘€濆畷褰掓偨閸撳弶鏅滈梺鍐叉惈閹冲繘宕愰崹顐e弿婵妫楁晶缁樹繆閹绘帞绉洪柡灞炬礋瀹曟儼顦叉い蹇e幘閳ь剚顔栭崰鏇犲垝濞嗘劒绻嗘慨婵嗙焾濡插ジ姊洪棃鈺冪シ闁稿骸纾Σ鎰板箻鐎涙ê顎撶紓浣圭☉椤戝懎鈻撻鐐╂斀闁宠棄妫楁禍婵堢磼鐠囪尙澧曟い鏇稻缁绘繂顫濋鐐扮盎缂備胶鍋撴刊鑺ャ仈閹间礁鐤鹃柨婵嗩槹閸嬧剝绻濇繝鍌氭殶閺佸牓姊虹拠鈥虫灍闁挎洏鍨介獮濠囨偐濞茬粯鏅㈤梺绋挎湰缁絿妲愰弻銉︹拺闁告繂瀚峰Σ鎼佹煟濡も偓鐎氭澘鐣峰┑鍥ㄥ劅闁挎繂娲g粭澶愭⒑缂佹ê濮夐柛搴涘€濋幃鈥斥槈閵忊€斥偓鍫曟煟閹邦垱纭剧悮姘舵⒑閸濄儱校闁挎洏鍨藉濠氬焺閸愨晛顎撻梺鑽ゅ枑濠㈡﹢锝為幒妤佸€甸悷娆忓缁€鍫ユ煕閻樺磭澧甸柕鍡曠椤粓鍩€椤掑嫬绠栭柍鍝勬噺閹偞銇勯幇鈺佲偓婵嬪箯婵犳碍鈷掗柛灞捐壘閳ь剙鍢查湁闁搞儜鍛闂佸壊鐓堥崑鍛村矗韫囨稒鐓欓柟顖涙緲琚氶梺鎶芥敱濮婂鍩€椤掆偓缁犲秹宕曢柆宓ュ洭顢涢悙鎻掔€梺绋跨灱閸嬬偤鎮¢姀鈥茬箚妞ゆ牗绮岄惃鎴犵磼鏉堛劌鍝洪柡灞诲妼閳规垿宕遍埡鍌傦妇绱撴担鎻掍壕闁诲函缍嗛崑浣圭濠婂牊鐓涚€广儱鍟俊鍧楁煃閽樺妲圭紒缁樼洴瀹曞ジ鎮㈤搹鍦帨婵犳鍠栭敃銊モ枍閿濆應妲堥柣銏⑶瑰婵囥亜閺傛儳瀚庨柍褜鍓氶崝鏇⑩€旈崘顔嘉ч幖绮光偓鑼嚬婵犵數鍋犵亸娆撳窗閺嵮呮殾婵炲樊浜滈悞鍨亜閹哄秹妾峰ù婊勭矒閺岀喖宕崟顒夋婵炲瓨绮撶粻鏍ь潖濞差亜绠伴幖娣灮閳规稒绻濈喊妯峰亾閾忣偅鎮欓柛妤呬憾閺岀喖鎮ч崼鐔哄嚒缂備緡鍋勭粔褰掑蓟濞戙埄鏁冮柨婵嗘川閻g厧顪冮妶鍡樺鞍婵$偠妫勯~蹇涙惞閸︻厾锛滃┑鈽嗗灠閹碱偊锝炲畝鍕€垫繛鍫濈仢濞呮﹢鏌涢幘瀵告噯闁诲繐鍟村娲川婵犱胶绻侀梺鍝ュУ瀹€绋跨暦閵忋倕绠瑰ù锝呭帨閹锋椽姊洪崨濠冨鞍鐟滄澘鍟粋宥嗙鐎n偆鍘遍柣搴秵娴滄粓顢旈銏$厵妞ゆ梹鏋婚懓鍧楁煛娴gǹ鏆g€规洘甯掗埥澶婎潩椤掆偓缁犵偤姊绘担绛嬪殭闁告垹鏅槐鐐哄幢濞戞ḿ锛涢梺绯曞墲钃辨繛鍛У閵囧嫰骞掗幋婵冨亾閼姐倕顥氬┑鍌氭啞閻撴洟鎮橀悙鎻掆挃闁宠棄顦辩槐鎺戭渻閿曗偓濞诧箓鎮″▎鎾寸厽闁绘柨鎲$欢鍙夈亜韫囷絽寮柡宀€鍠栭幃鈩冩償閵忥絿顢呴梻浣烘嚀瀵爼骞愰崘鑼殾闁绘柨鍚嬮ˉ鍫熺箾閹寸偟鎳勯柣婵撶節濮婂宕掑顑藉亾閹间礁纾瑰瀣捣閻棗銆掑锝呬壕濡ょ姷鍋為悧鐘汇€侀弴銏犖ч柛灞剧煯婢规洖鈹戦鐭亜鐣烽鍕偍閻庣數纭堕崑鎾舵喆閸曨剛顦ョ紓鍌氱Т閿曨亜顕f繝姘耿婵°倕锕ら幃鎴︽⒑閸涘﹣绶遍柛銊ф櫕濡叉劙鏌嗗鍡欏幗闁硅壈鎻槐鏇㈡偩椤撱垺鐓曢幖娣妺閹查箖鎸婂┑鍠㈠綊宕楅崗鑲╃▏缂佺偓宕樺▔鏇㈠焵椤掆偓缁犲秹宕曢柆宓ュ洦瀵肩€涙ê浜楅梺鍝勬储閸ㄦ椽鎮″☉銏$厱闁靛绲介崝姘攽閿涘嫬甯舵い顓″劵椤т線鏌涢妸銈呭祮婵犫偓娓氣偓濮婅櫣绱掑Ο鎾虫贡缁棃顢氶埀顒勩€侀弮鍫濋唶闁绘棁娅i弳銏ゆ⒒閸屾艾鈧兘鎮為敂閿亾缁楁稑鎳忓畷鏌ユ煕鐏炵虎鍤ゆ繛鎴烆焸閺冨牆宸濇い鎾跺Т楠炴帡姊绘担鍛婃儓婵炲眰鍨藉畷鐟懊洪鍛簵闂佸憡鍔︽禍婵嬪窗閹邦厾绡€濠电姴鍊绘晶鏇犵磼閳ь剟宕奸悢绋垮伎濠碘槅鍨辩€笛呮兜妤e啯鐓㈤柛鎰典簻閺嬫盯鏌$仦鐐缂佺粯绋栭ˇ鏌ユ倵濮樺崬鍘寸€规洘鍨挎俊鎼佸煛閸屾瀚肩紓鍌氬€烽悞锕傛晪婵犳鍠栧ú锕傚Φ閸曨垰鍗抽柕濞垮劚缁秹姊虹化鏇熸澓闁搞劏妫勯锝夊箻椤旂⒈娼婇梺鐐藉劜閺嬪ジ宕戦幘缁樺仺闁告稑锕﹂崣鍡椻攽閻樼粯娑ф俊顐n殜閸┾偓妞ゆ帒鍊归崵鈧梺瀹狀嚙缁夌懓鐣烽崼鏇炍╅柨婵嗗閻╁酣姊绘繝搴′簻婵炶濡囩划娆撳箛閺夎法鐤呮俊銈忕到閸燁垶鎮″☉銏″€堕柣鎰版涧娴滃墽绱掗埀顒傗偓锝庡厴閸嬫挾鎲撮崟顒傤槹婵炲瓨绮岄悥濂稿Υ娴e壊娼ㄩ柍褜鍓熼獮鍐閿涘嫰妾繝銏f硾椤﹁鲸寰勯敓锟�

    重磅专题
    往期文章
    最新文章