2007-12-31
struts与spring如何整合
关键字: spring struts
一、struts与spring如何整合
线索从web.xml看起
这里我们要关注的是两个地方的配置文件
1、/WEB-INF/spring/*.spring.xml
2、/WEB-INF/struts/struts-config.xml,/WEB-INF/struts/action/fileupload-action-config.xml,/WEB-INF/struts/action/demo-action-config.xml
{1}中放置的配置文件是关于service层的配置
如:demo.spring.xml
{2}中放置的都是struts的配置文件
如:/WEB-INF/sturts/action/demo-action-config.xml
而衔接struts与spring的地方是在struts-config.xml中体现
/WEB-INF/struts/struts-config.xml:
要知道Struts转发的一个重要类是RequestProcessor,而现在通过对controller的设置将转发类被org.springframework.web.struts.DelegatingRequestProcessor替换,
而org.springframework.web.struts.DelegatingRequestProcessor只是封装了RequestProcessor,这样struts的转发就由spring来处理了。
问题:这里的plug-in标签的作用是什么?可以不写plugin-in这个标签吗?
1、其实plug-in只是为了装载Struts的ActionServlet用的,如果在web.xml的context-param中已经指定了这个Struts的ActionServlet配置文件,那么此时可以不写plug-in。
2、如果在web.xml的context-param中并没有指定这个Struts的ActionServlet配置文件,那么必须加上plug-in
3、plug-in中contextConfigLocation属性的作用是什么?可以不要这个属性吗?
如果用了plug-in,那么contextConfigLocation属性的作用是指定Struts的ActionServlet配置文件所在的位置;
如果去掉了contextConfigLocation属性,那么Struts的ActionServlet配置文件将被指定为/WEB-INF/{app}-servlet.xml文件,
({app}指的是web.xml中servlet-name的值,此处为"action"
)
所以,这是就必须在/WEB-INF/下存在action-servlet.xml文件。
现在默认的/WEB-INF/action-servlet.xml文件或由plug-in的contextConfigLocation属性指定的/WEB-INF/struts/spring/demo-action.spring.xml文件内容应该结合
web.xml的struts配置中指定的config文件内容可以这样写:
其实这样配置的目的也就是为了利用spring的依赖注入,能够使得Struts的servletAction自如的使用service层的bean。
这里需要关注的一点是:
请看/WEB-INF/struts/action/demo-action-config.xml中的
和/WEB-INF/struts/spring/demo-action.spring.xml中的
当url中执行..../demo/test.do时,将会是个什么样的过程?
首先会到/WEB-INF/struts/spring/demo-action.spring.xml中去找name为"/demo/test"的bean,
1、找到了,则执行target属性中指定的bean(此bean就是ServletAction类):com.ramix.demo.webapp.action.Test的execute方法,并通过autowire="byName"对该类的set方法进行依赖注入。
2、没找到,才会去/WEB-INF/struts/action/demo-action-config.xml中去找/demo/test.do,
并执行type属性中指定的ServletAction:com.ramix.demo.webapp.action.DemoListAction的execute方法
提问:servletAction中必须要写execute方法吗?
如果真的写了execute方法,那么就失去了parameter="method"的意义,如果这样做的话,那势必每个功能(通过页面操作增删改查)都需要写一个action类,这样会导致action类数量的急剧膨胀。
其实,struts的DispatchAction的execute方法被执行时,他的机制是去获得method参数,如果该参数有值,那么会去执行这个元素对应的方法。比如url是这样的.../demo/test.do?method=test
就会去执行对应的servletAction类中的test方法;如果method参数没有值,则会去执行unspecified方法。
这样我们可以通过在servletAction中多写几个方法就能很好的解决这个action类急剧膨胀的问题,从管理上看还能更加的简介。
所以如果重写了execute方法,那么就失去了这些功能。
现在可以看看com.ramix.demo.webapp.action.Test类可以怎么写了:
unspecified是不带method参数是执行的方法
test是method参数值为test是执行的方法
当然如果应用很简单的,你并不需要parameter="method"的话,你非要写上execute方法也没有关系,就像下面代码这样:
线索从web.xml看起
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>app name</display-name>
<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>com.ramix.common.util.InitPlatformLoader</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.spring.xml
</param-value>
</context-param>
<!-- Spring的过滤器 -->
<filter>
<filter-name>OpenSessionFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 编码转换过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.ramix.common.webapp.filter.EncodingFilter</filter-class>
</filter>
<!--sitemesh过滤器-->
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
<init-param>
<param-name>configFile</param-name>
<param-value>/WEB-INF/classes/sitemesh.xml</param-value>
</init-param>
</filter>
<!--session-->
<filter-mapping>
<filter-name>OpenSessionFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!--encode-->
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!--sitemesh过滤-->
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!-- struts 的配置 -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>
/WEB-INF/struts/struts-config.xml,
/WEB-INF/struts/action/fileupload-action-config.xml,
/WEB-INF/struts/action/demo-action-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!--showpic-->
<servlet>
<servlet-name>showphoto</servlet-name>
<servlet-class>com.ramix.demo.webapp.servlet.ShowParentPicServlet</servlet-class>
<init-param>
<param-name>noimage</param-name>
<param-value>/images/noimage.gif</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>showphoto</servlet-name>
<url-pattern>/showphoto</url-pattern>
</servlet-mapping>
<!--cxf-->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/page/common/e404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/page/common/e500.jsp</location>
</error-page>
</web-app>
这里我们要关注的是两个地方的配置文件
1、/WEB-INF/spring/*.spring.xml
2、/WEB-INF/struts/struts-config.xml,/WEB-INF/struts/action/fileupload-action-config.xml,/WEB-INF/struts/action/demo-action-config.xml
{1}中放置的配置文件是关于service层的配置
如:demo.spring.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="parentManager" parent="baseTxService"> <property name="target"> <bean class="com.ramix.demo.service.impl.ParentManagerImpl" autowire="byName"> <property name="childMgr" ref="childManager"/> </bean> </property> </bean> <bean id="childManager" parent="baseTxService"> <property name="target"> <bean class="com.ramix.demo.service.impl.ChildManagerImpl" autowire="byName"/> </property> </bean> <bean id="jdbcManager" parent="baseTxService"> <property name="target"> <bean class="com.ramix.demo.service.impl.JdbcManagerImpl" autowire="byName" parent="jdbcDao"/> </property> </bean> </beans>
{2}中放置的都是struts的配置文件
如:/WEB-INF/sturts/action/demo-action-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd"> <struts-config> <action-mappings> <action path="/demo/list" type="com.ramix.demo.webapp.action.DemoListAction" parameter="method" scope="request" name="globalForm"> <forward name="view" path="/WEB-INF/page/demo/list.jsp"/> </action> <action path="/demo/create" forward="/WEB-INF/page/demo/create.jsp"/> <action path="/demo/save" type="com.ramix.demo.webapp.action.DemoSaveAction" parameter="method" scope="request" name="globalForm"> <forward name="view" path="/demo/list.do"/> </action> <action path="/demo/client" type="com.ramix.demo.webapp.action.DemoClientAction" parameter="method" scope="request" name="globalForm"> <forward name="view" path="/WEB-INF/page/demo/client.jsp"/> </action> <action path="/demo/mail" forward="/WEB-INF/page/demo/sendmail.jsp"/> <action path="/demo/send" type="com.ramix.demo.webapp.action.DemoSendAction" parameter="method" scope="request" name="globalForm"/> <action path="/demo/child/create" type="com.ramix.demo.webapp.action.DemoChildCreateAction" parameter="method" scope="request" name="globalForm"> <forward name="view" path="/WEB-INF/page/demo/child_create.jsp"/> </action> <action path="/demo/child/save" type="com.ramix.demo.webapp.action.DemoChildSaveAction" parameter="method" scope="request" name="globalForm"/> <action path="/demo/child/list" type="com.ramix.demo.webapp.action.DemoChildListAction" parameter="method" scope="request" name="globalForm"> <forward name="view" path="/WEB-INF/page/demo/child_list.jsp"/> </action> <action path="/demo/cahce_list" forward="/WEB-INF/page/demo/cache.jsp"/> <action path="/demo/child/list/ajax" forward="/WEB-INF/page/demo/child_list_ajax.jsp"/> <action path="/demo/ajax/child/list" type="com.ramix.demo.webapp.action.DemoAjaxChildListAction" parameter="method" scope="request" name="globalForm"> <forward name="view" path="/WEB-INF/page/demo/ajax_list.jsp"/> </action> <action path="/demo/test" type="com.ramix.demo.webapp.action.DemoListAction" parameter="method" scope="request" name="globalForm"> <forward name="test" path="/WEB-INF/page/demo/test.jsp"/> </action> </action-mappings> </struts-config>
而衔接struts与spring的地方是在struts-config.xml中体现
/WEB-INF/struts/struts-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<form-beans>
<form-bean name="globalForm" type="org.apache.struts.action.DynaActionForm"/>
</form-beans>
<global-forwards>
<forward name="globalError" path="/WEB-INF/page/common/error.jsp"/>
<forward name="globalSuccess" path="/WEB-INF/page/common/success.jsp"/>
</global-forwards>
<!--
利用了 <controller> 标记来用 DelegatingRequestProcessor 覆盖默认的 Struts RequestProcessor。
下一步是在 Spring 配置文件中注册该动作
DelegatingRequestProcessor自动地配置属性。这种设计使 Struts 动作并不知道它正被 Spring 管理,并且使您能够利用 Sping 的动作管理框架的所有优点。
在请求转发给action之前,转发给Spring的Bean
-->
<controller>
<set-property property="processorClass"
value="org.springframework.web.struts.DelegatingRequestProcessor"/>
</controller>
<!--
装载环境:需要使用 Spring 的 ContextLoaderPlugin 为 Struts 的 ActionServlet 装载 Spring 应用程序环境
-->
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/struts/spring/demo-action.spring.xml"/>
</plug-in>
</struts-config>
要知道Struts转发的一个重要类是RequestProcessor,而现在通过对controller的设置将转发类被org.springframework.web.struts.DelegatingRequestProcessor替换,
而org.springframework.web.struts.DelegatingRequestProcessor只是封装了RequestProcessor,这样struts的转发就由spring来处理了。
问题:这里的plug-in标签的作用是什么?可以不写plugin-in这个标签吗?
1、其实plug-in只是为了装载Struts的ActionServlet用的,如果在web.xml的context-param中已经指定了这个Struts的ActionServlet配置文件,那么此时可以不写plug-in。
2、如果在web.xml的context-param中并没有指定这个Struts的ActionServlet配置文件,那么必须加上plug-in
3、plug-in中contextConfigLocation属性的作用是什么?可以不要这个属性吗?
如果用了plug-in,那么contextConfigLocation属性的作用是指定Struts的ActionServlet配置文件所在的位置;
如果去掉了contextConfigLocation属性,那么Struts的ActionServlet配置文件将被指定为/WEB-INF/{app}-servlet.xml文件,
({app}指的是web.xml中servlet-name的值,此处为"action"
<!-- struts 的配置 --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value> /WEB-INF/struts/struts-config.xml, /WEB-INF/struts/action/fileupload-action-config.xml, /WEB-INF/struts/action/demo-action-config.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
)
所以,这是就必须在/WEB-INF/下存在action-servlet.xml文件。
现在默认的/WEB-INF/action-servlet.xml文件或由plug-in的contextConfigLocation属性指定的/WEB-INF/struts/spring/demo-action.spring.xml文件内容应该结合
web.xml的struts配置中指定的config文件内容可以这样写:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean name="/demo/list" parent="baseTxService">
<property name="target">
<bean class="com.ramix.demo.webapp.action.DemoListAction" autowire="byName">
<property name="mgr" ref="parentManager"/>
</bean>
</property>
</bean>
<bean name="/demo/save" parent="baseTxService">
<property name="target">
<bean class="com.ramix.demo.webapp.action.DemoSaveAction" autowire="byName">
<property name="mgr" ref="parentManager"/>
</bean>
</property>
</bean>
<bean name="/demo/client" class="com.ramix.demo.webapp.action.DemoClientAction">
<property name="dws" ref="demoClient"/>
</bean>
<bean name="/demo/send" class="com.ramix.demo.webapp.action.DemoSendAction">
<property name="mgr" ref="mailSendManager"/>
</bean>
<bean name="/demo/child/create" parent="baseTxService">
<property name="target">
<bean class="com.ramix.demo.webapp.action.DemoChildCreateAction" autowire="byName">
<property name="mgr" ref="parentManager"/>
</bean>
</property>
</bean>
<bean name="/demo/child/save" parent="baseTxService">
<property name="target">
<bean class="com.ramix.demo.webapp.action.DemoChildSaveAction" autowire="byName">
<property name="PMgr" ref="parentManager"/>
<property name="CMgr" ref="childManager"/>
</bean>
</property>
</bean>
<bean name="/demo/child/list" parent="baseTxService">
<property name="target">
<bean class="com.ramix.demo.webapp.action.DemoChildListAction" autowire="byName">
<property name="mgr" ref="childManager"/>
</bean>
</property>
</bean>
<bean name="/demo/ajax/child/list" parent="baseTxService">
<property name="target">
<bean class="com.ramix.demo.webapp.action.DemoAjaxChildListAction" autowire="byName">
<property name="mgr" ref="jdbcManager"/>
</bean>
</property>
</bean>
<bean name="/demo/test" parent="baseTxService">
<property name="target">
<bean class="com.ramix.demo.webapp.action.Test" autowire="byName">
</bean>
</property>
</bean>
</beans>
其实这样配置的目的也就是为了利用spring的依赖注入,能够使得Struts的servletAction自如的使用service层的bean。
这里需要关注的一点是:
请看/WEB-INF/struts/action/demo-action-config.xml中的
<action path="/demo/test" type="com.ramix.demo.webapp.action.DemoListAction" parameter="method" scope="request" name="globalForm"> <forward name="test" path="/WEB-INF/page/demo/test.jsp"/> </action>
和/WEB-INF/struts/spring/demo-action.spring.xml中的
<bean name="/demo/test" parent="baseTxService"> <property name="target"> <bean class="com.ramix.demo.webapp.action.Test" autowire="byName"> </bean> </property> </bean>
当url中执行..../demo/test.do时,将会是个什么样的过程?
首先会到/WEB-INF/struts/spring/demo-action.spring.xml中去找name为"/demo/test"的bean,
1、找到了,则执行target属性中指定的bean(此bean就是ServletAction类):com.ramix.demo.webapp.action.Test的execute方法,并通过autowire="byName"对该类的set方法进行依赖注入。
2、没找到,才会去/WEB-INF/struts/action/demo-action-config.xml中去找/demo/test.do,
并执行type属性中指定的ServletAction:com.ramix.demo.webapp.action.DemoListAction的execute方法
提问:servletAction中必须要写execute方法吗?
如果真的写了execute方法,那么就失去了parameter="method"的意义,如果这样做的话,那势必每个功能(通过页面操作增删改查)都需要写一个action类,这样会导致action类数量的急剧膨胀。
其实,struts的DispatchAction的execute方法被执行时,他的机制是去获得method参数,如果该参数有值,那么会去执行这个元素对应的方法。比如url是这样的.../demo/test.do?method=test
就会去执行对应的servletAction类中的test方法;如果method参数没有值,则会去执行unspecified方法。
这样我们可以通过在servletAction中多写几个方法就能很好的解决这个action类急剧膨胀的问题,从管理上看还能更加的简介。
所以如果重写了execute方法,那么就失去了这些功能。
现在可以看看com.ramix.demo.webapp.action.Test类可以怎么写了:
package com.ramix.demo.webapp.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.ramix.common.webapp.action.BaseAction;
public class Test extends BaseAction {
@Override
public ActionForward unspecified(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
request.setAttribute("test", "test");
return mapping.findForward("test");
}
public ActionForward test(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
request.setAttribute("test", request.getParameter("test"));
return mapping.findForward("test");
}
}
unspecified是不带method参数是执行的方法
test是method参数值为test是执行的方法
当然如果应用很简单的,你并不需要parameter="method"的话,你非要写上execute方法也没有关系,就像下面代码这样:
package com.ramix.demo.webapp.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.ramix.common.webapp.action.BaseAction;
public class Test extends BaseAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
System.out.println("ok");
System.out.println("ok1");
return null;
}
}
说明:这里的BaseAction只是对org.springframework.web.struts.DispatchActionSupport做了封装,代码如下:
package com.ramix.common.webapp.action;
import com.ramix.common.util.RequestParamUtil;
import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.struts.DispatchActionSupport;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* 基础的Action,提供一些action中最基本的方法
*
* @author: Feng
* @since: 2007-11-30
*/
public class BaseAction extends DispatchActionSupport {
// 用来输出log。
protected final Logger log = Logger.getLogger(this.getClass());
// 默认分页个数
protected static final int DEF_PAGE_SIZE = 10;
// 默认错误页
protected static final String DEF_VIEW_PAGE = "view";
// 默认错误页
protected static final String DEF_ERROR_PAGE = "globalError";
// 默认成功页
protected static final String DEF_SUCCESS_PAGE = "globalSuccess";
// 令牌名称
protected static final String TOKEN_KEY = "RIMAX_TOKEN";
/**
* 用来得到spring注入的bean。
*
* @param beanName 在spring配置文件中定义的bean的名字。
* @return 从ApplicationContext中得到的bean对象。
*/
protected Object getBean(String beanName) {
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servlet.getServletContext());
return ctx.getBean(beanName);
}
/**
* 从request取得目标页码,没有设置,默认显示第一页
*
* @param request HttpServletRequest
* @return 目标页码
*/
protected int getPageNum(HttpServletRequest request) {
return RequestParamUtil.getIntParam(request, "pageNum", 1);
}
/**
* 从request取得目标页码,没有设置,默认显示第一页
*
* @param request HttpServletRequest
* @return 目标页码
*/
protected int getPageSize(HttpServletRequest request) {
return RequestParamUtil.getIntParam(request, "pageSize", DEF_PAGE_SIZE);
}
/**
* 转向错误页面
*
* @param mapping ActionMapping
* @param request HttpServletRequest
* @param message 显示信息
* @param url 目标地址
* @return ActionForward
*/
protected ActionForward toGobalError(ActionMapping mapping, HttpServletRequest request, String message, String url) {
request.setAttribute("url", url);
request.setAttribute("message", message);
return mapping.findForward(DEF_ERROR_PAGE);
}
/**
* 转向全局成功页面
*
* @param mapping ActionMapping
* @param request HttpServletRequest
* @param message 显示信息
* @param url 目标地址
* @return ActionForward
*/
protected ActionForward toGobalSuccess(ActionMapping mapping, HttpServletRequest request, String message, String url) {
request.setAttribute("url", url);
request.setAttribute("message", message);
return mapping.findForward(DEF_SUCCESS_PAGE);
}
/**
* 验证当前提交的令牌,并不重置令牌
*
* @param request HttpServletRequest
* @return 令牌是否有效
*/
protected boolean validCurToken(HttpServletRequest request) {
HttpSession session = request.getSession();
if (session == null) {
return false;
}
Map map = (Map) session.getAttribute(TOKEN_KEY);
if (map == null) {
return true;
}
String strToken = request.getParameter(TOKEN_KEY);
if (strToken == null) {
return false;
}
return map.containsKey(strToken);
}
/**
* 删除当前令牌
*
* @param request HttpServletRequest
*/
protected void removeCurToken(HttpServletRequest request) {
HttpSession session = request.getSession();
if (session == null) {
return;
}
Map map = (Map) session.getAttribute(TOKEN_KEY);
if (map == null) {
return;
}
String strToken = request.getParameter(TOKEN_KEY);
if (strToken == null) {
return;
}
map.remove(strToken);
}
}
发表评论
- 浏览: 29759 次
- 性别:

- 来自: 杭州

- 详细资料
搜索本博客
我的相册
ExtJs中关于grid和store的应用分析(一)
共 14 张
共 14 张
最近加入圈子
最新评论
-
ExtJs视频教程集锦
怎么ftp上还没有, 急死了!
-- by slmdyk -
EXTJS动态树的实现
不明白你说的意思
-- by yahaitt -
EXTJS动态树的实现
你好! 请问添加节点时, 提示需要验证: http://localhost:80 ...
-- by davy138 -
ExtJs想入门的请进-解读 ...
非常感谢!正在学extjs,正不知道该如何下手。对java script不熟悉, ...
-- by xt95 -
关于动态树的完整示例代码 ...
...
-- by yahaitt






评论排行榜