- 浏览: 165919 次
- 性别:
- 来自: 天堂
最新评论
-
woodpeckerboy:
您好 。我这边也遇到了这种怪问题 。也是按照你说的那样导入ja ...
JSTL http://java.sun.com/jsp/jstl/core -
henuhaigang:
[color=darkred]jk[size=x-small] ...
AJAX学习之序列二:struts2 jquery json 实现AJAX 注册ID验证 -
king_jw:
不错,学习了
Web Service学习,用于web service实现的两个主要的框架axis和xfire. -
Mr0o0rM:
顶顶顶顶顶顶
SOAP -
tengfeineu:
...
AJAX学习之序列二:struts2 jquery json 实现AJAX 注册ID验证
第一天上午学习目录列表:
一、第一个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 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 >
<?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中的配置如下:
- < 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 >
<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类,代码如下:
- public class HelloWorldAction {
- private String message;
- public String getMessage() {
- return message;
- }
- //返回的是一个字符串
- public String execute(){
- message = "struts2版的HelloWorld" ;
- return "success" ;
- }
- }
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里的配置:
- <?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>
<?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信息:
- <%@ 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>
<%@ 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请求
- < action name = "registerUI" >
- < result > /WEB-INF/page/register.jsp </ result >
- </ action >
<action name="registerUI"> <result>/WEB-INF/page/register.jsp</result> </action>
知识提示: 当访问路径/struts2.1/test/registerUI时,返回给浏览器的就是register.jsp页面.配置相当于struts1.x,如下:
- < 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>改成如下:
- < 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文件源代码的时候,我们可以使用此类型。配置如下:
- <result name= "source" type= "plainText " >
- <param name="location" >/view.jsp</param>
- <param name="charSet" >UTF- 8 </param><!-- 指定读取文件的编码 -->
- </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方法:
- public void setMessage(String message) {
- this .message = message;
- }
public void setMessage(String message) { this.message = message; }
2、为了避免覆盖,将execute方法里给message赋值的那一段代码注释掉.
3、在struts.xml配置文件的<action>增加一个子标签<param name="">,配置改成如下:
- < package name = "test" namespace = "/test" extends = "struts-default" >
- < action name = "helloworld" class = "cn.gkit.action.HelloWorldAction" method = "execute" >
- < param name = "message" > 属性注入 </ param >
- t;result name = "success" > /WEB-INF/jsp/helloworld.jsp </ result >
- </ action >
- </ 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 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 >
<?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、如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号隔开。如:
- < 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里添加两个业务方法,如下:
- public String del() {
- message = "调用del()删除方法" ;
- return "success" ;
- }
- public String add() {
- message = "调用add()添加方法" ;
- return "success" ;
- }
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,如下:
- < 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 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>使用:
- < 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方法.如下:
- private Date birthday;
- public Date getBirthday() {
- return birthday;
- }
- public void setBirthday(Date birthday) {
- this .birthday = birthday;
- }
private Date birthday; public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; }
然后: 定义Date类型转换器,定义转器有两种方式:
第一种是继承com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter类,重写它的convertValue方法,实现如下:
- 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 ;
- }
- }
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类,并实现它的两个抽象方法,实现代码如下:
- 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);
- }
- }
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的简单类名(即不带包名),在该文件里如下定义:
- 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.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实体类,如下:
- 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;
- }
- }
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类,如下:
- public class UserLoginAction {
- //接收复合类型的参数,与struts1.x相类似,此时表单的元素名称
- //应该为:user.username user.password
- private User user;
- public User getUser() {
- return user;
- }
- public void setUser(User user) {
- this .user = user;
- }
- public String execute(){
- //模拟用户登陆,实际应用是从数据库里取的,这里只是为了方便测试和学习
- if ( "yulon" .equals(user.getUsername())&& "123456" .equals(user.getPassword())){
- //为了不让我们看到真正的session,struts2框架对其作了一层封装,用一个Map对象来存储.
- //Map map = ActionContext.getContext().getSession();
- //map.put("user", user);
- //把两段代码合成一段,就不用导入Map类
-
ActionContext.getContex
发表评论
-
struts2 使用之我见
2010-01-12 11:52 70struts2 使用之我见 Struts2 是一个相当强 ... -
MySQL查询优化系列讲座之查询优化器
2010-01-07 00:33 310MySQL查询优化系列讲座之查询优化器 当你提交一个查询的时 ... -
MySQL 命令行
2010-01-07 00:26 84MySQL 命令行 第一招、mysql服务的启动和停止 ... -
MySQL中SQL优化和架构设计的一些简单想法
2010-01-06 17:34 395MySQL中SQL优化和架构设计的一些简单想法普通MySQL运 ... -
我的mysql 优化日记
2010-01-06 17:24 1055同时在线访问量继续 ... -
mysql优化
2010-01-06 17:00 980在整体的系统运行过程 ... -
我也谈谈JAVA并发程序设计的现状和前景
2010-01-06 12:07 1300最近我也是在涉及并发J ... -
SVN配置
2010-01-05 23:12 1033在大学期间为了配这个S ... -
Easy Ajax with jQuery
2009-12-25 01:00 1094Ajax is changing web applicatio ... -
Use jquery remote validation with struts2
2009-12-25 00:00 164I feel that jquery’s vali ... -
实战DDD(Domain-Driven Design领域驱动设计:Evans DDD)
2009-12-24 17:53 1226http://www.jdon.com//mda/ddd.ht ... -
面向对象与领域建模
2009-12-24 17:36 836多变且复杂的需求 ... -
How to Write an Effective Design Document
2009-12-24 17:00 1262http://blog.slickedit.com/2007/ ... -
已经会struts1.x了为何还要学习struts2呢
2009-12-24 15:44 956一、首先,一个新版本的程序是为了解决老版本的一些bug而出世. ... -
AJAX学习之序列二:struts2 jquery json 实现AJAX 注册ID验证
2009-12-24 14:09 2624http://blog.csdn.net/abing37/ar ... -
如何写一个好的需求文档
2009-12-24 11:01 10031、从用户角度的编写 ... -
MRD
2009-12-24 10:59 846MRD ... -
软件开发从文档做起
2009-12-24 10:52 749说起文档,首先我从即 ... -
设计与开发的五条原则–六年真谛
2009-12-24 10:47 732这篇文章发表于我的博 ... -
接口开发及技术负责人的职责随笔
2009-12-24 10:35 2094对于网站或者平台,大 ...
相关推荐
书中通过大量的示范性实例(全书范例近百个),逐一、详细地讲解了Struts2各知识点的用法,并细致地讲解每个用法的各种参数、选项,可以帮助读者入门到精通。 3.配合案例,快速提高 《Struts 2.1权威指南》最后配备...
Struts2.1是Apache软件基金会的开源框架Struts的第二个主要版本,它基于MVC(Model-View-Controller)设计模式,为Java Web应用程序提供了一种强大的开发框架。Struts2的核心目标是简化Web应用的开发过程,提高代码...
### Struts 2.1 教程知识点解析 #### 一、Struts 2.1 概述 - **框架定义**:Struts 2.1 是一款基于Java的开源Web应用开发框架,继承了Struts 1.x的优秀特性,并在很多方面进行了改进和优化。它提供了一种构建可扩展...
Struts 2.1 是一个基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架,由Apache软件基金会维护。它旨在提供一个结构化的、可扩展的平台,帮助开发者构建可维护性高、易于扩展的企业级Web应用。在这个...
Struts2.1权威指南 李刚的著作 共四个部分 用7-zip解压
struts2.1在tomcat下载的包总是报错,根据tomcat官方解释修改后无任何错误,并且已经运行
Struts2.1是Apache软件基金会的开源框架,主要用于构建基于Java EE的Web应用程序。它在Struts1的基础上进行了重大改进,提供了更强大的MVC(Model-View-Controller)架构支持,增强了动作处理、异常处理、国际化、...
struts2.0升级到struts2.1的工具,自动修改配置文件和页面
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...
本书最后配备的两个常用的实例也都升级为基于Struts 2.1运行,读者可通过这两个实例触类旁通,解决日常开发中的问题。 本书第二版保留了第一版通俗易懂的写作风格:按Struts 2.1的架构体系,细致地介绍了Struts ...