每一个web应用的WEB-INF路径下的web.xml文件被称为配置描述符,这个web.xml对于Java Web非常重要,每个Java Web应用都必须包含一个web.xml文件,且必须放在WEB-INF路径下。
对于Java Web应用而言,WEB-INF是一个特殊的文件夹,Web容器会包含该文件夹下的内容,客户端浏览器无法访问WEB-INF下的任何内容。
Java Web应用的绝大部分内容都由web.xml文件来配置管理,下面的内容都需要通过web.xml文件进行配置管理:
配置Jsp
配置和管理Servlet
配置和管理Listener
配置和管理Filter
配置标签库
配置JSP属性
除此之外,web.xml还负责配置、管理如下常用的内容:
配置和管理JAAS授权认证
配置和管理资源引用
Web应用首页
另外,每一个web框架都应该在web.xml中配置成一个servlet或者是filter,这样这个框架才会在这个web项目中产生作用。
添加struts2的应用:
在web.xml中添加struts2的核心Filter。
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!--定义Struts2的FilterDispatcher的Filter--> <filter> <!--定义核心Filter的名字--> <filter-name>Struts2</filter-name> <!--定义核心Filter的实现类--> <filter-class>Struts2.dispatcher.FilterDispatcher</filter-class> </filter> <!--FilterDispatcher用来初始化Struts2并且处理所有请求--> <filter-mapping> <filter-name>Struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>在web.xml文件中定义Servlet或者Filter拦截用户请求,通常这个Servlet或Filter是该框架的核心,负责拦截所有用户的请求。
由于Web应用是基于请求/相应架构的应用,所以不管哪个MVC Web框架,都需要在web.xml中配置该框架的核心Servlet或Filter,这样才可以让该框架介入Web应用中。
在web的类加载路径下防止struts.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <!--指定全局国际化资源文件的base名--> <constant name="struts.custom.i18n.resources" value="messageResource" /> <!--指定国际化编码所使用的字符集--> <constant name="struts.i18n.encoding" value="UTF-8" /> </struts>上面配置文件中制定国际化资源文件的base名为messageResource,所以我们还应该为该应用提供一个messageResource_zh_CN.properties文件。
处理用户的请求:
核心的Servlet或者Filter接收到用户的请求后,通常会对用户请求进行简单预处理,例如解析、封装参数等,然后通过反射来创建Action实例,并调用Action制定的方法(Struts1通常是execute,struts2可以是任意方法)来处理用户请求。
这里又有一个问题,当filter拦截到用户请求后,它如何知道创建哪个Action实例呢?这里有两种解决方案:
(1)利用配置文件:
(2)利用约定:称为“零配置”
常量配置:
struts2除了使用struts2.xml文件来管理配置外,还可以使用struts.properties文件来管理配置,该文件定义了Struts2框架的大量属性,开发者可以通过改变这些属性来满足应用的需求。同样只要将struts.properties文件放在Web应用的类加载路径下,Struts2框架就可以加载该文件。其中的default.properties文件在struts-core的jar包中org/apaceh/struts2/目录下的default.properties文件,修改该文件中的配置就可以修改对应的struts的配置。这个相见另一篇文章。呵呵~
Struts2会默认加载类加载路径下的struts.xml、struts-default.xml、struts-plugin.xml三类文件,其中struts.xml是开发者定义的默认配置文件,struts-default.xml是struts2框架自带的配置文件,而struts-plugin.xml则是struts2插件的默认配置文件。
有些开发者不喜欢使用struts.properties文件,Struts2也允许在struts.xml文件中管理struts2属性。在struts.xml文件中通过常量配置一样可以配置这些属性。如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <!--通过constant元素配置struts2的属性--> <constant name="struts.custom.i18n.resources" value="mess" /> <!--通过include属性导入其他配置文件--> <include file="struts-part1.xml"/> </struts>
除此之外,当我们在web.xml文件配置FilterDispatcher时也可以配置Struts2属性,此时采用为FilterDispatcher配置初始化参数的方式来配置struts2属性,如下代码:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!--定义Struts2的FilterDispatcher的Filter--> <filter> <!--定义核心Filter的名字--> <filter-name>Struts2</filter-name> <!--定义核心Filter的实现类--> <filter-class>Struts2.dispatcher.FilterDispatcher</filter-class> <init-param> <param-name>struts.custom.i18n.resources</param-name> <param-value>mess</param-value> </init-param> </filter> <!--FilterDispatcher用来初始化Struts2并且处理所有请求--> <filter-mapping> <filter-name>Struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
综上所述,struts2提供了三种方式来管理Struts2的属性:既可以通过struts.properties文件来配置Struts2属性;也可以通过在struts.xml文件中配置constant元素来配置Struts2属性;还可以在web.xml文件中配置Struts2属性。通常推荐在struts.xml文件中定义Struts2属性,而不是在struts.properties中定义,之所以保留properties文件,只是为了保持与WebWork的向后兼容性。
Action接口和ActionSupport基类:
struts2提供了一个Action接口,这个接口定义了Struts2的Action处理类应该实现的规范。
public interface Action { public static final String ERROR = "error"; public static final String INPUT = "input"; public static final String LOGIN = "login"; public static final String NONE = "none"; public static final String SUCCESS = "success"; public String execute() throws Exception; }
另外Struts2还提供一个Action接口的一个实现类,ActionSupport
ActionSupport是一个默认的Action实现类,该类里已经提供了许多默认方法,这些默认方法包含很多方法,如果继承了这个类,会大大降低开发的复杂度。
Struts2访问ServletAPI,一共有三种方式;
Strust2的action没有与任何的servletAPI耦合,这是struts2的一个改良之处,因为Action类不再与ServletAPI耦合,从而能更轻松地测试该Action。
但对于web应用的控制器而言,不访问ServletAPI几乎是不可能的,例如跟踪HTTPSession状态等。Struts2提供了一种更轻松的方式来访问ServletAPI。Web应用中通常需要访问的ServletAPI就是HTTPServletRequest、HTTPSession和ServletContext,这三个类分别代码JSP内置对象中的request、session和application。
方式一:Struts2提供了一个ActionContext类,Struts2的Action可以通过该类来访问ServletAPI
public String execute() { ActionContext ctx = ActionContext.getContext(); Integer counter = (Integer)ctx.getApplication().get("counter"); ctx.getApplication().put("counter",counter);//${applicationScope.counter} ctx.getSession().put("user",username);//${sessionScope.user} ctx.put("tip","服务器的提示信息");//${requestScope.tip} }
上述的Action成功操作request、session和application范围的属性。
方式二:Action直接访问ServletAPI
虽然struts2提供了ActionContext来访问ServletAPI,但这种访问毕竟不是直接获得ServletAPI的实例。为了在Action中直接访问ServletAPI,Struts2还提供了如下几个接口。
ServletContextAware//实现该接口的Action可以直接访问Web应用的ServletContext接口 ServletResponseAware//实现该接口的Action可以直接访问服务器响应的HttpServletResponse实例。 ServletRequestAware//实现该接口的Action可以直接访问用户请求的HttpServletRequest实例。
项目中的例子
public abstract interface IBaseAction extends Preparable, ServletResponseAware, ServletRequestAware { public abstract String list() throws Exception; public abstract String edit() throws Exception; public abstract String save() throws Exception; public abstract String delete() throws Exception; }
public class BaseAction extends ActionSupport implements IBaseAction { public HttpServletResponse response = null; public HttpServletRequest request = null; public void setServletRequest(HttpServletRequest arg0) { this.request = arg0; } @Override public void setBundleContext(BundleContext context) { this.context = context; } public void setServletResponse(HttpServletResponse arg0) { this.response = arg0; } }方式三:除了上述两种方法之外,Strut2还提供了一个ServletActionContext工具类,这个类包含了几个静态方法
static PageContext getPageContext() //:取得Web应用的PageContext对象 static HttpServletRequest getRequest()//:取得Web应用的HttpServletRequest对象 static HttpServletResponse getResponse()//:取得Web应用的HttpServletResponse对象 static ServletContext getServletContext()//:取得Web应用的ServletContext对象
借助于ServletActionContext类的帮助,开发者也可以在Action中直接访问ServletAPI,并可避免Action类需要实现XxxAware接口--虽然如此,但该Action依然与ServletAPI直接耦合,一样不利于高层次的解耦。
注意点:
虽然可以在Action类中获取HttpServletResponse,但如果希望通过HttpServletResponse来生成服务器响应是不可能的,因为Action只是业务控制器。即如果在Action中书写如下代码:
//用于在Servlet中直接生成响应的代码 response.getWriter().println("Hello World");
上面代码在标准的Servlet中会生成对客户端的响应,但在struts2的Action中没有任何实际意义。
struts支持下面几种结果类型:
Type的值可以填写如下几种:
1:chain Action链接的结果类型
2:chart 整合JfreeChart的结果类型
3:dispatcher JSP整合的结果类型
4:freemarker FreeMarker整合的结果类型
5:httpheader 控制特殊的HTTP行为的结果类型
6:jasper JasperReports整合的结果类型
7:jsf 与JSF整合的的结果类型
8:redirect 直接跳转到其它URL的结果类型
9:redurectAction 用于直接跳转到其它Action的结果类型
10:stream 向浏览器返回一个InputStrean(一般用于文件下载)
11:tiles 与Tiles整合的结果类型
12:velocity 与Vlocity整合的结果类型
13:xslt 与XML/XSLT整合的结果类型
14:plainText 用于显示某个页面的原始代码的结果类型
有一篇文档另有详细说明。
Struts2的零配置:在项目中的web.xml中
<filter> <filter-name>action2</filter-name> <filter-class>com.glodon.gboat.web.filter.ExtractedFilterDispatcher</filter-class> <init-param> <param-name>actionPackages</param-name> <param-value>com.glodon.gets.crms.action</param-value> </init-param> </filter>actionPackages是默认的Action存放的包,多个包用逗号隔开。
Action的结果集使用注解的形式@Results进行跳转,还用@NameSpace定义命名空间。这个在项目中已经大量使用,现如今才真正明白了其中的原理。