`

struts2.1两天快速入门

阅读更多

第一天上午学习目录列表:

            一、第一个struts2.1应用开发

            二、Action配置的各项默认值

            三、配置的各种视图转发类型

            四、Action属性注入值

            五、Struts 2.1处理的请求

 

开发环境:MyEclipse+Tomcat6.x

一、第一个struts2应用开发

  1.1、开发Struts 2程序最少需要的JAR如下:

      struts2-core-2.x.x.jar :Struts 2框架的核心类库
      xwork-core-2.x.x.jar :XWork类库,Struts 2在其上构建
      ognl-2.6.x.jar :对象图导航语言(Object Graph Navigation Language),struts2框架通过其读写对象的属性
      freemarker-2.3.x.jar :Struts 2的UI标签的模板使用FreeMarker编写
      commons-logging-1.x.x.jar :ASF出品的日志包,Struts 2框架使用这个日志包来支持Log4J和JDK 1.4+的日志记录。
      commons-fileupload-1.2.1.jar 文件上传组件,2.1.6版本后必须加入此文件

 

  1.2、Struts2默认的配置文件为struts.xml ,该文件需要存放在WEB-INF/classes下,该文件的配置模板如下:    

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3C!DOCTYPE%20struts%20PUBLIC%0A%20%20%20%20%22-%2F%2FApache%20Software%20Foundation%2F%2FDTD%20Struts%20Configuration%202.0%2F%2FEN%22%0A%20%20%20%20%22http%3A%2F%2Fstruts.apache.org%2Fdtds%2Fstruts-2.0.dtd%22%3E%0A%3Cstruts%3E%0A%3C%2Fstruts%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. <? xml   version = "1.0"   encoding = "UTF-8" ?>   
  2. <!DOCTYPE struts PUBLIC  
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.0.dtd">   
  5. < struts >   
  6. </ struts >   
<?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>
</struts>

    知识提示 : 此模板可在struts-2.1.6\apps\struts2-blank-2.1.6.war的空白项目里面拷.

 

  1.3、struts2框架是通过Filter启动的。他在web.xml中的配置如下:

 

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Cfilter%3E%0A%20%20%20%20%3Cfilter-name%3Estruts2%3C%2Ffilter-name%3E%0A%20%20%20%20%3Cfilter-class%3Eorg.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter%3C%2Ffilter-class%3E%0A%20%3C!--%20%E8%87%AA%E4%BB%8EStruts%202.1.3%E4%BB%A5%E5%90%8E%EF%BC%8C%E4%B8%8B%E9%9D%A2%E7%9A%84FilterDispatcher%E5%B7%B2%E7%BB%8F%E6%A0%87%E6%B3%A8%E4%B8%BA%E8%BF%87%E6%97%B6%0A%20%20%20%20%3Cfilter-class%3Eorg.apache.struts2.dispatcher.FilterDispatcher%3C%2Ffilter-class%3E%20--%3E%20%0A%3C%2Ffilter%3E%0A%3Cfilter-mapping%3E%0A%20%20%20%20%3Cfilter-name%3Estruts2%3C%2Ffilter-name%3E%0A%20%20%20%20%3Curl-pattern%3E%2F*%3C%2Furl-pattern%3E%0A%3C%2Ffilter-mapping%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. < filter >   
  2.     < filter-name > struts2 </ filter-name >   
  3.     < filter-class > org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter </ filter-class >   
  4.  <!-- 自从Struts 2.1.3以后,下面的FilterDispatcher已经标注为过时  
  5.     < filter-class > org.apache.struts2.dispatcher.FilterDispatcher </ filter-class >  -- >    
  6. </ filter >   
  7. < filter-mapping >   
  8.     < filter-name > struts2 </ filter-name >   
  9.     < url-pattern > /* </ url-pattern >   
  10. </ filter-mapping >   
<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
 <!-- 自从Struts 2.1.3以后,下面的FilterDispatcher已经标注为过时
    <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> --> 
</filter>
<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

    知识提示 : 在StrutsPrepareAndExecuteFilter的init()方法中将会加载类路径下默认的配置文件struts.xml完成初始化操作,些初始化工作只做一次,在服务器启动过程中完成.

 

  1.4、第一个Struts2版HelloWorld.

 

        1.4.1、新建cn.gkit.action.HelloWorldAction类,代码如下:

 

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20class%20HelloWorldAction%20%7B%0A%09%0A%09private%20String%20message%3B%0A%09public%20String%20getMessage()%20%7B%0A%09%09return%20message%3B%0A%09%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%E8%BF%94%E5%9B%9E%E7%9A%84%E6%98%AF%E4%B8%80%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%0A%09public%20String%20execute()%7B%0A%09%09message%20%3D%20%22struts2%E7%89%88%E7%9A%84HelloWorld%22%3B%0A%09%09return%20%22success%22%3B%0A%09%7D%0A%7D" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. public   class  HelloWorldAction {  
  2.       
  3.     private  String message;  
  4.     public  String getMessage() {  
  5.         return  message;  
  6.     }  
  7.                  //返回的是一个字符串   
  8.     public  String execute(){  
  9.         message = "struts2版的HelloWorld" ;  
  10.         return   "success" ;  
  11.     }  
  12. }  
public class HelloWorldAction {
	
	private String message;
	public String getMessage() {
		return message;
	}
                 //返回的是一个字符串
	public String execute(){
		message = "struts2版的HelloWorld";
		return "success";
	}
}

    知识提示 : 可以看到此Action类并没有继承其它类,是一个简单的POJO类.

 

        1.4.2、action在struts.xml里的配置:

 

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%20%3F%3E%0A%3C!DOCTYPE%20struts%20PUBLIC%0A%20%20%20%20%22-%2F%2FApache%20Software%20Foundation%2F%2FDTD%20Struts%20Configuration%202.0%2F%2FEN%22%0A%20%20%20%20%22http%3A%2F%2Fstruts.apache.org%2Fdtds%2Fstruts-2.0.dtd%22%3E%0A%3Cstruts%3E%0A%20%20%20%3Cpackage%20name%3D%22test%22%20namespace%3D%22%2Ftest%22%20extends%3D%22struts-default%22%3E%0A%20%20%20%20%20%20%20%20%3Caction%20name%3D%22helloworld%22%20class%3D%22cn.gkit.action.HelloWorldAction%22%20method%3D%22execute%22%20%3E%0A%09%3Cresult%20name%3D%22success%22%3E%2FWEB-INF%2Fjsp%2Fhelloworld.jsp%3C%2Fresult%3E%0A%20%20%20%20%20%20%20%20%3C%2Faction%3E%0A%20%20%20%20%3C%2Fpackage%3E%20%20%20%0A%3C%2Fstruts%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. <?xml version= "1.0"  encoding= "UTF-8"  ?>  
  2. <!DOCTYPE struts PUBLIC  
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"   
  4.     "http://struts.apache.org/dtds/struts-2.0.dtd" >  
  5. <struts>  
  6.    <package  name= "test"  namespace= "/test"   extends = "struts-default" >  
  7.         <action name="helloworld"   class = "cn.gkit.action.HelloWorldAction"  method= "execute"  >  
  8.     <result name="success" >/WEB-INF/jsp/helloworld.jsp</result>  
  9.         </action>  
  10.     </package >     
  11. </struts>  
<?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>
   <package name="test" namespace="/test" extends="struts-default">
        <action name="helloworld" class="cn.gkit.action.HelloWorldAction" method="execute" >
	<result name="success">/WEB-INF/jsp/helloworld.jsp</result>
        </action>
    </package>   
</struts>

    知识 提示 :<package> 表示一个包,类似java包. 此包可以被其它包继承.继承的属性是extends. test包就继承了一个struts的默认包struts-default.struts-default包定义在struts-defautl.xml 配置文件里,可以在struts2核心包根路径下面找到.namespace属性表示命名空间,可以把请求路径相同的一部分抽取出来。如访问 helloworld请求的路径为:/struts2.1/test/helloworld,其中struts2.1是指向该应用程序的虚拟目录(即内容 路径).<result>表示返回的视图,具体配置会在第三章中讲到.

 

         1.4.3、在helloworld.jsp显示message信息:

 

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3C%25%40%20page%20language%3D%22java%22%20import%3D%22java.util.*%22%20pageEncoding%3D%22UTF-8%22%25%3E%0A%3C!DOCTYPE%20HTML%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20HTML%204.01%20Transitional%2F%2FEN%22%3E%0A%3Chtml%3E%0A%20%20%3Chead%3E%0A%20%20%20%20%3Ctitle%3Estruts2.1%E7%89%88HelloWorld%3C%2Ftitle%3E%0A%20%20%3C%2Fhead%3E%0A%20%20%3Cbody%3E%0A%20%20%20%20%24%7Bmessage%7D%0A%20%20%3C%2Fbody%3E%0A%3C%2Fhtml%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. <%@ page language= "java"   import = "java.util.*"  pageEncoding= "UTF-8" %>  
  2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >  
  3. <html>  
  4.   <head>  
  5.     <title>struts2.1 版HelloWorld</title>  
  6.   </head>  
  7.   <body>  
  8.     ${message}  
  9.   </body>  
  10. </html>  
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>struts2.1版HelloWorld</title>
  </head>
  <body>
    ${message}
  </body>
</html>

     知识 提示 :用el表达式可以将action里的属性取出来.

 

二、Action配置(struts.xml--<action>)的各项默认值

 1>如果没有为action指定class属性,默认是ActionSupport。

 2>如果没有为action指定method属性,默认执行action中的execute() 方法。
 3>如果没有指定result的name属性,默认值为success。

    如在test包里增加如下一个action请求

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Caction%20name%3D%22registerUI%22%3E%0A%20%20%20%20%20%3Cresult%3E%2FWEB-INF%2Fpage%2Fregister.jsp%3C%2Fresult%3E%0A%3C%2Faction%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. < action   name = "registerUI" >   
  2.      < result > /WEB-INF/page/register.jsp </ result >   
  3. </ action >   
<action name="registerUI">
     <result>/WEB-INF/page/register.jsp</result>
</action>

    知识提示: 当访问路径/struts2.1/test/registerUI时,返回给浏览器的就是register.jsp页面.配置相当于struts1.x,如下:

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Caction%20path%3D%22%2Ftest%2FregiterUI%22%20forward%3D%22%2FWEB-INF%2Fpage%2Fregister.jsp%22%2F%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. < action   path = "/test/regiterUI"   forward = "/WEB-INF/page/register.jsp" />   
<action path="/test/regiterUI" forward="/WEB-INF/page/register.jsp"/>

 

三、配置的各种视图转发类型

    <result>配置类似于struts1中的<forward>,但struts2中提供了多种结果类型,常用的类型有: dispatcher(默认值)、   redirect(重定向) 、 redirectAction 、 plainText (文本).

 

    3.1、redirect

           但在<result>中还可以使用${属性名}表达式访问action中的属性,表达式里的属性名对应action中的属性。

    将1.4.2里的struts.xml配置文件里的<result>改成如下:

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Cresult%20type%3D%22redirect%22%3E%2Fhelloworld.jsp%3Fmessage%3D%24%7Bmessage%7D%3C%2Fresult%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. < result   type = "redirect" > /helloworld.jsp? message =${message} </ result >   
<result type="redirect">/helloworld.jsp?message=${message}</result>

    知识提示: 此时的helloworld.jsp应放在WebRoot目录下才可重定向访问.而在struts1.x的配置文件里的是做不到这一点的.  除非使用urlrewrite重写url,但也不能传一个action里的属性值.  重新访问/struts2.1/test/helloworld请求,浏览器地址将变为/struts2.1 /helloworld.jsp?message=struts2H凥elloWorld.这里先忽略中文乱码问题.

 

     3.2、plaintext:显示原始文件内容,例如:当我们需要原样显示jsp文件源代码的时候,我们可以使用此类型。配置如下:

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Cresult%20name%3D%22source%22%20type%3D%22plainText%20%22%3E%0A%09%3Cparam%20name%3D%22location%22%3E%2Fview.jsp%3C%2Fparam%3E%0A%09%3Cparam%20name%3D%22charSet%22%3EUTF-8%3C%2Fparam%3E%3C!--%20%E6%8C%87%E5%AE%9A%E8%AF%BB%E5%8F%96%E6%96%87%E4%BB%B6%E7%9A%84%E7%BC%96%E7%A0%81%20--%3E%20%20%20%0A%3C%2Fresult%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. <result name= "source"  type= "plainText " >  
  2.     <param name="location" >/view.jsp</param>  
  3.     <param name="charSet" >UTF- 8 </param><!-- 指定读取文件的编码 -->     
  4. </result>  
<result name="source" type="plainText ">
	<param name="location">/view.jsp</param>
	<param name="charSet">UTF-8</param><!-- 指定读取文件的编码 -->   
</result>

    知识提示: 当访问该请求时,返回的一个jsp页面代码文体视图,即jsp页面代码将不会被执行.

 

      3.3、redirectAction作用与redirect类似,不同的是它重定向的是一个action.

四、Action属性注入值

 

 属性注入类似于spring的属性注入,原理上是一样的, 都是通过反射技术将xml对应的值设值到相对应的java属性里.被注入的属性也要有对应的setter方法.

1、在HelloWorldAction 类里增加一下setter方法:

 

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20void%20setMessage(String%20message)%20%7B%0A%09%09this.message%20%3D%20message%3B%0A%09%7D" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. public   void  setMessage(String message) {  
  2.         this .message = message;  
  3.     }  
public void setMessage(String message) {
		this.message = message;
	}

 2、为了避免覆盖,将execute方法里给message赋值的那一段代码注释掉.

 

 3、在struts.xml配置文件的<action>增加一个子标签<param name="">,配置改成如下:

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%20%20%20%3Cpackage%20name%3D%22test%22%20namespace%3D%22%2Ftest%22%20extends%3D%22struts-default%22%3E%0A%20%20%20%20%20%20%20%20%3Caction%20name%3D%22helloworld%22%20class%3D%22cn.gkit.action.HelloWorldAction%22%20method%3D%22execute%22%20%3E%0A%20%20%20%20%20%20%20%20%09%3Cparam%20name%3D%22message%22%3E%E5%B1%9E%E6%80%A7%E6%B3%A8%E5%85%A5%3C%2Fparam%3E%0A%09%3Cresult%20name%3D%22success%22%3E%2FWEB-INF%2Fjsp%2Fhelloworld.jsp%3C%2Fresult%3E%0A%20%20%20%20%20%20%20%20%3C%2Faction%3E%0A%20%20%20%20%3C%2Fpackage%3E%20%20%20" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. < package   name = "test"   namespace = "/test"   extends = "struts-default" >   
  2.      < action   name = "helloworld"   class = "cn.gkit.action.HelloWorldAction"   method = "execute"   >   
  3.         < param   name = "message" > 属性注入 </ param >   
  4. t;result name = "success" > /WEB-INF/jsp/helloworld.jsp </ result >   
  5.      </ action >   
  6.  </ package >      
   <package name="test" namespace="/test" extends="struts-default">
        <action name="helloworld" class="cn.gkit.action.HelloWorldAction" method="execute" >
        	<param name="message">属性注入</param>
	<result name="success">/WEB-INF/jsp/helloworld.jsp</result>
        </action>
    </package>   

    此时访问该请求,页面显示的mesage属性值为:   属性注入

五、Struts 2处理的请求

      1、指定需要Struts 2处理的请求后缀,配置文件struts.xml配置里增加一下常量标签<constant>

 

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3C!DOCTYPE%20struts%20PUBLIC%0A%20%20%20%20%22-%2F%2FApache%20Software%20Foundation%2F%2FDTD%20Struts%20Configuration%202.0%2F%2FEN%22%0A%20%20%20%20%22http%3A%2F%2Fstruts.apache.org%2Fdtds%2Fstruts-2.0.dtd%22%3E%0A%3Cstruts%3E%0A%20%20%20%20%3Cconstant%20name%3D%22struts.action.extension%22%20value%3D%22do%22%2F%3E%0A%3C%2Fstruts%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. <? xml   version = "1.0"   encoding = "UTF-8" ?>   
  2. <!DOCTYPE struts PUBLIC  
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.0.dtd">   
  5. < struts >   
  6.     < constant   name = "struts.action.extension"   value = "do" />   
  7. </ struts >   
<?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 name="struts.action.extension" value="do"/>
</struts>

 

      2、如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号隔开。如:

 

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Cconstant%20name%3D%22struts.action.extension%22%20value%3D%22do%2Chtm%22%2F%3E%0A" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. < constant   name = "struts.action.extension"   value = "do,htm" />   
<constant name="struts.action.extension" value="do,htm"/>

 

     3、常量名struts.action.extension可以在default.properties里找到,里面包含了struts2默认的常量 值.default.properties可以在struts2核心包下的org.apache.struts2下找到.

 

第一天上午内容结束.

 

下午内容目录如下:

        六、Struts2的处理流程与Action的管理方式

        七、动态方法调用和使用通配符定义action

        八、自定义类型转换器

        九、自定义拦截器

        十、文件上传

第一天下午学习目录列表:

        六、Struts2的处理流程与Action的管理方式

        七、动态方法调用和使用通配符定义action

        八、自定义类型转换器

        九、自定义拦截器

        十、文件上传(改成一个专题来讲)

 

六、Struts2的处理流程与Action的管理方式

       6.1struts2处理请求图

StrutsPrepareAndExecuteFilter是Struts 2框架的核心控制器(相当于strtuts1.x的ActionServlet类的作用 ), 它负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到达时,该 Filter会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入Struts 2框架处理,否则Struts 2框架将略过该请求的处理。当请求转入Struts 2框架处理时会先经过一系列的拦截器,然后再到Action。与Struts1不同,Struts2对用户的每一次请求都会创建一个Action,所以 Struts2中的Action是线程安全的。也正因为如此,Struts2里可以定义成员变量,从而废弃了Struts1.x里的Form Bean.即Struts2的Action已具备了Struts1.x里的Form Bean的功能.

七、动态方法调用和使用通配符定义action

       7.1  动态方法调用

              如果Action中存在多个业务方法时,我们可以使用!+方法名调用指定方法。 我们在HelloWorldAction里添加两个业务方法,如下:

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%09public%20String%20del()%20%7B%0A%09%09message%20%3D%20%22%E8%B0%83%E7%94%A8del()%E5%88%A0%E9%99%A4%E6%96%B9%E6%B3%95%22%3B%0A%09%09return%20%22success%22%3B%0A%09%7D%0A%0A%09public%20String%20add()%20%7B%0A%09%09message%20%3D%20%22%E8%B0%83%E7%94%A8add()%E6%B7%BB%E5%8A%A0%E6%96%B9%E6%B3%95%22%3B%0A%09%09return%20%22success%22%3B%0A%09%7D" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. public  String del() {  
  2.     message = "调用del()删除方法" ;  
  3.     return   "success" ;  
  4. }  
  5.   
  6. public  String add() {  
  7.     message = "调用add()添加方法" ;  
  8.     return   "success" ;  
  9. }  
	public String del() {
		message = "调用del()删除方法";
		return "success";
	}

	public String add() {
		message = "调用add()添加方法";
		return "success";
	}

    如果要访问action的del() 方法,我们可以这样调用:/struts2.1/test/helloworld!del    ,动态方法调用就是那么简单,它实现了跟struts1.x 的DispatchAction一样的作用.

    注意: struts2的官方文档已经不建议我们这样使用,建议我们使用另外一种方式来实现: 使用通配符定义action来替代

 

        7.2   使用通配符定义action

                即用*号来表示在动态改变的字符或字符串.在struts.xml的test包中添加一个action,如下:

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%20%3Caction%20name%3D%22*User%22%20class%3D%22cn.gkit.action.HelloWorldAction%22%20method%3D%22%7B1%7D%22%20%3E%0A%20%20%20%20%20%20%20%20%09%3Cparam%20name%3D%22message%22%3E%E5%B1%9E%E6%80%A7%E6%B3%A8%E5%85%A5%3C%2Fparam%3E%0A%09%3Cresult%20name%3D%22success%22%3E%2FWEB-INF%2Fjsp%2Fhelloworld.jsp%3C%2Fresult%3E%20%0A%20%3C%2Faction%3E" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. < action   name = "*User"   class = "cn.gkit.action.HelloWorldAction"   method = "{1}"   >   
  2.         < param   name = "message" > 属性注入 </ param >   
  3. < result   name = "success" > /WEB-INF/jsp/helloworld.jsp </ result >    
  4. </ action >   
 <action name="*User" class="cn.gkit.action.HelloWorldAction" method="{1}" >
        	<param name="message">属性注入</param>
	<result name="success">/WEB-INF/jsp/helloworld.jsp</result> 
 </action>

    此时 如果要访问action的del() 方法,我们可以这样调用:/struts2.1/test/delUser 即可调用到del()方法.

    知识提示: {1}表示与第一个*号匹配,{1}不但可以在method属性上使用,还可以在其他地方使用,如在<result>使用:

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%3Cresult%20name%3D%22success%22%3E%2FWEB-INF%2Fjsp%2F%7B1%7D.jsp%3C%2Fresult%3E%20%0A" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. < result   name = "success" > /WEB-INF/jsp/{1}.jsp </ result >    
<result name="success">/WEB-INF/jsp/{1}.jsp</result> 

 

 八、自定义类型转换器 

        问题引入 :对于Date类型的属性,可以接收格式为2009-12-20的请求参数值,并将其自动转换成Date类型.但如果项目需求要接收形如:20091220格式的日期该怎么办,在struts1.x中我们可以通过定义类型转换器来实现,同样在Struts2.x里我们也可以定义类似的转换器,并且比struts1.x的转换器要强大,它实现了双向转换的功能.

 

      8.1   定义局部类型转换器

 

       首先在HelloWorldAction里增加一个java.util.Date 类型的birthday字段,并提供getter和setter方法.如下:

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=%09private%20Date%20birthday%3B%0A%0A%09public%20Date%20getBirthday()%20%7B%0A%09%09return%20birthday%3B%0A%09%7D%0A%0A%09public%20void%20setBirthday(Date%20birthday)%20%7B%0A%09%09this.birthday%20%3D%20birthday%3B%0A%09%7D" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. private  Date birthday;  
  2.   
  3. public  Date getBirthday() {  
  4.     return  birthday;  
  5. }  
  6.   
  7. public   void  setBirthday(Date birthday) {  
  8.     this .birthday = birthday;  
  9. }  
	private Date birthday;

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

      然后: 定义Date类型转换器,定义转器有两种方式:

      第一种是继承com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter类,重写它的convertValue方法,实现如下:

 

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20class%20DateTypeConverter%20extends%20DefaultTypeConverter%7B%0A%09%40Override%0A%09public%20Object%20convertValue(Map%3CString%2C%20Object%3E%20context%2C%20Object%20value%2C%0A%09%09%09Class%20toType)%20%7B%0A%09%09SimpleDateFormat%20dateFormat%20%3D%20new%20SimpleDateFormat(%22yyyyMMdd%22)%3B%0A%09%09try%20%7B%20%0A%09%09%09if(toType%20%3D%3D%20Date.class)%7B%2F%2F%E5%BD%93%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%90%91Date%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E6%97%B6%0A%09%09%09%09String%5B%5D%20params%20%3D%20(String%5B%5D)%20value%3B%2F%2F%20Request.getParameterValues()%20%0A%09%09%09%09return%20dateFormat.parse(params%5B0%5D)%3B%0A%09%09%09%7Delse%20if(toType%20%3D%3D%20String.class)%7B%2F%2F%E5%BD%93Date%E8%BD%AC%E6%8D%A2%E6%88%90%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%97%B6%0A%09%09%09%09Date%20date%20%3D%20(Date)%20value%3B%0A%09%09%09%09return%20dateFormat.format(date)%3B%0A%09%09%09%7D%0A%09%09%7D%20catch%20(ParseException%20e)%20%7B%7D%0A%09%09return%20null%3B%0A%09%09%7D%0A%7D" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. public   class  DateTypeConverter  extends  DefaultTypeConverter{  
  2.     @Override   
  3.     public  Object convertValue(Map<String, Object> context, Object value,  
  4.             Class toType) {  
  5.         SimpleDateFormat dateFormat = new  SimpleDateFormat( "yyyyMMdd" );  
  6.         try  {   
  7.             if (toType == Date. class ){ //当字符串向Date类型转换时   
  8.                 String[] params = (String[]) value;// Request.getParameterValues()    
  9.                 return  dateFormat.parse(params[ 0 ]);  
  10.             }else   if (toType == String. class ){ //当Date转换成字符串时   
  11.                 Date date = (Date) value;  
  12.                 return  dateFormat.format(date);  
  13.             }  
  14.         } catch  (ParseException e) {}  
  15.         return   null ;  
  16.         }  
  17. }  
public class DateTypeConverter extends DefaultTypeConverter{
	@Override
	public Object convertValue(Map<String, Object> context, Object value,
			Class toType) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
		try { 
			if(toType == Date.class){//当字符串向Date类型转换时
				String[] params = (String[]) value;// Request.getParameterValues() 
				return dateFormat.parse(params[0]);
			}else if(toType == String.class){//当Date转换成字符串时
				Date date = (Date) value;
				return dateFormat.format(date);
			}
		} catch (ParseException e) {}
		return null;
		}
}

 

    第二种方式是继承org.apache.struts2.util.strutsTypeConverter类,并实现它的两个抽象方法,实现代码如下:

 

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20class%20DateTypeConverter%20extends%20StrutsTypeConverter%20%7B%0A%09SimpleDateFormat%20dateFormat%20%3D%20new%20SimpleDateFormat(%22yyyyMMdd%22)%3B%0A%09%40Override%0A%09public%20Object%20convertFromString(Map%20context%2C%20String%5B%5D%20value%2C%20Class%20toType)%20%7B%0A%09%09String%5B%5D%20params%20%3D%20(String%5B%5D)%20value%3B%2F%2F%20Request.getParameterValues()%20%0A%09%09try%20%7B%0A%09%09%09return%20dateFormat.parse(params%5B0%5D)%3B%0A%09%09%7D%20catch%20(ParseException%20e)%20%7B%7D%0A%09%09return%20null%3B%0A%09%7D%0A%0A%09%40Override%0A%09public%20String%20convertToString(Map%20context%2C%20Object%20value)%20%7B%0A%09%09Date%20date%20%3D%20(Date)%20value%3B%0A%09%09return%20dateFormat.format(date)%3B%0A%09%7D%0A%7D" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. public   class  DateTypeConverter  extends  StrutsTypeConverter {  
  2.     SimpleDateFormat dateFormat = new  SimpleDateFormat( "yyyyMMdd" );  
  3.     @Override   
  4.     public  Object convertFromString(Map context, String[] value, Class toType) {  
  5.         String[] params = (String[]) value;// Request.getParameterValues()    
  6.         try  {  
  7.             return  dateFormat.parse(params[ 0 ]);  
  8.         } catch  (ParseException e) {}  
  9.         return   null ;  
  10.     }  
  11.   
  12.     @Override   
  13.     public  String convertToString(Map context, Object value) {  
  14.         Date date = (Date) value;  
  15.         return  dateFormat.format(date);  
  16.     }  
  17. }  
public class DateTypeConverter extends StrutsTypeConverter {
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
	@Override
	public Object convertFromString(Map context, String[] value, Class toType) {
		String[] params = (String[]) value;// Request.getParameterValues() 
		try {
			return dateFormat.parse(params[0]);
		} catch (ParseException e) {}
		return null;
	}

	@Override
	public String convertToString(Map context, Object value) {
		Date date = (Date) value;
		return dateFormat.format(date);
	}
}

    知识提示: 查找StrutsTypeConverter的源码发现,它本身也继承了DefaultTypeConverter类.StrutsTypeConverter类使用的一种设计模式是模板方法设计模式 ,在http://yulon.iteye.com/admin/blogs/550501 这里有讲到模板方法模式在项目中的应用.

 

        最后 ,配置要使用该转换器的action类

        在HelloWorldAction同一包内新建HelloWorldAction-conversion.properties文件.文件名的后半部分是固定不变的

*-conversion.properties,*表示的是对应的Action的简单类名(即不带包名),在该文件里如下定义:

Xml代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=birthday%3Dcn.gkit.type.converter.DateTypeConverter%0A" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. birthday = cn .gkit.type.converter.DateTypeConverter  
birthday=cn.gkit.type.converter.DateTypeConverter

 birthday表示要转换的属性,右边对应一个转换器.

此时访问路径:/struts2.1/test/helloworld.action?birthday=20091220,Struts框架就是使用刚才定义的转换器将String类型转换成java.util.Date类型.

 

     8.2  定义全局类型转换器

           全局类型转换器的配置文件名是固定的:xwork-conversion.properties,并将该文件放到src目录,编译后会自动WEB-INF\classes目录下.在该文件里如下定义:

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=java.util.Date%3Dcn.gkit.type.converter.DateTypeConverter" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. java.util.Date=cn.gkit.type.converter.DateTypeConverter  
java.util.Date=cn.gkit.type.converter.DateTypeConverter

    左边定义的是要转换的类型,作用了全部Action类.

    注意: 如果同时定义了局部和全局的类型转换器,对于同一个类型,局部会覆盖全局的转换器

 

 相关文章:http://yulon.iteye.com/admin/blogs/551982 (struts2.1两天快速入门(第一天上午))

由于拦截器的重要性,决定将其从(struts2.1两天快速入门第一天下午  抽取出来讲)

 

本讲将结合模拟用户权限验证展开:判断用户是否有权限请求访问某一模块或页面 .

 

第九讲、自定义拦截器

 

   9.1 首先定义一个User实体类,如下:

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20class%20User%20implements%20Serializable%20%7B%0A%09private%20String%20username%3B%0A%09private%20String%20password%3B%0A%09public%20String%20getUsername()%20%7B%0A%09%09return%20username%3B%0A%09%7D%0A%09public%20void%20setUsername(String%20username)%20%7B%0A%09%09this.username%20%3D%20username%3B%0A%09%7D%0A%09public%20String%20getPassword()%20%7B%0A%09%09return%20password%3B%0A%09%7D%0A%09public%20void%20setPassword(String%20password)%20%7B%0A%09%09this.password%20%3D%20password%3B%0A%09%7D%0A%7D" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. public   class  User  implements  Serializable {  
  2.     private  String username;  
  3.     private  String password;  
  4.     public  String getUsername() {  
  5.         return  username;  
  6.     }  
  7.     public   void  setUsername(String username) {  
  8.         this .username = username;  
  9.     }  
  10.     public  String getPassword() {  
  11.         return  password;  
  12.     }  
  13.     public   void  setPassword(String password) {  
  14.         this .password = password;  
  15.     }  
  16. }  
public class User implements Serializable {
	private String username;
	private String password;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
}

  9.2 编写一个用户登陆的Action类,如下:

Java代码 <embed type="application/x-shockwave-flash" width="14" height="15" src="http://yulon.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" flashvars="clipboard=public%20class%20UserLoginAction%20%7B%0A%09%2F%2F%E6%8E%A5%E6%94%B6%E5%A4%8D%E5%90%88%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8F%82%E6%95%B0%2C%E4%B8%8Estruts1.x%E7%9B%B8%E7%B1%BB%E4%BC%BC%2C%E6%AD%A4%E6%97%B6%E8%A1%A8%E5%8D%95%E7%9A%84%E5%85%83%E7%B4%A0%E5%90%8D%E7%A7%B0%0A%09%2F%2F%E5%BA%94%E8%AF%A5%E4%B8%BA%3Auser.username%20%20%20user.password%0A%09private%20User%20user%3B%20%20%0A%09public%20User%20getUser()%20%7B%0A%09%09return%20user%3B%0A%09%7D%0A%09public%20void%20setUser(User%20user)%20%7B%0A%09%09this.user%20%3D%20user%3B%0A%09%7D%0A%09public%20String%20execute()%7B%0A%09%2F%2F%E6%A8%A1%E6%8B%9F%E7%94%A8%E6%88%B7%E7%99%BB%E9%99%86%2C%E5%AE%9E%E9%99%85%E5%BA%94%E7%94%A8%E6%98%AF%E4%BB%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E9%87%8C%E5%8F%96%E7%9A%84%2C%E8%BF%99%E9%87%8C%E5%8F%AA%E6%98%AF%E4%B8%BA%E4%BA%86%E6%96%B9%E4%BE%BF%E6%B5%8B%E8%AF%95%E5%92%8C%E5%AD%A6%E4%B9%A0%09%0A%09if(%22yulon%22.equals(user.getUsername())%26%26%22123456%22.equals(user.getPassword()))%7B%0A%09%09%2F%2F%E4%B8%BA%E4%BA%86%E4%B8%8D%E8%AE%A9%E6%88%91%E4%BB%AC%E7%9C%8B%E5%88%B0%E7%9C%9F%E6%AD%A3%E7%9A%84session%2Cstruts2%E6%A1%86%E6%9E%B6%E5%AF%B9%E5%85%B6%E4%BD%9C%E4%BA%86%E4%B8%80%E5%B1%82%E5%B0%81%E8%A3%85%2C%E7%94%A8%E4%B8%80%E4%B8%AAMap%E5%AF%B9%E8%B1%A1%E6%9D%A5%E5%AD%98%E5%82%A8.%0A%09%09%2F%2FMap%20map%20%3D%20ActionContext.getContext().getSession()%3B%0A%09%09%2F%2Fmap.put(%22user%22%2C%20user)%3B%0A%09%09%2F%2F%E6%8A%8A%E4%B8%A4%E6%AE%B5%E4%BB%A3%E7%A0%81%E5%90%88%E6%88%90%E4%B8%80%E6%AE%B5%2C%E5%B0%B1%E4%B8%8D%E7%94%A8%E5%AF%BC%E5%85%A5Map%E7%B1%BB%0A%09%09ActionContext.getContext().getSession().put(%22user%22%2C%20user)%3B%0A%09%09return%20Action.SUCCESS%3B%20%20%20%2F%2F%E8%BF%94%E5%9B%9E%E5%88%B0%E6%AC%A2%E8%BF%8E%E9%A1%B5%E9%9D%A2%0A%09%20%7D%0A%09%09ActionContext.getContext().put(%22msg%22%2C%20%22%E7%94%A8%E6%88%B7%E7%99%BB%E9%99%86%E5%A4%B1%E8%B4%A5!%22)%3B%0A%09%09%2F%2F%E8%BF%94%E5%9B%9E%E5%88%B0%E7%99%BB%E9%99%86%E9%A1%B5%E9%9D%A2%2Cstruts%E5%AE%9A%E4%B9%89%E4%BA%86%E4%B8%80%E7%B3%BB%E5%88%97%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F%2C%E6%96%B9%E4%BE%BF%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%2C%E7%BB%9F%E4%B8%80%E7%9A%84%E5%A5%BD%E5%A4%84%0A%09%09return%20Action.LOGIN%3B%20%20%20%0A%09%7D%0A%7D" quality="high" allowscriptaccess="always" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
  1. public   class  UserLoginAction {  
  2.     //接收复合类型的参数,与struts1.x相类似,此时表单的元素名称   
  3.     //应该为:user.username   user.password   
  4.     private  User user;    
  5.     public  User getUser() {  
  6.         return  user;  
  7.     }  
  8.     public   void  setUser(User user) {  
  9.         this .user = user;  
  10.     }  
  11.     public  String execute(){  
  12.     //模拟用户登陆,实际应用是从数据库里取的,这里只是为了方便测试和学习    
  13.     if ( "yulon" .equals(user.getUsername())&& "123456" .equals(user.getPassword())){  
  14.         //为了不让我们看到真正的session,struts2框架对其作了一层封装,用一个Map对象来存储.   
  15.         //Map map = ActionContext.getContext().getSession();   
  16.         //map.put("user", user);   
  17.         //把两段代码合成一段,就不用导入Map类   
  18.         ActionContext.getContex
    分享到:
    评论

相关推荐

    Struts2.1权威指南——基于WebWork核心的MVC开发.zip

    书中通过大量的示范性实例(全书范例近百个),逐一、详细地讲解了Struts2各知识点的用法,并细致地讲解每个用法的各种参数、选项,可以帮助读者入门到精通。 3.配合案例,快速提高 《Struts 2.1权威指南》最后配备...

    Struts2.1 源码+开发包(项目依赖库)

    Struts2.1源码+Struts2.1依赖库(jar包)

    struts2.1完整jar包

    struts2.1完整jar包。内容齐全。

    Struts2.1权威指南2

    Struts2.1权威指南 李刚的著作 共四个部分 用7-zip解压

    struts2.1 jar包

    struts2.1在tomcat下载的包总是报错,根据tomcat官方解释修改后无任何错误,并且已经运行

    struts2.0升级到struts2.1的工具

    struts2.0升级到struts2.1的工具,自动修改配置文件和页面

    Myeclipse8.5下搭建SSH框架(图解)Struts2.1+Spring3.0+Hibernate3.3

    Myeclipse8.5下搭建SSH框架(图解)Struts2.1+Spring3.0+Hibernate3.3

    Struts2.1的jar包

    Struts2.1的jar包

    Struts 2.1 权威指南 part13 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part04 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part01 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part02 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part06 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part03 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part05 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part11 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part12 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part10 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part09 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

    Struts 2.1 权威指南 part07 pdf

    本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。  本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...

Global site tag (gtag.js) - Google Analytics