view model 中的MapToBoview help是什么意思思

3492人阅读
首先介绍ModelMap和ModelAndView的作用
ModelMap对象主要用于传递控制方法处理数据到结果页面,也就是说我们把结果页面上需要的数据放到ModelMap对象中即可,他的作用类似于request对象的setAttribute方法的作用,用来在一个请求过程中传递处理的数据。通过以下方法向页面传递参数:
addAttribute(String key,Object value);
在页面上可以通过el变量方式$key或者bboss的一系列获取并展示modelmap中的数据。
modelmap本身不能设置页面跳转的url地址别名或者物理跳转地址,那么我们可以通过控制器方法的返回值来设置跳转url地址别名或者物理跳转地址。
ModelAndView
ModelAndView对象有两个作用:
作用一 设置转向地址,如下所示(这也是ModelAndView和ModelMap的主要区别)
ModelAndView view = new ModelAndView(&path:ok&);
作用二 用于传递控制方法处理结果数据到结果页面,也就是说我们把需要在结果页面上需要的数据放到ModelAndView对象中即可,他的作用类似于request对象的setAttribute方法的作用,用来在一个请求过程中传递处理的数据。通过以下方法向页面传递参数:
addObject(String key,Object value);
在页面上可以通过el变量方式$key或者bboss的一系列获取并展示ModelAndView中的数据。
作用介绍完了后,接下来介绍使用方法
ModelMap的实例是由bboss mvc框架自动创建并作为控制器方法参数传入,用户无需自己创建。
Java代码 &
public&String&xxxxmethod(String&someparam,ModelMap&model) &&{ &&&&&&&&&&&&&&&&&&&&&&&model.addAttribute(&key&,someparam); &&&&&&&...... &&&&&&&
&&&&&&&&return&&path:handleok&; &&}&&
Java代码 &
public&String&xxxxmethod(String&someparam,ModelMap&model)&&{&&&&&&&&&&&&&&&&&&&&&&&model.addAttribute(&key&,someparam);&&&&&&&......&&&&&&&&&&&&&&&return&&path:handleok&;&&}&&
ModelAndView
ModelAndView的实例是由用户手动创建的,这也是和ModelMap的一个区别。
Java代码 &
public&ModelAndView&xxxxmethod(String&someparam) &&{ &&&&&&&&&&&&&&&&&&&&&&&ModelAndView&view&=&new&ModelAndView(&path:handleok&); &&&&&&&&&&&&&&&&view.addObject(&key&,someparam); &&&&&&&...... &&&&&&&&&&&&&&&return& &&}&
& & public ModelAndView view(HttpServletRequest request, HttpServletResponse response){
& & & & Integer memberId = Integer.parseInt(request.getParameter(&memberId&));
& & & & Member member = memberService.get(memberId);
& & & & return new ModelAndView(&view&).addObject(&member&, member);
& & public ModelAndView delete(HttpServletRequest request, HttpServletResponse response) throws ServletRequestBindingException{
& & & & Integer memberId = ServletRequestUtils.getIntParameter(request, &memberId&);
& & & & memberService.delete(memberId);
& & & & return new ModelAndView(&redirect:/member/list.html&);
??? ? ? ??? ??? ? ?? ??? ????? ??? ???? ?????.
boolean, float, double, int, long, String ??으? ?? ? ? ?으? ? ???? ??([]) ??으?? ?? ????? ?? ?? ? ????. ? ???????
String ?? ??? ???? ?? API? ???...??? ??? ??? ???? ????.
static String & & getStringParameter(ServletRequest request, String name)
?? ??? API?
static String & & getStringParameter(ServletRequest request, String name, String encoding)
??? ??? ?? ??? ? ???..
String koreanName = ServletRequestUtils.getIntParameter(request, &name&, &UTF-8&)
??? ??? ???으?? ??? ?? ?? ???. ??? ? ???? ?? ? ??;;;
String name = new String(request.getParameter(&name&).getBytes(&8859_1&), &UTF-8&);
?? ??? ??? ??? ?? ?? ? Util ??? ??? ???? ???? ???.
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:439360次
积分:7002
积分:7002
排名:第1354名
原创:248篇
转载:317篇
评论:52条
(9)(3)(9)(16)(30)(2)(44)(12)(11)(15)(57)(13)(14)(8)(11)(29)(18)(6)(11)(13)(22)(16)(29)(21)(11)(14)(3)(6)(4)(13)(2)(4)(3)(2)(2)(2)(6)(5)(10)(9)(8)(6)(7)(11)(6)(1)(4)(1)(2)(4)Robotlegs2中文教程-1使用MVCBundle | zrong's blog
› Robotlegs2中文教程-1使用MVCBundle
本站文章除注明转载外,均为本站原创或者翻译。
本站文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处,尊重我的劳动,也尊重你的智商;
本站部分原创和翻译文章提供markdown格式源码,欢迎使用进行转载;
本文标题:Robotlegs2中文教程-1使用MVCBundle
本文链接:
本系列全部文章:
本章使用Robotlegs2自带的MVCBundle实现一个简单的MVC实例。
Robotlegs2在架构设计上,框架仅实现了生命周期管理、Logger、消息调度、插件管理器、配置管理器等核心功能,其他功能全部使用插件实现。而MVCBundle,就是Robotlegs2提供的一个插件和配置集合,这个集合包含所有MVC需要的插件和功能。
本章不会研究Robotlegs2在结构上的设计,而是从最终用户的角度来使用MVCBundle。若希望了解Robotlegs2的架构,请关注本系列后续文章。
本章也不会详细介绍MVCBundle的所有用法,那样会导致本文篇幅过长。下一章会进行详细介绍。
Timer-MVCBundle-Sample概述
Timer-MVCBundle-Sample是本章的实例名称。这个实例实现了一个简单的定时器。看看定时器的3个状态:
初始状态,设置时、分,类名为TimerSetView。按Start按钮开始倒计时。
倒计时状态,类名为TimerActionView。按Cancel按钮取消倒计时,回到初始状态。
倒计时时间到,类名为AlertView。按Dismiss按钮回到初始状态。
本项目依赖
组件库和 。
这里简单介绍一下项目中的包分类,以及各个部分的作用。介绍按照MVC分块进行。如果你性急,也可以跳过这部分直接看后面的项目详解。
View + Mediator
刚才看到的后缀为View的类,我叫它们“视图类”,所有的视图类,都位于 view 包中,并实现 ITimerView 接口。 ITimerView 中并没有包含任何方法签名。实现这个接口,是为了方便进行类型匹配。
视图类用于我们能看到的定时器的3个状态,每个状态对应一个视图。定时器运行的过程中所显示的状态,在这3个视图之间切换。上节 Timer-MCBundle-Sample 已经介绍了这3个状态以及对应的类名。
视图类都是显示对象的子类,3个视图也就是3个显示对象。在一个视图显示的时候,它会被加到舞台上,其他的视图则移出舞台。
在这个项目中,我使用了组件。视图类继承其中的VBox或者HBox。3个视图类如下图:
每个视图类都有一个带有Mediator后缀的类,这是视图类的中介类。中介类负责管理视图事件,接收和传递系统事件等等。所有的中介类都继承 Robotlegs2 提供的 Mediator 类。如下图:
此项目有2个Model:TimerModel 和 ViewModel。
TimerModel 实现 ITimerModel 接口。由于项目过于简单,ITimerModel 中不包含任何需要具体实现的方法,但是这种编程习惯是Robotlegs所推荐的。它既方便了在Robotlegs中替换Model(例如你可以在开发和发布的时候使用不同的Model),也符合中的针对接口编程的OO原则。
TimerModel 中包含了一个 flash.util.Timer 实例,用它来实现定时器的核心功能。同时它还会发布定时器 工作的事件,并暴露一些方法来停止和启动定时器。
ViewModel 保存上面提到的3个视图类的实例,以此实现对视图实例的重用。同时它还提供一个 getView() 方法根据类或者类名来获取一个新的/重用的实例。你可以把 ViewModel 理解成一个对象池,虽然它并不是对象池。如下图:
Command + Event
此项目有3个Commnd: ChangeStateCmd 、 TimerStartCmd 和 TimerStopCmd 。
ChangeStateCmd 负责切换视图状态。它收到切换的命令,然后移除掉当前舞台上的视图实例,再从 ViewModel 中获取一个视图实例,将它加到舞台上。
TimerStartCmd 负责用户主动开始定时器运行的事件。它只是简单的更新 TimerModel 中的定时器流逝时间,然后开启定时器。
TimerStopCmd 负责用户主动停止定时器运行的事件。它停止 TimerModel 中的定时器,然后将视图切换到 TimerSetView。
TEvent 是此项目中使用的系统事件类型。上面的几个Command均使用这个类型代表的事件来触发。如下图:
初始化Robotlegs2
先来看看主类 Robotlegs2TimerExample 的全部内容(省略了package和import):
[SWF(width=200,height=200)]
public class Robotlegs2TimerExample extends Sprite
public function Robotlegs2TimerExample()
Style.embedFonts = true;
Style.fontSize = 8;
Component.initStage(this.stage);
private var _context:IContext;
private function init():void
_context = new Context()
.install(MVCSBundle)
.configure(AppConfig)
.configure(new ContextView(this));
_context.logLevel = LogLevel.DEBUG;
trace(&init done&);
//这里通过内置的事件框架来实现View的启动
(_context.injector.getInstance(IEventDispatcher) as IEventDispatcher).dispatchEvent(new TEvent(TEvent.CHANGE_STATE, TimerSetView));
Style和Component都是
中的类,具体用法可参考该。需要注意的是,如果需要显示中文,那么需要将 Style.embedFonts 设置为 false,具体原因可参考 。
让我们来看 init 方法的具体内容。Context 类是Robotlegs2初始化的核心。在本项目的初始化当中,我们使用了 Context 的 install 和 configuare 方法。这两个方法都会返回 Context 自身,因此我们可以进行链式调用。
链式调用是JAVA和JavaScript中常用的调用方式,能减少代码量,让代码看起来更干净。当然,如果你不愿意用它,依然可以使用旧的方式。例如,上面的链式调用可以改成这样:
_context = new Context();
_content.install(MVCSBundle);
_content.configure(AppConfig);
_content.configure(new ContextView(this));
install() 的作用是安装一个 IExtension 或者 IBundle。前者是一个扩展,后者是一个/一堆扩展和配置的集合。Robotlegs2根据我们的调用对 IExtension 和 IBundle 进行按需安装,这样可以节省资源。install() 支持无限参数,如果有多个 IBundle,可以使用链式调用进行单个安装,也可以使用一个 install() 多个参数进行安装。
为了描述的统一性和准确性,后文将不对 IExtension 和 IBundle 进行翻译,而直接使用接口名。
MVCBundle 是一个包含许多 IExtension 的 IBundle,它包含了MVC框架中的所有 IExtension。除此以外,它还包含一些Logger系统等核心功能。在这个项目中,我们不需要其他的 IExtension ,一包足矣。
configuare() 的作用是对项目进行配置,通常将各种映射放在这里。与 install() 只能接收 IBundle 和 IExtension 不同, configuare() 可以接受任何类型的对象作为参数。同时,它也接受多个参数。例如上面的 configuare() 相关代码可以写成这样:
_content.configure(AppConfig, new ContextView(this));
需要注意的是,对于ContextView的配置,必须放在所有配置的最后。具体原因,请关注本系列后续文章。
ContextView 是Robotlegs2提供的类,它没有实现任何接口,只是用于保存根显示对象的引用。我们可以将它注入到需要的地方,以方便访问根显示对象。
init() 的最后一句直接发布 TEvent.CHANGE_STATE 事件,ChangeStateCmd 会处理这个事件,它获取 TimerSetView 的实例,将其添加到舞台上。
注意这一句的作用:
(_context.injector.getInstance(IEventDispatcher) as IEventDispatcher)....
最外层的括号中的内容,是为了获取一个 IEventDispatcher 的实例。IEventDispatcher 是AS3原生的用于发布事件的接口。 Robotlegs2中使用它作为 MVCBundle 的事件核心。
它以单例的形式存在,我们使用 injector.getInstance 方法,就可以得到这个单例。
injector是SwiftSuspenders提供的注入器。Robotlegs2使用这个注入器来实现注入,我们也可以使用它来获取Robotlegs2中注册过的各种资源。在 Context 中包含一个它的引用。我们既可以使用 _context.injector 的方式获取它,也可以使用注入的方式获取它。
例如,我们要得到 TimerModel 的单例,可以这样做(注意我使用的是接口):
public var injector:Injector;
//获取到ITimerModel的单例,调用它的start方法让计时器开始运行
(injector.getInstance(ITimerModel) as ITimerModel).start();
那么,既然 ITimerModel 已经在Robotlegs2中注册(这个注册是在AppConfig中完成的,后面会讲到),更简单的方法是这样的:
public var timerModel:ITimerModel;
timerModel.start();
可是,我们为什么不在 Robotlegs2TimerSample 中直接注入 IEventDispatcher ,而要用 injector 来获取呢?例如像这样:
public var eventDispatcher:IEventDispatcher;
private function init():void
................
eventDispatcher.dispatchEvent(new TEvent(TEvent.CHANGE_STATE, TimerSetView));
这样的代码会出现运行时错误,原因是 eventDispatcher 的值为 null 。
这是因为在默认情况下, 只有被注入器初始化的类,才能被注入 。主类 Robotlegs2TimerSample 是无法被注入器初始化的,因此在主类中进行注入,在默认情况下是不会成功的。
让我们看看 AppConfig 的内容(同样省略了package和import)。
public class AppConfig implements IConfig
public var injector:Injector;
public var mediatorMap:IMediatorMap;
public var commandMap:IEventCommandMap;
public var logger:ILogger;
public function configure():void
mediators();
commands();
logger.info(&logger in AppConfig&);
private function models():void
injector.map(ITimerModel).toSingleton(TimerModel);
injector.map(ViewModel).asSingleton();
private function mediators():void
mediatorMap.map(TimerSetView).toMediator(TimerSetMediator);
mediatorMap.map(TimerActionView).toMediator(TimerActionMediator);
mediatorMap.map(AlertView).toMediator(AlertViewMediator);
private function commands():void
commandMap.map(TEvent.TIMER_START, TEvent).toCommand(TimerStartCmd);
commandMap.map(TEvent.TIMER_STOP, TEvent).toCommand(TimerStopCmd);
commandMap.map(TEvent.CHANGE_STATE, TEvent).toCommand(ChangeStateCmd);
AppConfig 实现了 IConfig 接口。Robotlegs2在对该接口进行配置的时候,会自动调用它的 configuare 方法进行注册。
我们来仔细看看这个类中注入的4个对象。
injector上面讲过一些,这里继续。使用它,可以进行单例映射。toSingleton() 方法和 asSingleton() 方法的不同之处在于,前者针对接口映射,我们可以方便在该方法的参数中替换具体实现;后者针对具体实现映射,它不能被替换。
如果你用过Robotlegs1,你会发现injector的映射语法改变了不少。它抛弃了原来使用参数来映射的方式,改用链式调用,在我看来,这样的改动让语法更加简洁,且容易记忆。
本系列文章在必要的时候会对Robotlegs1和2进行比较,这是为了方便使用过Robotlegs1的读者进行更深入的理解。如果你以前没有使用过Robotlegs1,可以跳过这些内容。
例如,在Robotlegs1中,要实现本例中的两个单例映射,需要这样调用:
injector.mapSingletonOf(ITimerModel, TimerModel);
injector.mapSingleton(ViewModel);
mediatorMap用来实现视图类和Mediator的映射。以 mediatorMap.map(TimerSetView).toMediator(TimerSetMediator) 为例,这句实现了在 TimerSetView 被添加到舞台的时候, TimerSetMediator 会自动创建并完成初始化,同时进行需要的注入。
在Robotlegs1中,mediatorMap的调用方式也做了与injector类似的修改。这并不奇怪,因为mediatorMap的映射就是使用injector实现的。
例如,在Robotlegs1中,实现 TimerSetView 与 TimerSetMediator 的映射,需要这样调用:
mediatorMap.mapView(TimerActionView, TimerActionMediator);
commandMap用来实现事件与Command的映射。以 commandMap.map(TEvent.TIMER_START, TEvent).toCommand(TimerStartCmd) 为例,这句实现了在 TEvent.TIMER_START 事件发生的时候, TimerStartCmd 被自动创建,同时进行需要的注入,然后执行其 execute 方法。
在Robotlegs1中,要实现 TEvent.TIMER_START 与 TimerStartCmd 的映射,需要这样调用:
commandMap.mapEvent(TEvent.TIMER_START, TimerStartCmd);
logger提供一个全局的日志分析器,默认使用tarce实现。logger不但可以像上面的代码一样,直接输出文字,也可以方便的实现文本替换。例如:
logger.info(&logger in {0}, {1}&, [this, &done&]);
//输出内容
//638 INFO Context-0-9f [class AppConfig] logger in [object AppConfig], done
AppConfig实际上是分担了一部分Context的功能。我们可以把不同模块,不同需求的Config进行分离,让程序之间的耦合更加松散。
在Robotlegs1中,我们一般把映射放在 Context 的 startup 方法中,这样在项目逐渐庞大的时候,Context就无可避免的庞大起来:
..........
//========================================
// 注入Model和Service
//========================================
injector.mapSingletonOf(SocketServiceBase, SocketService);
injector.mapSingleton(SocketDataDispatcherModel);
injector.mapSingleton(StateModel);
injector.mapSingleton(HTTPService2);
injector.mapSingleton(UpdateService);
//----界面信号
signalCommandMap.mapSignalClass(FightEndSign, FightEndCmd);
signalCommandMap.mapSignalClass(GuideAniEndSign, GuideAniEndCmd);
signalCommandMap.mapSignalClass(GuideHelpSign, GuideHelpCmd);
signalCommandMap.mapSignalClass(GuideCheckOpen8Sign, GuideCheckOpen8Cmd);
signalCommandMap.mapSignalClass(CheckMausoleumSign, CheckMausoleumCmd);
signalCommandMap.mapSignalClass(ExitMausoleumSign, ExitMausoleumCmd);
//----其他不便分类的信号
signalCommandMap.mapSignalClass(NecessarySocketInitDataDoneSign, NecessarySocketInitDataDoneCmd);
signalCommandMap.mapSignalClass(SetDefaultPreferenceSign, SetDefaultPreferenceCmd);
signalCommandMap.mapSignalClass(ActiveSign, ActiveCmd);
signalCommandMap.mapSignalClass(ChargeInWebSign, ChargeInWebCmd);
//========================================
// 所有的子滑动界面注册
//========================================
//LoginModuleContent和RegisterModuleContent与接入商相关,因此在子Context类中注册
mediatorMap.mapView(FightDeployModuleContent, FightDeployModuleContentMediator, null, false, false);
mediatorMap.mapView(FightSpyModuleContent, FightSpyModuleContentMediator, null, false, false);
mediatorMap.mapView(ChooseServerModuleContent, ChooseServerModuleContentMediator, null, false, false);
mediatorMap.mapView(AccelerateCoolingModule,AccelerateCoolingModuleMediator,null,false,false);
1 这段代码是项目的界面入口
(_context.injector.getInstance(IEventDispatcher) as IEventDispatcher).dispatchEvent(new TEvent(TEvent.CHANGE_STATE, TimerSetView));
IEventDispatcher 发布了一个事件 TEvent.CHANGE_STATE,同时传递了一个视图类 TimerSetView。由于我们前面已经将该事件映射到了 ChangeStateCmd,因此,ChangeStateCmd 中的 execute() 方法被执行。
2 ChangeStateCmd做了什么?
让我们看看 ChangeStateCmd 的全部内容:
public class ChangeStateCmd extends Command
public var evt:TEvent;
public var logger:ILogger;
public var contextView:ContextView;
public var viewModel:ViewModel;
override public function execute():void
logger.debug(evt.info);
logger.debug(contextView.view.numChildren);
if(contextView.view.numChildren & 0)
var __currentView:ITimerView = contextView.view.getChildAt(0) as ITimerView;
if(__currentView)
contextView.view.removeChild(__currentView as DisplayObject);
var __newView:DisplayObject = viewModel.getView(evt.info) as DisplayObject;
center(__newView);
contextView.view.addChild(__newView);
logger.debug(&get view:{0}&, [__newView]);
private function center($view:DisplayObject):void
$view.x = (contextView.view.stage.stageWidth - $view.width) / 2;
$view.y = (contextView.view.stage.stageHeight - $view.height) / 2;
在 ChangeStateCmd 中,我们需要得到 TEvent 传来的视图类,使用其创建视图实例,然后将实例添加到舞台上。
注入的 evt 实例,也就是前面 TEvent.CHANGE_STATE 事件传来的事件实例。在这次的调用这,< 的值,就是 TimerSetView。
execute() 方法先移除已存在的视图实例,然后根据 < 的值获取一个新的实例,并将其添加到舞台。
所有的视图类,都实现了 ITimerView 接口。因此在这里可以通过判断 ITimerView 的实现情况,来了解实例的创建是否成功。
创建实例的工作在 ViewModel 中完成,可查看源码了解,此处不深入讲解。
TimerSetView 视图实例被添加到舞台的时候,TimerSetViewMediator 会自动创建。
3 TimerSetViewMediator 做了什么?
让我们来看看 TimerSetViewMediator 的全部内容:
public class TimerSetMediator extends Mediator
public var logger:ILogger;
public var v:TimerSetView;
public function TimerSetMediator()
override public function initialize():void
super.initialize();
logger.info(&initialize&);
v.startBtn.addEventListener(MouseEvent.CLICK, handler_start);
override public function destroy():void
v.startBtn.removeEventListener(MouseEvent.CLICK, handler_start);
super.destroy();
logger.info(&destory&);
private function handler_start(e:Event):void
logger.debug(&click&);
eventDispatcher.dispatchEvent(new TEvent(TEvent.TIMER_START, {minute:v.minute, second:v.second}));
eventDispatcher.dispatchEvent(new TEvent(TEvent.CHANGE_STATE, TimerActionView));
v 被自动注入,它就是刚才我们创建的 TimerSetView 视图实例。
initialize() 方法在注入完成之后自动执行。因此,该方法适合进行 v 的视图侦听器。在本类中,加入了用户按下“Start”按钮时的鼠标事件侦听。
TimerSetView 的实例从舞台移除的时候, TimerSetViewMediator 被销毁。 destroy() 方法在此时执行。我们在这里移除“Start”按钮的鼠标事件侦听。
在单击“Start”按钮的时候,我们发布了两个系统事件 —— 1. TEvent.TIMER_START,并传递当前选择的分、秒;2. TEvent.CHANGE_STATE,切换到 TimerActionView 视图。
由于前面我们已经将 TEVent.TIMER_START 映射到了 TimerStartCmd ,因此 TimerStartCmd 中的 execute() 方法将被执行。
4 启动计时器
让我们来看看 TimerStartCmd 的全部内容:
public class TimerStartCmd extends Command
public var timerModel:ITimerModel;
public var evt:TEvent;
override public function execute():void
timerModel.minute = evt.info.minute;
timerModel.second = evt.info.second;
timerModel.start();
在这里,我们更新了 TimerModel 中保存的分、秒,然后启动了计时器。
到此,我已经把主要流程讲完。至于后面的计时器时间到,或者中断计时器等操作,和前面的流程类似。大家可以继续在 TimerModel 和 TimerActionMediator 中找到它们的具体实现。
本章使用一个简单的计时器例子,讲解了Robotlegs2中的MVCBundle的使用。拥有Robotlegs1使用经验的同学,现在应该已经可以转移到Robotlegs2上来了。
即使你从没有用过Robotlegs,那么也可以从本文开始,从头学习Robotlegs2。
下一章,我们将深入MVCBundle中,分析其中的Extension组成,并试图抛弃MVCBundle,使用更底层的方式来重新构架我们的计时器范例。
标签: , , ,
- 109,981 views - 43,939 views - 37,796 views - 34,372 views - 34,172 views - 29,790 views - 24,951 views - 21,086 views - 20,448 views - 19,751 views
2015年七月 &(4)
2015年六月 &(4)
2015年五月 &(4)
2015年四月 &(3)
2015年三月 &(3)
2015年二月 &(2)
2015年一月 &(6)
2014年十二月 &(6)
2014年十一月 &(11)
2014年十月 &(5)
2014年九月 &(4)
2014年八月 &(4)
2014年七月 &(5)
2014年六月 &(3)
2014年五月 &(2)
2014年四月 &(11)
2014年三月 &(7)
2014年二月 &(5)
2014年一月 &(5)
2013年十二月 &(7)
2013年十一月 &(6)
2013年十月 &(7)
2013年九月 &(8)
2013年八月 &(7)
2013年六月 &(3)
2013年五月 &(11)
2013年四月 &(5)
2013年三月 &(3)
2013年二月 &(4)
2013年一月 &(12)
2012年十二月 &(11)
2012年十一月 &(9)
2012年十月 &(6)
2012年九月 &(6)
2012年八月 &(13)
2012年七月 &(5)
2012年六月 &(2)
2012年五月 &(3)
2012年四月 &(11)
2012年三月 &(12)
2012年二月 &(15)
2012年一月 &(4)
2011年十二月 &(7)
2011年十一月 &(9)
2011年十月 &(3)
2011年九月 &(9)
2011年八月 &(9)
2011年七月 &(10)
2011年六月 &(9)
2011年五月 &(5)
2011年四月 &(7)
2011年三月 &(3)
2011年二月 &(15)
2011年一月 &(3)
2010年十二月 &(14)
2010年十一月 &(6)
2010年十月 &(2)
2010年九月 &(7)
2010年八月 &(16)
2010年七月 &(11)
2010年六月 &(4)
2010年五月 &(15)
2010年四月 &(2)
2010年三月 &(1)
2010年二月 &(1)
2010年一月 &(4)
2009年十二月 &(7)
2009年十一月 &(3)
2009年十月 &(1)
2009年九月 &(3)
2009年八月 &(5)
2009年七月 &(1)
2009年六月 &(1)
2009年三月 &(10)
2009年二月 &(4)
2008年十一月 &(2)
2008年十月 &(1)
2008年八月 &(4)
2008年七月 &(4)
2008年六月 &(4)
2008年五月 &(1)
2008年四月 &(4)
2008年三月 &(7)
2008年二月 &(5)
2008年一月 &(1)
2007年十二月 &(6)
2007年十一月 &(7)
2007年十月 &(1)
2007年九月 &(4)
2007年八月 &(6)
2007年七月 &(6)
2007年六月 &(4)
2007年五月 &(4)
2007年三月 &(3)
2007年二月 &(10)
2007年一月 &(12)
2006年十二月 &(9)
2006年十一月 &(4)
2006年十月 &(11)
2006年九月 &(10)
2006年八月 &(9)
2006年七月 &(9)
2006年六月 &(11)
2006年五月 &(15)
2006年四月 &(6)
2006年三月 &(16)
2006年二月 &(15)
2006年一月 &(4)
2005年十一月 &(14)
2005年十月 &(10)
2005年九月 &(7)
2005年八月 &(2)
2005年七月 &(10)
2005年六月 &(5)
2005年五月 &(11)
2005年四月 &(3)
静态文件存储由提供

我要回帖

更多关于 model是什么牌子 的文章

 

随机推荐