ITPub博客

面试题

原创 Linux操作系统 作者:silver6 时间:2007-12-16 04:23:15 0 删除 编辑

c++面试题

silver6 | 27 十月, 2005 17:15

定义了一个基类CLayer,想让它的派生类CCircle对用户不可见,只能调用基类CLayer里的方法,问:
要到下面空格处完成两到三个方法。
layer.h #include layer.h

class CLayer class CCircle():public CLayer
{ {
public: public:
CCircle();
virtual void Draw();
virtual void Draw(); virtual int GetRadius();
virtual int GetRadius(); private:
(1) int Radius;
-----------------
(2) }
-----------------
(3)
__________________
protect:
CLayer();
virtual ~CLayer();
}

只能通过左边的基类来访问CCircle,请问上面的空格怎样填写

mainfrm.h

class CCircle;

class CLayer
{
public:
virtual void Draw(){};
virtual int GetRadius(){return 0;};
typedef enum{ CIRCLE = 0, THER = 1}CLASSTYPE;
static CLayer* GetObject(CLASSTYPE enmType);
void ReleaseObject(){delete this;};
protected:
CLayer(){};
virtual ~CLayer(){};
};

class CCircle : public CLayer
{
public:
CCircle(){Radius = 3;};
virtual void Draw(){};
virtual int GetRadius(){return Radius;};
private:
int Radius;
};

mainfrm.cpp

CLayer* CLayer::GetObject(CLASSTYPE enmType)
{
if (CIRCLE == enmType)
{
return new CCircle();
}
else
{
return NULL;
}
}

CMainFrame.:CMainFrame()
{
CLayer* pL = CLayer::GetObject(CLayer::CIRCLE); // 创建对象
if (pL)
{
int iR = pL->GetRadius(); //访问方法
pL->ReleaseObject(); // 销毁
}
}


<!--

面试题目 VC(c++)

silver6 | 27 十月, 2005 17:12

1 dll,lib处理实现 .lib文件中包含什么? dll在内存中被多个函数共享,有几个拷贝?
2 template,template等编译的时候作为几个类
3 struct ,class的区别,联系
4 MAcro,inline区别,实现.编译运行时
5 进程与线程区别
6 hdc-cdc区别联系
7 model dialog,modeless dialog,从创建到销毁全过程具体描述
8 各个线程new的内存,别的线程是否可以使用?
9 RUNTIME_CLASS, is what??

1 dll,lib处理实现 .lib文件中包含什么? dll在内存中被多个函数共享,有几个拷贝?
简单说,lib里面只有符号,dll里面才是具体的实现.dll在内存中被函数共享有几个拷贝??比较奇怪的问题,dll是在进程空间,所以每个进程有一份dll的copy,可以用GetModuleHandle去判断是否dll已经被load进进程地址空间.
2 template,template等编译的时候作为几个类
如果没有记错,是两个.模板都是编译时产生代码,所以会出现两个类.如果程序中的类型较多,就会展开比较大的代码,但是速度会快.
3 struct ,class的区别,联系
只是成员变量或者函数默认的属性,struct默认是public,class是private
4 MAcro,inline区别,实现.编译运行时
准确来说,内联要更加安全.使用内联,参数需要精确地进行一次求值,参数类型被检查,并且被正确地进行必要的转换,避免了宏的一些问题.也方便调试.简单说,内联更加像函数.
5 进程与线程区别
很多书上都有介绍,一般来说,进程是不活泼的,是线程的容器;线程是在进程里面创建的,执行代码的.
6 hdc-cdc区别联系
cdc是一块空间,保存一定的数据,hdc是放在进程的句柄表里面,用来标示所代表的cdc的
7 model dialog,modeless dialog,从创建到销毁全过程具体描述
模式的是CDialog的DoModal调用CreateIndirect创建对话框,然后通过一个循环自己处理消息的分发;无模式的是通过create创建,类似于一般窗口
8 各个线程new的内存,别的线程是否可以使用?
不可以,因为线程new的空间是在自己的进程空间,别的进程是得不到的.
9 RUNTIME_CLASS, is what??
建议看一下深入浅出mfc

5 进程与线程区别: 最主要: 线程是执行代码的,CPU调度的单元,进程是个资源的容器

8. 同一进程内的线程之间共享进程的地址空间和所有资源

1 dll并不是拷贝到每一个调用者的进程空间,而是只在内存中保留一份拷贝。通过引用计数的方式控制其卸载。
但是dll中的全局变量是要被拷贝到每一个调用者的进程空间的
2 对于第八题,new的内存是在系统中的,虽然它会随着创建进程的消失而被自动回收,但是,还是可以将指针作为参数传递给别的线程或者进程,虽然这种做法不被推荐使用。
但是,如果如本题所说,在同一个进程种的线程,是否可以传递堆的指针,我觉得是可以的,而且没有风险。

.关于dll,代码是放到了RAM中,其他进程都可以通过静态或者动态映射到其地址空间,共享该分页,任何对该dll的使用会引起计数器加一.之前和hookapi有点混了.

那个指针传递给别的进程,好像不能直接用.必须分配的空间是在别的进程,这样的指针在别的空间才用效,好像要用到VirtualAllocEx分配虚拟空间,对于进程间的WM_SetText这类消息,指针里面的数据也是被复制到了对应进程的空间才有效,呵呵.举个例子,a空间里面的0x12345678标示字符串"ABC",但是b空间0x12345678也许是"efg",所以a给b里面传这个指针是不能用的.但是同一个进程里面的线程是可以使用别的线程分配的空间的.

对于第十个问题,是Doc/view框架里面的,可以通过设定view和doc之间的映射,那个单文档多视图做过,不过单视图多文档没有做过,可能需要动态调整各个文档在视图里面的位置吧,没有实践就没有发言权,就此打住,哈哈.


<!--

Spring简介

silver6 | 24 十月, 2005 18:50

Spring简介
关于Spring Framework,今年夏天你可能已经听见很多的议论。在本文中,我将试图解释Spring能完成什么,和我怎么会认为它能帮助你开发J2EE应用程序。

另一framework? 你可能正在想“不过是另外一个的framework”。当已经有许多开放源代码(和专有) J2EE framework时,为什么你应该费心读这篇文章,或下载Spring Framework?

我相信Spring是独特的,因为若干个原因:
. 它定位的领域是许多其他流行的framework没有的。Spring关注提供一种方法管理你的业务对象。
. Spring是全面的和模块化的。Spring有分层的体系结构,这意味着你能选择使用它孤立的任何部分,它的架构仍然是内在稳定的。因此从你的学习中,你可得到最大的价值。例如,你可能选择仅仅使用Spring来简单化JDBC的使用,或用来管理所有的业务对象。
. 它的设计从底部帮助你编写易于测试的代码。Spring是用于测试驱动工程的理想的framework。

Spring对你的工程来说,它不需要一个以上的framework。Spring是潜在地一站式解决方案,定位于与典型应用相关的大部分基础结构。它也涉及到其他framework没有考虑到的内容。

尽管它仅仅是一个从2003年2月才开始的开源工程,但Spring有较长的历史根基。这个开源工程是起源自我在2002年后期出版的《Expert One-on-One J2EE设计与开发》书中的基础代码。这本书展示了Spring背后的基础架构。然而,这个基础架构的概念要追溯到2000年的早些时候,并且反映了我为一系列成功的商业工程开发基础结构的经验。

从2003年1月,Spring已经落户于SourceForge上。现在有10个开发人员,其中6是高度投入的积极分子。

Spring的架构性的好处
在我们进入细节以前,让我们看一下Spring可以给一个工程带来的一些好处:

. Spring能有效地组织你的中间层对象,无论你是否选择使用了EJB。如果你仅仅使用了Struts或其他的包含了J2EE特有APIs的framework,你会发现Spring关注了遗留下的问题,。

. Spring能消除在许多工程上对Singleton的过多使用。根据我的经验,这是一个主要的问题,它减少了系统的可测试性和面向对象特性。

. Spring能消除使用各种各样格式的属性定制文件的需要,在整个应用和工程中,可通过一种一致的方法来进行配置。曾经感到迷惑,一个特定类要查找迷幻般的属性关键字或系统属性,为此不得不读Javadoc乃至源编码吗?有了Spring,你可很简单地看到类的JavaBean属性。倒置控制的使用(在下面讨论)帮助完成这种简化。

. Spring能通过接口而不是类促进好的编程习惯,减少编程代价到几乎为零。
. Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。
. 使用Spring构建的应用程序易于单元测试
. Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实现业务接口,却不会影响调用代码。
. Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适于许多web应用。例如,Spring能使用AOP提供声明性事务而不通过使用EJB容器,如果你仅仅需要与单个的数据库打交道,甚至不需要JTA实现。
. Spring为数据存取提供了一致的框架,不论是使用JDBC或O/R mapping产品(如Hibernate)。
Spring确实使你能通过最简单可行的解决办法解决你的问题。这些特性是有很大价值的。

Spring能做什么?

Spring提供许多功能,在此我将快速地依次展示其各个主要方面。

任务描述:
首先,让我们明确Spring范围。尽管Spring覆盖了许多方面,但我们已经有清楚的概念,它什么应该涉及和什么不应该涉及。

Spring的主要目的是使J2EE易用和促进好编程习惯
Spring不重新开发已有的东西。因此,在Spring中你将发现没有日志记录的包,没有连接池,没有分布事务调度。这些均有开源项目提供(例如Commons Logging 用来做所有的日志输出,或Commons DBCP用来作数据连接池),或由你的应用程序服务器提供。因为同样的的原因,我们没有提供O/R mapping层,对此,已有有好的解决办法如Hibernate和JDO。

Spring的目标是使已存在的技术更加易用。例如,尽管我们没有底层事务协调处理,但我们提供了一个抽象层覆盖了JTA或任何其他的事务策略。

Spring没有直接和其他的开源项目竞争,除非我们感到我们能提供新的一些东西。例如,象许多开发人员,我们从来没有为Struts高兴过,并且感到在MVC web framework中还有改进的余地。在某些领域,例如轻量级的IoC容器和AOP框架,Spring有直接的竞争,但是在这些领域还没有已经较为流行的解决方案。(Spring在这些区域是开路先锋。)

Spring也得益于内在的一致性
所有的开发者都在唱同样的的赞歌,基础想法依然是Expert One-on-One J2EE设计与开发的那些。
并且我们已经能够使用一些主要的概念,例如倒置控制,来处理多个领域。

Spring在应用服务器之间是可移植的
当然保证可移植性总是一次挑战,但是我们避免任何特定平台或非标准化,并且支持在WebLogic,Tomcat,Resin,JBoss,WebSphere和其他的应用服务器上的用户。

倒置控制容器
Spring的设计核心是 org.springframework.beans 包, 为与JavaBeans一起工作而设计。 这个包一般不直接被用户使用, 但作为基础为更多的其他功能服务. 下一个较高层面的抽象是"Bean Factory"。 Spring bean factory 是一个普通的Factory,它使对象能够按名称获取,并且能管理对象之间的关系。

Bean factories 支持两种对象模式:
. Singleton:在此模式中,有一个具有特定名称的共享对象实例,它在查找时被获取。这是默认的,而且是最为经常使用的。它对于无状态对象是一种理想的模式。
.Prototype:在此模式中,每次获取将创建一个独立的对象。例如,这可以被用于允许用户拥有他们自己的对象。

由于 org.springframwork.beans.factory.BeanFactory是一个简单的接口,它能被为了底层存储方法而实现。你能够方便地实现你自己的BeanFactory,尽管很少用户需要。最为常用的定义是:
.XmlBeanFactory: 可解析简单直观的定义类和命名对象属性的XML结构。 我们提供了一个DTD来使编写更容易。
.ListableBeanFactoryImpl:可提供解析存放在属性文件中的bean定义,和可通过编程创建BeanFactories。

每个bean定义可能是一个POJO(通过类名和JavaBean初始属性定义),或是一个FactoryBean。FactoryBean接口添加了一个间接层。通常,这用于使用AOP或其他方法来创建代理对象:例如,添加了声明性事务管理的代理。(这在概念上和EJB侦听相似,但在实践中实现更简单。)

BeanFactories能在一个层次结构中可选择性的参与,根据来自祖先的继承定义。这使在整个应用中公共配置的共享成为可能,虽然个别资源,如controller servlets,也拥有他们自己的独立的对象集合。

这种使用JavaBeans的动机在的第四章中有描述,在TheServerSide网站上的有免费的PDF(http://www.theserverside.com/resources/article.jsp?l=RodJohnsonInterview).

通过BeanFactory概念,Spring成为一个倒置控制的容器。(我非常不喜欢container这个术语,因为它使人联想到重量级容器,如EJB容器。Spring的BeanFactory是一个可通过一行代码创建的容器,并且不需要特殊的部署步骤。)

位于倒置控制背后的概念是在Hollywood原则中经常表述:"Don’t call me, I’ll call you." IoC将控制职责搬进了框架中,并脱离应用代码。涉及到配置的地方,意思是说在传统的容器体系结构中,如EJB,一个组件可以调用容器并问“我需要它给我做工作的对象X在哪里?”;使用IoC容器则只需指出组件需要X对象,在运行时容器会提供给它。容器基于方法名作出这种说明,或可能根据配置数据如XML。

倒置控制的几个重要好处。如:
. 因为组件不需要在运行时间寻找合作者,所以他们可以更简单的编写和维护。在Spring的IoC版本里,组件通过暴露JavaBean的setter方法表达他们依赖的其他组件。这相当于EJB通过JNDI来查找,EJB查找需要开发人员编写代码。
. 同样原因,应用代码更容易测试。JavaBean属性是简单的,Java核心的,并且容易测试:仅编写一个包含自身的Junit测试方法用来创建对象和设置相关属性即可。
. 一个好的IoC实现隐藏了强类型。如果你使用一个普通的factory来寻找合作者,你必须通过类型转换将返回结果转变为想要的类型。这不是一个主要问题,但是不雅观。使用IoC,你在你的代码中表达强类型依赖,框架将负责类型转换。这意味着在框架配置应用时,类型不匹配将导致错误;在你的代码中,你无需担心类型转换异常。
. 大部分业务对象不依赖于IoC容器的APIs。这使得很容易使用遗留下来的代码,且很容易的使用对象无论在容器内或不在容器内。例如,Spring用户经常配置Jakarta Commons DBCP数据源为一个Spring bean:不需要些任何定制代码去做这件事。我们说一个IoC容器不是侵入性的:使用它并不会使你的代码依赖于它的APIs。任何JavaBena在Spring bean factory中都能成为一个组件。

最后应该强调的是,IoC 不同于传统的容器的体系结构( 如EJB), 应用代码最小程度的依靠于容器。这意味着你的业务对象可以潜在的被运行在不同的IoC 框架上-或者在任何框架之外-不需要任何代码改。

以我的经验和作为Spring用户,过分强调IoC给应用代码带来的好处是不容易的。

IoC不是一个新概念,但是它在J2EE团体里面刚刚到达黄金时间。 有一些可供选择的IoC 容器: notably, Apache Avalon, PicoContainer 和 HiveMind. Avalon 不会成为特别流行的,尽管它很强大而且有很长的历史。Avalon是相当的重量级和复杂的,并且看起来比新的IoC解决方案更具侵入性。 PicoContainer是一个轻量级而且更强调通过构造器表达依赖性而不是JavaBean 属性。 与Spring不同,它的设计允许每个类型一个对象的定义(可能局限性结果来自它对Java代码外的元数据的拒绝)。作为和Spring and PicoContainer and other IoC frameworks的比较,可参看文章http://www.springframework.org/docs/lightweight_container.html. 这个业面包含了PicoContainer站点链接 。

Spring BeanFactories 是非常轻量级的。用户已经成功地将他们应用在applets中和单独的Swing应用中。(它们也很好地工作在EJB容器中。) 没有特殊的部署步骤和可察觉的启动时间。这个能力表明一个容器在应用的任何层面差不多立即可以发挥非常大的价值。

Spring BeanFactory 概念应用贯穿于Spring整体, 而且是Spring如此内在一致的关键原因。在IoC容器中,Spring也是唯一的,它使用IoC作为基础概念贯穿于整个框架。

对应用开发人员,最重要的是,一个或多个BeanFactory提供一个定义明确的业务对象层。这是类似的,但比local session bean层更简单。与EJBs不同,在这个层中的对象可能是相关的,并且他们的关系被自己的factory管理。有一个定义明确的业务对象层对于一个成功的体系结构是非常重要的。

Spring ApplicationContext 是BeanFactory的子接口,为下列提供支持:
.消息寻找,国际化支持
.事件机制,允许应用对象发布和随意地注册为事件监听
.便携文件和资源访问


XmlBeanFactory示例
Spring用户通常在XML“bean定义”文件中配置他们的应用。Spring的XML bean定义文档的根是一个 元素。该元素包含一个或多个 定义。我们一般指定一个bean定义的类和属性。我们也必须指定ID作为标识,我们将在代码中使用该标志。
让我们来看一个简单的例子,在J2EE应用中常看到用来配置三个应用对象:
. J2EE DataSource
. 使用DataSource的DAO
. 在处理过程中使用DAO的业务对象

在下面的例子中,我们使用一个来自Jakarta Commons DBCP项目的BasicDataSource。这个class(和其他存在的class一样)可以简单地被应用在Spring bean factory中,因为它提供了JavaBean格式的配置。需要在shutdown时被调用的Close方法可通过Spring的"destroy-method"属性被注册,来避免BasicDataSource需要实现任何Spring 接口。

代码:


我们感兴趣的BasicDataSource的所有属性都是String型的,因此,我们用元素来指定他们的值。如果必要的话,Spring使用标准的 JavaBean属性编辑器机制来转换String以表示其他的类型。

现在,我们定义了DAO,它有一个对DataSource的bean引用。Bean间关系通过元素来指定:
代码:

业务对象有一个DAO的引用和一个int型属性(exampleParam):
代码:



对象间的关系一般在配置中明确地设置,象此例子一样。我们认为这样做是件好事情。无论如何,Spring也提供了我们叫做"autowire"的支持, 一个la PicoContainer,在那里,它可以指出bean间的依赖关系。这样做的局限性-如使用PicoContainer-是如果有一个特殊类型的多个Bean,要作出一个类型应该与哪个实例相关的判断将是不可能的。好的方面,在factory初始化后,不理想的依赖可能会被捕获到。(Spring 也为清楚的配置提供一种可选的依赖检查,它可以完成这个目的)

如果我们不想明确的编写他们的关系,在上面的例子中,我们可如下使用autowire特性:


使用这用用法,Spring将找出exampleBusinessObject的dataSource属性应该被设置为在当前BeanFactory中找到的DataSource实现。在当前的BeanFactory中,如果所需要类型的bean不存在或多于一个,将产生一个错误。我们依然要设置exampleParam属性,因为它不是一个引用。

Autowire支持和依赖检查刚刚加入CVS并将在Spring 1.0 M2(到10/20,2003)中提供。本文中所讨论的所有其他特性都包含在当前1.0 M1版本中。

来自Java代码的外在关系比硬编码有极大的好处,因为改变XML文件而无需改变一行Java代码是可能的。例如,我们可以简单地改变myDataSource的bean定义来提供不同的bean class以使用一个可供选择的连接池,或者一个测试数据源。 在一个单独可选的XML片断中,我们可以用Spring的JNDI 定位FactoryBean来从application server获取一个数据源。

现在让我们来看例子中业务对象的java 代码。注意下面列出的代码中没有对Spring的依赖。不像EJB容器,Spring BeanFactory不是侵入性的:在应用对象里面你通常不需要对他们编码。
代码:
public class ExampleBusinessObject implements MyBusinessObject {

private ExampleDataAccessObject dao;
private int exampleParam;

public void setDataAccessObject(ExampleDataAccessObject dao) {
this.dao = dao;
}

public void setExampleParam(int exampleParam) {
this.exampleParam = exampleParam;
}

public void myBusinessMethod() {
// do stuff using dao
}
}


注意属性设置器,在bean定义文档中,它对应与XML引用。这些将在对象使用之前被Spring调用.

这些应用bean不需要依赖于Spring。他们不需要实现任何Spring接口或者继承Spring的类:他们只需要遵守JavaBeans命名习惯。在Spring 应用环境之外重用它们是非常简单的,例如,一个测试环境。只是例示它有默认的构造器,并且通过setDataSource()和setExampleParam()的调用来手工设置它的属性。只要你有一个没有参数的构造器,如果你想在单行代码支持程序化的创建,你可以自由定义其他的带有多个属性构建的器。

注意,在业务接口中没有声明的JavaBean属性将会一起工作。 他们是一个实现细节。我们可以插入带有不同bean属性的不同的实现类而不影响连接对象或者调用代码。

当然,Spring XML bean factories 有更多的功能没有在这里描述,但是,这将给你一种基本使用的感觉。同时,简单的属性和有JavaBean属性编辑器的属性,Spring可以自动处理lists,maps和java.util.Properties.

<!--

Struts常见错误汇总

silver6 | 20 十月, 2005 10:39

以下所说的struts-config.xml和ApplicationResources.properties等文件名是缺省时使用的,如果你使用了多模块,或指定了不同的资源文件名称,这些名字要做相应的修改。   1、“No bean found under attribute key XXX”   在struts-config.xml里定义了一个ActionForm,但type属性指定的类不存在,type属性的值应该是Form类的全名。或者是,在Action的定义中,name或attribute属性指定的ActionForm不存在。   2、“Cannot find bean XXX in any scope”   在Action里一般会request.setAttribute()一些对象,然后在转向的jsp文件里(用tag或request.getAttribute()方法)得到这些对象并显示出来。这个异常是说jsp要得到一个对象,但前面的Action里并没有将对象设置到request(也可以是session、servletContext)里。   可能是名字错了,请检查jsp里的tag的一般是name属性,或getAttribute()方法的参数值;或者是Action逻辑有问题没有执行setAttribute()方法就先转向了。   还有另外一个可能,纯粹是jsp文件的问题,例如会指定一个id值,然后在循环里使用这个值作为name的值,如果这两个值不同,也会出现此异常。(都是一个道理,request里没有对应的对象。)   3、“Missing message for key "XXX"”   缺少所需的资源,检查ApplicationResources.properties文件里是否有jsp文件里需要的资源,例如:      这行代码会找msg.name.prompt资源,如果AppliationResources.properties里没有这个资源就会出现本异常。在使用多模块时,要注意在模块的struts-config-xxx.xml里指定要使用的资源文件名称,否则当然什么资源也找不到,这也是一个很容易犯的错误。   4、“No getter method for property XXX of bean teacher”   这条异常信息说得很明白,jsp里要取一个bean的属性出来,但这个bean并没有这个属性。你应该检查jsp中某个标签的property属性的值。例如下面代码中的cade应该改为code才对:      5、“Cannot find ActionMappings or ActionFormBeans collection”   待解决。   6、“Cannot retrieve mapping for action XXX”   在.jsp的 标签里指定action='/XXX',但这个Action并未在struts-config.xml里设置过。   7、HTTP Status 404 - /xxx/xxx.jsp   Forward的path属性指向的jsp页面不存在,请检查路径和模块,对于同一模块中的Action转向,path中不应包含模块名;模块间转向,记住使用contextRelative="true"。   8、没有任何异常信息,显示空白页面   可能是Action里使用的forward与struts-config.xml里定义的forward名称不匹配。   9、“The element type "XXX" must be terminated by the matching end-tag "XXX".”   这个是struts-config.xml文件的格式错误,仔细检查它是否是良构的xml文件,关于xml文件的格式这里就不赘述了。   10、“Servlet.init() for servlet action threw exception”   一般出现这种异常在后面会显示一个关于ActionServlet的异常堆栈信息,其中指出了异常具体出现在代码的哪一行。我曾经遇到的一次提示如下:   java.lang.NullPointerException    at org.apache.struts.action.ActionServlet.parseModuleConfigFile(ActionServlet.java:1003)    at org.apache.struts.action.ActionServlet.initModuleConfig(ActionServlet.java:955)   为解决问题,先下载struts的源码包,然后在ActionServlet.java的第1003行插入断点,并对各变量进行监视。很丢人,我竟然把struts-config.xml文件弄丢了,因此出现了上面的异常,应该是和CVS同步时不小心删除的。   11、“Resources not defined for Validator”   这个是利用Validator插件做验证时可能出现的异常,这时你要检查validation.xml文件,看里面使用的资源是否确实有定义,form的名称是否正确,等等。

<!--

Struts学习傻瓜式入门篇

silver6 | 19 十月, 2005 19:26

该案例包括首页,用户登陆、网站向导页面。就这么简单,没有深奥的struts概念,主要靠动手,然后用心体会。   WEB Server用tomcat4。到http://jakarta.apache.org下载struts1.1,把zip文件释放到c:struts,拷贝C:strutswebappsstruts-example.war到c:tomcat4webapps中,启动tomcat,war包被释放为struts-example文件夹,删除war包,把struts-example文件夹更名为test。  一、把WEB-INFweb.xml改成: action org.apache.struts.action.ActionServlet config /WEB-INF/struts-config.xml 1 action *.cool index.jsp   二、把testWEB-INF struts-config.xml改成:   三、增加一个FormBean,类路径为test.UserForm,以下是这个类的内容:package test; import org.apache.struts.action.ActionForm; public class UserForm. extends ActionForm. {  private String name="lpw";//用户名 private String ps="1111";//密码  public UserForm(){}  public void setName(String s) {name=s;}  public String getName() {return name;}  public void setPs(String s) {ps=s;}  public String getPs() {return ps;} }   四、增加一个Action的子类,类路径为test. RegistAction,以下是这个类的内容: package test; import java.lang.reflect.InvocationTargetException; import java.util.Locale; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.util.MessageResources; import test.UserForm; public final class RegistAction extends Action {  public ActionForward execute(ActionMapping mapping,ActionForm. form, HttpServletRequest request, HttpServletResponse response)  throws Exception  {   Locale locale = getLocale(request);   MessageResources messages = getResources(request);   HttpSession session = request.getSession();   UserForm. userform. = (UserForm) form;   //此处可以调用其他类来执行数据库写入或其他逻辑判断  // 如果UserForm传来的参数name的值为默认的lpw,将forward到failed,   // 该名称将到struts-config.xml的中寻找映射的url地址   // (可以是绝对路径,也可以是相对路径),对于本例,是转到failed.cool,   // 还记得吗?后缀为cool的请求全部到action-mappings中寻找  // 对应的action处理,最终目录是wuwu.jsp*/   if( "lpw".equals(userform.getName()) )    return (mapping.findForward("failed"));   else    return (mapping.findForward("regist"));  } } 五、以下所有新增或修改的页面相当于struts的View部分,把首页index.jsp改成: 站点导航
用户:
密码:
  六、增加hello.jsp,用于站点导航:

site map

The following is content filling by reader   七、增加wuwu.jsp,当没有新用户登陆时,将转到这个页面: 现有用户:
密码:
  没有得到新的用户!   八、增加regist.jsp,当有新用户登陆时,将转到这个页面: 新用户帐号:
密码:   九、启动tomcat4,浏览器中键入http://localhost:8080/test/index.jsp,操作一下,就可以看到结果,并初步理解struts的M、V、C各部分的协同工作原理,当然这是作者的良好意愿,如果读者看得一头雾水,欢迎指出错误在哪里 :)

<!--

Struts入门经验

silver6 | 19 十月, 2005 15:56

一个实例: 一个用户注册系统,用户通过网页输入相关信息:注册ID号,密码,EMAIL,若注册成功,则返回成功提示信息,反之出现注册失败提示信息。
以下是相关文件的部分核心代码。

项目建立:
正式开发前,需要在Tocmat(我的tomcat装在c:tomcat)中建立此项目。比较快的一种建立方式为:在C:tomcatwebapps下新建目录test,再将C:tomcatwebappsstruts-example下的
WEB-INF目录拷贝到test目录下,然后将testWEB-INF下的src和classes目录清空,以及struts-config.xml文件中内容清空即可。这样,我们需要的Struts类包及相关的配置文件就都齐了。
开发时,将JSP文件放在test目录下,Java原文件放在testWEB-INFsrc下,编译后的类文件放在testWEB-INFclasses下。

注册页面:reguser.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="/WEB-INF/Struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/Struts-html.tld" prefix="html" %>


RegUser























Logname:



Password:



E-mail:











此JSP页面不同于普通的JSP页,因为它大量运用了taglib,这些taglib对初学者而言,可能难于掌握,可这却是Struts的精华之一。灵活运用,将大大提高开发效率。

Struts-config.xml:



type="org.cjea.Struts.example. RegUserForm. "/>


type=" org.cjea.Struts.example.RegUserAction "
attribute=" regUserForm. "
scope="request"
validate="false">






Struts的核心是Controller,即ActionServlet,而ActionServlet的核心就是Struts-config.xml,Struts-config.xml集中了所有页面的导航定义。对于大型的WEB项目,通过此配置文件即可迅速把握其脉络,这不管是对于前期的开发,还是后期的维护或升级都是大有裨益的。掌握Struts-config.xml是掌握Struts的关键所在。

FormBean:RegUserForm

package org.cjea.Struts.example;

import javax.Servlet.http.HttpServletRequest;
import org.apache.Struts.action.ActionForm;
import org.apache.Struts.action.ActionMapping;

public final class RegUserForm. extends ActionForm{

private String logname;
private String password;
private String email;

public RegUserForm(){
logname = null;
password = null;
email = null;
}

public String getLogName() {
return this.logname;
}
public void setLogName(String logname) {
this.logname = logname;
}
public void setPassWord(String password) {
this.password = password;
}
public String getPassWord() {
return this.password;
}
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return this.email;
}

public void reset(ActionMapping mapping, HttpServletRequest request)
{
logname = null;
password = null;
email = null;
}
}

每一个FormBean 都必须继承ActionForm类,FormBean是对页面请求的封装。即把HTTP request 封装在一个对象中,需要说明的一点就是多个HTTP request可以共用一个FormBean,便于维护和重用。

ActionBean:RegUserAction

package org.cjea.Struts.example;

import javax.Servlet.http.*;
import org.apache.Struts.action.*;

public final class RegUserAction extends Action
{

public ActionForward perform(ActionMapping mapping,
ActionForm. form, HttpServletRequest req,
HttpServletResponse res)
{
String title = req.getParameter("title");
String password = req.getParameter("password");
String email = req.getParameter("email");
/*
取得用户请求,做相应数据库操作,略
*/
}
}

FormBean的产生是为了提供数据给ActionBean,在ActionBean中可以取得FormBean中封装的数据,经相应的逻辑处理后,调用业务方法完成相应业务要求。

Servlet的演变:在常规的 JSP,Servlet,JavaBean三层结构中,JSP实现View的功能,Servlet实现Controller的功能,JavaBean实现Model的实现。

在Struts中,将常规情况下的Servlet拆分与ActionServlet、FormBean、ActionBean三个部分。ActionServlet配合Struts-config.xml,专职完成页面导航,而不再负责具体的数据获取与相应逻辑,这两部分功能由FormBean和ActionBean来完成。

Struts优缺点
优点:
Struts跟Tomcat、Turbine等诸多Apache项目一样,是开源软件,这是它的一大优点。使开发者能更深入的了解其内部实现机制。
除此之外,Struts的优点主要集中体现在两个方面:Taglib和页面导航。Taglib是Struts的标记库,灵活动用,能大大提高开发效率。另外,就目前国内的JSP开发者而言,除了使用JSP自带的常用标记外,很少开发自己的标记,或许Struts是一个很好的起点。
关于页面导航,我认为那将是今后的一个发展方向,事实上,这样做,使系统的脉络更加清晰。通过一个配置文件,即可把握整个系统各部分之间的联系,这对于后期的维护有着莫大的好处。尤其是当另一批开发者接手这个项目时,这种优势体现得更加明显。
缺点:
Taglib是Struts的一大优势,但对于初学者而言,却需要一个持续学习的过程,甚至还会打乱你网页编写的习惯,但是,当你习惯了它时,你会觉得它真的很棒。
Struts将MVC的Controller一分为三,在获得结构更加清晰的同时,也增加了系统的复杂度。
Struts从产生到现在还不到半年,但已逐步越来越多运用于商业软件。虽然它现在还有不少缺点,但它是一种非常优秀的J2EE MVC实现方式,如果你的系统准备采用J2EE MVC架构,那么,不妨考虑一下Struts。

Struts实施经验:
1、基于Struts架构的项目开发,首先需要有一个很好的整体规划,整个系统中包括哪几个模块,每个模块各需要多少FormBean和ActionBean等,而且最好有专人负责Struts-config.xml的管理。开发基于Struts的项目的难点在于配置管理,尤其是对Struts-config.xml的管理

2、如果你的项目非常紧,并且项目组中又没有富有经验的Struts开发人员,建议不要冒然采用Struts。Struts的掌握需要一个过程,对于一个熟练的JSP程序员,自学大概需要半个月左右的时间。如果结合titls,则需要更长的时间

3、如果你在网页中大量运用taglib,那么你的美工将做出部分牺牲。当你结合Tiles,功能增强的同时,这种牺牲尤为明显。当然,你对功能和美观的取舍由你自己决定

4、Taglib是一个好东西,但灵活运用它却需要一个过程,如果你不想在Taglib上花太多的时间,那么只需理解与FORM有关的几个标记,其它的标记就放着吧,以后再看,先去研究ActionServlet和Struts-config.xml,你会觉得很有成就感

5、Struts是否只适合于大型项目呢?No!Struts适合于各种大小的项目,当然,对于大型项目,它所体现出来的优势更加明显。

<!--

java实现图片验证代码

silver6 | 18 十月, 2005 11:49

java实现图片验证的完整代码,有待验证,觉得还成,保留先 package util; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; /** * 描述: * * @author $author$ * @version $Revision$ */ public class PicCheckCode extends HttpServlet { private Font mFont = new Font("Arial Black", Font.PLAIN, 15); //设置字体 private int lineWidth = 2; //干扰线的长度=1.414*lineWidth private int width = 60; //定义图形大小 private int height = 20; //定义图形大小 private int count = 200; /** * 描述: * * @param fc 描述: * @param bc 描述: * * @return 描述: */ private Color getRandColor(int fc, int bc) { //取得给定范围随机颜色 Random random = new Random(); if (fc > 255) { fc = 255; } if (bc > 255) { bc = 255; } int r = fc + random.nextInt (bc - fc); int g = fc + random.nextInt (bc - fc); int b = fc + random.nextInt (bc - fc); return new Color(r, g, b); } //处理post public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet (request, response); } /** * 描述: * * @param request 描述: * @param response 描述: * * @throws ServletException 描述: * @throws IOException 描述: */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //response.reset(); //设置页面不缓存 response.setHeader ("Pragma", "No-cache"); response.setHeader ("Cache-Control", "no-cache"); response.setDateHeader ("Expires", 0); response.setContentType ("image/gif"); // 在内存中创建图象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获取图形上下文 Graphics2D g = (Graphics2D) image.getGraphics (); //生成随机类 Random random = new Random(); // 设定背景色 g.setColor (getRandColor (200, 250)); //---1 g.fillRect (0, 0, width, height); //设定字体 g.setFont (mFont); //画边框 g.setColor (getRandColor (0, 20)); //---2 g.drawRect (0, 0, width - 1, height - 1); //随机产生干扰线,使图象中的认证码不易被其它程序探测到 for (int i = 0; i

<!--

微软笔试唯一一道C#题

silver6 | 18 十月, 2005 11:47

C#的内存处理和C++有什么不同。。。
这是唯一一道。。。

其他都是C++

1.Basic
考的都是一些基本的知识,如操作系统,网络,不难,可惜很多都忘了。。。
2.推理题
跟GRE的逻辑部分一样,一道逻辑推理,两道分析推理,以前做过的话感觉会好些
3.2个编程题,第一个找一个数组所有数字的最大公约数,第二道是在一个字典中查找所有以所给字母开头的单词。
4.写写对MSN的看法,有什么改进意见。
5.一个循环链表检测程序,挑bug
还要写一些test case 。


<!--

2个面试题目

silver6 | 18 十月, 2005 11:44

1. a)下面的代码输出是什么,为什么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b>6)?puts(">6"):puts("<=6");//puts为打印函数
}
b)运行下面的函数会有什么结果?为什么?
void foo(void)
{
char string[10],str1[10];
int i;
for(i=0;i<10;i++)
{
str1[i] = 'a';
}
strcpy(string, str1);
printf("%s",string);
}

2. 编写strcpy函数
已知strcpy函数的原型是
char *strcpy(char *strDest, const char *strSrc);
其中strDest是目的字符串,strSrc是源字符串。
a)不调用C++/C的字符串库函数,请写出函数strcpy。
b)strcpy能把strSrc的内容复制到strDest,为什么还要char* 类型的返回值?


我的回答是:1.1 输出 >6 因为int b 被强制转换为unsigned int 型,所以变成一个很大的正数;
1.2 由于str1末尾没有‘’结束标志,所以strcpy不知道拷贝到何时结束,会造成内存泄漏。
2. char *strcpy(char *strDest, const char *strSrc)
{
int len;
char* p=strSrc;
while(!*p++)
len++;
strDest=new char[len+1];
assert(!strDest)
while(!*strSrc)
*strDest++ = *strSrc++;
strDest[len]='';
return strDest;
}

高手看看,不知道做的对不对?

2. char *strcpy(char *strDest, const char *strSrc)
{
int len;
char* p=strSrc;
while(!*p++)
len++;
strDest=new char[len+1]; //你在这分配了空间 由谁来释放啊??
assert(!strDest)
while(!*strSrc)
*strDest++ = *strSrc++;
strDest[len]='';
return strDest;
}

8.解:这是出现频率最高的笔试题,应该源自于林锐的《C/C++高级编程指南》
关键字:C++,strcpy,字符串,复制,拷贝,copy,笔试,试题
题目:
已知strcpy函数的原型是:
char * strcpy(char * strDest,const char * strSrc);
1.不调用库函数,实现strcpy函数。
2.解释为什么要返回char *。
解说:
1.strcpy的实现代码
char * strcpy(char * strDest,const char * strSrc)
{
if ((strDest==NULL)||(strSrc==NULL)) //[1]
throw "Invalid argument(s)"; //[2]
char * strDestCopy=strDest; //[3]
while ((*strDest++=*strSrc++)!=''); //[4]
return strDestCopy;
}
错误的做法:
[1]
(A)不检查指针的有效性,说明答题者不注重代码的健壮性。
(B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),
说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char *转换为bool即是类
型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以
C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。
(C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使
用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单
,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程
序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出
来。
[2]
(A)return new string("Invalid argument(s)");,说明答题者根本不知道返回值
的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危
险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释
放内存,这导致内存泄漏。
(B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调
用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和
异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这
样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。
[3]
(A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。
[4]
(A)循环写成while (*strDest++=*strSrc++);,同[1](B)。
(B)循环写成while (*strSrc!='') *strDest++=*strSrc++;,说明答题者对边界
条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上''。
2.返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同
样功能的函数,如果能合理地提高的可用性,自然就更加理想。

char *strcpy(char *strDest, const char *strSrc)
{
if(strDest == NULL || strSrc == NULL)
{
return NULL;
}
char* temp = strDest;
while((*strDest++ = *strSrc++) != '');
return temp;
}
返回的指针是strDest的初始值
strDest在strcpy中会改变


<!--

Struts提供的HTML标签库

silver6 | 15 十月, 2005 12:01

继续学习Struts提供的HTML标签库。 by Budi Kurniawan 在本文系列的第一部分中我讲述了如何使用Struts提供的HTML标签库来配置一个Struts应用程序。我还介绍了该标签库中的一类标签:独立使用的标签。在第二部分中我将继续介绍第二类标签:与form相关的标签。 与form相关的标签包括 标签本身以及所有必须包含在其中的标签。比如,和标签就是和form相关的标签,因为如果不把它们放到一个form中它们就没有意义。 标签标签用于生成一个HTML form。使用该标签时必须遵循许多规则。 首先,标签中必须包含一个action属性,它是这个标签中唯一必需的属性。如果不具备该属性则JSP页面会抛出一个异常。之后你必须给这个action属性指定一个有效值。一个有效值是指应用程序的Struts配置文件中元素里的任何一个子元素的访问路径。而且相应的元素中必须有一个name属性,它的值是form. bean的名称。 例如,如果你有这样一个标签: 那么你的Struts配置文件的元素中必须有一个如下显示为粗体的元素: . . . 这就是说一个form标签是和form. bean相关联的。 另一个要遵循的规则是:任何包含在 中用来接收用户输入的标签(、、、、
Password:
注意,

标签中method属性的缺省值是POST。另外,有没有看到这个标签库是如何建立JavaScript来定焦到password元素上的? 这也是该库让人着迷的地方之一。你不用担心如何在客户端进行编程,它会帮你自动生成。 在运行前面的例子时还要注意,你必须有一个包含userName和password属性的相关form。 标签 标签用于生成一个文本的输入区域。它必须包含和相关form. bean中的相同属性对应的“property”属性。该标签只有在嵌入到一个标签中时才有效。 例如: 会被转换成: 标签 标签用于生成一个口令字(type password)的输入区域。它必须包含和相关form. bean中的相同属性对应的“property”属性。该标签只有在嵌入到一个标签中时才有效。该标签中的一个很重要的属性是“redisplay”,它用于重新显示以前输入到这个区域中的值。该属性的缺省值为true。然而,为了使password不能被重新显示,你或许希望将该属性的值设为false。 例如: 会被转换成: 标签 标签用于生成一个隐藏文本的输入区域。它必须包含和相关form. bean中的相同属性对应的“property”属性。该标签只有在嵌入到一个标签中时才有效: 例如: 会被转换成:
全部评论

注册时间:2007-12-16

  • 博文量
    12
  • 访问量
    330785