• 1. 第三章:struts2配置详解 主讲:刘雷
  • 2. 学习目标掌握struts2的几个主要配置文件:struts.properties、struts-default.xml和struts.xml、struts-plugin.xml 掌握struts.xml中各项内容的配置 重点掌握Action和Result的配置 掌握使用注解来配置Action
  • 3. Struts2框架的主要配置文件
  • 4. web.xml struts2 org.apache.struts2.dispatcher.FilterDispatcher struts2 /* 说明: 准确的说,web.xml并不是Struts2框架特有的文件。作为部署描述符文件,web.xml是所有Java Web应用程序都需要的核心配置文件。 struts2框架需要你在web.xml文件中配置一个前端控制器-----FilterDispatcher ,用于对struts2框架进行初始化,以及处理所有的请求。
  • 5. struts.propertiesstruts2.0框架有两核心的配置文件:struts.xml和struts.properties struts.xml文件主要负责管理应用中的action映射,以及该Action中包含的result定义等。 struts.properties通常放在WEB应用下的WEB-INF/classes路径下。 其实,struts.properties的内容均可在struts.xml中以加载 以下是整合一些资料总结的详细配置参数
  • 6. struts.properties
  • 7. struts.properties
  • 8. struts.properties
  • 9. struts.properties
  • 10. struts.properties
  • 11. struts.properties
  • 12. struts.xml
  • 13. (本页无文本内容)
  • 14. (本页无文本内容)
  • 15. struts.xml---- Bean设置Bean设置 Struts2框架是一个高度可扩展的框架,框架的大部分核心组件,Struts2并不是直接以硬编码的方式写在代码中的,而是以自己的IOC(控制反转容器)来管理框架的核心组件. Struts2框架以可配置的方式来管理Struts2的核心组件,从而允许开发者可以非常方便的扩展该框架的核心组件.当开发者需要扩展,或者替换Struts2的核心组件的时候,只需要提供自己的组件实现类,并且将组件实现类部署在Struts2的IOC容器当中就可以了.
  • 16. 打开Struts-core-2.1.6.jar压缩文件中的struts-default.xml文件,看到在该文件中配置了大量的Bean定义,该配置文件的代码如下:
  • 17. 上面的配置文件配置了Struts2框架的内置Bean,其中有三个类型检测Bean,就是在前面struts.properties文件中允许使用的类型检测器.( struts.objectTypeDeterminer:该属性指定Struts2的类型检测机制,通常支持tiger和notiger两个属性值.). 在struts.xml文件中定义bean时,通常有如下两个作用 a.创建该bean的实例,将该实例作为struts2框架的核心组件使用 b.bean包含的静态方法需要注入一个值 。 在第一种用法下,因为Bean实例往往是作为一个核心组件使用的,因此需要告诉Struts2容器该实例的作用----就是该实例实现了哪个接口,这个接口往往定义了该组件所必须遵守的一个规范.
  • 18. (本页无文本内容)
  • 19. (本页无文本内容)
  • 20. struts.xml----常量配置
  • 21. (本页无文本内容)
  • 22. 这里配置有错,写反了
  • 23. struts.xml ----包的配置
  • 24. 下面的struts.xml文件当中配置了两个包,其中名为 default的包,继承了Struts2框架的默认包struts-default
  • 25. (本页无文本内容)
  • 26. (本页无文本内容)
  • 27. struts.xml-----命名空间配置
  • 28. (本页无文本内容)
  • 29. struts.xml----包含的配置
  • 30. struts.xml----包拦截器配置
  • 31. 拦截器的定义片段
  • 32. (本页无文本内容)
  • 33. (本页无文本内容)
  • 34. struts.xml-----Action配置详解 Struts2的核心功能是action,对于开发人员来说,使用struts2框架,主要的编码工作就是编写action类。Action类通常都要实现com.opensymphony.xwork2.Action接口,并实现该接口中的execute()方法,该方法语法格式如下: public String execute() throws Exception 当然,struts2并不要求你所编写的action类一定要实现Action接口,你也可以编写一个普通的Java类作为action,只要该类提供一个返回类型为String的无参的public方法,如下所示: public String xxx() 在实际开发中,action类很少直接实现Action接口,通常都是从com.opensymphony.xwork2.ActionSupport类继承。ActionSupport实现了Action接口和Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable的接口,提供了输入验证、错误信息存取,以及国际化的支持,选择从ActionSupport继承,可以简化action的开发。 开发action后,就需要配置action映射,以告诉struts2框架,针对某个URL的请求应该交由哪一个action进行处理。
  • 35. Action的配置在struts2框架中每一个Action是一个工作单元。Action负责将一个请求对应到一个Action处理上去,每当一个Action类匹配一个请求的时候,这个Action类就会被Struts2框架调用。 Struts.xml中的每一个action元素就是一个action映射。action完整的属性如表所示:
  • 36. 举例说明 /success.jsp /error.jsp Action的name属性是必需的,其他属性是可选的。在为action取名时,默认 情况下在名字中是不允许出现斜杠(/)的。如果想在名字中使用斜杠(/): (例如,),就需 要在struts.xml文件中通过指定 来打开这个功能。 此外,在为action取名时,名字中尽量不要使用点号(.)(例如create.user)和连接字符(-)(例如:my-action),否则会出现一些莫名其妙的问题。 其实我们不用去记忆名字中不允许出现哪些字符,只要按照通常的命名习惯去为action取名就可以了,顶多在名字中使用一下下划线(_)(例如:my_action),这样是可以保证不会出现问题。
  • 37. 使用method属性在软件开发中,经常会用到CRUD操作,CRUD即create(创建)、Read/Retrieve(读取)、Update(更新)和Delete(删除)的首字母的缩写。例如:在一个用户管理系统中,对用户有四种操作:添加用户、浏览用户、编辑用户和删除用户,分别对应CRUD的四种操作。在具体实现时,为了节省action类的数量,通常是在一个action类中编写四个方法来实现CRUD操作。 public String loginUser() throws Exception{} //查询用户 public String addUser() throws Exception{} //添加用户 public String updateUser() throws Exception{} //修改用户 public String deleteUser() throws Exception{} // 删除用户 现在的问题是,我们如何才能让框架在不同的请求到来时,去调用Action中的相应方法呢?要知道,在执行action时,默认调用方法是execute().
  • 38. 使用method属性在配置action时,我们可以通过action元素的method属性来指定action调用的方法。所指定的方法必须遵循与execute方法相同的格式。 在struts.xml文件中,我们可以为同一个action类配置不同的别名,并使用method属性,如下所示: index.jsp reg.jsp index.jsp reg.jsp index.jsp reg.jsp index.jsp reg.jsp
  • 39. 注意:使用method属性使用action的method属性可以任意指定处理请求的方法(只要该方法和execute方法具有相同的格式),这样就可以在同一个类中完成相关的任务,而不需要去编写不同的Action类。 Struts2在根据action元素的method属性查找方法时有两种途径: 1)查找与method属性值完全一致的方法 2)查找doMethod()形式的方法。 以上面的例子为例,当请求/reg时,struts2首先查找addUser()方法,如果找不到,则继续查找名为doAddUser() 的方法。这种特性是从WebWork继承而来的,而WebWork提供这种特性,一方面是为了兼容旧版本WebWork遗留的功能,另一方面是因为一些方法别名的需要,例如,default是Java的关键字,不能作为方法名,你可以使用doDefault作为方法名,在配置时,可以使用method=“default”. 这种特性同样也适用于下一节要讲述的动态方法调用,例如,请求/users! addUser.action,struts2会依次查找addUser()和doAddUser()方法
  • 40. Action动态方法调用(一)另一种无须配置就可以直接调用Action中的非execute()方法的方式,就是使用struts2的动态方法调用。 动态方法调用(Dynamic Method Invocation,DMI)是在action的名字中使用感叹号( ! )来标识要调用的方法名,其语法格式为: actionName!methodName.action 例如 , 我们配置了如下的Action ….. 当请求/users! addUser.action时,将调用UserAction的addUser()方法; 当请求/users! updateUser.action时,将调用UserAction的updateUser()方法; DMI的实现本质是,其实现代码扫描action名字中的“!”字符,如果找到,则“欺骗”框架来调用“!”字符后的方法,而非execute方法。虽然调用的是其它方法,但是它使用的仍然是execute方法的配置,包括验证。框架“相信”它正在调用的是Action类的execute()方法。
  • 41. Action动态方法调用(二)在struts2中使用DMI有两个要注意的问题。首先,DMI可能会带来安全隐患,由于通过URL可以执行action中的任意方法,恶意的用户会利用这一特性来执行一些敏感的方法,即使你不想这些方法被执行。所以在确定使用DMI时,你应该确保Action中的方法都是普通、开放的方法;否则,你应该加上安全控制。其次,DMI与下一节要介绍的通配符方法有所重叠。 由于上述两个原因,struts2提供了一个属性配置,用于禁止DMI。你可以在struts.xml文件中,使用constant元素将struts.enable.DynamicMethodInvocation属性设置为false,来关闭DMI 那么什么时候使用动态方法调用,什么时候使用action元素的mrthod属性呢?或者二者有什么区别吗? 如果同一个Action的不同方法使用的是相同的配置(同样的拦截器引用,同样的result映射),那么可以使用动态方法调用; 如果不同的方法调用需要配置不同的拦截器引用、不同的result映射,那么可以使用action元素的method属性,为同一个Action配置多个别名。
  • 42. Action 通配符映射一些时候对Action中方法的调用满足一定的规律,例如edit.Action对应edit方法,delete.Action对应 delete方法,这个时候我们可以使用方法通配符,例如: 这时,editCrud.Action的引用将调用edit方法,同理,deleteCrud.Action的引用将调用delete 方法。     另外一种比较常用的方式是使用下划线分割,例如: 这样当遇到如下调用的时候可以找到对应的方法。 "action=Crud_input"  =>  input方法 "action=Crud_delete" =>  delete方法 通配符和普通的配置具有相同的地位,可以结合使用框架的所有其他功能。
  • 43. Action 通配符映射通配符即星号(*),用于匹配0个或多个字符。在配置action时,可以在action元素的name属性中使用星号(*)来匹配任意的字符。 通配符中几个特殊的标记,如下所述: *:可以匹配0个或多个任意字符,但是不包括正斜杠”/”; **:可以匹配0个或多个任意字符,包括正斜杠”/”在内 \:反斜杠,转义字符。 因为*不能匹配正斜杠,所以前面/editSubscription/add不会被匹配上。 在action mapping中,被通配符所匹配上的值可以用符号{N}来访问,其中N是一个1到9之间的数,用来表示代替第N个被匹配上的值,说通俗点就是第N个*号所表示的内容,比方说通配符表达式是/edit*/add*/confirm*,它匹配上了/editOrder/addItem/confirmResult,那么{1}就代表Order,{2}就代表Item,{3}就代表Result,依此类推。
  • 44. 配置Result一个result代表了一个可能的输出。当Action类的方法执行完成时,它返回一个字符串类型的结果码,框架根据这个结果码选择对应的result,向用户输出。 在com.opensymphony.xwork2.Action接口中定义了一组标准的结果代码,可供开发人员使用,如下所示: public interface Action { public static final String SUCCESS = “success”; public static final String NONE = “none”; public static final String ERROR = “error”; public static final String INPUT = “input”; public static final String LOGIN = “login”; } 除了这些预定义的结果码外,开发人员也可以定义其它的结果码来满足自身应用程序的需 要。 Result配置由两部分组成:一部分是result映射,另一部分是result类型。下面我们分别对 这两部分进行介绍。
  • 45. 结果映射----result映射在struts.xml文件中,使用result元素来配置result映射。Result元素有两个可选的属性:如下: 属性是否必需说明name否指定result的逻辑名type否指定result的类型,不同类型的result代表了不同的结果输出在result元素中,可以使用param子元素来指定这个结果对应的实际资源的位置。param元素有一个必需的属性name,用于指定参数名,param元素的内容给出参数值。如果要指定资源的位置,name属性的值需要设置为location.
  • 46. 配置 result映射看完上面的配置,感觉是否有一点复杂。为什么我们之前的配置没有这样复杂呢?在上面的例子中我们用result元素的 type属性来指定结果的类型,同时还使用param子元素来指定资源的实际位置,因此就变得复杂了。
  • 47. 配置 result映射在struts2中允许你定义一个默认的Result类型,这是通过result-type元素来定义的。在框架的默认配置文件struts-default.xml中,在struts-default包中有如下的一个配置: result-type元素的default属性指定名为dispatcher的结果类型为默认的结果类型。dispatcher结果类型使用Servlet API中的RequestDispatcher将请求导向到目标资源,通常是JSP页面。如果你在使用result元素配置result映射时,没有使用type属性,那么框架将使用默认的dispatcher类型。
  • 48. 配置 result映射由于struts2中的包是可以继承的,在上面的实例中我们定义的default包继承自struts-default包,因此也继承了默认的结果类型定义(当然,你也可以在“子”包中定义自己的默认结果类型)。既然有了默认的结果类型,而你想要使用的也正是这种结果类型,那么就可以省略result元素的type属性。 在result的配置中,当结果类型为dispatcher时,如果你使用param子元素为该类型的result设置location参数(这是最常用的参数),那么param子元素也是可以省略的。此外如果你没有指定result元素的name属性,那么框架将把它命名为“success”.使用框架提供的这些默认设置,我们简化配置: /success.jsp /error.jsp
  • 49. 配置 result映射在result映射的配置中,在指定实际资源的位置时,可以使用绝对路径,也可以使用相对路径。 绝对路径以斜杠(/)开头,相对于当前的Web应用程序的上下文路径; 相对路径不以斜杠(/)开头,相对于当前执行的action的路径。 例如: success.jsp /error.jsp 如果当前Web应用程序的上下文路径是/Shop,那么请求/Shop/admin/login.action,执行成功后,转向的页面路径为:/Shop/admin/success.jsp;执行失败后,转向的页面路径为/Shop/error.jsp.
  • 50. result结果类型在框架调用Action对请求进行处理之后,就要向用户呈现一个结果视图。Struts2支持多种类型的视图,这些视图是由不同的结果类型来管理的。一个结果类型就是实现了com.opensymphony.xwork2.Result接口的类,在struts2中,预定义了多种结果类型,如表: 结果类型在包中使用result-type元素来定义,上面的结果类型都是在框架的默认配置文件struts-default.xml中定义的。
  • 51. struts-default.xml
  • 52. dispatcher结果类型(一)最常用的结果类型当然是dispatcher了,要不然struts2也不会将它设为默认的结果类型了。 Struts2在后台使用Servlet API 的RequestDispatcher来转发请求,因此在用户的整个请求/响应过程中,目标Servlet/JSP接收到的request/response对象,与最初的Servlet/JSP相同。 Dispatcher结果类型的实现是org.apache.struts2.dispatcher.ServletDispatcherResult,该类的二个属性(property):location和parse,这两个属性可以通过struts.xml配置文件中的result元素的param子元素来设置。param元素的name属性指定结果类型实现类的属性名,param元素的内容是属性的值。例如: /success.jsp true 其中location参数用于指定action执行完毕后要转向的目标资源,parse属性是一个布尔类型的值,如果为true,则解析location参数中的OGNL表达式;如果为false,则不解析。parse属性的默认值就是true. location参数是默认的参数,在所有的Result实现类中,都定义了一个字符串类型的DEFAULT_PARAM静态常量,专门用于指定默认的参数名。 DEFAULT_PARAM常量的定义:public static final String DEFAULT_PARAM=“location”;
  • 53. dispatcher结果类型(二)在设置location参数时,可以在参数值中使用OGNL表达式。 /viewNews.jsp?id=${id} true 考虑到默认值的使用,上述可以简化为: viewNews.jsp?id=${id}
  • 54. redirect结果类型(一)Redirect结果类型在后台使用HttpServletResponse的sendRedirect方法将请求重定向到指定的URL,它的实现类是org.apache.struts2.dispatcher.ServletRedirectResult.在使用redirect结果类型的场景中,用户要完成一次与服务器之间的交互,浏览器需要完成两次请求,如下图:
  • 55. redirect结果类型(二)①浏览器发出一个请求,struts2框架调用对应的Action实例对请求进行处理; ②Action返回”success”结果码,框架根据这个结果码选择对应的结果类型,在上图是redirect结果类型; ③ServletRedirectResult在内部使用HttpServletResponse的sendRedirect方法将请求重定向到目标资源; ④浏览器重新发起一个针对目标资源的新的请求; ⑤目标资源作用为响应呈现给用户。 由于在一次用户交互过程中存在着两次请求,因此第一次请求中的数据在第二次请求中是不可用的,这意味在目标资源中是不能访问action实例、action错误以及错误等。 如果有某些数据需要在目标资源中访问, 一种方式是将数据保存到Session中, 另一种方式是通过请求参数来传递数据。
  • 56. redirectAction结果类型(一)redirectAction结果类型的实现类是org.apache.struts2.dispatcher.ServletActionRedirectResult,该类是ServletDispatcherResult的子类,因此我们也就可以判断出redirectAction结果类型和redirect结果类型的后台工作原理是一样的,即都是利用HttpServletResponse的sendRedirect方法将请求重定向到指定的URL。 那么redirect与redirectAction有什么区别呢? 从结果类型的名字上,我们可以大致判断出redirectAction结果类型主要是用于重定向到action。也就是说,在请求处理完成后,如果你需要重定向到另一个action,那么建议你使用redirectAction结果类型。 使用redirectAction结果类型可以简化对那些带有名称空间的action URL的设置,ServletActionRedirectResult类在内部使用ActionMapper来构建访问action的URL,这样你就不需要在struts.xml配置文件中手动去编码访问action的URL了.
  • 57. redirectAction结果类型(二)redirectAction结果类型有二个参数: actionName(default):指定重定向的action的名字。该参数是默认参数。 namespace:指定action所属的名称空间,如果没有使用这个参数,那么默认使用当前的名称空间。
  • 58. redirectAction结果类型(三)
  • 59. plainText结果类型(一)plainText结果类型可能不是很常用,但是它是一个非常有趣的结果类型,因为它可以用于输出JSP或HTML的源代码。想一想,你制作一个在线实例教程,用户看完页面效果后,想看看你的页面如何编写的,点击你提供的“查看源代码链接” ,整个页面的源代码就以页面的形式在浏览器中显示出来,这个功能是不是很贴心呢! 通常情况下,要想在浏览器中显示一个JSP或HTML页面的代码,你必须对其中的标记使用实体引用或字符引用的方式来做置换,这样才能在浏览器中显示页面代码。不过如果这样做,一方面工作量太大,另一方面你的源文件也被破坏了。所以我们通常是编写一个转换程序,在页面输出时,由程序读取页面的内容,将其中的特殊字符转换成对应的字符引用,然后再输出到浏览器中。 在struts2中你不需要这样去编写这样的程序了,直接使用plainText结果类型就可以实现输出页面源代码的功能。
  • 60. plainText结果类型(二)plainText结果类型有两个参数,如下所示: Location:指定要输出原始内容的页面(JSP或HTML)。该参数是默认的。 charSet:指定输出页面内容时使用的字符编码。这个字符编码将被用作设置响应类型(例如:Content-Type=text/plain;charset=GBK),以及使用Reader对象读取文件时的编码。 /myJspFile GBK 如果你在myJspFile.jsp中使用了中文,那么需要设置charSet参数为GBK或者GB2312,否则在浏览器中显示时会出现乱码。
  • 61. chain结果类型(一)Struts2框架支持配置多个Action组成一个链或者工作流来处理用户的请求,而Action链的实现,是通过拦截器ChainingInterceptor完成的。 ChainingInterceptor在源Action执行完毕后,将源Action的用户请求参数、值栈、session的数据赋值给目的Action,就是说,在执行多个Action过程中,参数都是保留的。
  • 62. chain结果类型(二)下面配置中,通过chain结果类型,将3个Action组成了一个链,共同完成一个用户请求。
  • 63. chain结果类型(三)①第一个Action的result定义为chain,并指向名为login的Action;该Action中result同样指定type为chain,但是增加了actionName属性和namespace属性,actionName属性指定目的Action的名称,namespace属性指定了目的Action所在的命名空间名称,也就是定位该Action所在的package名称。 ②第3个Action存在另外一个package中,也就是第2个Action的result中指定的命名空间中,该Action的result没有指定type属性,则使用默认值dispatcher,即JSP视图。 ③该配置文件调用关系为createAccout-----login------secure。在上述调用过程中,每个Action所属的参数、值栈等数据通过拦截器被传入下一个Action,直到最后一个Action执行完成。Login.jspActionChain1_ActionActionChain2_ActionActionChain3_ActionSuccess.jsp
  • 64. Stream结果类型示例Stream类型的result一般是指将原始数据直接传递给HttpServletResponse,这种结果类型在用户下载文件(例如PDF文件等)等情况下非常有意义。 配置stream类型的result,一般可以指定下面几个参数: contentType:指定传递给浏览器的stream类型,默认类型为text/plain. contentlength:数据流的字节长度(用于浏览器显示进度条) contentDispostion:指定文件的内容规格,默认值为inline. inputName:数据流的属性,默认值为inputstream bufferSize:缓冲区容量,默认为1024. 示例: image/jpeg imageStream filename="document.pdf" 1024
  • 65. 全局结果(一)上述我们所配置的结果映射都是在action元素的内部,这些结果只能被它外部的action所使用,这样的结果可以看成是局部结果。 在某些场景中,可能有多个action需要访问同一个结果,例如在论坛系统中,用户在发帖、回帖、搜索帖子时都需要先登录,那么我们可以配置一个全局的login结果,这样在action中就不需要再一一配置login结果了。 全局结果也是在包中定义的,在这个包中所有的action可以共享全局结果。全局结果也是使用result元素来配置,只不过不是在action元素中嵌套,而是在global-results元素中嵌套。
  • 66. 全局结果(二)当请求/bbs/addArticle时,ArticleAction的execute方法如果没有返回login结果码,那么框架将首先在addArticle这个action的配置中查找嵌套的局部结果。 如果没有找到匹配的局部结果,那么就在全局结果中查找,找到后,应用redirectAction结果类型将请求重定向到/bbs/login!input.action.如果用户登录失败,或者发贴失败,Action返回error结果码,那么全局结果中的error.jsp页面将呈现给用户。
  • 67. 动态结果所谓动态结果,就是指在配置时你不知道要执行哪一个结果,在运行时刻才能确定执行的结果。简单地说,就是在配置结果时使用了表达式,在运行时刻,框架解析并计算表达式,根据表达式的值来确定要执行的结果。 例如一个公司的内部办公系统,它根据用户登录的身份(普通雇员还是经理)来决定用户可浏览的资源。用户登录由LoginAction来处理,雇员可访问资源由EmployeeAction来处理,经理访问资源由ManagerAction根据用户权限的不同,将请求重定向到EmployeeAction或ManagerAction. public class EmployeeAction extends ActionSupport{…..........} public class ManagerAction extends ActionSupport{…..........}
  • 68. Action类代码用于保存请求重定向到的action的名字提供getter方法,在result映射中使用表达式访问nextAction属性判断用户是否是管理者
  • 69. struts.xml配置文件上述深色部分,我们使用${nextAction}来获取Action中的nextAction属性的值,而这个值要在运行时刻才能知道。在运行时刻,计算出${nextAction}的值后,然后由redirectAction结果类型将请求重定向到指定的action.
  • 70. 说明在结果映射中,使用${nextAction}语法访问的属性一定要在Action中存在,这种存在不是简单地定义一个实例变量就完了,而是要提供对应的JavaBean风格的getter方法。在JavaBean中,实例变量的名字和属性(property)名可以是不同的,例如: private String name; public getUsername() { return name; } 在上述的代码中,实例变量名是name,属性名是username.使用${….}语法访问的是属性名。
  • 71. struts2中异常处理(一)Struts2通过拦截器对action抛出的异常进行捕获,这个拦截器就是: com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor 在try语句中调用invocation.invoke(),invoke方法在内部调用Action的方法 得到配置的异常映射的列表 在异常映射列表中,查找异常类型对应的结果代码
  • 72. struts2中异常处理(二)要使用struts2的声明式异常处理,就需要配置ExceptionMappingInterceptor拦截器。 在struts2的默认配置文件struts-default.xml中,ExceptionMappingInterceptor已经配好 ……… ……………… ……………… 从struts-default包继承的”子”包中的action都将使用默认的拦截器栈defaultStack(除非action引用了其他的拦截器),而在这个拦截器栈中引用了exception拦截器(是defaultStack栈中第一个引用的拦截器)。因此,在默认情况下,所有的action自然就引用了exception拦截器,而不需要再配置它了。
  • 73. struts2中异常处理(三)既然异常映射拦截器已经为我们配置好了,那么剩下的工作就是使用exception-mapping元素来配置异常映射,将异常类型映射到指定的结果。 exception-mapping元素有二个属性: exception:指定一个异常类型的完整类名, result:指定对该异常进行处理的结果的名字。 Struts2框架提供了二种方式来声明一个异常映射: 全局和局部的(针对一个特定的action). 与result映射的查找规则一样,当一个异常发生时,exception拦截器将首先查找抛出异常的action中的局部拦截器映射,然后再查找全局的异常映射。只要找到一个匹配的,那么对应的结果就这被处理。
  • 74. struts2中异常处理(四)
  • 75. struts2中异常处理(五)在上述的配置中,定义了三个异常映射,当异常发生时,框架的处理情况如下: Java.sql.SQLException异常将链接到/sqlExceptionAction.action; com.ibm.SecurityException异常将重定向到/login.action; 其他从java.lang.Exception继承的异常将向用户返回/exception.jsp页面 ExceptionMappingInterceptor在捕获到Action的方法抛出的异常后,除了从异常映射的配置中查找对应的结果名外,还会将下列两个值放到值栈中,以便在结果页面中访问异常信息。 exception:异常对象本身。 exceptionStack:保存异常发生时的栈跟踪信息。 在结果页面中。可以使用struts2的标签来访问异常信息。例如 取出异常对象的描述信息。 取出异常发生时的栈跟踪信息。
  • 76. 使用注解配置Action注解(Annotation)是J2SE 5.0中提供的新特性,目前应用已经非常广泛,其中的一个主要应用就是代替传统的XML配置文件,使用注解来提供配置信息。 Struts2也提供了使用注解的方式来配置Action,这样就不再需要struts.xml文件,以实现零配置。 与Action2在org.apache.struts.config包中定义了4个与Action配置相关的注解类型,如下: Parentpackage:指定action所在的包要继承的父包。 Namespace:指定action所属的名称空间。 Result:定义一个result映射。 Results:定义一组result映射。
  • 77. ParentPackage注解的参数如果注解中只有一个名为value的参数,或者有其他参数,但其他参数都有默认值,那么在为value参数设值时可以忽略value和等号(=),例如: @ParentPackage(value=“struts-default”)和@ParentPackage(“struts-default”)是一样的参数类型是否必需默认值描述valueString是无指定要继承的父包参数类型是否必需默认值描述valueString是无指定action所属的名称空间Namespace注解的参数例如:@Namespace(“/secure”) 注意在名称空间取名时,要以斜杠(/)开头。
  • 78. Result注解的参数例如:@Result(“/success.jsp”) 在这个例子中我们没有使用name和type参数,因此使用它们的默认值。type参数的默认值是NullResult.class,那么这个例子能否正常运行呢?如果type参数的值是NullResult.class,那么struts2框架在解析result的配置时,会使用默认的结果类型(即ServletDispatcherResult)来替换NullResult。参数类型是否必需默认值描述nameString否Action.SUCCESS指定result的逻辑名,即结果代码valueString是无指定result对应的资源的URLtypeClass否NullResult.class指定result的类型paramString[ ]否{ }为result传递参数,格式为:{key1,value1,key2,value2}
  • 79. Results注解的参数例: @Results({ @Result(name=“input”,value=“/input.jsp”), @Result(name=“error”,value=“/error.jsp”,type=“ServletDispatcherResult.class”) }) 在上面的例子中定义了两个result映射。一个逻辑名是input,资源位置是/input.jsp;另一个逻辑名是error,资源位置是/error.jsp. 参数类型是否必需默认值描述valueResult[ ]是无为action定义一组result映射
  • 80. 使用注解配置Action的注意事项 (一)在struts2中使用注解配置action,有一些需要注意的地方。 ①与action配置相关的4个注解只能用在类级别上。 ②需要在web.xml文件中为FilterDispatcher过滤器设置actionPackages参数,指定包含了Action类(这些类使用了注解)的包的列表,多个包之间以逗号(,)分隔。这些包和它们的子包都将被扫描,在指定包中的所有实现了Action接口的类,或以“Action”结尾的类都将被检测。后者允许我们编写POJO Action类, 而不需要实现Action接口。如果有多个包,则以逗号(,)分隔。
  • 81. 使用注解配置Action的注意事项 (二)③包名、名称空间名和action名的产生方式如下: Action类所在的包作为action的包名。 除了使用Namespace注解指定名称空间外,也可以通过子包名来产生名称空间。例如,Action类所在的包为com.ibm.action,如果actionPackages参数指定的包是com.ibm,那么“/action”将作为名称空间的名字。 通过Action的类名来产生action的名字。如果类名以“Action”结尾,那么”Action”将被去掉,剩余部分将首字母变为小写作为action的名字。例如:action的类名是LoginAction,那么产生的action的名字是login. 我们看一个完整的例子:如果Action的完整类名是com.ibm.action.LoginAction, actionPackages参数的配置为com.ibm action的包名为com.ibm.action action所属的命名空间是/action action的名字是login 可以通过http://localhost:8080/myapp/action/login.action来访问LoginAction. ④如果你想让你的包继承struts-default包,无须使用ParentPackage注解,在框架内部,会自动让你的包继承struts-default包。
  • 82. 使用注解配置Action实例(一)一个Action和三个页面。三个页面配置为Result映射。实例开发步骤如下: 第一步:编写success.jsp,input.jsp,error.jsp页面 第二步:编写AnnotationAction类
  • 83. 使用注解配置Action实例(二)第三步:配置web.xml第四步:测试 http://localhost:8080/myapp/test.annotation.action http://localhost:8080/myapp/test.annotation!input.action http://localhost:8080/myapp/test.annotation!error.action
  • 84. 谢谢!