struts2源代码分析(精选8篇)
读者如果曾经学习过Struts1.x或者有过Struts1.x的开发经验,那么千万不要想当然地以为这一章可以跳过。实际上Struts1.x与Struts2并无我们想象的血缘关系。虽然Struts2的开发小组极力保留Struts1.x的习惯,但因为Struts2的核心设计完全改变,从思想到设计到工作流程,都有了很大的不同。
Struts2是Struts社区和WebWork社区的共同成果,我们甚至可以说,Struts2是WebWork的升级版,他采用的正是WebWork的核心,所以,Struts2并不是一个不成熟的产品,相反,构建在WebWork基础之上的Struts2是一个运行稳定、性能优异、设计成熟的WEB框架。
本章主要对Struts的源代码进行分析,因为Struts2与WebWork的关系如此密不可分,因此,读者需要下载xwork的源代码,访问http://文件,则通过过滤器链继续往下传送,直到到达请求的资源为止。
如果getMapping()方法返回有效的ActionMapping对象,则被认为正在请求某个Action,将调用Dispatcher.serviceAction(request, response, servletContext, mapping)方法,该方法是处理Action的关键所在。上述过程的源代码如清单15所示。
代码清单15:FilterDispatcher.doFilter()方法
publicvoid doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {
HttpServletRequest request =(HttpServletRequest)req;
HttpServletResponse response =(HttpServletResponse)res;
ServletContext servletContext = getServletContext();
String timerKey = “FilterDispatcher_doFilter: ”;
try {
UtilTimerStack.push(timerKey);
request = prepareDispatcherAndWrapRequest(request, response);//重新包装request
ActionMapping mapping;
try {
mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());//得到存储Action信息的ActionMapping对象
} catch(Exception ex){
……(省略部分代码)
return;
}
if(mapping == null){//如果mapping为null,则认为不是请求Action资源
String resourcePath = RequestUtils.getServletPath(request);
if(“".equals(resourcePath)&& null!= request.getPathInfo()){
resourcePath = request.getPathInfo();
}
{
ngth());
//如果请求的资源以/struts开头,则当作静态资源处理
if(serveStatic && resourcePath.startsWith(”/struts“))
String name = resourcePath.substring(”/struts“.le
findStaticResource(name, request, response);} else {
//否则,过滤器链继续往下传递
chain.doFilter(request, response);}
// The framework did its job here
return;
}
//如果请求的资源是Action,则调用serviceAction方法。
dispatcher.serviceAction(request, response, servletContext, mapping);
} finally {
try {
ActionContextCleanUp.cleanUp(req);
}
} finally {
UtilTimerStack.pop(timerKey);
} }
这段代码的活动图如图18所示:
(图18)
在Dispatcher.serviceAction()方法中,先加载Struts2的配置文件,如果没有人为配置,则默认加载struts-default.xml、struts-plugin.xml和struts.xml,并且将配置信息保存在形如com.opensymphony.xwork2.config.entities.XxxxConfig的类中。
类com.opensymphony.xwork2.config.providers.XmlConfigurationProvider负责配置文件的读取和解析,addAction()方法负责读取标签,并将数据保存在ActionConfig中;addResultTypes()方法负责将
代码清单16:XmlConfigurationProvider.addPackage()方法
protected PackageConfig addPackage(Element packageElement)throws ConfigurationException {
PackageConfig newPackage = buildPackageContext(packageElement);
age
if(newPackage.isNeedsRefresh()){
return newPackage;} if(LOG.isDebugEnabled()){
LOG.debug(”Loaded “ + newPackage);} // add result types(and default result)to this package addResultTypes(newPackage, packageElement);// load the interceptors and interceptor stacks for this packloadInterceptors(newPackage, packageElement);// load the default interceptor reference for this package loadDefaultInterceptorRef(newPackage, packageElement);// load the default class ref for this package loadDefaultClassRef(newPackage, packageElement);// load the global result list for this package loadGlobalResults(newPackage, packageElement);// load the global exception handler list for this package
loadGlobalExceptionMappings(newPackage, packageElement);
// get actions
NodeList actionList = packageElement.getElementsByTagName(”action“);
for(int i = 0;i < actionList.getLength();i++){
Element actionElement =(Element)actionList.item(i);
addAction(actionElement, newPackage);
}
// load the default action reference for this package
loadDefaultActionRef(newPackage, packageElement);
configuration.addPackageConfig(newPackage.getName(), newPackage);
return newPackage;
}
活动图如图19所示:
(图19)
配置信息加载完成后,创建一个Action的代理对象——ActionProxy引用,实际上对Action的调用正是通过ActionProxy实现的,而ActionProxy又由ActionProxyFactory创建,ActionProxyFactory是创建ActionProxy的工厂。
注:ActionProxy和ActionProxyFactory都是接口,他们的默认实现类分别是DefaultActionProxy和DefaultActionProxyFactory,位于com.opensymphony.xwork2包下。
在这里,我们绝对有必要介绍一下com.opensymphony.xwork2.DefaultActionInvocation类,该类是对ActionInvocation接口的默认实现,负责Action和截拦器的执行。
在DefaultActionInvocation类中,定义了invoke()方法,该方法实现了截拦器的递归调用和执行Action的execute()方法。其中,递归调用截拦器的代码如清单17所示:
代码清单17:调用截拦器,DefaultActionInvocation.invoke()方法的部分代码
if(interceptors.hasNext()){
//从截拦器集合中取出当前的截拦器
final InterceptorMapping interceptor =(InterceptorMapping)interceptors.next();
UtilTimerStack.profile(”interceptor: “+interceptor.getName(),new UtilTimerStack.ProfilingBlock
public String doProfiling()throws Exception {
//执行截拦器(Interceptor)接口中定义的intercept方法
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
returnnull;
}
});
}
从代码中似乎看不到截拦器的递归调用,其实是否递归完全取决于程序员对程序的控制,先来看一下Interceptor接口的定义:
代码清单18:Interceptor.java publicinterface Interceptor extends Serializable {
void destroy();
void init();
String intercept(ActionInvocation invocation)throws Exception;}
所有的截拦器必须实现intercept方法,而该方法的参数恰恰又是ActionInvocation,所以,如果在intercept方法中调用invocation.invoke(),代码清单17会再次执行,从Action的Intercepor列表中找到下一个截拦器,依此递归。下面是一个自定义截拦器示例:
代码清单19:CustomIntercepter.java publicclass CustomIntercepter extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation actionInvocation)throws Exception
} { actionInvocation.invoke();return”李赞红“;}
截拦器的调用活动图如图20所示:
(图20)
如果截拦器全部执行完毕,则调用invokeActionOnly()方法执行Action,invokeActionOnly()方法基本没做什么工作,只调用了invokeAction()方法。
为了执行Action,必须先创建该对象,该工作在DefaultActionInvocation的构造方法中调用init()方法早早完成。调用过程是:DefaultActionInvocation()->init()->createAction()。创建Action的代码如下:
代码清单20:DefaultActionInvocation.createAction()方法
protectedvoid createAction(Map contextMap){
try {
action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);
} catch(InstantiationException e){
……异常代码省略
}
}
Action创建好后,轮到invokeAction()大显身手了,该方法比较长,但关键语句实在很少,用心点看不会很难。
代码清单20:DefaultActionInvocation.invokeAction()方法
protected String invokeAction(Object action, ActionConfig actionConfig)throws Exception {
//获取Action中定义的execute()方法名称,实际上该方法是可以随便定义的
String methodName = proxy.getMethod();
String timerKey = ”invokeAction: “+proxy.getActionName();
try {
UtilTimerStack.push(timerKey);
Method method;
try {
//将方法名转化成Method对象
method = getAction().getClass().getMethod(methodName, new Class[0]);
} catch(NoSuchMethodException e){
// hmm--OK, try doXxx instead
try {
//如果Method出错,则尝试在方法名前加do,再转成Method对象
String altMethodName = ”do“ + methodName.substring(0, 1).toUpperCase()+ methodName.substring(1);
method = getAction().getClass().getMethod(altMethodName, new Class[0]);
} catch(NoSuchMethodException e1){
// throw the original one
throw e;
}
}
//执行方法
[0]);
}
Object methodResult = method.invoke(action, new Object
//处理跳转
if(methodResult instanceof Result){
this.result =(Result)methodResult;
returnnull;
} else {
return(String)methodResult;
} } catch(NoSuchMethodException e){
……省略异常代码 } finally {
UtilTimerStack.pop(timerKey);}
刚才使用了一段插述,我们继续回到ActionProxy类。
我们说Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法。归根到底,最后调用的是DefaultActionInvocation.invokeAction()方法。
以下是调用关系图:
其中:
Ø
ActionProxy:管理Action的生命周期,它是设置和执行Action的起始点。
Ø
ActionInvocation:在ActionProxy层之下,它表示了Action的执行状态。它持有Action实例和所有的Interceptor
以下是serviceAction()方法的定义:
代码清单21:Dispatcher.serviceAction()方法
publicvoid serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,ActionMapping mapping)throws ServletException {
Map
// If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
ValueStack stack =(ValueStack)request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
if(stack!= null){
extraContext.put(ActionContext.VALUE_STACK, ValueStackFactory.getFactory().createValueStack(stack));
}
String timerKey = ”Handling request from Dispatcher“;
try {
UtilTimerStack.push(timerKey);
String namespace = mapping.getNamespace();
String name = mapping.getName();
String method = mapping.getMethod();
Configuration config = configurationManager.getConfiguration();
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, extraContext, true, false);
proxy.setMethod(method);
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
// if the ActionMapping says to go straight to a result, do it!
if(mapping.getResult()!= null){
Result result = mapping.getResult();
result.execute(proxy.getInvocation());
} else {
proxy.execute();
}
// If there was a previous value stack then set it back onto the request
if(stack!= null){
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
}
} catch(ConfigurationException e){
LOG.error(”Could not find action or result", e);
sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
} catch(Exception e){
thrownew ServletException(e);
} finally {
UtilTimerStack.pop(timerKey);
}
}
最后,通过Result完成页面的跳转。
3.4 本小节总结
总体来讲,Struts2的工作机制比Struts1.x要复杂很多,但我们不得不佩服Struts和WebWork开发小组的功底,代码如此优雅,甚至能够感受看到两个开发小组心神相通的默契。两个字:佩服。
以下是Struts2运行时调用方法的顺序图:
(图21)
四、总结
阅读源代码是一件非常辛苦的事,对读者本身的要求也很高,一方面要有扎实的功底,另一方面要有超强的耐力和恒心。本章目的就是希望能帮助读者理清一条思路,在必要的地方作出简单的解释,达到事半功倍的效果。
当然,笔者不可能为读者解释所有类,这也不是我的初衷。Struts2+xwork一共有700余类,除了为读者做到现在的这些,已无法再做更多的事情。读者可以到Struts官方网站下载帮助文档,慢慢阅读和理解,相信会受益颇丰。
本章并不适合java语言初学者或者对java博大精深的思想理解不深的读者阅读,这其中涉及到太多的术语和类的使用,特别不要去钻牛角尖,容易使自信心受损。基本搞清楚Struts2的使用之后,再回过头来阅读本章,对一些知识点和思想也许会有更深的体会。
随着Web领域的不断发展,MVC (Mode-View-Controller)成为一种公认的优秀设计模式,该模式分为模型层、视图层、控制层,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。Struts2是建立在Struts和WebWork基础上,并且集成了Struts和WebWork的优点,它是使用了MVC设计模式的框架,能够具有更好的可扩展性、强大的功能,同时它也是目前最流行的MVC框架之一[1]。FreeMarker和Velocity是应用在Struts2中非常流行的模板语言。主要研究FreeMarker和Velocity模板语言在Struts2中的应用,工作原理,分析比较两种模板语言的特点,方便开发人员在开发过程中,选择最合适的模板语言开发项目工程,提高工作效率,从而节省了开发所需要的时间。
2 FreeMarker模板语言
FreeMarker是一个用Java编写的模板引擎,能够将数据与页面模板分离,根据指定的模板输出多种规格的文本,如HTML、XML、RTF等。FreeMarker实际上是被设计用来生成HTML页面,尤其是通过实现了基于MVC (Mode-View-Controller)模式的Java Servlet应用程序。使用MVC模式的动态页面的设计思想,可以将前端设计师从程序员中分离出来。网页设计人员专注于改写视图页面的显示内容,而不受到程序开发人员编写底层代码的干扰,这是因为将业务逻辑和视图页面设计被分离出来了。这种设计思想可以让同一个人在同一个项目当中拥有程序员和页面设计师的角色,由于逻辑和视图分离使代码变得简洁,更加方便程序员去维护。
FreeMarker的工作原理是模板+数据模型=输出[2],以此将数据模型中的数据合并到模板并将其输出,如图1所示。虽然FreeMarker也具有一些编程能力,但是它不是一种很全面的编程语言。当程序需要显示数据库的数据信息时,FreeMarker是通过模板生成文本页面把数据库中的数据信息显示出来。
FreeMarker不是Web开发的应用程序框架。它是一个适用于Web应用程序框架中的组件,但是FreeMarker引擎本身并不知道HTTP协议或Java Servlet的存在。它仅仅来生成文本内容。即使是这样,它也非常适用于非Web应用程序的开发环境。值得注意的是,我们使用FreeMarker作为视图层的组件,是为了给例如Struts这样的Model 2应用框架提供现成的解决方案。FreeMarker本身是免费的,它基于BSD规则的许可协议。它也是OSI认证的开源软件[2]。
FreeMarker是Struts2默认的模板技术,较Velocity模板引擎,FreeMarker支持JSP标签,内嵌XML、DOM解析功更强大,使用起来更加方便快捷。此外,Free Marker的指令具有对数据的分值控制、循环输出等功能,对处理Hash和Sequence对象时具有更好的灵活性。Free Marker生成的纯文本的静态文件,有利于减轻服务器的负担[3]。如果用户使用FreeMarker生成纯文本的HTML、XML等文档,服务器需要更少的硬件资源,服务器能够对用户的请求做出快速的响应,不同于JSP页面,当JSP页面发布于服务器上时,用户请求需要不断地与服务器进行交互,从而使服务器占用了大量的资源。与JSP相比较,使用FreeMarker能够提高服务器的响应速度,缩短反应时间,降低对硬件资源的占用率。
3 Velocity模板语言
Velocity模板语言简称VTL,是一个基于Java的模版引擎[4]。在同一个应用程序中,Web设计师可以使用Velocity模板语言预先设计好模板Java开发人员编写程序代码设置上下文,将页面中的数据放入到上下文中,通过使用Velocity引擎将数据和上下文结合起来,实现动态页面的效果。Java代码和视图设计的有效分离[5],可以使Java开发人员专注于Java代码的底层编写,页面设计师专注于页面设计的效果,不需要考虑更多的代码编程,有利于后期应用程序的管理与维护。Velocity可用来从模板产生Web页面,SQL,PostScript以及其他输出,简化了Web开发。它也可用于一个独立的程序以产生源代码和报告,或者作为其他系统的一个集成组件。Velocity还支持模板的国际化编码转换。Velocity也是Apache软件组织提供的一项开源项目,可以免费下载。
Struts2对Velocity提供了很好的支持,只需要经过简单的配置,就可以在程序中使用Velocity,不需要Velocity的API。
4 比较分析
FreeMarker和Velocity都是目前非常流行的两种模板语言,两种语言的语法也很相似,适用对象也基本相同,它们最大的相似点都是通过分离页面视图和程序逻辑,从而实现MVC架构。
FreeMarker比Velocity多了一个格式化的功能,而且FreeMarker还支持JSP标签,内嵌XML DOM解析,功能上要比Velocity强[1]。使用Velocity,需要寻找各种工作环境或者特定工具来一次次地解决典型的模板创作任务,最后会浪费很多时间。工作环境经常意味着把Java对象在Velocity模板中直接使用,这违反了简单、无编程HTML设计的理念。如果将表示任务移到控制器代码中的话,这也违反了MVC框架设计理念。使用FreeMarker,可以以out-of-the-box的方式实现Velocity所能做的。
当访问一个未定义的变量,可以通过配置FreeMarker来停止render模板显示错误信息,或者跳过错误部分,FreeMarker会记录问题(日志),在写错指令名时,FreeMarker也会抛出异常。而Velocity会输出源代码。
Velocity语法上相对FreeMarker要简单一些,不需要什么特定的标签,它只使用简单的$varName来输出变量,灵活度要较FreeMarker高一些。Velocity不支持其他标签库(即在Velocity中不能引用其他标签,如不能使用Struts的标签
5 结语
FreeMarker和Velocity都是优秀的模板语言,分离了页面逻辑和业务逻辑,通过与Struts2的组合使用可以进行高效的工作。Struts2框架采用FreeMarker作为其默认的模板技术,同时对Velocity的支持性也是非常良好,是选择FreeMarker还是选择Velocity,程序开发人员可以根据实际项目中的需求,去选择对自己更加方便、快捷、高效的模板语言。
摘要:Struts2是一个基于MVC架构的框架,有许多视图表示形式。为了使Java Web的页面视图更好地与业务逻辑分离开来,引入了基于Java的FreeMarker和Velocity模板语言,这两种模板语言凭借着自身的优势在众多模板语言中广泛应用,使用FreeMarker和Velocity模板引擎技术,不仅提高了程序员的开发效率,还使得应用程序在较长的时间内具有良好的维护性。
关键词:FreeMarker语言,Velocity语言,模板引擎,Struts 2框架,Java Web应用
参考文献
[1]范立峰,林果园.Java Web程序设计教程[M].北京:人民邮电出版社,2010.
[2]南磊,译.FreeMarker手册.
[3]耿晓君,等.Struts2下基于FreeMarker的XML数据输出与ExtJS的解析实现[J].江苏广播电视大学学报,2009,(05):59-62.
[4]陈涛,白栩翔.Velocity模板引擎技术在Java Web中的应用[J].农业网络信息,2011,(05):38—40.
关键词组织机构代码;现状;对策;分析
中图分类号TB文献标识码A文章编号1673-9671-(2011)021-0225-01
代码事业在我国已有二十年的历史,在全国代码工作人员的努力下取得了令人瞩目的成绩,但是代码事业要想更加深入的发展,满足日益快速的发展大中小企业的需求,就面临着严峻且强有力的考验。
1组织机构代码工作的现状和面临的挑战
1)法人基础信息库的确立给组织机构代码工作人员带来的挑战。国家信息化的发展要求法人库的确立,此项工作量大、面广、技术要求高,进度较为缓慢,其中的主要问题就是代码在法人库中的定位、流程、系统建设和协调等问题,如果这些问题解决不了,就无法保证法人库建设的正常进行,要代码介入到国家电子政务中去只能是纸上谈兵,只有极大力度把各项繁杂、细致的基础性工作做好,才有可能使得代码事业在较短的时间内有新的进展和突破。
2)提高代码的赋码率来满足应用部门的需求。目前,组织机构代码因历史和法律法规执行上的原因受到一定的局限,这是由于国家经济战略的调整,各种经济活动不断的涌现,从而也致使了代码赋码不全的问题出现,制约着代码工作的进一步发展。要拓宽赋码范围,提高赋码率,不仅是代码工作及时为各应用部门提供准确有效的基础信息,也为国家宏观经济调控起到重要作用。我们必须高度重视且努力认真的落实。
3)是立法问题。代码事业在发展中一直不断面临种种挑战,法人单位基础信息库工程建设仍然举步维艰、进展迟缓,最关键、最核心的原因就是组织机构代码至今尚未立法。由于没有法律的保障,部门间利益矛盾难以协调也就成了必然。事实上,随着法人单位基础信息库确立,相关部委和专家对代码有了越来越多的了解,对其重要性也有更深刻的认识,并对代码还没能立法也感到困惑。为此代码中心一直在坚定信心地全方位努力,将这一很有希望的事情抓紧抓好。
2代码工作必须努力奋斗的几个方面
1)加快法人单位基础的信息库建设的进程。代码工作的生命线在于能否在国家的信息化建设中担当重要角色,如果代码工作被国家的信息化工作边缘化,那么后果将不堪设想。不进则退,我们没有更多的考虑和徘徊余地。因此,我们将承受更繁重的工作,更艰巨的任务,在紧迫的时间里,必须重点做好以下几项工作:①加强于国信办、编办、工商、税务、民政和统计等部门的协调,在代码工作基础不受影响的前提下,求大同存小异,把法人库建设的进程推向实质性阶段;②利用专家组等各方力量,进一步做好方案的论证及完善工作,使其既能满足国家电子政务的需求,又能满足代码事业的长久发展;③做好法人库方案实施计划中的各项准备工作,在做好需求分析的基础上,抓好基础建设、技术装备的配置、软件的开发与系统管理;④做好各级代码管理机构法人库建设的指导与落实,在搞好调研的基础上,研究出实现法人单位基础信息库动态化实时管理的关键要素,形成更加完善的法人单位基础分信息库的动态采集维护管理系统;⑤代码中心要尽快完成代码管理信息系统的升级工作,完成计算机房的扩建与改造;⑥加强对代码工作人员的培训工作,要有计划地针对高级管理人员和一般工作人员进行不同层次、不同内容地培训,切实为法人库的建设、应用和维护打下良好的基础。
2)加强代码立法工作。组织机构代码立法仍是今年一项重要工作,而且是一件只能抓紧不能放松的工作。目前,已有近90%的代码管理机构都有地方法规可依,这为国家代码立法奠定了一个好的基础,因为这是一件大有希望的事,所以必须努力去做,早一天出台,我们的工作就早一天步入法制化正轨,法人库的建设就会早日做成,代码就能早日在国家电子政务和信息化建设中站稳脚跟。
3)提高代码库数据质量。应用是代码的生命,而推动代码应用的关键是数据质量。我们讲提高数据质量,不仅是几个应用部门的需求,更重要的是国家在电子政务建设中对基础信息的需求,是全面提高政府依法行政能力,加快建设廉洁、勤政、务实、高效的政府、促进国民经济可持续快速健康发展和社会进步的需求。代码在法人库中的定位向我们提出了挑战,而挑战的核心问题就是数据质量是否能经得起考验,这就给我们敲响了警钟:法人库建成后,代码数据与多个部门的数据可能共置于一个平台,使其更具透明度与可比性,这种资源整合的结果终究会以优质而胜出,以劣质而淘汰,可见代码的数据质量是代码事业生死存亡的关键。因此,对代码数据的准确性、规范性和完整性,我们必须给予高度重视,切不可掉以轻心。
4)进一步加大推广应用的力度。组织机构代码工作能够得以不断发展,推广应用是生命。法人库建设进程给代码的推广应用工作提出了更艰巨的任务。今年,代码中心一方面要努力抓好法人库建设中与各参与部门的协调工作,另一方面,要继续深化代码在银行、外汇、社会保障、公安车辆管理和质检部门的应用,尤其是要通过与银行和外汇部门的数据核对,核查清理问题数据和沉淀数据。各地方代码管理机构要充分重视此项工作,积极配合国家代码中心做好清查工作,以提高代码数据库信息的整体质量,为各应用部门提供满意的服务。
5)完善个体户赋码。完善个体赋码,是代码在国家经济实现金融监管、税源监控应用中的一个重要需求,也是代码拓展自身事业,适应更广泛的应用一个重要环节。今年3月11日总局下发了《关于向个体工商户颁发组织机构代码证书有关问题的通知》,通知对在向个体户赋码中的法律依据、颁证原则和有关注意事项都做了规定,望各地要认真贯彻执行,既保证赋码的合法性,又要保证应用部门的数据真实性与完整性。个体工商户赋码牵涉的问题较多,政策性又很强,做好了对代码的应用将产生巨大的影响与推动。因此必须注重二个方面:一是严格政策,在自愿的基础上对符合条件的一定要赋,否则不赋;二是实施代码区段单独管理,杜绝码段混用和重错码现象发生。
6)加大培训力度。国家信息化的不断发展,给代码工作不断提出了新要求,同时,也促使代码工作不断产生新的变化,包括政策性、技术性、管理性等等。变化是客观存在,只有适应变化才能进步,怎样适应?最根本的还是靠人,没有一批能够适应变化的人,代码工作就没办法做好,几年来不管代码中心还是各地代码管理机构在培训上都做了很多工作,但仍不能满足代码工作的发展要求,代码工作有些问题的产生,就是因为人员素质没能达到要求而产生的,所以,人员加强培养工作一定要抓紧、抓好、抓出成效。
3结语
国家信息化的不断发展,给代码工作不断提出了新要求,同时,也促使代码工作不断产生新的变化,包括政策性、技术性、管理性等等。变化是客观存在,只有适应变化才能进步,培养一批能够适应变化的人,各地代码管理工作才能获得良好的成效。
参考文献
[1]刘晓平.提高代码质量.拓宽应用领域[J].学理论,2010,09.
标识、可以、如果没写,说明该包为默认空间 2.Action 的实现通集成常用那种方法? 一种是直接实现自己的Action 另一种是实现Action的接口 继承ActionSupport 3.不属于Struts2的动作类的常量返回值的是(C)
A.success
B.input
C.never
D.login 4.以下不属于Struts2动作执行的结果类型是(A)a.action b.redirect c.redirectAction d.dispatcher 5.在struts.xml中。假如在一个package中没有配置namespace,那么在其中配置一个Action名字叫做login,它的result是这样配置的
配置的
A A.在根路径后输入/login B.在根路径后输入/user/login C.在根路径后输入/login/user D.在根路径后输入/abc/login 6.正规开发中,在使用struts2时定义Action使用哪种方式。B A.直接定义Action类。B.从ActionSupport继承。C.从Action继承。D.实现Action接口。
7.不同的线程在调用Action时创建几个Action实例。C A.1个 B.2个
C.每个线程创建1个。D.可以自定义配置。
8.struts提供了Action接口定义了5个标准字符串常量,不包括的有(C)A SUCCESS
B NONE C REG D LOGIN
9.列举出action执行结果类型,并说明用途。
默认结果类型是dispatcher chain:Action链式处理的结果类型,也就是将结果转发到这个action中。
dispatcher:用于整合JSP的结果类型
redirect:实际上dispatcher和redirect的区别就是在于转发和重定向的区别。
redirect-action:重定向action 10.struts2中result-type的chain和redirectAction的区别 chain,它是一个琏式的,是从一个Action转发另外一个Aciton redirectAction,是从新请求一个Action 11.action的class里面写的是什么? Action相应类的详细路径
12.action的extends里面调用的是什么?
从另外一个包继承、相当于拥有即承包的所有配置
13.如果不写action的后面mothod,默认的调用的方法是什么,如果写的话,写的时候有什么需要注意的?
不写会默认调用最上面的方法
14.输出值的strtus标签是什么?
s:property
15.循环的struts标签是什么?
s:iterator
15.判断的strtuts标签是什么?
s:if
16.显示文本的strtuts标签是什么?
17.请简述前台提交后是如何到达后台action的。
通过form表单action找到struts配置文件相应action的类 再去找相应action类里的方法
Struts2习题2
一、填空题
1.Struts2框架由___________和___________框架发展而来。(Struts&WebWork)2.Struts2以___________为核心,采用___________的机制来处理用户的请求。(WebWork,拦截器)
3.Struts2中的控制器类是一个普通的___________。Class或填过滤器类
二、选择题
1.不属于Action接口中定义的字符串常量的是___________。B A.SUCCESS B.FAILURE
C.ERROR D.INPUT 2.在控制器类中一般需要添加相应属性的___________和___________。AC A.setter方法 B.as方法 C.getter方法 D.is方法 3.控制器需要在___________配置文件中进行配置。B A.web.xml B.struts.xml C.struts2.xml D.webwork.xml 4.不属于Struts 2表单标签库的是___________。D A.
三、简答题
1、简述什么是MVC?
MVC即模型-视图-控制器.MVC是一种设计模式,它强制把应用程序的输入处理和输出分开.视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并能接受用户的输入,但是它并不进行任何实际的业务处理。模型是应用程序的主体部分。模型表示业务数据和业务逻辑。控制器接受用户的输入并调用模型和视图去完成用户的需求
2、简述servlet的生命周期。
WINDOWS系统访问共享文件时(file:协议,可以在HTM里面夹杂此协议),会自动试着以当前用户的身份连接(发送用户名、加密的密码),如果不能连接才提示用户输入用户名和密码,所以造成密码泄漏,
影响版本:WIN95、WIN98、WINNT、WIN2000。
补救措施:找微软。
下面是WIN98系统的泄露密码相关代码分析。这是文件VREDIR.VXD的一段代码:
15760 sub_0285 proc near
15760 55 push ebp
15761 8B EC mov ebp,esp
15763 83 EC 0C sub esp,0Ch
15766 33 C0 xor eax,eax
15768 53 push ebx
15769 56 push esi
1576A 57 push edi
1576B 8B 7D 08 mov edi,dword ptr [ebp+PARAMETER_1]
1576E 8B 5D 14 mov ebx,dword ptr [ebp+PARAMETER_4]
15771 66| C7 43 01 00FF mov word ptr [ebx+1],0FFh
15777 8B 77 1C mov esi,dword ptr [edi+1Ch]
1577A 8A 47 05 mov al,byte ptr [edi+5]
1577D 8B 55 10 mov edx,dword ptr [ebp+PARAMETER_3]
15780 C6 03 0D mov byte ptr [ebx],0Dh
15783 8B 0C 85 00000AE0 mov ecx,dword ptr data_0114[eax*4] ;
1578A 8B 45 18 mov eax,dword ptr [ebp+PARAMETER_5]
1578D 66| 89 43 05 mov word ptr [ebx+5],ax
15791 89 4D F8 mov dword ptr [ebp+LOCAL_2],ecx
;the login user block 用户信息块
15794 66| 0F B6 4A 18 movzx cx,byte ptr [edx+18h]
15799 66| 89 4B 07 mov word ptr [ebx+7],cx
1579D 8D 42 2C lea eax,dword ptr [edx+2Ch]
157A0 ?0 push eax
157A1 E8 FFFFFADA call sub_0282
157A6 66| 89 43 09 mov word ptr [ebx+9],ax
157AA 83 C4 04 add esp,4
157AD C7 43 13 00000000 mov dword ptr [ebx+13h],0
157B4 8B 55 10 mov edx,dword ptr [ebp+PARAMETER_3]
157B7 C7 43 17 00000000 mov dword ptr [ebx+17h],0
157BE 8B 4A 28 mov ecx,dword ptr [edx+28h]
157C1 89 4B 0B mov dword ptr [ebx+0Bh],ecx
;key
157C4 66| 8B 4A 1A mov cx,word ptr [edx+1Ah]
157C8 66| 8B C1 mov ax,cx
157CB 66| 25 0200 and ax,200h
157CF 66| 3D 0001 cmp ax,1
157D3 B8 00000000 mov eax,0
157D8 83 D0 FF adc eax,0FFFFFFFFh
157DB 66| 83 E1 03 and cx,3
157DF 83 E0 04 and eax,4
157E2 66| 83 F9 01 cmp cx,1
157E6 89 43 17 mov dword ptr [ebx+17h],eax
157E9 1B C9 sbb ecx,ecx
157EB 41 inc ecx
157EC 0B C8 or ecx,eax
157EE 83 7D F8 00 cmp dword ptr [ebp+LOCAL_2],0
157F2 89 4B 17 mov dword ptr [ebx+17h],ecx
157F5 0F 84 00000244 jz loc_1740
157FB 8A 4A 19 mov cl,byte ptr [edx+19h]
; SECURITY MODE 安全模式
;是服务方发过来的数据,所以服务方可以主动按其需要修改
157FE F6 C1 01 test cl,1
15801 0F 84 000001CB jz loc_1739
; USER OR SHARE MODE
;共享控制的跳转
15807 80 7F 05 02 cmp byte ptr [edi+5],2
1580B 75 53 jne short loc_1729
1580D 8B 45 F8 mov eax,dword ptr [ebp+LOCAL_2]
15810 8B 70 28 mov esi,dword ptr [eax+28h]
15813 85 F6 test esi,esi
15815 74 12 jz short loc_1726
15817 8D 7B 1D lea edi,dword ptr [ebx+1Dh]
1581A B9 00000006 mov ecx,6
1581F F3/ A5 rep movsd
15821 66| C7 43 0F 0018 mov word ptr [ebx+0Fh],18h
;PASSWORD LONG
15827 EB 06 jmp short loc_1727
15829 loc_1726:
15829 66| C7 43 0F 0000 mov word ptr [ebx+0Fh],0
1582F loc_1727:
1582F 33 C0 xor eax,eax
15831 8B 4D F8 mov ecx,dword ptr [ebp+LOCAL_2]
15834 66| 8B 43 0F mov ax,word ptr [ebx+0Fh]
15838 8B 71 2C mov esi,dword ptr [ecx+2Ch]
1583B 85 F6 test esi,esi
1583D 8D 7C 18 1D lea edi,dword ptr [eax+1Dh][ebx]
15841 74 12 jz short loc_1728
15843 B9 00000006 mov ecx,6
15848 F3/ A5 rep movsd
1584A 66| C7 43 11 0018 mov word ptr [ebx+11h],18h
15850 E9 000000E8 jmp loc_1736
15855 loc_1728:
15855 66| C7 43 11 0000mov word ptr [ebx+11h],0
1585B E9 000000DD jmp loc_1736
15860 loc_1729:
15860 C7 45 FC 00001A78 mov dword ptr [ebp+LOCAL_1],1A78h
15867 F6 46 1C 20 test byte ptr [esi+1Ch],20h
1586B 74 08 jz short loc_1730
1586D 83 C6 35 add esi,35h
15870 89 75 FC mov dword ptr [ebp+LOCAL_1],esi
15873 EB 12 jmp short loc_1731
15875 loc_1730:
15875 8B 55 10 mov edx,dword ptr [ebp+PARAMETER_3]
15878 8B 42 0C mov eax,dword ptr [edx+0Ch]
1587B F6 40 1C 20 test byte ptr [eax+1Ch],20h
1587F 74 06 jz short loc_1731
15881 83 C0 35 add eax,35h
;THE PASSWORD POINTER
15884 89 45 FC mov dword ptr [ebp+LOCAL_1],eax
15887 loc_1731:
15887 8B 45 FC mov eax,dword ptr [ebp+LOCAL_1]
1588A 80 38 00 cmp byte ptr [eax],0;
;THE PASSWORD
1588D 75 09 jne short loc_1732
;比较看有否输入密码,如果没有密码就用用户密码替换
;因为开始还没有出来提示输入密码时就有好几次密码实验,
;所以一定有没有密码的情况,也就泄露了当前用户密码
1588F 8B 45 F8 mov eax,dword ptr [ebp+LOCAL_2]
15892 83 C0 05 add eax,5
Struts2 的开发应用
一、实验目的
理解MVC设计模式的基本概念和Java Web开发的两种模式Model1和Model2,以及Struts开发工作流程和基本应用。
二、实验要求
1. 2. 3. 4. 掌握Struts2.0的开发环境的建立。理解Struts的框架原理。掌握Struts的工作流程。掌握Struts2.0的基本应用。
三、实验内容
(一)Struts2的文件上传
1. 文件上传页面,其中包含两个表单域:文件标题和文件浏览域 程序功能:上传页面,包含两个表单域。 程序源码: upload.html