问题:这里的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>
<!-- 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>
<?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>
<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>
<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");
- }
- }
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);
- }
- }