在进行Web应用程序开发时,一些Java程序员可能自己编写HTML语言,而有的则会交给专门的页面设计人员来编写。
关于HTTP,HTML和User Agents更多知识可参考以下资源:
- Getting started with HTMLDave
Raggett著;
- 在Java Web Services Tutorial中的HTTP Overview
;
- HTTP/1.1规范
;
- HTTP Basic and Digest Authentication 规范
;
- State Management Mechanism规范(Cookies)
;
0.3 HTTP请求响应周期
对于Web开发人员来说,对HTTP的最关心的就是HTTP的请求响应周期,使用HTTP提交一个请求,然后HTTP服务器(如Web服务器)返回一个响应。当我们进行Web开发设计时,我们设计成一个HTTP请求对应返回一个HTTP响应。Struts框架就是对这一周期进行抽象,而对我们来说更重要的是应该知道这一幕后发生的事情。
如果你对HTTP请求响应周期并不熟悉,那么我们强烈推荐你去读一读Java Web Services Tutorial中的HTTP Overview
0.4 Java语言和应用程序框架
Struts框架是用时下最流行的万能编程语言(译者注:这么形容Java语言我觉得一点也不为过)Java写成的。Java是面向对象的编程语言,Struts正是利用了它的面向对象这一技术。另外还有,Java自身对线程的良好支持,可以在同一时刻执行多项任务。很好的理解Java语言,面向对象编程和线程,对我们掌握Struts和使用本用户指南大有裨益。
学习Java语言和线程可以参考以下资料:
- The Java Tutorial之Learning the Java Language
;
- The Java Language Tutorial之Learning the Threads之Doing Two or More Tasks At Once
;
即使你已经使用过Java和面向对象的编程,创建和使用应用程序框架对你编程也是大有帮助的。有关应用程序框架的更多知识,可以参考下面两本白皮书:
- Designing Reusable Classes
Ralph E. Johnson 和Brian Foote著;
- Object-Oriented Application Frameworks
Mohamed Fayad和Douglas C. Schmidt著;
如果你正在找一个服务器端框架那么这两页可能对你有些帮助:1和2
0.5 JavaBeans
正像许多Java应用程序一样,大多Struts对象也被设计为JavaBean。使用JavaBean设计模式使Struts类更易被Java开发人员和Java部署工具使用。
JavaBan最初只是为可视化元素编程而创建的,现在这种对象设计模式已经被广泛地应用到更多可重用组件的基础设计中,如Struts框架。
关于JavaBean更多知识,可参考:
- java.sun.com中的The JavaBeans Component Architecture Documentation
和JavaBeans 1.01 Specification
;
- The Java Tutorial中的The JavaBean Trail
;
- The Java Web Services Tutorial中的JavaBeans Components in JSP Pages
;
0.5.1 反射和内省机制
反射就是确定对象的哪个成员变量或方法是可用的一种处理机制。内省是JavaBean API使用的一种特殊形式的反射。使用内省我们可以知道JavaBean的哪些方法是可以被其他对象访问的。
Struts框架使用内省机制把HTTP参数转换为JavaBean属性和使用JavaBean属性组装HTML表单域。这项技术使在JavaBean和HTML表单域之间进行“双向访问”属性更加简单。
关于反射和内省更多,请参考:
0.5.2 映射(Maps)
JavaBean通过使用属性来存储数据而在其他方法中操作这些数据。JavaBean是一个便捷而有强大的对象,但它不是编程人员用来存储数据的对象唯一选择。另外一个流行的对象就是映射(Map)java.util.map?。一个映射就是一个简单的名称值对集合。映射常在“幕后”作为存储动态数据的一种便捷方法。
0.5.3 动态Bean(DynaBeans)
动态Bean集JavaBean的可扩展性和Map的灵活性于一身。我们知道即使要定义一个简单的JavaBean,也要新建一个类,定义一个属性变量,还有编写每个属性对应的两个访问方法(setXXX和getXXX)。而动态Bean则可以通过XML配置文件来定义属性,动态Bean的虚拟属性并不能像普通的Java方法一样来调用,而是要通过组件使用反射(Reflection)和内省(introspection)机制来进行访问。
在Struts框架中,你可以使用动态Bean来描述一个HTML表单。这一个策略避免了我们要为一些简单的表单域创建正式JavaBean子类。
关于动态Bean更多,请参考:
- Jakarta Commons项目的BeanUtils的Package Description
和Javadocs;
0.6 属性(Properties)文件和资源绑定(Resourse Bundles)
很多Java应用程序(包括Web应用程序在内)经常通过属性文件进行一些配置。属性文件是Struts框架用于给应用程序提供消息资源资源绑定
的基础所在。
关于属性文件更多,请参考:
- The Java Tutorial中的Using Properties to Manage Program Attributes
- Java资源绑定是根据用户区域(Locale)
通过一个或多个属性文件为用户提供国际化支持。Struts从一建立开始就对应用程序的本地化有很好的支持。
- 关于本地化和资源绑定的更多,请参考:
- The Java Tutorial 中的About the ResourceBundle Class
0.7 Java Servlet
由于Java是一种面向对象的编程语言,所以Java Servlet平台就把HTTP强制造型(或构造)为面向对象的形式。这一策略使得Java开发人员省下更多的时间去处理自己的应用程序的功能上,而不是放在HTTP的机制处理上。
HTTP提供了一套扩展服务器的基本机制,即公共网关接口(Common Gateway Interface,CGI)。服务器可以传递一个请求给CGI程序,然后CGI程序返回一个响应。同样,一个Java服务器传递一个请求给一个Servlet容器,容器可以对请求作一些处理,也可以把这个请求直接返还给HTTP服务器,容器检查它的Servlet列表来决定是否要对这个请求进行处理,如果请求注册了一个Servlert,那么容器就把这请求转交给这个Servlet。
当一个请求进入时,容器检查该请求是否注册了Servlet,如果找到一个匹配的Servlet,容器就把这个请求传给这个Servlet,如果没有,请求就被返还给HTTP服务器。
容器的职责就是管理Servlet的生命周期,创建Servlet,调用Servlet,最后释放Servlet。
一般情况下一个Servlet是[javax.servlet.http.HttpServlet]的一个子类,一个Servlet必须实现容器需要调用的四个方法:
- public void init(ServletConfig config):当Servlet实例第一次被创建时和执行所有请求之前Servlet容器调用这个方法;
- public void doGet(HttpServletRequest request,HttpServletResponse response)此方法用于处理一个使用HTTP GET 协议的请求,并生成一个相应的动态响应;
- public void doPost(HttpServletRequest request HttpServletResponse response)此方法用于处理一个使用HTTP POST协议的请求,并生成一个相应的动态响应;
- public void destroy() 当Servlet实例中止服务时容器调用这个方法,诸如当Web应用程序正在被undeploy或当整个容器被shut down时;
Struts框架已为我们的应用程序提供一个现成Servlet[org.apache.struts.action.ActionServlet]。作为一个Struts应用程序开发人员,在使用Struts框架的ActionServlet实例的同时,了解Servlet的基础知识和明白它在Web应用程序所扮演的角色也是相当重要。
关于Servlet的更多知识,请参考:
- java.sun.com中的The Java Servlet Technology
;
- java.sun.com中的The Servlet 2.2 and 2.3 Specifications
;
- The Java Web Service Tutorial的Java Servlet Technology
;
- The Java Web Service Tutorial的Web Applications
;
0.7.1 Servlet和Thread
为了提高性能,容器支持多线程Servlet。一个具体的Servlet只能创建一个实例,通过同一个对象为注册了这个Servlet的每个请求服务。这一个策略可以使容器充分利用系统资源,与此同时也就必须考虑Servlet的doGet和doPost方法编码的线程安全问题。
关于Servlet与线程安全的更多资料,请参考:
- The Java Web Service Tutorial中的Controlling Concurrent Access to Shared Resources
;
0.7.2 Servlet上下文(Context)
ServletContext接口[javax.servlet.ServletContext]提供正在运行的Servlet所处的Web应用程序的上下文(或环境)的视图。Servlet可以通过getServletConfig()方法访问,而JSP页面可以通过隐含变量application变量获得。Servlet上下文提供的几个API在创建Struts Web应用程序时是相当有用的。
- 访问Web应用程序资源:Servlet可以通过getResource()和getResourceAsStream()方法访问Web应用程序内的静态资源文件;
- Servlet上下文属性:上下文可以用来存储Java对象,通过字符串值的key来识别对象,这些属性对整个Web应用程序都是全局的,Servlet可以通过getAttribute(),getAttributeNames(),removeAtrribute()和setAttribute()方法进行访问。对JSP页面来说,Servlet上下文属性相当于“应用程序作用域Bean”;
关于Servlet上下文的更多信息,请参考:
- The Java Web Services Tutorial中的Accessing the Web Context
;
0.7.3 Servlet请求
每个Servlet处理的请求用一个Java接口代表,一般是HttpServletRequest接口 [javax.servlet.http.HttpServletRequest]。这个请求接口提供了一套访问包含在底层HTTP请求内的所有信息的面向对象机制,包含:
- Cookie:通过getCookie()方法获得包含在请求中的有效Cookie集;
- 头:可以通过名称访问包含在请求中的HTTP头。你可以枚举包含的所有的HTTP头的名称;
- 参数:请求参数,可以通过名称访问包含在URL的查询字符串中(doGet)或包含在请求内容中(doPost)的请求参数;
- 请求特征:输入HTTP请求的一些其他特征,诸如GET或POST方法使用的协议规格("http" 或"https"),等等;
- 请求URI信息:通过getRequestURI()方法可以获得原始的请求URL。另外,Servlet容器把请求URL解析为一些可以单独访问的组成部分(contextPath、 servletPath和 pathInfo);
- 用户信息:如果你使用了用户管理的安全,那么你就可以查找一个已认证用户名,获得一个代表当前用户的Principal对象,还有当前用户是否被授权为一个特定角色;
另外,Servlet请求还支持请求属性(在JSP中,就是请求作用域Bean),类似于前面讲到的Servlet上下文属性。请求属性常用于业务逻辑层和视图层之间状态信息通信,业务逻辑层产生这些状态信息,视图层使用这些信息产生相应的响应。
Servlet容器会确保一个具体的请求被一个单独线程的Servlet处理,所以你就不必担心在访问Servlet请求的属性时有关线程安全的问题。
关于Servlet请求的更多,请参考:
- The Java Web Tutorial中的Getting Information from Requests
;
0.7.4 Servlet响应
一个Servlet的主要目的就是处理一个输入的Servlet请求[javax.servlet.http.HttpServletRequest],并生成对应的响应。生成响应的过程是通过调用Servlet响应接口[javax.servlet.http.HttpServletResponse]相应的方法来完成的,可用的方法如下:
- 设置HTTP头:你可以设置包含在响应中的HTTP头信息。最重要的HTTP头信息就是Content-Type,它告诉你的客户端包含在响应体中信息是哪种类型的,一般情况下,设为text/html类型就是HTML页面,或设为text/xml类型就是XML文档;
- 设置Cookies:你可以向当前的响应中增加Cookie;
- 发送错误响应:你可以使用sendErro()发送一个HTTP错误状态信息(代替一般的页面内容);
- 重定向到其他资源:你可以使用sendRedirect()方法重定向客户端到你指定的其他URL资源上去;
使用Servlet响应API的一个重要原则就是调用维护头信息和Cookies所有方法都必须在缓存的全部响应内容第一次被更新给客户端之前完成。原因是因为这些信息都是作为HTTP响应最开始部分被传输的,因此试图在头信息已被送出之后再添加头信息,必然是徒劳的。
使用Model 2模式的应用程序的表现层,你可能不直接使用Servlet 响应APIs来生成响应。一般是使用JSP页面来完成,在Servlet容器中JSP页面将被JSP编译器转换为Servlet,由这个JSP Servlet生成响应,其中可能包含一些JSP标签生成的动态信息。
其他的表现系统,诸如Struts工具Velocity框架,可能把生成响应的任务代理给一个专门的Servlet来完成,但是原理是相同的。你创建一个模板,然后动态的响应由模板动态生成。
关于Servlet响应的更多,请参考:
- The Java Web Tutorial中的Constructing Responses
;
0.7.5 过滤器(Filtering)
如果你使用2.3版或更新规范的Servlet容器(如Tomcat4.x),你可以使用新的过滤器APIs[javax.servlet.Filter]组合一些组件来处理请求和生成响应。过滤器其实是一个过滤器链的集合,每个过滤器都可以处理请求和生成响应,然后把处理权交给下一个过滤器,最后调用Servlet。
Struts 1.x系列(1.0,1.1版本等)仅支持2.2版本或更早的Servlet规范的Servlet容器,所以Struts自身并没有使用过滤器。下一代的Struts(2.x系列)是基于Servlet2.3或更新规范的。Struts 2.x版可能会使用到过滤器。
关于过滤器更多,请参考:
0.7.6 会话(Session)
HTTP最关键的特征就是无状态性。换句话说就是,HTTP内建机制无法识别同一个用户在后续请求和它的前继请求是同一个用户。这就使得建立一个跨请求的用户交互的应用程序变得相当困难!
为了克服这个困难,Servlet APIs提供了一个编程概念—会话(Session),用一个实现了[javax.servlet.http.HttpSession]接口的对象表示。Servlet容器将使用Cookies或重写URL两项技术中之一来确保同一用户的会话的会话ID包含在下一个请求中,这样就使保存在会话中的状态信息可以关联到多个请求上。状态信息被保存在会话属性(session attributes)中,在JSP页面中,就是“会话作用域Bean”。
为了避免一个用户在未能完全完成一个交互时造成永久占用资源,会话可以配置会话的超时时间间隔。如果两个请求间的时间间隔超过配置的超时时间间隔,会话将超时,所有的会话属性将被删除。你可以在Web应用程序的配置描述符文件中定义一个默认的会话超时时间间隔,也可以在具体的会话中通过调用setMaxInactiveInterval()方法来动态更改超时时间间隔。
会话和请求不同不同之处在于,在使用会话属性时应当考虑线程安全的问题,而请求属性不用。(不仅是会话自身getAttribute()和setAttribute()方法,还有这些Bean提供的所有方法)会话使同一用户的多个同步请求变得出奇的容易,因为它们只要访问同一个会话就可以了。
另一个应该考虑的问题是请求间的会话属性要占用一定的服务器内存资源,这可能会影响系统支持的同步用户数。如果你的应用程序需要支持大量的同步用户数,那么你应该尽可能地最小程度地使用会话属性,从而控制你的整个应用程序对内存需求。
关于会话更多,请参考:
- The Java Web Tutorail中的Maintaining Client State
;
- javax.servlet.http.HttpSession
;
0.7.7 分发请求(Dispatching Requests)
Java Servlet规范通过在资源之间分发、转发请求来扩展HTTP的请求/响应周期。Struts框架使用Servlet的这一特性让一个请求在几个特定的专用组件之间游走,每个组件都可能影响响应的内容。一般的过程是这样的,一个请求先被控制器组件抓住,接着被传给模型组件,最后被交给视图组件,这可能仅仅是一个单独的请求/响应周期的一部分。
0.7.8 Web应用程序
不仅一个HTTP服务器可以宿主多个单独的Web站点,Servlet容器也可以为多个Web应用程序提供服务。Java Servlet平台对组织和部署Web应用程序有明确的机制。每个Web应用程序运行在属于自己的命名空间中,可以进行单独开发,单独部署。一个Web应用程序可以打成一个Web应用程序文件,或叫WAR文件。单独的WAR文件可以被上传到服务器上并自动进行部署。
关于Web应用程序更多,请参考:
- The Java Web Tutorial中的Web Applications
;
0.7.9 Web应用程序配置描述符文件(web.xml)
应用程序的生命周期中属性和事件都可以通过Web应用程序配置描述符文件XML文件进行配置。配置文件web.xml的模式(schema)由Java Servlet规范给出。
关于web.xml和应用程序生命周期中的事件,请参考:
- The Java Web Tutorial中的Web Application Life Cycle
;
0.7.10 安全(Security)
在Web应用程序配置文件中可以配置容器管理的安全。声明级的安全可以保护匹配一定模式的URI的请求。编程级安全用于进行微观的安全控制,如基于时刻、调用的参数或Web组件内部状态的授权控制;或是基于数据库的约束验证。
关于容器管理的安全更多,请参考:
- The Java Web Tutorial中的Web Application Security (Chapter 24)
;
0.8 JSP、JSP标签库和JSF
JSP其实本质上也是Servlet,它是使创建和维护动态Web页面更容易的Servlet。JSP页面中除了其中特定的Java语句外所有都将被写入到HTTP响应中,代替使用Java的print语句写HTTP响应。
使用JSP,你可以从一个标准的HTML页面开始,然后再使用Java语言或 JSP标签增加一些动态特性。Struts框架本身包含有一些JSP标签库,可以使你在JSP页面中很轻松地访问到框架的特征。
关于JSP和自定义JSP标签库,请参考:
- java.sun.com的JSP技术
页;
- java.sun.com的JSP1.1和1.2规范
下载页;
- The Java Web Services Tutorial中的JSP技术
;
- The Java Web Services Tutorial中的JSP自定义标签
;
许多时候JSP标签是协同JavaBean一同使用的,应用程序发送一个JavaBean给JSP页面,JSP标签使用Bean为当前用户定制页面。关于更多,请参考The Java Web Tutorial中的JSP中的JavaBean组件
Struts可以很好的和新的JSP标准标签库(JSTL)配合使用,同时也和其他的标签库也有很好的兼容,如JSP Tags
和 Jakarta Taglibs
。
还有一些其他的有用工具包可以使Struts框架使用更加容易,如XSLT和Velocity Templates
在Java地平线上最新的一颗新星就是Java Server Faces。JavaServer Faces技术简化了JavaServer应用程序(包括Web和桌面)的用户界面的创建。虽然JSF规范还处于开发阶段,但在Java Web Services Developer Pack
已经包含了可用的最初参考实现版本。同样,Struts框架的JSF标签库Struts-Faces
也通过夜以继日的努力完成了最初版。
JSF和Struts框架是完全兼容的。随着JSF规范的最终定案,Struts/JSF整合工具也陆续出现,并得到了广泛地传播使用。
关于JSTL和JSF更多,请参考:
- Practical JSTL, Part 1
-Sue Spielman著;
- JSF Central
- JSF资源;
- JavaServer Faces Resources
- James Holmes dot Com;
0.9 XML语言
Struts框架提供的许多对象都是通过部署XML配置文件来提供的。配置Java Web应用程序也是通过XML文件提供的。
关于XML配置文件和Java Web应用程序更多,请参考:
- The Java Web Tutorial 中Configuring Web Applications
;
关于如何在普通的Java应用程序中使用XML文件,可以参考The Java Web Services Tutorial 中的Java API for XML Processing。Struts框架的内部充分地使用了这个API,Struts开发人员在开发自己的应用程序时可能会用不到。
0.9.1 描述符(Descriptors)
当Java应用程序使用XML配置文件时,元素常被用作描述符,应用程序不直接使用XML的元素。这些元素用于创建和配置(或部署)Java对象。
Java Servlet平台使用XML配置文件部署Servlet。同样Struts框架也使用XML文件部署框架使用的对象。
0.10 其他层(layers)
Struts框架提供Web应用程序的控制器层,开发人员可以使用其他一些标准技术提供数据访问层和表现层来协同控制器层一起工作。常用的流行数据访问技术包括:
表现层技术包括:
0.11 JAAS
Struts框架可以使用许多方法用于用户认证和授权,Struts1.1和以后版本支持标准的Java认证和授权服务(JAAS)。你可以指定Action间的安全角色。
关于JAAS的更多,请参考Javasoft product page和Java Web Services Tutorial
的Web Application Security
一章